summaryrefslogtreecommitdiffstats
path: root/patches/linux-3.7
diff options
context:
space:
mode:
Diffstat (limited to 'patches/linux-3.7')
-rw-r--r--patches/linux-3.7/0001-video-st7735fb-add-st7735-framebuffer-driver.patch799
-rw-r--r--patches/linux-3.7/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch40
-rw-r--r--patches/linux-3.7/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch93
-rw-r--r--patches/linux-3.7/0004-of-Add-generic-device-tree-DMA-helpers.patch532
-rw-r--r--patches/linux-3.7/0005-of-dma-fix-build-break-for-CONFIG_OF.patch53
-rw-r--r--patches/linux-3.7/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch68
-rw-r--r--patches/linux-3.7/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch23
-rw-r--r--patches/linux-3.7/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch143
-rw-r--r--patches/linux-3.7/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch4047
-rw-r--r--patches/linux-3.7/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch68
-rw-r--r--patches/linux-3.7/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch632
-rw-r--r--patches/linux-3.7/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch127
-rw-r--r--patches/linux-3.7/0013-dmaengine-edma-enable-build-for-AM33XX.patch24
-rw-r--r--patches/linux-3.7/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch70
-rw-r--r--patches/linux-3.7/0015-ARM-dts-add-AM33XX-EDMA-support.patch54
-rw-r--r--patches/linux-3.7/0016-dmaengine-add-dma_request_slave_channel_compat.patch41
-rw-r--r--patches/linux-3.7/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch44
-rw-r--r--patches/linux-3.7/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch38
-rw-r--r--patches/linux-3.7/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch54
-rw-r--r--patches/linux-3.7/0020-ARM-dts-add-AM33XX-MMC-support.patch90
-rw-r--r--patches/linux-3.7/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch118
-rw-r--r--patches/linux-3.7/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch55
-rw-r--r--patches/linux-3.7/0023-ARM-dts-add-AM33XX-SPI-support.patch123
-rw-r--r--patches/linux-3.7/0024-Documentation-bindings-add-spansion.patch21
-rw-r--r--patches/linux-3.7/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch43
-rw-r--r--patches/linux-3.7/0026-misc-add-gpevt-driver.patch218
-rw-r--r--patches/linux-3.7/0027-ARM-dts-add-BeagleBone-gpevt-support.patch49
-rw-r--r--patches/linux-3.7/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch234
-rw-r--r--patches/linux-3.7/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch2000
-rw-r--r--patches/linux-3.7/0030-misc-gpevt-null-terminate-the-of_match_table.patch21
-rw-r--r--patches/linux-3.7/0031-proposed-probe-fix-works-for-me-on-evm.patch42
-rw-r--r--patches/linux-3.7/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch79
-rw-r--r--patches/linux-3.7/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch34
-rw-r--r--patches/linux-3.7/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch86
-rw-r--r--patches/linux-3.7/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch108
-rw-r--r--patches/linux-3.7/0038-i2c-pinctrl-ify-i2c-omap.c.patch45
-rw-r--r--patches/linux-3.7/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch69
-rw-r--r--patches/linux-3.7/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch28
-rw-r--r--patches/linux-3.7/0041-beaglebone-add-a-cpu-led-trigger.patch21
-rw-r--r--patches/linux-3.7/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch78
-rw-r--r--patches/linux-3.7/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch24
-rw-r--r--patches/linux-3.7/0046-input-TSC-ti_tscadc-Correct-register-usage.patch225
-rw-r--r--patches/linux-3.7/0047-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch137
-rw-r--r--patches/linux-3.7/0048-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch66
-rw-r--r--patches/linux-3.7/0049-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch36
-rw-r--r--patches/linux-3.7/0050-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch1173
-rw-r--r--patches/linux-3.7/0051-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch452
-rw-r--r--patches/linux-3.7/0052-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch570
-rw-r--r--patches/linux-3.7/0053-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch419
-rw-r--r--patches/linux-3.7/0054-input-ti_am335x_tsc-Make-steps-enable-configurable.patch73
-rw-r--r--patches/linux-3.7/0055-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch328
-rw-r--r--patches/linux-3.7/0056-input-ti_am335x_tsc-Add-variance-filters.patch74
-rw-r--r--patches/linux-3.7/0057-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch182
-rw-r--r--patches/linux-3.7/0058-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch183
-rw-r--r--patches/linux-3.7/0060-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch164
-rw-r--r--patches/linux-3.7/0061-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch67
-rw-r--r--patches/linux-3.7/0062-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch119
-rw-r--r--patches/linux-3.7/0063-Control-module-EHRPWM-clk-enabling.patch42
-rw-r--r--patches/linux-3.7/0064-pwm-pwm-tiecap-Enable-clock-gating.patch101
-rw-r--r--patches/linux-3.7/0065-PWM-ti-ehrpwm-fix-up-merge-conflict.patch21
-rw-r--r--patches/linux-3.7/0066-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch369
-rw-r--r--patches/linux-3.7/0067-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch83
-rw-r--r--patches/linux-3.7/0068-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch121
-rw-r--r--patches/linux-3.7/0069-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch26
-rw-r--r--patches/linux-3.7/0071-pinctrl-pinctrl-single-must-be-initialized-early.patch34
-rw-r--r--patches/linux-3.7/0072-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch93
-rw-r--r--patches/linux-3.7/0073-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch106
-rw-r--r--patches/linux-3.7/0074-beaglebone-fix-backlight-entry-in-DT.patch28
-rw-r--r--patches/linux-3.7/0076-Shut-up-musb.patch23
-rw-r--r--patches/linux-3.7/0077-musb-Fix-crashes-and-other-weirdness.patch45
-rw-r--r--patches/linux-3.7/0078-musb-revert-parts-of-032ec49f.patch370
-rw-r--r--patches/linux-3.7/0079-usb-musb-dsps-get-the-PHY-using-phandle-api.patch54
-rw-r--r--patches/linux-3.7/0080-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch203
-rw-r--r--patches/linux-3.7/0081-usb-otg-nop-add-dt-support.patch47
-rw-r--r--patches/linux-3.7/0082-usb-musb-dsps-add-phy-control-logic-to-glue.patch274
-rw-r--r--patches/linux-3.7/0083-usb-musb-dsps-enable-phy-control-for-am335x.patch57
-rw-r--r--patches/linux-3.7/0084-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch44
-rw-r--r--patches/linux-3.7/0086-omap2-clk-Add-missing-lcdc-clock-definition.patch39
-rw-r--r--patches/linux-3.7/0087-da8xx-Allow-use-by-am33xx-based-devices.patch22
-rw-r--r--patches/linux-3.7/0088-da8xx-Fix-revision-check-on-the-da8xx-driver.patch21
-rw-r--r--patches/linux-3.7/0089-da8xx-De-constify-members-in-the-platform-config.patch28
-rw-r--r--patches/linux-3.7/0090-da8xx-Add-standard-panel-definition.patch35
-rw-r--r--patches/linux-3.7/0091-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch33
-rw-r--r--patches/linux-3.7/0092-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch34
-rw-r--r--patches/linux-3.7/0094-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch116
-rw-r--r--patches/linux-3.7/0095-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch37
-rw-r--r--patches/linux-3.7/0096-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch22
-rw-r--r--patches/linux-3.7/0098-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch24
-rw-r--r--patches/linux-3.7/0100-f2fs-add-document.patch437
-rw-r--r--patches/linux-3.7/0101-f2fs-add-on-disk-layout.patch382
-rw-r--r--patches/linux-3.7/0102-f2fs-add-superblock-and-major-in-memory-structure.patch1961
-rw-r--r--patches/linux-3.7/0103-f2fs-add-super-block-operations.patch611
-rw-r--r--patches/linux-3.7/0104-f2fs-add-checkpoint-operations.patch833
-rw-r--r--patches/linux-3.7/0105-f2fs-add-node-operations.patch1823
-rw-r--r--patches/linux-3.7/0106-f2fs-add-segment-operations.patch1842
-rw-r--r--patches/linux-3.7/0107-f2fs-add-file-operations.patch660
-rw-r--r--patches/linux-3.7/0108-f2fs-add-address-space-operations-for-data.patch723
-rw-r--r--patches/linux-3.7/0109-f2fs-add-core-inode-operations.patch281
-rw-r--r--patches/linux-3.7/0110-f2fs-add-inode-operations-for-special-inodes.patch513
-rw-r--r--patches/linux-3.7/0111-f2fs-add-core-directory-operations.patch781
-rw-r--r--patches/linux-3.7/0112-f2fs-add-xattr-and-acl-functionalities.patch1101
-rw-r--r--patches/linux-3.7/0113-f2fs-add-garbage-collection-functions.patch1394
-rw-r--r--patches/linux-3.7/0114-f2fs-add-recovery-routines-for-roll-forward.patch410
-rw-r--r--patches/linux-3.7/0115-f2fs-update-Kconfig-and-Makefile.patch114
-rw-r--r--patches/linux-3.7/0116-f2fs-gc.h-make-should_do_checkpoint-inline.patch25
-rw-r--r--patches/linux-3.7/0117-f2fs-move-statistics-code-into-one-file.patch966
-rw-r--r--patches/linux-3.7/0118-f2fs-move-proc-files-to-debugfs.patch448
-rw-r--r--patches/linux-3.7/0119-f2fs-compile-fix.patch21
-rw-r--r--patches/linux-3.7/0121-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch40
-rw-r--r--patches/linux-3.7/0122-6lowpan-next-header-is-not-properly-set-upon-decompr.patch30
-rw-r--r--patches/linux-3.7/0123-6lowpan-always-enable-link-layer-acknowledgments.patch30
-rw-r--r--patches/linux-3.7/0124-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch22
-rw-r--r--patches/linux-3.7/0125-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch52
-rw-r--r--patches/linux-3.7/0126-6lowpan-fix-first-fragment-FRAG1-handling.patch136
-rw-r--r--patches/linux-3.7/0127-6lowpan-store-fragment-tag-values-per-device-instead.patch64
-rw-r--r--patches/linux-3.7/0128-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch47
-rw-r--r--patches/linux-3.7/0129-6lowpan-add-a-new-parameter-in-sysfs-to-turn-on-off-.patch44
-rw-r--r--patches/linux-3.7/0130-6lowpan-use-the-PANID-provided-by-the-device-instead.patch29
-rw-r--r--patches/linux-3.7/0131-6lowpan-modify-udp-compression-uncompression-to-matc.patch89
-rw-r--r--patches/linux-3.7/0132-6lowpan-make-memory-allocation-atomic-during-6lowpan.patch26
-rw-r--r--patches/linux-3.7/0133-mac802154-make-mem-alloc-ATOMIC-to-prevent-schedulin.patch25
-rw-r--r--patches/linux-3.7/0134-mac802154-remove-unnecessary-spinlocks.patch50
-rw-r--r--patches/linux-3.7/0135-mac802154-re-introduce-MAC-primitives-required-to-se.patch100
-rw-r--r--patches/linux-3.7/0136-serial-initial-import-of-the-IEEE-802.15.4-serial-dr.patch1323
-rw-r--r--patches/linux-3.7/0138-i2c-EEPROM-Export-memory-accessor.patch88
-rw-r--r--patches/linux-3.7/0139-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch70
-rw-r--r--patches/linux-3.7/0140-gpio-keys-Pinctrl-fy.patch39
-rw-r--r--patches/linux-3.7/0141-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch194
-rw-r--r--patches/linux-3.7/0142-pwm-export-of_pwm_request.patch66
-rw-r--r--patches/linux-3.7/0143-i2c-Export-capability-to-probe-devices.patch64
-rw-r--r--patches/linux-3.7/0144-pwm-backlight-Pinctrl-fy.patch36
-rw-r--r--patches/linux-3.7/0145-spi-Export-OF-interfaces-for-capebus-use.patch118
-rw-r--r--patches/linux-3.7/0146-w1-gpio-Pinctrl-fy.patch35
-rw-r--r--patches/linux-3.7/0147-w1-gpio-Simplify-get-rid-of-defines.patch140
-rw-r--r--patches/linux-3.7/0148-arm-dt-Enable-DT-proc-updates.patch21
-rw-r--r--patches/linux-3.7/0149-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch56
-rw-r--r--patches/linux-3.7/0150-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch500
-rw-r--r--patches/linux-3.7/0151-beaglebone-enable-emmc-for-bonelt.patch48
-rw-r--r--patches/linux-3.7/0152-da8xx-dt-Create-da8xx-DT-adapter-device.patch232
-rw-r--r--patches/linux-3.7/0153-ti-tscadc-dt-Create-ti-tscadc-dt-DT-adapter-device.patch188
-rw-r--r--patches/linux-3.7/0154-capebus-Core-capebus-support.patch1395
-rw-r--r--patches/linux-3.7/0155-capebus-Add-beaglebone-board-support.patch1693
-rw-r--r--patches/linux-3.7/0156-capebus-Beaglebone-generic-cape-support.patch123
-rw-r--r--patches/linux-3.7/0157-capebus-Beaglebone-geiger-cape-support.patch563
-rw-r--r--patches/linux-3.7/0158-capebus-Beaglebone-capebus-DT-update.patch748
-rw-r--r--patches/linux-3.7/0159-capebus-Document-DT-bindings.patch471
-rw-r--r--patches/linux-3.7/0160-capebus-Documentation-capebus-summary.patch58
-rw-r--r--patches/linux-3.7/0161-beaglebone-Update-default-config-for-capebus.patch3909
-rw-r--r--patches/linux-3.7/0162-capebus-Geiger-Cape-config-bugfixs.patch26
-rw-r--r--patches/linux-3.7/0163-am335x-bone-Add-spi0-pins-defines.patch43
-rw-r--r--patches/linux-3.7/0164-Allow-more-than-one-instance-of-generic-devices.patch64
-rw-r--r--patches/linux-3.7/0165-Mark-the-device-as-PRIVATE.patch52
-rw-r--r--patches/linux-3.7/0166-DT-overlay.patch448
-rw-r--r--patches/linux-3.7/0167-Bug-fixes-pinctl-gpio-reset.patch138
-rw-r--r--patches/linux-3.7/0168-ARM-HSMMC-fix-error-path-when-no-gpio_reset.patch35
-rw-r--r--patches/linux-3.7/0169-capebus-Add-PRUSS-DT-bindings.patch135
-rw-r--r--patches/linux-3.7/0171-Import-working-HDMI-driver-from-3.2-kernel.patch72647
-rw-r--r--patches/linux-3.7/0172-Added-DT-binding-to-NXP-driver.patch34
-rw-r--r--patches/linux-3.7/0173-da8xx-fb-Add-timings-for-720x480-60.patch78
-rw-r--r--patches/linux-3.7/0174-Add-capebus-override-and-pinmux-for-da8xx-dt.patch91
-rw-r--r--patches/linux-3.7/0175-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch48
-rw-r--r--patches/linux-3.7/0176-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch34
-rw-r--r--patches/linux-3.7/0177-tda-driver-enable-1280x720.patch25
-rw-r--r--patches/linux-3.7/0178-Makefile-Disable-CEC.patch22
-rw-r--r--patches/linux-3.7/0180-uio-uio_pruss-port-to-AM33xx.patch239
-rw-r--r--patches/linux-3.7/0181-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch80
-rw-r--r--patches/linux-3.7/0182-ARM-dts-AM33xx-PRUSS-support.patch33
-rw-r--r--patches/linux-3.7/0184-kbuild-deb-pkg-set-host-machine-after-dpkg-gencontro.patch110
-rw-r--r--patches/linux-3.7/0185-arm-add-definition-of-strstr-to-decompress.c.patch36
-rw-r--r--patches/linux-3.7/0187-mach-omap2-board-igep0020.c-Fix-reboot-problem.patch65
-rw-r--r--patches/linux-3.7/0188-regulator-core-if-voltage-scaling-fails-restore-orig.patch53
-rw-r--r--patches/linux-3.7/0190-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch74
-rw-r--r--patches/linux-3.7/0191-video-add-timings-for-hd720.patch24
-rw-r--r--patches/linux-3.7/0193-Beagle-expansion-add-buddy-param-for-expansionboard-.patch58
-rw-r--r--patches/linux-3.7/0194-Beagle-expansion-add-zippy.patch227
-rw-r--r--patches/linux-3.7/0195-Beagle-expansion-add-zippy2.patch82
-rw-r--r--patches/linux-3.7/0196-Beagle-expansion-add-trainer.patch51
-rw-r--r--patches/linux-3.7/0197-Beagle-expansion-add-CircuitCo-ulcd-Support.patch290
-rw-r--r--patches/linux-3.7/0198-Beagle-expansion-add-wifi.patch172
-rw-r--r--patches/linux-3.7/0199-Beagle-expansion-add-beaglefpga.patch111
-rw-r--r--patches/linux-3.7/0200-Beagle-expansion-add-spidev.patch29
-rw-r--r--patches/linux-3.7/0201-Beagle-expansion-add-Aptina-li5m03-camera.patch223
-rw-r--r--patches/linux-3.7/0202-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch119
-rw-r--r--patches/linux-3.7/0204-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch26
-rw-r--r--patches/linux-3.7/0205-backlight-Add-TLC59108-backlight-control-driver.patch212
-rw-r--r--patches/linux-3.7/0206-tlc59108-adjust-for-beagleboard-uLCD7.patch120
-rw-r--r--patches/linux-3.7/0207-zeroMAP-Open-your-eyes.patch27
-rw-r--r--patches/linux-3.7/0208-ARM-OMAP-Beagle-C4-fix-reboot-problem.patch63
-rw-r--r--patches/linux-3.7/0210-panda-fix-wl12xx-regulator.patch23
-rw-r--r--patches/linux-3.7/0211-ti-st-st-kim-fixing-firmware-path.patch32
-rw-r--r--patches/linux-3.7/0213-Revert-drm-kill-drm_sman.patch400
-rw-r--r--patches/linux-3.7/0215-omap3-Increase-limit-on-bootarg-mpurate.patch29
-rw-r--r--patches/linux-3.7/0217-staging-omap-thermal-fix-compilation.patch24
-rw-r--r--patches/linux-3.7/0218-staging-omap-thermal-remove-platform-data-nomenclatu.patch40
-rw-r--r--patches/linux-3.7/0219-staging-omap-thermal-remove-freq_clip-table.patch156
-rw-r--r--patches/linux-3.7/0220-staging-omap-thermal-add-IRQ-debugging-messaging.patch28
-rw-r--r--patches/linux-3.7/0221-staging-omap-thermal-fix-context-restore-function.patch93
-rw-r--r--patches/linux-3.7/0223-Attempted-SMC911x-BQL-patch.patch56
-rw-r--r--patches/linux-3.7/0225-spi-spidev-Add-device-tree-bindings.patch43
-rw-r--r--patches/linux-3.7/0301-Release-distrokit-beaglebone-20121218.patch22
-rw-r--r--patches/linux-3.7/series209
201 files changed, 123243 insertions, 0 deletions
diff --git a/patches/linux-3.7/0001-video-st7735fb-add-st7735-framebuffer-driver.patch b/patches/linux-3.7/0001-video-st7735fb-add-st7735-framebuffer-driver.patch
new file mode 100644
index 0000000..20d32c9
--- /dev/null
+++ b/patches/linux-3.7/0001-video-st7735fb-add-st7735-framebuffer-driver.patch
@@ -0,0 +1,799 @@
+From: Matt Porter <mporter@ti.com>
+Date: Tue, 11 Sep 2012 15:30:10 -0400
+Subject: [PATCH] video: st7735fb: add st7735 framebuffer driver
+
+Add driver for the SPI-connected ST7735 display controller.
+This driver requires that the platform support DT booting.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ .../devicetree/bindings/vendor-prefixes.txt | 2 +
+ drivers/video/Kconfig | 11 +
+ drivers/video/Makefile | 1 +
+ drivers/video/st7735fb.c | 631 ++++++++++++++++++++
+ drivers/video/st7735fb.h | 84 +++
+ 5 files changed, 729 insertions(+)
+ create mode 100644 drivers/video/st7735fb.c
+ create mode 100644 drivers/video/st7735fb.h
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
+index 9de2b9f..54463a7 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -4,6 +4,7 @@ This isn't an exhaustive list, but you should add new prefixes to it before
+ using them to avoid name-space collisions.
+
+ ad Avionic Design GmbH
++adafruit Adafruit Industries
+ adi Analog Devices, Inc.
+ amcc Applied Micro Circuits Corporation (APM, formally AMCC)
+ apm Applied Micro Circuits Corporation (APM)
+@@ -45,6 +46,7 @@ schindler Schindler
+ sil Silicon Image
+ simtek
+ sirf SiRF Technology, Inc.
++sitronix Sitronix Technology Corp.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+ ti Texas Instruments
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index d08d799..9791d10 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2417,6 +2417,17 @@ config FB_PUV3_UNIGFX
+ Choose this option if you want to use the Unigfx device as a
+ framebuffer device. Without the support of PCI & AGP.
+
++config FB_ST7735
++ tristate "ST7735 framebuffer support"
++ depends on FB && SPI
++ select FB_SYS_FILLRECT
++ select FB_SYS_COPYAREA
++ select FB_SYS_IMAGEBLIT
++ select FB_SYS_FOPS
++ select FB_DEFERRED_IO
++ help
++ Framebuffer support for the ST7735 display controller in SPI mode.
++
+ source "drivers/video/omap/Kconfig"
+ source "drivers/video/omap2/Kconfig"
+ source "drivers/video/exynos/Kconfig"
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 23e948e..0e13296 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -146,6 +146,7 @@ obj-$(CONFIG_FB_MSM) += msm/
+ obj-$(CONFIG_FB_NUC900) += nuc900fb.o
+ obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
+ obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
++obj-$(CONFIG_FB_ST7735) += st7735fb.o
+
+ # Platform or fallback drivers go here
+ obj-$(CONFIG_FB_UVESA) += uvesafb.o
+diff --git a/drivers/video/st7735fb.c b/drivers/video/st7735fb.c
+new file mode 100644
+index 0000000..67c2544
+--- /dev/null
++++ b/drivers/video/st7735fb.c
+@@ -0,0 +1,631 @@
++/*
++ * linux/drivers/video/st7735fb.c -- FB driver for ST7735 LCD controller
++ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
++ *
++ * Copyright (C) 2012, Matt Porter <matt@ohporter.com>
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/fb.h>
++#include <linux/gpio.h>
++#include <linux/spi/spi.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/uaccess.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++
++#include "st7735fb.h"
++
++static struct st7735_function st7735_cfg_script[] = {
++ { ST7735_START, ST7735_START},
++ { ST7735_CMD, ST7735_SWRESET},
++ { ST7735_DELAY, 150},
++ { ST7735_CMD, ST7735_SLPOUT},
++ { ST7735_DELAY, 500},
++ { ST7735_CMD, ST7735_FRMCTR1},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_FRMCTR2},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_FRMCTR3},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x2d},
++ { ST7735_CMD, ST7735_INVCTR},
++ { ST7735_DATA, 0x07},
++ { ST7735_CMD, ST7735_PWCTR1},
++ { ST7735_DATA, 0xa2},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x84},
++ { ST7735_CMD, ST7735_PWCTR2},
++ { ST7735_DATA, 0xc5},
++ { ST7735_CMD, ST7735_PWCTR3},
++ { ST7735_DATA, 0x0a},
++ { ST7735_DATA, 0x00},
++ { ST7735_CMD, ST7735_PWCTR4},
++ { ST7735_DATA, 0x8a},
++ { ST7735_DATA, 0x2a},
++ { ST7735_CMD, ST7735_PWCTR5},
++ { ST7735_DATA, 0x8a},
++ { ST7735_DATA, 0xee},
++ { ST7735_CMD, ST7735_VMCTR1},
++ { ST7735_DATA, 0x0e},
++ { ST7735_CMD, ST7735_INVOFF},
++ { ST7735_CMD, ST7735_MADCTL},
++ { ST7735_DATA, 0xc8},
++ { ST7735_CMD, ST7735_COLMOD},
++ { ST7735_DATA, 0x05},
++ { ST7735_CMD, ST7735_CASET},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x7f},
++ { ST7735_CMD, ST7735_RASET},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x9f},
++ { ST7735_CMD, ST7735_GMCTRP1},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x1c},
++ { ST7735_DATA, 0x07},
++ { ST7735_DATA, 0x12},
++ { ST7735_DATA, 0x37},
++ { ST7735_DATA, 0x32},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x25},
++ { ST7735_DATA, 0x2b},
++ { ST7735_DATA, 0x39},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x01},
++ { ST7735_DATA, 0x03},
++ { ST7735_DATA, 0x10},
++ { ST7735_CMD, ST7735_GMCTRN1},
++ { ST7735_DATA, 0x03},
++ { ST7735_DATA, 0x1d},
++ { ST7735_DATA, 0x07},
++ { ST7735_DATA, 0x06},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x2c},
++ { ST7735_DATA, 0x29},
++ { ST7735_DATA, 0x2d},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x2e},
++ { ST7735_DATA, 0x37},
++ { ST7735_DATA, 0x3f},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x00},
++ { ST7735_DATA, 0x02},
++ { ST7735_DATA, 0x10},
++ { ST7735_CMD, ST7735_DISPON},
++ { ST7735_DELAY, 100},
++ { ST7735_CMD, ST7735_NORON},
++ { ST7735_DELAY, 10},
++ { ST7735_END, ST7735_END},
++};
++
++static struct fb_fix_screeninfo st7735fb_fix __devinitdata = {
++ .id = "ST7735",
++ .type = FB_TYPE_PACKED_PIXELS,
++ .visual = FB_VISUAL_DIRECTCOLOR,
++ .xpanstep = 0,
++ .ypanstep = 0,
++ .ywrapstep = 0,
++ .line_length = WIDTH*BPP/8,
++ .accel = FB_ACCEL_NONE,
++};
++
++static struct fb_var_screeninfo st7735fb_var __devinitdata = {
++ .xres = WIDTH,
++ .yres = HEIGHT,
++ .xres_virtual = WIDTH,
++ .yres_virtual = HEIGHT,
++ .bits_per_pixel = BPP,
++ .nonstd = 0,
++};
++
++static int st7735_write(struct st7735fb_par *par, u8 data)
++{
++ par->buf[0] = data;
++
++ return spi_write(par->spi, par->buf, 1);
++}
++
++static void st7735_write_data(struct st7735fb_par *par, u8 data)
++{
++ int ret = 0;
++
++ /* Set data mode */
++ gpio_set_value(par->dc, 1);
++
++ ret = st7735_write(par, data);
++ if (ret < 0)
++ pr_err("%s: write data %02x failed with status %d\n",
++ par->info->fix.id, data, ret);
++}
++
++static int st7735_write_data_buf(struct st7735fb_par *par,
++ u8 *txbuf, int size)
++{
++ /* Set data mode */
++ gpio_set_value(par->dc, 1);
++
++ /* Write entire buffer */
++ return spi_write(par->spi, txbuf, size);
++}
++
++static void st7735_write_cmd(struct st7735fb_par *par, u8 data)
++{
++ int ret = 0;
++
++ /* Set command mode */
++ gpio_set_value(par->dc, 0);
++
++ ret = st7735_write(par, data);
++ if (ret < 0)
++ pr_err("%s: write command %02x failed with status %d\n",
++ par->info->fix.id, data, ret);
++}
++
++static void st7735_run_cfg_script(struct st7735fb_par *par)
++{
++ int i = 0;
++ int end_script = 0;
++
++ do {
++ switch (st7735_cfg_script[i].cmd)
++ {
++ case ST7735_START:
++ break;
++ case ST7735_CMD:
++ st7735_write_cmd(par,
++ st7735_cfg_script[i].data & 0xff);
++ break;
++ case ST7735_DATA:
++ st7735_write_data(par,
++ st7735_cfg_script[i].data & 0xff);
++ break;
++ case ST7735_DELAY:
++ mdelay(st7735_cfg_script[i].data);
++ break;
++ case ST7735_END:
++ end_script = 1;
++ }
++ i++;
++ } while (!end_script);
++}
++
++static void st7735_set_addr_win(struct st7735fb_par *par,
++ int xs, int ys, int xe, int ye)
++{
++ st7735_write_cmd(par, ST7735_CASET);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, xs + par->xoff);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, xe + par->xoff);
++ st7735_write_cmd(par, ST7735_RASET);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, ys + par->yoff);
++ st7735_write_data(par, 0x00);
++ st7735_write_data(par, ye + par->yoff);
++}
++
++static void st7735_reset(struct st7735fb_par *par)
++{
++ /* Reset controller */
++ gpio_set_value(par->rst, 0);
++ udelay(10);
++ gpio_set_value(par->rst, 1);
++ mdelay(120);
++}
++
++static void st7735fb_update_display(struct st7735fb_par *par)
++{
++ int ret = 0;
++ u16 *vmem;
++#ifdef __LITTLE_ENDIAN
++ int i;
++ u16 *vmem16 = (u16 *)par->info->screen_base;
++ vmem = par->ssbuf;
++
++ for (i=0; i<WIDTH*HEIGHT*BPP/8/2; i++)
++ vmem[i] = swab16(vmem16[i]);
++#else
++ vmem = (u16 *)par->info->screen_base;
++#endif
++
++ mutex_lock(&(par->io_lock));
++
++ /* Set row/column data window */
++ st7735_set_addr_win(par, 0, 0, WIDTH-1, HEIGHT-1);
++
++ /* Internal RAM write command */
++ st7735_write_cmd(par, ST7735_RAMWR);
++
++ /* Blast framebuffer to ST7735 internal display RAM */
++ ret = st7735_write_data_buf(par, (u8 *)vmem, WIDTH*HEIGHT*BPP/8);
++ if (ret < 0)
++ pr_err("%s: spi_write failed to update display buffer\n",
++ par->info->fix.id);
++
++ mutex_unlock(&(par->io_lock));
++}
++
++static int st7735fb_init_display(struct st7735fb_par *par)
++{
++ int ret = 0;
++
++ /* Request GPIOs and initialize to default values */
++ ret = gpio_request_one(par->rst, GPIOF_OUT_INIT_HIGH,
++ "ST7735 Reset Pin");
++ if (ret < 0) {
++ pr_err("%s: failed to claim reset pin\n", par->info->fix.id);
++ goto out;
++ }
++ ret = gpio_request_one(par->dc, GPIOF_OUT_INIT_LOW,
++ "ST7735 Data/Command Pin");
++ if (ret < 0) {
++ pr_err("%s: failed to claim data/command pin\n", par->info->fix.id);
++ goto out;
++ }
++
++ st7735_reset(par);
++
++ st7735_run_cfg_script(par);
++
++out:
++ return ret;
++}
++
++static void st7735fb_deferred_io(struct fb_info *info,
++ struct list_head *pagelist)
++{
++ st7735fb_update_display(info->par);
++}
++
++static void st7735fb_update_display_deferred(struct fb_info *info)
++{
++ struct fb_deferred_io *fbdefio = info->fbdefio;
++
++ schedule_delayed_work(&info->deferred_work, fbdefio->delay);
++}
++
++static void st7735fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
++{
++ sys_fillrect(info, rect);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static void st7735fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
++{
++ sys_copyarea(info, area);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static void st7735fb_imageblit(struct fb_info *info, const struct fb_image *image)
++{
++ sys_imageblit(info, image);
++
++ st7735fb_update_display_deferred(info);
++}
++
++static ssize_t st7735fb_write(struct fb_info *info, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ unsigned long p = *ppos;
++ void *dst;
++ int err = 0;
++ unsigned long total_size;
++
++ if (info->state != FBINFO_STATE_RUNNING)
++ return -EPERM;
++
++ total_size = info->fix.smem_len;
++
++ if (p > total_size)
++ return -EFBIG;
++
++ if (count > total_size) {
++ err = -EFBIG;
++ count = total_size;
++ }
++
++ if (count + p > total_size) {
++ if (!err)
++ err = -ENOSPC;
++
++ count = total_size - p;
++ }
++
++ dst = (void __force *) (info->screen_base + p);
++
++ if (copy_from_user(dst, buf, count))
++ err = -EFAULT;
++
++ if (!err)
++ *ppos += count;
++
++ st7735fb_update_display_deferred(info);
++
++ return (err) ? err : count;
++}
++
++static int st7735fb_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp,
++ struct fb_info *info)
++{
++ if (regno >= MAX_PALETTE)
++ return -EINVAL;
++
++ /* RGB565 */
++ ((u32*)(info->pseudo_palette))[regno] =
++ ((red & 0xf800) |
++ ((green & 0xfc00) >> 5) |
++ ((blue & 0xf800) >> 11));
++
++ return 0;
++}
++
++static struct fb_ops st7735fb_ops = {
++ .owner = THIS_MODULE,
++ .fb_read = fb_sys_read,
++ .fb_write = st7735fb_write,
++ .fb_fillrect = st7735fb_fillrect,
++ .fb_copyarea = st7735fb_copyarea,
++ .fb_imageblit = st7735fb_imageblit,
++ .fb_setcolreg = st7735fb_setcolreg,
++};
++
++static struct fb_deferred_io st7735fb_defio = {
++ .delay = HZ/20,
++ .deferred_io = st7735fb_deferred_io,
++};
++
++static const struct spi_device_id st7735fb_device_id[] = {
++ {
++ .name = "tft-lcd-1.8-green",
++ .driver_data = ST7735_AF_TFT18_GREEN,
++ }, {
++ .name = "tft-lcd-1.8-red",
++ .driver_data = ST7735_AF_TFT18_RED,
++ }, {
++ /* sentinel */
++ }
++};
++MODULE_DEVICE_TABLE(spi, st7735fb_device_id);
++
++static const struct of_device_id st7735fb_dt_ids[] = {
++ { .compatible = "adafruit,tft-lcd-1.8-green", .data = (void *) ST7735_AF_TFT18_GREEN, },
++ { .compatible = "adafruit,tft-lcd-1.8-red", .data = (void *) ST7735_AF_TFT18_RED, },
++};
++MODULE_DEVICE_TABLE(of, st7735fb_dt_ids);
++
++static int __devinit st7735fb_probe (struct spi_device *spi)
++{
++ int vmem_size = WIDTH*HEIGHT*BPP/8;
++ u8 *vmem;
++ struct fb_info *info;
++ struct st7735fb_par *par;
++ int retval = -ENOMEM;
++ struct device_node *np = spi->dev.of_node;
++ const struct spi_device_id *spi_id = spi_get_device_id(spi);
++ struct pinctrl *pinctrl;
++
++ if (!spi_id) {
++ dev_err(&spi->dev,
++ "device id not supported!\n");
++ return -EINVAL;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&spi->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&spi->dev,
++ "pins are not configured from the driver\n");
++
++#ifdef __LITTLE_ENDIAN
++ vmem = (u8 *)vmalloc(vmem_size);
++#else
++ vmem = (u8 *)kmalloc(vmem_size, GFP_KERNEL);
++#endif
++ if (!vmem)
++ return retval;
++
++ info = framebuffer_alloc(sizeof(struct st7735fb_par), &spi->dev);
++ if (!info)
++ goto fballoc_fail;
++
++ info->pseudo_palette = kmalloc(sizeof(u32)*MAX_PALETTE, GFP_KERNEL);
++ if (!info->pseudo_palette) {
++ goto palette_fail;
++ }
++
++ info->screen_base = (u8 __force __iomem *)vmem;
++ info->fbops = &st7735fb_ops;
++ info->fix = st7735fb_fix;
++ info->fix.smem_len = vmem_size;
++ info->var = st7735fb_var;
++ /* Choose any packed pixel format as long as it's RGB565 */
++ info->var.red.offset = 11;
++ info->var.red.length = 5;
++ info->var.green.offset = 5;
++ info->var.green.length = 6;
++ info->var.blue.offset = 0;
++ info->var.blue.length = 5;
++ info->var.transp.offset = 0;
++ info->var.transp.length = 0;
++ info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
++
++ info->fbdefio = &st7735fb_defio;
++ fb_deferred_io_init(info);
++
++ retval = fb_alloc_cmap(&info->cmap, MAX_PALETTE, 0);
++ if (retval < 0)
++ goto cmap_fail;
++ info->cmap.len = MAX_PALETTE;
++
++ par = info->par;
++ par->info = info;
++ par->spi = spi;
++
++ mutex_init(&par->io_lock);
++
++ if (spi_id->driver_data == ST7735_AF_TFT18_GREEN) {
++ par->xoff = 2;
++ par->yoff = 1;
++ } else {
++ par->xoff = 0;
++ par->yoff = 0;
++ }
++
++ /* TODO: fix all exit paths for cleanup */
++ par->rst = of_get_named_gpio(np, "st7735-rst", 0);
++ if (par->rst < 0) {
++ printk("failed to find st7735-rst node!\n");
++ return -EINVAL;
++ }
++
++ par->dc = of_get_named_gpio(np, "st7735-dc", 0);
++ if (par->dc < 0) {
++ printk("failed to find st7735-dc node!\n");
++ return -EINVAL;
++ }
++
++ par->buf = kmalloc(1, GFP_KERNEL);
++ if (!par->buf) {
++ retval = -ENOMEM;
++ goto buf_fail;
++ }
++
++#ifdef __LITTLE_ENDIAN
++ /* Allocated swapped shadow buffer */
++ par->ssbuf = kmalloc(vmem_size, GFP_KERNEL);
++ if (!par->ssbuf) {
++ retval = -ENOMEM;
++ goto ssbuf_fail;
++ }
++#endif
++
++ retval = st7735fb_init_display(par);
++ if (retval < 0)
++ goto init_fail;
++
++ retval = register_framebuffer(info);
++ if (retval < 0)
++ goto fbreg_fail;
++
++ spi_set_drvdata(spi, info);
++
++ printk(KERN_INFO
++ "fb%d: %s frame buffer device,\n\tusing %d KiB of video memory\n",
++ info->node, info->fix.id, vmem_size);
++
++ return 0;
++
++
++ spi_set_drvdata(spi, NULL);
++
++fbreg_fail:
++ /* TODO: release gpios on fail */
++ /* TODO: and unwind everything in init */
++
++init_fail:
++#ifdef __LITTLE_ENDIAN
++ kfree(par->ssbuf);
++#endif
++
++ssbuf_fail:
++ kfree(par->buf);
++
++buf_fail:
++ fb_dealloc_cmap(&info->cmap);
++
++cmap_fail:
++ kfree(info->pseudo_palette);
++
++palette_fail:
++ framebuffer_release(info);
++
++fballoc_fail:
++#ifdef __LITTLE_ENDIAN
++ vfree(vmem);
++#else
++ kfree(vmem);
++#endif
++
++ return retval;
++}
++
++static int __devexit st7735fb_remove(struct spi_device *spi)
++{
++ struct fb_info *info = spi_get_drvdata(spi);
++
++ spi_set_drvdata(spi, NULL);
++
++ if (info) {
++ unregister_framebuffer(info);
++ fb_dealloc_cmap(&info->cmap);
++ kfree(info->pseudo_palette);
++ vfree(info->screen_base);
++ framebuffer_release(info);
++ }
++
++ /* TODO: release gpios */
++
++ return 0;
++}
++
++static struct spi_driver st7735fb_driver = {
++ .id_table = st7735fb_device_id,
++ .driver = {
++ .name = "st7735",
++ .owner = THIS_MODULE,
++ .of_match_table = st7735fb_dt_ids,
++ },
++ .probe = st7735fb_probe,
++ .remove = __devexit_p(st7735fb_remove),
++};
++
++static int __init st7735fb_init(void)
++{
++ return spi_register_driver(&st7735fb_driver);
++}
++
++static void __exit st7735fb_exit(void)
++{
++ spi_unregister_driver(&st7735fb_driver);
++}
++
++/* ------------------------------------------------------------------------- */
++
++module_init(st7735fb_init);
++module_exit(st7735fb_exit);
++
++MODULE_DESCRIPTION("FB driver for ST7735 display controller");
++MODULE_AUTHOR("Matt Porter <matt@ohporter.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/st7735fb.h b/drivers/video/st7735fb.h
+new file mode 100644
+index 0000000..0ce5c11
+--- /dev/null
++++ b/drivers/video/st7735fb.h
+@@ -0,0 +1,84 @@
++/*
++ * linux/include/video/st7735fb.h -- FB driver for ST7735 LCD controller
++ *
++ * Copyright (C) 2012, Matt Porter
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#define DRVNAME "st7735fb"
++#define WIDTH 128
++#define HEIGHT 160
++#define BPP 16
++#define MAX_PALETTE 16
++
++/* Supported display modules */
++#define ST7735_AF_TFT18_GREEN 0 /* Adafruit SPI TFT 1.8" - green tab */
++#define ST7735_AF_TFT18_RED 1 /* Adafruit SPI TFT 1.8" - red tab */
++
++/* Init script function */
++struct st7735_function {
++ u16 cmd;
++ u16 data;
++};
++
++/* Init script commands */
++enum st7735_cmd {
++ ST7735_START,
++ ST7735_END,
++ ST7735_CMD,
++ ST7735_DATA,
++ ST7735_DELAY
++};
++
++struct st7735fb_par {
++ struct spi_device *spi;
++ struct fb_info *info;
++ struct mutex io_lock;
++ int xoff;
++ int yoff;
++ int rst;
++ int dc;
++ u16 *ssbuf;
++ u8 *buf;
++};
++
++/* ST7735 Commands */
++#define ST7735_NOP 0x0
++#define ST7735_SWRESET 0x01
++#define ST7735_RDDID 0x04
++#define ST7735_RDDST 0x09
++#define ST7735_SLPIN 0x10
++#define ST7735_SLPOUT 0x11
++#define ST7735_PTLON 0x12
++#define ST7735_NORON 0x13
++#define ST7735_INVOFF 0x20
++#define ST7735_INVON 0x21
++#define ST7735_DISPOFF 0x28
++#define ST7735_DISPON 0x29
++#define ST7735_CASET 0x2A
++#define ST7735_RASET 0x2B
++#define ST7735_RAMWR 0x2C
++#define ST7735_RAMRD 0x2E
++#define ST7735_COLMOD 0x3A
++#define ST7735_MADCTL 0x36
++#define ST7735_FRMCTR1 0xB1
++#define ST7735_FRMCTR2 0xB2
++#define ST7735_FRMCTR3 0xB3
++#define ST7735_INVCTR 0xB4
++#define ST7735_DISSET5 0xB6
++#define ST7735_PWCTR1 0xC0
++#define ST7735_PWCTR2 0xC1
++#define ST7735_PWCTR3 0xC2
++#define ST7735_PWCTR4 0xC3
++#define ST7735_PWCTR5 0xC4
++#define ST7735_VMCTR1 0xC5
++#define ST7735_RDID1 0xDA
++#define ST7735_RDID2 0xDB
++#define ST7735_RDID3 0xDC
++#define ST7735_RDID4 0xDD
++#define ST7735_GMCTRP1 0xE0
++#define ST7735_GMCTRN1 0xE1
++#define ST7735_PWCTR6 0xFC
diff --git a/patches/linux-3.7/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch b/patches/linux-3.7/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
new file mode 100644
index 0000000..e7cc14d
--- /dev/null
+++ b/patches/linux-3.7/0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
@@ -0,0 +1,40 @@
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Mon, 15 Oct 2012 12:15:58 +0000
+Subject: [PATCH] regulator: tps65910: fix BUG_ON() shown with vrtc regulator
+
+Fix BUG_ON() error if tps65910 VRTC regulator is used with out
+rdev->desc->volt_table data. Recent changes in regulator core driver
+which add support for "regulator_list_voltage_table" have BUG_ON() if
+regulator descriptor do not voltage table information. This patch adds
+the voltage table information to fix the issue.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ drivers/regulator/tps65910-regulator.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
+index 793adda..1d2dd18 100644
+--- a/drivers/regulator/tps65910-regulator.c
++++ b/drivers/regulator/tps65910-regulator.c
+@@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
+
+ /* VSEL tables for TPS65910 specific LDOs and dcdc's */
+
++/* supported VRTC voltages in microvolts */
++static const unsigned int VRTC_VSEL_table[] = {
++ 1800000,
++};
++
+ /* supported VDD3 voltages in microvolts */
+ static const unsigned int VDD3_VSEL_table[] = {
+ 5000000,
+@@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
+ {
+ .name = "vrtc",
+ .vin_name = "vcc7",
++ .n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
++ .voltage_table = VRTC_VSEL_table,
+ .enable_time_us = 2200,
+ },
+ {
diff --git a/patches/linux-3.7/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch b/patches/linux-3.7/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
new file mode 100644
index 0000000..3368d21
--- /dev/null
+++ b/patches/linux-3.7/0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
@@ -0,0 +1,93 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Fri, 14 Sep 2012 17:41:57 -0500
+Subject: [PATCH] dmaengine: add helper function to request a slave DMA
+ channel
+
+Currently slave DMA channels are requested by calling dma_request_channel()
+and requires DMA clients to pass various filter parameters to obtain the
+appropriate channel.
+
+With device-tree being used by architectures such as arm and the addition of
+device-tree helper functions to extract the relevant DMA client information
+from device-tree, add a new function to request a slave DMA channel using
+device-tree. This function is currently a simple wrapper that calls the
+device-tree of_dma_request_slave_channel() function.
+
+Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
+Cc: Benoit Cousson <b-cousson@ti.com>
+Cc: Stephen Warren <swarren@nvidia.com>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Rob Herring <rob.herring@calxeda.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Vinod Koul <vinod.koul@intel.com>
+Cc: Dan Williams <djbw@fb.com>
+
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Reviewed-by: Stephen Warren <swarren@wwwdotorg.org>
+Acked-by: Rob Herring <rob.herring@calxeda.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ drivers/dma/dmaengine.c | 16 ++++++++++++++++
+ include/linux/dmaengine.h | 6 ++++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index a815d44..d37cf95 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -62,6 +62,7 @@
+ #include <linux/rculist.h>
+ #include <linux/idr.h>
+ #include <linux/slab.h>
++#include <linux/of_dma.h>
+
+ static DEFINE_MUTEX(dma_list_mutex);
+ static DEFINE_IDR(dma_idr);
+@@ -546,6 +547,21 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
+ }
+ EXPORT_SYMBOL_GPL(__dma_request_channel);
+
++/**
++ * dma_request_slave_channel - try to allocate an exclusive slave channel
++ * @dev: pointer to client device structure
++ * @name: slave channel name
++ */
++struct dma_chan *dma_request_slave_channel(struct device *dev, char *name)
++{
++ /* If device-tree is present get slave info from here */
++ if (dev->of_node)
++ return of_dma_request_slave_channel(dev->of_node, name);
++
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(dma_request_slave_channel);
++
+ void dma_release_channel(struct dma_chan *chan)
+ {
+ mutex_lock(&dma_list_mutex);
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index d3201e4..8cd0e25 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -974,6 +974,7 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
+ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+ void dma_issue_pending_all(void);
+ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
++struct dma_chan *dma_request_slave_channel(struct device *dev, char *name);
+ void dma_release_channel(struct dma_chan *chan);
+ #else
+ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+@@ -988,6 +989,11 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+ {
+ return NULL;
+ }
++static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
++ char *name)
++{
++ return NULL
++}
+ static inline void dma_release_channel(struct dma_chan *chan)
+ {
+ }
diff --git a/patches/linux-3.7/0004-of-Add-generic-device-tree-DMA-helpers.patch b/patches/linux-3.7/0004-of-Add-generic-device-tree-DMA-helpers.patch
new file mode 100644
index 0000000..71a2fc0
--- /dev/null
+++ b/patches/linux-3.7/0004-of-Add-generic-device-tree-DMA-helpers.patch
@@ -0,0 +1,532 @@
+From: Jon Hunter <jon-hunter@ti.com>
+Date: Fri, 14 Sep 2012 17:41:56 -0500
+Subject: [PATCH] of: Add generic device tree DMA helpers
+
+This is based upon the work by Benoit Cousson [1] and Nicolas Ferre [2]
+to add some basic helpers to retrieve a DMA controller device_node and the
+DMA request/channel information.
+
+Aim of DMA helpers
+- The purpose of device-tree is to describe the capabilites of the hardware.
+ Thinking about DMA controllers purely from the context of the hardware to
+ begin with, we can describe a device in terms of a DMA controller as
+ follows ...
+ 1. Number of DMA controllers
+ 2. Number of channels (maybe physical or logical)
+ 3. Mapping of DMA requests signals to DMA controller
+ 4. Number of DMA interrupts
+ 5. Mapping of DMA interrupts to channels
+- With the above in mind the aim of the DT DMA helper functions is to extract
+ the above information from the DT and provide to the appropriate driver.
+ However, due to the vast number of DMA controllers and not all are using a
+ common driver (such as DMA Engine) it has been seen that this is not a
+ trivial task. In previous discussions on this topic the following concerns
+ have been raised ...
+ 1. How does the binding support devices with multiple DMA controllers?
+ 2. How to support both legacy DMA controllers not using DMA Engine as
+ well as those that support DMA Engine.
+ 3. When using with DMA Engine how do we support the various
+ implementations where the opaque filter function parameter differs
+ between implementations?
+ 4. How do we handle DMA channels that are identified with a string
+ versus a integer?
+- Hence the design of the DMA helpers has to accomodate the above or align on
+ an agreement what can be or should be supported.
+
+Design of DMA helpers
+
+1. Registering DMA controllers
+
+ In the case of DMA controllers that are using DMA Engine, requesting a
+ channel is performed by calling the following function.
+
+ struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+ dma_filter_fn filter_fn,
+ void *filter_param);
+
+ The mask variable is used to match a type of the device controller in a list
+ of controllers. The filter_fn and filter_param are used to identify the
+ required dma channel and return a handle to the dma channel of type dma_chan.
+
+ From the examples I have seen, the mask and filter_fn are constant
+ for a given DMA controller and therefore, we can specify these as controller
+ specific data when registering the DMA controller with the device-tree DMA
+ helpers.
+
+ The filter_param variable is of an unknown type and is typically specific
+ to the DMA engine implementation for a given DMA controller. To allow some
+ flexibility in the type and formating of this filter_param we employ an
+ xlate to translate the device-tree binding information into the appropriate
+ format. The xlate function used for a DMA controller can also be specified
+ when registering the DMA controller with the device-tree DMA helpers.
+
+ Based upon the above, a function for registering the DMA controller with the
+ DMA helpers now looks like the below. The data variable is used to pass a
+ pointer to DMA controller specific data used by the xlate function.
+
+ int of_dma_controller_register(struct device_node *np,
+ struct dma_chan *(*of_dma_xlate)
+ (struct of_phandle_args *, struct of_dma *),
+ void *data)
+
+ For example, in the case where DMA engine is used, we define the following
+ structure (that stores the DMA engine capability mask and filter function)
+ and pass this to the data variable in the above function.
+
+ struct of_dma_filter_info {
+ dma_cap_mask_t dma_cap;
+ dma_filter_fn filter_fn;
+ };
+
+2. Representing and requesting channel information
+
+ Please see the dma binding documentation included in this patch for a
+ description of how DMA controllers and client information should be
+ represented with device-tree. For more information on how this binding
+ came about please see [3]. In addition to this, feedback received from
+ the Linux kernel summit showed a consensus (among those who attended) to
+ use a name to identify DMA client information [4].
+
+ A DMA channel can be requested by calling the following function, where name
+ is a required parameter used for identifying a DMA channel. This function
+ has been designed to return a structure of type dma_chan to work with the
+ DMA engine driver. Note that if DMA engine is used then drivers should be
+ using the DMA engine API dma_request_slave_channel() (implemented in part 2
+ of this series, "dmaengine: add helper function to request a slave DMA
+ channel") which will in turn call the below function if device-tree is
+ present. The aim being to have a common DMA engine interface regardless of
+ whether device tree is being used.
+
+ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+ char *name)
+
+3. Supporting legacy devices not using DMA Engine
+
+ These devices present a problem, as there may not be a uniform way to easily
+ support them with regard to device tree. Ideally, these should be migrated
+ to DMA engine. However, if this is not possible, then they should still be
+ able to use this binding, the only constaint imposed by this implementation
+ is that when requesting a DMA channel via of_dma_request_slave_channel(), it
+ will return a type of dma_chan.
+
+This implementation has been tested on OMAP4430 using the kernel v3.6-rc5. I
+have validated that MMC is working on the PANDA board with this implementation.
+My development branch for testing on OMAP can be found here [5].
+
+v6: - minor corrections in DMA binding documentation
+v5: - minor update to binding documentation
+ - added loop to exhaustively search for a slave channel in the case where
+ there could be alternative channels available
+v4: - revert the removal of xlate function from v3
+ - update the proposed binding format and APIs based upon discussions [3]
+v3: - avoid passing an xlate function and instead pass DMA engine parameters
+ - define number of dma channels and requests in dma-controller node
+v2: - remove of_dma_to_resource API
+ - make property #dma-cells required (no fallback anymore)
+ - another check in of_dma_xlate_onenumbercell() function
+
+[1] http://article.gmane.org/gmane.linux.drivers.devicetree/12022
+[2] http://article.gmane.org/gmane.linux.ports.arm.omap/73622
+[3] http://marc.info/?l=linux-omap&m=133582085008539&w=2
+[4] http://pad.linaro.org/arm-mini-summit-2012
+[5] https://github.com/jonhunter/linux/tree/dev-dt-dma
+
+Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
+Cc: Benoit Cousson <b-cousson@ti.com>
+Cc: Stephen Warren <swarren@nvidia.com>
+Cc: Grant Likely <grant.likely@secretlab.ca>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Rob Herring <rob.herring@calxeda.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Vinod Koul <vinod.koul@intel.com>
+Cc: Dan Williams <djbw@fb.com>
+
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
+Signed-off-by: Jon Hunter <jon-hunter@ti.com>
+Reviewed-by: Stephen Warren <swarren@wwwdotorg.org>
+Acked-by: Rob Herring <rob.herring@calxeda.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ Documentation/devicetree/bindings/dma/dma.txt | 81 +++++++++
+ drivers/of/Makefile | 2 +-
+ drivers/of/dma.c | 219 +++++++++++++++++++++++++
+ include/linux/of_dma.h | 45 +++++
+ 4 files changed, 346 insertions(+), 1 deletion(-)
+ create mode 100644 Documentation/devicetree/bindings/dma/dma.txt
+ create mode 100644 drivers/of/dma.c
+ create mode 100644 include/linux/of_dma.h
+
+diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
+new file mode 100644
+index 0000000..a4f59a5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/dma/dma.txt
+@@ -0,0 +1,81 @@
++* Generic DMA Controller and DMA request bindings
++
++Generic binding to provide a way for a driver using DMA Engine to retrieve the
++DMA request or channel information that goes from a hardware device to a DMA
++controller.
++
++
++* DMA controller
++
++Required property:
++- #dma-cells: Must be at least 1. Used to provide DMA controller
++ specific information. See DMA client binding below for
++ more details.
++
++Optional properties:
++- #dma-channels: Number of DMA channels supported by the controller.
++- #dma-requests: Number of DMA requests signals supported by the
++ controller.
++
++Example:
++
++ dma: dma@48000000 {
++ compatible = "ti,omap-sdma"
++ reg = <0x48000000 0x1000>;
++ interrupts = <0 12 0x4
++ 0 13 0x4
++ 0 14 0x4
++ 0 15 0x4>;
++ #dma-cells = <1>;
++ #dma-channels = <32>;
++ #dma-requests = <127>;
++ };
++
++
++* DMA client
++
++Client drivers should specify the DMA property using a phandle to the controller
++followed by DMA controller specific data.
++
++Required property:
++- dmas: List of one or more DMA specifiers, each consisting of
++ - A phandle pointing to DMA controller node
++ - A number of integer cells, as determined by the
++ #dma-cells property in the node referenced by phandle
++ containing DMA controller specific information. This
++ typically contains a DMA request line number or a
++ channel number, but can contain any data that is used
++ required for configuring a channel.
++- dma-names: Contains one identifier string for each DMA specifier in
++ the dmas property. The specific strings that can be used
++ are defined in the binding of the DMA client device.
++ Multiple DMA specifiers can be used to represent
++ alternatives and in this case the dma-names for those
++ DMA specifiers must be identical (see examples).
++
++Examples:
++
++1. A device with one DMA read channel, one DMA write channel:
++
++ i2c1: i2c@1 {
++ ...
++ dmas = <&dma 2 /* read channel */
++ &dma 3>; /* write channel */
++ dma-names = "rx", "tx"
++ ...
++ };
++
++2. A single read-write channel with three alternative DMA controllers:
++
++ dmas = <&dma1 5
++ &dma2 7
++ &dma3 2>;
++ dma-names = "rx-tx", "rx-tx", "rx-tx"
++
++3. A device with three channels, one of which has two alternatives:
++
++ dmas = <&dma1 2 /* read channel */
++ &dma1 3 /* write channel */
++ &dma2 0 /* error read */
++ &dma3 0>; /* alternative error read */
++ dma-names = "rx", "tx", "error", "error";
+diff --git a/drivers/of/Makefile b/drivers/of/Makefile
+index e027f44..eafa107 100644
+--- a/drivers/of/Makefile
++++ b/drivers/of/Makefile
+@@ -1,4 +1,4 @@
+-obj-y = base.o
++obj-y = base.o dma.o
+ obj-$(CONFIG_OF_FLATTREE) += fdt.o
+ obj-$(CONFIG_OF_PROMTREE) += pdt.o
+ obj-$(CONFIG_OF_ADDRESS) += address.o
+diff --git a/drivers/of/dma.c b/drivers/of/dma.c
+new file mode 100644
+index 0000000..19ad37c
+--- /dev/null
++++ b/drivers/of/dma.c
+@@ -0,0 +1,219 @@
++/*
++ * Device tree helpers for DMA request / controller
++ *
++ * Based on of_gpio.c
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/device.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/rculist.h>
++#include <linux/slab.h>
++#include <linux/of.h>
++#include <linux/of_dma.h>
++
++static LIST_HEAD(of_dma_list);
++
++/**
++ * of_dma_find_controller - Find a DMA controller in DT DMA helpers list
++ * @np: device node of DMA controller
++ */
++static struct of_dma *of_dma_find_controller(struct device_node *np)
++{
++ struct of_dma *ofdma;
++
++ if (list_empty(&of_dma_list)) {
++ pr_err("empty DMA controller list\n");
++ return NULL;
++ }
++
++ list_for_each_entry_rcu(ofdma, &of_dma_list, of_dma_controllers)
++ if (ofdma->of_node == np)
++ return ofdma;
++
++ return NULL;
++}
++
++/**
++ * of_dma_controller_register - Register a DMA controller to DT DMA helpers
++ * @np: device node of DMA controller
++ * @of_dma_xlate: translation function which converts a phandle
++ * arguments list into a dma_chan structure
++ * @data pointer to controller specific data to be used by
++ * translation function
++ *
++ * Returns 0 on success or appropriate errno value on error.
++ *
++ * Allocated memory should be freed with appropriate of_dma_controller_free()
++ * call.
++ */
++int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data)
++{
++ struct of_dma *ofdma;
++ int nbcells;
++
++ if (!np || !of_dma_xlate) {
++ pr_err("%s: not enough information provided\n", __func__);
++ return -EINVAL;
++ }
++
++ ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL);
++ if (!ofdma)
++ return -ENOMEM;
++
++ nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL));
++ if (!nbcells) {
++ pr_err("%s: #dma-cells property is missing or invalid\n",
++ __func__);
++ return -EINVAL;
++ }
++
++ ofdma->of_node = np;
++ ofdma->of_dma_nbcells = nbcells;
++ ofdma->of_dma_xlate = of_dma_xlate;
++ ofdma->of_dma_data = data;
++
++ /* Now queue of_dma controller structure in list */
++ list_add_tail_rcu(&ofdma->of_dma_controllers, &of_dma_list);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_dma_controller_register);
++
++/**
++ * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list
++ * @np: device node of DMA controller
++ *
++ * Memory allocated by of_dma_controller_register() is freed here.
++ */
++void of_dma_controller_free(struct device_node *np)
++{
++ struct of_dma *ofdma;
++
++ ofdma = of_dma_find_controller(np);
++ if (ofdma) {
++ list_del_rcu(&ofdma->of_dma_controllers);
++ kfree(ofdma);
++ }
++}
++EXPORT_SYMBOL_GPL(of_dma_controller_free);
++
++/**
++ * of_dma_find_channel - Find a DMA channel by name
++ * @np: device node to look for DMA channels
++ * @name: name of desired channel
++ * @dma_spec: pointer to DMA specifier as found in the device tree
++ *
++ * Find a DMA channel by the name. Returns 0 on success or appropriate
++ * errno value on error.
++ */
++static int of_dma_find_channel(struct device_node *np, char *name,
++ struct of_phandle_args *dma_spec)
++{
++ int count, i;
++ const char *s;
++
++ count = of_property_count_strings(np, "dma-names");
++ if (count < 0)
++ return count;
++
++ for (i = 0; i < count; i++) {
++ if (of_property_read_string_index(np, "dma-names", i, &s))
++ continue;
++
++ if (strcmp(name, s))
++ continue;
++
++ if (!of_parse_phandle_with_args(np, "dmas", "#dma-cells", i,
++ dma_spec))
++ return 0;
++ }
++
++ return -ENODEV;
++}
++
++/**
++ * of_dma_request_slave_channel - Get the DMA slave channel
++ * @np: device node to get DMA request from
++ * @name: name of desired channel
++ *
++ * Returns pointer to appropriate dma channel on success or NULL on error.
++ */
++struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name)
++{
++ struct of_phandle_args dma_spec;
++ struct of_dma *ofdma;
++ struct dma_chan *chan;
++ int r;
++
++ if (!np || !name) {
++ pr_err("%s: not enough information provided\n", __func__);
++ return NULL;
++ }
++
++ do {
++ r = of_dma_find_channel(np, name, &dma_spec);
++ if (r) {
++ pr_err("%s: can't find DMA channel\n", np->full_name);
++ return NULL;
++ }
++
++ ofdma = of_dma_find_controller(dma_spec.np);
++ if (!ofdma) {
++ pr_debug("%s: can't find DMA controller %s\n",
++ np->full_name, dma_spec.np->full_name);
++ continue;
++ }
++
++ if (dma_spec.args_count != ofdma->of_dma_nbcells) {
++ pr_debug("%s: wrong #dma-cells for %s\n", np->full_name,
++ dma_spec.np->full_name);
++ continue;
++ }
++
++ chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
++
++ of_node_put(dma_spec.np);
++
++ } while (!chan);
++
++ return chan;
++}
++
++/**
++ * of_dma_simple_xlate - Simple DMA engine translation function
++ * @dma_spec: pointer to DMA specifier as found in the device tree
++ * @of_dma: pointer to DMA controller data
++ *
++ * A simple translation function for devices that use a 32-bit value for the
++ * filter_param when calling the DMA engine dma_request_channel() function.
++ * Note that this translation function requires that #dma-cells is equal to 1
++ * and the argument of the dma specifier is the 32-bit filter_param. Returns
++ * pointer to appropriate dma channel on success or NULL on error.
++ */
++struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma)
++{
++ int count = dma_spec->args_count;
++ struct of_dma_filter_info *info = ofdma->of_dma_data;
++
++ if (!info || !info->filter_fn)
++ return NULL;
++
++ if (count != 1)
++ return NULL;
++
++ return dma_request_channel(info->dma_cap, info->filter_fn,
++ &dma_spec->args[0]);
++}
++EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
+diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
+new file mode 100644
+index 0000000..337823d
+--- /dev/null
++++ b/include/linux/of_dma.h
+@@ -0,0 +1,45 @@
++/*
++ * OF helpers for DMA request / controller
++ *
++ * Based on of_gpio.h
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __LINUX_OF_DMA_H
++#define __LINUX_OF_DMA_H
++
++#include <linux/of.h>
++#include <linux/dmaengine.h>
++
++struct device_node;
++
++struct of_dma {
++ struct list_head of_dma_controllers;
++ struct device_node *of_node;
++ int of_dma_nbcells;
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *);
++ void *of_dma_data;
++};
++
++struct of_dma_filter_info {
++ dma_cap_mask_t dma_cap;
++ dma_filter_fn filter_fn;
++};
++
++extern int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data);
++extern void of_dma_controller_free(struct device_node *np);
++extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name);
++extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma);
++
++#endif /* __LINUX_OF_DMA_H */
diff --git a/patches/linux-3.7/0005-of-dma-fix-build-break-for-CONFIG_OF.patch b/patches/linux-3.7/0005-of-dma-fix-build-break-for-CONFIG_OF.patch
new file mode 100644
index 0000000..04d864c
--- /dev/null
+++ b/patches/linux-3.7/0005-of-dma-fix-build-break-for-CONFIG_OF.patch
@@ -0,0 +1,53 @@
+From: Vinod Koul <vinod.koul@linux.intel.com>
+Date: Tue, 25 Sep 2012 09:57:36 +0530
+Subject: [PATCH] of: dma- fix build break for !CONFIG_OF
+
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ include/linux/of_dma.h | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
+index 337823d..67158dd 100644
+--- a/include/linux/of_dma.h
++++ b/include/linux/of_dma.h
+@@ -32,6 +32,7 @@ struct of_dma_filter_info {
+ dma_filter_fn filter_fn;
+ };
+
++#ifdef CONFIG_OF
+ extern int of_dma_controller_register(struct device_node *np,
+ struct dma_chan *(*of_dma_xlate)
+ (struct of_phandle_args *, struct of_dma *),
+@@ -41,5 +42,31 @@ extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
+ char *name);
+ extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma);
++#else
++static int of_dma_controller_register(struct device_node *np,
++ struct dma_chan *(*of_dma_xlate)
++ (struct of_phandle_args *, struct of_dma *),
++ void *data)
++{
++ return -ENODEV;
++}
++
++static void of_dma_controller_free(struct device_node *np)
++{
++}
++
++static struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
++ char *name)
++{
++ return NULL;
++}
++
++static struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
++ struct of_dma *ofdma)
++{
++ return NULL;
++}
++
++#endif
+
+ #endif /* __LINUX_OF_DMA_H */
diff --git a/patches/linux-3.7/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch b/patches/linux-3.7/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
new file mode 100644
index 0000000..bfbfad4
--- /dev/null
+++ b/patches/linux-3.7/0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
@@ -0,0 +1,68 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 19 Sep 2012 10:49:48 -0400
+Subject: [PATCH] of: dma: fix typos in generic dma binding definition
+
+Some semicolons were left out in the examples.
+
+The #dma-channels and #dma-requests properties have a prefix
+that is, by convention, reserved for cell size properties.
+Rename those properties to dma-channels and dma-requests.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Jon Hunter <jon-hunter@ti.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ Documentation/devicetree/bindings/dma/dma.txt | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
+index a4f59a5..8f504e6 100644
+--- a/Documentation/devicetree/bindings/dma/dma.txt
++++ b/Documentation/devicetree/bindings/dma/dma.txt
+@@ -13,22 +13,22 @@ Required property:
+ more details.
+
+ Optional properties:
+-- #dma-channels: Number of DMA channels supported by the controller.
+-- #dma-requests: Number of DMA requests signals supported by the
++- dma-channels: Number of DMA channels supported by the controller.
++- dma-requests: Number of DMA requests signals supported by the
+ controller.
+
+ Example:
+
+ dma: dma@48000000 {
+- compatible = "ti,omap-sdma"
++ compatible = "ti,omap-sdma";
+ reg = <0x48000000 0x1000>;
+ interrupts = <0 12 0x4
+ 0 13 0x4
+ 0 14 0x4
+ 0 15 0x4>;
+ #dma-cells = <1>;
+- #dma-channels = <32>;
+- #dma-requests = <127>;
++ dma-channels = <32>;
++ dma-requests = <127>;
+ };
+
+
+@@ -61,7 +61,7 @@ Examples:
+ ...
+ dmas = <&dma 2 /* read channel */
+ &dma 3>; /* write channel */
+- dma-names = "rx", "tx"
++ dma-names = "rx", "tx";
+ ...
+ };
+
+@@ -70,7 +70,7 @@ Examples:
+ dmas = <&dma1 5
+ &dma2 7
+ &dma3 2>;
+- dma-names = "rx-tx", "rx-tx", "rx-tx"
++ dma-names = "rx-tx", "rx-tx", "rx-tx";
+
+ 3. A device with three channels, one of which has two alternatives:
+
diff --git a/patches/linux-3.7/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch b/patches/linux-3.7/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
new file mode 100644
index 0000000..52ab593
--- /dev/null
+++ b/patches/linux-3.7/0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
@@ -0,0 +1,23 @@
+From: Vinod Koul <vinod.koul@linux.intel.com>
+Date: Tue, 25 Sep 2012 16:18:55 +0530
+Subject: [PATCH] dmaengine: fix build failure due to missing semi-colon
+
+Reported-by: Fengguang Wu <fengguang.wu@intel.com>
+Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
+---
+ include/linux/dmaengine.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index 8cd0e25..c88f302 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -992,7 +992,7 @@ static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+ static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
+ char *name)
+ {
+- return NULL
++ return NULL;
+ }
+ static inline void dma_release_channel(struct dma_chan *chan)
+ {
diff --git a/patches/linux-3.7/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch b/patches/linux-3.7/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
new file mode 100644
index 0000000..6e695b9
--- /dev/null
+++ b/patches/linux-3.7/0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
@@ -0,0 +1,143 @@
+From: Matt Porter <mporter@ti.com>
+Date: Tue, 18 Sep 2012 18:57:15 +0000
+Subject: [PATCH] dmaengine: edma: fix slave config dependency on direction
+
+The edma_slave_config() implementation depends on the
+direction field such that it will not properly configure
+a slave channel when called without direction set.
+
+This fixes the implementation so that the slave config
+is copied as is and prep_slave_sg() handles the
+direction dependent handling. spi-omap2-mcspi and
+omap_hsmmc both expose this bug as they configure the
+slave channel config from a common path with an unconfigured
+direction field.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/dma/edma.c | 55 ++++++++++++++++++++++++++--------------------------
+ 1 file changed, 27 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 05aea3c..fdcf079 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -69,9 +69,7 @@ struct edma_chan {
+ int ch_num;
+ bool alloced;
+ int slot[EDMA_MAX_SLOTS];
+- dma_addr_t addr;
+- int addr_width;
+- int maxburst;
++ struct dma_slave_config cfg;
+ };
+
+ struct edma_cc {
+@@ -178,29 +176,14 @@ static int edma_terminate_all(struct edma_chan *echan)
+ return 0;
+ }
+
+-
+ static int edma_slave_config(struct edma_chan *echan,
+- struct dma_slave_config *config)
++ struct dma_slave_config *cfg)
+ {
+- if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+- (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
++ if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
++ cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
+ return -EINVAL;
+
+- if (config->direction == DMA_MEM_TO_DEV) {
+- if (config->dst_addr)
+- echan->addr = config->dst_addr;
+- if (config->dst_addr_width)
+- echan->addr_width = config->dst_addr_width;
+- if (config->dst_maxburst)
+- echan->maxburst = config->dst_maxburst;
+- } else if (config->direction == DMA_DEV_TO_MEM) {
+- if (config->src_addr)
+- echan->addr = config->src_addr;
+- if (config->src_addr_width)
+- echan->addr_width = config->src_addr_width;
+- if (config->src_maxburst)
+- echan->maxburst = config->src_maxburst;
+- }
++ memcpy(&echan->cfg, cfg, sizeof(echan->cfg));
+
+ return 0;
+ }
+@@ -235,6 +218,9 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ struct edma_chan *echan = to_edma_chan(chan);
+ struct device *dev = chan->device->dev;
+ struct edma_desc *edesc;
++ dma_addr_t dev_addr;
++ enum dma_slave_buswidth dev_width;
++ u32 burst;
+ struct scatterlist *sg;
+ int i;
+ int acnt, bcnt, ccnt, src, dst, cidx;
+@@ -243,7 +229,20 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ if (unlikely(!echan || !sgl || !sg_len))
+ return NULL;
+
+- if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
++ if (direction == DMA_DEV_TO_MEM) {
++ dev_addr = echan->cfg.src_addr;
++ dev_width = echan->cfg.src_addr_width;
++ burst = echan->cfg.src_maxburst;
++ } else if (direction == DMA_MEM_TO_DEV) {
++ dev_addr = echan->cfg.dst_addr;
++ dev_width = echan->cfg.dst_addr_width;
++ burst = echan->cfg.dst_maxburst;
++ } else {
++ dev_err(dev, "%s: bad direction?\n", __func__);
++ return NULL;
++ }
++
++ if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+ dev_err(dev, "Undefined slave buswidth\n");
+ return NULL;
+ }
+@@ -275,14 +274,14 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ }
+ }
+
+- acnt = echan->addr_width;
++ acnt = dev_width;
+
+ /*
+ * If the maxburst is equal to the fifo width, use
+ * A-synced transfers. This allows for large contiguous
+ * buffer transfers using only one PaRAM set.
+ */
+- if (echan->maxburst == 1) {
++ if (burst == 1) {
+ edesc->absync = false;
+ ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
+ bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
+@@ -302,7 +301,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+ */
+ } else {
+ edesc->absync = true;
+- bcnt = echan->maxburst;
++ bcnt = burst;
+ ccnt = sg_dma_len(sg) / (acnt * bcnt);
+ if (ccnt > (SZ_64K - 1)) {
+ dev_err(dev, "Exceeded max SG segment size\n");
+@@ -313,13 +312,13 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+
+ if (direction == DMA_MEM_TO_DEV) {
+ src = sg_dma_address(sg);
+- dst = echan->addr;
++ dst = dev_addr;
+ src_bidx = acnt;
+ src_cidx = cidx;
+ dst_bidx = 0;
+ dst_cidx = 0;
+ } else {
+- src = echan->addr;
++ src = dev_addr;
+ dst = sg_dma_address(sg);
+ src_bidx = 0;
+ src_cidx = 0;
diff --git a/patches/linux-3.7/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch b/patches/linux-3.7/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
new file mode 100644
index 0000000..5581ab2
--- /dev/null
+++ b/patches/linux-3.7/0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
@@ -0,0 +1,4047 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 22 Aug 2012 09:24:24 -0400
+Subject: [PATCH] ARM: davinci: move private EDMA API to arm/common
+
+Move mach-davinci/dma.c to common/edma.c so it can be used
+by OMAP (specifically AM33xx) as well. This just moves the
+private EDMA API but does not support OMAP.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/Kconfig | 1 +
+ arch/arm/common/Kconfig | 3 +
+ arch/arm/common/Makefile | 1 +
+ arch/arm/common/edma.c | 1588 +++++++++++++++++++++++++++
+ arch/arm/mach-davinci/Makefile | 2 +-
+ arch/arm/mach-davinci/board-tnetv107x-evm.c | 2 +-
+ arch/arm/mach-davinci/davinci.h | 2 +-
+ arch/arm/mach-davinci/devices-tnetv107x.c | 2 +-
+ arch/arm/mach-davinci/devices.c | 7 +-
+ arch/arm/mach-davinci/dm355.c | 2 +-
+ arch/arm/mach-davinci/dm365.c | 2 +-
+ arch/arm/mach-davinci/dm644x.c | 2 +-
+ arch/arm/mach-davinci/dm646x.c | 2 +-
+ arch/arm/mach-davinci/dma.c | 1588 ---------------------------
+ arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
+ arch/arm/mach-davinci/include/mach/edma.h | 267 -----
+ arch/arm/plat-omap/Kconfig | 1 +
+ drivers/dma/edma.c | 2 +-
+ drivers/mmc/host/davinci_mmc.c | 1 +
+ include/linux/mfd/davinci_voicecodec.h | 3 +-
+ include/linux/platform_data/edma.h | 198 ++++
+ include/linux/platform_data/spi-davinci.h | 2 +-
+ sound/soc/davinci/davinci-evm.c | 1 +
+ sound/soc/davinci/davinci-pcm.c | 1 +
+ sound/soc/davinci/davinci-pcm.h | 2 +-
+ sound/soc/davinci/davinci-sffsdr.c | 6 +-
+ 26 files changed, 1815 insertions(+), 1875 deletions(-)
+ create mode 100644 arch/arm/common/edma.c
+ delete mode 100644 arch/arm/mach-davinci/dma.c
+ delete mode 100644 arch/arm/mach-davinci/include/mach/edma.h
+ create mode 100644 include/linux/platform_data/edma.h
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 9759fec..be22f68 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -925,6 +925,7 @@ config ARCH_DAVINCI
+ select GENERIC_IRQ_CHIP
+ select HAVE_IDE
+ select NEED_MACH_GPIO_H
++ select TI_PRIV_EDMA
+ select ZONE_DMA
+ help
+ Support for TI's DaVinci platform.
+diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
+index 45ceeb0..9e32d0d 100644
+--- a/arch/arm/common/Kconfig
++++ b/arch/arm/common/Kconfig
+@@ -40,3 +40,6 @@ config SHARP_PARAM
+
+ config SHARP_SCOOP
+ bool
++
++config TI_PRIV_EDMA
++ bool
+diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
+index e8a4e58..d09a39b 100644
+--- a/arch/arm/common/Makefile
++++ b/arch/arm/common/Makefile
+@@ -13,3 +13,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
+ obj-$(CONFIG_SHARP_SCOOP) += scoop.o
+ obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
+ obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
++obj-$(CONFIG_TI_PRIV_EDMA) += edma.o
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+new file mode 100644
+index 0000000..4411087
+--- /dev/null
++++ b/arch/arm/common/edma.c
+@@ -0,0 +1,1588 @@
++/*
++ * EDMA3 support for DaVinci
++ *
++ * Copyright (C) 2006-2009 Texas Instruments.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++
++#include <linux/platform_data/edma.h>
++
++/* Offsets matching "struct edmacc_param" */
++#define PARM_OPT 0x00
++#define PARM_SRC 0x04
++#define PARM_A_B_CNT 0x08
++#define PARM_DST 0x0c
++#define PARM_SRC_DST_BIDX 0x10
++#define PARM_LINK_BCNTRLD 0x14
++#define PARM_SRC_DST_CIDX 0x18
++#define PARM_CCNT 0x1c
++
++#define PARM_SIZE 0x20
++
++/* Offsets for EDMA CC global channel registers and their shadows */
++#define SH_ER 0x00 /* 64 bits */
++#define SH_ECR 0x08 /* 64 bits */
++#define SH_ESR 0x10 /* 64 bits */
++#define SH_CER 0x18 /* 64 bits */
++#define SH_EER 0x20 /* 64 bits */
++#define SH_EECR 0x28 /* 64 bits */
++#define SH_EESR 0x30 /* 64 bits */
++#define SH_SER 0x38 /* 64 bits */
++#define SH_SECR 0x40 /* 64 bits */
++#define SH_IER 0x50 /* 64 bits */
++#define SH_IECR 0x58 /* 64 bits */
++#define SH_IESR 0x60 /* 64 bits */
++#define SH_IPR 0x68 /* 64 bits */
++#define SH_ICR 0x70 /* 64 bits */
++#define SH_IEVAL 0x78
++#define SH_QER 0x80
++#define SH_QEER 0x84
++#define SH_QEECR 0x88
++#define SH_QEESR 0x8c
++#define SH_QSER 0x90
++#define SH_QSECR 0x94
++#define SH_SIZE 0x200
++
++/* Offsets for EDMA CC global registers */
++#define EDMA_REV 0x0000
++#define EDMA_CCCFG 0x0004
++#define EDMA_QCHMAP 0x0200 /* 8 registers */
++#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
++#define EDMA_QDMAQNUM 0x0260
++#define EDMA_QUETCMAP 0x0280
++#define EDMA_QUEPRI 0x0284
++#define EDMA_EMR 0x0300 /* 64 bits */
++#define EDMA_EMCR 0x0308 /* 64 bits */
++#define EDMA_QEMR 0x0310
++#define EDMA_QEMCR 0x0314
++#define EDMA_CCERR 0x0318
++#define EDMA_CCERRCLR 0x031c
++#define EDMA_EEVAL 0x0320
++#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
++#define EDMA_QRAE 0x0380 /* 4 registers */
++#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
++#define EDMA_QSTAT 0x0600 /* 2 registers */
++#define EDMA_QWMTHRA 0x0620
++#define EDMA_QWMTHRB 0x0624
++#define EDMA_CCSTAT 0x0640
++
++#define EDMA_M 0x1000 /* global channel registers */
++#define EDMA_ECR 0x1008
++#define EDMA_ECRH 0x100C
++#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
++#define EDMA_PARM 0x4000 /* 128 param entries */
++
++#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
++
++#define EDMA_DCHMAP 0x0100 /* 64 registers */
++#define CHMAP_EXIST BIT(24)
++
++#define EDMA_MAX_DMACH 64
++#define EDMA_MAX_PARAMENTRY 512
++
++/*****************************************************************************/
++
++static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
++
++static inline unsigned int edma_read(unsigned ctlr, int offset)
++{
++ return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
++}
++
++static inline void edma_write(unsigned ctlr, int offset, int val)
++{
++ __raw_writel(val, edmacc_regs_base[ctlr] + offset);
++}
++static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
++ unsigned or)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val &= and;
++ val |= or;
++ edma_write(ctlr, offset, val);
++}
++static inline void edma_and(unsigned ctlr, int offset, unsigned and)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val &= and;
++ edma_write(ctlr, offset, val);
++}
++static inline void edma_or(unsigned ctlr, int offset, unsigned or)
++{
++ unsigned val = edma_read(ctlr, offset);
++ val |= or;
++ edma_write(ctlr, offset, val);
++}
++static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
++{
++ return edma_read(ctlr, offset + (i << 2));
++}
++static inline void edma_write_array(unsigned ctlr, int offset, int i,
++ unsigned val)
++{
++ edma_write(ctlr, offset + (i << 2), val);
++}
++static inline void edma_modify_array(unsigned ctlr, int offset, int i,
++ unsigned and, unsigned or)
++{
++ edma_modify(ctlr, offset + (i << 2), and, or);
++}
++static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
++{
++ edma_or(ctlr, offset + (i << 2), or);
++}
++static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
++ unsigned or)
++{
++ edma_or(ctlr, offset + ((i*2 + j) << 2), or);
++}
++static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
++ unsigned val)
++{
++ edma_write(ctlr, offset + ((i*2 + j) << 2), val);
++}
++static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
++{
++ return edma_read(ctlr, EDMA_SHADOW0 + offset);
++}
++static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
++ int i)
++{
++ return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
++}
++static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
++{
++ edma_write(ctlr, EDMA_SHADOW0 + offset, val);
++}
++static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
++ unsigned val)
++{
++ edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
++}
++static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
++ int param_no)
++{
++ return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
++}
++static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
++ unsigned val)
++{
++ edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
++}
++static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
++ unsigned and, unsigned or)
++{
++ edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
++}
++static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
++ unsigned and)
++{
++ edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
++}
++static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
++ unsigned or)
++{
++ edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
++}
++
++static inline void set_bits(int offset, int len, unsigned long *p)
++{
++ for (; len > 0; len--)
++ set_bit(offset + (len - 1), p);
++}
++
++static inline void clear_bits(int offset, int len, unsigned long *p)
++{
++ for (; len > 0; len--)
++ clear_bit(offset + (len - 1), p);
++}
++
++/*****************************************************************************/
++
++/* actual number of DMA channels and slots on this silicon */
++struct edma {
++ /* how many dma resources of each type */
++ unsigned num_channels;
++ unsigned num_region;
++ unsigned num_slots;
++ unsigned num_tc;
++ unsigned num_cc;
++ enum dma_event_q default_queue;
++
++ /* list of channels with no even trigger; terminated by "-1" */
++ const s8 *noevent;
++
++ /* The edma_inuse bit for each PaRAM slot is clear unless the
++ * channel is in use ... by ARM or DSP, for QDMA, or whatever.
++ */
++ DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
++
++ /* The edma_unused bit for each channel is clear unless
++ * it is not being used on this platform. It uses a bit
++ * of SOC-specific initialization code.
++ */
++ DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
++
++ unsigned irq_res_start;
++ unsigned irq_res_end;
++
++ struct dma_interrupt_data {
++ void (*callback)(unsigned channel, unsigned short ch_status,
++ void *data);
++ void *data;
++ } intr_data[EDMA_MAX_DMACH];
++};
++
++static struct edma *edma_cc[EDMA_MAX_CC];
++static int arch_num_cc;
++
++/* dummy param set used to (re)initialize parameter RAM slots */
++static const struct edmacc_param dummy_paramset = {
++ .link_bcntrld = 0xffff,
++ .ccnt = 1,
++};
++
++/*****************************************************************************/
++
++static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
++ enum dma_event_q queue_no)
++{
++ int bit = (ch_no & 0x7) * 4;
++
++ /* default to low priority queue */
++ if (queue_no == EVENTQ_DEFAULT)
++ queue_no = edma_cc[ctlr]->default_queue;
++
++ queue_no &= 7;
++ edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
++ ~(0x7 << bit), queue_no << bit);
++}
++
++static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
++{
++ int bit = queue_no * 4;
++ edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
++}
++
++static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
++ int priority)
++{
++ int bit = queue_no * 4;
++ edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
++ ((priority & 0x7) << bit));
++}
++
++/**
++ * map_dmach_param - Maps channel number to param entry number
++ *
++ * This maps the dma channel number to param entry numberter. In
++ * other words using the DMA channel mapping registers a param entry
++ * can be mapped to any channel
++ *
++ * Callers are responsible for ensuring the channel mapping logic is
++ * included in that particular EDMA variant (Eg : dm646x)
++ *
++ */
++static void __init map_dmach_param(unsigned ctlr)
++{
++ int i;
++ for (i = 0; i < EDMA_MAX_DMACH; i++)
++ edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
++}
++
++static inline void
++setup_dma_interrupt(unsigned lch,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(lch);
++ lch = EDMA_CHAN_SLOT(lch);
++
++ if (!callback)
++ edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
++ BIT(lch & 0x1f));
++
++ edma_cc[ctlr]->intr_data[lch].callback = callback;
++ edma_cc[ctlr]->intr_data[lch].data = data;
++
++ if (callback) {
++ edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
++ BIT(lch & 0x1f));
++ edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
++ BIT(lch & 0x1f));
++ }
++}
++
++static int irq2ctlr(int irq)
++{
++ if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
++ return 0;
++ else if (irq >= edma_cc[1]->irq_res_start &&
++ irq <= edma_cc[1]->irq_res_end)
++ return 1;
++
++ return -1;
++}
++
++/******************************************************************************
++ *
++ * DMA interrupt handler
++ *
++ *****************************************************************************/
++static irqreturn_t dma_irq_handler(int irq, void *data)
++{
++ int ctlr;
++ u32 sh_ier;
++ u32 sh_ipr;
++ u32 bank;
++
++ ctlr = irq2ctlr(irq);
++ if (ctlr < 0)
++ return IRQ_NONE;
++
++ dev_dbg(data, "dma_irq_handler\n");
++
++ sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
++ if (!sh_ipr) {
++ sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
++ if (!sh_ipr)
++ return IRQ_NONE;
++ sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
++ bank = 1;
++ } else {
++ sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
++ bank = 0;
++ }
++
++ do {
++ u32 slot;
++ u32 channel;
++
++ dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
++
++ slot = __ffs(sh_ipr);
++ sh_ipr &= ~(BIT(slot));
++
++ if (sh_ier & BIT(slot)) {
++ channel = (bank << 5) | slot;
++ /* Clear the corresponding IPR bits */
++ edma_shadow0_write_array(ctlr, SH_ICR, bank,
++ BIT(slot));
++ if (edma_cc[ctlr]->intr_data[channel].callback)
++ edma_cc[ctlr]->intr_data[channel].callback(
++ channel, DMA_COMPLETE,
++ edma_cc[ctlr]->intr_data[channel].data);
++ }
++ } while (sh_ipr);
++
++ edma_shadow0_write(ctlr, SH_IEVAL, 1);
++ return IRQ_HANDLED;
++}
++
++/******************************************************************************
++ *
++ * DMA error interrupt handler
++ *
++ *****************************************************************************/
++static irqreturn_t dma_ccerr_handler(int irq, void *data)
++{
++ int i;
++ int ctlr;
++ unsigned int cnt = 0;
++
++ ctlr = irq2ctlr(irq);
++ if (ctlr < 0)
++ return IRQ_NONE;
++
++ dev_dbg(data, "dma_ccerr_handler\n");
++
++ if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
++ (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
++ (edma_read(ctlr, EDMA_QEMR) == 0) &&
++ (edma_read(ctlr, EDMA_CCERR) == 0))
++ return IRQ_NONE;
++
++ while (1) {
++ int j = -1;
++ if (edma_read_array(ctlr, EDMA_EMR, 0))
++ j = 0;
++ else if (edma_read_array(ctlr, EDMA_EMR, 1))
++ j = 1;
++ if (j >= 0) {
++ dev_dbg(data, "EMR%d %08x\n", j,
++ edma_read_array(ctlr, EDMA_EMR, j));
++ for (i = 0; i < 32; i++) {
++ int k = (j << 5) + i;
++ if (edma_read_array(ctlr, EDMA_EMR, j) &
++ BIT(i)) {
++ /* Clear the corresponding EMR bits */
++ edma_write_array(ctlr, EDMA_EMCR, j,
++ BIT(i));
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR,
++ j, BIT(i));
++ if (edma_cc[ctlr]->intr_data[k].
++ callback) {
++ edma_cc[ctlr]->intr_data[k].
++ callback(k,
++ DMA_CC_ERROR,
++ edma_cc[ctlr]->intr_data
++ [k].data);
++ }
++ }
++ }
++ } else if (edma_read(ctlr, EDMA_QEMR)) {
++ dev_dbg(data, "QEMR %02x\n",
++ edma_read(ctlr, EDMA_QEMR));
++ for (i = 0; i < 8; i++) {
++ if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
++ /* Clear the corresponding IPR bits */
++ edma_write(ctlr, EDMA_QEMCR, BIT(i));
++ edma_shadow0_write(ctlr, SH_QSECR,
++ BIT(i));
++
++ /* NOTE: not reported!! */
++ }
++ }
++ } else if (edma_read(ctlr, EDMA_CCERR)) {
++ dev_dbg(data, "CCERR %08x\n",
++ edma_read(ctlr, EDMA_CCERR));
++ /* FIXME: CCERR.BIT(16) ignored! much better
++ * to just write CCERRCLR with CCERR value...
++ */
++ for (i = 0; i < 8; i++) {
++ if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
++ /* Clear the corresponding IPR bits */
++ edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
++
++ /* NOTE: not reported!! */
++ }
++ }
++ }
++ if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
++ (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
++ (edma_read(ctlr, EDMA_QEMR) == 0) &&
++ (edma_read(ctlr, EDMA_CCERR) == 0))
++ break;
++ cnt++;
++ if (cnt > 10)
++ break;
++ }
++ edma_write(ctlr, EDMA_EEVAL, 1);
++ return IRQ_HANDLED;
++}
++
++/******************************************************************************
++ *
++ * Transfer controller error interrupt handlers
++ *
++ *****************************************************************************/
++
++#define tc_errs_handled false /* disabled as long as they're NOPs */
++
++static irqreturn_t dma_tc0err_handler(int irq, void *data)
++{
++ dev_dbg(data, "dma_tc0err_handler\n");
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t dma_tc1err_handler(int irq, void *data)
++{
++ dev_dbg(data, "dma_tc1err_handler\n");
++ return IRQ_HANDLED;
++}
++
++static int reserve_contiguous_slots(int ctlr, unsigned int id,
++ unsigned int num_slots,
++ unsigned int start_slot)
++{
++ int i, j;
++ unsigned int count = num_slots;
++ int stop_slot = start_slot;
++ DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
++
++ for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
++ j = EDMA_CHAN_SLOT(i);
++ if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
++ /* Record our current beginning slot */
++ if (count == num_slots)
++ stop_slot = i;
++
++ count--;
++ set_bit(j, tmp_inuse);
++
++ if (count == 0)
++ break;
++ } else {
++ clear_bit(j, tmp_inuse);
++
++ if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
++ stop_slot = i;
++ break;
++ } else {
++ count = num_slots;
++ }
++ }
++ }
++
++ /*
++ * We have to clear any bits that we set
++ * if we run out parameter RAM slots, i.e we do find a set
++ * of contiguous parameter RAM slots but do not find the exact number
++ * requested as we may reach the total number of parameter RAM slots
++ */
++ if (i == edma_cc[ctlr]->num_slots)
++ stop_slot = i;
++
++ j = start_slot;
++ for_each_set_bit_from(j, tmp_inuse, stop_slot)
++ clear_bit(j, edma_cc[ctlr]->edma_inuse);
++
++ if (count)
++ return -EBUSY;
++
++ for (j = i - num_slots + 1; j <= i; ++j)
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
++ &dummy_paramset, PARM_SIZE);
++
++ return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
++}
++
++static int prepare_unused_channel_list(struct device *dev, void *data)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ int i, ctlr;
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
++ (int)pdev->resource[i].start >= 0) {
++ ctlr = EDMA_CTLR(pdev->resource[i].start);
++ clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
++ edma_cc[ctlr]->edma_unused);
++ }
++ }
++
++ return 0;
++}
++
++/*-----------------------------------------------------------------------*/
++
++static bool unused_chan_list_done;
++
++/* Resource alloc/free: dma channels, parameter RAM slots */
++
++/**
++ * edma_alloc_channel - allocate DMA channel and paired parameter RAM
++ * @channel: specific channel to allocate; negative for "any unmapped channel"
++ * @callback: optional; to be issued on DMA completion or errors
++ * @data: passed to callback
++ * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
++ * Controller (TC) executes requests using this channel. Use
++ * EVENTQ_DEFAULT unless you really need a high priority queue.
++ *
++ * This allocates a DMA channel and its associated parameter RAM slot.
++ * The parameter RAM is initialized to hold a dummy transfer.
++ *
++ * Normal use is to pass a specific channel number as @channel, to make
++ * use of hardware events mapped to that channel. When the channel will
++ * be used only for software triggering or event chaining, channels not
++ * mapped to hardware events (or mapped to unused events) are preferable.
++ *
++ * DMA transfers start from a channel using edma_start(), or by
++ * chaining. When the transfer described in that channel's parameter RAM
++ * slot completes, that slot's data may be reloaded through a link.
++ *
++ * DMA errors are only reported to the @callback associated with the
++ * channel driving that transfer, but transfer completion callbacks can
++ * be sent to another channel under control of the TCC field in
++ * the option word of the transfer's parameter RAM set. Drivers must not
++ * use DMA transfer completion callbacks for channels they did not allocate.
++ * (The same applies to TCC codes used in transfer chaining.)
++ *
++ * Returns the number of the channel, else negative errno.
++ */
++int edma_alloc_channel(int channel,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data,
++ enum dma_event_q eventq_no)
++{
++ unsigned i, done = 0, ctlr = 0;
++ int ret = 0;
++
++ if (!unused_chan_list_done) {
++ /*
++ * Scan all the platform devices to find out the EDMA channels
++ * used and clear them in the unused list, making the rest
++ * available for ARM usage.
++ */
++ ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
++ prepare_unused_channel_list);
++ if (ret < 0)
++ return ret;
++
++ unused_chan_list_done = true;
++ }
++
++ if (channel >= 0) {
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++ }
++
++ if (channel < 0) {
++ for (i = 0; i < arch_num_cc; i++) {
++ channel = 0;
++ for (;;) {
++ channel = find_next_bit(edma_cc[i]->edma_unused,
++ edma_cc[i]->num_channels,
++ channel);
++ if (channel == edma_cc[i]->num_channels)
++ break;
++ if (!test_and_set_bit(channel,
++ edma_cc[i]->edma_inuse)) {
++ done = 1;
++ ctlr = i;
++ break;
++ }
++ channel++;
++ }
++ if (done)
++ break;
++ }
++ if (!done)
++ return -ENOMEM;
++ } else if (channel >= edma_cc[ctlr]->num_channels) {
++ return -EINVAL;
++ } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
++ return -EBUSY;
++ }
++
++ /* ensure access through shadow region 0 */
++ edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
++
++ /* ensure no events are pending */
++ edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
++ &dummy_paramset, PARM_SIZE);
++
++ if (callback)
++ setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
++ callback, data);
++
++ map_dmach_queue(ctlr, channel, eventq_no);
++
++ return EDMA_CTLR_CHAN(ctlr, channel);
++}
++EXPORT_SYMBOL(edma_alloc_channel);
++
++
++/**
++ * edma_free_channel - deallocate DMA channel
++ * @channel: dma channel returned from edma_alloc_channel()
++ *
++ * This deallocates the DMA channel and associated parameter RAM slot
++ * allocated by edma_alloc_channel().
++ *
++ * Callers are responsible for ensuring the channel is inactive, and
++ * will not be reactivated by linking, chaining, or software calls to
++ * edma_start().
++ */
++void edma_free_channel(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel >= edma_cc[ctlr]->num_channels)
++ return;
++
++ setup_dma_interrupt(channel, NULL, NULL);
++ /* REVISIT should probably take out of shadow region 0 */
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(channel, edma_cc[ctlr]->edma_inuse);
++}
++EXPORT_SYMBOL(edma_free_channel);
++
++/**
++ * edma_alloc_slot - allocate DMA parameter RAM
++ * @slot: specific slot to allocate; negative for "any unused slot"
++ *
++ * This allocates a parameter RAM slot, initializing it to hold a
++ * dummy transfer. Slots allocated using this routine have not been
++ * mapped to a hardware DMA channel, and will normally be used by
++ * linking to them from a slot associated with a DMA channel.
++ *
++ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
++ * slots may be allocated on behalf of DSP firmware.
++ *
++ * Returns the number of the slot, else negative errno.
++ */
++int edma_alloc_slot(unsigned ctlr, int slot)
++{
++ if (slot >= 0)
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < 0) {
++ slot = edma_cc[ctlr]->num_channels;
++ for (;;) {
++ slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
++ edma_cc[ctlr]->num_slots, slot);
++ if (slot == edma_cc[ctlr]->num_slots)
++ return -ENOMEM;
++ if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
++ break;
++ }
++ } else if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots) {
++ return -EINVAL;
++ } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
++ return -EBUSY;
++ }
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ &dummy_paramset, PARM_SIZE);
++
++ return EDMA_CTLR_CHAN(ctlr, slot);
++}
++EXPORT_SYMBOL(edma_alloc_slot);
++
++/**
++ * edma_free_slot - deallocate DMA parameter RAM
++ * @slot: parameter RAM slot returned from edma_alloc_slot()
++ *
++ * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
++ * Callers are responsible for ensuring the slot is inactive, and will
++ * not be activated.
++ */
++void edma_free_slot(unsigned slot)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots)
++ return;
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(slot, edma_cc[ctlr]->edma_inuse);
++}
++EXPORT_SYMBOL(edma_free_slot);
++
++
++/**
++ * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
++ * The API will return the starting point of a set of
++ * contiguous parameter RAM slots that have been requested
++ *
++ * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
++ * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
++ * @count: number of contiguous Paramter RAM slots
++ * @slot - the start value of Parameter RAM slot that should be passed if id
++ * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
++ *
++ * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
++ * contiguous Parameter RAM slots from parameter RAM 64 in the case of
++ * DaVinci SOCs and 32 in the case of DA8xx SOCs.
++ *
++ * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
++ * set of contiguous parameter RAM slots from the "slot" that is passed as an
++ * argument to the API.
++ *
++ * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
++ * starts looking for a set of contiguous parameter RAMs from the "slot"
++ * that is passed as an argument to the API. On failure the API will try to
++ * find a set of contiguous Parameter RAM slots from the remaining Parameter
++ * RAM slots
++ */
++int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
++{
++ /*
++ * The start slot requested should be greater than
++ * the number of channels and lesser than the total number
++ * of slots
++ */
++ if ((id != EDMA_CONT_PARAMS_ANY) &&
++ (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots))
++ return -EINVAL;
++
++ /*
++ * The number of parameter RAM slots requested cannot be less than 1
++ * and cannot be more than the number of slots minus the number of
++ * channels
++ */
++ if (count < 1 || count >
++ (edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
++ return -EINVAL;
++
++ switch (id) {
++ case EDMA_CONT_PARAMS_ANY:
++ return reserve_contiguous_slots(ctlr, id, count,
++ edma_cc[ctlr]->num_channels);
++ case EDMA_CONT_PARAMS_FIXED_EXACT:
++ case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
++ return reserve_contiguous_slots(ctlr, id, count, slot);
++ default:
++ return -EINVAL;
++ }
++
++}
++EXPORT_SYMBOL(edma_alloc_cont_slots);
++
++/**
++ * edma_free_cont_slots - deallocate DMA parameter RAM slots
++ * @slot: first parameter RAM of a set of parameter RAM slots to be freed
++ * @count: the number of contiguous parameter RAM slots to be freed
++ *
++ * This deallocates the parameter RAM slots allocated by
++ * edma_alloc_cont_slots.
++ * Callers/applications need to keep track of sets of contiguous
++ * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
++ * API.
++ * Callers are responsible for ensuring the slots are inactive, and will
++ * not be activated.
++ */
++int edma_free_cont_slots(unsigned slot, int count)
++{
++ unsigned ctlr, slot_to_free;
++ int i;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_channels ||
++ slot >= edma_cc[ctlr]->num_slots ||
++ count < 1)
++ return -EINVAL;
++
++ for (i = slot; i < slot + count; ++i) {
++ ctlr = EDMA_CTLR(i);
++ slot_to_free = EDMA_CHAN_SLOT(i);
++
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
++ &dummy_paramset, PARM_SIZE);
++ clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(edma_free_cont_slots);
++
++/*-----------------------------------------------------------------------*/
++
++/* Parameter RAM operations (i) -- read/write partial slots */
++
++/**
++ * edma_set_src - set initial DMA source address in parameter RAM slot
++ * @slot: parameter RAM slot being configured
++ * @src_port: physical address of source (memory, controller FIFO, etc)
++ * @addressMode: INCR, except in very rare cases
++ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
++ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
++ *
++ * Note that the source address is modified during the DMA transfer
++ * according to edma_set_src_index().
++ */
++void edma_set_src(unsigned slot, dma_addr_t src_port,
++ enum address_mode mode, enum fifo_width width)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
++
++ if (mode) {
++ /* set SAM and program FWID */
++ i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
++ } else {
++ /* clear SAM */
++ i &= ~SAM;
++ }
++ edma_parm_write(ctlr, PARM_OPT, slot, i);
++
++ /* set the source port address
++ in source register of param structure */
++ edma_parm_write(ctlr, PARM_SRC, slot, src_port);
++ }
++}
++EXPORT_SYMBOL(edma_set_src);
++
++/**
++ * edma_set_dest - set initial DMA destination address in parameter RAM slot
++ * @slot: parameter RAM slot being configured
++ * @dest_port: physical address of destination (memory, controller FIFO, etc)
++ * @addressMode: INCR, except in very rare cases
++ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
++ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
++ *
++ * Note that the destination address is modified during the DMA transfer
++ * according to edma_set_dest_index().
++ */
++void edma_set_dest(unsigned slot, dma_addr_t dest_port,
++ enum address_mode mode, enum fifo_width width)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
++
++ if (mode) {
++ /* set DAM and program FWID */
++ i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
++ } else {
++ /* clear DAM */
++ i &= ~DAM;
++ }
++ edma_parm_write(ctlr, PARM_OPT, slot, i);
++ /* set the destination port address
++ in dest register of param structure */
++ edma_parm_write(ctlr, PARM_DST, slot, dest_port);
++ }
++}
++EXPORT_SYMBOL(edma_set_dest);
++
++/**
++ * edma_get_position - returns the current transfer points
++ * @slot: parameter RAM slot being examined
++ * @src: pointer to source port position
++ * @dst: pointer to destination port position
++ *
++ * Returns current source and destination addresses for a particular
++ * parameter RAM slot. Its channel should not be active when this is called.
++ */
++void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
++{
++ struct edmacc_param temp;
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
++ if (src != NULL)
++ *src = temp.src;
++ if (dst != NULL)
++ *dst = temp.dst;
++}
++EXPORT_SYMBOL(edma_get_position);
++
++/**
++ * edma_set_src_index - configure DMA source address indexing
++ * @slot: parameter RAM slot being configured
++ * @src_bidx: byte offset between source arrays in a frame
++ * @src_cidx: byte offset between source frames in a block
++ *
++ * Offsets are specified to support either contiguous or discontiguous
++ * memory transfers, or repeated access to a hardware register, as needed.
++ * When accessing hardware registers, both offsets are normally zero.
++ */
++void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
++ 0xffff0000, src_bidx);
++ edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
++ 0xffff0000, src_cidx);
++ }
++}
++EXPORT_SYMBOL(edma_set_src_index);
++
++/**
++ * edma_set_dest_index - configure DMA destination address indexing
++ * @slot: parameter RAM slot being configured
++ * @dest_bidx: byte offset between destination arrays in a frame
++ * @dest_cidx: byte offset between destination frames in a block
++ *
++ * Offsets are specified to support either contiguous or discontiguous
++ * memory transfers, or repeated access to a hardware register, as needed.
++ * When accessing hardware registers, both offsets are normally zero.
++ */
++void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
++ 0x0000ffff, dest_bidx << 16);
++ edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
++ 0x0000ffff, dest_cidx << 16);
++ }
++}
++EXPORT_SYMBOL(edma_set_dest_index);
++
++/**
++ * edma_set_transfer_params - configure DMA transfer parameters
++ * @slot: parameter RAM slot being configured
++ * @acnt: how many bytes per array (at least one)
++ * @bcnt: how many arrays per frame (at least one)
++ * @ccnt: how many frames per block (at least one)
++ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
++ * the value to reload into bcnt when it decrements to zero
++ * @sync_mode: ASYNC or ABSYNC
++ *
++ * See the EDMA3 documentation to understand how to configure and link
++ * transfers using the fields in PaRAM slots. If you are not doing it
++ * all at once with edma_write_slot(), you will use this routine
++ * plus two calls each for source and destination, setting the initial
++ * address and saying how to index that address.
++ *
++ * An example of an A-Synchronized transfer is a serial link using a
++ * single word shift register. In that case, @acnt would be equal to
++ * that word size; the serial controller issues a DMA synchronization
++ * event to transfer each word, and memory access by the DMA transfer
++ * controller will be word-at-a-time.
++ *
++ * An example of an AB-Synchronized transfer is a device using a FIFO.
++ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
++ * The controller with the FIFO issues DMA synchronization events when
++ * the FIFO threshold is reached, and the DMA transfer controller will
++ * transfer one frame to (or from) the FIFO. It will probably use
++ * efficient burst modes to access memory.
++ */
++void edma_set_transfer_params(unsigned slot,
++ u16 acnt, u16 bcnt, u16 ccnt,
++ u16 bcnt_rld, enum sync_dimension sync_mode)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot < edma_cc[ctlr]->num_slots) {
++ edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
++ 0x0000ffff, bcnt_rld << 16);
++ if (sync_mode == ASYNC)
++ edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
++ else
++ edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
++ /* Set the acount, bcount, ccount registers */
++ edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
++ edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
++ }
++}
++EXPORT_SYMBOL(edma_set_transfer_params);
++
++/**
++ * edma_link - link one parameter RAM slot to another
++ * @from: parameter RAM slot originating the link
++ * @to: parameter RAM slot which is the link target
++ *
++ * The originating slot should not be part of any active DMA transfer.
++ */
++void edma_link(unsigned from, unsigned to)
++{
++ unsigned ctlr_from, ctlr_to;
++
++ ctlr_from = EDMA_CTLR(from);
++ from = EDMA_CHAN_SLOT(from);
++ ctlr_to = EDMA_CTLR(to);
++ to = EDMA_CHAN_SLOT(to);
++
++ if (from >= edma_cc[ctlr_from]->num_slots)
++ return;
++ if (to >= edma_cc[ctlr_to]->num_slots)
++ return;
++ edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
++ PARM_OFFSET(to));
++}
++EXPORT_SYMBOL(edma_link);
++
++/**
++ * edma_unlink - cut link from one parameter RAM slot
++ * @from: parameter RAM slot originating the link
++ *
++ * The originating slot should not be part of any active DMA transfer.
++ * Its link is set to 0xffff.
++ */
++void edma_unlink(unsigned from)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(from);
++ from = EDMA_CHAN_SLOT(from);
++
++ if (from >= edma_cc[ctlr]->num_slots)
++ return;
++ edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
++}
++EXPORT_SYMBOL(edma_unlink);
++
++/*-----------------------------------------------------------------------*/
++
++/* Parameter RAM operations (ii) -- read/write whole parameter sets */
++
++/**
++ * edma_write_slot - write parameter RAM data for slot
++ * @slot: number of parameter RAM slot being modified
++ * @param: data to be written into parameter RAM slot
++ *
++ * Use this to assign all parameters of a transfer at once. This
++ * allows more efficient setup of transfers than issuing multiple
++ * calls to set up those parameters in small pieces, and provides
++ * complete control over all transfer options.
++ */
++void edma_write_slot(unsigned slot, const struct edmacc_param *param)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot >= edma_cc[ctlr]->num_slots)
++ return;
++ memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
++ PARM_SIZE);
++}
++EXPORT_SYMBOL(edma_write_slot);
++
++/**
++ * edma_read_slot - read parameter RAM data from slot
++ * @slot: number of parameter RAM slot being copied
++ * @param: where to store copy of parameter RAM data
++ *
++ * Use this to read data from a parameter RAM slot, perhaps to
++ * save them as a template for later reuse.
++ */
++void edma_read_slot(unsigned slot, struct edmacc_param *param)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(slot);
++ slot = EDMA_CHAN_SLOT(slot);
++
++ if (slot >= edma_cc[ctlr]->num_slots)
++ return;
++ memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
++ PARM_SIZE);
++}
++EXPORT_SYMBOL(edma_read_slot);
++
++/*-----------------------------------------------------------------------*/
++
++/* Various EDMA channel control operations */
++
++/**
++ * edma_pause - pause dma on a channel
++ * @channel: on which edma_start() has been called
++ *
++ * This temporarily disables EDMA hardware events on the specified channel,
++ * preventing them from triggering new transfers on its behalf
++ */
++void edma_pause(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
++ }
++}
++EXPORT_SYMBOL(edma_pause);
++
++/**
++ * edma_resume - resumes dma on a paused channel
++ * @channel: on which edma_pause() has been called
++ *
++ * This re-enables EDMA hardware events on the specified channel.
++ */
++void edma_resume(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
++ }
++}
++EXPORT_SYMBOL(edma_resume);
++
++/**
++ * edma_start - start dma on a channel
++ * @channel: channel being activated
++ *
++ * Channels with event associations will be triggered by their hardware
++ * events, and channels without such associations will be triggered by
++ * software. (At this writing there is no interface for using software
++ * triggers except with channels that don't support hardware triggers.)
++ *
++ * Returns zero on success, else negative errno.
++ */
++int edma_start(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = channel >> 5;
++ unsigned int mask = BIT(channel & 0x1f);
++
++ /* EDMA channels without event association */
++ if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
++ pr_debug("EDMA: ESR%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_ESR, j));
++ edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
++ return 0;
++ }
++
++ /* EDMA channel with event association */
++ pr_debug("EDMA: ER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_ER, j));
++ /* Clear any pending event or error */
++ edma_write_array(ctlr, EDMA_ECR, j, mask);
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
++ pr_debug("EDMA: EER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_EER, j));
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL(edma_start);
++
++/**
++ * edma_stop - stops dma on the channel passed
++ * @channel: channel being deactivated
++ *
++ * When @lch is a channel, any active transfer is paused and
++ * all pending hardware events are cleared. The current transfer
++ * may not be resumed, and the channel's Parameter RAM should be
++ * reinitialized before being reused.
++ */
++void edma_stop(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = channel >> 5;
++ unsigned int mask = BIT(channel & 0x1f);
++
++ edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++
++ pr_debug("EDMA: EER%d %08x\n", j,
++ edma_shadow0_read_array(ctlr, SH_EER, j));
++
++ /* REVISIT: consider guarding against inappropriate event
++ * chaining by overwriting with dummy_paramset.
++ */
++ }
++}
++EXPORT_SYMBOL(edma_stop);
++
++/******************************************************************************
++ *
++ * It cleans ParamEntry qand bring back EDMA to initial state if media has
++ * been removed before EDMA has finished.It is usedful for removable media.
++ * Arguments:
++ * ch_no - channel no
++ *
++ * Return: zero on success, or corresponding error no on failure
++ *
++ * FIXME this should not be needed ... edma_stop() should suffice.
++ *
++ *****************************************************************************/
++
++void edma_clean_channel(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel < edma_cc[ctlr]->num_channels) {
++ int j = (channel >> 5);
++ unsigned int mask = BIT(channel & 0x1f);
++
++ pr_debug("EDMA: EMR%d %08x\n", j,
++ edma_read_array(ctlr, EDMA_EMR, j));
++ edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
++ /* Clear the corresponding EMR bits */
++ edma_write_array(ctlr, EDMA_EMCR, j, mask);
++ /* Clear any SER */
++ edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
++ edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
++ }
++}
++EXPORT_SYMBOL(edma_clean_channel);
++
++/*
++ * edma_clear_event - clear an outstanding event on the DMA channel
++ * Arguments:
++ * channel - channel number
++ */
++void edma_clear_event(unsigned channel)
++{
++ unsigned ctlr;
++
++ ctlr = EDMA_CTLR(channel);
++ channel = EDMA_CHAN_SLOT(channel);
++
++ if (channel >= edma_cc[ctlr]->num_channels)
++ return;
++ if (channel < 32)
++ edma_write(ctlr, EDMA_ECR, BIT(channel));
++ else
++ edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
++}
++EXPORT_SYMBOL(edma_clear_event);
++
++/*-----------------------------------------------------------------------*/
++
++static int __init edma_probe(struct platform_device *pdev)
++{
++ struct edma_soc_info **info = pdev->dev.platform_data;
++ const s8 (*queue_priority_mapping)[2];
++ const s8 (*queue_tc_mapping)[2];
++ int i, j, off, ln, found = 0;
++ int status = -1;
++ const s16 (*rsv_chans)[2];
++ const s16 (*rsv_slots)[2];
++ int irq[EDMA_MAX_CC] = {0, 0};
++ int err_irq[EDMA_MAX_CC] = {0, 0};
++ struct resource *r[EDMA_MAX_CC] = {NULL};
++ resource_size_t len[EDMA_MAX_CC];
++ char res_name[10];
++ char irq_name[10];
++
++ if (!info)
++ return -ENODEV;
++
++ for (j = 0; j < EDMA_MAX_CC; j++) {
++ sprintf(res_name, "edma_cc%d", j);
++ r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ res_name);
++ if (!r[j] || !info[j]) {
++ if (found)
++ break;
++ else
++ return -ENODEV;
++ } else {
++ found = 1;
++ }
++
++ len[j] = resource_size(r[j]);
++
++ r[j] = request_mem_region(r[j]->start, len[j],
++ dev_name(&pdev->dev));
++ if (!r[j]) {
++ status = -EBUSY;
++ goto fail1;
++ }
++
++ edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
++ if (!edmacc_regs_base[j]) {
++ status = -EBUSY;
++ goto fail1;
++ }
++
++ edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
++ if (!edma_cc[j]) {
++ status = -ENOMEM;
++ goto fail1;
++ }
++
++ edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
++ EDMA_MAX_DMACH);
++ edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
++ EDMA_MAX_PARAMENTRY);
++ edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
++ EDMA_MAX_CC);
++
++ edma_cc[j]->default_queue = info[j]->default_queue;
++
++ dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
++ edmacc_regs_base[j]);
++
++ for (i = 0; i < edma_cc[j]->num_slots; i++)
++ memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
++ &dummy_paramset, PARM_SIZE);
++
++ /* Mark all channels as unused */
++ memset(edma_cc[j]->edma_unused, 0xff,
++ sizeof(edma_cc[j]->edma_unused));
++
++ if (info[j]->rsv) {
++
++ /* Clear the reserved channels in unused list */
++ rsv_chans = info[j]->rsv->rsv_chans;
++ if (rsv_chans) {
++ for (i = 0; rsv_chans[i][0] != -1; i++) {
++ off = rsv_chans[i][0];
++ ln = rsv_chans[i][1];
++ clear_bits(off, ln,
++ edma_cc[j]->edma_unused);
++ }
++ }
++
++ /* Set the reserved slots in inuse list */
++ rsv_slots = info[j]->rsv->rsv_slots;
++ if (rsv_slots) {
++ for (i = 0; rsv_slots[i][0] != -1; i++) {
++ off = rsv_slots[i][0];
++ ln = rsv_slots[i][1];
++ set_bits(off, ln,
++ edma_cc[j]->edma_inuse);
++ }
++ }
++ }
++
++ sprintf(irq_name, "edma%d", j);
++ irq[j] = platform_get_irq_byname(pdev, irq_name);
++ edma_cc[j]->irq_res_start = irq[j];
++ status = request_irq(irq[j], dma_irq_handler, 0, "edma",
++ &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ irq[j], status);
++ goto fail;
++ }
++
++ sprintf(irq_name, "edma%d_err", j);
++ err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ edma_cc[j]->irq_res_end = err_irq[j];
++ status = request_irq(err_irq[j], dma_ccerr_handler, 0,
++ "edma_error", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ err_irq[j], status);
++ goto fail;
++ }
++
++ for (i = 0; i < edma_cc[j]->num_channels; i++)
++ map_dmach_queue(j, i, info[j]->default_queue);
++
++ queue_tc_mapping = info[j]->queue_tc_mapping;
++ queue_priority_mapping = info[j]->queue_priority_mapping;
++
++ /* Event queue to TC mapping */
++ for (i = 0; queue_tc_mapping[i][0] != -1; i++)
++ map_queue_tc(j, queue_tc_mapping[i][0],
++ queue_tc_mapping[i][1]);
++
++ /* Event queue priority mapping */
++ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
++ assign_priority_to_queue(j,
++ queue_priority_mapping[i][0],
++ queue_priority_mapping[i][1]);
++
++ /* Map the channel to param entry if channel mapping logic
++ * exist
++ */
++ if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
++ map_dmach_param(j);
++
++ for (i = 0; i < info[j]->n_region; i++) {
++ edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
++ edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
++ edma_write_array(j, EDMA_QRAE, i, 0x0);
++ }
++ arch_num_cc++;
++ }
++
++ if (tc_errs_handled) {
++ status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
++ "edma_tc0", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
++ IRQ_TCERRINT0, status);
++ return status;
++ }
++ status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
++ "edma_tc1", &pdev->dev);
++ if (status < 0) {
++ dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
++ IRQ_TCERRINT, status);
++ return status;
++ }
++ }
++
++ return 0;
++
++fail:
++ for (i = 0; i < EDMA_MAX_CC; i++) {
++ if (err_irq[i])
++ free_irq(err_irq[i], &pdev->dev);
++ if (irq[i])
++ free_irq(irq[i], &pdev->dev);
++ }
++fail1:
++ for (i = 0; i < EDMA_MAX_CC; i++) {
++ if (r[i])
++ release_mem_region(r[i]->start, len[i]);
++ if (edmacc_regs_base[i])
++ iounmap(edmacc_regs_base[i]);
++ kfree(edma_cc[i]);
++ }
++ return status;
++}
++
++
++static struct platform_driver edma_driver = {
++ .driver.name = "edma",
++};
++
++static int __init edma_init(void)
++{
++ return platform_driver_probe(&edma_driver, edma_probe);
++}
++arch_initcall(edma_init);
++
+diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
+index 2227eff..97c639e 100644
+--- a/arch/arm/mach-davinci/Makefile
++++ b/arch/arm/mach-davinci/Makefile
+@@ -5,7 +5,7 @@
+
+ # Common objects
+ obj-y := time.o clock.o serial.o psc.o \
+- dma.o usb.o common.o sram.o aemif.o
++ usb.o common.o sram.o aemif.o
+
+ obj-$(CONFIG_DAVINCI_MUX) += mux.o
+
+diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
+index be30997..86f55ba 100644
+--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
++++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
+@@ -26,12 +26,12 @@
+ #include <linux/input.h>
+ #include <linux/input/matrix_keypad.h>
+ #include <linux/spi/spi.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/arch.h>
+ #include <asm/mach-types.h>
+
+ #include <mach/irqs.h>
+-#include <mach/edma.h>
+ #include <mach/mux.h>
+ #include <mach/cp_intc.h>
+ #include <mach/tnetv107x.h>
+diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
+index 12d544b..d26a6bc 100644
+--- a/arch/arm/mach-davinci/davinci.h
++++ b/arch/arm/mach-davinci/davinci.h
+@@ -23,9 +23,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/spi/spi.h>
+ #include <linux/platform_data/davinci_asp.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/keyscan-davinci.h>
+ #include <mach/hardware.h>
+-#include <mach/edma.h>
+
+ #include <media/davinci/vpfe_capture.h>
+ #include <media/davinci/vpif_types.h>
+diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
+index 29b17f7..59efd7f 100644
+--- a/arch/arm/mach-davinci/devices-tnetv107x.c
++++ b/arch/arm/mach-davinci/devices-tnetv107x.c
+@@ -18,10 +18,10 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/clk.h>
+ #include <linux/slab.h>
++#include <linux/platform_data/edma.h>
+
+ #include <mach/common.h>
+ #include <mach/irqs.h>
+-#include <mach/edma.h>
+ #include <mach/tnetv107x.h>
+
+ #include "clock.h"
+diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
+index 4c48a36..f45d591 100644
+--- a/arch/arm/mach-davinci/devices.c
++++ b/arch/arm/mach-davinci/devices.c
+@@ -19,9 +19,10 @@
+ #include <mach/irqs.h>
+ #include <mach/cputype.h>
+ #include <mach/mux.h>
+-#include <mach/edma.h>
+ #include <linux/platform_data/mmc-davinci.h>
+ #include <mach/time.h>
++#include <linux/platform_data/edma.h>
++
+
+ #include "davinci.h"
+ #include "clock.h"
+@@ -141,10 +142,10 @@ static struct resource mmcsd0_resources[] = {
+ },
+ /* DMA channels: RX, then TX */
+ {
+- .start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCRXEVT),
++ .start = EDMA_CTLR_CHAN(0, 26),
+ .flags = IORESOURCE_DMA,
+ }, {
+- .start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCTXEVT),
++ .start = EDMA_CTLR_CHAN(0, 27),
+ .flags = IORESOURCE_DMA,
+ },
+ };
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index a255434..b165c27 100644
+--- a/arch/arm/mach-davinci/dm355.c
++++ b/arch/arm/mach-davinci/dm355.c
+@@ -19,7 +19,6 @@
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+ #include <mach/irqs.h>
+@@ -28,6 +27,7 @@
+ #include <mach/common.h>
+ #include <linux/platform_data/spi-davinci.h>
+ #include <mach/gpio-davinci.h>
++#include <linux/platform_data/edma.h>
+
+ #include "davinci.h"
+ #include "clock.h"
+diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
+index b680c83..a611716 100644
+--- a/arch/arm/mach-davinci/dm365.c
++++ b/arch/arm/mach-davinci/dm365.c
+@@ -18,11 +18,11 @@
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/spi/spi.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+ #include <mach/irqs.h>
+diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
+index 14e9947b..5b0a263 100644
+--- a/arch/arm/mach-davinci/dm644x.c
++++ b/arch/arm/mach-davinci/dm644x.c
+@@ -12,11 +12,11 @@
+ #include <linux/clk.h>
+ #include <linux/serial_8250.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/irqs.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
+index 97c0f8e..08f9dab 100644
+--- a/arch/arm/mach-davinci/dm646x.c
++++ b/arch/arm/mach-davinci/dm646x.c
+@@ -13,11 +13,11 @@
+ #include <linux/clk.h>
+ #include <linux/serial_8250.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+
+ #include <asm/mach/map.h>
+
+ #include <mach/cputype.h>
+-#include <mach/edma.h>
+ #include <mach/irqs.h>
+ #include <mach/psc.h>
+ #include <mach/mux.h>
+diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
+deleted file mode 100644
+index a685e97..0000000
+--- a/arch/arm/mach-davinci/dma.c
++++ /dev/null
+@@ -1,1588 +0,0 @@
+-/*
+- * EDMA3 support for DaVinci
+- *
+- * Copyright (C) 2006-2009 Texas Instruments.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/platform_device.h>
+-#include <linux/io.h>
+-#include <linux/slab.h>
+-
+-#include <mach/edma.h>
+-
+-/* Offsets matching "struct edmacc_param" */
+-#define PARM_OPT 0x00
+-#define PARM_SRC 0x04
+-#define PARM_A_B_CNT 0x08
+-#define PARM_DST 0x0c
+-#define PARM_SRC_DST_BIDX 0x10
+-#define PARM_LINK_BCNTRLD 0x14
+-#define PARM_SRC_DST_CIDX 0x18
+-#define PARM_CCNT 0x1c
+-
+-#define PARM_SIZE 0x20
+-
+-/* Offsets for EDMA CC global channel registers and their shadows */
+-#define SH_ER 0x00 /* 64 bits */
+-#define SH_ECR 0x08 /* 64 bits */
+-#define SH_ESR 0x10 /* 64 bits */
+-#define SH_CER 0x18 /* 64 bits */
+-#define SH_EER 0x20 /* 64 bits */
+-#define SH_EECR 0x28 /* 64 bits */
+-#define SH_EESR 0x30 /* 64 bits */
+-#define SH_SER 0x38 /* 64 bits */
+-#define SH_SECR 0x40 /* 64 bits */
+-#define SH_IER 0x50 /* 64 bits */
+-#define SH_IECR 0x58 /* 64 bits */
+-#define SH_IESR 0x60 /* 64 bits */
+-#define SH_IPR 0x68 /* 64 bits */
+-#define SH_ICR 0x70 /* 64 bits */
+-#define SH_IEVAL 0x78
+-#define SH_QER 0x80
+-#define SH_QEER 0x84
+-#define SH_QEECR 0x88
+-#define SH_QEESR 0x8c
+-#define SH_QSER 0x90
+-#define SH_QSECR 0x94
+-#define SH_SIZE 0x200
+-
+-/* Offsets for EDMA CC global registers */
+-#define EDMA_REV 0x0000
+-#define EDMA_CCCFG 0x0004
+-#define EDMA_QCHMAP 0x0200 /* 8 registers */
+-#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
+-#define EDMA_QDMAQNUM 0x0260
+-#define EDMA_QUETCMAP 0x0280
+-#define EDMA_QUEPRI 0x0284
+-#define EDMA_EMR 0x0300 /* 64 bits */
+-#define EDMA_EMCR 0x0308 /* 64 bits */
+-#define EDMA_QEMR 0x0310
+-#define EDMA_QEMCR 0x0314
+-#define EDMA_CCERR 0x0318
+-#define EDMA_CCERRCLR 0x031c
+-#define EDMA_EEVAL 0x0320
+-#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
+-#define EDMA_QRAE 0x0380 /* 4 registers */
+-#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
+-#define EDMA_QSTAT 0x0600 /* 2 registers */
+-#define EDMA_QWMTHRA 0x0620
+-#define EDMA_QWMTHRB 0x0624
+-#define EDMA_CCSTAT 0x0640
+-
+-#define EDMA_M 0x1000 /* global channel registers */
+-#define EDMA_ECR 0x1008
+-#define EDMA_ECRH 0x100C
+-#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
+-#define EDMA_PARM 0x4000 /* 128 param entries */
+-
+-#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
+-
+-#define EDMA_DCHMAP 0x0100 /* 64 registers */
+-#define CHMAP_EXIST BIT(24)
+-
+-#define EDMA_MAX_DMACH 64
+-#define EDMA_MAX_PARAMENTRY 512
+-
+-/*****************************************************************************/
+-
+-static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
+-
+-static inline unsigned int edma_read(unsigned ctlr, int offset)
+-{
+- return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
+-}
+-
+-static inline void edma_write(unsigned ctlr, int offset, int val)
+-{
+- __raw_writel(val, edmacc_regs_base[ctlr] + offset);
+-}
+-static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
+- unsigned or)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val &= and;
+- val |= or;
+- edma_write(ctlr, offset, val);
+-}
+-static inline void edma_and(unsigned ctlr, int offset, unsigned and)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val &= and;
+- edma_write(ctlr, offset, val);
+-}
+-static inline void edma_or(unsigned ctlr, int offset, unsigned or)
+-{
+- unsigned val = edma_read(ctlr, offset);
+- val |= or;
+- edma_write(ctlr, offset, val);
+-}
+-static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
+-{
+- return edma_read(ctlr, offset + (i << 2));
+-}
+-static inline void edma_write_array(unsigned ctlr, int offset, int i,
+- unsigned val)
+-{
+- edma_write(ctlr, offset + (i << 2), val);
+-}
+-static inline void edma_modify_array(unsigned ctlr, int offset, int i,
+- unsigned and, unsigned or)
+-{
+- edma_modify(ctlr, offset + (i << 2), and, or);
+-}
+-static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
+-{
+- edma_or(ctlr, offset + (i << 2), or);
+-}
+-static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
+- unsigned or)
+-{
+- edma_or(ctlr, offset + ((i*2 + j) << 2), or);
+-}
+-static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
+- unsigned val)
+-{
+- edma_write(ctlr, offset + ((i*2 + j) << 2), val);
+-}
+-static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
+-{
+- return edma_read(ctlr, EDMA_SHADOW0 + offset);
+-}
+-static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
+- int i)
+-{
+- return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
+-}
+-static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
+-{
+- edma_write(ctlr, EDMA_SHADOW0 + offset, val);
+-}
+-static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
+- unsigned val)
+-{
+- edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
+-}
+-static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
+- int param_no)
+-{
+- return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
+-}
+-static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
+- unsigned val)
+-{
+- edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
+-}
+-static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
+- unsigned and, unsigned or)
+-{
+- edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
+-}
+-static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
+- unsigned and)
+-{
+- edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
+-}
+-static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
+- unsigned or)
+-{
+- edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
+-}
+-
+-static inline void set_bits(int offset, int len, unsigned long *p)
+-{
+- for (; len > 0; len--)
+- set_bit(offset + (len - 1), p);
+-}
+-
+-static inline void clear_bits(int offset, int len, unsigned long *p)
+-{
+- for (; len > 0; len--)
+- clear_bit(offset + (len - 1), p);
+-}
+-
+-/*****************************************************************************/
+-
+-/* actual number of DMA channels and slots on this silicon */
+-struct edma {
+- /* how many dma resources of each type */
+- unsigned num_channels;
+- unsigned num_region;
+- unsigned num_slots;
+- unsigned num_tc;
+- unsigned num_cc;
+- enum dma_event_q default_queue;
+-
+- /* list of channels with no even trigger; terminated by "-1" */
+- const s8 *noevent;
+-
+- /* The edma_inuse bit for each PaRAM slot is clear unless the
+- * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+- */
+- DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+-
+- /* The edma_unused bit for each channel is clear unless
+- * it is not being used on this platform. It uses a bit
+- * of SOC-specific initialization code.
+- */
+- DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
+-
+- unsigned irq_res_start;
+- unsigned irq_res_end;
+-
+- struct dma_interrupt_data {
+- void (*callback)(unsigned channel, unsigned short ch_status,
+- void *data);
+- void *data;
+- } intr_data[EDMA_MAX_DMACH];
+-};
+-
+-static struct edma *edma_cc[EDMA_MAX_CC];
+-static int arch_num_cc;
+-
+-/* dummy param set used to (re)initialize parameter RAM slots */
+-static const struct edmacc_param dummy_paramset = {
+- .link_bcntrld = 0xffff,
+- .ccnt = 1,
+-};
+-
+-/*****************************************************************************/
+-
+-static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
+- enum dma_event_q queue_no)
+-{
+- int bit = (ch_no & 0x7) * 4;
+-
+- /* default to low priority queue */
+- if (queue_no == EVENTQ_DEFAULT)
+- queue_no = edma_cc[ctlr]->default_queue;
+-
+- queue_no &= 7;
+- edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
+- ~(0x7 << bit), queue_no << bit);
+-}
+-
+-static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
+-{
+- int bit = queue_no * 4;
+- edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
+-}
+-
+-static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
+- int priority)
+-{
+- int bit = queue_no * 4;
+- edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
+- ((priority & 0x7) << bit));
+-}
+-
+-/**
+- * map_dmach_param - Maps channel number to param entry number
+- *
+- * This maps the dma channel number to param entry numberter. In
+- * other words using the DMA channel mapping registers a param entry
+- * can be mapped to any channel
+- *
+- * Callers are responsible for ensuring the channel mapping logic is
+- * included in that particular EDMA variant (Eg : dm646x)
+- *
+- */
+-static void __init map_dmach_param(unsigned ctlr)
+-{
+- int i;
+- for (i = 0; i < EDMA_MAX_DMACH; i++)
+- edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
+-}
+-
+-static inline void
+-setup_dma_interrupt(unsigned lch,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(lch);
+- lch = EDMA_CHAN_SLOT(lch);
+-
+- if (!callback)
+- edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
+- BIT(lch & 0x1f));
+-
+- edma_cc[ctlr]->intr_data[lch].callback = callback;
+- edma_cc[ctlr]->intr_data[lch].data = data;
+-
+- if (callback) {
+- edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
+- BIT(lch & 0x1f));
+- edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
+- BIT(lch & 0x1f));
+- }
+-}
+-
+-static int irq2ctlr(int irq)
+-{
+- if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
+- return 0;
+- else if (irq >= edma_cc[1]->irq_res_start &&
+- irq <= edma_cc[1]->irq_res_end)
+- return 1;
+-
+- return -1;
+-}
+-
+-/******************************************************************************
+- *
+- * DMA interrupt handler
+- *
+- *****************************************************************************/
+-static irqreturn_t dma_irq_handler(int irq, void *data)
+-{
+- int ctlr;
+- u32 sh_ier;
+- u32 sh_ipr;
+- u32 bank;
+-
+- ctlr = irq2ctlr(irq);
+- if (ctlr < 0)
+- return IRQ_NONE;
+-
+- dev_dbg(data, "dma_irq_handler\n");
+-
+- sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
+- if (!sh_ipr) {
+- sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
+- if (!sh_ipr)
+- return IRQ_NONE;
+- sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
+- bank = 1;
+- } else {
+- sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
+- bank = 0;
+- }
+-
+- do {
+- u32 slot;
+- u32 channel;
+-
+- dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
+-
+- slot = __ffs(sh_ipr);
+- sh_ipr &= ~(BIT(slot));
+-
+- if (sh_ier & BIT(slot)) {
+- channel = (bank << 5) | slot;
+- /* Clear the corresponding IPR bits */
+- edma_shadow0_write_array(ctlr, SH_ICR, bank,
+- BIT(slot));
+- if (edma_cc[ctlr]->intr_data[channel].callback)
+- edma_cc[ctlr]->intr_data[channel].callback(
+- channel, DMA_COMPLETE,
+- edma_cc[ctlr]->intr_data[channel].data);
+- }
+- } while (sh_ipr);
+-
+- edma_shadow0_write(ctlr, SH_IEVAL, 1);
+- return IRQ_HANDLED;
+-}
+-
+-/******************************************************************************
+- *
+- * DMA error interrupt handler
+- *
+- *****************************************************************************/
+-static irqreturn_t dma_ccerr_handler(int irq, void *data)
+-{
+- int i;
+- int ctlr;
+- unsigned int cnt = 0;
+-
+- ctlr = irq2ctlr(irq);
+- if (ctlr < 0)
+- return IRQ_NONE;
+-
+- dev_dbg(data, "dma_ccerr_handler\n");
+-
+- if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+- (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+- (edma_read(ctlr, EDMA_QEMR) == 0) &&
+- (edma_read(ctlr, EDMA_CCERR) == 0))
+- return IRQ_NONE;
+-
+- while (1) {
+- int j = -1;
+- if (edma_read_array(ctlr, EDMA_EMR, 0))
+- j = 0;
+- else if (edma_read_array(ctlr, EDMA_EMR, 1))
+- j = 1;
+- if (j >= 0) {
+- dev_dbg(data, "EMR%d %08x\n", j,
+- edma_read_array(ctlr, EDMA_EMR, j));
+- for (i = 0; i < 32; i++) {
+- int k = (j << 5) + i;
+- if (edma_read_array(ctlr, EDMA_EMR, j) &
+- BIT(i)) {
+- /* Clear the corresponding EMR bits */
+- edma_write_array(ctlr, EDMA_EMCR, j,
+- BIT(i));
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR,
+- j, BIT(i));
+- if (edma_cc[ctlr]->intr_data[k].
+- callback) {
+- edma_cc[ctlr]->intr_data[k].
+- callback(k,
+- DMA_CC_ERROR,
+- edma_cc[ctlr]->intr_data
+- [k].data);
+- }
+- }
+- }
+- } else if (edma_read(ctlr, EDMA_QEMR)) {
+- dev_dbg(data, "QEMR %02x\n",
+- edma_read(ctlr, EDMA_QEMR));
+- for (i = 0; i < 8; i++) {
+- if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
+- /* Clear the corresponding IPR bits */
+- edma_write(ctlr, EDMA_QEMCR, BIT(i));
+- edma_shadow0_write(ctlr, SH_QSECR,
+- BIT(i));
+-
+- /* NOTE: not reported!! */
+- }
+- }
+- } else if (edma_read(ctlr, EDMA_CCERR)) {
+- dev_dbg(data, "CCERR %08x\n",
+- edma_read(ctlr, EDMA_CCERR));
+- /* FIXME: CCERR.BIT(16) ignored! much better
+- * to just write CCERRCLR with CCERR value...
+- */
+- for (i = 0; i < 8; i++) {
+- if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
+- /* Clear the corresponding IPR bits */
+- edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
+-
+- /* NOTE: not reported!! */
+- }
+- }
+- }
+- if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+- (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+- (edma_read(ctlr, EDMA_QEMR) == 0) &&
+- (edma_read(ctlr, EDMA_CCERR) == 0))
+- break;
+- cnt++;
+- if (cnt > 10)
+- break;
+- }
+- edma_write(ctlr, EDMA_EEVAL, 1);
+- return IRQ_HANDLED;
+-}
+-
+-/******************************************************************************
+- *
+- * Transfer controller error interrupt handlers
+- *
+- *****************************************************************************/
+-
+-#define tc_errs_handled false /* disabled as long as they're NOPs */
+-
+-static irqreturn_t dma_tc0err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc0err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t dma_tc1err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc1err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static int reserve_contiguous_slots(int ctlr, unsigned int id,
+- unsigned int num_slots,
+- unsigned int start_slot)
+-{
+- int i, j;
+- unsigned int count = num_slots;
+- int stop_slot = start_slot;
+- DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
+-
+- for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
+- j = EDMA_CHAN_SLOT(i);
+- if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
+- /* Record our current beginning slot */
+- if (count == num_slots)
+- stop_slot = i;
+-
+- count--;
+- set_bit(j, tmp_inuse);
+-
+- if (count == 0)
+- break;
+- } else {
+- clear_bit(j, tmp_inuse);
+-
+- if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
+- stop_slot = i;
+- break;
+- } else {
+- count = num_slots;
+- }
+- }
+- }
+-
+- /*
+- * We have to clear any bits that we set
+- * if we run out parameter RAM slots, i.e we do find a set
+- * of contiguous parameter RAM slots but do not find the exact number
+- * requested as we may reach the total number of parameter RAM slots
+- */
+- if (i == edma_cc[ctlr]->num_slots)
+- stop_slot = i;
+-
+- j = start_slot;
+- for_each_set_bit_from(j, tmp_inuse, stop_slot)
+- clear_bit(j, edma_cc[ctlr]->edma_inuse);
+-
+- if (count)
+- return -EBUSY;
+-
+- for (j = i - num_slots + 1; j <= i; ++j)
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
+- &dummy_paramset, PARM_SIZE);
+-
+- return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
+-}
+-
+-static int prepare_unused_channel_list(struct device *dev, void *data)
+-{
+- struct platform_device *pdev = to_platform_device(dev);
+- int i, ctlr;
+-
+- for (i = 0; i < pdev->num_resources; i++) {
+- if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
+- (int)pdev->resource[i].start >= 0) {
+- ctlr = EDMA_CTLR(pdev->resource[i].start);
+- clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
+- edma_cc[ctlr]->edma_unused);
+- }
+- }
+-
+- return 0;
+-}
+-
+-/*-----------------------------------------------------------------------*/
+-
+-static bool unused_chan_list_done;
+-
+-/* Resource alloc/free: dma channels, parameter RAM slots */
+-
+-/**
+- * edma_alloc_channel - allocate DMA channel and paired parameter RAM
+- * @channel: specific channel to allocate; negative for "any unmapped channel"
+- * @callback: optional; to be issued on DMA completion or errors
+- * @data: passed to callback
+- * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
+- * Controller (TC) executes requests using this channel. Use
+- * EVENTQ_DEFAULT unless you really need a high priority queue.
+- *
+- * This allocates a DMA channel and its associated parameter RAM slot.
+- * The parameter RAM is initialized to hold a dummy transfer.
+- *
+- * Normal use is to pass a specific channel number as @channel, to make
+- * use of hardware events mapped to that channel. When the channel will
+- * be used only for software triggering or event chaining, channels not
+- * mapped to hardware events (or mapped to unused events) are preferable.
+- *
+- * DMA transfers start from a channel using edma_start(), or by
+- * chaining. When the transfer described in that channel's parameter RAM
+- * slot completes, that slot's data may be reloaded through a link.
+- *
+- * DMA errors are only reported to the @callback associated with the
+- * channel driving that transfer, but transfer completion callbacks can
+- * be sent to another channel under control of the TCC field in
+- * the option word of the transfer's parameter RAM set. Drivers must not
+- * use DMA transfer completion callbacks for channels they did not allocate.
+- * (The same applies to TCC codes used in transfer chaining.)
+- *
+- * Returns the number of the channel, else negative errno.
+- */
+-int edma_alloc_channel(int channel,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data,
+- enum dma_event_q eventq_no)
+-{
+- unsigned i, done = 0, ctlr = 0;
+- int ret = 0;
+-
+- if (!unused_chan_list_done) {
+- /*
+- * Scan all the platform devices to find out the EDMA channels
+- * used and clear them in the unused list, making the rest
+- * available for ARM usage.
+- */
+- ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
+- prepare_unused_channel_list);
+- if (ret < 0)
+- return ret;
+-
+- unused_chan_list_done = true;
+- }
+-
+- if (channel >= 0) {
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+- }
+-
+- if (channel < 0) {
+- for (i = 0; i < arch_num_cc; i++) {
+- channel = 0;
+- for (;;) {
+- channel = find_next_bit(edma_cc[i]->edma_unused,
+- edma_cc[i]->num_channels,
+- channel);
+- if (channel == edma_cc[i]->num_channels)
+- break;
+- if (!test_and_set_bit(channel,
+- edma_cc[i]->edma_inuse)) {
+- done = 1;
+- ctlr = i;
+- break;
+- }
+- channel++;
+- }
+- if (done)
+- break;
+- }
+- if (!done)
+- return -ENOMEM;
+- } else if (channel >= edma_cc[ctlr]->num_channels) {
+- return -EINVAL;
+- } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
+- return -EBUSY;
+- }
+-
+- /* ensure access through shadow region 0 */
+- edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+-
+- /* ensure no events are pending */
+- edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+- &dummy_paramset, PARM_SIZE);
+-
+- if (callback)
+- setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
+- callback, data);
+-
+- map_dmach_queue(ctlr, channel, eventq_no);
+-
+- return EDMA_CTLR_CHAN(ctlr, channel);
+-}
+-EXPORT_SYMBOL(edma_alloc_channel);
+-
+-
+-/**
+- * edma_free_channel - deallocate DMA channel
+- * @channel: dma channel returned from edma_alloc_channel()
+- *
+- * This deallocates the DMA channel and associated parameter RAM slot
+- * allocated by edma_alloc_channel().
+- *
+- * Callers are responsible for ensuring the channel is inactive, and
+- * will not be reactivated by linking, chaining, or software calls to
+- * edma_start().
+- */
+-void edma_free_channel(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel >= edma_cc[ctlr]->num_channels)
+- return;
+-
+- setup_dma_interrupt(channel, NULL, NULL);
+- /* REVISIT should probably take out of shadow region 0 */
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(channel, edma_cc[ctlr]->edma_inuse);
+-}
+-EXPORT_SYMBOL(edma_free_channel);
+-
+-/**
+- * edma_alloc_slot - allocate DMA parameter RAM
+- * @slot: specific slot to allocate; negative for "any unused slot"
+- *
+- * This allocates a parameter RAM slot, initializing it to hold a
+- * dummy transfer. Slots allocated using this routine have not been
+- * mapped to a hardware DMA channel, and will normally be used by
+- * linking to them from a slot associated with a DMA channel.
+- *
+- * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+- * slots may be allocated on behalf of DSP firmware.
+- *
+- * Returns the number of the slot, else negative errno.
+- */
+-int edma_alloc_slot(unsigned ctlr, int slot)
+-{
+- if (slot >= 0)
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < 0) {
+- slot = edma_cc[ctlr]->num_channels;
+- for (;;) {
+- slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
+- edma_cc[ctlr]->num_slots, slot);
+- if (slot == edma_cc[ctlr]->num_slots)
+- return -ENOMEM;
+- if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
+- break;
+- }
+- } else if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots) {
+- return -EINVAL;
+- } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
+- return -EBUSY;
+- }
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- &dummy_paramset, PARM_SIZE);
+-
+- return EDMA_CTLR_CHAN(ctlr, slot);
+-}
+-EXPORT_SYMBOL(edma_alloc_slot);
+-
+-/**
+- * edma_free_slot - deallocate DMA parameter RAM
+- * @slot: parameter RAM slot returned from edma_alloc_slot()
+- *
+- * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
+- * Callers are responsible for ensuring the slot is inactive, and will
+- * not be activated.
+- */
+-void edma_free_slot(unsigned slot)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots)
+- return;
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(slot, edma_cc[ctlr]->edma_inuse);
+-}
+-EXPORT_SYMBOL(edma_free_slot);
+-
+-
+-/**
+- * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
+- * The API will return the starting point of a set of
+- * contiguous parameter RAM slots that have been requested
+- *
+- * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
+- * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+- * @count: number of contiguous Paramter RAM slots
+- * @slot - the start value of Parameter RAM slot that should be passed if id
+- * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+- *
+- * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
+- * contiguous Parameter RAM slots from parameter RAM 64 in the case of
+- * DaVinci SOCs and 32 in the case of DA8xx SOCs.
+- *
+- * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
+- * set of contiguous parameter RAM slots from the "slot" that is passed as an
+- * argument to the API.
+- *
+- * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
+- * starts looking for a set of contiguous parameter RAMs from the "slot"
+- * that is passed as an argument to the API. On failure the API will try to
+- * find a set of contiguous Parameter RAM slots from the remaining Parameter
+- * RAM slots
+- */
+-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
+-{
+- /*
+- * The start slot requested should be greater than
+- * the number of channels and lesser than the total number
+- * of slots
+- */
+- if ((id != EDMA_CONT_PARAMS_ANY) &&
+- (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots))
+- return -EINVAL;
+-
+- /*
+- * The number of parameter RAM slots requested cannot be less than 1
+- * and cannot be more than the number of slots minus the number of
+- * channels
+- */
+- if (count < 1 || count >
+- (edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
+- return -EINVAL;
+-
+- switch (id) {
+- case EDMA_CONT_PARAMS_ANY:
+- return reserve_contiguous_slots(ctlr, id, count,
+- edma_cc[ctlr]->num_channels);
+- case EDMA_CONT_PARAMS_FIXED_EXACT:
+- case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
+- return reserve_contiguous_slots(ctlr, id, count, slot);
+- default:
+- return -EINVAL;
+- }
+-
+-}
+-EXPORT_SYMBOL(edma_alloc_cont_slots);
+-
+-/**
+- * edma_free_cont_slots - deallocate DMA parameter RAM slots
+- * @slot: first parameter RAM of a set of parameter RAM slots to be freed
+- * @count: the number of contiguous parameter RAM slots to be freed
+- *
+- * This deallocates the parameter RAM slots allocated by
+- * edma_alloc_cont_slots.
+- * Callers/applications need to keep track of sets of contiguous
+- * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
+- * API.
+- * Callers are responsible for ensuring the slots are inactive, and will
+- * not be activated.
+- */
+-int edma_free_cont_slots(unsigned slot, int count)
+-{
+- unsigned ctlr, slot_to_free;
+- int i;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_channels ||
+- slot >= edma_cc[ctlr]->num_slots ||
+- count < 1)
+- return -EINVAL;
+-
+- for (i = slot; i < slot + count; ++i) {
+- ctlr = EDMA_CTLR(i);
+- slot_to_free = EDMA_CHAN_SLOT(i);
+-
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
+- &dummy_paramset, PARM_SIZE);
+- clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
+- }
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(edma_free_cont_slots);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Parameter RAM operations (i) -- read/write partial slots */
+-
+-/**
+- * edma_set_src - set initial DMA source address in parameter RAM slot
+- * @slot: parameter RAM slot being configured
+- * @src_port: physical address of source (memory, controller FIFO, etc)
+- * @addressMode: INCR, except in very rare cases
+- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+- * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+- *
+- * Note that the source address is modified during the DMA transfer
+- * according to edma_set_src_index().
+- */
+-void edma_set_src(unsigned slot, dma_addr_t src_port,
+- enum address_mode mode, enum fifo_width width)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+-
+- if (mode) {
+- /* set SAM and program FWID */
+- i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
+- } else {
+- /* clear SAM */
+- i &= ~SAM;
+- }
+- edma_parm_write(ctlr, PARM_OPT, slot, i);
+-
+- /* set the source port address
+- in source register of param structure */
+- edma_parm_write(ctlr, PARM_SRC, slot, src_port);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_src);
+-
+-/**
+- * edma_set_dest - set initial DMA destination address in parameter RAM slot
+- * @slot: parameter RAM slot being configured
+- * @dest_port: physical address of destination (memory, controller FIFO, etc)
+- * @addressMode: INCR, except in very rare cases
+- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+- * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+- *
+- * Note that the destination address is modified during the DMA transfer
+- * according to edma_set_dest_index().
+- */
+-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+- enum address_mode mode, enum fifo_width width)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+-
+- if (mode) {
+- /* set DAM and program FWID */
+- i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
+- } else {
+- /* clear DAM */
+- i &= ~DAM;
+- }
+- edma_parm_write(ctlr, PARM_OPT, slot, i);
+- /* set the destination port address
+- in dest register of param structure */
+- edma_parm_write(ctlr, PARM_DST, slot, dest_port);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_dest);
+-
+-/**
+- * edma_get_position - returns the current transfer points
+- * @slot: parameter RAM slot being examined
+- * @src: pointer to source port position
+- * @dst: pointer to destination port position
+- *
+- * Returns current source and destination addresses for a particular
+- * parameter RAM slot. Its channel should not be active when this is called.
+- */
+-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
+-{
+- struct edmacc_param temp;
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
+- if (src != NULL)
+- *src = temp.src;
+- if (dst != NULL)
+- *dst = temp.dst;
+-}
+-EXPORT_SYMBOL(edma_get_position);
+-
+-/**
+- * edma_set_src_index - configure DMA source address indexing
+- * @slot: parameter RAM slot being configured
+- * @src_bidx: byte offset between source arrays in a frame
+- * @src_cidx: byte offset between source frames in a block
+- *
+- * Offsets are specified to support either contiguous or discontiguous
+- * memory transfers, or repeated access to a hardware register, as needed.
+- * When accessing hardware registers, both offsets are normally zero.
+- */
+-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+- 0xffff0000, src_bidx);
+- edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+- 0xffff0000, src_cidx);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_src_index);
+-
+-/**
+- * edma_set_dest_index - configure DMA destination address indexing
+- * @slot: parameter RAM slot being configured
+- * @dest_bidx: byte offset between destination arrays in a frame
+- * @dest_cidx: byte offset between destination frames in a block
+- *
+- * Offsets are specified to support either contiguous or discontiguous
+- * memory transfers, or repeated access to a hardware register, as needed.
+- * When accessing hardware registers, both offsets are normally zero.
+- */
+-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+- 0x0000ffff, dest_bidx << 16);
+- edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+- 0x0000ffff, dest_cidx << 16);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_dest_index);
+-
+-/**
+- * edma_set_transfer_params - configure DMA transfer parameters
+- * @slot: parameter RAM slot being configured
+- * @acnt: how many bytes per array (at least one)
+- * @bcnt: how many arrays per frame (at least one)
+- * @ccnt: how many frames per block (at least one)
+- * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+- * the value to reload into bcnt when it decrements to zero
+- * @sync_mode: ASYNC or ABSYNC
+- *
+- * See the EDMA3 documentation to understand how to configure and link
+- * transfers using the fields in PaRAM slots. If you are not doing it
+- * all at once with edma_write_slot(), you will use this routine
+- * plus two calls each for source and destination, setting the initial
+- * address and saying how to index that address.
+- *
+- * An example of an A-Synchronized transfer is a serial link using a
+- * single word shift register. In that case, @acnt would be equal to
+- * that word size; the serial controller issues a DMA synchronization
+- * event to transfer each word, and memory access by the DMA transfer
+- * controller will be word-at-a-time.
+- *
+- * An example of an AB-Synchronized transfer is a device using a FIFO.
+- * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+- * The controller with the FIFO issues DMA synchronization events when
+- * the FIFO threshold is reached, and the DMA transfer controller will
+- * transfer one frame to (or from) the FIFO. It will probably use
+- * efficient burst modes to access memory.
+- */
+-void edma_set_transfer_params(unsigned slot,
+- u16 acnt, u16 bcnt, u16 ccnt,
+- u16 bcnt_rld, enum sync_dimension sync_mode)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot < edma_cc[ctlr]->num_slots) {
+- edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
+- 0x0000ffff, bcnt_rld << 16);
+- if (sync_mode == ASYNC)
+- edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
+- else
+- edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
+- /* Set the acount, bcount, ccount registers */
+- edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
+- edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
+- }
+-}
+-EXPORT_SYMBOL(edma_set_transfer_params);
+-
+-/**
+- * edma_link - link one parameter RAM slot to another
+- * @from: parameter RAM slot originating the link
+- * @to: parameter RAM slot which is the link target
+- *
+- * The originating slot should not be part of any active DMA transfer.
+- */
+-void edma_link(unsigned from, unsigned to)
+-{
+- unsigned ctlr_from, ctlr_to;
+-
+- ctlr_from = EDMA_CTLR(from);
+- from = EDMA_CHAN_SLOT(from);
+- ctlr_to = EDMA_CTLR(to);
+- to = EDMA_CHAN_SLOT(to);
+-
+- if (from >= edma_cc[ctlr_from]->num_slots)
+- return;
+- if (to >= edma_cc[ctlr_to]->num_slots)
+- return;
+- edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
+- PARM_OFFSET(to));
+-}
+-EXPORT_SYMBOL(edma_link);
+-
+-/**
+- * edma_unlink - cut link from one parameter RAM slot
+- * @from: parameter RAM slot originating the link
+- *
+- * The originating slot should not be part of any active DMA transfer.
+- * Its link is set to 0xffff.
+- */
+-void edma_unlink(unsigned from)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(from);
+- from = EDMA_CHAN_SLOT(from);
+-
+- if (from >= edma_cc[ctlr]->num_slots)
+- return;
+- edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
+-}
+-EXPORT_SYMBOL(edma_unlink);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Parameter RAM operations (ii) -- read/write whole parameter sets */
+-
+-/**
+- * edma_write_slot - write parameter RAM data for slot
+- * @slot: number of parameter RAM slot being modified
+- * @param: data to be written into parameter RAM slot
+- *
+- * Use this to assign all parameters of a transfer at once. This
+- * allows more efficient setup of transfers than issuing multiple
+- * calls to set up those parameters in small pieces, and provides
+- * complete control over all transfer options.
+- */
+-void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot >= edma_cc[ctlr]->num_slots)
+- return;
+- memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
+- PARM_SIZE);
+-}
+-EXPORT_SYMBOL(edma_write_slot);
+-
+-/**
+- * edma_read_slot - read parameter RAM data from slot
+- * @slot: number of parameter RAM slot being copied
+- * @param: where to store copy of parameter RAM data
+- *
+- * Use this to read data from a parameter RAM slot, perhaps to
+- * save them as a template for later reuse.
+- */
+-void edma_read_slot(unsigned slot, struct edmacc_param *param)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(slot);
+- slot = EDMA_CHAN_SLOT(slot);
+-
+- if (slot >= edma_cc[ctlr]->num_slots)
+- return;
+- memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+- PARM_SIZE);
+-}
+-EXPORT_SYMBOL(edma_read_slot);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-/* Various EDMA channel control operations */
+-
+-/**
+- * edma_pause - pause dma on a channel
+- * @channel: on which edma_start() has been called
+- *
+- * This temporarily disables EDMA hardware events on the specified channel,
+- * preventing them from triggering new transfers on its behalf
+- */
+-void edma_pause(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
+- }
+-}
+-EXPORT_SYMBOL(edma_pause);
+-
+-/**
+- * edma_resume - resumes dma on a paused channel
+- * @channel: on which edma_pause() has been called
+- *
+- * This re-enables EDMA hardware events on the specified channel.
+- */
+-void edma_resume(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
+- }
+-}
+-EXPORT_SYMBOL(edma_resume);
+-
+-/**
+- * edma_start - start dma on a channel
+- * @channel: channel being activated
+- *
+- * Channels with event associations will be triggered by their hardware
+- * events, and channels without such associations will be triggered by
+- * software. (At this writing there is no interface for using software
+- * triggers except with channels that don't support hardware triggers.)
+- *
+- * Returns zero on success, else negative errno.
+- */
+-int edma_start(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = channel >> 5;
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- /* EDMA channels without event association */
+- if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
+- pr_debug("EDMA: ESR%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_ESR, j));
+- edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
+- return 0;
+- }
+-
+- /* EDMA channel with event association */
+- pr_debug("EDMA: ER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_ER, j));
+- /* Clear any pending event or error */
+- edma_write_array(ctlr, EDMA_ECR, j, mask);
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
+- pr_debug("EDMA: EER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_EER, j));
+- return 0;
+- }
+-
+- return -EINVAL;
+-}
+-EXPORT_SYMBOL(edma_start);
+-
+-/**
+- * edma_stop - stops dma on the channel passed
+- * @channel: channel being deactivated
+- *
+- * When @lch is a channel, any active transfer is paused and
+- * all pending hardware events are cleared. The current transfer
+- * may not be resumed, and the channel's Parameter RAM should be
+- * reinitialized before being reused.
+- */
+-void edma_stop(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = channel >> 5;
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+-
+- pr_debug("EDMA: EER%d %08x\n", j,
+- edma_shadow0_read_array(ctlr, SH_EER, j));
+-
+- /* REVISIT: consider guarding against inappropriate event
+- * chaining by overwriting with dummy_paramset.
+- */
+- }
+-}
+-EXPORT_SYMBOL(edma_stop);
+-
+-/******************************************************************************
+- *
+- * It cleans ParamEntry qand bring back EDMA to initial state if media has
+- * been removed before EDMA has finished.It is usedful for removable media.
+- * Arguments:
+- * ch_no - channel no
+- *
+- * Return: zero on success, or corresponding error no on failure
+- *
+- * FIXME this should not be needed ... edma_stop() should suffice.
+- *
+- *****************************************************************************/
+-
+-void edma_clean_channel(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel < edma_cc[ctlr]->num_channels) {
+- int j = (channel >> 5);
+- unsigned int mask = BIT(channel & 0x1f);
+-
+- pr_debug("EDMA: EMR%d %08x\n", j,
+- edma_read_array(ctlr, EDMA_EMR, j));
+- edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+- /* Clear the corresponding EMR bits */
+- edma_write_array(ctlr, EDMA_EMCR, j, mask);
+- /* Clear any SER */
+- edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+- edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
+- }
+-}
+-EXPORT_SYMBOL(edma_clean_channel);
+-
+-/*
+- * edma_clear_event - clear an outstanding event on the DMA channel
+- * Arguments:
+- * channel - channel number
+- */
+-void edma_clear_event(unsigned channel)
+-{
+- unsigned ctlr;
+-
+- ctlr = EDMA_CTLR(channel);
+- channel = EDMA_CHAN_SLOT(channel);
+-
+- if (channel >= edma_cc[ctlr]->num_channels)
+- return;
+- if (channel < 32)
+- edma_write(ctlr, EDMA_ECR, BIT(channel));
+- else
+- edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
+-}
+-EXPORT_SYMBOL(edma_clear_event);
+-
+-/*-----------------------------------------------------------------------*/
+-
+-static int __init edma_probe(struct platform_device *pdev)
+-{
+- struct edma_soc_info **info = pdev->dev.platform_data;
+- const s8 (*queue_priority_mapping)[2];
+- const s8 (*queue_tc_mapping)[2];
+- int i, j, off, ln, found = 0;
+- int status = -1;
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
+- int irq[EDMA_MAX_CC] = {0, 0};
+- int err_irq[EDMA_MAX_CC] = {0, 0};
+- struct resource *r[EDMA_MAX_CC] = {NULL};
+- resource_size_t len[EDMA_MAX_CC];
+- char res_name[10];
+- char irq_name[10];
+-
+- if (!info)
+- return -ENODEV;
+-
+- for (j = 0; j < EDMA_MAX_CC; j++) {
+- sprintf(res_name, "edma_cc%d", j);
+- r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+- res_name);
+- if (!r[j] || !info[j]) {
+- if (found)
+- break;
+- else
+- return -ENODEV;
+- } else {
+- found = 1;
+- }
+-
+- len[j] = resource_size(r[j]);
+-
+- r[j] = request_mem_region(r[j]->start, len[j],
+- dev_name(&pdev->dev));
+- if (!r[j]) {
+- status = -EBUSY;
+- goto fail1;
+- }
+-
+- edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
+- if (!edmacc_regs_base[j]) {
+- status = -EBUSY;
+- goto fail1;
+- }
+-
+- edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
+- if (!edma_cc[j]) {
+- status = -ENOMEM;
+- goto fail1;
+- }
+-
+- edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
+- EDMA_MAX_DMACH);
+- edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
+- EDMA_MAX_PARAMENTRY);
+- edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
+- EDMA_MAX_CC);
+-
+- edma_cc[j]->default_queue = info[j]->default_queue;
+-
+- dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
+- edmacc_regs_base[j]);
+-
+- for (i = 0; i < edma_cc[j]->num_slots; i++)
+- memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
+- &dummy_paramset, PARM_SIZE);
+-
+- /* Mark all channels as unused */
+- memset(edma_cc[j]->edma_unused, 0xff,
+- sizeof(edma_cc[j]->edma_unused));
+-
+- if (info[j]->rsv) {
+-
+- /* Clear the reserved channels in unused list */
+- rsv_chans = info[j]->rsv->rsv_chans;
+- if (rsv_chans) {
+- for (i = 0; rsv_chans[i][0] != -1; i++) {
+- off = rsv_chans[i][0];
+- ln = rsv_chans[i][1];
+- clear_bits(off, ln,
+- edma_cc[j]->edma_unused);
+- }
+- }
+-
+- /* Set the reserved slots in inuse list */
+- rsv_slots = info[j]->rsv->rsv_slots;
+- if (rsv_slots) {
+- for (i = 0; rsv_slots[i][0] != -1; i++) {
+- off = rsv_slots[i][0];
+- ln = rsv_slots[i][1];
+- set_bits(off, ln,
+- edma_cc[j]->edma_inuse);
+- }
+- }
+- }
+-
+- sprintf(irq_name, "edma%d", j);
+- irq[j] = platform_get_irq_byname(pdev, irq_name);
+- edma_cc[j]->irq_res_start = irq[j];
+- status = request_irq(irq[j], dma_irq_handler, 0, "edma",
+- &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- irq[j], status);
+- goto fail;
+- }
+-
+- sprintf(irq_name, "edma%d_err", j);
+- err_irq[j] = platform_get_irq_byname(pdev, irq_name);
+- edma_cc[j]->irq_res_end = err_irq[j];
+- status = request_irq(err_irq[j], dma_ccerr_handler, 0,
+- "edma_error", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- err_irq[j], status);
+- goto fail;
+- }
+-
+- for (i = 0; i < edma_cc[j]->num_channels; i++)
+- map_dmach_queue(j, i, info[j]->default_queue);
+-
+- queue_tc_mapping = info[j]->queue_tc_mapping;
+- queue_priority_mapping = info[j]->queue_priority_mapping;
+-
+- /* Event queue to TC mapping */
+- for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+- map_queue_tc(j, queue_tc_mapping[i][0],
+- queue_tc_mapping[i][1]);
+-
+- /* Event queue priority mapping */
+- for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+- assign_priority_to_queue(j,
+- queue_priority_mapping[i][0],
+- queue_priority_mapping[i][1]);
+-
+- /* Map the channel to param entry if channel mapping logic
+- * exist
+- */
+- if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
+- map_dmach_param(j);
+-
+- for (i = 0; i < info[j]->n_region; i++) {
+- edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
+- edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
+- edma_write_array(j, EDMA_QRAE, i, 0x0);
+- }
+- arch_num_cc++;
+- }
+-
+- if (tc_errs_handled) {
+- status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+- "edma_tc0", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- IRQ_TCERRINT0, status);
+- return status;
+- }
+- status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+- "edma_tc1", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+- IRQ_TCERRINT, status);
+- return status;
+- }
+- }
+-
+- return 0;
+-
+-fail:
+- for (i = 0; i < EDMA_MAX_CC; i++) {
+- if (err_irq[i])
+- free_irq(err_irq[i], &pdev->dev);
+- if (irq[i])
+- free_irq(irq[i], &pdev->dev);
+- }
+-fail1:
+- for (i = 0; i < EDMA_MAX_CC; i++) {
+- if (r[i])
+- release_mem_region(r[i]->start, len[i]);
+- if (edmacc_regs_base[i])
+- iounmap(edmacc_regs_base[i]);
+- kfree(edma_cc[i]);
+- }
+- return status;
+-}
+-
+-
+-static struct platform_driver edma_driver = {
+- .driver.name = "edma",
+-};
+-
+-static int __init edma_init(void)
+-{
+- return platform_driver_probe(&edma_driver, edma_probe);
+-}
+-arch_initcall(edma_init);
+-
+diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
+index aaccdc4..4380691 100644
+--- a/arch/arm/mach-davinci/include/mach/da8xx.h
++++ b/arch/arm/mach-davinci/include/mach/da8xx.h
+@@ -20,8 +20,8 @@
+ #include <linux/videodev2.h>
+
+ #include <mach/serial.h>
+-#include <mach/edma.h>
+ #include <mach/pm.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/i2c-davinci.h>
+ #include <linux/platform_data/mmc-davinci.h>
+ #include <linux/platform_data/usb-davinci.h>
+diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
+deleted file mode 100644
+index 7e84c90..0000000
+--- a/arch/arm/mach-davinci/include/mach/edma.h
++++ /dev/null
+@@ -1,267 +0,0 @@
+-/*
+- * TI DAVINCI dma definitions
+- *
+- * Copyright (C) 2006-2009 Texas Instruments.
+- *
+- * This program is free software; you can redistribute it and/or modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the License, or (at your
+- * option) any later version.
+- *
+- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- *
+- * You should have received a copy of the GNU General Public License along
+- * with this program; if not, write to the Free Software Foundation, Inc.,
+- * 675 Mass Ave, Cambridge, MA 02139, USA.
+- *
+- */
+-
+-/*
+- * This EDMA3 programming framework exposes two basic kinds of resource:
+- *
+- * Channel Triggers transfers, usually from a hardware event but
+- * also manually or by "chaining" from DMA completions.
+- * Each channel is coupled to a Parameter RAM (PaRAM) slot.
+- *
+- * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
+- * "set"), source and destination addresses, a link to a
+- * next PaRAM slot (if any), options for the transfer, and
+- * instructions for updating those addresses. There are
+- * more than twice as many slots as event channels.
+- *
+- * Each PaRAM set describes a sequence of transfers, either for one large
+- * buffer or for several discontiguous smaller buffers. An EDMA transfer
+- * is driven only from a channel, which performs the transfers specified
+- * in its PaRAM slot until there are no more transfers. When that last
+- * transfer completes, the "link" field may be used to reload the channel's
+- * PaRAM slot with a new transfer descriptor.
+- *
+- * The EDMA Channel Controller (CC) maps requests from channels into physical
+- * Transfer Controller (TC) requests when the channel triggers (by hardware
+- * or software events, or by chaining). The two physical DMA channels provided
+- * by the TCs are thus shared by many logical channels.
+- *
+- * DaVinci hardware also has a "QDMA" mechanism which is not currently
+- * supported through this interface. (DSP firmware uses it though.)
+- */
+-
+-#ifndef EDMA_H_
+-#define EDMA_H_
+-
+-/* PaRAM slots are laid out like this */
+-struct edmacc_param {
+- unsigned int opt;
+- unsigned int src;
+- unsigned int a_b_cnt;
+- unsigned int dst;
+- unsigned int src_dst_bidx;
+- unsigned int link_bcntrld;
+- unsigned int src_dst_cidx;
+- unsigned int ccnt;
+-};
+-
+-#define CCINT0_INTERRUPT 16
+-#define CCERRINT_INTERRUPT 17
+-#define TCERRINT0_INTERRUPT 18
+-#define TCERRINT1_INTERRUPT 19
+-
+-/* fields in edmacc_param.opt */
+-#define SAM BIT(0)
+-#define DAM BIT(1)
+-#define SYNCDIM BIT(2)
+-#define STATIC BIT(3)
+-#define EDMA_FWID (0x07 << 8)
+-#define TCCMODE BIT(11)
+-#define EDMA_TCC(t) ((t) << 12)
+-#define TCINTEN BIT(20)
+-#define ITCINTEN BIT(21)
+-#define TCCHEN BIT(22)
+-#define ITCCHEN BIT(23)
+-
+-#define TRWORD (0x7<<2)
+-#define PAENTRY (0x1ff<<5)
+-
+-/* Drivers should avoid using these symbolic names for dm644x
+- * channels, and use platform_device IORESOURCE_DMA resources
+- * instead. (Other DaVinci chips have different peripherals
+- * and thus have different DMA channel mappings.)
+- */
+-#define DAVINCI_DMA_MCBSP_TX 2
+-#define DAVINCI_DMA_MCBSP_RX 3
+-#define DAVINCI_DMA_VPSS_HIST 4
+-#define DAVINCI_DMA_VPSS_H3A 5
+-#define DAVINCI_DMA_VPSS_PRVU 6
+-#define DAVINCI_DMA_VPSS_RSZ 7
+-#define DAVINCI_DMA_IMCOP_IMXINT 8
+-#define DAVINCI_DMA_IMCOP_VLCDINT 9
+-#define DAVINCI_DMA_IMCO_PASQINT 10
+-#define DAVINCI_DMA_IMCOP_DSQINT 11
+-#define DAVINCI_DMA_SPI_SPIX 16
+-#define DAVINCI_DMA_SPI_SPIR 17
+-#define DAVINCI_DMA_UART0_URXEVT0 18
+-#define DAVINCI_DMA_UART0_UTXEVT0 19
+-#define DAVINCI_DMA_UART1_URXEVT1 20
+-#define DAVINCI_DMA_UART1_UTXEVT1 21
+-#define DAVINCI_DMA_UART2_URXEVT2 22
+-#define DAVINCI_DMA_UART2_UTXEVT2 23
+-#define DAVINCI_DMA_MEMSTK_MSEVT 24
+-#define DAVINCI_DMA_MMCRXEVT 26
+-#define DAVINCI_DMA_MMCTXEVT 27
+-#define DAVINCI_DMA_I2C_ICREVT 28
+-#define DAVINCI_DMA_I2C_ICXEVT 29
+-#define DAVINCI_DMA_GPIO_GPINT0 32
+-#define DAVINCI_DMA_GPIO_GPINT1 33
+-#define DAVINCI_DMA_GPIO_GPINT2 34
+-#define DAVINCI_DMA_GPIO_GPINT3 35
+-#define DAVINCI_DMA_GPIO_GPINT4 36
+-#define DAVINCI_DMA_GPIO_GPINT5 37
+-#define DAVINCI_DMA_GPIO_GPINT6 38
+-#define DAVINCI_DMA_GPIO_GPINT7 39
+-#define DAVINCI_DMA_GPIO_GPBNKINT0 40
+-#define DAVINCI_DMA_GPIO_GPBNKINT1 41
+-#define DAVINCI_DMA_GPIO_GPBNKINT2 42
+-#define DAVINCI_DMA_GPIO_GPBNKINT3 43
+-#define DAVINCI_DMA_GPIO_GPBNKINT4 44
+-#define DAVINCI_DMA_TIMER0_TINT0 48
+-#define DAVINCI_DMA_TIMER1_TINT1 49
+-#define DAVINCI_DMA_TIMER2_TINT2 50
+-#define DAVINCI_DMA_TIMER3_TINT3 51
+-#define DAVINCI_DMA_PWM0 52
+-#define DAVINCI_DMA_PWM1 53
+-#define DAVINCI_DMA_PWM2 54
+-
+-/* DA830 specific EDMA3 information */
+-#define EDMA_DA830_NUM_DMACH 32
+-#define EDMA_DA830_NUM_TCC 32
+-#define EDMA_DA830_NUM_PARAMENTRY 128
+-#define EDMA_DA830_NUM_EVQUE 2
+-#define EDMA_DA830_NUM_TC 2
+-#define EDMA_DA830_CHMAP_EXIST 0
+-#define EDMA_DA830_NUM_REGIONS 4
+-#define DA830_DMACH2EVENT_MAP0 0x000FC03Fu
+-#define DA830_DMACH2EVENT_MAP1 0x00000000u
+-#define DA830_EDMA_ARM_OWN 0x30FFCCFFu
+-
+-/*ch_status paramater of callback function possible values*/
+-#define DMA_COMPLETE 1
+-#define DMA_CC_ERROR 2
+-#define DMA_TC1_ERROR 3
+-#define DMA_TC2_ERROR 4
+-
+-enum address_mode {
+- INCR = 0,
+- FIFO = 1
+-};
+-
+-enum fifo_width {
+- W8BIT = 0,
+- W16BIT = 1,
+- W32BIT = 2,
+- W64BIT = 3,
+- W128BIT = 4,
+- W256BIT = 5
+-};
+-
+-enum dma_event_q {
+- EVENTQ_0 = 0,
+- EVENTQ_1 = 1,
+- EVENTQ_2 = 2,
+- EVENTQ_3 = 3,
+- EVENTQ_DEFAULT = -1
+-};
+-
+-enum sync_dimension {
+- ASYNC = 0,
+- ABSYNC = 1
+-};
+-
+-#define EDMA_CTLR_CHAN(ctlr, chan) (((ctlr) << 16) | (chan))
+-#define EDMA_CTLR(i) ((i) >> 16)
+-#define EDMA_CHAN_SLOT(i) ((i) & 0xffff)
+-
+-#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
+-#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
+-#define EDMA_CONT_PARAMS_ANY 1001
+-#define EDMA_CONT_PARAMS_FIXED_EXACT 1002
+-#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
+-
+-#define EDMA_MAX_CC 2
+-
+-/* alloc/free DMA channels and their dedicated parameter RAM slots */
+-int edma_alloc_channel(int channel,
+- void (*callback)(unsigned channel, u16 ch_status, void *data),
+- void *data, enum dma_event_q);
+-void edma_free_channel(unsigned channel);
+-
+-/* alloc/free parameter RAM slots */
+-int edma_alloc_slot(unsigned ctlr, int slot);
+-void edma_free_slot(unsigned slot);
+-
+-/* alloc/free a set of contiguous parameter RAM slots */
+-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
+-int edma_free_cont_slots(unsigned slot, int count);
+-
+-/* calls that operate on part of a parameter RAM slot */
+-void edma_set_src(unsigned slot, dma_addr_t src_port,
+- enum address_mode mode, enum fifo_width);
+-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+- enum address_mode mode, enum fifo_width);
+-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
+-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
+-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
+-void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
+- u16 bcnt_rld, enum sync_dimension sync_mode);
+-void edma_link(unsigned from, unsigned to);
+-void edma_unlink(unsigned from);
+-
+-/* calls that operate on an entire parameter RAM slot */
+-void edma_write_slot(unsigned slot, const struct edmacc_param *params);
+-void edma_read_slot(unsigned slot, struct edmacc_param *params);
+-
+-/* channel control operations */
+-int edma_start(unsigned channel);
+-void edma_stop(unsigned channel);
+-void edma_clean_channel(unsigned channel);
+-void edma_clear_event(unsigned channel);
+-void edma_pause(unsigned channel);
+-void edma_resume(unsigned channel);
+-
+-struct edma_rsv_info {
+-
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
+-};
+-
+-/* platform_data for EDMA driver */
+-struct edma_soc_info {
+-
+- /* how many dma resources of each type */
+- unsigned n_channel;
+- unsigned n_region;
+- unsigned n_slot;
+- unsigned n_tc;
+- unsigned n_cc;
+- /*
+- * Default queue is expected to be a low-priority queue.
+- * This way, long transfers on the default queue started
+- * by the codec engine will not cause audio defects.
+- */
+- enum dma_event_q default_queue;
+-
+- /* Resource reservation for other cores */
+- struct edma_rsv_info *rsv;
+-
+- const s8 (*queue_tc_mapping)[2];
+- const s8 (*queue_priority_mapping)[2];
+-};
+-
+-#endif
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index 82fcb20..74ce024 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -29,6 +29,7 @@ config ARCH_OMAP2PLUS
+ select PINCTRL
+ select PROC_DEVICETREE if PROC_FS
+ select SPARSE_IRQ
++ select TI_PRIV_EDMA
+ select USE_OF
+ help
+ "Systems based on OMAP2, OMAP3, OMAP4 or OMAP5"
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index fdcf079..47ba7bf 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -24,7 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ #include "dmaengine.h"
+ #include "virt-dma.h"
+diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
+index 2063677..f5d46ea 100644
+--- a/drivers/mmc/host/davinci_mmc.c
++++ b/drivers/mmc/host/davinci_mmc.c
+@@ -35,6 +35,7 @@
+ #include <linux/edma.h>
+ #include <linux/mmc/mmc.h>
+
++#include <linux/platform_data/edma.h>
+ #include <linux/platform_data/mmc-davinci.h>
+
+ /*
+diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h
+index 0ab6132..7dd6524 100644
+--- a/include/linux/mfd/davinci_voicecodec.h
++++ b/include/linux/mfd/davinci_voicecodec.h
+@@ -26,8 +26,7 @@
+ #include <linux/kernel.h>
+ #include <linux/platform_device.h>
+ #include <linux/mfd/core.h>
+-
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ /*
+ * Register values.
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+new file mode 100644
+index 0000000..7396f0b3
+--- /dev/null
++++ b/include/linux/platform_data/edma.h
+@@ -0,0 +1,198 @@
++/*
++ * TI DAVINCI dma definitions
++ *
++ * Copyright (C) 2006-2009 Texas Instruments.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This EDMA3 programming framework exposes two basic kinds of resource:
++ *
++ * Channel Triggers transfers, usually from a hardware event but
++ * also manually or by "chaining" from DMA completions.
++ * Each channel is coupled to a Parameter RAM (PaRAM) slot.
++ *
++ * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
++ * "set"), source and destination addresses, a link to a
++ * next PaRAM slot (if any), options for the transfer, and
++ * instructions for updating those addresses. There are
++ * more than twice as many slots as event channels.
++ *
++ * Each PaRAM set describes a sequence of transfers, either for one large
++ * buffer or for several discontiguous smaller buffers. An EDMA transfer
++ * is driven only from a channel, which performs the transfers specified
++ * in its PaRAM slot until there are no more transfers. When that last
++ * transfer completes, the "link" field may be used to reload the channel's
++ * PaRAM slot with a new transfer descriptor.
++ *
++ * The EDMA Channel Controller (CC) maps requests from channels into physical
++ * Transfer Controller (TC) requests when the channel triggers (by hardware
++ * or software events, or by chaining). The two physical DMA channels provided
++ * by the TCs are thus shared by many logical channels.
++ *
++ * DaVinci hardware also has a "QDMA" mechanism which is not currently
++ * supported through this interface. (DSP firmware uses it though.)
++ */
++
++#ifndef EDMA_H_
++#define EDMA_H_
++
++/* PaRAM slots are laid out like this */
++struct edmacc_param {
++ unsigned int opt;
++ unsigned int src;
++ unsigned int a_b_cnt;
++ unsigned int dst;
++ unsigned int src_dst_bidx;
++ unsigned int link_bcntrld;
++ unsigned int src_dst_cidx;
++ unsigned int ccnt;
++};
++
++/* fields in edmacc_param.opt */
++#define SAM BIT(0)
++#define DAM BIT(1)
++#define SYNCDIM BIT(2)
++#define STATIC BIT(3)
++#define EDMA_FWID (0x07 << 8)
++#define TCCMODE BIT(11)
++#define EDMA_TCC(t) ((t) << 12)
++#define TCINTEN BIT(20)
++#define ITCINTEN BIT(21)
++#define TCCHEN BIT(22)
++#define ITCCHEN BIT(23)
++
++/*ch_status paramater of callback function possible values*/
++#define DMA_COMPLETE 1
++#define DMA_CC_ERROR 2
++#define DMA_TC1_ERROR 3
++#define DMA_TC2_ERROR 4
++
++enum address_mode {
++ INCR = 0,
++ FIFO = 1
++};
++
++enum fifo_width {
++ W8BIT = 0,
++ W16BIT = 1,
++ W32BIT = 2,
++ W64BIT = 3,
++ W128BIT = 4,
++ W256BIT = 5
++};
++
++enum dma_event_q {
++ EVENTQ_0 = 0,
++ EVENTQ_1 = 1,
++ EVENTQ_2 = 2,
++ EVENTQ_3 = 3,
++ EVENTQ_DEFAULT = -1
++};
++
++enum sync_dimension {
++ ASYNC = 0,
++ ABSYNC = 1
++};
++
++#define EDMA_CTLR_CHAN(ctlr, chan) (((ctlr) << 16) | (chan))
++#define EDMA_CTLR(i) ((i) >> 16)
++#define EDMA_CHAN_SLOT(i) ((i) & 0xffff)
++
++#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
++#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
++#define EDMA_CONT_PARAMS_ANY 1001
++#define EDMA_CONT_PARAMS_FIXED_EXACT 1002
++#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
++
++#define EDMA_MAX_CC 2
++
++/* alloc/free DMA channels and their dedicated parameter RAM slots */
++int edma_alloc_channel(int channel,
++ void (*callback)(unsigned channel, u16 ch_status, void *data),
++ void *data, enum dma_event_q);
++void edma_free_channel(unsigned channel);
++
++/* alloc/free parameter RAM slots */
++int edma_alloc_slot(unsigned ctlr, int slot);
++void edma_free_slot(unsigned slot);
++
++/* alloc/free a set of contiguous parameter RAM slots */
++int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
++int edma_free_cont_slots(unsigned slot, int count);
++
++/* calls that operate on part of a parameter RAM slot */
++void edma_set_src(unsigned slot, dma_addr_t src_port,
++ enum address_mode mode, enum fifo_width);
++void edma_set_dest(unsigned slot, dma_addr_t dest_port,
++ enum address_mode mode, enum fifo_width);
++void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
++void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
++void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
++void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
++ u16 bcnt_rld, enum sync_dimension sync_mode);
++void edma_link(unsigned from, unsigned to);
++void edma_unlink(unsigned from);
++
++/* calls that operate on an entire parameter RAM slot */
++void edma_write_slot(unsigned slot, const struct edmacc_param *params);
++void edma_read_slot(unsigned slot, struct edmacc_param *params);
++
++/* channel control operations */
++int edma_start(unsigned channel);
++void edma_stop(unsigned channel);
++void edma_clean_channel(unsigned channel);
++void edma_clear_event(unsigned channel);
++void edma_pause(unsigned channel);
++void edma_resume(unsigned channel);
++
++struct edma_rsv_info {
++
++ const s16 (*rsv_chans)[2];
++ const s16 (*rsv_slots)[2];
++};
++
++/* platform_data for EDMA driver */
++struct edma_soc_info {
++
++ /* how many dma resources of each type */
++ unsigned n_channel;
++ unsigned n_region;
++ unsigned n_slot;
++ unsigned n_tc;
++ unsigned n_cc;
++ /*
++ * Default queue is expected to be a low-priority queue.
++ * This way, long transfers on the default queue started
++ * by the codec engine will not cause audio defects.
++ */
++ enum dma_event_q default_queue;
++
++ /* Resource reservation for other cores */
++ struct edma_rsv_info *rsv;
++
++ const s8 (*queue_tc_mapping)[2];
++ const s8 (*queue_priority_mapping)[2];
++};
++
++#endif
+diff --git a/include/linux/platform_data/spi-davinci.h b/include/linux/platform_data/spi-davinci.h
+index 7af305b..8dc2fa47 100644
+--- a/include/linux/platform_data/spi-davinci.h
++++ b/include/linux/platform_data/spi-davinci.h
+@@ -19,7 +19,7 @@
+ #ifndef __ARCH_ARM_DAVINCI_SPI_H
+ #define __ARCH_ARM_DAVINCI_SPI_H
+
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ #define SPI_INTERN_CS 0xFF
+
+diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
+index 6fac5af..44365d5 100644
+--- a/sound/soc/davinci/davinci-evm.c
++++ b/sound/soc/davinci/davinci-evm.c
+@@ -14,6 +14,7 @@
+ #include <linux/timer.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/i2c.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
+index 93ea3bf..c9d1b7a 100644
+--- a/sound/soc/davinci/davinci-pcm.c
++++ b/sound/soc/davinci/davinci-pcm.c
+@@ -16,6 +16,7 @@
+ #include <linux/slab.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
++#include <linux/platform_data/edma.h>
+
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
+index fc4d01c..deab6c3 100644
+--- a/sound/soc/davinci/davinci-pcm.h
++++ b/sound/soc/davinci/davinci-pcm.h
+@@ -13,7 +13,7 @@
+ #define _DAVINCI_PCM_H
+
+ #include <linux/platform_data/davinci_asp.h>
+-#include <mach/edma.h>
++#include <linux/platform_data/edma.h>
+
+ struct davinci_pcm_dma_params {
+ int channel; /* sync dma channel ID */
+diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
+index 5be65aa..5345e63 100644
+--- a/sound/soc/davinci/davinci-sffsdr.c
++++ b/sound/soc/davinci/davinci-sffsdr.c
+@@ -17,6 +17,7 @@
+ #include <linux/timer.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++#include <linux/platform_data/edma.h>
+ #include <linux/gpio.h>
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+@@ -28,7 +29,6 @@
+ #include <asm/plat-sffsdr/sffsdr-fpga.h>
+ #endif
+
+-#include <mach/edma.h>
+
+ #include "../codecs/pcm3008.h"
+ #include "davinci-pcm.h"
+@@ -123,8 +123,8 @@ static struct resource sffsdr_snd_resources[] = {
+ };
+
+ static struct evm_snd_platform_data sffsdr_snd_data = {
+- .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
+- .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
++ .tx_dma_ch = 2,
++ .rx_dma_ch = 3,
+ };
+
+ static struct platform_device *sffsdr_snd_device;
diff --git a/patches/linux-3.7/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch b/patches/linux-3.7/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
new file mode 100644
index 0000000..05f7b56
--- /dev/null
+++ b/patches/linux-3.7/0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
@@ -0,0 +1,68 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 22 Aug 2012 09:31:49 -0400
+Subject: [PATCH] ARM: edma: remove unused transfer controller handlers
+
+Fix build on OMAP, the irqs are undefined on AM33xx.
+These error interrupt handlers were hardcoded as disabled
+so since they are unused code, simply remove them.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 37 -------------------------------------
+ 1 file changed, 37 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index 4411087..a3d189d 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -494,26 +494,6 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
+ return IRQ_HANDLED;
+ }
+
+-/******************************************************************************
+- *
+- * Transfer controller error interrupt handlers
+- *
+- *****************************************************************************/
+-
+-#define tc_errs_handled false /* disabled as long as they're NOPs */
+-
+-static irqreturn_t dma_tc0err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc0err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t dma_tc1err_handler(int irq, void *data)
+-{
+- dev_dbg(data, "dma_tc1err_handler\n");
+- return IRQ_HANDLED;
+-}
+-
+ static int reserve_contiguous_slots(int ctlr, unsigned int id,
+ unsigned int num_slots,
+ unsigned int start_slot)
+@@ -1538,23 +1518,6 @@ static int __init edma_probe(struct platform_device *pdev)
+ arch_num_cc++;
+ }
+
+- if (tc_errs_handled) {
+- status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+- "edma_tc0", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+- IRQ_TCERRINT0, status);
+- return status;
+- }
+- status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+- "edma_tc1", &pdev->dev);
+- if (status < 0) {
+- dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+- IRQ_TCERRINT, status);
+- return status;
+- }
+- }
+-
+ return 0;
+
+ fail:
diff --git a/patches/linux-3.7/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch b/patches/linux-3.7/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
new file mode 100644
index 0000000..440d17a
--- /dev/null
+++ b/patches/linux-3.7/0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
@@ -0,0 +1,632 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:40:42 -0400
+Subject: [PATCH] ARM: edma: add DT and runtime PM support for AM33XX
+
+Adds support for parsing the TI EDMA DT data into the required
+EDMA private API platform data.
+
+Calls runtime PM API only in the DT case in order to unidle the
+associated hwmods on AM33XX.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 255 +++++++++++++++++++++++++--
+ arch/arm/mach-davinci/board-da830-evm.c | 4 +-
+ arch/arm/mach-davinci/board-da850-evm.c | 8 +-
+ arch/arm/mach-davinci/board-dm646x-evm.c | 4 +-
+ arch/arm/mach-davinci/board-omapl138-hawk.c | 8 +-
+ arch/arm/mach-davinci/devices-da8xx.c | 8 +-
+ arch/arm/mach-davinci/devices-tnetv107x.c | 4 +-
+ arch/arm/mach-davinci/dm355.c | 4 +-
+ arch/arm/mach-davinci/dm365.c | 4 +-
+ arch/arm/mach-davinci/dm644x.c | 4 +-
+ arch/arm/mach-davinci/dm646x.c | 4 +-
+ include/linux/platform_data/edma.h | 8 +-
+ 12 files changed, 272 insertions(+), 43 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index a3d189d..6d2a590 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -24,6 +24,13 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/slab.h>
++#include <linux/edma.h>
++#include <linux/err.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/of_dma.h>
++#include <linux/of_irq.h>
++#include <linux/pm_runtime.h>
+
+ #include <linux/platform_data/edma.h>
+
+@@ -1366,31 +1373,237 @@ void edma_clear_event(unsigned channel)
+ EXPORT_SYMBOL(edma_clear_event);
+
+ /*-----------------------------------------------------------------------*/
++static int edma_of_read_u32_to_s8_array(const struct device_node *np,
++ const char *propname, s8 *out_values,
++ size_t sz)
++{
++ struct property *prop = of_find_property(np, propname, NULL);
++ const __be32 *val;
++
++ if (!prop)
++ return -EINVAL;
++ if (!prop->value)
++ return -ENODATA;
++ if ((sz * sizeof(u32)) > prop->length)
++ return -EOVERFLOW;
++
++ val = prop->value;
++
++ while (sz--)
++ *out_values++ = (s8)(be32_to_cpup(val++) & 0xff);
++
++ /* Terminate it */
++ *out_values++ = -1;
++ *out_values++ = -1;
++
++ return 0;
++}
++
++static int edma_of_read_u32_to_s16_array(const struct device_node *np,
++ const char *propname, s16 *out_values,
++ size_t sz)
++{
++ struct property *prop = of_find_property(np, propname, NULL);
++ const __be32 *val;
++
++ if (!prop)
++ return -EINVAL;
++ if (!prop->value)
++ return -ENODATA;
++ if ((sz * sizeof(u32)) > prop->length)
++ return -EOVERFLOW;
++
++ val = prop->value;
++
++ while (sz--)
++ *out_values++ = (s16)(be32_to_cpup(val++) & 0xffff);
++
++ /* Terminate it */
++ *out_values++ = -1;
++ *out_values++ = -1;
++
++ return 0;
++}
++
++static int edma_of_parse_dt(struct device *dev,
++ struct device_node *node,
++ struct edma_soc_info *pdata)
++{
++ int ret = 0;
++ u32 value;
++ struct property *prop;
++ size_t sz;
++ struct edma_rsv_info *rsv_info;
++ s16 (*rsv_chans)[2], (*rsv_slots)[2];
++ s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
++
++ ret = of_property_read_u32(node, "dma-channels", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_channel = value;
++
++ ret = of_property_read_u32(node, "ti,edma-regions", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_region = value;
++
++ ret = of_property_read_u32(node, "ti,edma-slots", &value);
++ if (ret < 0)
++ return ret;
++ pdata->n_slot = value;
++
++ pdata->n_cc = 1;
++ /* This is unused */
++ pdata->n_tc = 3;
++
++ rsv_info =
++ devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
++ if (!rsv_info)
++ return -ENOMEM;
++ pdata->rsv = rsv_info;
++
++ /* Build the reserved channel/slots arrays */
++ prop = of_find_property(node, "ti,edma-reserved-channels", &sz);
++ if (prop) {
++ rsv_chans = devm_kzalloc(dev,
++ sz/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!rsv_chans)
++ return -ENOMEM;
++ pdata->rsv->rsv_chans = rsv_chans;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-reserved-channels",
++ (s16 *)rsv_chans,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++ }
++
++ prop = of_find_property(node, "ti,edma-reserved-slots", &sz);
++ if (prop) {
++ rsv_slots = devm_kzalloc(dev,
++ sz/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!rsv_slots)
++ return -ENOMEM;
++ pdata->rsv->rsv_slots = rsv_slots;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-reserved-slots",
++ (s16 *)rsv_slots,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++ }
++
++ prop = of_find_property(node, "ti,edma-queue-tc-map", &sz);
++ if (!prop)
++ return -EINVAL;
++
++ queue_tc_map = devm_kzalloc(dev,
++ sz/sizeof(s8) + 2*sizeof(s8),
++ GFP_KERNEL);
++ if (!queue_tc_map)
++ return -ENOMEM;
++ pdata->queue_tc_mapping = queue_tc_map;
++
++ ret = edma_of_read_u32_to_s8_array(node,
++ "ti,edma-queue-tc-map",
++ (s8 *)queue_tc_map,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++
++ prop = of_find_property(node, "ti,edma-queue-priority-map", &sz);
++ if (!prop)
++ return -EINVAL;
++
++ queue_priority_map = devm_kzalloc(dev,
++ sz/sizeof(s8) + 2*sizeof(s8),
++ GFP_KERNEL);
++ if (!queue_priority_map)
++ return -ENOMEM;
++ pdata->queue_priority_mapping = queue_priority_map;
++
++ ret = edma_of_read_u32_to_s8_array(node,
++ "ti,edma-queue-tc-map",
++ (s8 *)queue_priority_map,
++ sz/sizeof(u32));
++ if (ret < 0)
++ return ret;
++
++ ret = of_property_read_u32(node, "ti,edma-default-queue", &value);
++ if (ret < 0)
++ return ret;
++ pdata->default_queue = value;
++
++ return ret;
++}
++
++static struct of_dma_filter_info edma_filter_info = {
++ .filter_fn = edma_filter_fn,
++};
+
+ static int __init edma_probe(struct platform_device *pdev)
+ {
+ struct edma_soc_info **info = pdev->dev.platform_data;
+- const s8 (*queue_priority_mapping)[2];
+- const s8 (*queue_tc_mapping)[2];
++ s8 (*queue_priority_mapping)[2];
++ s8 (*queue_tc_mapping)[2];
+ int i, j, off, ln, found = 0;
+ int status = -1;
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
++ s16 (*rsv_chans)[2];
++ s16 (*rsv_slots)[2];
+ int irq[EDMA_MAX_CC] = {0, 0};
+ int err_irq[EDMA_MAX_CC] = {0, 0};
+- struct resource *r[EDMA_MAX_CC] = {NULL};
++ struct resource *r[EDMA_MAX_CC] = {NULL, NULL};
++ struct resource res[EDMA_MAX_CC];
+ resource_size_t len[EDMA_MAX_CC];
+ char res_name[10];
+ char irq_name[10];
++ struct device_node *node = pdev->dev.of_node;
++ struct device *dev = &pdev->dev;
++ struct edma_soc_info *pdata;
++ int ret;
++
++ if (node) {
++ pdata = devm_kzalloc(dev,
++ sizeof(struct edma_soc_info),
++ GFP_KERNEL);
++ edma_of_parse_dt(dev, node, pdata);
++ info = &pdata;
++ dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
++ of_dma_controller_register(dev->of_node,
++ of_dma_simple_xlate,
++ &edma_filter_info);
++ pm_runtime_enable(dev);
++ ret = pm_runtime_get_sync(dev);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(dev, "pm_runtime_get_sync() failed\n");
++ return ret;
++ }
++ }
+
+ if (!info)
+ return -ENODEV;
+
+ for (j = 0; j < EDMA_MAX_CC; j++) {
+- sprintf(res_name, "edma_cc%d", j);
+- r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
++ if (!info[j]) {
++ if (!found)
++ return -ENODEV;
++ break;
++ }
++ if (node) {
++ ret = of_address_to_resource(node, j, &res[j]);
++ if (!IS_ERR_VALUE(ret))
++ r[j] = &res[j];
++ } else {
++ sprintf(res_name, "edma_cc%d", j);
++ r[j] = platform_get_resource_byname(pdev,
++ IORESOURCE_MEM,
+ res_name);
+- if (!r[j] || !info[j]) {
++ }
++ if (!r[j]) {
+ if (found)
+ break;
+ else
+@@ -1465,8 +1678,12 @@ static int __init edma_probe(struct platform_device *pdev)
+ }
+ }
+
+- sprintf(irq_name, "edma%d", j);
+- irq[j] = platform_get_irq_byname(pdev, irq_name);
++ if (node)
++ irq[j] = irq_of_parse_and_map(node, 0);
++ else {
++ sprintf(irq_name, "edma%d", j);
++ irq[j] = platform_get_irq_byname(pdev, irq_name);
++ }
+ edma_cc[j]->irq_res_start = irq[j];
+ status = request_irq(irq[j], dma_irq_handler, 0, "edma",
+ &pdev->dev);
+@@ -1476,8 +1693,12 @@ static int __init edma_probe(struct platform_device *pdev)
+ goto fail;
+ }
+
+- sprintf(irq_name, "edma%d_err", j);
+- err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ if (node)
++ err_irq[j] = irq_of_parse_and_map(node, 2);
++ else {
++ sprintf(irq_name, "edma%d_err", j);
++ err_irq[j] = platform_get_irq_byname(pdev, irq_name);
++ }
+ edma_cc[j]->irq_res_end = err_irq[j];
+ status = request_irq(err_irq[j], dma_ccerr_handler, 0,
+ "edma_error", &pdev->dev);
+@@ -1538,9 +1759,17 @@ fail1:
+ return status;
+ }
+
++static const struct of_device_id edma_of_ids[] = {
++ { .compatible = "ti,edma3", },
++ {}
++};
+
+ static struct platform_driver edma_driver = {
+- .driver.name = "edma",
++ .driver = {
++ .name = "edma",
++ .of_match_table = edma_of_ids,
++ },
++ .probe = edma_probe,
+ };
+
+ static int __init edma_init(void)
+diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
+index 95b5e10..ffcbec1 100644
+--- a/arch/arm/mach-davinci/board-da830-evm.c
++++ b/arch/arm/mach-davinci/board-da830-evm.c
+@@ -512,7 +512,7 @@ static struct davinci_i2c_platform_data da830_evm_i2c_0_pdata = {
+ * example: Timer, GPIO, UART events etc) on da830/omap-l137 EVM, hence
+ * they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da830_dma_rsv_chans[][2] = {
++static s16 da830_dma_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 2},
+ {12, 2},
+@@ -521,7 +521,7 @@ static const s16 da830_dma_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da830_dma_rsv_slots[][2] = {
++static s16 da830_dma_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 2},
+ {12, 2},
+diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
+index 32ee3f8..f207965 100644
+--- a/arch/arm/mach-davinci/board-da850-evm.c
++++ b/arch/arm/mach-davinci/board-da850-evm.c
+@@ -1097,7 +1097,7 @@ device_initcall(da850_evm_config_emac);
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM, hence
+ * they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da850_dma0_rsv_chans[][2] = {
++static s16 da850_dma0_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -1105,7 +1105,7 @@ static const s16 da850_dma0_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma0_rsv_slots[][2] = {
++static s16 da850_dma0_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -1113,14 +1113,14 @@ static const s16 da850_dma0_rsv_slots[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_chans[][2] = {
++static s16 da850_dma1_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 2},
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_slots[][2] = {
++static s16 da850_dma1_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 90},
+diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
+index 1dbf85b..6c5b814 100644
+--- a/arch/arm/mach-davinci/board-dm646x-evm.c
++++ b/arch/arm/mach-davinci/board-dm646x-evm.c
+@@ -764,7 +764,7 @@ static struct davinci_uart_config uart_config __initdata = {
+ * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
+ * reserved for codecs on the DSP side.
+ */
+-static const s16 dm646x_dma_rsv_chans[][2] = {
++static s16 dm646x_dma_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 4},
+ {13, 3},
+@@ -774,7 +774,7 @@ static const s16 dm646x_dma_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 dm646x_dma_rsv_slots[][2] = {
++static s16 dm646x_dma_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 4},
+ {13, 3},
+diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
+index dc1208e..09c34f8 100644
+--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
++++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
+@@ -70,7 +70,7 @@ static __init void omapl138_hawk_config_emac(void)
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard,
+ * hence they are being reserved for codecs on the DSP side.
+ */
+-static const s16 da850_dma0_rsv_chans[][2] = {
++static s16 da850_dma0_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -78,7 +78,7 @@ static const s16 da850_dma0_rsv_chans[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma0_rsv_slots[][2] = {
++static s16 da850_dma0_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 8, 6},
+ {24, 4},
+@@ -86,14 +86,14 @@ static const s16 da850_dma0_rsv_slots[][2] = {
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_chans[][2] = {
++static s16 da850_dma1_rsv_chans[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 2},
+ {-1, -1}
+ };
+
+-static const s16 da850_dma1_rsv_slots[][2] = {
++static s16 da850_dma1_rsv_slots[][2] = {
+ /* (offset, number) */
+ { 0, 28},
+ {30, 90},
+diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
+index bd2f72b..1f9c6ff 100644
+--- a/arch/arm/mach-davinci/devices-da8xx.c
++++ b/arch/arm/mach-davinci/devices-da8xx.c
+@@ -103,27 +103,27 @@ struct platform_device da8xx_serial_device = {
+ },
+ };
+
+-static const s8 da8xx_queue_tc_mapping[][2] = {
++static s8 da8xx_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+ {1, 1},
+ {-1, -1}
+ };
+
+-static const s8 da8xx_queue_priority_mapping[][2] = {
++static s8 da8xx_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {1, 7},
+ {-1, -1}
+ };
+
+-static const s8 da850_queue_tc_mapping[][2] = {
++static s8 da850_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+ {-1, -1}
+ };
+
+-static const s8 da850_queue_priority_mapping[][2] = {
++static s8 da850_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {-1, -1}
+diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
+index 59efd7f..d2453c9 100644
+--- a/arch/arm/mach-davinci/devices-tnetv107x.c
++++ b/arch/arm/mach-davinci/devices-tnetv107x.c
+@@ -58,14 +58,14 @@
+ #define TNETV107X_DMACH_SDIO1_RX 28
+ #define TNETV107X_DMACH_SDIO1_TX 29
+
+-static const s8 edma_tc_mapping[][2] = {
++static s8 edma_tc_mapping[][2] = {
+ /* event queue no TC no */
+ { 0, 0 },
+ { 1, 1 },
+ { -1, -1 }
+ };
+
+-static const s8 edma_priority_mapping[][2] = {
++static s8 edma_priority_mapping[][2] = {
+ /* event queue no Prio */
+ { 0, 3 },
+ { 1, 7 },
+diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
+index b165c27..cdefef3 100644
+--- a/arch/arm/mach-davinci/dm355.c
++++ b/arch/arm/mach-davinci/dm355.c
+@@ -567,7 +567,7 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+
+ /*----------------------------------------------------------------------*/
+
+-static const s8
++static s8
+ queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -575,7 +575,7 @@ queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
+index a611716..801e162 100644
+--- a/arch/arm/mach-davinci/dm365.c
++++ b/arch/arm/mach-davinci/dm365.c
+@@ -822,7 +822,7 @@ static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ };
+
+ /* Four Transfer Controllers on DM365 */
+-static const s8
++static s8
+ dm365_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -832,7 +832,7 @@ dm365_queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ dm365_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 7},
+diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
+index 5b0a263..d4e04c5 100644
+--- a/arch/arm/mach-davinci/dm644x.c
++++ b/arch/arm/mach-davinci/dm644x.c
+@@ -497,7 +497,7 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+
+ /*----------------------------------------------------------------------*/
+
+-static const s8
++static s8
+ queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -505,7 +505,7 @@ queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
+index 08f9dab..b4a4da6 100644
+--- a/arch/arm/mach-davinci/dm646x.c
++++ b/arch/arm/mach-davinci/dm646x.c
+@@ -531,7 +531,7 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ /*----------------------------------------------------------------------*/
+
+ /* Four Transfer Controllers on DM646x */
+-static const s8
++static s8
+ dm646x_queue_tc_mapping[][2] = {
+ /* {event queue no, TC no} */
+ {0, 0},
+@@ -541,7 +541,7 @@ dm646x_queue_tc_mapping[][2] = {
+ {-1, -1},
+ };
+
+-static const s8
++static s8
+ dm646x_queue_priority_mapping[][2] = {
+ /* {event queue no, Priority} */
+ {0, 4},
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+index 7396f0b3..b20b586 100644
+--- a/include/linux/platform_data/edma.h
++++ b/include/linux/platform_data/edma.h
+@@ -168,8 +168,8 @@ void edma_resume(unsigned channel);
+
+ struct edma_rsv_info {
+
+- const s16 (*rsv_chans)[2];
+- const s16 (*rsv_slots)[2];
++ s16 (*rsv_chans)[2];
++ s16 (*rsv_slots)[2];
+ };
+
+ /* platform_data for EDMA driver */
+@@ -191,8 +191,8 @@ struct edma_soc_info {
+ /* Resource reservation for other cores */
+ struct edma_rsv_info *rsv;
+
+- const s8 (*queue_tc_mapping)[2];
+- const s8 (*queue_priority_mapping)[2];
++ s8 (*queue_tc_mapping)[2];
++ s8 (*queue_priority_mapping)[2];
+ };
+
+ #endif
diff --git a/patches/linux-3.7/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch b/patches/linux-3.7/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
new file mode 100644
index 0000000..e4177fd
--- /dev/null
+++ b/patches/linux-3.7/0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
@@ -0,0 +1,127 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 16:13:17 -0400
+Subject: [PATCH] ARM: edma: add AM33XX crossbar event support
+
+Adds support for the per-EDMA channel event mux. This is required
+for any peripherals using DMA crossbar mapped events.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 63 +++++++++++++++++++++++++++++++++++-
+ include/linux/platform_data/edma.h | 1 +
+ 2 files changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index 6d2a590..b761b7a 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -1425,6 +1425,53 @@ static int edma_of_read_u32_to_s16_array(const struct device_node *np,
+ return 0;
+ }
+
++static int edma_xbar_event_map(struct device *dev,
++ struct device_node *node,
++ struct edma_soc_info *pdata, int len)
++{
++ int ret = 0;
++ int i;
++ struct resource res;
++ void *xbar;
++ s16 (*xbar_chans)[2];
++ u32 shift, offset, mux;
++
++ xbar_chans = devm_kzalloc(dev,
++ len/sizeof(s16) + 2*sizeof(s16),
++ GFP_KERNEL);
++ if (!xbar_chans)
++ return -ENOMEM;
++
++ ret = of_address_to_resource(node, 1, &res);
++ if (IS_ERR_VALUE(ret))
++ return -EIO;
++
++ xbar = devm_ioremap(dev, res.start, resource_size(&res));
++ if (!xbar)
++ return -EIO;
++
++ ret = edma_of_read_u32_to_s16_array(node,
++ "ti,edma-xbar-event-map",
++ (s16 *)xbar_chans,
++ len/sizeof(u32));
++ if (IS_ERR_VALUE(ret))
++ return -EIO;
++
++ for (i = 0; xbar_chans[i][0] != -1; i++) {
++ shift = (xbar_chans[i][1] % 4) * 8;
++ offset = xbar_chans[i][1] >> 2;
++ offset <<= 2;
++ mux = __raw_readl((void *)((u32)xbar + offset));
++ mux &= (~(0xff << shift));
++ mux |= (xbar_chans[i][0] << shift);
++ __raw_writel(mux, (void *)((u32)xbar + offset));
++ }
++
++ pdata->xbar_chans = xbar_chans;
++
++ return 0;
++}
++
+ static int edma_of_parse_dt(struct device *dev,
+ struct device_node *node,
+ struct edma_soc_info *pdata)
+@@ -1453,7 +1500,6 @@ static int edma_of_parse_dt(struct device *dev,
+ pdata->n_slot = value;
+
+ pdata->n_cc = 1;
+- /* This is unused */
+ pdata->n_tc = 3;
+
+ rsv_info =
+@@ -1538,6 +1584,10 @@ static int edma_of_parse_dt(struct device *dev,
+ return ret;
+ pdata->default_queue = value;
+
++ prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
++ if (prop)
++ ret = edma_xbar_event_map(dev, node, pdata, sz);
++
+ return ret;
+ }
+
+@@ -1554,6 +1604,7 @@ static int __init edma_probe(struct platform_device *pdev)
+ int status = -1;
+ s16 (*rsv_chans)[2];
+ s16 (*rsv_slots)[2];
++ s16 (*xbar_chans)[2];
+ int irq[EDMA_MAX_CC] = {0, 0};
+ int err_irq[EDMA_MAX_CC] = {0, 0};
+ struct resource *r[EDMA_MAX_CC] = {NULL, NULL};
+@@ -1678,6 +1729,16 @@ static int __init edma_probe(struct platform_device *pdev)
+ }
+ }
+
++ /* Clear the xbar mapped channels in unused list */
++ xbar_chans = info[j]->xbar_chans;
++ if (xbar_chans) {
++ for (i = 0; xbar_chans[i][1] != -1; i++) {
++ off = xbar_chans[i][1];
++ clear_bits(off, 1,
++ edma_cc[j]->edma_unused);
++ }
++ }
++
+ if (node)
+ irq[j] = irq_of_parse_and_map(node, 0);
+ else {
+diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
+index b20b586..888a3c6 100644
+--- a/include/linux/platform_data/edma.h
++++ b/include/linux/platform_data/edma.h
+@@ -191,6 +191,7 @@ struct edma_soc_info {
+ /* Resource reservation for other cores */
+ struct edma_rsv_info *rsv;
+
++ s16 (*xbar_chans)[2];
+ s8 (*queue_tc_mapping)[2];
+ s8 (*queue_priority_mapping)[2];
+ };
diff --git a/patches/linux-3.7/0013-dmaengine-edma-enable-build-for-AM33XX.patch b/patches/linux-3.7/0013-dmaengine-edma-enable-build-for-AM33XX.patch
new file mode 100644
index 0000000..b3d58ab
--- /dev/null
+++ b/patches/linux-3.7/0013-dmaengine-edma-enable-build-for-AM33XX.patch
@@ -0,0 +1,24 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:42:35 -0400
+Subject: [PATCH] dmaengine: edma: enable build for AM33XX
+
+Enable TI EDMA option on OMAP.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/dma/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index d4c1218..20ef955 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -221,7 +221,7 @@ config SIRF_DMA
+
+ config TI_EDMA
+ tristate "TI EDMA support"
+- depends on ARCH_DAVINCI
++ depends on ARCH_DAVINCI || ARCH_OMAP
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ default n
diff --git a/patches/linux-3.7/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch b/patches/linux-3.7/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
new file mode 100644
index 0000000..0b78112
--- /dev/null
+++ b/patches/linux-3.7/0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
@@ -0,0 +1,70 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 07:46:04 -0400
+Subject: [PATCH] dmaengine: edma: Add TI EDMA device tree binding
+
+The binding definition is based on the generic DMA controller
+binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/dma/ti-edma.txt | 51 +++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/dma/ti-edma.txt
+
+diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
+new file mode 100644
+index 0000000..3344345
+--- /dev/null
++++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
+@@ -0,0 +1,51 @@
++TI EDMA
++
++Required properties:
++- compatible : "ti,edma3"
++- ti,hwmods: Name of the hwmods associated to the EDMA
++- ti,edma-regions: Number of regions
++- ti,edma-slots: Number of slots
++- ti,edma-queue-tc-map: List of transfer control to queue mappings
++- ti,edma-queue-priority-map: List of queue priority mappings
++- ti,edma-default-queue: Default queue value
++
++Optional properties:
++- ti,edma-reserved-channels: List of reserved channel regions
++- ti,edma-reserved-slots: List of reserved slot regions
++- ti,edma-xbar-event-map: Crossbar event to channel map
++
++Example:
++
++edma: edma@49000000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x49000000 0x10000>;
++ interrupt-parent = <&intc>;
++ interrupts = <12 13 14>;
++ compatible = "ti,edma3";
++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
++ #dma-cells = <1>;
++ dma-channels = <64>;
++ ti,edma-regions = <4>;
++ ti,edma-slots = <256>;
++ ti,edma-reserved-channels = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8>;
++ ti,edma-reserved-slots = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8
++ 64 127>;
++ ti,edma-queue-tc-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-queue-priority-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-default-queue = <0>;
++ ti,edma-xbar-event-map = <1 12
++ 2 13>;
++};
diff --git a/patches/linux-3.7/0015-ARM-dts-add-AM33XX-EDMA-support.patch b/patches/linux-3.7/0015-ARM-dts-add-AM33XX-EDMA-support.patch
new file mode 100644
index 0000000..fc3dca8
--- /dev/null
+++ b/patches/linux-3.7/0015-ARM-dts-add-AM33XX-EDMA-support.patch
@@ -0,0 +1,54 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 10 Oct 2012 10:01:33 -0400
+Subject: [PATCH] ARM: dts: add AM33XX EDMA support
+
+Adds AM33XX EDMA support to the am33xx.dtsi as documented in
+Documentation/devicetree/bindings/dma/ti-edma.txt
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index bb31bff..ab9c78f 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -62,6 +62,37 @@
+ reg = <0x48200000 0x1000>;
+ };
+
++ edma: edma@49000000 {
++ compatible = "ti,edma3";
++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
++ reg = <0x49000000 0x10000>,
++ <0x44e10f90 0x10>;
++ interrupt-parent = <&intc>;
++ interrupts = <12 13 14>;
++ #dma-cells = <1>;
++ dma-channels = <64>;
++ ti,edma-regions = <4>;
++ ti,edma-slots = <256>;
++ ti,edma-reserved-channels = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8>;
++ ti,edma-reserved-slots = <0 2
++ 14 2
++ 26 6
++ 48 4
++ 56 8
++ 64 127>;
++ ti,edma-queue-tc-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-queue-priority-map = <0 0
++ 1 1
++ 2 2>;
++ ti,edma-default-queue = <0>;
++ };
++
+ gpio1: gpio@44e07000 {
+ compatible = "ti,omap4-gpio";
+ ti,hwmods = "gpio1";
diff --git a/patches/linux-3.7/0016-dmaengine-add-dma_request_slave_channel_compat.patch b/patches/linux-3.7/0016-dmaengine-add-dma_request_slave_channel_compat.patch
new file mode 100644
index 0000000..776ddf8
--- /dev/null
+++ b/patches/linux-3.7/0016-dmaengine-add-dma_request_slave_channel_compat.patch
@@ -0,0 +1,41 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 12:58:44 -0400
+Subject: [PATCH] dmaengine: add dma_request_slave_channel_compat()
+
+Adds a dma_request_slave_channel_compat() wrapper which accepts
+both the arguments from dma_request_channel() and
+dma_request_slave_channel(). Based on whether the driver is
+instantiated via DT, the appropriate channel request call will be
+made.
+
+This allows for a much cleaner migration of drivers to the
+dmaengine DT API as platforms continue to be mixed between those
+that boot using DT and those that do not.
+
+Suggested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ include/linux/dmaengine.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
+index c88f302..11d9e25 100644
+--- a/include/linux/dmaengine.h
++++ b/include/linux/dmaengine.h
+@@ -1007,6 +1007,16 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
+ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
+ struct dma_chan *net_dma_find_channel(void);
+ #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
++static inline struct dma_chan
++*dma_request_slave_channel_compat(dma_cap_mask_t mask, dma_filter_fn fn,
++ void *fn_param, struct device *dev,
++ char *name)
++{
++ if (dev->of_node)
++ return dma_request_slave_channel(dev, name);
++ else
++ return dma_request_channel(mask, fn, fn_param);
++}
+
+ /* --- Helper iov-locking functions --- */
+
diff --git a/patches/linux-3.7/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch b/patches/linux-3.7/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
new file mode 100644
index 0000000..519d7c7
--- /dev/null
+++ b/patches/linux-3.7/0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
@@ -0,0 +1,44 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 6 Sep 2012 17:47:21 -0400
+Subject: [PATCH] mmc: omap_hsmmc: convert to
+ dma_request_slave_channel_compat()
+
+Convert dmaengine channel requests to use
+dma_request_slave_channel_compat(). This supports the DT case of
+platforms requiring channel selection from either the OMAP DMA or
+the EDMA engine. AM33xx only boots from DT and is the only user
+implementing EDMA so in the !DT case we can default to the OMAP DMA
+filter.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index fedd258..f74141e 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1871,14 +1871,20 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+- host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req);
++ host->rx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &rx_req, &pdev->dev, "rx");
++
+ if (!host->rx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
+ ret = -ENXIO;
+ goto err_irq;
+ }
+
+- host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req);
++ host->tx_chan =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &tx_req, &pdev->dev, "tx");
++
+ if (!host->tx_chan) {
+ dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
+ ret = -ENXIO;
diff --git a/patches/linux-3.7/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch b/patches/linux-3.7/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
new file mode 100644
index 0000000..cf10fa8
--- /dev/null
+++ b/patches/linux-3.7/0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
@@ -0,0 +1,38 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 08:55:41 -0400
+Subject: [PATCH] mmc: omap_hsmmc: limit max_segs with the EDMA DMAC
+
+The EDMA DMAC has a hardware limitation that prevents supporting
+scatter gather lists with any number of segments. Since the EDMA
+DMA Engine driver sets the maximum segments to 16, we do the
+same.
+
+TODO: this will be replaced once the DMA Engine API supports an
+API to query the DMAC's segment size limit.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index f74141e..4fe62b0 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1833,6 +1833,16 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ * as we want. */
+ mmc->max_segs = 1024;
+
++ /* Eventually we should get our max_segs limitation for EDMA by
++ * querying the dmaengine API */
++ if (pdev->dev.of_node) {
++ struct device_node *parent = pdev->dev.of_node->parent;
++ struct device_node *node;
++ node = of_find_node_by_name(parent, "edma");
++ if (node)
++ mmc->max_segs = 16;
++ }
++
+ mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
+ mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
diff --git a/patches/linux-3.7/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch b/patches/linux-3.7/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
new file mode 100644
index 0000000..ff2892f
--- /dev/null
+++ b/patches/linux-3.7/0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
@@ -0,0 +1,54 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 07:47:47 -0400
+Subject: [PATCH] mmc: omap_hsmmc: add generic DMA request support to the DT
+ binding
+
+The binding definition is based on the generic DMA request binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 25 +++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+index be76a23..d1b8932 100644
+--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
++++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+@@ -19,8 +19,28 @@ ti,dual-volt: boolean, supports dual voltage cards
+ "supply-name" examples are "vmmc", "vmmc_aux" etc
+ ti,non-removable: non-removable slot (like eMMC)
+ ti,needs-special-reset: Requires a special softreset sequence
++dmas: DMA controller phandle and DMA request value ordered pair
++One tx and one rx pair is required.
++dma-names: DMA request names. These strings correspond 1:1 with
++the ordered pairs in dmas. The RX request must be "rx" and the
++TX request must be "tx".
++
++Examples:
++
++[hwmod populated DMA resources]
++
++ mmc1: mmc@0x4809c000 {
++ compatible = "ti,omap4-hsmmc";
++ reg = <0x4809c000 0x400>;
++ ti,hwmods = "mmc1";
++ ti,dual-volt;
++ bus-width = <4>;
++ vmmc-supply = <&vmmc>; /* phandle to regulator node */
++ ti,non-removable;
++ };
++
++[generic DMA request binding]
+
+-Example:
+ mmc1: mmc@0x4809c000 {
+ compatible = "ti,omap4-hsmmc";
+ reg = <0x4809c000 0x400>;
+@@ -29,4 +49,7 @@ Example:
+ bus-width = <4>;
+ vmmc-supply = <&vmmc>; /* phandle to regulator node */
+ ti,non-removable;
++ dmas = <&edma 24
++ &edma 25>;
++ dma-names = "tx", "rx";
+ };
diff --git a/patches/linux-3.7/0020-ARM-dts-add-AM33XX-MMC-support.patch b/patches/linux-3.7/0020-ARM-dts-add-AM33XX-MMC-support.patch
new file mode 100644
index 0000000..9b8506d
--- /dev/null
+++ b/patches/linux-3.7/0020-ARM-dts-add-AM33XX-MMC-support.patch
@@ -0,0 +1,90 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 10 Oct 2012 15:14:03 -0400
+Subject: [PATCH] ARM: dts: add AM33XX MMC support
+
+Adds AM33XX MMC support for am335x-bone and am335x-evm.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 6 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 6 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 27 +++++++++++++++++++++++++++
+ 3 files changed, 39 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index c634f87..5510979 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -70,6 +70,8 @@
+ };
+
+ ldo3_reg: regulator@5 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+@@ -78,3 +80,7 @@
+ };
+ };
+ };
++
++&mmc1 {
++ vmmc-supply = <&ldo3_reg>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 185d632..d63fce8 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -114,7 +114,13 @@
+ };
+
+ vmmc_reg: regulator@12 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
++
++&mmc1 {
++ vmmc-supply = <&vmmc_reg>;
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index ab9c78f..26a6af7 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -234,6 +234,33 @@
+ status = "disabled";
+ };
+
++ mmc1: mmc@48060000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc1";
++ ti,dual-volt;
++ ti,needs-special-reset;
++ dmas = <&edma 24
++ &edma 25>;
++ dma-names = "tx", "rx";
++ };
++
++ mmc2: mmc@481d8000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc2";
++ ti,needs-special-reset;
++ dmas = <&edma 2
++ &edma 3>;
++ dma-names = "tx", "rx";
++ status = "disabled";
++ };
++
++ mmc3: mmc@47810000 {
++ compatible = "ti,omap3-hsmmc";
++ ti,hwmods = "mmc3";
++ ti,needs-special-reset;
++ status = "disabled";
++ };
++
+ wdt2: wdt@44e35000 {
+ compatible = "ti,omap3-wdt";
+ ti,hwmods = "wd_timer2";
diff --git a/patches/linux-3.7/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch b/patches/linux-3.7/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
new file mode 100644
index 0000000..d4081a5
--- /dev/null
+++ b/patches/linux-3.7/0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
@@ -0,0 +1,118 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 00:37:54 -0400
+Subject: [PATCH] spi: omap2-mcspi: convert to
+ dma_request_slave_channel_compat()
+
+Convert dmaengine channel requests to use
+dma_request_slave_channel_compat(). This supports the DT case of
+platforms requiring channel selection from either the OMAP DMA or
+the EDMA engine. AM33xx only boots from DT and is the only user
+implementing EDMA so in the !DT case we can default to the OMAP DMA
+filter.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/spi/spi-omap2-mcspi.c | 65 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 45 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
+index 3542fdc..793ae8c 100644
+--- a/drivers/spi/spi-omap2-mcspi.c
++++ b/drivers/spi/spi-omap2-mcspi.c
+@@ -103,6 +103,9 @@ struct omap2_mcspi_dma {
+
+ struct completion dma_tx_completion;
+ struct completion dma_rx_completion;
++
++ char dma_rx_ch_name[14];
++ char dma_tx_ch_name[14];
+ };
+
+ /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
+@@ -819,14 +822,23 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ sig = mcspi_dma->dma_rx_sync_dev;
+- mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
++
++ mcspi_dma->dma_rx =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &sig, &master->dev,
++ mcspi_dma->dma_rx_ch_name);
++
+ if (!mcspi_dma->dma_rx) {
+ dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
+ return -EAGAIN;
+ }
+
+ sig = mcspi_dma->dma_tx_sync_dev;
+- mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
++ mcspi_dma->dma_tx =
++ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
++ &sig, &master->dev,
++ mcspi_dma->dma_tx_ch_name);
++
+ if (!mcspi_dma->dma_tx) {
+ dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
+ dma_release_channel(mcspi_dma->dma_rx);
+@@ -1217,29 +1229,42 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)
+ goto free_master;
+
+ for (i = 0; i < master->num_chipselect; i++) {
+- char dma_ch_name[14];
++ char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
++ char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name;
+ struct resource *dma_res;
+
+- sprintf(dma_ch_name, "rx%d", i);
+- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+- dma_ch_name);
+- if (!dma_res) {
+- dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
+- status = -ENODEV;
+- break;
+- }
++ sprintf(dma_rx_ch_name, "rx%d", i);
++ if (!pdev->dev.of_node) {
++ dma_res =
++ platform_get_resource_byname(pdev,
++ IORESOURCE_DMA,
++ dma_rx_ch_name);
++ if (!dma_res) {
++ dev_dbg(&pdev->dev,
++ "cannot get DMA RX channel\n");
++ status = -ENODEV;
++ break;
++ }
+
+- mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
+- sprintf(dma_ch_name, "tx%d", i);
+- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+- dma_ch_name);
+- if (!dma_res) {
+- dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
+- status = -ENODEV;
+- break;
++ mcspi->dma_channels[i].dma_rx_sync_dev =
++ dma_res->start;
+ }
++ sprintf(dma_tx_ch_name, "tx%d", i);
++ if (!pdev->dev.of_node) {
++ dma_res =
++ platform_get_resource_byname(pdev,
++ IORESOURCE_DMA,
++ dma_tx_ch_name);
++ if (!dma_res) {
++ dev_dbg(&pdev->dev,
++ "cannot get DMA TX channel\n");
++ status = -ENODEV;
++ break;
++ }
+
+- mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
++ mcspi->dma_channels[i].dma_tx_sync_dev =
++ dma_res->start;
++ }
+ }
+
+ if (status < 0)
diff --git a/patches/linux-3.7/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch b/patches/linux-3.7/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
new file mode 100644
index 0000000..e6baf04
--- /dev/null
+++ b/patches/linux-3.7/0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
@@ -0,0 +1,55 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 20 Sep 2012 09:21:16 -0400
+Subject: [PATCH] spi: omap2-mcspi: add generic DMA request support to the DT
+ binding
+
+The binding definition is based on the generic DMA request binding.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/spi/omap-spi.txt | 27 +++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
+index 81df374..11aff04 100644
+--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
++++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
+@@ -7,8 +7,18 @@ Required properties:
+ - ti,spi-num-cs : Number of chipselect supported by the instance.
+ - ti,hwmods: Name of the hwmod associated to the McSPI
+
++Optional properties:
++- dmas: List of DMA controller phandle and DMA request ordered
++ pairs. One tx and one rx pair is required for each chip
++ select.
++- dma-names: List of DMA request names. These strings correspond
++ 1:1 with the ordered pairs in dmas. The string naming is
++ to be "rxN" and "txN" for RX and TX requests,
++ respectively, where N equals the chip select number.
+
+-Example:
++Examples:
++
++[hwmod populated DMA resources]
+
+ mcspi1: mcspi@1 {
+ #address-cells = <1>;
+@@ -18,3 +28,18 @@ mcspi1: mcspi@1 {
+ ti,spi-num-cs = <4>;
+ };
+
++[generic DMA request binding]
++
++mcspi1: mcspi@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "mcspi1";
++ ti,spi-num-cs = <2>;
++ dmas = <&edma 42
++ &edma 43
++ &edma 44
++ &edma 45>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++};
++
diff --git a/patches/linux-3.7/0023-ARM-dts-add-AM33XX-SPI-support.patch b/patches/linux-3.7/0023-ARM-dts-add-AM33XX-SPI-support.patch
new file mode 100644
index 0000000..d8c8d74
--- /dev/null
+++ b/patches/linux-3.7/0023-ARM-dts-add-AM33XX-SPI-support.patch
@@ -0,0 +1,123 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 08:51:46 -0400
+Subject: [PATCH] ARM: dts: add AM33XX SPI support
+
+Adds AM33XX SPI support for am335x-bone and am335x-evm.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 17 +++++++++++++++
+ arch/arm/boot/dts/am335x-evm.dts | 9 ++++++++
+ arch/arm/boot/dts/am33xx.dtsi | 43 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 69 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 5510979..23edfd8 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -18,6 +18,17 @@
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+ };
+
++ am3358_pinmux: pinmux@44e10800 {
++ spi1_pins: pinmux_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
++ >;
++ };
++ };
++
+ ocp {
+ uart1: serial@44e09000 {
+ status = "okay";
+@@ -84,3 +95,9 @@
+ &mmc1 {
+ vmmc-supply = <&ldo3_reg>;
+ };
++
++&spi1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins>;
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index d63fce8..8d5f660 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -124,3 +124,12 @@
+ &mmc1 {
+ vmmc-supply = <&vmmc_reg>;
+ };
++
++&spi0 {
++ status = "okay";
++ spi-flash@0 {
++ compatible = "spansion,s25fl064k", "m25p80";
++ spi-max-frequency = <24000000>;
++ reg = <0>;
++ };
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 26a6af7..063ecea 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -40,6 +40,15 @@
+ };
+ };
+
++ am3358_pinmux: pinmux@44e10800 {
++ compatible = "pinctrl-single";
++ reg = <0x44e10800 0x0238>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ pinctrl-single,register-width = <32>;
++ pinctrl-single,function-mask = <0x7f>;
++ };
++
+ /*
+ * XXX: Use a flat representation of the AM33XX interconnect.
+ * The real AM33XX interconnect network is quite complex.Since
+@@ -261,6 +270,40 @@
+ status = "disabled";
+ };
+
++ spi0: spi@48030000 {
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "spi0";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x48030000 0x400>;
++ interrupt-parent = <&intc>;
++ interrupt = <65>;
++ dmas = <&edma 16
++ &edma 17
++ &edma 18
++ &edma 19>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++ ti,spi-num-cs = <2>;
++ status = "disabled";
++ };
++
++ spi1: spi@481a0000 {
++ compatible = "ti,omap4-mcspi";
++ ti,hwmods = "spi1";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x481a0000 0x400>;
++ interrupt-parent = <&intc>;
++ interrupt = <125>;
++ dmas = <&edma 42
++ &edma 43
++ &edma 44
++ &edma 45>;
++ dma-names = "tx0", "rx0", "tx1", "rx1";
++ ti,spi-num-cs = <2>;
++ status = "disabled";
++ };
++
+ wdt2: wdt@44e35000 {
+ compatible = "ti,omap3-wdt";
+ ti,hwmods = "wd_timer2";
diff --git a/patches/linux-3.7/0024-Documentation-bindings-add-spansion.patch b/patches/linux-3.7/0024-Documentation-bindings-add-spansion.patch
new file mode 100644
index 0000000..a603210
--- /dev/null
+++ b/patches/linux-3.7/0024-Documentation-bindings-add-spansion.patch
@@ -0,0 +1,21 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 17:12:09 -0400
+Subject: [PATCH] Documentation: bindings: add spansion
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
+index 54463a7..261b6d5 100644
+--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
++++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
+@@ -47,6 +47,7 @@ sil Silicon Image
+ simtek
+ sirf SiRF Technology, Inc.
+ sitronix Sitronix Technology Corp.
++spansion Spansion, Inc.
+ st STMicroelectronics
+ stericsson ST-Ericsson
+ ti Texas Instruments
diff --git a/patches/linux-3.7/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch b/patches/linux-3.7/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
new file mode 100644
index 0000000..dc40167
--- /dev/null
+++ b/patches/linux-3.7/0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
@@ -0,0 +1,43 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 11 Oct 2012 08:52:54 -0400
+Subject: [PATCH] ARM: dts: add BeagleBone Adafruit 1.8 LCD support
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 23edfd8..290408c 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -27,6 +27,12 @@
+ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+ >;
+ };
++ lcd_pins: pinmux_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -100,4 +106,16 @@
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
+ };
diff --git a/patches/linux-3.7/0026-misc-add-gpevt-driver.patch b/patches/linux-3.7/0026-misc-add-gpevt-driver.patch
new file mode 100644
index 0000000..757e48c
--- /dev/null
+++ b/patches/linux-3.7/0026-misc-add-gpevt-driver.patch
@@ -0,0 +1,218 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 10:48:22 -0400
+Subject: [PATCH] misc: add gpevt driver
+
+Simply amazing...'nuff said.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/misc/Kconfig | 6 ++
+ drivers/misc/Makefile | 1 +
+ drivers/misc/gpevt.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 179 insertions(+)
+ create mode 100644 drivers/misc/gpevt.c
+
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index b151b7c..cd43cbd 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -499,6 +499,12 @@ config USB_SWITCH_FSA9480
+ stereo and mono audio, video, microphone and UART data to use
+ a common connector port.
+
++config GPEVT
++ tristate "Amazing GPIO DMA Event Test Driver(tm)"
++ depends on TI_EDMA
++ help
++ Simply amazing!
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 2129377..661d093 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -49,3 +49,4 @@ obj-y += carma/
+ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
+ obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
+ obj-$(CONFIG_INTEL_MEI) += mei/
++obj-$(CONFIG_GPEVT) += gpevt.o
+diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
+new file mode 100644
+index 0000000..4fe256c
+--- /dev/null
++++ b/drivers/misc/gpevt.c
+@@ -0,0 +1,172 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmaengine.h>
++#include <linux/gpio.h>
++#include <linux/err.h>
++#include <linux/uaccess.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++
++#define GPEVT_MAGIC 0xdeadbeef
++
++static u32 *dst_fifo;
++static dma_addr_t fifo_addr;
++
++static void gpevt_callback(void *data)
++{
++ struct device *dev = data;
++
++ dma_unmap_single(dev, fifo_addr, 32, DMA_FROM_DEVICE);
++
++ if (*dst_fifo == GPEVT_MAGIC)
++ dev_info(dev, "*** DMA transfer succeeded ***\n");
++ else
++ dev_info(dev, "*** DMA transfer failed ***\n");
++}
++
++static int __devinit gpevt_probe (struct platform_device *pdev)
++{
++ struct device_node *np = pdev->dev.of_node;
++ struct pinctrl *pinctrl;
++ struct dma_chan *chan;
++ struct dma_slave_config cfg;
++ struct dma_async_tx_descriptor *tx;
++ int gpio_evt = 0;
++ int ret;
++ u32 *src_buf;
++ struct scatterlist sg;
++
++ src_buf = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
++ if (!src_buf) {
++ dev_err(&pdev->dev, "failed to allocate src buffer\n");
++ return -ENOMEM;
++ }
++
++ dst_fifo = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
++ if (!dst_fifo) {
++ dev_err(&pdev->dev, "failed to allocate dst fifo\n");
++ return -ENOMEM;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ gpio_evt = of_get_named_gpio(np, "gpio-evt", 0);
++ if (gpio_evt < 0) {
++ dev_err(&pdev->dev, "failed to find gpio event signal!\n");
++ return -EINVAL;
++ }
++
++ ret = devm_gpio_request_one(&pdev->dev, gpio_evt,
++ GPIOF_IN, "GPIO Event Pin");
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to claim gpio-evt pin\n");
++ return ret;
++ }
++
++ ret = request_irq(gpio_to_irq(gpio_evt), no_action,
++ IRQ_TYPE_EDGE_FALLING, "gpevt", &pdev->dev);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to request falling edge irq/event\n");
++ return ret;
++ }
++
++ chan = dma_request_slave_channel(&pdev->dev, "gpioevt");
++ if (!chan) {
++ dev_err(&pdev->dev, "no gpio channel for gpevt\n");
++ return -EAGAIN;
++ }
++
++ fifo_addr = dma_map_single(&pdev->dev, dst_fifo, 32, DMA_FROM_DEVICE);
++ if (!fifo_addr) {
++ dev_err(&pdev->dev, "could not map dst fifo\n");
++ return -EIO;
++ }
++ cfg.dst_addr = fifo_addr;
++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ cfg.dst_maxburst = 1;
++
++ ret = dmaengine_slave_config(chan, &cfg);
++ if (ret)
++ return ret;
++
++ *src_buf = GPEVT_MAGIC;
++ sg_init_table(&sg, 1);
++ sg_dma_address(&sg) = dma_map_single(&pdev->dev, src_buf, 32, DMA_TO_DEVICE);
++ sg_dma_len(&sg) = 4;
++
++ tx = dmaengine_prep_slave_sg(chan, &sg, 1, DMA_MEM_TO_DEV,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!tx) {
++ dev_err(&pdev->dev, "prep_slave_sg() failed\n");
++ return -EIO;
++ }
++
++ tx->callback = gpevt_callback;
++ tx->callback_param = &pdev->dev;
++ dmaengine_submit(tx);
++
++ dma_async_issue_pending(chan);
++
++ dev_info(&pdev->dev, "Amazing GPIO DMA Event Test Driver(tm) engaged\n");
++
++ return 0;
++}
++
++static int __devexit gpevt_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static const struct of_device_id gpevt_dt_ids[] = {
++ { .compatible = "gpevt", .data = (void *) NULL, },
++};
++MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
++
++static struct platform_driver gpevt_driver = {
++ .driver = {
++ .name = "gpevt",
++ .owner = THIS_MODULE,
++ .of_match_table = gpevt_dt_ids,
++ },
++ .probe = gpevt_probe,
++ .remove = __devexit_p(gpevt_remove),
++};
++
++static int __init gpevt_init(void)
++{
++ return platform_driver_register(&gpevt_driver);
++}
++
++static void __exit gpevt_exit(void)
++{
++ platform_driver_unregister(&gpevt_driver);
++}
++
++/* ------------------------------------------------------------------------- */
++
++module_init(gpevt_init);
++module_exit(gpevt_exit);
++
++MODULE_DESCRIPTION("Amazing GPIO DMA Event Test Driver(tm)");
++MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.7/0027-ARM-dts-add-BeagleBone-gpevt-support.patch b/patches/linux-3.7/0027-ARM-dts-add-BeagleBone-gpevt-support.patch
new file mode 100644
index 0000000..1fe8639
--- /dev/null
+++ b/patches/linux-3.7/0027-ARM-dts-add-BeagleBone-gpevt-support.patch
@@ -0,0 +1,49 @@
+From: Matt Porter <mporter@ti.com>
+Date: Wed, 17 Oct 2012 17:12:45 -0400
+Subject: [PATCH] ARM: dts: add BeagleBone gpevt support
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 290408c..2ad3914 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -33,6 +33,11 @@
+ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ gpevt_pins: pinmux_gpevt_pins {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -49,6 +54,15 @@
+ };
+
+ };
++
++ gpevt {
++ compatible = "gpevt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpevt_pins>;
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
+ };
+ };
+
+@@ -119,3 +133,7 @@
+ st7735-dc = <&gpio4 21 0>;
+ };
+ };
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
diff --git a/patches/linux-3.7/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch b/patches/linux-3.7/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
new file mode 100644
index 0000000..87c49dc
--- /dev/null
+++ b/patches/linux-3.7/0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
@@ -0,0 +1,234 @@
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 12 Oct 2012 16:52:55 -0400
+Subject: [PATCH] ARM: configs: working AM33XX edma dmaengine defconfig
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/configs/omap2plus_defconfig | 68 ++++++++++++++++++++--------------
+ 1 file changed, 40 insertions(+), 28 deletions(-)
+
+diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
+index 6230304..89e1c58 100644
+--- a/arch/arm/configs/omap2plus_defconfig
++++ b/arch/arm/configs/omap2plus_defconfig
+@@ -1,14 +1,15 @@
+ CONFIG_EXPERIMENTAL=y
+ CONFIG_SYSVIPC=y
+ CONFIG_POSIX_MQUEUE=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_BSD_PROCESS_ACCT=y
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=16
++CONFIG_CGROUPS=y
+ CONFIG_BLK_DEV_INITRD=y
+ CONFIG_EXPERT=y
+-# CONFIG_SYSCTL_SYSCALL is not set
+-CONFIG_KALLSYMS_EXTRA_PASS=y
+ CONFIG_SLAB=y
+ CONFIG_PROFILING=y
+ CONFIG_OPROFILE=y
+@@ -20,19 +21,20 @@ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+ # CONFIG_BLK_DEV_BSG is not set
++CONFIG_PARTITION_ADVANCED=y
+ CONFIG_ARCH_OMAP=y
+ CONFIG_OMAP_RESET_CLOCKS=y
+ CONFIG_OMAP_MUX_DEBUG=y
++CONFIG_SOC_OMAP5=y
+ CONFIG_ARM_THUMBEE=y
+ CONFIG_ARM_ERRATA_411920=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_SMP=y
+ CONFIG_NR_CPUS=2
+-CONFIG_LEDS=y
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
++CONFIG_ARM_APPENDED_DTB=y
++CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO0,115200"
++CONFIG_CMDLINE_FORCE=y
+ CONFIG_KEXEC=y
+ CONFIG_FPE_NWFPE=y
+ CONFIG_BINFMT_MISC=y
+@@ -52,18 +54,24 @@ CONFIG_IP_PNP_RARP=y
+ # CONFIG_INET_LRO is not set
+ # CONFIG_IPV6 is not set
+ CONFIG_NETFILTER=y
+-CONFIG_BT=m
++CONFIG_BT=y
+ 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_CFG80211=m
+-CONFIG_MAC80211=m
++CONFIG_CFG80211=y
++CONFIG_NL80211_TESTMODE=y
++CONFIG_CFG80211_DEBUGFS=y
++CONFIG_CFG80211_WEXT=y
++CONFIG_LIB80211=y
++CONFIG_MAC80211=y
+ CONFIG_MAC80211_RC_PID=y
+ CONFIG_MAC80211_RC_DEFAULT_PID=y
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
+ CONFIG_CONNECTOR=y
+ CONFIG_MTD=y
+ CONFIG_MTD_CMDLINE_PARTS=y
+@@ -72,6 +80,7 @@ CONFIG_MTD_BLOCK=y
+ CONFIG_MTD_OOPS=y
+ CONFIG_MTD_CFI=y
+ CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_M25P80=y
+ CONFIG_MTD_NAND=y
+ CONFIG_MTD_NAND_OMAP2=y
+ CONFIG_MTD_ONENAND=y
+@@ -81,28 +90,27 @@ CONFIG_MTD_UBI=y
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_SIZE=16384
++CONFIG_GPEVT=y
+ CONFIG_SCSI=y
+ CONFIG_BLK_DEV_SD=y
+ CONFIG_SCSI_MULTI_LUN=y
+ CONFIG_SCSI_SCAN_ASYNC=y
+ CONFIG_MD=y
+ CONFIG_NETDEVICES=y
+-CONFIG_SMSC_PHY=y
+-CONFIG_NET_ETHERNET=y
+-CONFIG_SMC91X=y
+-CONFIG_SMSC911X=y
+ CONFIG_KS8851=y
+ CONFIG_KS8851_MLL=y
+-CONFIG_LIBERTAS=m
+-CONFIG_LIBERTAS_USB=m
+-CONFIG_LIBERTAS_SDIO=m
+-CONFIG_LIBERTAS_DEBUG=y
++CONFIG_SMC91X=y
++CONFIG_SMSC911X=y
++CONFIG_SMSC_PHY=y
+ CONFIG_USB_USBNET=y
+ CONFIG_USB_NET_SMSC95XX=y
+ CONFIG_USB_ALI_M5632=y
+ CONFIG_USB_AN2720=y
+ CONFIG_USB_EPSON2888=y
+ CONFIG_USB_KC2190=y
++CONFIG_WL_TI=y
++CONFIG_WL12XX=y
++CONFIG_WLCORE_SDIO=y
+ CONFIG_INPUT_JOYDEV=y
+ CONFIG_INPUT_EVDEV=y
+ CONFIG_KEYBOARD_GPIO=y
+@@ -123,23 +131,29 @@ CONFIG_HW_RANDOM=y
+ CONFIG_I2C_CHARDEV=y
+ CONFIG_SPI=y
+ CONFIG_SPI_OMAP24XX=y
++CONFIG_DEBUG_PINCTRL=y
+ CONFIG_PINCTRL_SINGLE=y
+ CONFIG_DEBUG_GPIO=y
+ CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_GENERIC_PLATFORM=y
+ CONFIG_GPIO_TWL4030=y
+ CONFIG_W1=y
+ CONFIG_POWER_SUPPLY=y
+ CONFIG_WATCHDOG=y
+ CONFIG_OMAP_WATCHDOG=y
+ CONFIG_TWL4030_WATCHDOG=y
+-CONFIG_REGULATOR_TWL4030=y
++CONFIG_MFD_TPS65217=y
++CONFIG_MFD_TPS65910=y
+ CONFIG_REGULATOR_TPS65023=y
+ CONFIG_REGULATOR_TPS6507X=y
++CONFIG_REGULATOR_TPS65217=y
++CONFIG_REGULATOR_TPS65910=y
++CONFIG_REGULATOR_TWL4030=y
+ CONFIG_FB=y
+ CONFIG_FIRMWARE_EDID=y
+ CONFIG_FB_MODE_HELPERS=y
+ CONFIG_FB_TILEBLITTING=y
+-CONFIG_FB_OMAP_LCD_VGA=y
++CONFIG_FB_ST7735=y
+ CONFIG_OMAP2_DSS=m
+ CONFIG_OMAP2_DSS_RFBI=y
+ CONFIG_OMAP2_DSS_SDI=y
+@@ -154,7 +168,6 @@ CONFIG_PANEL_ACX565AKM=m
+ CONFIG_BACKLIGHT_LCD_SUPPORT=y
+ CONFIG_LCD_CLASS_DEVICE=y
+ CONFIG_LCD_PLATFORM=y
+-CONFIG_DISPLAY_SUPPORT=y
+ CONFIG_FRAMEBUFFER_CONSOLE=y
+ CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+ CONFIG_FONTS=y
+@@ -174,12 +187,10 @@ CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+ CONFIG_USB=y
+ CONFIG_USB_DEBUG=y
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+-CONFIG_USB_DEVICEFS=y
+ CONFIG_USB_SUSPEND=y
+ CONFIG_USB_MON=y
+ CONFIG_USB_WDM=y
+ CONFIG_USB_STORAGE=y
+-CONFIG_USB_LIBUSUAL=y
+ CONFIG_USB_TEST=y
+ CONFIG_USB_GADGET=y
+ CONFIG_USB_GADGET_DEBUG=y
+@@ -192,9 +203,13 @@ CONFIG_SDIO_UART=y
+ CONFIG_MMC_OMAP=y
+ CONFIG_MMC_OMAP_HS=y
+ CONFIG_RTC_CLASS=y
++# CONFIG_RTC_INTF_SYSFS is not set
++# CONFIG_RTC_INTF_PROC is not set
++# CONFIG_RTC_INTF_DEV is not set
+ CONFIG_RTC_DRV_TWL92330=y
+ CONFIG_RTC_DRV_TWL4030=y
+ CONFIG_DMADEVICES=y
++CONFIG_TI_EDMA=y
+ CONFIG_DMA_OMAP=y
+ CONFIG_EXT2_FS=y
+ CONFIG_EXT3_FS=y
+@@ -202,6 +217,7 @@ CONFIG_EXT3_FS=y
+ CONFIG_EXT4_FS=y
+ CONFIG_QUOTA=y
+ CONFIG_QFMT_V2=y
++CONFIG_AUTOFS4_FS=y
+ CONFIG_MSDOS_FS=y
+ CONFIG_VFAT_FS=y
+ CONFIG_TMPFS=y
+@@ -214,23 +230,20 @@ CONFIG_JFFS2_RUBIN=y
+ CONFIG_UBIFS_FS=y
+ CONFIG_CRAMFS=y
+ CONFIG_NFS_FS=y
+-CONFIG_NFS_V3=y
+ CONFIG_NFS_V3_ACL=y
+ CONFIG_NFS_V4=y
+ CONFIG_ROOT_NFS=y
+-CONFIG_PARTITION_ADVANCED=y
+ CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_ISO8859_1=y
+ CONFIG_PRINTK_TIME=y
+ CONFIG_MAGIC_SYSRQ=y
+-CONFIG_DEBUG_KERNEL=y
+ CONFIG_SCHEDSTATS=y
+ CONFIG_TIMER_STATS=y
+ CONFIG_PROVE_LOCKING=y
+-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+ CONFIG_DEBUG_INFO=y
+-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++CONFIG_DEBUG_LL=y
++CONFIG_EARLY_PRINTK=y
+ CONFIG_SECURITY=y
+ CONFIG_CRYPTO_MICHAEL_MIC=y
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+@@ -239,4 +252,3 @@ CONFIG_CRC_T10DIF=y
+ CONFIG_CRC_ITU_T=y
+ CONFIG_CRC7=y
+ CONFIG_LIBCRC32C=y
+-CONFIG_SOC_OMAP5=y
diff --git a/patches/linux-3.7/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch b/patches/linux-3.7/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
new file mode 100644
index 0000000..17a54af
--- /dev/null
+++ b/patches/linux-3.7/0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
@@ -0,0 +1,2000 @@
+From: Matt Porter <mporter@ti.com>
+Date: Mon, 15 Oct 2012 10:17:43 -0400
+Subject: [PATCH] ARM: configs: working da850 edma dmaengine defconfig
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/configs/da8xx_omapl_defconfig | 1878 +++++++++++++++++++++++++++++++-
+ 1 file changed, 1857 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig
+index 88ccde0..571445f 100644
+--- a/arch/arm/configs/da8xx_omapl_defconfig
++++ b/arch/arm/configs/da8xx_omapl_defconfig
+@@ -1,129 +1,1965 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.7.0-rc1 Kernel Configuration
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_HAVE_PROC_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_ARCH_HAS_CPUFREQ=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_ARM_PATCH_PHYS_VIRT=y
++CONFIG_NEED_MACH_GPIO_H=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++
++#
++# General setup
++#
+ CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_XZ=y
++CONFIG_HAVE_KERNEL_LZO=y
++CONFIG_KERNEL_GZIP=y
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_XZ is not set
++# CONFIG_KERNEL_LZO is not set
++CONFIG_DEFAULT_HOSTNAME="(none)"
+ # CONFIG_SWAP is not set
+ CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
+ CONFIG_POSIX_MQUEUE=y
++CONFIG_POSIX_MQUEUE_SYSCTL=y
++# CONFIG_FHANDLE is not set
++# CONFIG_AUDIT is not set
++CONFIG_HAVE_GENERIC_HARDIRQS=y
++
++#
++# IRQ subsystem
++#
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_IRQ_SHOW=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_CHIP=y
++CONFIG_IRQ_DOMAIN=y
++# CONFIG_IRQ_DOMAIN_DEBUG is not set
++CONFIG_KTIME_SCALAR=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++
++#
++# Timers subsystem
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++
++#
++# CPU/Task time and stats accounting
++#
++CONFIG_TICK_CPU_ACCOUNTING=y
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_TINY_PREEMPT_RCU=y
++CONFIG_PREEMPT_RCU=y
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_RCU_BOOST is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+ CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++# CONFIG_CHECKPOINT_RESTORE is not set
++# CONFIG_NAMESPACES is not set
++# CONFIG_SCHED_AUTOGROUP is not set
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
+ CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_XZ is not set
++# CONFIG_RD_LZO is not set
++# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
+ CONFIG_EXPERT=y
++CONFIG_HAVE_UID16=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_EMBEDDED is not set
++CONFIG_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++# CONFIG_PERF_EVENTS is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++# CONFIG_JUMP_LABEL is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_ARCH_TRACEHOOK=y
++CONFIG_HAVE_DMA_ATTRS=y
++CONFIG_HAVE_DMA_CONTIGUOUS=y
++CONFIG_GENERIC_SMP_IDLE_THREAD=y
++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_DMA_API_DEBUG=y
++CONFIG_HAVE_ARCH_JUMP_LABEL=y
++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
++CONFIG_GENERIC_KERNEL_THREAD=y
++CONFIG_GENERIC_KERNEL_EXECVE=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
+ CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
+ CONFIG_MODULE_UNLOAD=y
+ CONFIG_MODULE_FORCE_UNLOAD=y
+ CONFIG_MODVERSIONS=y
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_MODULE_SIG is not set
++CONFIG_BLOCK=y
++CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_BSGLIB is not set
++# CONFIG_BLK_DEV_INTEGRITY 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
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
+ # CONFIG_IOSCHED_DEADLINE is not set
+ # CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++CONFIG_UNINLINE_SPIN_UNLOCK=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# CONFIG_ARCH_MULTIPLATFORM 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_BCM2835 is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_SIRF is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_MXS is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_LPC32XX is not set
++# CONFIG_ARCH_TEGRA is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C24XX is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_S5P64X0 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_EXYNOS is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_PLAT_SPEAR is not set
+ CONFIG_ARCH_DAVINCI=y
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VT8500 is not set
++# CONFIG_ARCH_ZYNQ is not set
++CONFIG_CP_INTC=y
++
++#
++# TI DaVinci Implementations
++#
++
++#
++# DaVinci Core Type
++#
++# CONFIG_ARCH_DAVINCI_DM644x is not set
++# CONFIG_ARCH_DAVINCI_DM355 is not set
++# CONFIG_ARCH_DAVINCI_DM646x is not set
+ CONFIG_ARCH_DAVINCI_DA830=y
+ CONFIG_ARCH_DAVINCI_DA850=y
++CONFIG_ARCH_DAVINCI_DA8XX=y
++# CONFIG_ARCH_DAVINCI_DM365 is not set
++# CONFIG_ARCH_DAVINCI_TNETV107X is not set
++
++#
++# DaVinci Board Type
++#
++CONFIG_MACH_DAVINCI_DA830_EVM=y
++CONFIG_DA830_UI_LCD=y
++# CONFIG_DA830_UI_NAND is not set
++CONFIG_MACH_DAVINCI_DA850_EVM=y
++CONFIG_DA850_UI_NONE=y
++# CONFIG_DA850_UI_RMII is not set
++# CONFIG_DA850_UI_SD_VIDEO_PORT is not set
++# CONFIG_DA850_WL12XX is not set
++CONFIG_GPIO_PCA953X=y
++CONFIG_KEYBOARD_GPIO_POLLED=y
+ CONFIG_MACH_MITYOMAPL138=y
+ CONFIG_MACH_OMAPL138_HAWKBOARD=y
++CONFIG_DAVINCI_MUX=y
++# CONFIG_DAVINCI_MUX_DEBUG is not set
++# CONFIG_DAVINCI_MUX_WARNINGS is not set
+ CONFIG_DAVINCI_RESET_CLOCKS=y
+-CONFIG_NO_HZ=y
+-CONFIG_HIGH_RES_TIMERS=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_LEGACY=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
++CONFIG_CPU_USE_DOMAINS=y
++
++#
++# Processor Features
++#
++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++CONFIG_CPU_DCACHE_WRITETHROUGH=y
++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
++# CONFIG_CACHE_L2X0 is not set
++CONFIG_ARM_L1_CACHE_SHIFT=5
++CONFIG_ARM_NR_BANKS=8
++CONFIG_TI_PRIV_EDMA=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++CONFIG_ARCH_NR_GPIO=0
++# CONFIG_PREEMPT_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
+ CONFIG_PREEMPT=y
++CONFIG_PREEMPT_COUNT=y
++CONFIG_HZ=100
+ CONFIG_AEABI=y
+ # CONFIG_OABI_COMPAT is not set
+-CONFIG_LEDS=y
++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_HAVE_ARCH_PFN_VALID=y
++# CONFIG_HIGHMEM is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_HAVE_MEMBLOCK=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=999999
++CONFIG_COMPACTION=y
++CONFIG_MIGRATION=y
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_CROSS_MEMORY_ATTACH=y
++CONFIG_NEED_PER_CPU_KM=y
++# CONFIG_CLEANCACHE is not set
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++# CONFIG_SECCOMP is not set
++# CONFIG_CC_STACKPROTECTOR is not set
++
++#
++# Boot options
++#
++# CONFIG_USE_OF is not set
++CONFIG_ATAGS=y
++# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++
++#
++# CPU Frequency scaling
++#
+ CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++CONFIG_CPU_FREQ_STAT=y
++# CONFIG_CPU_FREQ_STAT_DETAILS is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+ CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+ CONFIG_CPU_FREQ_GOV_PERFORMANCE=m
+ CONFIG_CPU_FREQ_GOV_POWERSAVE=m
++CONFIG_CPU_FREQ_GOV_USERSPACE=y
+ CONFIG_CPU_FREQ_GOV_ONDEMAND=m
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
++
++#
++# ARM CPU frequency scaling drivers
++#
++# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+ CONFIG_CPU_IDLE=y
++CONFIG_CPU_IDLE_GOV_LADDER=y
++CONFIG_CPU_IDLE_GOV_MENU=y
++# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++# CONFIG_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
++CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++CONFIG_COREDUMP=y
++
++#
++# Power management options
++#
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++CONFIG_PM_SLEEP=y
++# CONFIG_PM_AUTOSLEEP is not set
++# CONFIG_PM_WAKELOCKS is not set
++# CONFIG_PM_RUNTIME is not set
++CONFIG_PM=y
++# CONFIG_PM_DEBUG is not set
++# CONFIG_APM_EMULATION is not set
++CONFIG_PM_CLK=y
++CONFIG_CPU_PM=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_ARM_CPU_SUSPEND=y
+ CONFIG_NET=y
++
++#
++# Networking options
++#
+ CONFIG_PACKET=y
++# CONFIG_PACKET_DIAG is not set
+ CONFIG_UNIX=y
++# CONFIG_UNIX_DIAG is not set
++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 is not set
+ CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
+ 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_DEMUX is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_NET_IPVTI 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_INET_UDP_DIAG is not set
++# 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_SIT_6RD is not set
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_GRE is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+ CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_ACCT is not set
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_XTABLES is not set
++# CONFIG_IP_VS is not set
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV4 is not set
++# CONFIG_IP_NF_QUEUE is not set
++# CONFIG_IP_NF_IPTABLES is not set
++# CONFIG_IP_NF_ARPTABLES is not set
++
++#
++# IPv6: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV6 is not set
++# CONFIG_IP6_NF_IPTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_L2TP is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_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
++# CONFIG_BATMAN_ADV is not set
++# CONFIG_OPENVSWITCH is not set
++CONFIG_BQL=y
++# CONFIG_BPF_JIT is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++# CONFIG_LIB80211 is not set
++
++#
++# CFG80211 needs to be enabled for MAC80211
++#
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_RFKILL_REGULATOR is not set
++# CONFIG_NET_9P is not set
++# CONFIG_CAIF is not set
++# CONFIG_CEPH_LIB is not set
++# CONFIG_NFC is not set
++CONFIG_HAVE_BPF_JIT=y
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
+ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++# CONFIG_DEVTMPFS is not set
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
+ # CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_GENERIC_CPU_DEVICES is not set
++CONFIG_REGMAP=y
++CONFIG_REGMAP_I2C=y
++CONFIG_REGMAP_SPI=y
++# CONFIG_DMA_SHARED_BUFFER is not set
++# CONFIG_CMA is not set
++
++#
++# Bus devices
++#
++# CONFIG_OMAP_OCP2SCP is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=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 is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_SM_FTL is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# 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=y
++CONFIG_M25PXX_USE_FAST_READ=y
++# CONFIG_MTD_SST25L is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOCG3 is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++# 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=m
++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++
++#
++# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
++#
++# CONFIG_BLK_DEV_NBD is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=1
+ 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_BLK_DEV_RBD is not set
++
++#
++# Misc devices
++#
++# CONFIG_SENSORS_LIS3LV02D is not set
++# CONFIG_AD525X_DPOT is not set
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_APDS9802ALS is not set
++# CONFIG_ISL29003 is not set
++# CONFIG_ISL29020 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_SENSORS_BH1780 is not set
++# CONFIG_SENSORS_BH1770 is not set
++# CONFIG_SENSORS_APDS990X is not set
++# CONFIG_HMC6352 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_TI_DAC7512 is not set
++# CONFIG_BMP085_I2C is not set
++# CONFIG_BMP085_SPI is not set
++# CONFIG_USB_SWITCH_FSA9480 is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
+ CONFIG_EEPROM_AT24=y
++# 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_EEPROM_93XX46 is not set
++
++#
++# Texas Instruments shared transport line discipline
++#
++# CONFIG_TI_ST is not set
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_LIS3_I2C is not set
++
++#
++# Altera FPGA firmware download module
++#
++# CONFIG_ALTERA_STAPL is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=m
++# 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 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
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_ISCSI_BOOT_SYSFS is not set
++# CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
++# CONFIG_SCSI_DEBUG is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_TARGET_CORE is not set
+ CONFIG_NETDEVICES=y
+-CONFIG_TUN=m
+-CONFIG_LXT_PHY=y
+-CONFIG_LSI_ET1011C_PHY=y
+-CONFIG_NET_ETHERNET=y
++CONFIG_NET_CORE=y
++# CONFIG_BONDING is not set
++# CONFIG_DUMMY is not set
++# CONFIG_EQUALIZER is not set
+ CONFIG_MII=y
+-CONFIG_TI_DAVINCI_EMAC=y
+-# CONFIG_NETDEV_1000 is not set
+-# CONFIG_NETDEV_10000 is not set
++# CONFIG_NET_TEAM is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_VXLAN is not set
+ CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
+ CONFIG_NETPOLL_TRAP=y
++CONFIG_NET_POLL_CONTROLLER=y
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++
++#
++# CAIF transport drivers
++#
++CONFIG_ETHERNET=y
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++CONFIG_NET_VENDOR_CHELSIO=y
++CONFIG_NET_VENDOR_CIRRUS=y
++# CONFIG_CS89x0 is not set
++# CONFIG_DM9000 is not set
++# CONFIG_DNET is not set
++CONFIG_NET_VENDOR_FARADAY=y
++# CONFIG_FTMAC100 is not set
++# CONFIG_FTGMAC100 is not set
++CONFIG_NET_VENDOR_INTEL=y
++CONFIG_NET_VENDOR_I825XX=y
++CONFIG_NET_VENDOR_MARVELL=y
++CONFIG_NET_VENDOR_MICREL=y
++# CONFIG_KS8842 is not set
++# CONFIG_KS8851 is not set
++# CONFIG_KS8851_MLL is not set
++CONFIG_NET_VENDOR_MICROCHIP=y
++# CONFIG_ENC28J60 is not set
++CONFIG_NET_VENDOR_NATSEMI=y
++CONFIG_NET_VENDOR_8390=y
++# CONFIG_AX88796 is not set
++# CONFIG_ETHOC is not set
++CONFIG_NET_VENDOR_SEEQ=y
++# CONFIG_SEEQ8005 is not set
++CONFIG_NET_VENDOR_SMSC=y
++# CONFIG_SMC91X is not set
++# CONFIG_SMC911X is not set
++# CONFIG_SMSC911X is not set
++CONFIG_NET_VENDOR_STMICRO=y
++# CONFIG_STMMAC_ETH is not set
++CONFIG_NET_VENDOR_TI=y
++CONFIG_TI_DAVINCI_EMAC=y
++CONFIG_TI_DAVINCI_MDIO=y
++CONFIG_TI_DAVINCI_CPDMA=y
++# CONFIG_TI_CPSW is not set
++CONFIG_NET_VENDOR_WIZNET=y
++# CONFIG_WIZNET_W5100 is not set
++# CONFIG_WIZNET_W5300 is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_AMD_PHY is not set
++# CONFIG_MARVELL_PHY is not set
++# CONFIG_DAVICOM_PHY is not set
++# CONFIG_QSEMI_PHY is not set
++CONFIG_LXT_PHY=y
++# 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_BCM87XX_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=y
++# CONFIG_MICREL_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++# CONFIG_MICREL_KS8995MA is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++CONFIG_WLAN=y
++# CONFIG_HOSTAP is not set
++# CONFIG_WL_TI is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++CONFIG_INPUT_POLLDEV=y
++# CONFIG_INPUT_SPARSEKMAP is not set
++# CONFIG_INPUT_MATRIXKMAP 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 is not set
+ CONFIG_INPUT_EVDEV=m
+ CONFIG_INPUT_EVBUG=m
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ADP5588 is not set
++# CONFIG_KEYBOARD_ADP5589 is not set
+ CONFIG_KEYBOARD_ATKBD=m
++# CONFIG_KEYBOARD_QT1070 is not set
++# CONFIG_KEYBOARD_QT2160 is not set
++# CONFIG_KEYBOARD_LKKBD is not set
+ CONFIG_KEYBOARD_GPIO=y
++# CONFIG_KEYBOARD_TCA6416 is not set
++# CONFIG_KEYBOARD_TCA8418 is not set
++# CONFIG_KEYBOARD_MATRIX is not set
++# CONFIG_KEYBOARD_LM8333 is not set
++# CONFIG_KEYBOARD_MAX7359 is not set
++# CONFIG_KEYBOARD_MCS is not set
++# CONFIG_KEYBOARD_MPR121 is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_SAMSUNG is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_OMAP4 is not set
+ CONFIG_KEYBOARD_XTKBD=m
+ # CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_ADS7846 is not set
++# CONFIG_TOUCHSCREEN_AD7877 is not set
++# CONFIG_TOUCHSCREEN_AD7879 is not set
++# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
++# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_BU21013 is not set
++# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
++# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
++# CONFIG_TOUCHSCREEN_DYNAPRO is not set
++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
++# CONFIG_TOUCHSCREEN_EETI is not set
++# CONFIG_TOUCHSCREEN_EGALAX is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_ILI210X is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
++# CONFIG_TOUCHSCREEN_MAX11801 is not set
++# CONFIG_TOUCHSCREEN_MCS5000 is not set
++# CONFIG_TOUCHSCREEN_MMS114 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_EDT_FT5X06 is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
++# CONFIG_TOUCHSCREEN_TSC2005 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
++# CONFIG_TOUCHSCREEN_ST1232 is not set
++# CONFIG_TOUCHSCREEN_TPS6507X is not set
++# CONFIG_INPUT_MISC 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_SERIO_ALTERA_PS2 is not set
++# CONFIG_SERIO_PS2MULT is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
+ # CONFIG_VT_CONSOLE is not set
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++# CONFIG_TRACE_SINK is not set
++CONFIG_DEVKMEM=y
++
++#
++# Serial drivers
++#
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++# CONFIG_SERIAL_8250_EM is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++# CONFIG_SERIAL_MAX310X is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_SCCNXP is not set
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++# CONFIG_SERIAL_IFX6X60 is not set
++# CONFIG_SERIAL_XILINX_PS_UART is not set
++# CONFIG_TTY_PRINTK is not set
++# CONFIG_HVC_DCC is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
++# CONFIG_HW_RANDOM_ATMEL is not set
++# CONFIG_HW_RANDOM_EXYNOS 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_COMPAT=y
+ CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_MUX is not set
++CONFIG_I2C_HELPER_AUTO=y
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
+ CONFIG_I2C_DAVINCI=y
++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_PXA_PCI is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_XILINX is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ALTERA is not set
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_DAVINCI=y
++# CONFIG_SPI_GPIO is not set
++# CONFIG_SPI_OC_TINY is not set
++# CONFIG_SPI_PXA2XX_PCI is not set
++# CONFIG_SPI_SC18IS602 is not set
++# CONFIG_SPI_XCOMM is not set
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_HSI is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++
++#
++# PPS generators support
++#
++
++#
++# PTP clock support
++#
++
++#
++# Enable Device Drivers -> PPS to see the PTP clock options.
++#
++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++# CONFIG_DEBUG_GPIO is not set
++# CONFIG_GPIO_SYSFS is not set
++
++#
++# Memory mapped GPIO drivers:
++#
++# CONFIG_GPIO_GENERIC_PLATFORM is not set
++# CONFIG_GPIO_EM is not set
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX7300 is not set
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X_IRQ is not set
++CONFIG_GPIO_PCF857X=y
++# CONFIG_GPIO_SX150X is not set
++# CONFIG_GPIO_ADP5588 is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_GPIO_MC33880 is not set
++# CONFIG_GPIO_74X164 is not set
++
++#
++# AC97 GPIO expanders:
++#
++
++#
++# MODULbus GPIO expanders:
++#
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_POWER_AVS is not set
+ # CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
+ CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_CORE is not set
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_DW_WATCHDOG is not set
++# CONFIG_DAVINCI_WATCHDOG is not set
++# CONFIG_MAX63XX_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++CONFIG_BCMA_POSSIBLE=y
++
++#
++# Broadcom specific AMBA
++#
++# CONFIG_BCMA is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_88PM860X is not set
++# CONFIG_MFD_88PM800 is not set
++# CONFIG_MFD_88PM805 is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_HTC_I2CPLD is not set
++# CONFIG_MFD_LM3533 is not set
++# CONFIG_TPS6105X is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_TPS6507X is not set
++# CONFIG_MFD_TPS65217 is not set
++# CONFIG_MFD_TPS6586X is not set
++# CONFIG_MFD_TPS65910 is not set
++# CONFIG_MFD_TPS65912_I2C is not set
++# CONFIG_MFD_TPS65912_SPI is not set
++# CONFIG_TWL4030_CORE is not set
++# CONFIG_TWL6040_CORE is not set
++# CONFIG_MFD_STMPE is not set
++# CONFIG_MFD_TC3589X is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_SMSC is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_DA9052_SPI is not set
++# CONFIG_MFD_DA9052_I2C is not set
++# CONFIG_MFD_DA9055 is not set
++# CONFIG_PMIC_ADP5520 is not set
++# CONFIG_MFD_LP8788 is not set
++# CONFIG_MFD_MAX77686 is not set
++# CONFIG_MFD_MAX77693 is not set
++# CONFIG_MFD_MAX8907 is not set
++# CONFIG_MFD_MAX8925 is not set
++# CONFIG_MFD_MAX8997 is not set
++# CONFIG_MFD_MAX8998 is not set
++# CONFIG_MFD_SEC_CORE is not set
++# CONFIG_MFD_ARIZONA_I2C is not set
++# CONFIG_MFD_ARIZONA_SPI is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM831X_I2C is not set
++# CONFIG_MFD_WM831X_SPI is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_WM8994 is not set
++# CONFIG_MFD_PCF50633 is not set
++# CONFIG_MFD_MC13XXX_SPI is not set
++# CONFIG_MFD_MC13XXX_I2C is not set
++# CONFIG_ABX500_CORE is not set
++# CONFIG_EZX_PCAP is not set
++# CONFIG_MFD_WL1273_CORE is not set
++# CONFIG_MFD_TPS65090 is not set
++# CONFIG_MFD_AAT2870_CORE is not set
++# CONFIG_MFD_RC5T583 is not set
++# CONFIG_MFD_PALMAS is not set
+ CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
+ CONFIG_REGULATOR_DUMMY=y
++# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
++# CONFIG_REGULATOR_GPIO is not set
++# CONFIG_REGULATOR_AD5398 is not set
++# CONFIG_REGULATOR_FAN53555 is not set
++# CONFIG_REGULATOR_ISL6271A is not set
++# CONFIG_REGULATOR_MAX1586 is not set
++# CONFIG_REGULATOR_MAX8649 is not set
++# CONFIG_REGULATOR_MAX8660 is not set
++# CONFIG_REGULATOR_MAX8952 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS62360 is not set
++# CONFIG_REGULATOR_TPS65023 is not set
+ CONFIG_REGULATOR_TPS6507X=y
++# CONFIG_REGULATOR_TPS6524X is not set
++# CONFIG_MEDIA_SUPPORT is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_WMT_GE_ROPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
+ CONFIG_FB_DA8XX=y
+-# CONFIG_VGA_CONSOLE is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_AUO_K190X is not set
++# CONFIG_FB_ST7735 is not set
++# CONFIG_EXYNOS_VIDEO is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Console display driver support
++#
++CONFIG_DUMMY_CONSOLE=y
+ CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++# CONFIG_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
+ CONFIG_LOGO=y
+-CONFIG_SOUND=m
+-CONFIG_SND=m
+-CONFIG_SND_SOC=m
+-CONFIG_SND_DAVINCI_SOC=m
+-# CONFIG_HID_SUPPORT is not set
++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_COMPRESS_OFFLOAD=y
++CONFIG_SND_JACK=y
++# CONFIG_SND_SEQUENCER is not set
++# CONFIG_SND_MIXER_OSS is not set
++# CONFIG_SND_PCM_OSS is not set
++# CONFIG_SND_HRTIMER is not set
++# CONFIG_SND_DYNAMIC_MINORS is not set
++CONFIG_SND_SUPPORT_OLD_API=y
++CONFIG_SND_VERBOSE_PROCFS=y
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++# CONFIG_SND_RAWMIDI_SEQ is not set
++# CONFIG_SND_OPL3_LIB_SEQ is not set
++# CONFIG_SND_OPL4_LIB_SEQ is not set
++# CONFIG_SND_SBAWE_SEQ is not set
++# CONFIG_SND_EMU10K1_SEQ is not set
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_ALOOP is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++CONFIG_SND_ARM=y
++CONFIG_SND_SPI=y
++CONFIG_SND_SOC=y
++CONFIG_SND_DAVINCI_SOC=y
++CONFIG_SND_DAVINCI_SOC_MCASP=y
++# CONFIG_SND_DA830_SOC_EVM is not set
++CONFIG_SND_DA850_SOC_EVM=y
++# CONFIG_SND_DESIGNWARE_I2S is not set
++CONFIG_SND_SOC_I2C_AND_SPI=y
++# CONFIG_SND_SOC_ALL_CODECS is not set
++CONFIG_SND_SOC_TLV320AIC3X=y
++# CONFIG_SND_SIMPLE_CARD is not set
++# CONFIG_SOUND_PRIME is not set
++
++#
++# HID support
++#
++CONFIG_HID=y
++# CONFIG_HIDRAW is not set
++# CONFIG_UHID is not set
++CONFIG_HID_GENERIC=y
++
++#
++# Special HID drivers
++#
++CONFIG_USB_ARCH_HAS_OHCI=y
++# CONFIG_USB_ARCH_HAS_EHCI is not set
++# CONFIG_USB_ARCH_HAS_XHCI is not set
+ # CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_UNSAFE_RESUME=y
++# CONFIG_MMC_CLKGATE is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_MINORS=8
++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_SDHCI_PXAV3 is not set
++# CONFIG_MMC_SDHCI_PXAV2 is not set
++CONFIG_MMC_DAVINCI=y
++# CONFIG_MMC_SPI is not set
++# CONFIG_MMC_DW is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_DS3232 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_ISL12022 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_BQ32K is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
++# CONFIG_RTC_DRV_EM3027 is not set
++# CONFIG_RTC_DRV_RV3029C2 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T93 is not set
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++# CONFIG_RTC_DRV_PCF2123 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_MSM6242 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_RP5C01 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++# CONFIG_RTC_DRV_DS2404 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_OMAP=y
++CONFIG_DMADEVICES=y
++# CONFIG_DMADEVICES_DEBUG is not set
++
++#
++# DMA Devices
++#
++# CONFIG_DW_DMAC is not set
++# CONFIG_TIMB_DMA is not set
++CONFIG_TI_EDMA=y
++CONFIG_DMA_ENGINE=y
++CONFIG_DMA_VIRTUAL_CHANNELS=y
++
++#
++# DMA Clients
++#
++# CONFIG_NET_DMA is not set
++# CONFIG_ASYNC_TX_DMA is not set
++# CONFIG_DMATEST is not set
++# CONFIG_AUXDISPLAY is not set
++CONFIG_UIO=y
++# CONFIG_UIO_PDRV is not set
++# CONFIG_UIO_PDRV_GENIRQ is not set
++CONFIG_UIO_PRUSS=y
++
++#
++# Virtio drivers
++#
++# CONFIG_VIRTIO_MMIO is not set
++
++#
++# Microsoft Hyper-V guest support
++#
++# CONFIG_STAGING is not set
++CONFIG_CLKDEV_LOOKUP=y
++
++#
++# Hardware Spinlock drivers
++#
++CONFIG_IOMMU_SUPPORT=y
++
++#
++# Remoteproc drivers (EXPERIMENTAL)
++#
++# CONFIG_STE_MODEM_RPROC is not set
++
++#
++# Rpmsg drivers (EXPERIMENTAL)
++#
++# CONFIG_VIRT_DRIVERS is not set
++# CONFIG_PM_DEVFREQ is not set
++# CONFIG_EXTCON is not set
++# CONFIG_MEMORY is not set
++# CONFIG_IIO is not set
++# CONFIG_PWM 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=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
+ CONFIG_XFS_FS=m
+-CONFIG_INOTIFY=y
++# 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_BTRFS_FS is not set
++# CONFIG_NILFS2_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_EXPORTFS=m
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_FANOTIFY is not set
++# CONFIG_QUOTA is not set
++# CONFIG_QUOTACTL is not set
+ CONFIG_AUTOFS4_FS=m
++# 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_TMPFS_XATTR 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_LOGFS is not set
+ CONFIG_CRAMFS=y
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
+ CONFIG_MINIX_FS=m
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX6FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_PSTORE 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_V2=y
+ CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_SWAP is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFSD=m
+ CONFIG_NFSD_V3=y
+-CONFIG_SMB_FS=m
+-CONFIG_PARTITION_ADVANCED=y
++# CONFIG_NFSD_V3_ACL is not set
++# CONFIG_NFSD_V4 is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_DEBUG is not set
++# CONFIG_CEPH_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++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=m
+ 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_MAC_ROMAN is not set
++# CONFIG_NLS_MAC_CELTIC is not set
++# CONFIG_NLS_MAC_CENTEURO is not set
++# CONFIG_NLS_MAC_CROATIAN is not set
++# CONFIG_NLS_MAC_CYRILLIC is not set
++# CONFIG_NLS_MAC_GAELIC is not set
++# CONFIG_NLS_MAC_GREEK is not set
++# CONFIG_NLS_MAC_ICELAND is not set
++# CONFIG_NLS_MAC_INUIT is not set
++# CONFIG_NLS_MAC_ROMANIAN is not set
++# CONFIG_NLS_MAC_TURKISH is not set
+ CONFIG_NLS_UTF8=m
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_READABLE_ASM is not set
++# CONFIG_UNUSED_SYMBOLS is not set
+ CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_SECTION_MISMATCH is not set
+ CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_LOCKUP_DETECTOR is not set
++# CONFIG_PANIC_ON_OOPS is not set
++CONFIG_PANIC_ON_OOPS_VALUE=0
++# CONFIG_DETECT_HUNG_TASK is not set
++CONFIG_SCHED_DEBUG=y
++# CONFIG_SCHEDSTATS is not set
+ CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_HAVE_DEBUG_KMEMLEAK=y
++# CONFIG_DEBUG_KMEMLEAK is not set
++CONFIG_DEBUG_PREEMPT=y
+ CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_PI_LIST=y
++# CONFIG_RT_MUTEX_TESTER is not set
++# CONFIG_DEBUG_SPINLOCK is not set
+ CONFIG_DEBUG_MUTEXES=y
+-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_PROVE_RCU_DELAY is not set
++# CONFIG_SPARSE_RCU_POINTER is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_ATOMIC_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++# CONFIG_DEBUG_STACK_USAGE is not set
++# 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_TEST_LIST_SORT is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++# CONFIG_DEBUG_CREDENTIALS is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_TRACE is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
++# CONFIG_LKDTM is not set
++# CONFIG_NOTIFIER_ERROR_INJECTION is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
++CONFIG_HAVE_DYNAMIC_FTRACE=y
++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
++CONFIG_HAVE_C_RECORDMCOUNT=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_FTRACE_SYSCALLS 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_BLK_DEV_IO_TRACE is not set
++# CONFIG_PROBE_EVENTS is not set
++# CONFIG_RBTREE_TEST is not set
++# CONFIG_INTERVAL_TREE_TEST is not set
++# CONFIG_DYNAMIC_DEBUG is not set
++# CONFIG_DMA_API_DEBUG is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++# CONFIG_TEST_KSTRTOX is not set
++# CONFIG_STRICT_DEVMEM is not set
++CONFIG_ARM_UNWIND=y
+ CONFIG_DEBUG_USER=y
+-CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_LL is not set
++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY_DMESG_RESTRICT is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_USER is not set
++# 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 is not set
++# 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
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# 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_SHA1_ARM 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_AES_ARM 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 is not set
++# 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_USER_API_HASH is not set
++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+ # CONFIG_CRYPTO_HW is not set
++# CONFIG_BINARY_PRINTF is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_STRNCPY_FROM_USER=y
++CONFIG_GENERIC_STRNLEN_USER=y
++CONFIG_GENERIC_PCI_IOMAP=y
++CONFIG_GENERIC_IO=y
+ CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
+ CONFIG_CRC_T10DIF=m
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC32_SELFTEST is not set
++CONFIG_CRC32_SLICEBY8=y
++# CONFIG_CRC32_SLICEBY4 is not set
++# CONFIG_CRC32_SARWATE is not set
++# CONFIG_CRC32_BIT is not set
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++# CONFIG_CRC8 is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++# CONFIG_XZ_DEC is not set
++# CONFIG_XZ_DEC_BCJ is not set
++CONFIG_DECOMPRESS_GZIP=y
++CONFIG_GENERIC_ALLOCATOR=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_DQL=y
++CONFIG_NLATTR=y
++CONFIG_GENERIC_ATOMIC64=y
++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
++# CONFIG_AVERAGE is not set
++# CONFIG_CORDIC is not set
++# CONFIG_DDR is not set
diff --git a/patches/linux-3.7/0030-misc-gpevt-null-terminate-the-of_match_table.patch b/patches/linux-3.7/0030-misc-gpevt-null-terminate-the-of_match_table.patch
new file mode 100644
index 0000000..eb61b79
--- /dev/null
+++ b/patches/linux-3.7/0030-misc-gpevt-null-terminate-the-of_match_table.patch
@@ -0,0 +1,21 @@
+From: Matt Porter <mporter@ti.com>
+Date: Thu, 18 Oct 2012 10:29:57 -0400
+Subject: [PATCH] misc: gpevt: null terminate the of_match_table
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ drivers/misc/gpevt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
+index 4fe256c..c0cc1a2 100644
+--- a/drivers/misc/gpevt.c
++++ b/drivers/misc/gpevt.c
+@@ -139,6 +139,7 @@ static int __devexit gpevt_remove(struct platform_device *pdev)
+
+ static const struct of_device_id gpevt_dt_ids[] = {
+ { .compatible = "gpevt", .data = (void *) NULL, },
++ { },
+ };
+ MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
+
diff --git a/patches/linux-3.7/0031-proposed-probe-fix-works-for-me-on-evm.patch b/patches/linux-3.7/0031-proposed-probe-fix-works-for-me-on-evm.patch
new file mode 100644
index 0000000..3ba2b8f
--- /dev/null
+++ b/patches/linux-3.7/0031-proposed-probe-fix-works-for-me-on-evm.patch
@@ -0,0 +1,42 @@
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 19 Oct 2012 11:24:40 -0400
+Subject: [PATCH] proposed probe fix - works for me on evm
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+---
+ arch/arm/common/edma.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
+index b761b7a..6ed394f 100644
+--- a/arch/arm/common/edma.c
++++ b/arch/arm/common/edma.c
+@@ -1598,6 +1598,8 @@ static struct of_dma_filter_info edma_filter_info = {
+ static int __init edma_probe(struct platform_device *pdev)
+ {
+ struct edma_soc_info **info = pdev->dev.platform_data;
++ struct edma_soc_info *ninfo[EDMA_MAX_CC] = {NULL, NULL};
++ struct edma_soc_info tmpinfo;
+ s8 (*queue_priority_mapping)[2];
+ s8 (*queue_tc_mapping)[2];
+ int i, j, off, ln, found = 0;
+@@ -1614,15 +1616,13 @@ static int __init edma_probe(struct platform_device *pdev)
+ char irq_name[10];
+ struct device_node *node = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+- struct edma_soc_info *pdata;
+ int ret;
+
+ if (node) {
+- pdata = devm_kzalloc(dev,
+- sizeof(struct edma_soc_info),
+- GFP_KERNEL);
+- edma_of_parse_dt(dev, node, pdata);
+- info = &pdata;
++ info = ninfo;
++ edma_of_parse_dt(dev, node, &tmpinfo);
++ info[0] = &tmpinfo;
++
+ dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
+ of_dma_controller_register(dev->of_node,
+ of_dma_simple_xlate,
diff --git a/patches/linux-3.7/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch b/patches/linux-3.7/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
new file mode 100644
index 0000000..0202d23
--- /dev/null
+++ b/patches/linux-3.7/0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
@@ -0,0 +1,79 @@
+From: Mugunthan V N <mugunthanvnm@ti.com>
+Date: Tue, 5 Jun 2012 13:18:01 +0530
+Subject: [PATCH] ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio
+
+This patch adds minimal hwmod support for davinci mdio driver. This patch
+requires rework on parent child relation between cpsw and davinci mdio
+hwmod data to support runtime PM.
+
+Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 34 ++++++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 59d5c1c..f96bbc0 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -650,8 +650,7 @@ static struct omap_hwmod_class_sysconfig am33xx_cpgmac_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x8,
+ .syss_offs = 0x4,
+- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+- SYSS_HAS_RESET_STATUS),
++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+ MSTANDBY_NO),
+ .sysc_fields = &omap_hwmod_sysc_type3,
+@@ -682,6 +681,8 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
++ HWMOD_INIT_NO_RESET | HWMOD_INIT_NO_IDLE),
+ };
+
+ /*
+@@ -2510,6 +2511,34 @@ static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
+ { }
+ };
+
++/* mdio class */
++static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
++ .name = "davinci_mdio",
++};
++
++struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
++ {
++ .pa_start = 0x4A101000,
++ .pa_end = 0x4A101000 + SZ_256 - 1,
++ .flags = ADDR_MAP_ON_INIT,
++ },
++ { }
++};
++
++static struct omap_hwmod am33xx_mdio_hwmod = {
++ .name = "davinci_mdio",
++ .class = &am33xx_mdio_hwmod_class,
++ .clkdm_name = "cpsw_125mhz_clkdm",
++ .main_clk = "cpsw_125mhz_gclk",
++};
++
++struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
++ .master = &am33xx_cpgmac0_hwmod,
++ .slave = &am33xx_mdio_hwmod,
++ .addr = am33xx_mdio_addr_space,
++ .user = OCP_USER_MPU,
++};
++
+ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am33xx_elm_hwmod,
+@@ -3371,6 +3400,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+ &am33xx_l3_main__tptc2,
+ &am33xx_l3_s__usbss,
+ &am33xx_l4_hs__cpgmac0,
++ &am33xx_cpgmac0__mdio,
+ NULL,
+ };
+
diff --git a/patches/linux-3.7/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch b/patches/linux-3.7/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
new file mode 100644
index 0000000..69872f5
--- /dev/null
+++ b/patches/linux-3.7/0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
@@ -0,0 +1,34 @@
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Mon, 3 Sep 2012 21:14:52 +0530
+Subject: [PATCH] net: davinci_mdio: Fix type mistake in calling runtime-pm
+ api
+
+By mistake (most likely a copy-paste), instead of pm_runtime_get_sync()
+api, driver is calling pm_runtime_put_sync() api in resume callback
+function. The bug was introduced by commit id (ae2c07aaf74:
+davinci_mdio: runtime PM support).
+
+Now, the reason why it didn't impact functionality is, the patch has
+been tested on AM335x-EVM and BeagleBone platform while submitting;
+and in case of AM335x the MDIO driver doesn't control the module
+enable/disable part, which is handled by CPSW driver.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+Cc: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ drivers/net/ethernet/ti/davinci_mdio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
+index 51a96db..ae74280 100644
+--- a/drivers/net/ethernet/ti/davinci_mdio.c
++++ b/drivers/net/ethernet/ti/davinci_mdio.c
+@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
+ u32 ctrl;
+
+ spin_lock(&data->lock);
+- pm_runtime_put_sync(data->dev);
++ pm_runtime_get_sync(data->dev);
+
+ /* restart the scan state machine */
+ ctrl = __raw_readl(&data->regs->control);
diff --git a/patches/linux-3.7/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch b/patches/linux-3.7/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
new file mode 100644
index 0000000..a25eaac
--- /dev/null
+++ b/patches/linux-3.7/0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
@@ -0,0 +1,86 @@
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Mon, 3 Sep 2012 21:25:38 +0530
+Subject: [PATCH] net: cpsw: Add parent<->child relation support between cpsw
+ and mdio
+
+CPGMAC SubSystem consist of various sub-modules, like, mdio, cpdma,
+cpsw, etc... These sub-modules are also used in some of Davinci family
+of devices. Now based on requirement, use-case and available technology
+nodes the integration of these sub-modules varies across devices.
+
+So coming back to Linux net driver, currently separate and independent
+platform devices & drivers for CPSW and MDIO is implemented. In case of
+Davinci they both has separate control, from resources perspective,
+like clock.
+
+In case of AM33XX, the resources are shared and only one register
+bit-field is provided to control module/clock enable/disable, makes it
+difficult to handle common resource.
+
+So the solution here implemented in this patch is,
+
+Create parent<->child relationship between both the drivers, making
+CPSW as a parent and MDIO as its child and enumerate all the child nodes
+under cpsw module.
+Both the drivers will function exactly the way it was operating before,
+including runtime-pm functionality. No change is required in MDIO driver
+(for that matter to any child driver).
+
+As this is only supported during DT boot, the parent<->child relationship
+is created and populated in DT execution flow. The only required change
+is inside DTS file, making MDIO as a child to CPSW node.
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+Cc: Mugunthan V N <mugunthanvnm@ti.com>
+---
+ drivers/net/ethernet/ti/cpsw.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
+index df55e24..fb1a692 100644
+--- a/drivers/net/ethernet/ti/cpsw.c
++++ b/drivers/net/ethernet/ti/cpsw.c
+@@ -827,7 +827,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ }
+ data->mac_control = prop;
+
+- for_each_child_of_node(node, slave_node) {
++ for_each_node_by_name(slave_node, "slave") {
+ struct cpsw_slave_data *slave_data = data->slave_data + i;
+ const char *phy_id = NULL;
+ const void *mac_addr = NULL;
+@@ -862,6 +862,14 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
+ i++;
+ }
+
++ /*
++ * Populate all the child nodes here...
++ */
++ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
++ /* We do not want to force this, as in some cases may not have child */
++ if (ret)
++ pr_warn("Doesn't have any child node\n");
++
+ return 0;
+
+ error_ret:
+@@ -895,6 +903,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
+ priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+ priv->rx_packet_max = max(rx_packet_max, 128);
+
++ /*
++ * This may be required here for child devices.
++ */
++ pm_runtime_enable(&pdev->dev);
++
+ if (cpsw_probe_dt(&priv->data, pdev)) {
+ pr_err("cpsw: platform data missing\n");
+ ret = -ENODEV;
+@@ -921,7 +934,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
+ for (i = 0; i < data->slaves; i++)
+ priv->slaves[i].slave_num = i;
+
+- pm_runtime_enable(&pdev->dev);
+ priv->clk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(priv->clk)) {
+ dev_err(&pdev->dev, "fck is not found\n");
diff --git a/patches/linux-3.7/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch b/patches/linux-3.7/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
new file mode 100644
index 0000000..6b21ee5
--- /dev/null
+++ b/patches/linux-3.7/0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
@@ -0,0 +1,108 @@
+From: Mugunthan V N <mugunthanvnm@ti.com>
+Date: Sun, 29 Jul 2012 20:56:29 +0530
+Subject: [PATCH] arm/dts: am33xx: Add cpsw and mdio module nodes for AM33XX
+
+Add CPSW and MDIO related device tree data for AM33XX.
+Also enable them into board/evm dts files by providing
+respective phy-id.
+
+Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 8 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 66 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 2ad3914..47c17e8 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -137,3 +137,11 @@
+ &edma {
+ ti,edma-xbar-event-map = <32 12>;
+ };
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 8d5f660..23d1e26 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -133,3 +133,11 @@
+ reg = <0>;
+ };
+ };
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 063ecea..a6bfd9b 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -311,5 +311,55 @@
+ interrupt-parent = <&intc>;
+ interrupts = <91>;
+ };
++
++ mac: ethernet@4A100000 {
++ compatible = "ti,cpsw";
++ ti,hwmods = "cpgmac0";
++ cpdma_channels = <8>;
++ host_port_no = <0>;
++ cpdma_reg_ofs = <0x800>;
++ cpdma_sram_ofs = <0xa00>;
++ ale_reg_ofs = <0xd00>;
++ ale_entries = <1024>;
++ host_port_reg_ofs = <0x108>;
++ hw_stats_reg_ofs = <0x900>;
++ bd_ram_ofs = <0x2000>;
++ bd_ram_size = <0x2000>;
++ no_bd_ram = <0>;
++ rx_descs = <64>;
++ mac_control = <0x20>;
++ slaves = <2>;
++ reg = <0x4a100000 0x800
++ 0x4a101200 0x100
++ 0x4a101000 0x100>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++ interrupt-parent = <&intc>;
++ /* c0_rx_thresh_pend c0_rx_pend c0_tx_pend c0_misc_pend*/
++ interrupts = <40 41 42 43>;
++ ranges;
++ cpsw_emac0: slave@0 {
++ slave_reg_ofs = <0x208>;
++ sliver_reg_ofs = <0xd80>;
++ /* Filled in by U-Boot */
++ mac-address = [ 00 00 00 00 00 00 ];
++ };
++ cpsw_emac1: slave@1 {
++ slave_reg_ofs = <0x308>;
++ sliver_reg_ofs = <0xdc0>;
++ /* Filled in by U-Boot */
++ mac-address = [ 00 00 00 00 00 00 ];
++ };
++
++ davinci_mdio: mdio@4a101000 {
++ compatible = "ti,davinci_mdio";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ ti,hwmods = "davinci_mdio";
++ bus_freq = <1000000>;
++ reg = <0x4a101000 0x100>;
++ };
++
++ };
+ };
+ };
diff --git a/patches/linux-3.7/0038-i2c-pinctrl-ify-i2c-omap.c.patch b/patches/linux-3.7/0038-i2c-pinctrl-ify-i2c-omap.c.patch
new file mode 100644
index 0000000..dda67a6
--- /dev/null
+++ b/patches/linux-3.7/0038-i2c-pinctrl-ify-i2c-omap.c.patch
@@ -0,0 +1,45 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 14 Sep 2012 17:51:11 +0300
+Subject: [PATCH] i2c: pinctrl-ify i2c-omap.c
+
+Conflicts:
+ drivers/i2c/busses/i2c-omap.c
+---
+ drivers/i2c/busses/i2c-omap.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index 3525c9e..b4952b7 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -43,6 +43,8 @@
+ #include <linux/slab.h>
+ #include <linux/i2c-omap.h>
+ #include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ /* I2C controller revisions */
+ #define OMAP_I2C_OMAP1_REV_2 0x20
+@@ -1060,6 +1062,7 @@ omap_i2c_probe(struct platform_device *pdev)
+ const struct of_device_id *match;
+ int irq;
+ int r;
++ struct pinctrl *pinctrl;
+
+ /* NOTE: driver uses the static register mapping */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -1200,6 +1203,13 @@ omap_i2c_probe(struct platform_device *pdev)
+
+ of_i2c_register_devices(adap);
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(dev->dev, "unable to select pin group\n");
++
++ dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr,
++ dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
++
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
+
diff --git a/patches/linux-3.7/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch b/patches/linux-3.7/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
new file mode 100644
index 0000000..adb03e0
--- /dev/null
+++ b/patches/linux-3.7/0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
@@ -0,0 +1,69 @@
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Fri, 31 Aug 2012 09:29:18 +0000
+Subject: [PATCH] arm/dts: AM33XX: Configure pinmuxs for user leds control on
+ Bone
+
+Adds GPIO pinctrl nodes to am3358_pinmux master node to control
+user leds (USR0, USR1, USR2 and USR3) present on BeagleBone.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 38 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 47c17e8..3a089c0 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -38,6 +38,14 @@
+ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+ >;
+ };
++ userled_pins: pinmux_userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -45,6 +53,36 @@
+ status = "okay";
+ };
+
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&userled_pins>;
++
++ led0 {
++ label = "beaglebone:green:usr0";
++ gpios = <&gpio2 21 0>;
++ default-state = "off";
++ };
++
++ led1 {
++ label = "beaglebone:green:usr1";
++ gpios = <&gpio2 22 0>;
++ default-state = "off";
++ };
++
++ led2 {
++ label = "beaglebone:green:usr2";
++ gpios = <&gpio2 23 0>;
++ default-state = "off";
++ };
++
++ led3 {
++ label = "beaglebone:green:usr3";
++ gpios = <&gpio2 24 0>;
++ default-state = "off";
++ };
++ };
++
+ i2c1: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
diff --git a/patches/linux-3.7/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch b/patches/linux-3.7/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
new file mode 100644
index 0000000..8857338
--- /dev/null
+++ b/patches/linux-3.7/0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
@@ -0,0 +1,28 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 5 Sep 2012 09:49:21 +0200
+Subject: [PATCH] beaglebone DT: set default triggers for LEDS
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 3a089c0..63acfb4 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -61,12 +61,14 @@
+ led0 {
+ label = "beaglebone:green:usr0";
+ gpios = <&gpio2 21 0>;
++ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ led1 {
+ label = "beaglebone:green:usr1";
+ gpios = <&gpio2 22 0>;
++ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
diff --git a/patches/linux-3.7/0041-beaglebone-add-a-cpu-led-trigger.patch b/patches/linux-3.7/0041-beaglebone-add-a-cpu-led-trigger.patch
new file mode 100644
index 0000000..c1b2059
--- /dev/null
+++ b/patches/linux-3.7/0041-beaglebone-add-a-cpu-led-trigger.patch
@@ -0,0 +1,21 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 15 Oct 2012 16:53:28 +0200
+Subject: [PATCH] beaglebone: add a cpu led trigger
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 63acfb4..147bc01 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -75,6 +75,7 @@
+ led2 {
+ label = "beaglebone:green:usr2";
+ gpios = <&gpio2 23 0>;
++ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
diff --git a/patches/linux-3.7/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch b/patches/linux-3.7/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
new file mode 100644
index 0000000..f89a4c8
--- /dev/null
+++ b/patches/linux-3.7/0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
@@ -0,0 +1,78 @@
+From: "AnilKumar, Chimata" <anilkumar@ti.com>
+Date: Fri, 31 Aug 2012 09:37:20 +0000
+Subject: [PATCH] arm/dts: AM33XX: Add device tree OPP table
+
+Add DT OPP table for AM33XX family of devices. This data is
+decoded by OF with of_init_opp_table() helper function.
+
+Also adds cpu0 supply name to the corresponding dts files.
+cpu0-supply name is used by cpufreq-cpu0 driver to get the
+regulator pointer for voltage modifications.
+
+Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 6 ++++++
+ arch/arm/boot/dts/am335x-evm.dts | 6 ++++++
+ arch/arm/boot/dts/am33xx.dtsi | 15 +++++++++++++++
+ 3 files changed, 27 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 147bc01..87686e9 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -13,6 +13,12 @@
+ model = "TI AM335x BeagleBone";
+ compatible = "ti,am335x-bone", "ti,am33xx";
+
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&dcdc2_reg>;
++ };
++ };
++
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 23d1e26..43e23a8 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -13,6 +13,12 @@
+ model = "TI AM335x EVM";
+ compatible = "ti,am335x-evm", "ti,am33xx";
+
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&vdd1_reg>;
++ };
++ };
++
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256 MB */
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index a6bfd9b..9755276 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -25,6 +25,21 @@
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a8";
++
++ /*
++ * To consider voltage drop between PMIC and SoC,
++ * tolerance value is reduced to 2% from 4% and
++ * voltage value is increased as a precaution.
++ */
++ operating-points = <
++ /* kHz uV */
++ 720000 1285000
++ 600000 1225000
++ 500000 1125000
++ 275000 1125000
++ >;
++ voltage-tolerance = <2>; /* 2 percentage */
++ clock-latency = <300000>; /* From omap-cpufreq driver */
+ };
+ };
+
diff --git a/patches/linux-3.7/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch b/patches/linux-3.7/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
new file mode 100644
index 0000000..119174b
--- /dev/null
+++ b/patches/linux-3.7/0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
@@ -0,0 +1,24 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 6 Dec 2012 11:55:52 +0100
+Subject: [PATCH] am33xx DT: add commented out OPP values for ES2.0
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 9755276..ce429a0 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -33,6 +33,10 @@
+ */
+ operating-points = <
+ /* kHz uV */
++ /* ES 2.0 Nitro and Turbo OPPs"
++ 1000000 1350000
++ 800000 1300000
++ */
+ 720000 1285000
+ 600000 1225000
+ 500000 1125000
diff --git a/patches/linux-3.7/0046-input-TSC-ti_tscadc-Correct-register-usage.patch b/patches/linux-3.7/0046-input-TSC-ti_tscadc-Correct-register-usage.patch
new file mode 100644
index 0000000..f8ede3c
--- /dev/null
+++ b/patches/linux-3.7/0046-input-TSC-ti_tscadc-Correct-register-usage.patch
@@ -0,0 +1,225 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:38 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Correct register usage
+
+This patch cleans up the wrong register definitions
+and usage for touchscreen controller.
+Bit masks were not defined earlier.
+
+For ex: consider a register define as:
+write(xyz, ABC)
+ABC is expected to be written to register bits 0-11.
+Here we see that value written is as expected, but this write
+is also affecting all the remaining bits of xyz.
+The remaining bits hold the default value as 0 and the write
+also sets it to zero. Hence wrong usage were not causing user
+visible bugs.
+Due to these reasons it was difficult to follow when
+compared with TRM.
+
+Unused definitions are also removed.
+Since there is change in some naming convention because of
+all the above mentioned reasons, the same has been
+updated throughout the code.
+Bit declarations are grouped to increase readability.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 128 +++++++++++++++++++++------------
+ 1 file changed, 82 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index d229c74..d198cab 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -52,43 +52,79 @@
+
+ /* Register Bitfields */
+ #define IRQWKUP_ENB BIT(0)
+-#define STPENB_STEPENB 0x7FFF
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) (val << 0)
++#define STPENB_STEPENB STEPENB(0x7FFF)
++
++/* IRQ enable */
+ #define IRQENB_FIFO1THRES BIT(5)
+ #define IRQENB_PENUP BIT(9)
+-#define STEPCONFIG_MODE_HWSYNC 0x2
+-#define STEPCONFIG_SAMPLES_AVG (1 << 4)
+-#define STEPCONFIG_XPP (1 << 5)
+-#define STEPCONFIG_XNN (1 << 6)
+-#define STEPCONFIG_YPP (1 << 7)
+-#define STEPCONFIG_YNN (1 << 8)
+-#define STEPCONFIG_XNP (1 << 9)
+-#define STEPCONFIG_YPN (1 << 10)
+-#define STEPCONFIG_INM (1 << 18)
+-#define STEPCONFIG_INP (1 << 20)
+-#define STEPCONFIG_INP_5 (1 << 21)
+-#define STEPCONFIG_FIFO1 (1 << 26)
+-#define STEPCONFIG_OPENDLY 0xff
+-#define STEPCONFIG_Z1 (3 << 19)
+-#define STEPIDLE_INP (1 << 22)
+-#define STEPCHARGE_RFP (1 << 12)
+-#define STEPCHARGE_INM (1 << 15)
+-#define STEPCHARGE_INP (1 << 19)
+-#define STEPCHARGE_RFM (1 << 23)
+-#define STEPCHARGE_DELAY 0x1
+-#define CNTRLREG_TSCSSENB (1 << 0)
+-#define CNTRLREG_STEPID (1 << 1)
+-#define CNTRLREG_STEPCONFIGWRT (1 << 2)
+-#define CNTRLREG_4WIRE (1 << 5)
+-#define CNTRLREG_5WIRE (1 << 6)
+-#define CNTRLREG_8WIRE (3 << 5)
+-#define CNTRLREG_TSCENB (1 << 7)
+-#define ADCFSM_STEPID 0x10
+
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) (val << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) (val << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) (val << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) (val << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) (val << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) (val << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) (val << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) (val << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) (val << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) (val << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) (val << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+ #define ADC_CLK 3000000
+ #define MAX_12BIT ((1 << 12) - 1)
+-#define TSCADC_DELTA_X 15
+-#define TSCADC_DELTA_Y 15
+
+ struct tscadc {
+ struct input_dev *input;
+@@ -119,18 +155,18 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ /* Configure the Step registers */
+
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP;
++ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_INP | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+ break;
+ case 5:
+ config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_5 | STEPCONFIG_XNN |
++ STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+ STEPCONFIG_YPP;
+ break;
+ case 8:
+- config |= STEPCONFIG_INP | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+ break;
+ }
+
+@@ -141,14 +177,14 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+
+ config = 0;
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN |
+- STEPCONFIG_INM | STEPCONFIG_FIFO1;
++ STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+ switch (ts_dev->wires) {
+ case 4:
+ config |= STEPCONFIG_YPP;
+ break;
+ case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
++ config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+ STEPCONFIG_XNP | STEPCONFIG_YPN;
+ break;
+ case 8:
+@@ -164,21 +200,21 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ config = 0;
+ /* Charge step configuration */
+ config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+- STEPCHARGE_RFP | STEPCHARGE_RFM |
+- STEPCHARGE_INM | STEPCHARGE_INP;
++ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+
+ tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
+- tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
++ tscadc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+
+ config = 0;
+ /* Configure to calculate pressure */
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM;
++ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
++ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+ tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
+ tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
+
+- config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
++ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+ tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
+ tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
+
+@@ -190,8 +226,8 @@ static void tscadc_idle_config(struct tscadc *ts_config)
+ unsigned int idleconfig;
+
+ idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM |
+- STEPCONFIG_YPN | STEPIDLE_INP;
++ STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+ tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
+ }
+
diff --git a/patches/linux-3.7/0047-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch b/patches/linux-3.7/0047-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
new file mode 100644
index 0000000..f8f43e3
--- /dev/null
+++ b/patches/linux-3.7/0047-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
@@ -0,0 +1,137 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:39 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Add Step configuration as platform
+ data
+
+There are 16 programmable Step Configuration
+registers which are used by the sequencer.
+Program the Steps in order to configure a channel
+input to be sampled. If the same step is applied
+several times, the coordinate values read are more
+accurate.
+Hence we provide the user an option of how many steps
+should be configured.
+
+For ex: If this value is assigned as 4, This means that
+4 steps are applied to read x co-ordinate and 4 steps to read
+y co-ordinate. Furtheron the interrupt handler already
+holds code to use delta filter and report the best value
+out of these values to the input sub-system.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 25 +++++++++++++------------
+ include/linux/input/ti_tscadc.h | 6 ++++++
+ 2 files changed, 19 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index d198cab..c1bd8e5 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -41,10 +41,6 @@
+ #define REG_CHARGEDELAY 0x060
+ #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+ #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_STEPCONFIG13 0x0C4
+-#define REG_STEPDELAY13 0x0C8
+-#define REG_STEPCONFIG14 0x0CC
+-#define REG_STEPDELAY14 0x0D0
+ #define REG_FIFO0CNT 0xE4
+ #define REG_FIFO1THR 0xF4
+ #define REG_FIFO0 0x100
+@@ -134,6 +130,7 @@ struct tscadc {
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+ bool pen_down;
++ int steps_to_configure;
+ };
+
+ static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
+@@ -150,9 +147,10 @@ static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
+ static void tscadc_step_config(struct tscadc *ts_dev)
+ {
+ unsigned int config;
+- int i;
++ int i, total_steps;
+
+ /* Configure the Step registers */
++ total_steps = 2 * ts_dev->steps_to_configure;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+@@ -170,7 +168,7 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ break;
+ }
+
+- for (i = 1; i < 7; i++) {
++ for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+ tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -192,7 +190,7 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ break;
+ }
+
+- for (i = 7; i < 13; i++) {
++ for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+ tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+ tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+ }
+@@ -211,12 +209,14 @@ static void tscadc_step_config(struct tscadc *ts_dev)
+ config = STEPCONFIG_MODE_HWSYNC |
+ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+- tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
+- tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
++ tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
++ tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
++ STEPCONFIG_OPENDLY);
+
+ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+- tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
+- tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
++ tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
++ tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
++ STEPCONFIG_OPENDLY);
+
+ tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+ }
+@@ -379,6 +379,7 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ ts_dev->irq = irq;
+ ts_dev->wires = pdata->wires;
+ ts_dev->x_plate_resistance = pdata->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->steps_to_configure;
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (!res) {
+@@ -447,7 +448,7 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ tscadc_idle_config(ts_dev);
+ tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+ tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO1THR, 6);
++ tscadc_writel(ts_dev, REG_FIFO1THR, ts_dev->steps_to_configure);
+
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
+diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
+index b10a527..ad442a3 100644
+--- a/include/linux/input/ti_tscadc.h
++++ b/include/linux/input/ti_tscadc.h
+@@ -7,11 +7,17 @@
+ * i.e. 4/5/8 wire touchscreen support
+ * on the platform.
+ * @x_plate_resistance: X plate resistance.
++ * @steps_to_configure: The sequencer supports a total of
++ * 16 programmable steps.
++ * A step configured to read a single
++ * co-ordinate value, can be applied
++ * more number of times for better results.
+ */
+
+ struct tsc_data {
+ int wires;
+ int x_plate_resistance;
++ int steps_to_configure;
+ };
+
+ #endif
diff --git a/patches/linux-3.7/0048-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch b/patches/linux-3.7/0048-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
new file mode 100644
index 0000000..fa1162b
--- /dev/null
+++ b/patches/linux-3.7/0048-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
@@ -0,0 +1,66 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:40 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: set FIFO0 threshold Interrupt
+
+Code currently uses FIFO1 threshold interrupt.
+since this is a MFD, Dedicating FIFO0 to touchscreen
+and making way for other devices to use FIFO1 as well.
+The FIFO can be shared between 2 devices but since the
+interrupt used is threshold interrupt on FIFO1, we would
+end up having wrong interrupts. Hence changing the same.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index c1bd8e5..2cc19b0 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -42,6 +42,7 @@
+ #define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+ #define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+ #define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
+ #define REG_FIFO1THR 0xF4
+ #define REG_FIFO0 0x100
+ #define REG_FIFO1 0x200
+@@ -55,6 +56,7 @@
+ #define STPENB_STEPENB STEPENB(0x7FFF)
+
+ /* IRQ enable */
++#define IRQENB_FIFO0THRES BIT(2)
+ #define IRQENB_FIFO1THRES BIT(5)
+ #define IRQENB_PENUP BIT(9)
+
+@@ -277,7 +279,7 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ unsigned int fsm;
+
+ status = tscadc_readl(ts_dev, REG_IRQSTATUS);
+- if (status & IRQENB_FIFO1THRES) {
++ if (status & IRQENB_FIFO0THRES) {
+ tscadc_read_coordinates(ts_dev, &x, &y);
+
+ z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+@@ -303,7 +305,7 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ input_sync(input_dev);
+ }
+ }
+- irqclr |= IRQENB_FIFO1THRES;
++ irqclr |= IRQENB_FIFO0THRES;
+ }
+
+ /*
+@@ -446,9 +448,9 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
+
+ tscadc_idle_config(ts_dev);
+- tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
++ tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+ tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO1THR, ts_dev->steps_to_configure);
++ tscadc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(ts_dev, REG_CTRL, ctrl);
diff --git a/patches/linux-3.7/0049-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch b/patches/linux-3.7/0049-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
new file mode 100644
index 0000000..7160244
--- /dev/null
+++ b/patches/linux-3.7/0049-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
@@ -0,0 +1,36 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:41 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Remove definition of End Of Interrupt
+ register
+
+The touchscreen IP uses level sensitive interrupts rather
+than edge sensitive interrupts and therefore the is no need
+to use the EOI register to have the module re-strobe the
+interrupt line if there pending interrupts exist.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_tscadc.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+index 2cc19b0..ec0a442 100644
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ b/drivers/input/touchscreen/ti_tscadc.c
+@@ -27,7 +27,6 @@
+ #include <linux/input/ti_tscadc.h>
+ #include <linux/delay.h>
+
+-#define REG_IRQEOI 0x020
+ #define REG_RAWIRQSTATUS 0x024
+ #define REG_IRQSTATUS 0x028
+ #define REG_IRQENABLE 0x02C
+@@ -330,8 +329,6 @@ static irqreturn_t tscadc_irq(int irq, void *dev)
+ }
+
+ tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+- /* check pending interrupts */
+- tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
+
+ tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+ return IRQ_HANDLED;
diff --git a/patches/linux-3.7/0050-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch b/patches/linux-3.7/0050-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
new file mode 100644
index 0000000..8f8ac8f
--- /dev/null
+++ b/patches/linux-3.7/0050-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
@@ -0,0 +1,1173 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:42 +0000
+Subject: [PATCH] input: TSC: ti_tscadc: Rename the existing touchscreen
+ driver
+
+Make way for addition of MFD driver.
+The existing touchsreen driver is a MFD client.
+For better readability we rename the file to
+indicate its functionality as only touchscreen.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/Kconfig | 4 +-
+ drivers/input/touchscreen/Makefile | 2 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c | 522 +++++++++++++++++++++++++++++
+ drivers/input/touchscreen/ti_tscadc.c | 522 -----------------------------
+ include/linux/input/ti_am335x_tsc.h | 23 ++
+ include/linux/input/ti_tscadc.h | 23 --
+ 6 files changed, 548 insertions(+), 548 deletions(-)
+ create mode 100644 drivers/input/touchscreen/ti_am335x_tsc.c
+ delete mode 100644 drivers/input/touchscreen/ti_tscadc.c
+ create mode 100644 include/linux/input/ti_am335x_tsc.h
+ delete mode 100644 include/linux/input/ti_tscadc.h
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index f7668b2..d31dc5f 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -529,7 +529,7 @@ config TOUCHSCREEN_TOUCHWIN
+ To compile this driver as a module, choose M here: the
+ module will be called touchwin.
+
+-config TOUCHSCREEN_TI_TSCADC
++config TOUCHSCREEN_TI_AM335X_TSC
+ tristate "TI Touchscreen Interface"
+ depends on ARCH_OMAP2PLUS
+ help
+@@ -539,7 +539,7 @@ config TOUCHSCREEN_TI_TSCADC
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+- module will be called ti_tscadc.
++ module will be called ti_am335x_tsc.
+
+ config TOUCHSCREEN_ATMEL_TSADCC
+ tristate "Atmel Touchscreen Interface"
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 178eb12..7c4c78e 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -52,7 +52,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
+ obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
+-obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o
++obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
+ obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
+ obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+new file mode 100644
+index 0000000..462950a
+--- /dev/null
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -0,0 +1,522 @@
++/*
++ * TI Touch Screen driver
++ *
++ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.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 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/init.h>
++#include <linux/kernel.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/input.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/delay.h>
++
++#define REG_RAWIRQSTATUS 0x024
++#define REG_IRQSTATUS 0x028
++#define REG_IRQENABLE 0x02C
++#define REG_IRQWAKEUP 0x034
++#define REG_CTRL 0x040
++#define REG_ADCFSM 0x044
++#define REG_CLKDIV 0x04C
++#define REG_SE 0x054
++#define REG_IDLECONFIG 0x058
++#define REG_CHARGECONFIG 0x05C
++#define REG_CHARGEDELAY 0x060
++#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
++#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
++#define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
++#define REG_FIFO1THR 0xF4
++#define REG_FIFO0 0x100
++#define REG_FIFO1 0x200
++
++/* Register Bitfields */
++#define IRQWKUP_ENB BIT(0)
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) (val << 0)
++#define STPENB_STEPENB STEPENB(0x7FFF)
++
++/* IRQ enable */
++#define IRQENB_FIFO0THRES BIT(2)
++#define IRQENB_FIFO1THRES BIT(5)
++#define IRQENB_PENUP BIT(9)
++
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) (val << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) (val << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) (val << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) (val << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) (val << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) (val << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) (val << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) (val << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) (val << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) (val << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) (val << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADCFSM_STEPID 0x10
++#define SEQ_SETTLE 275
++#define ADC_CLK 3000000
++#define MAX_12BIT ((1 << 12) - 1)
++
++struct titsc {
++ struct input_dev *input;
++ struct clk *tsc_ick;
++ void __iomem *tsc_base;
++ unsigned int irq;
++ unsigned int wires;
++ unsigned int x_plate_resistance;
++ bool pen_down;
++ int steps_to_configure;
++};
++
++static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
++{
++ return readl(ts->tsc_base + reg);
++}
++
++static void titsc_writel(struct titsc *tsc, unsigned int reg,
++ unsigned int val)
++{
++ writel(val, tsc->tsc_base + reg);
++}
++
++static void titsc_step_config(struct titsc *ts_dev)
++{
++ unsigned int config;
++ int i, total_steps;
++
++ /* Configure the Step registers */
++ total_steps = 2 * ts_dev->steps_to_configure;
++
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
++ switch (ts_dev->wires) {
++ case 4:
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ break;
++ case 5:
++ config |= STEPCONFIG_YNN |
++ STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
++ STEPCONFIG_YPP;
++ break;
++ case 8:
++ config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ break;
++ }
++
++ for (i = 1; i <= ts_dev->steps_to_configure; i++) {
++ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
++ }
++
++ config = 0;
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
++ switch (ts_dev->wires) {
++ case 4:
++ config |= STEPCONFIG_YPP;
++ break;
++ case 5:
++ config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
++ STEPCONFIG_XNP | STEPCONFIG_YPN;
++ break;
++ case 8:
++ config |= STEPCONFIG_YPP;
++ break;
++ }
++
++ for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
++ titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
++ }
++
++ config = 0;
++ /* Charge step configuration */
++ config = STEPCONFIG_XPP | STEPCONFIG_YNN |
++ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
++
++ titsc_writel(ts_dev, REG_CHARGECONFIG, config);
++ titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
++
++ config = 0;
++ /* Configure to calculate pressure */
++ config = STEPCONFIG_MODE_HWSYNC |
++ STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
++ STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
++ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
++ STEPCONFIG_OPENDLY);
++
++ config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
++ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
++ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
++ STEPCONFIG_OPENDLY);
++
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++}
++
++static void titsc_idle_config(struct titsc *ts_config)
++{
++ unsigned int idleconfig;
++
++ idleconfig = STEPCONFIG_YNN |
++ STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
++ titsc_writel(ts_config, REG_IDLECONFIG, idleconfig);
++}
++
++static void titsc_read_coordinates(struct titsc *ts_dev,
++ unsigned int *x, unsigned int *y)
++{
++ unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
++ unsigned int prev_val_x = ~0, prev_val_y = ~0;
++ unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
++ unsigned int read, diff;
++ unsigned int i;
++
++ /*
++ * Delta filter is used to remove large variations in sampled
++ * values from ADC. The filter tries to predict where the next
++ * coordinate could be. This is done by taking a previous
++ * coordinate and subtracting it form current one. Further the
++ * algorithm compares the difference with that of a present value,
++ * if true the value is reported to the sub system.
++ */
++ for (i = 0; i < fifocount - 1; i++) {
++ read = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
++ diff = abs(read - prev_val_x);
++ if (diff < prev_diff_x) {
++ prev_diff_x = diff;
++ *x = read;
++ }
++ prev_val_x = read;
++
++ read = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
++ diff = abs(read - prev_val_y);
++ if (diff < prev_diff_y) {
++ prev_diff_y = diff;
++ *y = read;
++ }
++ prev_val_y = read;
++ }
++}
++
++static irqreturn_t titsc_irq(int irq, void *dev)
++{
++ struct titsc *ts_dev = dev;
++ struct input_dev *input_dev = ts_dev->input;
++ unsigned int status, irqclr = 0;
++ unsigned int x = 0, y = 0;
++ unsigned int z1, z2, z;
++ unsigned int fsm;
++
++ status = titsc_readl(ts_dev, REG_IRQSTATUS);
++ if (status & IRQENB_FIFO0THRES) {
++ titsc_read_coordinates(ts_dev, &x, &y);
++
++ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
++ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
++
++ if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
++ /*
++ * Calculate pressure using formula
++ * Resistance(touch) = x plate resistance *
++ * x postion/4096 * ((z2 / z1) - 1)
++ */
++ z = z2 - z1;
++ z *= x;
++ z *= ts_dev->x_plate_resistance;
++ z /= z1;
++ z = (z + 2047) >> 12;
++
++ if (z <= MAX_12BIT) {
++ input_report_abs(input_dev, ABS_X, x);
++ input_report_abs(input_dev, ABS_Y, y);
++ input_report_abs(input_dev, ABS_PRESSURE, z);
++ input_report_key(input_dev, BTN_TOUCH, 1);
++ input_sync(input_dev);
++ }
++ }
++ irqclr |= IRQENB_FIFO0THRES;
++ }
++
++ /*
++ * Time for sequencer to settle, to read
++ * correct state of the sequencer.
++ */
++ udelay(SEQ_SETTLE);
++
++ status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
++ if (status & IRQENB_PENUP) {
++ /* Pen up event */
++ fsm = titsc_readl(ts_dev, REG_ADCFSM);
++ if (fsm == ADCFSM_STEPID) {
++ ts_dev->pen_down = false;
++ input_report_key(input_dev, BTN_TOUCH, 0);
++ input_report_abs(input_dev, ABS_PRESSURE, 0);
++ input_sync(input_dev);
++ } else {
++ ts_dev->pen_down = true;
++ }
++ irqclr |= IRQENB_PENUP;
++ }
++
++ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
++
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++ return IRQ_HANDLED;
++}
++
++/*
++ * The functions for inserting/removing driver as a module.
++ */
++
++static int __devinit titsc_probe(struct platform_device *pdev)
++{
++ const struct tsc_data *pdata = pdev->dev.platform_data;
++ struct resource *res;
++ struct titsc *ts_dev;
++ struct input_dev *input_dev;
++ struct clk *clk;
++ int err;
++ int clk_value, ctrl, irq;
++
++ if (!pdata) {
++ dev_err(&pdev->dev, "missing platform data.\n");
++ return -EINVAL;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource defined.\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "no irq ID is specified.\n");
++ return -EINVAL;
++ }
++
++ /* Allocate memory for device */
++ ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
++ input_dev = input_allocate_device();
++ if (!ts_dev || !input_dev) {
++ dev_err(&pdev->dev, "failed to allocate memory.\n");
++ err = -ENOMEM;
++ goto err_free_mem;
++ }
++
++ ts_dev->input = input_dev;
++ ts_dev->irq = irq;
++ ts_dev->wires = pdata->wires;
++ ts_dev->x_plate_resistance = pdata->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->steps_to_configure;
++
++ res = request_mem_region(res->start, resource_size(res), pdev->name);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to reserve registers.\n");
++ err = -EBUSY;
++ goto err_free_mem;
++ }
++
++ ts_dev->tsc_base = ioremap(res->start, resource_size(res));
++ if (!ts_dev->tsc_base) {
++ dev_err(&pdev->dev, "failed to map registers.\n");
++ err = -ENOMEM;
++ goto err_release_mem_region;
++ }
++
++ err = request_irq(ts_dev->irq, titsc_irq,
++ 0, pdev->dev.driver->name, ts_dev);
++ if (err) {
++ dev_err(&pdev->dev, "failed to allocate irq.\n");
++ goto err_unmap_regs;
++ }
++
++ ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
++ if (IS_ERR(ts_dev->tsc_ick)) {
++ dev_err(&pdev->dev, "failed to get TSC ick\n");
++ goto err_free_irq;
++ }
++ clk_enable(ts_dev->tsc_ick);
++
++ clk = clk_get(&pdev->dev, "adc_tsc_fck");
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get TSC fck\n");
++ err = PTR_ERR(clk);
++ goto err_disable_clk;
++ }
++
++ clk_value = clk_get_rate(clk) / ADC_CLK;
++ clk_put(clk);
++
++ if (clk_value < 7) {
++ dev_err(&pdev->dev, "clock input less than min clock requirement\n");
++ goto err_disable_clk;
++ }
++ /* CLKDIV needs to be configured to the value minus 1 */
++ titsc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
++
++ /* Enable wake-up of the SoC using touchscreen */
++ titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
++
++ ctrl = CNTRLREG_STEPCONFIGWRT |
++ CNTRLREG_TSCENB |
++ CNTRLREG_STEPID;
++ switch (ts_dev->wires) {
++ case 4:
++ ctrl |= CNTRLREG_4WIRE;
++ break;
++ case 5:
++ ctrl |= CNTRLREG_5WIRE;
++ break;
++ case 8:
++ ctrl |= CNTRLREG_8WIRE;
++ break;
++ }
++ titsc_writel(ts_dev, REG_CTRL, ctrl);
++
++ titsc_idle_config(ts_dev);
++ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
++ titsc_step_config(ts_dev);
++ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
++
++ ctrl |= CNTRLREG_TSCSSENB;
++ titsc_writel(ts_dev, REG_CTRL, ctrl);
++
++ input_dev->name = "ti-tsc-adc";
++ input_dev->dev.parent = &pdev->dev;
++
++ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
++ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
++
++ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
++
++ /* register to the input system */
++ err = input_register_device(input_dev);
++ if (err)
++ goto err_disable_clk;
++
++ platform_set_drvdata(pdev, ts_dev);
++ return 0;
++
++err_disable_clk:
++ clk_disable(ts_dev->tsc_ick);
++ clk_put(ts_dev->tsc_ick);
++err_free_irq:
++ free_irq(ts_dev->irq, ts_dev);
++err_unmap_regs:
++ iounmap(ts_dev->tsc_base);
++err_release_mem_region:
++ release_mem_region(res->start, resource_size(res));
++err_free_mem:
++ input_free_device(input_dev);
++ kfree(ts_dev);
++ return err;
++}
++
++static int __devexit titsc_remove(struct platform_device *pdev)
++{
++ struct titsc *ts_dev = platform_get_drvdata(pdev);
++ struct resource *res;
++
++ free_irq(ts_dev->irq, ts_dev);
++
++ input_unregister_device(ts_dev->input);
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ iounmap(ts_dev->tsc_base);
++ release_mem_region(res->start, resource_size(res));
++
++ clk_disable(ts_dev->tsc_ick);
++ clk_put(ts_dev->tsc_ick);
++
++ kfree(ts_dev);
++
++ platform_set_drvdata(pdev, NULL);
++ return 0;
++}
++
++static struct platform_driver ti_tsc_driver = {
++ .probe = titsc_probe,
++ .remove = __devexit_p(titsc_remove),
++ .driver = {
++ .name = "tsc",
++ .owner = THIS_MODULE,
++ },
++};
++module_platform_driver(ti_tsc_driver);
++
++MODULE_DESCRIPTION("TI touchscreen controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
+deleted file mode 100644
+index ec0a442..0000000
+--- a/drivers/input/touchscreen/ti_tscadc.c
++++ /dev/null
+@@ -1,522 +0,0 @@
+-/*
+- * TI Touch Screen driver
+- *
+- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.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 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/init.h>
+-#include <linux/kernel.h>
+-#include <linux/err.h>
+-#include <linux/module.h>
+-#include <linux/input.h>
+-#include <linux/slab.h>
+-#include <linux/interrupt.h>
+-#include <linux/clk.h>
+-#include <linux/platform_device.h>
+-#include <linux/io.h>
+-#include <linux/input/ti_tscadc.h>
+-#include <linux/delay.h>
+-
+-#define REG_RAWIRQSTATUS 0x024
+-#define REG_IRQSTATUS 0x028
+-#define REG_IRQENABLE 0x02C
+-#define REG_IRQWAKEUP 0x034
+-#define REG_CTRL 0x040
+-#define REG_ADCFSM 0x044
+-#define REG_CLKDIV 0x04C
+-#define REG_SE 0x054
+-#define REG_IDLECONFIG 0x058
+-#define REG_CHARGECONFIG 0x05C
+-#define REG_CHARGEDELAY 0x060
+-#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+-#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_FIFO0CNT 0xE4
+-#define REG_FIFO0THR 0xE8
+-#define REG_FIFO1THR 0xF4
+-#define REG_FIFO0 0x100
+-#define REG_FIFO1 0x200
+-
+-/* Register Bitfields */
+-#define IRQWKUP_ENB BIT(0)
+-
+-/* Step Enable */
+-#define STEPENB_MASK (0x1FFFF << 0)
+-#define STEPENB(val) (val << 0)
+-#define STPENB_STEPENB STEPENB(0x7FFF)
+-
+-/* IRQ enable */
+-#define IRQENB_FIFO0THRES BIT(2)
+-#define IRQENB_FIFO1THRES BIT(5)
+-#define IRQENB_PENUP BIT(9)
+-
+-/* Step Configuration */
+-#define STEPCONFIG_MODE_MASK (3 << 0)
+-#define STEPCONFIG_MODE(val) (val << 0)
+-#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
+-#define STEPCONFIG_AVG_MASK (7 << 2)
+-#define STEPCONFIG_AVG(val) (val << 2)
+-#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
+-#define STEPCONFIG_XPP BIT(5)
+-#define STEPCONFIG_XNN BIT(6)
+-#define STEPCONFIG_YPP BIT(7)
+-#define STEPCONFIG_YNN BIT(8)
+-#define STEPCONFIG_XNP BIT(9)
+-#define STEPCONFIG_YPN BIT(10)
+-#define STEPCONFIG_INM_MASK (0xF << 15)
+-#define STEPCONFIG_INM(val) (val << 15)
+-#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+-#define STEPCONFIG_INP_MASK (0xF << 19)
+-#define STEPCONFIG_INP(val) (val << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+-#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+-#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+-#define STEPCONFIG_FIFO1 BIT(26)
+-
+-/* Delay register */
+-#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
+-#define STEPDELAY_OPEN(val) (val << 0)
+-#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
+-
+-/* Charge Config */
+-#define STEPCHARGE_RFP_MASK (7 << 12)
+-#define STEPCHARGE_RFP(val) (val << 12)
+-#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
+-#define STEPCHARGE_INM_MASK (0xF << 15)
+-#define STEPCHARGE_INM(val) (val << 15)
+-#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+-#define STEPCHARGE_INP_MASK (0xF << 19)
+-#define STEPCHARGE_INP(val) (val << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+-#define STEPCHARGE_RFM_MASK (3 << 23)
+-#define STEPCHARGE_RFM(val) (val << 23)
+-#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+-
+-/* Charge delay */
+-#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
+-#define CHARGEDLY_OPEN(val) (val << 0)
+-#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
+-
+-/* Control register */
+-#define CNTRLREG_TSCSSENB BIT(0)
+-#define CNTRLREG_STEPID BIT(1)
+-#define CNTRLREG_STEPCONFIGWRT BIT(2)
+-#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
+-#define CNTRLREG_AFE_CTRL(val) (val << 5)
+-#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
+-#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
+-#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+-#define CNTRLREG_TSCENB BIT(7)
+-
+-#define ADCFSM_STEPID 0x10
+-#define SEQ_SETTLE 275
+-#define ADC_CLK 3000000
+-#define MAX_12BIT ((1 << 12) - 1)
+-
+-struct tscadc {
+- struct input_dev *input;
+- struct clk *tsc_ick;
+- void __iomem *tsc_base;
+- unsigned int irq;
+- unsigned int wires;
+- unsigned int x_plate_resistance;
+- bool pen_down;
+- int steps_to_configure;
+-};
+-
+-static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
+-{
+- return readl(ts->tsc_base + reg);
+-}
+-
+-static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
+- unsigned int val)
+-{
+- writel(val, tsc->tsc_base + reg);
+-}
+-
+-static void tscadc_step_config(struct tscadc *ts_dev)
+-{
+- unsigned int config;
+- int i, total_steps;
+-
+- /* Configure the Step registers */
+- total_steps = 2 * ts_dev->steps_to_configure;
+-
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+- switch (ts_dev->wires) {
+- case 4:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+- break;
+- case 5:
+- config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+- STEPCONFIG_YPP;
+- break;
+- case 8:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+- break;
+- }
+-
+- for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+- tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+- }
+-
+- config = 0;
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+- switch (ts_dev->wires) {
+- case 4:
+- config |= STEPCONFIG_YPP;
+- break;
+- case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+- STEPCONFIG_XNP | STEPCONFIG_YPN;
+- break;
+- case 8:
+- config |= STEPCONFIG_YPP;
+- break;
+- }
+-
+- for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+- tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
+- }
+-
+- config = 0;
+- /* Charge step configuration */
+- config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+- STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+- STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+-
+- tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
+- tscadc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+-
+- config = 0;
+- /* Configure to calculate pressure */
+- config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+- tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+- STEPCONFIG_OPENDLY);
+-
+- config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+- tscadc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
+- tscadc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+- STEPCONFIG_OPENDLY);
+-
+- tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+-}
+-
+-static void tscadc_idle_config(struct tscadc *ts_config)
+-{
+- unsigned int idleconfig;
+-
+- idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM |
+- STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+- tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
+-}
+-
+-static void tscadc_read_coordinates(struct tscadc *ts_dev,
+- unsigned int *x, unsigned int *y)
+-{
+- unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
+- unsigned int prev_val_x = ~0, prev_val_y = ~0;
+- unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
+- unsigned int read, diff;
+- unsigned int i;
+-
+- /*
+- * Delta filter is used to remove large variations in sampled
+- * values from ADC. The filter tries to predict where the next
+- * coordinate could be. This is done by taking a previous
+- * coordinate and subtracting it form current one. Further the
+- * algorithm compares the difference with that of a present value,
+- * if true the value is reported to the sub system.
+- */
+- for (i = 0; i < fifocount - 1; i++) {
+- read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- diff = abs(read - prev_val_x);
+- if (diff < prev_diff_x) {
+- prev_diff_x = diff;
+- *x = read;
+- }
+- prev_val_x = read;
+-
+- read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
+- diff = abs(read - prev_val_y);
+- if (diff < prev_diff_y) {
+- prev_diff_y = diff;
+- *y = read;
+- }
+- prev_val_y = read;
+- }
+-}
+-
+-static irqreturn_t tscadc_irq(int irq, void *dev)
+-{
+- struct tscadc *ts_dev = dev;
+- struct input_dev *input_dev = ts_dev->input;
+- unsigned int status, irqclr = 0;
+- unsigned int x = 0, y = 0;
+- unsigned int z1, z2, z;
+- unsigned int fsm;
+-
+- status = tscadc_readl(ts_dev, REG_IRQSTATUS);
+- if (status & IRQENB_FIFO0THRES) {
+- tscadc_read_coordinates(ts_dev, &x, &y);
+-
+- z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
+-
+- if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+- /*
+- * Calculate pressure using formula
+- * Resistance(touch) = x plate resistance *
+- * x postion/4096 * ((z2 / z1) - 1)
+- */
+- z = z2 - z1;
+- z *= x;
+- z *= ts_dev->x_plate_resistance;
+- z /= z1;
+- z = (z + 2047) >> 12;
+-
+- if (z <= MAX_12BIT) {
+- input_report_abs(input_dev, ABS_X, x);
+- input_report_abs(input_dev, ABS_Y, y);
+- input_report_abs(input_dev, ABS_PRESSURE, z);
+- input_report_key(input_dev, BTN_TOUCH, 1);
+- input_sync(input_dev);
+- }
+- }
+- irqclr |= IRQENB_FIFO0THRES;
+- }
+-
+- /*
+- * Time for sequencer to settle, to read
+- * correct state of the sequencer.
+- */
+- udelay(SEQ_SETTLE);
+-
+- status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
+- if (status & IRQENB_PENUP) {
+- /* Pen up event */
+- fsm = tscadc_readl(ts_dev, REG_ADCFSM);
+- if (fsm == ADCFSM_STEPID) {
+- ts_dev->pen_down = false;
+- input_report_key(input_dev, BTN_TOUCH, 0);
+- input_report_abs(input_dev, ABS_PRESSURE, 0);
+- input_sync(input_dev);
+- } else {
+- ts_dev->pen_down = true;
+- }
+- irqclr |= IRQENB_PENUP;
+- }
+-
+- tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+-
+- tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+- return IRQ_HANDLED;
+-}
+-
+-/*
+- * The functions for inserting/removing driver as a module.
+- */
+-
+-static int __devinit tscadc_probe(struct platform_device *pdev)
+-{
+- const struct tsc_data *pdata = pdev->dev.platform_data;
+- struct resource *res;
+- struct tscadc *ts_dev;
+- struct input_dev *input_dev;
+- struct clk *clk;
+- int err;
+- int clk_value, ctrl, irq;
+-
+- if (!pdata) {
+- dev_err(&pdev->dev, "missing platform data.\n");
+- return -EINVAL;
+- }
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(&pdev->dev, "no memory resource defined.\n");
+- return -EINVAL;
+- }
+-
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(&pdev->dev, "no irq ID is specified.\n");
+- return -EINVAL;
+- }
+-
+- /* Allocate memory for device */
+- ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
+- input_dev = input_allocate_device();
+- if (!ts_dev || !input_dev) {
+- dev_err(&pdev->dev, "failed to allocate memory.\n");
+- err = -ENOMEM;
+- goto err_free_mem;
+- }
+-
+- ts_dev->input = input_dev;
+- ts_dev->irq = irq;
+- ts_dev->wires = pdata->wires;
+- ts_dev->x_plate_resistance = pdata->x_plate_resistance;
+- ts_dev->steps_to_configure = pdata->steps_to_configure;
+-
+- res = request_mem_region(res->start, resource_size(res), pdev->name);
+- if (!res) {
+- dev_err(&pdev->dev, "failed to reserve registers.\n");
+- err = -EBUSY;
+- goto err_free_mem;
+- }
+-
+- ts_dev->tsc_base = ioremap(res->start, resource_size(res));
+- if (!ts_dev->tsc_base) {
+- dev_err(&pdev->dev, "failed to map registers.\n");
+- err = -ENOMEM;
+- goto err_release_mem_region;
+- }
+-
+- err = request_irq(ts_dev->irq, tscadc_irq,
+- 0, pdev->dev.driver->name, ts_dev);
+- if (err) {
+- dev_err(&pdev->dev, "failed to allocate irq.\n");
+- goto err_unmap_regs;
+- }
+-
+- ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
+- if (IS_ERR(ts_dev->tsc_ick)) {
+- dev_err(&pdev->dev, "failed to get TSC ick\n");
+- goto err_free_irq;
+- }
+- clk_enable(ts_dev->tsc_ick);
+-
+- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+- if (IS_ERR(clk)) {
+- dev_err(&pdev->dev, "failed to get TSC fck\n");
+- err = PTR_ERR(clk);
+- goto err_disable_clk;
+- }
+-
+- clk_value = clk_get_rate(clk) / ADC_CLK;
+- clk_put(clk);
+-
+- if (clk_value < 7) {
+- dev_err(&pdev->dev, "clock input less than min clock requirement\n");
+- goto err_disable_clk;
+- }
+- /* CLKDIV needs to be configured to the value minus 1 */
+- tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
+-
+- /* Enable wake-up of the SoC using touchscreen */
+- tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
+-
+- ctrl = CNTRLREG_STEPCONFIGWRT |
+- CNTRLREG_TSCENB |
+- CNTRLREG_STEPID;
+- switch (ts_dev->wires) {
+- case 4:
+- ctrl |= CNTRLREG_4WIRE;
+- break;
+- case 5:
+- ctrl |= CNTRLREG_5WIRE;
+- break;
+- case 8:
+- ctrl |= CNTRLREG_8WIRE;
+- break;
+- }
+- tscadc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- tscadc_idle_config(ts_dev);
+- tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+- tscadc_step_config(ts_dev);
+- tscadc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+-
+- ctrl |= CNTRLREG_TSCSSENB;
+- tscadc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- input_dev->name = "ti-tsc-adc";
+- input_dev->dev.parent = &pdev->dev;
+-
+- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+-
+- input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
+- input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
+- input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
+-
+- /* register to the input system */
+- err = input_register_device(input_dev);
+- if (err)
+- goto err_disable_clk;
+-
+- platform_set_drvdata(pdev, ts_dev);
+- return 0;
+-
+-err_disable_clk:
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+-err_free_irq:
+- free_irq(ts_dev->irq, ts_dev);
+-err_unmap_regs:
+- iounmap(ts_dev->tsc_base);
+-err_release_mem_region:
+- release_mem_region(res->start, resource_size(res));
+-err_free_mem:
+- input_free_device(input_dev);
+- kfree(ts_dev);
+- return err;
+-}
+-
+-static int __devexit tscadc_remove(struct platform_device *pdev)
+-{
+- struct tscadc *ts_dev = platform_get_drvdata(pdev);
+- struct resource *res;
+-
+- free_irq(ts_dev->irq, ts_dev);
+-
+- input_unregister_device(ts_dev->input);
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- iounmap(ts_dev->tsc_base);
+- release_mem_region(res->start, resource_size(res));
+-
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+-
+- kfree(ts_dev);
+-
+- platform_set_drvdata(pdev, NULL);
+- return 0;
+-}
+-
+-static struct platform_driver ti_tsc_driver = {
+- .probe = tscadc_probe,
+- .remove = __devexit_p(tscadc_remove),
+- .driver = {
+- .name = "tsc",
+- .owner = THIS_MODULE,
+- },
+-};
+-module_platform_driver(ti_tsc_driver);
+-
+-MODULE_DESCRIPTION("TI touchscreen controller driver");
+-MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
+-MODULE_LICENSE("GPL");
+diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
+new file mode 100644
+index 0000000..49269a2
+--- /dev/null
++++ b/include/linux/input/ti_am335x_tsc.h
+@@ -0,0 +1,23 @@
++#ifndef __LINUX_TI_AM335X_TSC_H
++#define __LINUX_TI_AM335X_TSC_H
++
++/**
++ * struct tsc_data Touchscreen wire configuration
++ * @wires: Wires refer to application modes
++ * i.e. 4/5/8 wire touchscreen support
++ * on the platform.
++ * @x_plate_resistance: X plate resistance.
++ * @steps_to_configure: The sequencer supports a total of
++ * 16 programmable steps.
++ * A step configured to read a single
++ * co-ordinate value, can be applied
++ * more number of times for better results.
++ */
++
++struct tsc_data {
++ int wires;
++ int x_plate_resistance;
++ int steps_to_configure;
++};
++
++#endif
+diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
+deleted file mode 100644
+index ad442a3..0000000
+--- a/include/linux/input/ti_tscadc.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-#ifndef __LINUX_TI_TSCADC_H
+-#define __LINUX_TI_TSCADC_H
+-
+-/**
+- * struct tsc_data Touchscreen wire configuration
+- * @wires: Wires refer to application modes
+- * i.e. 4/5/8 wire touchscreen support
+- * on the platform.
+- * @x_plate_resistance: X plate resistance.
+- * @steps_to_configure: The sequencer supports a total of
+- * 16 programmable steps.
+- * A step configured to read a single
+- * co-ordinate value, can be applied
+- * more number of times for better results.
+- */
+-
+-struct tsc_data {
+- int wires;
+- int x_plate_resistance;
+- int steps_to_configure;
+-};
+-
+-#endif
diff --git a/patches/linux-3.7/0051-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch b/patches/linux-3.7/0051-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
new file mode 100644
index 0000000..1e20a54
--- /dev/null
+++ b/patches/linux-3.7/0051-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
@@ -0,0 +1,452 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:43 +0000
+Subject: [PATCH] MFD: ti_tscadc: Add support for TI's TSC/ADC MFDevice
+
+Add the mfd core driver which supports touchscreen
+and ADC.
+With this patch we are only adding infrastructure to
+support the MFD clients.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/mfd/Kconfig | 11 ++
+ drivers/mfd/Makefile | 1 +
+ drivers/mfd/ti_am335x_tscadc.c | 250 ++++++++++++++++++++++++++++++++++
+ include/linux/mfd/ti_am335x_tscadc.h | 137 +++++++++++++++++++
+ 4 files changed, 399 insertions(+)
+ create mode 100644 drivers/mfd/ti_am335x_tscadc.c
+ create mode 100644 include/linux/mfd/ti_am335x_tscadc.h
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index acab3ef..9bba7f7 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -94,6 +94,17 @@ config MFD_TI_SSP
+ To compile this driver as a module, choose M here: the
+ module will be called ti-ssp.
+
++config MFD_TI_AM335X_TSCADC
++ tristate "TI ADC / Touch Screen chip support"
++ select MFD_CORE
++ select REGMAP
++ select REGMAP_MMIO
++ help
++ If you say yes here you get support for Texas Instruments series
++ of Touch Screen /ADC chips.
++ To compile this driver as a module, choose M here: the
++ module will be called ti_am335x_tscadc.
++
+ config HTC_EGPIO
+ bool "HTC EGPIO support"
+ depends on GENERIC_HARDIRQS && GPIOLIB && ARM
+diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
+index d8ccb63..442c17e 100644
+--- a/drivers/mfd/Makefile
++++ b/drivers/mfd/Makefile
+@@ -16,6 +16,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
+ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o
+ obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
+ obj-$(CONFIG_MFD_TI_SSP) += ti-ssp.o
++obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
+
+ obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o
+ obj-$(CONFIG_MFD_STMPE) += stmpe.o
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+new file mode 100644
+index 0000000..14df67b
+--- /dev/null
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -0,0 +1,250 @@
++/*
++ * TI Touch Screen / ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.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 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/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/regmap.h>
++#include <linux/mfd/core.h>
++#include <linux/pm_runtime.h>
++
++#include <linux/mfd/ti_am335x_tscadc.h>
++
++static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
++{
++ unsigned int val;
++
++ regmap_read(tsadc->regmap_tscadc, reg, &val);
++ return val;
++}
++
++static void tscadc_writel(struct ti_tscadc_dev *tsadc, unsigned int reg,
++ unsigned int val)
++{
++ regmap_write(tsadc->regmap_tscadc, reg, val);
++}
++
++static const struct regmap_config tscadc_regmap_config = {
++ .name = "ti_tscadc",
++ .reg_bits = 32,
++ .reg_stride = 4,
++ .val_bits = 32,
++};
++
++static void tscadc_idle_config(struct ti_tscadc_dev *config)
++{
++ unsigned int idleconfig;
++
++ idleconfig = STEPCONFIG_YNN | STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_INP_ADCREFM | STEPCONFIG_YPN;
++
++ tscadc_writel(config, REG_IDLECONFIG, idleconfig);
++}
++
++static int __devinit ti_tscadc_probe(struct platform_device *pdev)
++{
++ struct ti_tscadc_dev *tscadc;
++ struct resource *res;
++ struct clk *clk;
++ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
++ int irq;
++ int err, ctrl;
++ int clk_value, clock_rate;
++
++ if (!pdata) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
++ return -EINVAL;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "no memory resource defined.\n");
++ return -EINVAL;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(&pdev->dev, "no irq ID is specified.\n");
++ return -EINVAL;
++ }
++
++ /* Allocate memory for device */
++ tscadc = devm_kzalloc(&pdev->dev,
++ sizeof(struct ti_tscadc_dev), GFP_KERNEL);
++ if (!tscadc) {
++ dev_err(&pdev->dev, "failed to allocate memory.\n");
++ return -ENOMEM;
++ }
++ tscadc->dev = &pdev->dev;
++ tscadc->irq = irq;
++
++ res = devm_request_mem_region(&pdev->dev,
++ res->start, resource_size(res), pdev->name);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to reserve registers.\n");
++ err = -EBUSY;
++ goto err;
++ }
++
++ tscadc->tscadc_base = devm_ioremap(&pdev->dev,
++ res->start, resource_size(res));
++ if (!tscadc->tscadc_base) {
++ dev_err(&pdev->dev, "failed to map registers.\n");
++ err = -ENOMEM;
++ goto err;
++ }
++
++ tscadc->regmap_tscadc = devm_regmap_init_mmio(&pdev->dev,
++ tscadc->tscadc_base, &tscadc_regmap_config);
++ if (IS_ERR(tscadc->regmap_tscadc)) {
++ dev_err(&pdev->dev, "regmap init failed\n");
++ err = PTR_ERR(tscadc->regmap_tscadc);
++ goto err;
++ }
++
++ pm_runtime_enable(&pdev->dev);
++ pm_runtime_get_sync(&pdev->dev);
++
++ /*
++ * The TSC_ADC_Subsystem has 2 clock domains
++ * OCP_CLK and ADC_CLK.
++ * The ADC clock is expected to run at target of 3MHz,
++ * and expected to capture 12-bit data at a rate of 200 KSPS.
++ * The TSC_ADC_SS controller design assumes the OCP clock is
++ * at least 6x faster than the ADC clock.
++ */
++ clk = clk_get(&pdev->dev, "adc_tsc_fck");
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get TSC fck\n");
++ err = PTR_ERR(clk);
++ goto err_disable_clk;
++ }
++ clock_rate = clk_get_rate(clk);
++ clk_put(clk);
++ clk_value = clock_rate / ADC_CLK;
++ if (clk_value < MAX_CLK_DIV) {
++ dev_err(&pdev->dev, "clock input less than min clock requirement\n");
++ err = -EINVAL;
++ goto err_disable_clk;
++ }
++ /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
++ clk_value = clk_value - 1;
++ tscadc_writel(tscadc, REG_CLKDIV, clk_value);
++
++ /* Set the control register bits */
++ ctrl = CNTRLREG_STEPCONFIGWRT |
++ CNTRLREG_TSCENB |
++ CNTRLREG_STEPID |
++ CNTRLREG_4WIRE;
++ tscadc_writel(tscadc, REG_CTRL, ctrl);
++
++ /* Set register bits for Idle Config Mode */
++ tscadc_idle_config(tscadc);
++
++ /* Enable the TSC module enable bit */
++ ctrl = tscadc_readl(tscadc, REG_CTRL);
++ ctrl |= CNTRLREG_TSCSSENB;
++ tscadc_writel(tscadc, REG_CTRL, ctrl);
++
++ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
++ TSCADC_CELLS, NULL, 0, NULL);
++ if (err < 0)
++ goto err_disable_clk;
++
++ device_init_wakeup(&pdev->dev, true);
++ platform_set_drvdata(pdev, tscadc);
++
++ return 0;
++
++err_disable_clk:
++ pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++err:
++ return err;
++}
++
++static int __devexit ti_tscadc_remove(struct platform_device *pdev)
++{
++ struct ti_tscadc_dev *tscadc = platform_get_drvdata(pdev);
++
++ tscadc_writel(tscadc, REG_SE, 0x00);
++
++ pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
++ mfd_remove_devices(tscadc->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int tscadc_suspend(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev);
++
++ tscadc_writel(tscadc_dev, REG_SE, 0x00);
++ pm_runtime_put_sync(dev);
++
++ return 0;
++}
++
++static int tscadc_resume(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev_get_drvdata(dev);
++ unsigned int restore, ctrl;
++
++ pm_runtime_get_sync(dev);
++
++ /* context restore */
++ ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
++ CNTRLREG_STEPID | CNTRLREG_4WIRE;
++ tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
++ tscadc_idle_config(tscadc_dev);
++ tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
++ restore = tscadc_readl(tscadc_dev, REG_CTRL);
++ tscadc_writel(tscadc_dev, REG_CTRL,
++ (restore | CNTRLREG_TSCSSENB));
++
++ return 0;
++}
++
++static const struct dev_pm_ops tscadc_pm_ops = {
++ .suspend = tscadc_suspend,
++ .resume = tscadc_resume,
++};
++#define TSCADC_PM_OPS (&tscadc_pm_ops)
++#else
++#define TSCADC_PM_OPS NULL
++#endif
++
++static struct platform_driver ti_tscadc_driver = {
++ .driver = {
++ .name = "ti_tscadc",
++ .owner = THIS_MODULE,
++ .pm = TSCADC_PM_OPS,
++ },
++ .probe = ti_tscadc_probe,
++ .remove = __devexit_p(ti_tscadc_remove),
++
++};
++
++module_platform_driver(ti_tscadc_driver);
++
++MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+new file mode 100644
+index 0000000..b7232b1
+--- /dev/null
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -0,0 +1,137 @@
++#ifndef __LINUX_TI_AM335X_TSCADC_MFD_H
++#define __LINUX_TI_AM335X_TSCADC_MFD_H
++
++/*
++ * TI Touch Screen / ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.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 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/mfd/core.h>
++
++#define REG_RAWIRQSTATUS 0x024
++#define REG_IRQSTATUS 0x028
++#define REG_IRQENABLE 0x02C
++#define REG_IRQCLR 0x030
++#define REG_IRQWAKEUP 0x034
++#define REG_CTRL 0x040
++#define REG_ADCFSM 0x044
++#define REG_CLKDIV 0x04C
++#define REG_SE 0x054
++#define REG_IDLECONFIG 0x058
++#define REG_CHARGECONFIG 0x05C
++#define REG_CHARGEDELAY 0x060
++#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
++#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
++#define REG_FIFO0CNT 0xE4
++#define REG_FIFO0THR 0xE8
++#define REG_FIFO1CNT 0xF0
++#define REG_FIFO1THR 0xF4
++#define REG_FIFO0 0x100
++#define REG_FIFO1 0x200
++
++/* Register Bitfields */
++/* IRQ wakeup enable */
++#define IRQWKUP_ENB BIT(0)
++
++/* Step Enable */
++#define STEPENB_MASK (0x1FFFF << 0)
++#define STEPENB(val) ((val) << 0)
++#define STPENB_STEPENB STEPENB(0x1FFFF)
++
++/* IRQ enable */
++#define IRQENB_HW_PEN BIT(0)
++#define IRQENB_FIFO0THRES BIT(2)
++#define IRQENB_FIFO1THRES BIT(5)
++#define IRQENB_PENUP BIT(9)
++
++/* Step Configuration */
++#define STEPCONFIG_MODE_MASK (3 << 0)
++#define STEPCONFIG_MODE(val) ((val) << 0)
++#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
++#define STEPCONFIG_AVG_MASK (7 << 2)
++#define STEPCONFIG_AVG(val) ((val) << 2)
++#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
++#define STEPCONFIG_XPP BIT(5)
++#define STEPCONFIG_XNN BIT(6)
++#define STEPCONFIG_YPP BIT(7)
++#define STEPCONFIG_YNN BIT(8)
++#define STEPCONFIG_XNP BIT(9)
++#define STEPCONFIG_YPN BIT(10)
++#define STEPCONFIG_INM_MASK (0xF << 15)
++#define STEPCONFIG_INM(val) ((val) << 15)
++#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
++#define STEPCONFIG_INP_MASK (0xF << 19)
++#define STEPCONFIG_INP(val) ((val) << 19)
++#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
++#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
++#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
++#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
++#define STEPCONFIG_FIFO1 BIT(26)
++
++/* Delay register */
++#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
++#define STEPDELAY_OPEN(val) ((val) << 0)
++#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
++#define STEPDELAY_SAMPLE_MASK (0xFF << 24)
++#define STEPDELAY_SAMPLE(val) ((val) << 24)
++#define STEPCONFIG_SAMPLEDLY STEPDELAY_SAMPLE(0)
++
++/* Charge Config */
++#define STEPCHARGE_RFP_MASK (7 << 12)
++#define STEPCHARGE_RFP(val) ((val) << 12)
++#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
++#define STEPCHARGE_INM_MASK (0xF << 15)
++#define STEPCHARGE_INM(val) ((val) << 15)
++#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
++#define STEPCHARGE_INP_MASK (0xF << 19)
++#define STEPCHARGE_INP(val) ((val) << 19)
++#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
++#define STEPCHARGE_RFM_MASK (3 << 23)
++#define STEPCHARGE_RFM(val) ((val) << 23)
++#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
++
++/* Charge delay */
++#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
++#define CHARGEDLY_OPEN(val) ((val) << 0)
++#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
++
++/* Control register */
++#define CNTRLREG_TSCSSENB BIT(0)
++#define CNTRLREG_STEPID BIT(1)
++#define CNTRLREG_STEPCONFIGWRT BIT(2)
++#define CNTRLREG_POWERDOWN BIT(4)
++#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
++#define CNTRLREG_AFE_CTRL(val) ((val) << 5)
++#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
++#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
++#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
++#define CNTRLREG_TSCENB BIT(7)
++
++#define ADC_CLK 3000000
++#define MAX_CLK_DIV 7
++
++#define TSCADC_CELLS 0
++
++struct mfd_tscadc_board {
++ struct tsc_data *tsc_init;
++};
++
++struct ti_tscadc_dev {
++ struct device *dev;
++ struct regmap *regmap_tscadc;
++ void __iomem *tscadc_base;
++ int irq;
++ struct mfd_cell cells[TSCADC_CELLS];
++};
++
++#endif
diff --git a/patches/linux-3.7/0052-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch b/patches/linux-3.7/0052-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
new file mode 100644
index 0000000..4b9e4fa
--- /dev/null
+++ b/patches/linux-3.7/0052-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
@@ -0,0 +1,570 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:44 +0000
+Subject: [PATCH] input: TSC: ti_tsc: Convert TSC into a MFDevice
+
+This patch converts touchscreen into a MFD client.
+All the register definitions, clock initialization,
+etc has been moved to MFD core driver.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/Kconfig | 2 +-
+ drivers/input/touchscreen/ti_am335x_tsc.c | 318 +++++++++--------------------
+ drivers/mfd/ti_am335x_tscadc.c | 11 +
+ include/linux/mfd/ti_am335x_tscadc.h | 10 +-
+ 4 files changed, 118 insertions(+), 223 deletions(-)
+
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index d31dc5f..0c45cad 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -531,7 +531,7 @@ config TOUCHSCREEN_TOUCHWIN
+
+ config TOUCHSCREEN_TI_AM335X_TSC
+ tristate "TI Touchscreen Interface"
+- depends on ARCH_OMAP2PLUS
++ depends on MFD_TI_AM335X_TSCADC
+ help
+ Say Y here if you have 4/5/8 wire touchscreen controller
+ to be connected to the ADC controller on your TI AM335x SoC.
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 462950a..7a18a8a 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -27,106 +27,15 @@
+ #include <linux/input/ti_am335x_tsc.h>
+ #include <linux/delay.h>
+
+-#define REG_RAWIRQSTATUS 0x024
+-#define REG_IRQSTATUS 0x028
+-#define REG_IRQENABLE 0x02C
+-#define REG_IRQWAKEUP 0x034
+-#define REG_CTRL 0x040
+-#define REG_ADCFSM 0x044
+-#define REG_CLKDIV 0x04C
+-#define REG_SE 0x054
+-#define REG_IDLECONFIG 0x058
+-#define REG_CHARGECONFIG 0x05C
+-#define REG_CHARGEDELAY 0x060
+-#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
+-#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
+-#define REG_FIFO0CNT 0xE4
+-#define REG_FIFO0THR 0xE8
+-#define REG_FIFO1THR 0xF4
+-#define REG_FIFO0 0x100
+-#define REG_FIFO1 0x200
+-
+-/* Register Bitfields */
+-#define IRQWKUP_ENB BIT(0)
+-
+-/* Step Enable */
+-#define STEPENB_MASK (0x1FFFF << 0)
+-#define STEPENB(val) (val << 0)
+-#define STPENB_STEPENB STEPENB(0x7FFF)
+-
+-/* IRQ enable */
+-#define IRQENB_FIFO0THRES BIT(2)
+-#define IRQENB_FIFO1THRES BIT(5)
+-#define IRQENB_PENUP BIT(9)
+-
+-/* Step Configuration */
+-#define STEPCONFIG_MODE_MASK (3 << 0)
+-#define STEPCONFIG_MODE(val) (val << 0)
+-#define STEPCONFIG_MODE_HWSYNC STEPCONFIG_MODE(2)
+-#define STEPCONFIG_AVG_MASK (7 << 2)
+-#define STEPCONFIG_AVG(val) (val << 2)
+-#define STEPCONFIG_AVG_16 STEPCONFIG_AVG(4)
+-#define STEPCONFIG_XPP BIT(5)
+-#define STEPCONFIG_XNN BIT(6)
+-#define STEPCONFIG_YPP BIT(7)
+-#define STEPCONFIG_YNN BIT(8)
+-#define STEPCONFIG_XNP BIT(9)
+-#define STEPCONFIG_YPN BIT(10)
+-#define STEPCONFIG_INM_MASK (0xF << 15)
+-#define STEPCONFIG_INM(val) (val << 15)
+-#define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+-#define STEPCONFIG_INP_MASK (0xF << 19)
+-#define STEPCONFIG_INP(val) (val << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+-#define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+-#define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+-#define STEPCONFIG_FIFO1 BIT(26)
+-
+-/* Delay register */
+-#define STEPDELAY_OPEN_MASK (0x3FFFF << 0)
+-#define STEPDELAY_OPEN(val) (val << 0)
+-#define STEPCONFIG_OPENDLY STEPDELAY_OPEN(0x098)
+-
+-/* Charge Config */
+-#define STEPCHARGE_RFP_MASK (7 << 12)
+-#define STEPCHARGE_RFP(val) (val << 12)
+-#define STEPCHARGE_RFP_XPUL STEPCHARGE_RFP(1)
+-#define STEPCHARGE_INM_MASK (0xF << 15)
+-#define STEPCHARGE_INM(val) (val << 15)
+-#define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+-#define STEPCHARGE_INP_MASK (0xF << 19)
+-#define STEPCHARGE_INP(val) (val << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+-#define STEPCHARGE_RFM_MASK (3 << 23)
+-#define STEPCHARGE_RFM(val) (val << 23)
+-#define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+-
+-/* Charge delay */
+-#define CHARGEDLY_OPEN_MASK (0x3FFFF << 0)
+-#define CHARGEDLY_OPEN(val) (val << 0)
+-#define CHARGEDLY_OPENDLY CHARGEDLY_OPEN(1)
+-
+-/* Control register */
+-#define CNTRLREG_TSCSSENB BIT(0)
+-#define CNTRLREG_STEPID BIT(1)
+-#define CNTRLREG_STEPCONFIGWRT BIT(2)
+-#define CNTRLREG_AFE_CTRL_MASK (3 << 5)
+-#define CNTRLREG_AFE_CTRL(val) (val << 5)
+-#define CNTRLREG_4WIRE CNTRLREG_AFE_CTRL(1)
+-#define CNTRLREG_5WIRE CNTRLREG_AFE_CTRL(2)
+-#define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+-#define CNTRLREG_TSCENB BIT(7)
++#include <linux/mfd/ti_am335x_tscadc.h>
+
+ #define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+-#define ADC_CLK 3000000
+ #define MAX_12BIT ((1 << 12) - 1)
+
+ struct titsc {
+ struct input_dev *input;
+- struct clk *tsc_ick;
+- void __iomem *tsc_base;
++ struct ti_tscadc_dev *mfd_tscadc;
+ unsigned int irq;
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+@@ -136,13 +45,13 @@ struct titsc {
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+ {
+- return readl(ts->tsc_base + reg);
++ return readl(ts->mfd_tscadc->tscadc_base + reg);
+ }
+
+ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, tsc->tsc_base + reg);
++ writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+ }
+
+ static void titsc_step_config(struct titsc *ts_dev)
+@@ -219,17 +128,7 @@ static void titsc_step_config(struct titsc *ts_dev)
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
+-}
+-
+-static void titsc_idle_config(struct titsc *ts_config)
+-{
+- unsigned int idleconfig;
+-
+- idleconfig = STEPCONFIG_YNN |
+- STEPCONFIG_INM_ADCREFM |
+- STEPCONFIG_YPN | STEPCONFIG_INP_ADCREFM;
+- titsc_writel(ts_config, REG_IDLECONFIG, idleconfig);
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+@@ -239,7 +138,7 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ unsigned int prev_val_x = ~0, prev_val_y = ~0;
+ unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
+ unsigned int read, diff;
+- unsigned int i;
++ unsigned int i, channel;
+
+ /*
+ * Delta filter is used to remove large variations in sampled
+@@ -250,21 +149,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
+ * if true the value is reported to the sub system.
+ */
+ for (i = 0; i < fifocount - 1; i++) {
+- read = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+- diff = abs(read - prev_val_x);
+- if (diff < prev_diff_x) {
+- prev_diff_x = diff;
+- *x = read;
++ read = titsc_readl(ts_dev, REG_FIFO0);
++ channel = read & 0xf0000;
++ channel = channel >> 0x10;
++ if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
++ read &= 0xfff;
++ diff = abs(read - prev_val_x);
++ if (diff < prev_diff_x) {
++ prev_diff_x = diff;
++ *x = read;
++ }
++ prev_val_x = read;
+ }
+- prev_val_x = read;
+
+- read = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+- diff = abs(read - prev_val_y);
+- if (diff < prev_diff_y) {
+- prev_diff_y = diff;
+- *y = read;
++ read = titsc_readl(ts_dev, REG_FIFO1);
++ channel = read & 0xf0000;
++ channel = channel >> 0x10;
++ if ((channel >= ts_dev->steps_to_configure) &&
++ (channel < (2 * ts_dev->steps_to_configure - 1))) {
++ read &= 0xfff;
++ diff = abs(read - prev_val_y);
++ if (diff < prev_diff_y) {
++ prev_diff_y = diff;
++ *y = read;
++ }
++ prev_val_y = read;
+ }
+- prev_val_y = read;
+ }
+ }
+
+@@ -276,6 +186,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ unsigned int x = 0, y = 0;
+ unsigned int z1, z2, z;
+ unsigned int fsm;
++ unsigned int fifo1count, fifo0count;
++ int i;
+
+ status = titsc_readl(ts_dev, REG_IRQSTATUS);
+ if (status & IRQENB_FIFO0THRES) {
+@@ -284,6 +196,14 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+
++ fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
++ for (i = 0; i < fifo1count; i++)
++ titsc_readl(ts_dev, REG_FIFO1);
++
++ fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
++ for (i = 0; i < fifo0count; i++)
++ titsc_readl(ts_dev, REG_FIFO0);
++
+ if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
+ /*
+ * Calculate pressure using formula
+@@ -330,7 +250,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB);
++ titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+ return IRQ_HANDLED;
+ }
+
+@@ -340,28 +260,16 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ static int __devinit titsc_probe(struct platform_device *pdev)
+ {
+- const struct tsc_data *pdata = pdev->dev.platform_data;
+- struct resource *res;
+ struct titsc *ts_dev;
+ struct input_dev *input_dev;
+- struct clk *clk;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct mfd_tscadc_board *pdata;
+ int err;
+- int clk_value, ctrl, irq;
+
+- if (!pdata) {
+- dev_err(&pdev->dev, "missing platform data.\n");
+- return -EINVAL;
+- }
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res) {
+- dev_err(&pdev->dev, "no memory resource defined.\n");
+- return -EINVAL;
+- }
++ pdata = tscadc_dev->dev->platform_data;
+
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0) {
+- dev_err(&pdev->dev, "no irq ID is specified.\n");
++ if (!pdata) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
+@@ -374,85 +282,26 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ goto err_free_mem;
+ }
+
++ tscadc_dev->tsc = ts_dev;
++ ts_dev->mfd_tscadc = tscadc_dev;
+ ts_dev->input = input_dev;
+- ts_dev->irq = irq;
+- ts_dev->wires = pdata->wires;
+- ts_dev->x_plate_resistance = pdata->x_plate_resistance;
+- ts_dev->steps_to_configure = pdata->steps_to_configure;
+-
+- res = request_mem_region(res->start, resource_size(res), pdev->name);
+- if (!res) {
+- dev_err(&pdev->dev, "failed to reserve registers.\n");
+- err = -EBUSY;
+- goto err_free_mem;
+- }
+-
+- ts_dev->tsc_base = ioremap(res->start, resource_size(res));
+- if (!ts_dev->tsc_base) {
+- dev_err(&pdev->dev, "failed to map registers.\n");
+- err = -ENOMEM;
+- goto err_release_mem_region;
+- }
++ ts_dev->irq = tscadc_dev->irq;
++ ts_dev->wires = pdata->tsc_init->wires;
++ ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
++ ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+ 0, pdev->dev.driver->name, ts_dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to allocate irq.\n");
+- goto err_unmap_regs;
+- }
+-
+- ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
+- if (IS_ERR(ts_dev->tsc_ick)) {
+- dev_err(&pdev->dev, "failed to get TSC ick\n");
+- goto err_free_irq;
+- }
+- clk_enable(ts_dev->tsc_ick);
+-
+- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+- if (IS_ERR(clk)) {
+- dev_err(&pdev->dev, "failed to get TSC fck\n");
+- err = PTR_ERR(clk);
+- goto err_disable_clk;
+- }
+-
+- clk_value = clk_get_rate(clk) / ADC_CLK;
+- clk_put(clk);
+-
+- if (clk_value < 7) {
+- dev_err(&pdev->dev, "clock input less than min clock requirement\n");
+- goto err_disable_clk;
+- }
+- /* CLKDIV needs to be configured to the value minus 1 */
+- titsc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
+-
+- /* Enable wake-up of the SoC using touchscreen */
+- titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
+-
+- ctrl = CNTRLREG_STEPCONFIGWRT |
+- CNTRLREG_TSCENB |
+- CNTRLREG_STEPID;
+- switch (ts_dev->wires) {
+- case 4:
+- ctrl |= CNTRLREG_4WIRE;
+- break;
+- case 5:
+- ctrl |= CNTRLREG_5WIRE;
+- break;
+- case 8:
+- ctrl |= CNTRLREG_8WIRE;
+- break;
++ goto err_free_mem;
+ }
+- titsc_writel(ts_dev, REG_CTRL, ctrl);
+
+- titsc_idle_config(ts_dev);
+ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+- ctrl |= CNTRLREG_TSCSSENB;
+- titsc_writel(ts_dev, REG_CTRL, ctrl);
+-
+- input_dev->name = "ti-tsc-adc";
++ input_dev->name = "ti-tsc";
+ input_dev->dev.parent = &pdev->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+@@ -465,20 +314,13 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ /* register to the input system */
+ err = input_register_device(input_dev);
+ if (err)
+- goto err_disable_clk;
++ goto err_free_irq;
+
+ platform_set_drvdata(pdev, ts_dev);
+ return 0;
+
+-err_disable_clk:
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
+ err_free_irq:
+ free_irq(ts_dev->irq, ts_dev);
+-err_unmap_regs:
+- iounmap(ts_dev->tsc_base);
+-err_release_mem_region:
+- release_mem_region(res->start, resource_size(res));
+ err_free_mem:
+ input_free_device(input_dev);
+ kfree(ts_dev);
+@@ -487,32 +329,66 @@ err_free_mem:
+
+ static int __devexit titsc_remove(struct platform_device *pdev)
+ {
+- struct titsc *ts_dev = platform_get_drvdata(pdev);
+- struct resource *res;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
+
+ free_irq(ts_dev->irq, ts_dev);
+
+ input_unregister_device(ts_dev->input);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- iounmap(ts_dev->tsc_base);
+- release_mem_region(res->start, resource_size(res));
++ platform_set_drvdata(pdev, NULL);
++ kfree(ts_dev);
++ return 0;
++}
+
+- clk_disable(ts_dev->tsc_ick);
+- clk_put(ts_dev->tsc_ick);
++#ifdef CONFIG_PM
++static int titsc_suspend(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
++ unsigned int idle;
++
++ if (device_may_wakeup(tscadc_dev->dev)) {
++ idle = titsc_readl(ts_dev, REG_IRQENABLE);
++ titsc_writel(ts_dev, REG_IRQENABLE,
++ (idle | IRQENB_HW_PEN));
++ titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
++ }
++ return 0;
++}
+
+- kfree(ts_dev);
++static int titsc_resume(struct device *dev)
++{
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ struct titsc *ts_dev = tscadc_dev->tsc;
+
+- platform_set_drvdata(pdev, NULL);
++ if (device_may_wakeup(tscadc_dev->dev)) {
++ titsc_writel(ts_dev, REG_IRQWAKEUP,
++ 0x00);
++ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
++ }
++ titsc_step_config(ts_dev);
++ titsc_writel(ts_dev, REG_FIFO0THR,
++ ts_dev->steps_to_configure);
+ return 0;
+ }
+
++static const struct dev_pm_ops titsc_pm_ops = {
++ .suspend = titsc_suspend,
++ .resume = titsc_resume,
++};
++#define TITSC_PM_OPS (&titsc_pm_ops)
++#else
++#define TITSC_PM_OPS NULL
++#endif
++
+ static struct platform_driver ti_tsc_driver = {
+ .probe = titsc_probe,
+ .remove = __devexit_p(titsc_remove),
+ .driver = {
+ .name = "tsc",
+ .owner = THIS_MODULE,
++ .pm = TITSC_PM_OPS,
+ },
+ };
+ module_platform_driver(ti_tsc_driver);
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index 14df67b..d812be4 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -24,6 +24,7 @@
+ #include <linux/pm_runtime.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/input/ti_am335x_tsc.h>
+
+ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+@@ -62,15 +63,19 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ struct resource *res;
+ struct clk *clk;
+ struct mfd_tscadc_board *pdata = pdev->dev.platform_data;
++ struct mfd_cell *cell;
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
++ int tsc_wires;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
++ tsc_wires = pdata->tsc_init->wires;
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no memory resource defined.\n");
+@@ -161,6 +166,12 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(tscadc, REG_CTRL, ctrl);
+
++ /* TSC Cell */
++ cell = &tscadc->cells[TSC_CELL];
++ cell->name = "tsc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+ TSCADC_CELLS, NULL, 0, NULL);
+ if (err < 0)
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index b7232b1..fc18b2e 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -47,6 +47,7 @@
+ #define STEPENB_MASK (0x1FFFF << 0)
+ #define STEPENB(val) ((val) << 0)
+ #define STPENB_STEPENB STEPENB(0x1FFFF)
++#define STPENB_STEPENB_TC STEPENB(0x1FFF)
+
+ /* IRQ enable */
+ #define IRQENB_HW_PEN BIT(0)
+@@ -120,7 +121,11 @@
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
+
+-#define TSCADC_CELLS 0
++#define TSCADC_CELLS 1
++
++enum tscadc_cells {
++ TSC_CELL,
++};
+
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
+@@ -132,6 +137,9 @@ struct ti_tscadc_dev {
+ void __iomem *tscadc_base;
+ int irq;
+ struct mfd_cell cells[TSCADC_CELLS];
++
++ /* tsc device */
++ struct titsc *tsc;
+ };
+
+ #endif
diff --git a/patches/linux-3.7/0053-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch b/patches/linux-3.7/0053-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
new file mode 100644
index 0000000..ab6df93
--- /dev/null
+++ b/patches/linux-3.7/0053-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
@@ -0,0 +1,419 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Tue, 16 Oct 2012 07:25:45 +0000
+Subject: [PATCH] IIO : ADC: tiadc: Add support of TI's ADC driver
+
+This patch adds support for TI's ADC driver.
+This is a multifunctional device.
+Analog input lines are provided on which
+voltage measurements can be carried out.
+You can have upto 8 input lines.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+Acked-by: Jonathan Cameron <jic23@kernel.org>
+---
+ drivers/iio/adc/Kconfig | 7 +
+ drivers/iio/adc/Makefile | 1 +
+ drivers/iio/adc/ti_am335x_adc.c | 260 +++++++++++++++++++++++++++
+ drivers/mfd/ti_am335x_tscadc.c | 18 +-
+ include/linux/mfd/ti_am335x_tscadc.h | 9 +-
+ include/linux/platform_data/ti_am335x_adc.h | 14 ++
+ 6 files changed, 307 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/iio/adc/ti_am335x_adc.c
+ create mode 100644 include/linux/platform_data/ti_am335x_adc.h
+
+diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
+index 4927581..1401ed1 100644
+--- a/drivers/iio/adc/Kconfig
++++ b/drivers/iio/adc/Kconfig
+@@ -60,4 +60,11 @@ config LP8788_ADC
+ help
+ Say yes here to build support for TI LP8788 ADC.
+
++config TI_AM335X_ADC
++ tristate "TI's ADC driver"
++ depends on MFD_TI_AM335X_TSCADC
++ help
++ Say yes here to build support for Texas Instruments ADC
++ driver which is also a MFD client.
++
+ endmenu
+diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
+index 900995d..4410a90 100644
+--- a/drivers/iio/adc/Makefile
++++ b/drivers/iio/adc/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_AD7476) += ad7476.o
+ obj-$(CONFIG_AD7791) += ad7791.o
+ obj-$(CONFIG_AT91_ADC) += at91_adc.o
+ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
++obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+new file mode 100644
+index 0000000..02a43c8
+--- /dev/null
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -0,0 +1,260 @@
++/*
++ * TI ADC MFD driver
++ *
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.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 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/init.h>
++#include <linux/kernel.h>
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/iio/iio.h>
++
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++
++struct tiadc_device {
++ struct ti_tscadc_dev *mfd_tscadc;
++ int channels;
++};
++
++static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
++{
++ return readl(adc->mfd_tscadc->tscadc_base + reg);
++}
++
++static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
++ unsigned int val)
++{
++ writel(val, adc->mfd_tscadc->tscadc_base + reg);
++}
++
++static void tiadc_step_config(struct tiadc_device *adc_dev)
++{
++ unsigned int stepconfig;
++ int i, channels = 0, steps;
++
++ /*
++ * There are 16 configurable steps and 8 analog input
++ * lines available which are shared between Touchscreen and ADC.
++ *
++ * Steps backwards i.e. from 16 towards 0 are used by ADC
++ * depending on number of input lines needed.
++ * Channel would represent which analog input
++ * needs to be given to ADC to digitalize data.
++ */
++
++ steps = TOTAL_STEPS - adc_dev->channels;
++ channels = TOTAL_CHANNELS - adc_dev->channels;
++
++ stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
++
++ for (i = (steps + 1); i <= TOTAL_STEPS; i++) {
++ tiadc_writel(adc_dev, REG_STEPCONFIG(i),
++ stepconfig | STEPCONFIG_INP(channels));
++ tiadc_writel(adc_dev, REG_STEPDELAY(i),
++ STEPCONFIG_OPENDLY);
++ channels++;
++ }
++ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++}
++
++static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
++{
++ struct iio_chan_spec *chan_array;
++ int i;
++
++ indio_dev->num_channels = channels;
++ chan_array = kcalloc(indio_dev->num_channels,
++ sizeof(struct iio_chan_spec), GFP_KERNEL);
++
++ if (chan_array == NULL)
++ return -ENOMEM;
++
++ for (i = 0; i < (indio_dev->num_channels); i++) {
++ struct iio_chan_spec *chan = chan_array + i;
++ chan->type = IIO_VOLTAGE;
++ chan->indexed = 1;
++ chan->channel = i;
++ chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ }
++
++ indio_dev->channels = chan_array;
++
++ return indio_dev->num_channels;
++}
++
++static void tiadc_channels_remove(struct iio_dev *indio_dev)
++{
++ kfree(indio_dev->channels);
++}
++
++static int tiadc_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ int *val, int *val2, long mask)
++{
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ int i;
++ unsigned int fifo1count, readx1;
++
++ /*
++ * When the sub-system is first enabled,
++ * the sequencer will always start with the
++ * lowest step (1) and continue until step (16).
++ * For ex: If we have enabled 4 ADC channels and
++ * currently use only 1 out of them, the
++ * sequencer still configures all the 4 steps,
++ * leading to 3 unwanted data.
++ * Hence we need to flush out this data.
++ */
++
++ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
++ for (i = 0; i < fifo1count; i++) {
++ readx1 = tiadc_readl(adc_dev, REG_FIFO1);
++ if (i == chan->channel)
++ *val = readx1 & 0xfff;
++ }
++ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
++
++ return IIO_VAL_INT;
++}
++
++static const struct iio_info tiadc_info = {
++ .read_raw = &tiadc_read_raw,
++};
++
++static int __devinit tiadc_probe(struct platform_device *pdev)
++{
++ struct iio_dev *indio_dev;
++ struct tiadc_device *adc_dev;
++ struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
++ struct mfd_tscadc_board *pdata;
++ int err;
++
++ pdata = tscadc_dev->dev->platform_data;
++ if (!pdata || !pdata->adc_init) {
++ dev_err(&pdev->dev, "Could not find platform data\n");
++ return -EINVAL;
++ }
++
++ indio_dev = iio_device_alloc(sizeof(struct tiadc_device));
++ if (indio_dev == NULL) {
++ dev_err(&pdev->dev, "failed to allocate iio device\n");
++ err = -ENOMEM;
++ goto err_ret;
++ }
++ adc_dev = iio_priv(indio_dev);
++
++ adc_dev->mfd_tscadc = tscadc_dev;
++ adc_dev->channels = pdata->adc_init->adc_channels;
++
++ indio_dev->dev.parent = &pdev->dev;
++ indio_dev->name = dev_name(&pdev->dev);
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->info = &tiadc_info;
++
++ tiadc_step_config(adc_dev);
++
++ err = tiadc_channel_init(indio_dev, adc_dev->channels);
++ if (err < 0)
++ goto err_free_device;
++
++ err = iio_device_register(indio_dev);
++ if (err)
++ goto err_free_channels;
++
++ platform_set_drvdata(pdev, indio_dev);
++
++ return 0;
++
++err_free_channels:
++ tiadc_channels_remove(indio_dev);
++err_free_device:
++ iio_device_free(indio_dev);
++err_ret:
++ return err;
++}
++
++static int __devexit tiadc_remove(struct platform_device *pdev)
++{
++ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
++
++ iio_device_unregister(indio_dev);
++ tiadc_channels_remove(indio_dev);
++
++ iio_device_free(indio_dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int tiadc_suspend(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
++ unsigned int idle;
++
++ if (!device_may_wakeup(tscadc_dev->dev)) {
++ idle = tiadc_readl(adc_dev, REG_CTRL);
++ idle &= ~(CNTRLREG_TSCSSENB);
++ tiadc_writel(adc_dev, REG_CTRL, (idle |
++ CNTRLREG_POWERDOWN));
++ }
++
++ return 0;
++}
++
++static int tiadc_resume(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct tiadc_device *adc_dev = iio_priv(indio_dev);
++ unsigned int restore;
++
++ /* Make sure ADC is powered up */
++ restore = tiadc_readl(adc_dev, REG_CTRL);
++ restore &= ~(CNTRLREG_POWERDOWN);
++ tiadc_writel(adc_dev, REG_CTRL, restore);
++
++ tiadc_step_config(adc_dev);
++
++ return 0;
++}
++
++static const struct dev_pm_ops tiadc_pm_ops = {
++ .suspend = tiadc_suspend,
++ .resume = tiadc_resume,
++};
++#define TIADC_PM_OPS (&tiadc_pm_ops)
++#else
++#define TIADC_PM_OPS NULL
++#endif
++
++static struct platform_driver tiadc_driver = {
++ .driver = {
++ .name = "tiadc",
++ .owner = THIS_MODULE,
++ .pm = TIADC_PM_OPS,
++ },
++ .probe = tiadc_probe,
++ .remove = __devexit_p(tiadc_remove),
++};
++
++module_platform_driver(tiadc_driver);
++
++MODULE_DESCRIPTION("TI ADC controller driver");
++MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index d812be4..e947dd8 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -25,6 +25,7 @@
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
+
+ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+@@ -67,14 +68,23 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
+- int tsc_wires;
++ int tsc_wires, adc_channels = 0, total_channels;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+ return -EINVAL;
+ }
+
++ if (pdata->adc_init)
++ adc_channels = pdata->adc_init->adc_channels;
++
+ tsc_wires = pdata->tsc_init->wires;
++ total_channels = tsc_wires + adc_channels;
++
++ if (total_channels > 8) {
++ dev_err(&pdev->dev, "Number of i/p channels more than 8\n");
++ return -EINVAL;
++ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+@@ -172,6 +182,12 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ cell->platform_data = tscadc;
+ cell->pdata_size = sizeof(*tscadc);
+
++ /* ADC Cell */
++ cell = &tscadc->cells[ADC_CELL];
++ cell->name = "tiadc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+ TSCADC_CELLS, NULL, 0, NULL);
+ if (err < 0)
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index fc18b2e..c79ad5d 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -120,15 +120,19 @@
+
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
++#define TOTAL_STEPS 16
++#define TOTAL_CHANNELS 8
+
+-#define TSCADC_CELLS 1
++#define TSCADC_CELLS 2
+
+ enum tscadc_cells {
+ TSC_CELL,
++ ADC_CELL,
+ };
+
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
++ struct adc_data *adc_init;
+ };
+
+ struct ti_tscadc_dev {
+@@ -140,6 +144,9 @@ struct ti_tscadc_dev {
+
+ /* tsc device */
+ struct titsc *tsc;
++
++ /* adc device */
++ struct adc_device *adc;
+ };
+
+ #endif
+diff --git a/include/linux/platform_data/ti_am335x_adc.h b/include/linux/platform_data/ti_am335x_adc.h
+new file mode 100644
+index 0000000..e41d583
+--- /dev/null
++++ b/include/linux/platform_data/ti_am335x_adc.h
+@@ -0,0 +1,14 @@
++#ifndef __LINUX_TI_AM335X_ADC_H
++#define __LINUX_TI_AM335X_ADC_H
++
++/**
++ * struct adc_data ADC Input information
++ * @adc_channels: Number of analog inputs
++ * available for ADC.
++ */
++
++struct adc_data {
++ unsigned int adc_channels;
++};
++
++#endif
diff --git a/patches/linux-3.7/0054-input-ti_am335x_tsc-Make-steps-enable-configurable.patch b/patches/linux-3.7/0054-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
new file mode 100644
index 0000000..a2fe55c
--- /dev/null
+++ b/patches/linux-3.7/0054-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
@@ -0,0 +1,73 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:16 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Make steps enable configurable
+
+Current code has hard coded value written to
+step enable bits. Now the bits are updated based
+on how many steps are needed to be configured got
+from platform data.
+
+The user needs to take care not to exceed
+the count more than 16. While using ADC and TSC
+one should take care to set this parameter correctly.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 10 ++++++++--
+ include/linux/mfd/ti_am335x_tscadc.h | 1 -
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 7a18a8a..4369224 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -39,6 +39,7 @@ struct titsc {
+ unsigned int irq;
+ unsigned int wires;
+ unsigned int x_plate_resistance;
++ unsigned int enable_bits;
+ bool pen_down;
+ int steps_to_configure;
+ };
+@@ -57,6 +58,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
++ unsigned int stepenable = 0;
+ int i, total_steps;
+
+ /* Configure the Step registers */
+@@ -128,7 +130,11 @@ static void titsc_step_config(struct titsc *ts_dev)
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
++ for (i = 0; i <= (total_steps + 2); i++)
++ stepenable |= 1 << i;
++ ts_dev->enable_bits = stepenable;
++
++ titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
+ }
+
+ static void titsc_read_coordinates(struct titsc *ts_dev,
+@@ -250,7 +256,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+
+ titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+
+- titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
++ titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
+ return IRQ_HANDLED;
+ }
+
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index c79ad5d..23e4f33 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -47,7 +47,6 @@
+ #define STEPENB_MASK (0x1FFFF << 0)
+ #define STEPENB(val) ((val) << 0)
+ #define STPENB_STEPENB STEPENB(0x1FFFF)
+-#define STPENB_STEPENB_TC STEPENB(0x1FFF)
+
+ /* IRQ enable */
+ #define IRQENB_HW_PEN BIT(0)
diff --git a/patches/linux-3.7/0055-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch b/patches/linux-3.7/0055-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
new file mode 100644
index 0000000..7c99ed2
--- /dev/null
+++ b/patches/linux-3.7/0055-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
@@ -0,0 +1,328 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:17 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Order of TSC wires connect, made
+ configurable
+
+The driver expected touchscreen wires(XP,XN,YP,YN)
+to be connected in a particular order.
+Making changes to accept this as platform data.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 156 ++++++++++++++++++++++++++---
+ include/linux/input/ti_am335x_tsc.h | 12 +++
+ include/linux/mfd/ti_am335x_tscadc.h | 10 +-
+ 3 files changed, 159 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 4369224..6a817a8 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -33,6 +33,17 @@
+ #define SEQ_SETTLE 275
+ #define MAX_12BIT ((1 << 12) - 1)
+
++/*
++ * Refer to function regbit_map() to
++ * map the values in the matrix.
++ */
++static int config[4][4] = {
++ {1, 0, 1, 0},
++ {2, 3, 2, 3},
++ {4, 5, 4, 5},
++ {0, 6, 0, 6}
++};
++
+ struct titsc {
+ struct input_dev *input;
+ struct ti_tscadc_dev *mfd_tscadc;
+@@ -42,6 +53,9 @@ struct titsc {
+ unsigned int enable_bits;
+ bool pen_down;
+ int steps_to_configure;
++ int config_inp[20];
++ int bit_xp, bit_xn, bit_yp, bit_yn;
++ int inp_xp, inp_xn, inp_yp, inp_yn;
+ };
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+@@ -55,6 +69,107 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ writel(val, tsc->mfd_tscadc->tscadc_base + reg);
+ }
+
++/*
++ * Each of the analog lines are mapped
++ * with one or two register bits,
++ * which can be either pulled high/low
++ * depending on the value to be read.
++ */
++static int regbit_map(int val)
++{
++ int map_bits = 0;
++
++ switch (val) {
++ case 1:
++ map_bits = XPP;
++ break;
++ case 2:
++ map_bits = XNP;
++ break;
++ case 3:
++ map_bits = XNN;
++ break;
++ case 4:
++ map_bits = YPP;
++ break;
++ case 5:
++ map_bits = YPN;
++ break;
++ case 6:
++ map_bits = YNN;
++ break;
++ }
++
++ return map_bits;
++}
++
++static int titsc_config_wires(struct titsc *ts_dev)
++{
++ int analog_line[10], wire_order[10];
++ int i, temp_bits, err;
++
++ for (i = 0; i < 4; i++) {
++ /*
++ * Get the order in which TSC wires are attached
++ * w.r.t. each of the analog input lines on the EVM.
++ */
++ analog_line[i] = ts_dev->config_inp[i] & 0xF0;
++ analog_line[i] = analog_line[i] >> 4;
++
++ wire_order[i] = ts_dev->config_inp[i] & 0x0F;
++ }
++
++ for (i = 0; i < 4; i++) {
++ switch (wire_order[i]) {
++ case 0:
++ temp_bits = config[analog_line[i]][0];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_xp = regbit_map(temp_bits);
++ ts_dev->inp_xp = analog_line[i];
++ break;
++ }
++ case 1:
++ temp_bits = config[analog_line[i]][1];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_xn = regbit_map(temp_bits);
++ ts_dev->inp_xn = analog_line[i];
++ break;
++ }
++ case 2:
++ temp_bits = config[analog_line[i]][2];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_yp = regbit_map(temp_bits);
++ ts_dev->inp_yp = analog_line[i];
++ break;
++ }
++ case 3:
++ temp_bits = config[analog_line[i]][3];
++ if (temp_bits == 0) {
++ err = -EINVAL;
++ goto ret;
++ } else {
++ ts_dev->bit_yn = regbit_map(temp_bits);
++ ts_dev->inp_yn = analog_line[i];
++ break;
++ }
++ }
++ }
++
++ return 0;
++
++ret:
++ return err;
++}
++
+ static void titsc_step_config(struct titsc *ts_dev)
+ {
+ unsigned int config;
+@@ -65,18 +180,18 @@ static void titsc_step_config(struct titsc *ts_dev)
+ total_steps = 2 * ts_dev->steps_to_configure;
+
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
++ STEPCONFIG_AVG_16 | ts_dev->bit_xp;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+ break;
+ case 5:
+- config |= STEPCONFIG_YNN |
+- STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
+- STEPCONFIG_YPP;
++ config |= ts_dev->bit_yn |
++ STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
++ ts_dev->bit_yp;
+ break;
+ case 8:
+- config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
++ config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
+ break;
+ }
+
+@@ -87,18 +202,18 @@ static void titsc_step_config(struct titsc *ts_dev)
+
+ config = 0;
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
++ STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+ STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
+ switch (ts_dev->wires) {
+ case 4:
+- config |= STEPCONFIG_YPP;
++ config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+ break;
+ case 5:
+- config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
+- STEPCONFIG_XNP | STEPCONFIG_YPN;
++ config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
++ ts_dev->bit_xn | ts_dev->bit_yp;
+ break;
+ case 8:
+- config |= STEPCONFIG_YPP;
++ config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
+ break;
+ }
+
+@@ -109,9 +224,9 @@ static void titsc_step_config(struct titsc *ts_dev)
+
+ config = 0;
+ /* Charge step configuration */
+- config = STEPCONFIG_XPP | STEPCONFIG_YNN |
++ config = ts_dev->bit_xp | ts_dev->bit_yn |
+ STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
+- STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
++ STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
+
+ titsc_writel(ts_dev, REG_CHARGECONFIG, config);
+ titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
+@@ -119,13 +234,14 @@ static void titsc_step_config(struct titsc *ts_dev)
+ config = 0;
+ /* Configure to calculate pressure */
+ config = STEPCONFIG_MODE_HWSYNC |
+- STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
+- STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
++ STEPCONFIG_AVG_16 | ts_dev->bit_yp |
++ ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
++ STEPCONFIG_INP(ts_dev->inp_xp);
+ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
+ STEPCONFIG_OPENDLY);
+
+- config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
++ config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1;
+ titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
+ titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
+ STEPCONFIG_OPENDLY);
+@@ -295,6 +411,8 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ ts_dev->wires = pdata->tsc_init->wires;
+ ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
+ ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
++ memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
++ sizeof(pdata->tsc_init->wire_config));
+
+ err = request_irq(ts_dev->irq, titsc_irq,
+ 0, pdev->dev.driver->name, ts_dev);
+@@ -304,6 +422,11 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+ }
+
+ titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
++ err = titsc_config_wires(ts_dev);
++ if (err) {
++ dev_err(&pdev->dev, "wrong i/p wire configuration\n");
++ goto err_free_irq;
++ }
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+
+@@ -373,6 +496,7 @@ static int titsc_resume(struct device *dev)
+ 0x00);
+ titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+ }
++ titsc_config_wires(ts_dev);
+ titsc_step_config(ts_dev);
+ titsc_writel(ts_dev, REG_FIFO0THR,
+ ts_dev->steps_to_configure);
+diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
+index 49269a2..6a66b4d 100644
+--- a/include/linux/input/ti_am335x_tsc.h
++++ b/include/linux/input/ti_am335x_tsc.h
+@@ -12,12 +12,24 @@
+ * A step configured to read a single
+ * co-ordinate value, can be applied
+ * more number of times for better results.
++ * @wire_config: Different EVM's could have a different order
++ * for connecting wires on touchscreen.
++ * We need to provide an 8 bit number where in
++ * the 1st four bits represent the analog lines
++ * and the next 4 bits represent positive/
++ * negative terminal on that input line.
++ * Notations to represent the input lines and
++ * terminals resoectively is as follows:
++ * AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
++ * XP = 0, XN = 1, YP = 2, YN = 3.
++ *
+ */
+
+ struct tsc_data {
+ int wires;
+ int x_plate_resistance;
+ int steps_to_configure;
++ int wire_config[10];
+ };
+
+ #endif
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 23e4f33..9624fea 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -72,8 +72,6 @@
+ #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
+ #define STEPCONFIG_INP_MASK (0xF << 19)
+ #define STEPCONFIG_INP(val) ((val) << 19)
+-#define STEPCONFIG_INP_AN2 STEPCONFIG_INP(2)
+-#define STEPCONFIG_INP_AN3 STEPCONFIG_INP(3)
+ #define STEPCONFIG_INP_AN4 STEPCONFIG_INP(4)
+ #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
+ #define STEPCONFIG_FIFO1 BIT(26)
+@@ -95,7 +93,6 @@
+ #define STEPCHARGE_INM_AN1 STEPCHARGE_INM(1)
+ #define STEPCHARGE_INP_MASK (0xF << 19)
+ #define STEPCHARGE_INP(val) ((val) << 19)
+-#define STEPCHARGE_INP_AN1 STEPCHARGE_INP(1)
+ #define STEPCHARGE_RFM_MASK (3 << 23)
+ #define STEPCHARGE_RFM(val) ((val) << 23)
+ #define STEPCHARGE_RFM_XNUR STEPCHARGE_RFM(1)
+@@ -117,6 +114,13 @@
+ #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3)
+ #define CNTRLREG_TSCENB BIT(7)
+
++#define XPP STEPCONFIG_XPP
++#define XNP STEPCONFIG_XNP
++#define XNN STEPCONFIG_XNN
++#define YPP STEPCONFIG_YPP
++#define YPN STEPCONFIG_YPN
++#define YNN STEPCONFIG_YNN
++
+ #define ADC_CLK 3000000
+ #define MAX_CLK_DIV 7
+ #define TOTAL_STEPS 16
diff --git a/patches/linux-3.7/0056-input-ti_am335x_tsc-Add-variance-filters.patch b/patches/linux-3.7/0056-input-ti_am335x_tsc-Add-variance-filters.patch
new file mode 100644
index 0000000..c1da777
--- /dev/null
+++ b/patches/linux-3.7/0056-input-ti_am335x_tsc-Add-variance-filters.patch
@@ -0,0 +1,74 @@
+From: "Patil, Rachna" <rachna@ti.com>
+Date: Mon, 22 Oct 2012 10:15:18 +0000
+Subject: [PATCH] input: ti_am335x_tsc: Add variance filters
+
+Only fine tuning variance present in tslib utility
+does not help in removing all the wanted ADC noise.
+This logic of filtering is necessary to get this
+touchscreen to work finely.
+
+Signed-off-by: Patil, Rachna <rachna@ti.com>
+---
+ drivers/input/touchscreen/ti_am335x_tsc.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 6a817a8..7a26810 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -32,6 +32,8 @@
+ #define ADCFSM_STEPID 0x10
+ #define SEQ_SETTLE 275
+ #define MAX_12BIT ((1 << 12) - 1)
++#define TSCADC_DELTA_X 15
++#define TSCADC_DELTA_Y 15
+
+ /*
+ * Refer to function regbit_map() to
+@@ -51,6 +53,8 @@ struct titsc {
+ unsigned int wires;
+ unsigned int x_plate_resistance;
+ unsigned int enable_bits;
++ unsigned int bckup_x;
++ unsigned int bckup_y;
+ bool pen_down;
+ int steps_to_configure;
+ int config_inp[20];
+@@ -309,12 +313,18 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ unsigned int z1, z2, z;
+ unsigned int fsm;
+ unsigned int fifo1count, fifo0count;
++ unsigned int diffx = 0, diffy = 0;
+ int i;
+
+ status = titsc_readl(ts_dev, REG_IRQSTATUS);
+ if (status & IRQENB_FIFO0THRES) {
+ titsc_read_coordinates(ts_dev, &x, &y);
+
++ diffx = abs(x - (ts_dev->bckup_x));
++ diffy = abs(y - (ts_dev->bckup_y));
++ ts_dev->bckup_x = x;
++ ts_dev->bckup_y = y;
++
+ z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
+ z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
+
+@@ -338,7 +348,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ z /= z1;
+ z = (z + 2047) >> 12;
+
+- if (z <= MAX_12BIT) {
++ if ((diffx < TSCADC_DELTA_X) &&
++ (diffy < TSCADC_DELTA_Y) && (z <= MAX_12BIT)) {
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_abs(input_dev, ABS_PRESSURE, z);
+@@ -361,6 +372,8 @@ static irqreturn_t titsc_irq(int irq, void *dev)
+ fsm = titsc_readl(ts_dev, REG_ADCFSM);
+ if (fsm == ADCFSM_STEPID) {
+ ts_dev->pen_down = false;
++ ts_dev->bckup_x = 0;
++ ts_dev->bckup_y = 0;
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+ input_sync(input_dev);
diff --git a/patches/linux-3.7/0057-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch b/patches/linux-3.7/0057-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
new file mode 100644
index 0000000..58d6720
--- /dev/null
+++ b/patches/linux-3.7/0057-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
@@ -0,0 +1,182 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:37:24 +0300
+Subject: [PATCH] ti_tscadc: Update with IIO map interface & deal with partial
+ activation
+
+Add an IIO map interface that consumers can use.
+While we're here fix the mfd device in the case where a subdevice
+might not be activated.
+---
+ drivers/iio/adc/ti_am335x_adc.c | 53 ++++++++++++++++++++++++++++------
+ drivers/mfd/ti_am335x_tscadc.c | 30 +++++++++++++------
+ include/linux/mfd/ti_am335x_tscadc.h | 8 ++---
+ 3 files changed, 68 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index 02a43c8..d48fd79 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -20,8 +20,9 @@
+ #include <linux/slab.h>
+ #include <linux/interrupt.h>
+ #include <linux/platform_device.h>
+-#include <linux/io.h>
+ #include <linux/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/driver.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+@@ -29,6 +30,8 @@
+ struct tiadc_device {
+ struct ti_tscadc_dev *mfd_tscadc;
+ int channels;
++ char *buf;
++ struct iio_map *map;
+ };
+
+ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+@@ -75,25 +78,57 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ {
+ struct iio_chan_spec *chan_array;
+- int i;
+-
+- indio_dev->num_channels = channels;
+- chan_array = kcalloc(indio_dev->num_channels,
+- sizeof(struct iio_chan_spec), GFP_KERNEL);
++ struct iio_chan_spec *chan;
++ char *s;
++ int i, len, size, ret;
+
++ size = indio_dev->num_channels * (sizeof(struct iio_chan_spec) + 6);
++ chan_array = kzalloc(size, GFP_KERNEL);
+ if (chan_array == NULL)
+ return -ENOMEM;
+
+- for (i = 0; i < (indio_dev->num_channels); i++) {
+- struct iio_chan_spec *chan = chan_array + i;
++ /* buffer space is after the array */
++ s = (char *)(chan_array + indio_dev->num_channels);
++ chan = chan_array;
++ for (i = 0; i < indio_dev->num_channels; i++, chan++, s += len + 1) {
++
++ len = sprintf(s, "AIN%d", i);
++
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->channel = i;
+- chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
++ chan->datasheet_name = s;
++ chan->scan_type.sign = 'u';
++ chan->scan_type.realbits = 12;
++ chan->scan_type.storagebits = 32;
++ chan->scan_type.shift = 0;
+ }
+
+ indio_dev->channels = chan_array;
+
++ size = (indio_dev->num_channels + 1) * sizeof(struct iio_map);
++ adc_dev->map = kzalloc(size, GFP_KERNEL);
++ if (adc_dev->map == NULL) {
++ kfree(chan_array);
++ return -ENOMEM;
++ }
++
++ for (i = 0; i < indio_dev->num_channels; i++) {
++ adc_dev->map[i].adc_channel_label = chan_array[i].datasheet_name;
++ adc_dev->map[i].consumer_dev_name = "any";
++ adc_dev->map[i].consumer_channel = chan_array[i].datasheet_name;
++ }
++ adc_dev->map[i].adc_channel_label = NULL;
++ adc_dev->map[i].consumer_dev_name = NULL;
++ adc_dev->map[i].consumer_channel = NULL;
++
++ ret = iio_map_array_register(indio_dev, adc_dev->map);
++ if (ret != 0) {
++ kfree(adc_dev->map);
++ kfree(chan_array);
++ return -ENOMEM;
++ }
++
+ return indio_dev->num_channels;
+ }
+
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index e947dd8..cbb8b70c 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -176,26 +176,38 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ ctrl |= CNTRLREG_TSCSSENB;
+ tscadc_writel(tscadc, REG_CTRL, ctrl);
+
++ tscadc->used_cells = 0;
++ tscadc->tsc_cell = -1;
++ tscadc->adc_cell = -1;
++
+ /* TSC Cell */
+- cell = &tscadc->cells[TSC_CELL];
+- cell->name = "tsc";
+- cell->platform_data = tscadc;
+- cell->pdata_size = sizeof(*tscadc);
++ if (tsc_wires > 0) {
++ tscadc->tsc_cell = tscadc->used_cells;
++ cell = &tscadc->cells[tscadc->used_cells++];
++ cell->name = "tsc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++ }
+
+ /* ADC Cell */
+- cell = &tscadc->cells[ADC_CELL];
+- cell->name = "tiadc";
+- cell->platform_data = tscadc;
+- cell->pdata_size = sizeof(*tscadc);
++ if (adc_channels > 0) {
++ tscadc->adc_cell = tscadc->used_cells;
++ cell = &tscadc->cells[tscadc->used_cells++];
++ cell->name = "tiadc";
++ cell->platform_data = tscadc;
++ cell->pdata_size = sizeof(*tscadc);
++ }
+
+ err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
+- TSCADC_CELLS, NULL, 0, NULL);
++ tscadc->used_cells, NULL, 0, NULL);
+ if (err < 0)
+ goto err_disable_clk;
+
+ device_init_wakeup(&pdev->dev, true);
+ platform_set_drvdata(pdev, tscadc);
+
++ dev_info(&pdev->dev, "Initialized OK.\n");
++
+ return 0;
+
+ err_disable_clk:
+diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
+index 9624fea..50a245f 100644
+--- a/include/linux/mfd/ti_am335x_tscadc.h
++++ b/include/linux/mfd/ti_am335x_tscadc.h
+@@ -128,11 +128,6 @@
+
+ #define TSCADC_CELLS 2
+
+-enum tscadc_cells {
+- TSC_CELL,
+- ADC_CELL,
+-};
+-
+ struct mfd_tscadc_board {
+ struct tsc_data *tsc_init;
+ struct adc_data *adc_init;
+@@ -143,6 +138,9 @@ struct ti_tscadc_dev {
+ struct regmap *regmap_tscadc;
+ void __iomem *tscadc_base;
+ int irq;
++ int used_cells; /* 0-2 */
++ int tsc_cell; /* -1 if not used */
++ int adc_cell; /* -1 if not used */
+ struct mfd_cell cells[TSCADC_CELLS];
+
+ /* tsc device */
diff --git a/patches/linux-3.7/0058-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch b/patches/linux-3.7/0058-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
new file mode 100644
index 0000000..d5e8362
--- /dev/null
+++ b/patches/linux-3.7/0058-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
@@ -0,0 +1,183 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 14:01:05 +0300
+Subject: [PATCH] ti_tscadc: Match mfd sub devices to regmap interface
+
+---
+ drivers/iio/adc/ti_am335x_adc.c | 27 +++++++++++++++++++--------
+ drivers/input/touchscreen/ti_am335x_tsc.c | 16 +++++++++++++---
+ drivers/mfd/ti_am335x_tscadc.c | 7 +++++--
+ 3 files changed, 37 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
+index d48fd79..5f325c1 100644
+--- a/drivers/iio/adc/ti_am335x_adc.c
++++ b/drivers/iio/adc/ti_am335x_adc.c
+@@ -23,7 +23,9 @@
+ #include <linux/iio/iio.h>
+ #include <linux/iio/machine.h>
+ #include <linux/iio/driver.h>
++#include <linux/regmap.h>
+
++#include <linux/io.h>
+ #include <linux/mfd/ti_am335x_tscadc.h>
+ #include <linux/platform_data/ti_am335x_adc.h>
+
+@@ -36,13 +38,17 @@ struct tiadc_device {
+
+ static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
+ {
+- return readl(adc->mfd_tscadc->tscadc_base + reg);
++ unsigned int val;
++
++ val = (unsigned int)-1;
++ regmap_read(adc->mfd_tscadc->regmap_tscadc, reg, &val);
++ return val;
+ }
+
+ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, adc->mfd_tscadc->tscadc_base + reg);
++ regmap_write(adc->mfd_tscadc->regmap_tscadc, reg, val);
+ }
+
+ static void tiadc_step_config(struct tiadc_device *adc_dev)
+@@ -75,22 +81,24 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
+ tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+ }
+
+-static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
++static int tiadc_channel_init(struct iio_dev *indio_dev,
++ struct tiadc_device *adc_dev)
+ {
+ struct iio_chan_spec *chan_array;
+ struct iio_chan_spec *chan;
+ char *s;
+ int i, len, size, ret;
++ int channels = adc_dev->channels;
+
+- size = indio_dev->num_channels * (sizeof(struct iio_chan_spec) + 6);
++ size = channels * (sizeof(struct iio_chan_spec) + 6);
+ chan_array = kzalloc(size, GFP_KERNEL);
+ if (chan_array == NULL)
+ return -ENOMEM;
+
+ /* buffer space is after the array */
+- s = (char *)(chan_array + indio_dev->num_channels);
++ s = (char *)(chan_array + channels);
+ chan = chan_array;
+- for (i = 0; i < indio_dev->num_channels; i++, chan++, s += len + 1) {
++ for (i = 0; i < channels; i++, chan++, s += len + 1) {
+
+ len = sprintf(s, "AIN%d", i);
+
+@@ -105,8 +113,9 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
+ }
+
+ indio_dev->channels = chan_array;
++ indio_dev->num_channels = channels;
+
+- size = (indio_dev->num_channels + 1) * sizeof(struct iio_map);
++ size = (channels + 1) * sizeof(struct iio_map);
+ adc_dev->map = kzalloc(size, GFP_KERNEL);
+ if (adc_dev->map == NULL) {
+ kfree(chan_array);
+@@ -203,7 +212,7 @@ static int __devinit tiadc_probe(struct platform_device *pdev)
+
+ tiadc_step_config(adc_dev);
+
+- err = tiadc_channel_init(indio_dev, adc_dev->channels);
++ err = tiadc_channel_init(indio_dev, adc_dev);
+ if (err < 0)
+ goto err_free_device;
+
+@@ -213,6 +222,8 @@ static int __devinit tiadc_probe(struct platform_device *pdev)
+
+ platform_set_drvdata(pdev, indio_dev);
+
++ dev_info(&pdev->dev, "Initialized\n");
++
+ return 0;
+
+ err_free_channels:
+diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
+index 7a26810..d09e1a7 100644
+--- a/drivers/input/touchscreen/ti_am335x_tsc.c
++++ b/drivers/input/touchscreen/ti_am335x_tsc.c
+@@ -26,6 +26,7 @@
+ #include <linux/io.h>
+ #include <linux/input/ti_am335x_tsc.h>
+ #include <linux/delay.h>
++#include <linux/regmap.h>
+
+ #include <linux/mfd/ti_am335x_tscadc.h>
+
+@@ -64,13 +65,17 @@ struct titsc {
+
+ static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
+ {
+- return readl(ts->mfd_tscadc->tscadc_base + reg);
++ unsigned int val;
++
++ val = (unsigned int)-1;
++ regmap_read(ts->mfd_tscadc->regmap_tscadc, reg, &val);
++ return val;
+ }
+
+ static void titsc_writel(struct titsc *tsc, unsigned int reg,
+ unsigned int val)
+ {
+- writel(val, tsc->mfd_tscadc->tscadc_base + reg);
++ regmap_write(tsc->mfd_tscadc->regmap_tscadc, reg, val);
+ }
+
+ /*
+@@ -455,10 +460,15 @@ static int __devinit titsc_probe(struct platform_device *pdev)
+
+ /* register to the input system */
+ err = input_register_device(input_dev);
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "Failed to register input device\n");
+ goto err_free_irq;
++ }
+
+ platform_set_drvdata(pdev, ts_dev);
++
++ dev_info(&pdev->dev, "Initialized OK\n");
++
+ return 0;
+
+ err_free_irq:
+diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
+index cbb8b70c..4a7041c 100644
+--- a/drivers/mfd/ti_am335x_tscadc.c
++++ b/drivers/mfd/ti_am335x_tscadc.c
+@@ -31,6 +31,7 @@ static unsigned int tscadc_readl(struct ti_tscadc_dev *tsadc, unsigned int reg)
+ {
+ unsigned int val;
+
++ val = (unsigned int)-1;
+ regmap_read(tsadc->regmap_tscadc, reg, &val);
+ return val;
+ }
+@@ -68,7 +69,7 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ int irq;
+ int err, ctrl;
+ int clk_value, clock_rate;
+- int tsc_wires, adc_channels = 0, total_channels;
++ int tsc_wires = 0, adc_channels = 0, total_channels;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Could not find platform data\n");
+@@ -78,7 +79,9 @@ static int __devinit ti_tscadc_probe(struct platform_device *pdev)
+ if (pdata->adc_init)
+ adc_channels = pdata->adc_init->adc_channels;
+
+- tsc_wires = pdata->tsc_init->wires;
++ if (pdata->tsc_init)
++ tsc_wires = pdata->tsc_init->wires;
++
+ total_channels = tsc_wires + adc_channels;
+
+ if (total_channels > 8) {
diff --git a/patches/linux-3.7/0060-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch b/patches/linux-3.7/0060-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
new file mode 100644
index 0000000..b868bfe
--- /dev/null
+++ b/patches/linux-3.7/0060-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
@@ -0,0 +1,164 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 2 Jul 2012 13:51:39 +0530
+Subject: [PATCH] ARM: OMAP3+: hwmod: Corrects resource data for PWM devices.
+
+PWM device has common space + module specific part in AM335x. To access
+module specific part from module drivers, resource regions for PWM
+device rearranged to access module specific part with index 0. This
+helps module re-usability for platforms that didn't have config space
+support like Davinci. Also ADDR_TYPE_RT flag removed for module specific
+part.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 72 ++++++++++++++--------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index f96bbc0..b6f78c1 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -2549,17 +2549,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48300200,
+ .pa_end = 0x48300200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48300000,
++ .pa_end = 0x48300000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2575,17 +2575,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm0 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+ {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48302200,
+ .pa_end = 0x48302200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2601,17 +2601,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm1 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48304200,
+ .pa_end = 0x48304200 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2627,17 +2627,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm2 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+ {
+- .pa_start = 0x48300000,
+- .pa_end = 0x48300000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48300100,
+ .pa_end = 0x48300100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48300000,
++ .pa_end = 0x48300000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2653,17 +2653,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap0 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+ {
+- .pa_start = 0x48302000,
+- .pa_end = 0x48302000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48302100,
+ .pa_end = 0x48302100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48302000,
++ .pa_end = 0x48302000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
+@@ -2679,17 +2679,17 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap1 = {
+
+ /*
+ * Splitting the resources to handle access of PWMSS config space
+- * and module specific part independently
++ * and module specific part independently. Also resources being
++ * arranged to be compatible with driver
+ */
+ static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+ {
+- .pa_start = 0x48304000,
+- .pa_end = 0x48304000 + SZ_16 - 1,
+- .flags = ADDR_TYPE_RT
+- },
+- {
+ .pa_start = 0x48304100,
+ .pa_end = 0x48304100 + SZ_256 - 1,
++ },
++ {
++ .pa_start = 0x48304000,
++ .pa_end = 0x48304000 + SZ_16 - 1,
+ .flags = ADDR_TYPE_RT
+ },
+ { }
diff --git a/patches/linux-3.7/0061-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch b/patches/linux-3.7/0061-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
new file mode 100644
index 0000000..8e5d982
--- /dev/null
+++ b/patches/linux-3.7/0061-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
@@ -0,0 +1,67 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 16 Jul 2012 14:59:41 +0530
+Subject: [PATCH] pwm_backlight: Add device tree support for Low Threshold
+ Brightness
+
+Low Threshold Brightness should be configured to have a linear relation
+in brightness scale. This patch adds device tree support for low
+threshold brightness as optional one for pwm_backlight.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ .../bindings/video/backlight/pwm-backlight.txt | 21 ++++++++++++++++++++
+ drivers/video/backlight/pwm_bl.c | 5 +++++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+index 1e4fc72..689c7d2 100644
+--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
++++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+@@ -14,6 +14,8 @@ Required properties:
+ Optional properties:
+ - pwm-names: a list of names for the PWM devices specified in the
+ "pwms" property (see PWM binding[0])
++ - low_threshold_brightness: brightness threshold low level. (get linear
++ scales in brightness in low end of brightness levels)
+
+ [0]: Documentation/devicetree/bindings/pwm/pwm.txt
+
+@@ -26,3 +28,22 @@ Example:
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
++
++Example for brightness_threshold_level:
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&pwm 0 50000>;
++
++ brightness-levels = <0 4 8 16 32 64 128 255>;
++ default-brightness-level = <6>;
++ low_threshold_brightness = <50>;
++ };
++};
++Note:
++Low threshold support is required to have linear brightness scale from
++0 to max. For some panels, backlight absent on low end of brightness
++scale. So support for Low Threshold been required. So that the scale of
++brightness changed from Low Threshold to Max in scales defined in
++brightness-levels. In this example 20% maximum brightness scale should
++be required to turn on panel backlight.
+diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
+index 069983c..0c91023 100644
+--- a/drivers/video/backlight/pwm_bl.c
++++ b/drivers/video/backlight/pwm_bl.c
+@@ -143,6 +143,11 @@ static int pwm_backlight_parse_dt(struct device *dev,
+
+ data->dft_brightness = value;
+ data->max_brightness--;
++
++ ret = of_property_read_u32(node, "low_threshold_brightness",
++ &value);
++ if (!ret)
++ data->lth_brightness = value;
+ }
+
+ /*
diff --git a/patches/linux-3.7/0062-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch b/patches/linux-3.7/0062-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
new file mode 100644
index 0000000..a72fbe6
--- /dev/null
+++ b/patches/linux-3.7/0062-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
@@ -0,0 +1,119 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Fri, 29 Jun 2012 10:52:57 +0530
+Subject: [PATCH] pwm: pwm-tiecap: Add device-tree binding support in APWM
+ driver
+
+Adds support for device-tree binding in ECAP APWM driver and custom
+of_xlate support. In custom of_xlate support, support for configuring
+polarity also been provided. This will provide configuration of ECAP
+APWM polarity from client drivers device-tree.
+Also size of pwm-cells set to 3 to support polarity configuration from
+device tree.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ Documentation/devicetree/bindings/pwm/ecap-pwm.txt | 24 ++++++++++++++
+ drivers/pwm/pwm-tiecap.c | 35 ++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+new file mode 100644
+index 0000000..fa56534
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+@@ -0,0 +1,24 @@
++TI SOC ECAP based APWM controller
++
++Required properties:
++- compatible : Must be "ti, ecap"
++- ti,hwmods : Must be "ecap<n>", n being the instance number (0-based)
++- #pwm-cells: On ECAP the number of cells used to specify a PWM is 3. The
++ first cell specifies the per-chip index of the PWM to use, the second
++ cell is the period cycle in nanoseconds and the third cell is the
++ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
++ inversed polarity (inverse duty cycle)
++
++Note: Current implementation will fetch base address, irq and dma
++from omap hwmod data base during device registration.
++Future plan is to migrate hwmod data base contents into device tree
++blob so that, all the required data will be used from device tree dts
++file.
++
++Example:
++
++ ecap0: ecap@0 {
++ compatible = "ti, ecap";
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ };
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index d6d4cf0..d15941c 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -37,6 +37,8 @@
+ #define ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6))
+ #define ECCTL2_TSCTR_FREERUN BIT(4)
+
++#define PWM_CELL_SIZE 3
++
+ struct ecap_pwm_chip {
+ struct pwm_chip chip;
+ unsigned int clk_rate;
+@@ -184,6 +186,26 @@ static const struct pwm_ops ecap_pwm_ops = {
+ .owner = THIS_MODULE,
+ };
+
++static struct pwm_device *of_ecap_xlate(struct pwm_chip *chip,
++ const struct of_phandle_args *args)
++{
++ struct pwm_device *pwm;
++
++ if (chip->of_pwm_n_cells < PWM_CELL_SIZE)
++ return ERR_PTR(-EINVAL);
++
++ if (args->args[0] >= chip->npwm)
++ return ERR_PTR(-EINVAL);
++
++ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
++ if (IS_ERR(pwm))
++ return pwm;
++
++ pwm_set_period(pwm, args->args[1]);
++ pwm_set_polarity(pwm, args->args[2]);
++ return pwm;
++}
++
+ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ {
+ int ret;
+@@ -211,6 +233,8 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &ecap_pwm_ops;
++ pc->chip.of_xlate = of_ecap_xlate;
++ pc->chip.of_pwm_n_cells = PWM_CELL_SIZE;
+ pc->chip.base = -1;
+ pc->chip.npwm = 1;
+
+@@ -244,9 +268,20 @@ static int __devexit ecap_pwm_remove(struct platform_device *pdev)
+ return pwmchip_remove(&pc->chip);
+ }
+
++#if defined(CONFIG_OF)
++static const struct of_device_id omap_ecap_of_match[] = {
++ { .compatible = "ti,ecap" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_ecap_of_match);
++#endif
++
+ static struct platform_driver ecap_pwm_driver = {
+ .driver = {
+ .name = "ecap",
++#if defined(CONFIG_OF)
++ .of_match_table = of_match_ptr(omap_ecap_of_match),
++#endif
+ },
+ .probe = ecap_pwm_probe,
+ .remove = __devexit_p(ecap_pwm_remove),
diff --git a/patches/linux-3.7/0063-Control-module-EHRPWM-clk-enabling.patch b/patches/linux-3.7/0063-Control-module-EHRPWM-clk-enabling.patch
new file mode 100644
index 0000000..6a268e8
--- /dev/null
+++ b/patches/linux-3.7/0063-Control-module-EHRPWM-clk-enabling.patch
@@ -0,0 +1,42 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 22 May 2012 11:34:58 +0530
+Subject: [PATCH] Control module : EHRPWM clk enabling
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/mach-omap2/devices.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index c72b5a7..9faecb9 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -434,6 +434,20 @@ static void omap_init_mcspi(void)
+ static inline void omap_init_mcspi(void) {}
+ #endif
+
++#include "cm33xx.h"
++
++int __init am33xx_register_ehrpwm(void)
++{
++ void __iomem *iobase;
++ unsigned short regword;
++
++ iobase = AM33XX_CM_REGADDR(0, 0x10664);
++ regword = readw(iobase);
++ regword |= 0x7;
++ writew(regword, iobase);
++ return 0;
++}
++
+ /**
+ * omap_init_rng - bind the RNG hwmod to the RNG omap_device
+ *
+@@ -720,6 +734,7 @@ static int __init omap2_init_devices(void)
+ omap_init_vout();
+ omap_init_ocp2scp();
+
++ am33xx_register_ehrpwm();
+ return 0;
+ }
+ arch_initcall(omap2_init_devices);
diff --git a/patches/linux-3.7/0064-pwm-pwm-tiecap-Enable-clock-gating.patch b/patches/linux-3.7/0064-pwm-pwm-tiecap-Enable-clock-gating.patch
new file mode 100644
index 0000000..f98ce61
--- /dev/null
+++ b/patches/linux-3.7/0064-pwm-pwm-tiecap-Enable-clock-gating.patch
@@ -0,0 +1,101 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 24 Jul 2012 14:58:09 +0530
+Subject: [PATCH] pwm: pwm-tiecap: Enable clock gating
+
+In AM335x SOC, clock to PWM modules is gated in common config space.
+This commit adds support for enabling clock gating in the driver and
+leave it enabled if config space node is present.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ Documentation/devicetree/bindings/pwm/ecap-pwm.txt | 12 +++++++
+ drivers/pwm/pwm-tiecap.c | 37 +++++++++++++++++++-
+ 2 files changed, 48 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+index fa56534..7d83587 100644
+--- a/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
++++ b/Documentation/devicetree/bindings/pwm/ecap-pwm.txt
+@@ -9,6 +9,11 @@ Required properties:
+ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
+ inversed polarity (inverse duty cycle)
+
++Optional properties:
++- has_configspace: Some ECAP hardwares has config space memory region
++ to enable clock gating to individual modules. Adding this as optional
++ properties.
++
+ Note: Current implementation will fetch base address, irq and dma
+ from omap hwmod data base during device registration.
+ Future plan is to migrate hwmod data base contents into device tree
+@@ -22,3 +27,10 @@ Example:
+ ti,hwmods = "ecap0";
+ #pwm-cells = <3>;
+ };
++Example with has_configspace:
++ ecap0: ecap@0 {
++ compatible = "ti, ecap";
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ has_configspace = <1>;
++ };
+diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
+index d15941c..5b07707 100644
+--- a/drivers/pwm/pwm-tiecap.c
++++ b/drivers/pwm/pwm-tiecap.c
+@@ -206,12 +206,16 @@ static struct pwm_device *of_ecap_xlate(struct pwm_chip *chip,
+ return pwm;
+ }
+
++#define CLKCONFIG 8
++#define ECAP_CLK_EN 1
+ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ {
+- int ret;
++ int ret, len;
+ struct resource *r;
+ struct clk *clk;
+ struct ecap_pwm_chip *pc;
++ void __iomem *mmio_base;
++ unsigned long regval;
+
+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc) {
+@@ -255,6 +259,37 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)
+ }
+
+ pm_runtime_enable(&pdev->dev);
++
++ /*
++ * Some IP's have config space and require special handling of
++ * clock gating from config space. So enabling clock gating
++ * at config space.
++ */
++ if (pdev->dev.of_node && of_find_property(pdev->dev.of_node,
++ "has_configspace", &len)) {
++
++ r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++ if (!r) {
++ pm_runtime_disable(&pdev->dev);
++ dev_err(&pdev->dev, "no memory resource defined\n");
++ return -ENODEV;
++ }
++
++ mmio_base = devm_ioremap(&pdev->dev, r->start,
++ resource_size(r));
++ if (!mmio_base) {
++ pm_runtime_disable(&pdev->dev);
++ dev_err(&pdev->dev, "failed to ioremap() registers\n");
++ return -EADDRNOTAVAIL;
++ }
++
++ pm_runtime_get_sync(&pdev->dev);
++ regval = readw(mmio_base + CLKCONFIG);
++ regval |= ECAP_CLK_EN;
++ writew(regval, mmio_base + CLKCONFIG);
++ pm_runtime_put_sync(&pdev->dev);
++ }
++
+ platform_set_drvdata(pdev, pc);
+ return 0;
+ }
diff --git a/patches/linux-3.7/0065-PWM-ti-ehrpwm-fix-up-merge-conflict.patch b/patches/linux-3.7/0065-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
new file mode 100644
index 0000000..9cc2a3f
--- /dev/null
+++ b/patches/linux-3.7/0065-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
@@ -0,0 +1,21 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Mon, 17 Sep 2012 10:34:22 +0200
+Subject: [PATCH] PWM: ti-ehrpwm: fix up merge conflict
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/pwm/pwm-tiehrpwm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index d3c1dff..288f93e 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -113,6 +113,7 @@ struct ehrpwm_pwm_chip {
+ struct pwm_chip chip;
+ unsigned int clk_rate;
+ void __iomem *mmio_base;
++ unsigned long duty_cycles;
+ unsigned long period_cycles[NUM_PWM_CHANNEL];
+ enum pwm_polarity polarity[NUM_PWM_CHANNEL];
+ };
diff --git a/patches/linux-3.7/0066-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch b/patches/linux-3.7/0066-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
new file mode 100644
index 0000000..5e012cc
--- /dev/null
+++ b/patches/linux-3.7/0066-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
@@ -0,0 +1,369 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Tue, 17 Jul 2012 21:35:11 +0530
+Subject: [PATCH] pwm: pwm_test: Driver support for PWM module testing
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ drivers/pwm/Kconfig | 11 ++
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/pwm_test.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 334 insertions(+)
+ create mode 100644 drivers/pwm/pwm_test.c
+
+diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
+index ed81720..f1a0721 100644
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -160,4 +160,15 @@ config PWM_VT8500
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-vt8500.
+
++config EHRPWM_TEST
++ tristate "EHRPWM TEST support"
++ depends on PWM_TIEHRPWM
++
++ help
++ Test driver support for the EHRPWM PWM driver found on AM33XX
++ TI SOC
++
++ To compile this driver as a module, choose M here: the module
++ will be called pwm_ehrpwm.
++
+ endif
+diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
+index acfe482..e2c6277 100644
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -13,3 +13,4 @@ obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
+ obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
+ obj-$(CONFIG_PWM_TWL6030) += pwm-twl6030.o
+ obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
++obj-$(CONFIG_EHRPWM_TEST) += pwm_test.o
+diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
+new file mode 100644
+index 0000000..d9948db
+--- /dev/null
++++ b/drivers/pwm/pwm_test.c
+@@ -0,0 +1,322 @@
++/*
++ * PWM Test driver
++ *
++ * Copyright (C) 2012 Texas Instruments.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pwm.h>
++#include <linux/slab.h>
++#include <linux/io.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/pm_runtime.h>
++
++struct pwm_test {
++ struct pwm_device *pwm;
++ int ret;
++ struct class *pwm_test_class;
++ unsigned long period, duty, run, polarity, config, requested;
++ unsigned long period_s, duty_s, run_s, polarity_s, config_s, requested_s;
++ struct device *dev;
++};
++
++static ssize_t pwm_test_show_duty(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%lu\n", pwm_test->duty);
++}
++
++static ssize_t pwm_test_store_duty(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->duty_s);
++ if (rc)
++ return rc;
++ return count;
++}
++
++static ssize_t pwm_test_show_period(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%lu\n", pwm_test->period);
++}
++
++static ssize_t pwm_test_store_period(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->period_s);
++ if (rc)
++ return rc;
++
++ return count;
++}
++
++static ssize_t pwm_test_show_config(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ if (pwm_test->config)
++ return sprintf(buf, "config Done\n");
++ else
++ return sprintf(buf, "config Failed\n");
++}
++static ssize_t pwm_test_store_config(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ int ret;
++
++ if (pwm_test->duty_s == 0) {
++ ret = pwm_config(pwm_test->pwm, 0, pwm_test->period_s);
++ if (ret) {
++ pwm_test->config = 0;
++ pr_err("operation failed %d\n", ret);
++ pwm_test->duty_s = pwm_test->duty;
++ pwm_test->period_s = pwm_test->period;
++ return ret;
++ }
++ pwm_test->duty = pwm_test->duty_s;
++ pwm_test->period = pwm_test->period_s;
++ pwm_test->config = 1;
++ } else {
++ ret = pwm_config(pwm_test->pwm, pwm_test->duty_s,
++ pwm_test->period_s);
++ if (ret) {
++ pwm_test->config = 0;
++ pr_err("operation failed %d\n", ret);
++ pwm_test->duty_s = pwm_test->duty;
++ pwm_test->period_s = pwm_test->period;
++ return ret;
++ }
++ pwm_test->duty = pwm_test->duty_s;
++ pwm_test->period = pwm_test->period_s;
++ pwm_test->config = 1;
++ }
++ return count;
++}
++
++static ssize_t pwm_test_show_run(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n", pwm_test->run ? "Enabled" : "Disabled");
++}
++
++static ssize_t pwm_test_store_run(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->run_s);
++ if (rc)
++ return rc;
++
++ if (pwm_test->run_s)
++ rc = pwm_enable(pwm_test->pwm);
++ else
++ pwm_disable(pwm_test->pwm);
++
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ pwm_test->run_s = pwm_test->run;
++ return rc;
++ }
++
++ pwm_test->run = pwm_test->run_s;
++ return count;
++}
++
++static ssize_t pwm_test_show_polarity(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n",
++ pwm_test->polarity ? "Polarity Inversed" :
++ "Polarity Normal");
++}
++
++static ssize_t pwm_test_store_polarity(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->polarity_s);
++ if (rc)
++ return rc;
++
++ rc = pwm_set_polarity(pwm_test->pwm, pwm_test->polarity_s);
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ return rc;
++ }
++
++ pwm_test->polarity = pwm_test->polarity_s;
++ return count;
++}
++
++static ssize_t pwm_test_show_request(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++ return sprintf(buf, "%s\n", pwm_test->requested ? "Requested" : "Freed");
++}
++
++static ssize_t pwm_test_store_request(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ int rc;
++ struct pwm_test *pwm_test = dev_get_drvdata(dev);
++
++ rc = kstrtoul(buf, 0, &pwm_test->requested_s);
++ if (rc)
++ return rc;
++
++ if (pwm_test->requested_s) {
++ pwm_test->pwm = pwm_get(dev, NULL);
++
++ if (IS_ERR(pwm_test->pwm)) {
++ dev_err(dev, "%s() %d %ld\n", __func__, __LINE__,
++ PTR_ERR(pwm_test->pwm));
++ rc = -EINVAL;
++ }
++ } else {
++ pwm_free(pwm_test->pwm);
++ pwm_test->polarity = 0;
++ pwm_test->run = 0;
++ pwm_test->duty = 0;
++ pwm_test->period = 0;
++ pwm_test->config = 0;
++ pwm_test->polarity_s = 0;
++ pwm_test->run_s = 0;
++ pwm_test->duty_s = 0;
++ pwm_test->period_s = 0;
++ pwm_test->config_s = 0;
++ rc = 0;
++ }
++
++ if (rc) {
++ pr_err("operation failed %d\n", rc);
++ pwm_test->requested_s = pwm_test->requested;
++ return rc;
++ }
++
++ pwm_test->requested = pwm_test->requested_s;
++ return count;
++}
++
++static DEVICE_ATTR(duty, 0644, pwm_test_show_duty, pwm_test_store_duty);
++static DEVICE_ATTR(period, 0644, pwm_test_show_period, pwm_test_store_period);
++static DEVICE_ATTR(polarity, 0644, pwm_test_show_polarity,
++ pwm_test_store_polarity);
++static DEVICE_ATTR(config, 0644 , pwm_test_show_config, pwm_test_store_config);
++static DEVICE_ATTR(run, 0644 , pwm_test_show_run, pwm_test_store_run);
++static DEVICE_ATTR(request, 0644 , pwm_test_show_request, pwm_test_store_request);
++
++static const struct attribute *pwm_attrs[] = {
++ &dev_attr_duty.attr,
++ &dev_attr_period.attr,
++ &dev_attr_config.attr,
++ &dev_attr_run.attr,
++ &dev_attr_request.attr,
++ &dev_attr_polarity.attr,
++ NULL,
++};
++
++static const struct attribute_group pwm_device_attr_group = {
++ .attrs = (struct attribute **) pwm_attrs,
++};
++
++static int __init pwm_test_class_init(struct device *dev)
++{
++ if (sysfs_create_group(&dev->kobj, &pwm_device_attr_group))
++ return 1;
++ return 0;
++}
++
++static int pwm_test_probe(struct platform_device *pdev)
++{
++ struct pwm_test *pwm_test;
++
++ pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
++
++ if (!pwm_test) {
++ dev_err(&pdev->dev, "memory error\n");
++ return -ENOMEM;
++ }
++
++ if (pwm_test_class_init(&pdev->dev)) {
++ dev_err(&pdev->dev, "sysfs creation failed\n");
++ return -EINVAL;
++ }
++ dev_set_drvdata(&pdev->dev, pwm_test);
++ platform_set_drvdata(pdev, pwm_test);
++ return 0;
++}
++
++static int pwm_test_remove(struct platform_device *pdev)
++{
++ struct pwm_test *pwm_test = platform_get_drvdata(pdev);
++
++ if (!pwm_test->ret) {
++ pwm_config(pwm_test->pwm, 0, 0x1000);
++ pwm_disable(pwm_test->pwm);
++ pr_emerg("PWM Device Disabled %s\n", dev_name(&pdev->dev));
++ }
++ if (pwm_test->requested)
++ pwm_free(pwm_test->pwm);
++
++ pr_emerg("PWM Device Freed %s\n", dev_name(&pdev->dev));
++ pwm_test->run = 0;
++ sysfs_remove_group(&pdev->dev.kobj, &pwm_device_attr_group);
++ return 0;
++}
++
++static struct of_device_id pwm_test_of_match[] = {
++ { .compatible = "pwm_test" },
++ { }
++};
++
++MODULE_DEVICE_TABLE(of, pwm_test_of_match);
++
++static struct platform_driver pwm_test_driver = {
++ .driver = {
++ .name = "pwm_test",
++ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(pwm_test_of_match),
++ },
++ .probe = pwm_test_probe,
++ .remove = pwm_test_remove,
++};
++
++module_platform_driver(pwm_test_driver);
++
++MODULE_DESCRIPTION("pwm_test Driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:pwm_test");
diff --git a/patches/linux-3.7/0067-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch b/patches/linux-3.7/0067-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
new file mode 100644
index 0000000..612da05
--- /dev/null
+++ b/patches/linux-3.7/0067-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
@@ -0,0 +1,83 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Wed, 11 Jul 2012 11:01:33 +0530
+Subject: [PATCH] arm/dts: DT support for EHRPWM and ECAP device.
+
+Adds DT support for EHRPWM and ECAP APWM device. Also sets size of
+pwm-cells to 3 to support - <PWM instance number>, <PWM period> in
+nano-seconds and <PWM polarity>.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 60 +++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index ce429a0..8484559 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -380,5 +380,65 @@
+ };
+
+ };
++
++ ehrpwm0: ehrpwm@48300200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48300200 0x100 0x48300000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <86 58>;
++ ti,hwmods = "ehrpwm0";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ehrpwm1: ehrpwm@48302200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48302200 0x100 0x48302000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <87 59>;
++ ti,hwmods = "ehrpwm1";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ehrpwm2: ehrpwm@48304200 {
++ compatible = "ti,omap2-ehrpwm";
++ reg = <0x48304200 0x100 0x48304000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <39 60>;
++ ti,hwmods = "ehrpwm2";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap0: ecap@48300100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48300100 0x80 0x48300000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <31>;
++ ti,hwmods = "ecap0";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap1: ecap@48302100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48302100 0x80 0x48302000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <47>;
++ ti,hwmods = "ecap1";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
++
++ ecap2: ecap@48304100 {
++ compatible = "ti,omap2-ecap";
++ reg = <0x48304100 0x80 0x48304000 0x10>;
++ interrupt-parent = <&intc>;
++ interrupt = <61>;
++ ti,hwmods = "ecap2";
++ #pwm-cells = <3>;
++ status = "disabled";
++ };
+ };
+ };
diff --git a/patches/linux-3.7/0068-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch b/patches/linux-3.7/0068-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
new file mode 100644
index 0000000..8c31560
--- /dev/null
+++ b/patches/linux-3.7/0068-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
@@ -0,0 +1,121 @@
+From: "Philip, Avinash" <avinashphilip@ti.com>
+Date: Mon, 2 Jul 2012 14:03:53 +0530
+Subject: [PATCH] pwm: pwm-tiehrpwm: Add device-tree binding support EHRPWM
+ driver
+
+Adds device-tree binding support in EHRWPM driver and custom of_xlate
+support. In custom of_xlate support, support for configuring polarity
+also been provided. This will provide configuration of EHRPWM polarity
+from client drivers device-tree.
+Also size of pwm-cells set to 3 to support polarity configuration from
+device tree.
+
+Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
+
+Conflicts:
+ drivers/pwm/pwm-tiehrpwm.c
+---
+ .../devicetree/bindings/pwm/ehrpwm-pwm.txt | 24 ++++++++++++++
+ drivers/pwm/pwm-tiehrpwm.c | 34 ++++++++++++++++++++
+ 2 files changed, 58 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+
+diff --git a/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt b/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+new file mode 100644
+index 0000000..a11543c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/ehrpwm-pwm.txt
+@@ -0,0 +1,24 @@
++TI SOC EHRPWM based PWM controller
++
++Required properties:
++- compatible : Must be "ti, ehrpwm"
++- ti,hwmods : Must be "ehrpwm<n>", n being the instance number (0-based)
++- #pwm-cells: On EHRPWM the number of cells used to specify a PWM is 3. The
++ first cell specifies the per-chip index of the PWM to use, the second
++ cell is the period cycle in nanoseconds and the third cell is the
++ polarity of PWM output. Polarity 0 gives normal polarity and 1 gives
++ inversed polarity (inverse duty cycle)
++
++Note: Current implementation will fetch base address, irq and dma
++from omap hwmod data base during device registration.
++Future plan is to migrate hwmod data base contents into device tree
++blob so that, all the required data will be used from device tree dts
++file.
++
++Example:
++
++ ehrpwm0: ehrpwm@0 {
++ compatible = "ti, ehrpwm";
++ ti,hwmods = "ehrpwm0";
++ #pwm-cells = <3>;
++ };
+diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
+index 288f93e..4f1e467 100644
+--- a/drivers/pwm/pwm-tiehrpwm.c
++++ b/drivers/pwm/pwm-tiehrpwm.c
+@@ -108,6 +108,7 @@
+ #define AQCSFRC_CSFA_DISSWFRC (BIT(1) | BIT(0))
+
+ #define NUM_PWM_CHANNEL 2 /* EHRPWM channels */
++#define PWM_CELL_SIZE 3
+
+ struct ehrpwm_pwm_chip {
+ struct pwm_chip chip;
+@@ -393,6 +394,26 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
+ .owner = THIS_MODULE,
+ };
+
++static struct pwm_device *of_ehrpwm_xlate(struct pwm_chip *chip,
++ const struct of_phandle_args *args)
++{
++ struct pwm_device *pwm;
++
++ if (chip->of_pwm_n_cells < PWM_CELL_SIZE)
++ return ERR_PTR(-EINVAL);
++
++ if (args->args[0] >= chip->npwm)
++ return ERR_PTR(-EINVAL);
++
++ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
++ if (IS_ERR(pwm))
++ return pwm;
++
++ pwm_set_period(pwm, args->args[1]);
++ pwm_set_polarity(pwm, args->args[2]);
++ return pwm;
++}
++
+ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+ {
+ int ret;
+@@ -420,6 +441,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)
+
+ pc->chip.dev = &pdev->dev;
+ pc->chip.ops = &ehrpwm_pwm_ops;
++ pc->chip.of_xlate = of_ehrpwm_xlate;
++ pc->chip.of_pwm_n_cells = PWM_CELL_SIZE;
+ pc->chip.base = -1;
+ pc->chip.npwm = NUM_PWM_CHANNEL;
+
+@@ -453,9 +476,20 @@ static int __devexit ehrpwm_pwm_remove(struct platform_device *pdev)
+ return pwmchip_remove(&pc->chip);
+ }
+
++#if defined(CONFIG_OF)
++static const struct of_device_id omap_ehrpwm_of_match[] = {
++ { .compatible = "ti,omap2-ehrpwm" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, omap_ehrpwm_of_match);
++#endif
++
+ static struct platform_driver ehrpwm_pwm_driver = {
+ .driver = {
+ .name = "ehrpwm",
++#if defined(CONFIG_OF)
++ .of_match_table = of_match_ptr(omap_ehrpwm_of_match),
++#endif
+ },
+ .probe = ehrpwm_pwm_probe,
+ .remove = __devexit_p(ehrpwm_pwm_remove),
diff --git a/patches/linux-3.7/0069-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch b/patches/linux-3.7/0069-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
new file mode 100644
index 0000000..0998781
--- /dev/null
+++ b/patches/linux-3.7/0069-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
@@ -0,0 +1,26 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 27 Nov 2012 10:53:23 -0600
+Subject: [PATCH] ARM: OMAP2: PWM: limit am33xx_register_ehrpwm to
+ soc_is_am33xx, fixes boot on Beagle/Panda
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/devices.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
+index 9faecb9..07af6c8 100644
+--- a/arch/arm/mach-omap2/devices.c
++++ b/arch/arm/mach-omap2/devices.c
+@@ -733,8 +733,9 @@ static int __init omap2_init_devices(void)
+ omap_init_aes();
+ omap_init_vout();
+ omap_init_ocp2scp();
+-
+- am33xx_register_ehrpwm();
++ if (soc_is_am33xx()) {
++ am33xx_register_ehrpwm();
++ }
+ return 0;
+ }
+ arch_initcall(omap2_init_devices);
diff --git a/patches/linux-3.7/0071-pinctrl-pinctrl-single-must-be-initialized-early.patch b/patches/linux-3.7/0071-pinctrl-pinctrl-single-must-be-initialized-early.patch
new file mode 100644
index 0000000..45918e8
--- /dev/null
+++ b/patches/linux-3.7/0071-pinctrl-pinctrl-single-must-be-initialized-early.patch
@@ -0,0 +1,34 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 12:00:41 +0300
+Subject: [PATCH] pinctrl: pinctrl-single must be initialized early.
+
+When using pinctrl-single to handle i2c initialization, it has
+to be done early. Whether this is the best way to do so, is an
+exercise left to the reader.
+---
+ drivers/pinctrl/pinctrl-single.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
+index 726a729..2b258c3 100644
+--- a/drivers/pinctrl/pinctrl-single.c
++++ b/drivers/pinctrl/pinctrl-single.c
+@@ -1014,7 +1014,17 @@ static struct platform_driver pcs_driver = {
+ },
+ };
+
+-module_platform_driver(pcs_driver);
++static int __init pcs_init(void)
++{
++ return platform_driver_register(&pcs_driver);
++}
++postcore_initcall(pcs_init);
++
++static void __exit pcs_exit(void)
++{
++ platform_driver_unregister(&pcs_driver);
++}
++module_exit(pcs_exit);
+
+ MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
+ MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
diff --git a/patches/linux-3.7/0072-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch b/patches/linux-3.7/0072-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
new file mode 100644
index 0000000..612c935
--- /dev/null
+++ b/patches/linux-3.7/0072-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
@@ -0,0 +1,93 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 12:05:04 +0300
+Subject: [PATCH] Bone DTS working i2c2 (i2c3 in the tree)
+
+---
+ arch/arm/boot/dts/am335x-bone.dts | 60 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 50 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 87686e9..d1c21ba 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -52,6 +52,12 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ i2c3_pins: pinmux_i2c3_pins {
++ pinctrl-single,pins = <
++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ >;
++ };
+ };
+
+ ocp {
+@@ -92,16 +98,6 @@
+ };
+ };
+
+- i2c1: i2c@44e0b000 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- };
+-
+ gpevt {
+ compatible = "gpevt";
+ pinctrl-names = "default";
+@@ -113,6 +109,50 @@
+ };
+ };
+
++&i2c1 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ baseboard_eeprom: baseboard_eeprom@50 {
++ compatible = "at,24c256";
++ reg = <0x50>;
++ };
++
++};
++
++&i2c3 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c3_pins>;
++
++ clock-frequency = <100000>;
++
++ /* OK, I know these are cape but for now it will do */
++ cape_eeprom_0: cape_eeprom_0@54 {
++ compatible = "at,24c256";
++ reg = <0x54>;
++ };
++
++ cape_eeprom_1: cape_eeprom_1@55 {
++ compatible = "at,24c256";
++ reg = <0x55>;
++ };
++
++ cape_eeprom_2: cape_eeprom_2@56 {
++ compatible = "at,24c256";
++ reg = <0x56>;
++ };
++
++ cape_eeprom_3: cape_eeprom_3@57 {
++ compatible = "at,24c256";
++ reg = <0x57>;
++ };
++};
++
+ /include/ "tps65217.dtsi"
+
+ &tps {
diff --git a/patches/linux-3.7/0073-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch b/patches/linux-3.7/0073-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
new file mode 100644
index 0000000..9751754
--- /dev/null
+++ b/patches/linux-3.7/0073-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
@@ -0,0 +1,106 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 15 Sep 2012 14:49:11 +0300
+Subject: [PATCH] am33xx: Convert I2C from omap to am33xx names
+
+On OMAP the TRM names I2C instances as i2c1, i2c2, etc.
+On the am33xx's it is i2c0, i2c1, etc.
+
+Use am33xx naming everywhere, beside the hwmod name.
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++----
+ arch/arm/boot/dts/am335x-evm.dts | 2 +-
+ arch/arm/boot/dts/am33xx.dtsi | 12 ++++++------
+ 3 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index d1c21ba..1daf1af 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -52,7 +52,7 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
+- i2c3_pins: pinmux_i2c3_pins {
++ i2c2_pins: pinmux_i2c2_pins {
+ pinctrl-single,pins = <
+ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+@@ -109,7 +109,7 @@
+ };
+ };
+
+-&i2c1 {
++&i2c0 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+@@ -124,10 +124,10 @@
+
+ };
+
+-&i2c3 {
++&i2c2 {
+ status = "okay";
+ pinctrl-names = "default";
+- pinctrl-0 = <&i2c3_pins>;
++ pinctrl-0 = <&i2c2_pins>;
+
+ clock-frequency = <100000>;
+
+diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
+index 43e23a8..6032648 100644
+--- a/arch/arm/boot/dts/am335x-evm.dts
++++ b/arch/arm/boot/dts/am335x-evm.dts
+@@ -29,7 +29,7 @@
+ status = "okay";
+ };
+
+- i2c1: i2c@44e0b000 {
++ i2c0: i2c@44e0b000 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 8484559..a2270aa 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -229,33 +229,33 @@
+ status = "disabled";
+ };
+
+- i2c1: i2c@44e0b000 {
++ i2c0: i2c@44e0b000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c1";
++ ti,hwmods = "i2c1"; /* TODO: Fix hwmod */
+ reg = <0x44e0b000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <70>;
+ status = "disabled";
+ };
+
+- i2c2: i2c@4802a000 {
++ i2c1: i2c@4802a000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c2";
++ ti,hwmods = "i2c2"; /* TODO: Fix hwmod */
+ reg = <0x4802a000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <71>;
+ status = "disabled";
+ };
+
+- i2c3: i2c@4819c000 {
++ i2c2: i2c@4819c000 {
+ compatible = "ti,omap4-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+- ti,hwmods = "i2c3";
++ ti,hwmods = "i2c3"; /* TODO: Fix hwmod */
+ reg = <0x4819c000 0x1000>;
+ interrupt-parent = <&intc>;
+ interrupts = <30>;
diff --git a/patches/linux-3.7/0074-beaglebone-fix-backlight-entry-in-DT.patch b/patches/linux-3.7/0074-beaglebone-fix-backlight-entry-in-DT.patch
new file mode 100644
index 0000000..410150c
--- /dev/null
+++ b/patches/linux-3.7/0074-beaglebone-fix-backlight-entry-in-DT.patch
@@ -0,0 +1,28 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 18 Sep 2012 11:23:47 +0200
+Subject: [PATCH] beaglebone: fix backlight entry in DT
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 1daf1af..667842d 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -107,6 +107,14 @@
+ gpio-evt = <&gpio3 2 0>;
+ };
+ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
+ };
+
+ &i2c0 {
diff --git a/patches/linux-3.7/0076-Shut-up-musb.patch b/patches/linux-3.7/0076-Shut-up-musb.patch
new file mode 100644
index 0000000..37caa4c
--- /dev/null
+++ b/patches/linux-3.7/0076-Shut-up-musb.patch
@@ -0,0 +1,23 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 4 Oct 2012 12:02:13 +0300
+Subject: [PATCH] Shut up musb!
+
+---
+ drivers/usb/musb/musb_host.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 3df6a76..f43b55c 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -2432,8 +2432,10 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
+ }
+
+ if (musb->is_active) {
++#if 0
+ WARNING("trying to suspend as %s while active\n",
+ otg_state_string(musb->xceiv->state));
++#endif
+ return -EBUSY;
+ } else
+ return 0;
diff --git a/patches/linux-3.7/0077-musb-Fix-crashes-and-other-weirdness.patch b/patches/linux-3.7/0077-musb-Fix-crashes-and-other-weirdness.patch
new file mode 100644
index 0000000..15a438e
--- /dev/null
+++ b/patches/linux-3.7/0077-musb-Fix-crashes-and-other-weirdness.patch
@@ -0,0 +1,45 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 4 Oct 2012 17:53:53 +0300
+Subject: [PATCH] musb: Fix crashes, and other weirdness.
+
+---
+ arch/arm/boot/dts/am33xx.dtsi | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index a2270aa..0b53cde 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -289,6 +289,32 @@
+ status = "disabled";
+ };
+
++ usb0_phy: phy0 {
++ compatible = "nop-xceiv-usb";
++ };
++
++ usb1_phy: phy1 {
++ compatible = "nop-xceiv-usb";
++ };
++
++ usb_otg_hs: usb_otg_hs {
++ compatible = "ti,musb-am33xx";
++ ti,hwmods = "usb_otg_hs";
++ multipoint = <1>;
++ num-eps = <16>;
++ ram-bits = <12>;
++ port0-mode = <3>;
++ port1-mode = <1>;
++ power = <250>;
++ usb0-phy = <&usb0_phy>;
++ usb1-phy = <&usb1_phy>;
++ };
++
++ rtc {
++ compatible = "ti,da830-rtc";
++ ti,hwmods = "rtc";
++ };
++
+ spi0: spi@48030000 {
+ compatible = "ti,omap4-mcspi";
+ ti,hwmods = "spi0";
diff --git a/patches/linux-3.7/0078-musb-revert-parts-of-032ec49f.patch b/patches/linux-3.7/0078-musb-revert-parts-of-032ec49f.patch
new file mode 100644
index 0000000..b59a7d8
--- /dev/null
+++ b/patches/linux-3.7/0078-musb-revert-parts-of-032ec49f.patch
@@ -0,0 +1,370 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 17 Oct 2012 15:34:24 +0200
+Subject: [PATCH] musb: revert parts of 032ec49f
+
+This reverts parts of commit 032ec49f ("usb: musb: drop useless
+board_mode usage") to get USB host mode working again.
+---
+ drivers/usb/musb/musb_core.c | 210 ++++++++++++++++++++++++++++--------------
+ drivers/usb/musb/musb_core.h | 5 +
+ 2 files changed, 144 insertions(+), 71 deletions(-)
+
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index bb56a0e..8621fca 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -681,7 +681,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_suspend(musb);
+- musb->is_active = otg->gadget->b_hnp_enable;
++ musb->is_active = is_otg_enabled(musb)
++ && otg->gadget->b_hnp_enable;
+ if (musb->is_active) {
+ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
+@@ -697,7 +698,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ break;
+ case OTG_STATE_A_HOST:
+ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+- musb->is_active = otg->host->b_hnp_enable;
++ musb->is_active = is_otg_enabled(musb)
++ && otg->host->b_hnp_enable;
+ break;
+ case OTG_STATE_B_HOST:
+ /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+@@ -785,7 +787,7 @@ b_host:
+ 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;
+@@ -961,16 +963,25 @@ void musb_start(struct musb *musb)
+ devctl = musb_readb(regs, MUSB_DEVCTL);
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+- /* session started after:
+- * (a) ID-grounded irq, host mode;
+- * (b) vbus present/connect IRQ, peripheral mode;
+- * (c) peripheral initiates, using SRP
+- */
+- if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+- musb->is_active = 1;
+- else
++ if (is_otg_enabled(musb)) {
++ /* session started after:
++ * (a) ID-grounded irq, host mode;
++ * (b) vbus present/connect IRQ, peripheral mode;
++ * (c) peripheral initiates, using SRP
++ */
++ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
++ musb->is_active = 1;
++ else
++ devctl |= MUSB_DEVCTL_SESSION;
++
++ } else if (is_host_enabled(musb)) {
++ /* assume ID pin is hard-wired to ground */
+ devctl |= MUSB_DEVCTL_SESSION;
+
++ } else /* peripheral is enabled */ {
++ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
++ musb->is_active = 1;
++ }
+ musb_platform_enable(musb);
+ musb_writeb(regs, MUSB_DEVCTL, devctl);
+ }
+@@ -1034,6 +1045,8 @@ static void musb_shutdown(struct platform_device *pdev)
+ musb_generic_disable(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
++ if (!is_otg_enabled(musb) && is_host_enabled(musb))
++ usb_remove_hcd(musb_to_hcd(musb));
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_platform_exit(musb);
+
+@@ -1891,7 +1904,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ int status;
+ struct musb *musb;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct usb_hcd *hcd;
+
+ /* The driver might handle more features than the board; OK.
+ * Fail when the board needs a feature that's not enabled.
+@@ -1914,6 +1926,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ pm_runtime_enable(musb->controller);
+
+ spin_lock_init(&musb->lock);
++ musb->board_mode = plat->mode;
+ musb->board_set_power = plat->set_power;
+ musb->min_power = plat->min_power;
+ musb->ops = plat->platform_ops;
+@@ -1984,7 +1997,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ goto fail3;
+ }
+ musb->nIrq = nIrq;
+- /* FIXME this handles wakeup irqs wrong */
++/* FIXME this handles wakeup irqs wrong */
+ if (enable_irq_wake(nIrq) == 0) {
+ musb->irq_wake = 1;
+ device_init_wakeup(dev, 1);
+@@ -1993,25 +2006,58 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+ }
+
+ /* host side needs more setup */
+- hcd = musb_to_hcd(musb);
+- otg_set_host(musb->xceiv->otg, &hcd->self);
+- hcd->self.otg_port = 1;
+- musb->xceiv->otg->host = &hcd->self;
+- hcd->power_budget = 2 * (plat->power ? : 250);
+-
+- /* program PHY to use external vBus if required */
+- if (plat->extvbus) {
+- u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
+- busctl |= MUSB_ULPI_USE_EXTVBUS;
+- musb_write_ulpi_buscontrol(musb->mregs, busctl);
++ if (is_host_enabled(musb)) {
++ struct usb_hcd *hcd = musb_to_hcd(musb);
++
++ otg_set_host(musb->xceiv->otg, &hcd->self);
++
++ if (is_otg_enabled(musb))
++ hcd->self.otg_port = 1;
++ musb->xceiv->otg->host = &hcd->self;
++ hcd->power_budget = 2 * (plat->power ? : 250);
++
++ /* program PHY to use external vBus if required */
++ if (plat->extvbus) {
++ u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ busctl |= MUSB_ULPI_USE_EXTVBUS;
++ musb_write_ulpi_buscontrol(musb->mregs, busctl);
++ }
+ }
+
+- MUSB_DEV_MODE(musb);
+- musb->xceiv->otg->default_a = 0;
+- musb->xceiv->state = OTG_STATE_B_IDLE;
++ /* For the host-only role, we can activate right away.
++ * (We expect the ID pin to be forcibly grounded!!)
++ * Otherwise, wait till the gadget driver hooks up.
++ */
++ if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
++ struct usb_hcd *hcd = musb_to_hcd(musb);
++
++ MUSB_HST_MODE(musb);
++ musb->xceiv->otg->default_a = 1;
++ musb->xceiv->state = OTG_STATE_A_IDLE;
++
++ status = usb_add_hcd(musb_to_hcd(musb), 0, 0);
++
++ hcd->self.uses_pio_for_control = 1;
++ dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n",
++ "HOST", status,
++ musb_readb(musb->mregs, MUSB_DEVCTL),
++ (musb_readb(musb->mregs, MUSB_DEVCTL)
++ & MUSB_DEVCTL_BDEVICE
++ ? 'B' : 'A'));
++
++ } else /* peripheral is enabled */ {
++ MUSB_DEV_MODE(musb);
++ musb->xceiv->otg->default_a = 0;
++ musb->xceiv->state = OTG_STATE_B_IDLE;
++
++ status = musb_gadget_setup(musb);
+
+- status = musb_gadget_setup(musb);
++ dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",
++ is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
++ status,
++ musb_readb(musb->mregs, MUSB_DEVCTL));
+
++ }
+ if (status < 0)
+ goto fail3;
+
+@@ -2027,13 +2073,28 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+
+ pm_runtime_put(musb->controller);
+
++ dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
++ ({char *s;
++ switch (musb->board_mode) {
++ case MUSB_HOST: s = "Host"; break;
++ case MUSB_PERIPHERAL: s = "Peripheral"; break;
++ default: s = "OTG"; break;
++ }; s; }),
++ ctrl,
++ (is_dma_capable() && musb->dma_controller)
++ ? "DMA" : "PIO",
++ musb->nIrq);
++
+ return 0;
+
+ fail5:
+ musb_exit_debugfs(musb);
+
+ fail4:
+- musb_gadget_cleanup(musb);
++ if (!is_otg_enabled(musb) && is_host_enabled(musb))
++ usb_remove_hcd(musb_to_hcd(musb));
++ else
++ musb_gadget_cleanup(musb);
+
+ fail3:
+ pm_runtime_put_sync(musb->controller);
+@@ -2116,9 +2177,11 @@ static void musb_save_context(struct musb *musb)
+ void __iomem *musb_base = musb->mregs;
+ void __iomem *epio;
+
+- musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
+- musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
+- musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ if (is_host_enabled(musb)) {
++ musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
++ musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
++ musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
++ }
+ musb->context.power = musb_readb(musb_base, MUSB_POWER);
+ musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
+ musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
+@@ -2157,29 +2220,30 @@ static void musb_save_context(struct musb *musb)
+ musb->context.index_regs[i].rxfifosz =
+ musb_read_rxfifosz(musb_base);
+ }
+-
+- musb->context.index_regs[i].txtype =
+- musb_readb(epio, MUSB_TXTYPE);
+- musb->context.index_regs[i].txinterval =
+- musb_readb(epio, MUSB_TXINTERVAL);
+- musb->context.index_regs[i].rxtype =
+- musb_readb(epio, MUSB_RXTYPE);
+- musb->context.index_regs[i].rxinterval =
+- musb_readb(epio, MUSB_RXINTERVAL);
+-
+- 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);
++ if (is_host_enabled(musb)) {
++ musb->context.index_regs[i].txtype =
++ musb_readb(epio, MUSB_TXTYPE);
++ musb->context.index_regs[i].txinterval =
++ musb_readb(epio, MUSB_TXINTERVAL);
++ musb->context.index_regs[i].rxtype =
++ musb_readb(epio, MUSB_RXTYPE);
++ musb->context.index_regs[i].rxinterval =
++ musb_readb(epio, MUSB_RXINTERVAL);
++
++ 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);
++ }
+ }
+ }
+
+@@ -2190,9 +2254,11 @@ static void musb_restore_context(struct musb *musb)
+ void __iomem *ep_target_regs;
+ void __iomem *epio;
+
+- musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
+- musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
+- musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
++ if (is_host_enabled(musb)) {
++ musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
++ musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
++ musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
++ }
+ musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+ musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
+ musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+@@ -2231,31 +2297,33 @@ static void musb_restore_context(struct musb *musb)
+ musb->context.index_regs[i].rxfifoadd);
+ }
+
+- musb_writeb(epio, MUSB_TXTYPE,
++ if (is_host_enabled(musb)) {
++ musb_writeb(epio, MUSB_TXTYPE,
+ musb->context.index_regs[i].txtype);
+- musb_writeb(epio, MUSB_TXINTERVAL,
++ musb_writeb(epio, MUSB_TXINTERVAL,
+ musb->context.index_regs[i].txinterval);
+- musb_writeb(epio, MUSB_RXTYPE,
++ musb_writeb(epio, MUSB_RXTYPE,
+ musb->context.index_regs[i].rxtype);
+- musb_writeb(epio, MUSB_RXINTERVAL,
++ musb_writeb(epio, MUSB_RXINTERVAL,
+
+- musb->context.index_regs[i].rxinterval);
+- musb_write_txfunaddr(musb_base, i,
++ musb->context.index_regs[i].rxinterval);
++ musb_write_txfunaddr(musb_base, i,
+ musb->context.index_regs[i].txfunaddr);
+- musb_write_txhubaddr(musb_base, i,
++ musb_write_txhubaddr(musb_base, i,
+ musb->context.index_regs[i].txhubaddr);
+- musb_write_txhubport(musb_base, i,
++ musb_write_txhubport(musb_base, i,
+ musb->context.index_regs[i].txhubport);
+
+- ep_target_regs =
+- musb_read_target_reg_base(i, musb_base);
++ ep_target_regs =
++ musb_read_target_reg_base(i, musb_base);
+
+- musb_write_rxfunaddr(ep_target_regs,
++ musb_write_rxfunaddr(ep_target_regs,
+ musb->context.index_regs[i].rxfunaddr);
+- musb_write_rxhubaddr(ep_target_regs,
++ musb_write_rxhubaddr(ep_target_regs,
+ musb->context.index_regs[i].rxhubaddr);
+- musb_write_rxhubport(ep_target_regs,
++ musb_write_rxhubport(ep_target_regs,
+ musb->context.index_regs[i].rxhubport);
++ }
+ }
+ musb_writeb(musb_base, MUSB_INDEX, musb->context.index);
+ }
+diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
+index c158aac..290e411 100644
+--- a/drivers/usb/musb/musb_core.h
++++ b/drivers/usb/musb/musb_core.h
+@@ -71,6 +71,10 @@ struct musb_ep;
+ #include <linux/usb/hcd.h>
+ #include "musb_host.h"
+
++#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
++#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
++#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG)
++
+ /* NOTE: otg and peripheral-only state machines start at B_IDLE.
+ * OTG or host-only go to A_IDLE when ID is sensed.
+ */
+@@ -368,6 +372,7 @@ struct musb {
+ u16 epmask;
+ u8 nr_endpoints;
+
++ u8 board_mode; /* enum musb_mode */
+ int (*board_set_power)(int state);
+
+ u8 min_power; /* vbus for periph, in mA/2 */
diff --git a/patches/linux-3.7/0079-usb-musb-dsps-get-the-PHY-using-phandle-api.patch b/patches/linux-3.7/0079-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
new file mode 100644
index 0000000..f29aa81
--- /dev/null
+++ b/patches/linux-3.7/0079-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
@@ -0,0 +1,54 @@
+From: Ravi Babu <ravibabu@ti.com>
+Date: Thu, 2 Aug 2012 16:13:32 +0530
+Subject: [PATCH] usb: musb: dsps: get the PHY using phandle api
+
+AM33xx has two PHY of same type used by each musb controller so
+use phandle of phy nodes to get the phy pointer.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Ravi Babu <ravibabu@ti.com>
+---
+ Documentation/devicetree/bindings/usb/am33xx-usb.txt | 5 +++++
+ drivers/usb/musb/musb_dsps.c | 5 ++++-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
+index ca8fa56..e2702df 100644
+--- a/Documentation/devicetree/bindings/usb/am33xx-usb.txt
++++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
+@@ -12,3 +12,8 @@ AM33XX MUSB GLUE
+ represents PERIPHERAL.
+ - power : Should be "250". This signifies the controller can supply upto
+ 500mA when operating in host mode.
++ - usb0-phy : phandle for usb0 NOP PHY
++ - usb1-phy : phandle for usb1 NOP PHY
++
++NOP USB PHY
++ - compatible : Should be "nop-xceiv-usb"
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index ff5f112..6a14101 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -367,10 +367,12 @@ static int dsps_musb_init(struct musb *musb)
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
++ struct platform_device *parent_pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ struct omap_musb_board_data *data = plat->board_data;
+ void __iomem *reg_base = musb->ctrl_base;
++ char name[10];
+ u32 rev, val;
+ int status;
+
+@@ -378,7 +380,8 @@ static int dsps_musb_init(struct musb *musb)
+ musb->mregs += wrp->musb_core_offset;
+
+ /* Get the NOP PHY */
+- musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
++ sprintf(name, "usb%d-phy", pdev->id);
++ musb->xceiv = devm_usb_get_phy_by_phandle(&parent_pdev->dev, name);
+ if (IS_ERR_OR_NULL(musb->xceiv))
+ return -ENODEV;
+
diff --git a/patches/linux-3.7/0080-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch b/patches/linux-3.7/0080-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
new file mode 100644
index 0000000..419b5eb
--- /dev/null
+++ b/patches/linux-3.7/0080-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
@@ -0,0 +1,203 @@
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Tue, 10 Jul 2012 14:10:38 +0530
+Subject: [PATCH] drivers: usb: otg: add device tree support to otg library
+
+Adds an API to get usb phy by passing a device node phandle value. Since
+now it's possible to obtain phy by phandle, the checks in usb_add_phy
+for a valid phy type is removed (now it's just a debug message if a user
+tries to add a phy with undefined type).
+This also allows to add multiple phys of same type.
+
+Cc: Richard Zhao <richard.zhao@freescale.com>
+Cc: Marek Vasut <marex@denx.de>
+Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ drivers/usb/otg/otg.c | 95 ++++++++++++++++++++++++++++++++++++++++-------
+ include/linux/usb/otg.h | 32 ++++++++++++++++
+ 2 files changed, 113 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
+index a30c041..ff08b34 100644
+--- a/drivers/usb/otg/otg.c
++++ b/drivers/usb/otg/otg.c
+@@ -14,6 +14,7 @@
+ #include <linux/err.h>
+ #include <linux/device.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+
+ #include <linux/usb/otg.h>
+
+@@ -35,6 +36,21 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,
+ return ERR_PTR(-ENODEV);
+ }
+
++static struct usb_phy *__of_usb_find_phy(struct list_head *list,
++ struct device_node *node)
++{
++ struct usb_phy *phy;
++
++ list_for_each_entry(phy, list, head) {
++ if (node != phy->dev->of_node)
++ continue;
++
++ return phy;
++ }
++
++ return ERR_PTR(-ENODEV);
++}
++
+ static void devm_usb_phy_release(struct device *dev, void *res)
+ {
+ struct usb_phy *phy = *(struct usb_phy **)res;
+@@ -111,6 +127,65 @@ err0:
+ EXPORT_SYMBOL(usb_get_phy);
+
+ /**
++ * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
++ * @dev - device that requests this phy
++ * @phandle - name of the property holding the phy phandle value
++ *
++ * Returns the phy driver associated with the given phandle value,
++ * after getting a refcount to it; or -ENODEV/NULL if there is no such phy.
++ * While at that, it also associates the device with the phy using
++ * devres. On driver detach, release function is invoked on the devres data,
++ * then, devres data is freed.
++ *
++ * For use by USB host and peripheral drivers.
++ */
++struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle)
++{
++ struct usb_phy *phy = NULL, **ptr;
++ unsigned long flags;
++ struct device_node *node;
++
++ if (!dev->of_node) {
++ dev_dbg(dev, "device does not have a device node entry\n");
++ return ERR_PTR(-EINVAL);
++ }
++
++ ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
++ if (!ptr) {
++ dev_dbg(dev, "failed to allocate memory for devres\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ spin_lock_irqsave(&phy_lock, flags);
++
++ node = of_parse_phandle(dev->of_node, phandle, 0);
++ if (!node) {
++ dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
++ dev->of_node->full_name);
++ goto err0;
++ }
++
++ phy = __of_usb_find_phy(&phy_list, node);
++ if (!IS_ERR(phy)) {
++ *ptr = phy;
++ devres_add(dev, ptr);
++ } else {
++ pr_err("unable to find transceiver with phandle %s\n", phandle);
++ devres_free(ptr);
++ goto err0;
++ }
++
++ get_device(phy->dev);
++
++err0:
++ spin_unlock_irqrestore(&phy_lock, flags);
++
++ return phy;
++}
++EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
++
++/**
+ * devm_usb_put_phy - release the USB PHY
+ * @dev - device that wants to release this phy
+ * @phy - the phy returned by devm_usb_get_phy()
+@@ -155,32 +230,24 @@ EXPORT_SYMBOL(usb_put_phy);
+ */
+ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
+ {
+- int ret = 0;
+ unsigned long flags;
+ struct usb_phy *phy;
+
+- if (x->type != USB_PHY_TYPE_UNDEFINED) {
+- dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
+- return -EINVAL;
+- }
++ if (x && x->type != USB_PHY_TYPE_UNDEFINED)
++ dev_dbg(x->dev, "add a phy with undefined type %s\n", x->label);
+
+ spin_lock_irqsave(&phy_lock, flags);
+
+- list_for_each_entry(phy, &phy_list, head) {
+- if (phy->type == type) {
+- ret = -EBUSY;
+- dev_err(x->dev, "transceiver type %s already exists\n",
++ list_for_each_entry(phy, &phy_list, head)
++ if (phy->type == type)
++ dev_dbg(x->dev, "transceiver type %s already exists\n",
+ usb_phy_type_string(type));
+- goto out;
+- }
+- }
+
+ x->type = type;
+ list_add_tail(&x->head, &phy_list);
+
+-out:
+ spin_unlock_irqrestore(&phy_lock, flags);
+- return ret;
++ return 0;
+ }
+ EXPORT_SYMBOL(usb_add_phy);
+
+diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
+index e8a5fe8..bae7599 100644
+--- a/include/linux/usb/otg.h
++++ b/include/linux/usb/otg.h
+@@ -37,8 +37,40 @@ struct usb_otg {
+ };
+
+ #ifdef CONFIG_USB_OTG_UTILS
++extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
++extern struct usb_phy *devm_usb_get_phy(struct device *dev,
++ enum usb_phy_type type);
++extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle);
++extern void usb_put_phy(struct usb_phy *);
++extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+ extern const char *otg_state_string(enum usb_otg_state state);
+ #else
++static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
++{
++ return NULL;
++}
++
++static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
++ enum usb_phy_type type)
++{
++ return NULL;
++}
++
++extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
++ const char *phandle)
++{
++ return NULL;
++}
++
++static inline void usb_put_phy(struct usb_phy *x)
++{
++}
++
++static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
++{
++}
++
+ static inline const char *otg_state_string(enum usb_otg_state state)
+ {
+ return NULL;
diff --git a/patches/linux-3.7/0081-usb-otg-nop-add-dt-support.patch b/patches/linux-3.7/0081-usb-otg-nop-add-dt-support.patch
new file mode 100644
index 0000000..4534f6a
--- /dev/null
+++ b/patches/linux-3.7/0081-usb-otg-nop-add-dt-support.patch
@@ -0,0 +1,47 @@
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Tue, 10 Jul 2012 14:51:53 +0530
+Subject: [PATCH] usb: otg: nop: add dt support
+
+Added device tree support for nop transceiver driver and updated the
+Documentation with device tree binding information for am33xx platform.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Signed-off-by: Ravi Babu <ravibabu@ti.com>
+---
+ drivers/usb/otg/nop-usb-xceiv.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
+index e52e35e..466a321 100644
+--- a/drivers/usb/otg/nop-usb-xceiv.c
++++ b/drivers/usb/otg/nop-usb-xceiv.c
+@@ -27,6 +27,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/of.h>
+ #include <linux/platform_device.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/usb/otg.h>
+@@ -154,12 +155,21 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_OF
++static const struct of_device_id nop_xceiv_id_table[] = {
++ { .compatible = "nop-xceiv-usb" },
++ {}
++};
++MODULE_DEVICE_TABLE(of, nop_xceiv_id_table);
++#endif
++
+ 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,
++ .of_match_table = of_match_ptr(nop_xceiv_id_table),
+ },
+ };
+
diff --git a/patches/linux-3.7/0082-usb-musb-dsps-add-phy-control-logic-to-glue.patch b/patches/linux-3.7/0082-usb-musb-dsps-add-phy-control-logic-to-glue.patch
new file mode 100644
index 0000000..c54df7c
--- /dev/null
+++ b/patches/linux-3.7/0082-usb-musb-dsps-add-phy-control-logic-to-glue.patch
@@ -0,0 +1,274 @@
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 5 Jul 2012 14:06:42 +0530
+Subject: [PATCH] usb: musb: dsps: add phy control logic to glue
+
+AM335x uses NOP transceiver driver and need to enable builtin PHY
+by writing into usb_ctrl register available in system control
+module register space. This is being added at musb glue driver
+layer untill a separate system control module driver is available.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ arch/arm/mach-omap2/board-ti8168evm.c | 1 -
+ arch/arm/mach-omap2/omap_phy_internal.c | 35 ------------
+ arch/arm/plat-omap/include/plat/usb.h | 5 +-
+ drivers/usb/musb/musb_dsps.c | 91 +++++++++++++++++++++++++------
+ 4 files changed, 75 insertions(+), 57 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
+index c4f8833..b367d18 100644
+--- a/arch/arm/mach-omap2/board-ti8168evm.c
++++ b/arch/arm/mach-omap2/board-ti8168evm.c
+@@ -23,7 +23,6 @@
+ #include <plat/usb.h>
+
+ static struct omap_musb_board_data musb_board_data = {
+- .set_phy_power = ti81xx_musb_phy_power,
+ .interface_type = MUSB_INTERFACE_ULPI,
+ .mode = MUSB_OTG,
+ .power = 500,
+diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
+index d992db8..db3ada8 100644
+--- a/arch/arm/mach-omap2/omap_phy_internal.c
++++ b/arch/arm/mach-omap2/omap_phy_internal.c
+@@ -118,38 +118,3 @@ void am35x_set_mode(u8 musb_mode)
+
+ omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+ }
+-
+-void ti81xx_musb_phy_power(u8 on)
+-{
+- void __iomem *scm_base = NULL;
+- u32 usbphycfg;
+-
+- scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K);
+- if (!scm_base) {
+- pr_err("system control module ioremap failed\n");
+- return;
+- }
+-
+- usbphycfg = __raw_readl(scm_base + USBCTRL0);
+-
+- if (on) {
+- if (cpu_is_ti816x()) {
+- usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
+- usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
+- } else if (cpu_is_ti814x()) {
+- usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
+- | USBPHY_DPINPUT | USBPHY_DMINPUT);
+- usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
+- | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
+- }
+- } else {
+- if (cpu_is_ti816x())
+- usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
+- else if (cpu_is_ti814x())
+- usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+-
+- }
+- __raw_writel(usbphycfg, scm_base + USBCTRL0);
+-
+- iounmap(scm_base);
+-}
+diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
+index 87ee140..43052e7f 100644
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -101,7 +101,6 @@ extern void am35x_musb_reset(void);
+ extern void am35x_musb_phy_power(u8 on);
+ extern void am35x_musb_clear_irq(void);
+ extern void am35x_set_mode(u8 musb_mode);
+-extern void ti81xx_musb_phy_power(u8 on);
+
+ /* AM35x */
+ /* USB 2.0 PHY Control */
+@@ -126,8 +125,8 @@ extern void ti81xx_musb_phy_power(u8 on);
+ #define CONF2_DATPOL (1 << 1)
+
+ /* TI81XX specific definitions */
+-#define USBCTRL0 0x620
+-#define USBSTAT0 0x624
++#define MUSB_USBSS_REV_816X 0x9
++#define MUSB_USBSS_REV_814X 0xb
+
+ /* TI816X PHY controls bits */
+ #define TI816X_USBPHY0_NORMAL_MODE (1 << 0)
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 6a14101..1151760 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -124,9 +124,46 @@ struct dsps_glue {
+ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
+ struct timer_list timer[2]; /* otg_workaround timer */
+ unsigned long last_timer[2]; /* last timer data for each instance */
++ u32 __iomem *usb_ctrl[2];
++ u8 usbss_rev;
+ };
+
+ /**
++ * musb_dsps_phy_control - phy on/off
++ * @glue: struct dsps_glue *
++ * @id: the id
++ * @on: flag for phy to be switched on or off
++ *
++ * This is to enable the PHY using usb_ctrl register in system control
++ * module space.
++ *
++ * XXX: This function will be removed once we have a seperate driver for
++ * control module
++ */
++static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
++{
++ u32 usbphycfg;
++
++ usbphycfg = __raw_readl(glue->usb_ctrl[id]);
++ if (on) {
++ if (glue->usbss_rev == MUSB_USBSS_REV_816X) {
++ usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
++ usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
++ } else if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
++ usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
++ | USBPHY_DPINPUT | USBPHY_DMINPUT);
++ usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
++ | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
++ }
++ } else {
++ if (glue->usbss_rev == MUSB_USBSS_REV_816X)
++ usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
++ else if (glue->usbss_rev == MUSB_USBSS_REV_814X)
++ usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
++ }
++ __raw_writel(usbphycfg, glue->usb_ctrl[id]);
++}
++/**
+ * dsps_musb_enable - enable interrupts
+ */
+ static void dsps_musb_enable(struct musb *musb)
+@@ -365,12 +402,10 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
+ static int dsps_musb_init(struct musb *musb)
+ {
+ struct device *dev = musb->controller;
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct platform_device *parent_pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+- struct omap_musb_board_data *data = plat->board_data;
+ void __iomem *reg_base = musb->ctrl_base;
+ char name[10];
+ u32 rev, val;
+@@ -398,8 +433,7 @@ static int dsps_musb_init(struct musb *musb)
+ dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
+
+ /* Start the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(1);
++ musb_dsps_phy_control(glue, pdev->id, 1);
+
+ musb->isr = dsps_interrupt;
+
+@@ -421,16 +455,13 @@ err0:
+ static int dsps_musb_exit(struct musb *musb)
+ {
+ struct device *dev = musb->controller;
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
+- struct platform_device *pdev = to_platform_device(dev);
+- struct dsps_glue *glue = dev_get_drvdata(dev->parent);
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ del_timer_sync(&glue->timer[pdev->id]);
+
+ /* Shutdown the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(0);
++ musb_dsps_phy_control(glue, pdev->id, 0);
+
+ /* NOP driver needs change if supporting dual instance */
+ usb_put_phy(musb->xceiv);
+@@ -464,6 +495,21 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+ char res_name[11];
+ int ret, musbid;
+
++ /* get memory resource for usb control register */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2 * id + 2);
++ if (!res) {
++ dev_err(dev, "%s get mem resource failed\n", res_name);
++ ret = -ENODEV;
++ goto err0;
++ }
++
++ glue->usb_ctrl[id] = devm_request_and_ioremap(&pdev->dev, res);
++ if (glue->usb_ctrl == NULL) {
++ dev_err(dev, "Failed to obtain usb_ctrl%d memory\n", id);
++ ret = -ENODEV;
++ goto err0;
++ }
++
+ /* get memory resource */
+ snprintf(res_name, sizeof(res_name), "musb%d", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+@@ -579,6 +625,7 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ const struct dsps_musb_wrapper *wrp;
+ struct dsps_glue *glue;
+ struct resource *iomem;
++ u32 __iomem *usbss;
+ int ret, i;
+
+ match = of_match_node(musb_dsps_of_match, np);
+@@ -605,6 +652,13 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ goto err1;
+ }
+
++ usbss = devm_request_and_ioremap(&pdev->dev, iomem);
++ if (usbss == NULL) {
++ dev_err(&pdev->dev, "Failed to obtain usbss memory\n");
++ ret = -ENODEV;
++ goto err1;
++ }
++
+ glue->dev = &pdev->dev;
+
+ glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
+@@ -636,6 +690,9 @@ static int __devinit dsps_probe(struct platform_device *pdev)
+ }
+ }
+
++ /* read the usbss revision register */
++ glue->usbss_rev = __raw_readl(usbss);
++
+ return 0;
+
+ err3:
+@@ -669,24 +726,22 @@ static int __devexit dsps_remove(struct platform_device *pdev)
+ #ifdef CONFIG_PM_SLEEP
+ static int dsps_suspend(struct device *dev)
+ {
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* Shutdown the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(0);
++ musb_dsps_phy_control(glue, pdev->id, 0);
+
+ return 0;
+ }
+
+ static int dsps_resume(struct device *dev)
+ {
+- struct musb_hdrc_platform_data *plat = dev->platform_data;
+- struct omap_musb_board_data *data = plat->board_data;
++ struct platform_device *pdev = to_platform_device(dev->parent);
++ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* Start the on-chip PHY and its PLL. */
+- if (data->set_phy_power)
+- data->set_phy_power(1);
++ musb_dsps_phy_control(glue, pdev->id, 1);
+
+ return 0;
+ }
diff --git a/patches/linux-3.7/0083-usb-musb-dsps-enable-phy-control-for-am335x.patch b/patches/linux-3.7/0083-usb-musb-dsps-enable-phy-control-for-am335x.patch
new file mode 100644
index 0000000..98c91ab
--- /dev/null
+++ b/patches/linux-3.7/0083-usb-musb-dsps-enable-phy-control-for-am335x.patch
@@ -0,0 +1,57 @@
+From: Ajay Kumar Gupta <ajay.gupta@ti.com>
+Date: Thu, 5 Jul 2012 14:35:06 +0530
+Subject: [PATCH] usb: musb: dsps: enable phy control for am335x
+
+Enabled the phy control logic for am335x also based on usbss
+revision register.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+ arch/arm/plat-omap/include/plat/usb.h | 1 +
+ drivers/usb/musb/musb_dsps.c | 17 +++++++++++------
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
+index 43052e7f..bb27e88 100644
+--- a/arch/arm/plat-omap/include/plat/usb.h
++++ b/arch/arm/plat-omap/include/plat/usb.h
+@@ -127,6 +127,7 @@ extern void am35x_set_mode(u8 musb_mode);
+ /* TI81XX specific definitions */
+ #define MUSB_USBSS_REV_816X 0x9
+ #define MUSB_USBSS_REV_814X 0xb
++#define MUSB_USBSS_REV_33XX 0xd
+
+ /* TI816X PHY controls bits */
+ #define TI816X_USBPHY0_NORMAL_MODE (1 << 0)
+diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
+index 1151760..ed3b379 100644
+--- a/drivers/usb/musb/musb_dsps.c
++++ b/drivers/usb/musb/musb_dsps.c
+@@ -149,16 +149,21 @@ static void musb_dsps_phy_control(struct dsps_glue *glue, u8 id, u8 on)
+ if (glue->usbss_rev == MUSB_USBSS_REV_816X) {
+ usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
+ usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
+- } else if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
+- usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
+- | USBPHY_DPINPUT | USBPHY_DMINPUT);
+- usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
+- | USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
++ } else if (glue->usbss_rev == MUSB_USBSS_REV_814X ||
++ glue->usbss_rev == MUSB_USBSS_REV_33XX) {
++ usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
++ usbphycfg |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
++ if (glue->usbss_rev == MUSB_USBSS_REV_814X) {
++ usbphycfg &= ~(USBPHY_DPINPUT | USBPHY_DMINPUT);
++ usbphycfg |= USBPHY_DPOPBUFCTL
++ | USBPHY_DMOPBUFCTL;
++ }
+ }
+ } else {
+ if (glue->usbss_rev == MUSB_USBSS_REV_816X)
+ usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
+- else if (glue->usbss_rev == MUSB_USBSS_REV_814X)
++ else if (glue->usbss_rev == MUSB_USBSS_REV_814X ||
++ glue->usbss_rev == MUSB_USBSS_REV_33XX)
+ usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
+ }
+ __raw_writel(usbphycfg, glue->usb_ctrl[id]);
diff --git a/patches/linux-3.7/0084-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch b/patches/linux-3.7/0084-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
new file mode 100644
index 0000000..0a0132c
--- /dev/null
+++ b/patches/linux-3.7/0084-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
@@ -0,0 +1,44 @@
+From: Daniel Mack <zonque@gmail.com>
+Date: Wed, 17 Oct 2012 16:39:00 +0200
+Subject: [PATCH] ARM: am33xx: fix mem regions in USB hwmod
+
+Signed-off-by: Daniel Mack <zonque@gmail.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index b6f78c1..2a5032f 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -3310,12 +3310,24 @@ static struct omap_hwmod_addr_space am33xx_usbss_addr_space[] = {
+ .pa_end = 0x47401000 + SZ_2K - 1,
+ .flags = ADDR_TYPE_RT
+ },
+- {
+- .name = "musb1",
+- .pa_start = 0x47401800,
+- .pa_end = 0x47401800 + SZ_2K - 1,
+- .flags = ADDR_TYPE_RT
+- },
++ {
++ .name = "usb_ctrl0",
++ .pa_start = 0x44E10620,
++ .pa_end = 0x44E10620 + SZ_4 - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .name = "musb1",
++ .pa_start = 0x47401800,
++ .pa_end = 0x47401800 + SZ_2K - 1,
++ .flags = ADDR_TYPE_RT
++ },
++ {
++ .name = "usb_ctrl1",
++ .pa_start = 0x44E10628,
++ .pa_end = 0x44E10628 + SZ_4 - 1,
++ .flags = ADDR_TYPE_RT
++ },
+ { }
+ };
+
diff --git a/patches/linux-3.7/0086-omap2-clk-Add-missing-lcdc-clock-definition.patch b/patches/linux-3.7/0086-omap2-clk-Add-missing-lcdc-clock-definition.patch
new file mode 100644
index 0000000..75cda70
--- /dev/null
+++ b/patches/linux-3.7/0086-omap2-clk-Add-missing-lcdc-clock-definition.patch
@@ -0,0 +1,39 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:12:22 +0300
+Subject: [PATCH] omap2-clk: Add missing lcdc clock definition
+
+Looks like the lcdc clock definition got dropped.
+It is required for the LCD controller to work. Reintroduce.
+---
+ arch/arm/mach-omap2/clock33xx_data.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
+index 1a45d6b..b7b7995 100644
+--- a/arch/arm/mach-omap2/clock33xx_data.c
++++ b/arch/arm/mach-omap2/clock33xx_data.c
+@@ -867,6 +867,16 @@ static struct clk lcd_gclk = {
+ .recalc = &followparent_recalc,
+ };
+
++static struct clk lcdc_fck = {
++ .name = "lcdc_fck",
++ .clkdm_name = "lcdc_clkdm",
++ .parent = &lcd_gclk,
++ .enable_reg = AM33XX_CM_PER_LCDC_CLKCTRL,
++ .enable_bit = AM33XX_MODULEMODE_SWCTRL,
++ .ops = &clkops_omap2_dflt,
++ .recalc = &followparent_recalc,
++};
++
+ static struct clk mmc_clk = {
+ .name = "mmc_clk",
+ .clkdm_name = "l4ls_clkdm",
+@@ -1075,6 +1085,7 @@ static struct omap_clk am33xx_clks[] = {
+ CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX),
+ CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX),
+ CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX),
++ CLK("da8xx_lcdc.0", NULL, &lcdc_fck, CK_AM33XX),
+ };
+
+ int __init am33xx_clk_init(void)
diff --git a/patches/linux-3.7/0087-da8xx-Allow-use-by-am33xx-based-devices.patch b/patches/linux-3.7/0087-da8xx-Allow-use-by-am33xx-based-devices.patch
new file mode 100644
index 0000000..97a9b4b
--- /dev/null
+++ b/patches/linux-3.7/0087-da8xx-Allow-use-by-am33xx-based-devices.patch
@@ -0,0 +1,22 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:18:37 +0300
+Subject: [PATCH] da8xx: Allow use by am33xx based devices
+
+This driver can be used for AM33xx devices, like the popular beaglebone.
+---
+ drivers/video/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 9791d10..e7868d8 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2202,7 +2202,7 @@ config FB_SH7760
+
+ config FB_DA8XX
+ tristate "DA8xx/OMAP-L1xx Framebuffer support"
+- depends on FB && ARCH_DAVINCI_DA8XX
++ depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
diff --git a/patches/linux-3.7/0088-da8xx-Fix-revision-check-on-the-da8xx-driver.patch b/patches/linux-3.7/0088-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
new file mode 100644
index 0000000..f8bdbaa
--- /dev/null
+++ b/patches/linux-3.7/0088-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
@@ -0,0 +1,21 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:21:05 +0300
+Subject: [PATCH] da8xx: Fix revision check on the da8xx driver
+
+The revision check fails for the beaglebone; Add new revision ID.
+---
+ drivers/video/da8xx-fb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 80665f6..866d804 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -1283,6 +1283,7 @@ static int __devinit fb_probe(struct platform_device *device)
+ lcd_revision = LCD_VERSION_1;
+ break;
+ case 0x4F200800:
++ case 0x4F201000:
+ lcd_revision = LCD_VERSION_2;
+ break;
+ default:
diff --git a/patches/linux-3.7/0089-da8xx-De-constify-members-in-the-platform-config.patch b/patches/linux-3.7/0089-da8xx-De-constify-members-in-the-platform-config.patch
new file mode 100644
index 0000000..66fe3e0
--- /dev/null
+++ b/patches/linux-3.7/0089-da8xx-De-constify-members-in-the-platform-config.patch
@@ -0,0 +1,28 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:22:47 +0300
+Subject: [PATCH] da8xx: De-constify members in the platform config.
+
+There's no need for this to be const. It interferes with
+creating the platform data dynamically.
+
+Remove const.
+---
+ include/video/da8xx-fb.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
+index 5a0e4f9..a512d6b 100644
+--- a/include/video/da8xx-fb.h
++++ b/include/video/da8xx-fb.h
+@@ -35,9 +35,9 @@ struct display_panel {
+ };
+
+ struct da8xx_lcdc_platform_data {
+- const char manu_name[10];
++ char manu_name[10];
+ void *controller_data;
+- const char type[25];
++ char type[25];
+ void (*panel_power_ctrl)(int);
+ };
+
diff --git a/patches/linux-3.7/0090-da8xx-Add-standard-panel-definition.patch b/patches/linux-3.7/0090-da8xx-Add-standard-panel-definition.patch
new file mode 100644
index 0000000..e53aa39
--- /dev/null
+++ b/patches/linux-3.7/0090-da8xx-Add-standard-panel-definition.patch
@@ -0,0 +1,35 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:24:19 +0300
+Subject: [PATCH] da8xx: Add standard panel definition
+
+Add standard panel definition that can work for the beaglebone
+DVI cape.
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 866d804..4462d9e 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -270,6 +270,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 7833600,
+ .invert_pxl_clk = 0,
+ },
++ [3] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "1024x768@60",
++ .width = 1024,
++ .height = 768,
++ .hfp = 48,
++ .hbp = 80,
++ .hsw = 32,
++ .vfp = 3,
++ .vbp = 15,
++ .vsw = 4,
++ .pxl_clk = 56000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7/0091-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch b/patches/linux-3.7/0091-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
new file mode 100644
index 0000000..9bfe02d
--- /dev/null
+++ b/patches/linux-3.7/0091-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
@@ -0,0 +1,33 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 15:43:55 +0300
+Subject: [PATCH] da8xx: Add CDTech_S035Q01 panel (used by LCD3 bone cape)
+
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 4462d9e..873789b 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -284,6 +284,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 56000000,
+ .invert_pxl_clk = 0,
+ },
++ [4] = {
++ /* CDTech S035Q01 */
++ .name = "CDTech_S035Q01",
++ .width = 320,
++ .height = 240,
++ .hfp = 58,
++ .hbp = 21,
++ .hsw = 47,
++ .vfp = 23,
++ .vbp = 11,
++ .vsw = 2,
++ .pxl_clk = 8000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7/0092-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch b/patches/linux-3.7/0092-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
new file mode 100644
index 0000000..87f3ea8
--- /dev/null
+++ b/patches/linux-3.7/0092-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
@@ -0,0 +1,34 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 17 Oct 2012 11:32:24 +0200
+Subject: [PATCH] da8xx-fb: add panel definition for beaglebone LCD7 cape
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/da8xx-fb.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 873789b..6d98184 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -298,6 +298,20 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 8000000,
+ .invert_pxl_clk = 0,
+ },
++ /* ThreeFive S9700RTWV35TR */
++ [5] = {
++ .name = "TFC_S9700RTWV35TR_01B",
++ .width = 800,
++ .height = 480,
++ .hfp = 39,
++ .hbp = 39,
++ .hsw = 47,
++ .vfp = 13,
++ .vbp = 29,
++ .vsw = 2,
++ .pxl_clk = 30000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7/0094-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch b/patches/linux-3.7/0094-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
new file mode 100644
index 0000000..6cf21e8
--- /dev/null
+++ b/patches/linux-3.7/0094-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
@@ -0,0 +1,116 @@
+From: "Hebbar, Gururaja" <gururaja.hebbar@ti.com>
+Date: Tue, 4 Sep 2012 13:09:11 +0000
+Subject: [PATCH] mmc: omap_hsmmc: Enable HSPE bit for high speed cards
+
+HSMMC IP on AM33xx need a special setting to handle High-speed cards.
+Other platforms like TI81xx, OMAP4 may need this as-well. This depends
+on the HSMMC IP timing closure done for the high speed cards.
+
+>From AM335x TRM (SPRUH73F - 18.3.12 Output Signals Generation)
+
+The MMC/SD/SDIO output signals can be driven on either falling edge or
+rising edge depending on the SD_HCTL[2] HSPE bit. This feature allows
+to reach better timing performance, and thus to increase data transfer
+frequency.
+
+There are few pre-requisites for enabling the HSPE bit
+- Controller should support High-Speed-Enable Bit and
+- Controller should not be using DDR Mode and
+- Controller should advertise that it supports High Speed in
+ capabilities register and
+- MMC/SD clock coming out of controller > 25MHz
+
+Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
+---
+ arch/arm/plat-omap/include/plat/mmc.h | 1 +
+ drivers/mmc/host/omap_hsmmc.c | 30 +++++++++++++++++++++++++++++-
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
+index 8b4e4f2..346af5b 100644
+--- a/arch/arm/plat-omap/include/plat/mmc.h
++++ b/arch/arm/plat-omap/include/plat/mmc.h
+@@ -126,6 +126,7 @@ struct omap_mmc_platform_data {
+ /* we can put the features above into this variable */
+ #define HSMMC_HAS_PBIAS (1 << 0)
+ #define HSMMC_HAS_UPDATED_RESET (1 << 1)
++#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
+ unsigned features;
+
+ int switch_pin; /* gpio (card detect) */
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 4fe62b0..897b718 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -62,6 +62,7 @@
+
+ #define VS18 (1 << 26)
+ #define VS30 (1 << 25)
++#define HSS (1 << 21)
+ #define SDVS18 (0x5 << 9)
+ #define SDVS30 (0x6 << 9)
+ #define SDVS33 (0x7 << 9)
+@@ -89,6 +90,7 @@
+ #define MSBS (1 << 5)
+ #define BCE (1 << 1)
+ #define FOUR_BIT (1 << 1)
++#define HSPE (1 << 2)
+ #define DDR (1 << 19)
+ #define DW8 (1 << 5)
+ #define CC 0x1
+@@ -494,6 +496,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+ struct mmc_ios *ios = &host->mmc->ios;
+ unsigned long regval;
+ unsigned long timeout;
++ unsigned long clkdiv;
+
+ dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
+
+@@ -501,7 +504,8 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+
+ regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+ regval = regval & ~(CLKD_MASK | DTO_MASK);
+- regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
++ clkdiv = calc_divisor(host, ios);
++ regval = regval | (clkdiv << 6) | (DTO << 16);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+@@ -512,6 +516,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
+ && time_before(jiffies, timeout))
+ cpu_relax();
+
++ /*
++ * Enable High-Speed Support
++ * Pre-Requisites
++ * - Controller should support High-Speed-Enable Bit
++ * - Controller should not be using DDR Mode
++ * - Controller should advertise that it supports High Speed
++ * in capabilities register
++ * - MMC/SD clock coming out of controller > 25MHz
++ */
++ if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
++ (ios->timing != MMC_TIMING_UHS_DDR50) &&
++ ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
++ regval = OMAP_HSMMC_READ(host->base, HCTL);
++ if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
++ regval |= HSPE;
++ else
++ regval &= ~HSPE;
++
++ OMAP_HSMMC_WRITE(host->base, HCTL, regval);
++ }
++
+ omap_hsmmc_start_clock(host);
+ }
+
+@@ -1705,6 +1730,9 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ if (of_find_property(np, "ti,needs-special-reset", NULL))
+ pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
++ if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
++ pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
++
+ return pdata;
+ }
+ #else
diff --git a/patches/linux-3.7/0095-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch b/patches/linux-3.7/0095-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
new file mode 100644
index 0000000..d27bff6
--- /dev/null
+++ b/patches/linux-3.7/0095-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
@@ -0,0 +1,37 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Thu, 18 Oct 2012 10:11:48 +0200
+Subject: [PATCH] am33xx.dtsi: enable MMC HSPE bit for all 3 controllers
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 0b53cde..5e418c7 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -267,6 +267,7 @@
+ ti,hwmods = "mmc1";
+ ti,dual-volt;
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ dmas = <&edma 24
+ &edma 25>;
+ dma-names = "tx", "rx";
+@@ -276,6 +277,7 @@
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc2";
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ dmas = <&edma 2
+ &edma 3>;
+ dma-names = "tx", "rx";
+@@ -286,6 +288,7 @@
+ compatible = "ti,omap3-hsmmc";
+ ti,hwmods = "mmc3";
+ ti,needs-special-reset;
++ ti,needs-special-hs-handling;
+ status = "disabled";
+ };
+
diff --git a/patches/linux-3.7/0096-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch b/patches/linux-3.7/0096-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
new file mode 100644
index 0000000..3128772
--- /dev/null
+++ b/patches/linux-3.7/0096-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
@@ -0,0 +1,22 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 15:48:00 +0300
+Subject: [PATCH] omap-hsmmc: Correct usage of of_find_node_by_name
+
+of_find_node_by_name expect to have the parent node reference taken.
+---
+ drivers/mmc/host/omap_hsmmc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 897b718..7a1283c 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -1864,7 +1864,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ /* Eventually we should get our max_segs limitation for EDMA by
+ * querying the dmaengine API */
+ if (pdev->dev.of_node) {
+- struct device_node *parent = pdev->dev.of_node->parent;
++ struct device_node *parent = of_node_get(pdev->dev.of_node->parent);
+ struct device_node *node;
+ node = of_find_node_by_name(parent, "edma");
+ if (node)
diff --git a/patches/linux-3.7/0098-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch b/patches/linux-3.7/0098-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
new file mode 100644
index 0000000..5e39bdb
--- /dev/null
+++ b/patches/linux-3.7/0098-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
@@ -0,0 +1,24 @@
+From: Vaibhav Hiremath <hvaibhav@ti.com>
+Date: Fri, 19 Oct 2012 02:01:39 +0530
+Subject: [PATCH] ARM: AM33XX: hwmod: Remove wrong INIT_NO_RESET/IDLE flags
+ from cpgmac entry
+
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+index 2a5032f..76531f9 100644
+--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+@@ -681,8 +681,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
+ .modulemode = MODULEMODE_SWCTRL,
+ },
+ },
+- .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
+- HWMOD_INIT_NO_RESET | HWMOD_INIT_NO_IDLE),
++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+ };
+
+ /*
diff --git a/patches/linux-3.7/0100-f2fs-add-document.patch b/patches/linux-3.7/0100-f2fs-add-document.patch
new file mode 100644
index 0000000..5934e17
--- /dev/null
+++ b/patches/linux-3.7/0100-f2fs-add-document.patch
@@ -0,0 +1,437 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:25:11 +0000
+Subject: [PATCH] f2fs: add document
+
+This adds a document describing the mount options, proc entries, usage, and
+design of Flash-Friendly File System, namely F2FS.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ Documentation/filesystems/00-INDEX | 2 +
+ Documentation/filesystems/f2fs.txt | 404 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 406 insertions(+)
+ create mode 100644 Documentation/filesystems/f2fs.txt
+
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 8c624a1..ce5fd46 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -48,6 +48,8 @@ ext4.txt
+ - info, mount options and specifications for the Ext4 filesystem.
+ files.txt
+ - info on file management in the Linux kernel.
++f2fs.txt
++ - info and mount options for the F2FS filesystem.
+ fuse.txt
+ - info on the Filesystem in User SpacE including mount options.
+ gfs2.txt
+diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
+new file mode 100644
+index 0000000..f2b4fde
+--- /dev/null
++++ b/Documentation/filesystems/f2fs.txt
+@@ -0,0 +1,404 @@
++================================================================================
++WHAT IS Flash-Friendly File System (F2FS)?
++================================================================================
++
++NAND flash memory-based storage devices, such as SSD, eMMC, and SD cards, have
++been widely being used for storage ranging from mobile to server systems. Since
++they are known to have different characteristics from the conventional rotating
++disks, a file system, an upper layer to the storage device, should adapt to the
++changes from the sketch in the design level.
++
++F2FS is a file system exploiting NAND flash memory-based storage devices, which
++is based on Log-structured File System (LFS). The design has been focused on
++addressing the fundamental issues in LFS, which are snowball effect of wandering
++tree and high cleaning overhead.
++
++Since a NAND flash memory-based storage device shows different characteristic
++according to its internal geometry or flash memory management scheme, namely FTL,
++F2FS and its tools support various parameters not only for configuring on-disk
++layout, but also for selecting allocation and cleaning algorithms.
++
++The file system formatting tool, "mkfs.f2fs", is available from the following
++download page: http://sourceforge.net/projects/f2fs-tools/
++
++================================================================================
++BACKGROUND AND DESIGN ISSUES
++================================================================================
++
++Log-structured File System (LFS)
++--------------------------------
++"A log-structured file system writes all modifications to disk sequentially in
++a log-like structure, thereby speeding up both file writing and crash recovery.
++The log is the only structure on disk; it contains indexing information so that
++files can be read back from the log efficiently. In order to maintain large free
++areas on disk for fast writing, we divide the log into segments and use a
++segment cleaner to compress the live information from heavily fragmented
++segments." from Rosenblum, M. and Ousterhout, J. K., 1992, "The design and
++implementation of a log-structured file system", ACM Trans. Computer Systems
++10, 1, 26–52.
++
++Wandering Tree Problem
++----------------------
++In LFS, when a file data is updated and written to the end of log, its direct
++pointer block is updated due to the changed location. Then the indirect pointer
++block is also updated due to the direct pointer block update. In this manner,
++the upper index structures such as inode, inode map, and checkpoint block are
++also updated recursively. This problem is called as wandering tree problem [1],
++and in order to enhance the performance, it should eliminate or relax the update
++propagation as much as possible.
++
++[1] Bityutskiy, A. 2005. JFFS3 design issues. http://www.linux-mtd.infradead.org/
++
++Cleaning Overhead
++-----------------
++Since LFS is based on out-of-place writes, it produces so many obsolete blocks
++scattered across the whole storage. In order to serve new empty log space, it
++needs to reclaim these obsolete blocks seamlessly to users. This job is called
++as a cleaning process.
++
++The process consists of three operations as follows.
++1. A victim segment is selected through referencing segment usage table.
++2. It loads parent index structures of all the data in the victim identified by
++ segment summary blocks.
++3. It checks the cross-reference between the data and its parent index structure.
++4. It moves valid data selectively.
++
++This cleaning job may cause unexpected long delays, so the most important goal
++is to hide the latencies to users. And also definitely, it should reduce the
++amount of valid data to be moved, and move them quickly as well.
++
++================================================================================
++KEY FEATURES
++================================================================================
++
++Flash Awareness
++---------------
++- Enlarge the random write area for better performance, but provide the high
++ spatial locality
++- Align FS data structures to the operational units in FTL as best efforts
++
++Wandering Tree Problem
++----------------------
++- Use a term, “node”, that represents inodes as well as various pointer blocks
++- Introduce Node Address Table (NAT) containing the locations of all the “node”
++ blocks; this will cut off the update propagation.
++
++Cleaning Overhead
++-----------------
++- Support a background cleaning process
++- Support greedy and cost-benefit algorithms for victim selection policies
++- Support multi-head logs for static/dynamic hot and cold data separation
++- Introduce adaptive logging for efficient block allocation
++
++================================================================================
++MOUNT OPTIONS
++================================================================================
++
++background_gc_off Turn off cleaning operations, namely garbage collection,
++ triggered in background when I/O subsystem is idle.
++disable_roll_forward Disable the roll-forward recovery routine
++discard Issue discard/TRIM commands when a segment is cleaned.
++no_heap Disable heap-style segment allocation which finds free
++ segments for data from the beginning of main area, while
++ for node from the end of main area.
++nouser_xattr Disable Extended User Attributes. Note: xattr is enabled
++ by default if CONFIG_F2FS_FS_XATTR is selected.
++noacl Disable POSIX Access Control List. Note: acl is enabled
++ by default if CONFIG_F2FS_FS_POSIX_ACL is selected.
++active_logs=%u Support configuring the number of active logs. In the
++ current design, f2fs supports only 2, 4, and 6 logs.
++ Default number is 6.
++disable_ext_identify Disable the extension list configured by mkfs, so f2fs
++ does not aware of cold files such as media files.
++
++================================================================================
++PROC ENTRIES
++================================================================================
++
++/proc/fs/f2fs/ contains information about partitions mounted as f2fs. For each
++partition, a corresponding directory, named as its device name, is provided with
++the following proc entries.
++
++- f2fs_stat major file system information managed by f2fs currently
++- f2fs_sit_stat average utilization information of the whole segments
++- f2fs_mem_stat current memory footprint consumed by f2fs
++
++e.g., in /proc/fs/f2fs/sdb1/
++
++================================================================================
++USAGE
++================================================================================
++
++1. Download userland tools
++
++2. Insmod f2fs.ko module:
++ # insmod f2fs.ko
++
++3. Check the directory trying to mount
++ # mkdir /mnt/f2fs
++
++4. Format the block device, and then mount as f2fs
++ # mkfs.f2fs -l label /dev/block_device
++ # mount -t f2fs /dev/block_device /mnt/f2fs
++
++Mount options
++-------------
++-l [label] : Give a volume label, up to 256 unicode name.
++-a [0 or 1] : Split start location of each area for heap-based allocation.
++ 1 is set by default, which performs this.
++-o [int] : Set overprovision ratio in percent over volume size.
++ 5 is set by default.
++-s [int] : Set the number of segments per section.
++ 1 is set by default.
++-z [int] : Set the number of sections per zone.
++ 1 is set by default.
++-e [str] : Set basic extension list. e.g. "mp3,gif,mov"
++
++================================================================================
++DESIGN
++================================================================================
++
++On-disk Layout
++--------------
++
++F2FS divides the whole volume into a number of segments, each of which is 2MB in
++size by default. A section is composed of consecutive segments, and a zone
++consists of a set of sections.
++
++F2FS maintains logically six log areas. Except SB, all the log areas are managed
++in a unit of multiple segments. SB is located at the beginning of the partition,
++and there exist two superblocks to avoid file system crash. Other file system
++metadata such as CP, NAT, SIT, and SSA are located in the front part of the
++volume. Main area contains file and directory data including their indices.
++
++Each area manages the following contents.
++- CP File system information, bitmaps for valid NAT/SIT sets, orphan
++ inode lists, and summary entries of current active segments.
++- NAT Block address table for all the node blocks stored in Main area.
++- SIT Segment information such as valid block count and bitmap for the
++ validity of all the blocks.
++- SSA Summary entries which contains the owner information of all the
++ data and node blocks stored in Main area.
++- Main Node and data blocks.
++
++In order to avoid misalignment between file system and flash-based storage, F2FS
++aligns the start block address of CP with the segment size. Also, it aligns the
++start block address of Main area with the zone size by reserving some segments
++in SSA area.
++
++ align with the zone size <-|
++ |-> align with the segment size
++ _________________________________________________________________________
++ | | | Node | Segment | Segment | |
++ | Superblock | Checkpoint | Address | Info. | Summary | Main |
++ | (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | |
++ |____________|_____2______|______N______|______N______|______N_____|__N___|
++ . .
++ . .
++ . .
++ ._________________________________________.
++ |_Segment_|_..._|_Segment_|_..._|_Segment_|
++ . .
++ ._________._________
++ |_section_|__...__|_
++ . .
++ .________.
++ |__zone__|
++
++
++File System Metadata Structure
++------------------------------
++
++F2FS adopts the checkpointing scheme to maintain file system consistency. At
++mount time, F2FS first tries to find the last valid checkpoint data by scanning
++CP area. In order to reduce the scanning time, F2FS uses only two copies of CP.
++One of them always indicates the last valid data, which is called as shadow copy
++mechanism. In addition to CP, NAT and SIT also adopt the shadow copy mechanism.
++
++For file system consistency, each CP points to which NAT and SIT copies are
++valid, as shown as below.
++
++ +--------+----------+---------+
++ | CP | NAT | SIT |
++ +--------+----------+---------+
++ . . . .
++ . . . .
++ . . . .
++ +-------+-------+--------+--------+--------+--------+
++ | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
++ +-------+-------+--------+--------+--------+--------+
++ | ^ ^
++ | | |
++ `----------------------------------------'
++
++Index Structure
++---------------
++
++The key data structure to manage the data locations is a "node". Similar to
++traditional file structures, F2FS has three types of node: inode, direct node,
++indirect node. F2FS assigns 4KB to an inode block which contains 929 data block
++indices, two direct node pointers, two indirect node pointers, and one double
++indirect node pointer as described below. One direct node block contains 1018
++data blocks, and one indirect node block contains also 1018 node blocks. Thus,
++one inode block (i.e., a file) covers:
++
++ 4KB * (927 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
++
++ Inode block (4KB)
++ |- data (927)
++ |- direct node (2)
++ | `- data (1018)
++ |- indirect node (2)
++ | `- direct node (1018)
++ | `- data (1018)
++ `- double indirect node (1)
++ `- indirect node (1018)
++ `- direct node (1018)
++ `- data (1018)
++
++Note that, all the node blocks are mapped by NAT which means the location of
++each node is translated by the NAT table. In the consideration of the wandering
++tree problem, F2FS is able to cut off the propagation of node updates caused by
++leaf data writes.
++
++Directory Structure
++-------------------
++
++A directory entry occupies 11 bytes, which consists of the following attributes.
++
++- hash hash value of the file name
++- ino inode number
++- len the length of file name
++- type file type such as directory, symlink, etc
++
++A dentry block consists of 214 dentry slots and file names. Therein a bitmap is
++used to represent whether each dentry is valid or not. A dentry block occupies
++4KB with the following composition.
++
++ Dentry Block(4 K) = bitmap (27 bytes) + reserved (3 bytes) +
++ dentries(11 * 214 bytes) + file name (8 * 214 bytes)
++
++ [Bucket]
++ +--------------------------------+
++ |dentry block 1 | dentry block 2 |
++ +--------------------------------+
++ . .
++ . .
++ . [Dentry Block Structure: 4KB] .
++ +--------+----------+----------+------------+
++ | bitmap | reserved | dentries | file names |
++ +--------+----------+----------+------------+
++ [Dentry Block: 4KB] . .
++ . .
++ . .
++ +------+------+-----+------+
++ | hash | ino | len | type |
++ +------+------+-----+------+
++ [Dentry Structure: 11 bytes]
++
++F2FS implements multi-level hash tables for directory structure. Each level has
++a hash table with dedicated number of hash buckets as shown below. Note that
++"A(2B)" means a bucket includes 2 data blocks.
++
++----------------------
++A : bucket
++B : block
++N : MAX_DIR_HASH_DEPTH
++----------------------
++
++level #0 | A(2B)
++ |
++level #1 | A(2B) - A(2B)
++ |
++level #2 | A(2B) - A(2B) - A(2B) - A(2B)
++ . | . . . .
++level #N/2 | A(2B) - A(2B) - A(2B) - A(2B) - A(2B) - ... - A(2B)
++ . | . . . .
++level #N | A(4B) - A(4B) - A(4B) - A(4B) - A(4B) - ... - A(4B)
++
++The number of blocks and buckets are determined by,
++
++ ,- 2, if n < MAX_DIR_HASH_DEPTH / 2,
++ # of blocks in level #n = |
++ `- 4, Otherwise
++
++ ,- 2^n, if n < MAX_DIR_HASH_DEPTH / 2,
++ # of buckets in level #n = |
++ `- 2^((MAX_DIR_HASH_DEPTH / 2) - 1), Otherwise
++
++When F2FS finds a file name in a directory, at first a hash value of the file
++name is calculated. Then, F2FS scans the hash table in level #0 to find the
++dentry consisting of the file name and its inode number. If not found, F2FS
++scans the next hash table in level #1. In this way, F2FS scans hash tables in
++each levels incrementally from 1 to N. In each levels F2FS needs to scan only
++one bucket determined by the following equation, which shows O(log(# of files))
++complexity.
++
++ bucket number to scan in level #n = (hash value) % (# of buckets in level #n)
++
++In the case of file creation, F2FS finds empty consecutive slots that cover the
++file name. F2FS searches the empty slots in the hash tables of whole levels from
++1 to N in the same way as the lookup operation.
++
++The following figure shows an example of two cases holding children.
++ --------------> Dir <--------------
++ | |
++ child child
++
++ child - child [hole] - child
++
++ child - child - child [hole] - [hole] - child
++
++ Case 1: Case 2:
++ Number of children = 6, Number of children = 3,
++ File size = 7 File size = 7
++
++Default Block Allocation
++------------------------
++
++At runtime, F2FS manages six active logs inside "Main" area: Hot/Warm/Cold node
++and Hot/Warm/Cold data.
++
++- Hot node contains direct node blocks of directories.
++- Warm node contains direct node blocks except hot node blocks.
++- Cold node contains indirect node blocks
++- Hot data contains dentry blocks
++- Warm data contains data blocks except hot and cold data blocks
++- Cold data contains multimedia data or migrated data blocks
++
++LFS has two schemes for free space management: threaded log and copy-and-compac-
++tion. The copy-and-compaction scheme which is known as cleaning, is well-suited
++for devices showing very good sequential write performance, since free segments
++are served all the time for writing new data. However, it suffers from cleaning
++overhead under high utilization. Contrarily, the threaded log scheme suffers
++from random writes, but no cleaning process is needed. F2FS adopts a hybrid
++scheme where the copy-and-compaction scheme is adopted by default, but the
++policy is dynamically changed to the threaded log scheme according to the file
++system status.
++
++In order to align F2FS with underlying flash-based storage, F2FS allocates a
++segment in a unit of section. F2FS expects that the section size would be the
++same as the unit size of garbage collection in FTL. Furthermore, with respect
++to the mapping granularity in FTL, F2FS allocates each section of the active
++logs from different zones as much as possible, since FTL can write the data in
++the active logs into one allocation unit according to its mapping granularity.
++
++Cleaning process
++----------------
++
++F2FS does cleaning both on demand and in the background. On-demand cleaning is
++triggered when there are not enough free segments to serve VFS calls. Background
++cleaner is operated by a kernel thread, and triggers the cleaning job when the
++system is idle.
++
++F2FS supports two victim selection policies: greedy and cost-benefit algorithms.
++In the greedy algorithm, F2FS selects a victim segment having the smallest number
++of valid blocks. In the cost-benefit algorithm, F2FS selects a victim segment
++according to the segment age and the number of valid blocks in order to address
++log block thrashing problem in the greedy algorithm. F2FS adopts the greedy
++algorithm for on-demand cleaner, while background cleaner adopts cost-benefit
++algorithm.
++
++In order to identify whether the data in the victim segment are valid or not,
++F2FS manages a bitmap. Each bit represents the validity of a block, and the
++bitmap is composed of a bit stream covering whole blocks in main area.
diff --git a/patches/linux-3.7/0101-f2fs-add-on-disk-layout.patch b/patches/linux-3.7/0101-f2fs-add-on-disk-layout.patch
new file mode 100644
index 0000000..fc1aac2
--- /dev/null
+++ b/patches/linux-3.7/0101-f2fs-add-on-disk-layout.patch
@@ -0,0 +1,382 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:26:00 +0000
+Subject: [PATCH] f2fs: add on-disk layout
+
+This adds a header file describing the on-disk layout of f2fs.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ include/linux/f2fs_fs.h | 362 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 362 insertions(+)
+ create mode 100644 include/linux/f2fs_fs.h
+
+diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
+new file mode 100644
+index 0000000..bd9c217
+--- /dev/null
++++ b/include/linux/f2fs_fs.h
+@@ -0,0 +1,362 @@
++/**
++ * include/linux/f2fs_fs.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _LINUX_F2FS_FS_H
++#define _LINUX_F2FS_FS_H
++
++#include <linux/pagemap.h>
++#include <linux/types.h>
++
++#define F2FS_SUPER_MAGIC 0xF2F52010
++#define F2FS_SUPER_OFFSET 0 /* start sector # for sb */
++#define F2FS_BLKSIZE 4096
++#define F2FS_MAX_EXTENSION 64
++
++#define NULL_ADDR 0x0U
++#define NEW_ADDR -1U
++
++#define F2FS_ROOT_INO(sbi) (sbi->root_ino_num)
++#define F2FS_NODE_INO(sbi) (sbi->node_ino_num)
++#define F2FS_META_INO(sbi) (sbi->meta_ino_num)
++
++#define GFP_F2FS_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_ZERO)
++
++#define MAX_ACTIVE_LOGS 16
++#define MAX_ACTIVE_NODE_LOGS 8
++#define MAX_ACTIVE_DATA_LOGS 8
++
++/*
++ * For superblock
++ */
++struct f2fs_super_block {
++ __le32 magic; /* Magic Number */
++ __le16 major_ver; /* Major Version */
++ __le16 minor_ver; /* Minor Version */
++ __le32 log_sectorsize; /* log2 (Sector size in bytes) */
++ __le32 log_sectors_per_block; /* log2 (Number of sectors per block */
++ __le32 log_blocksize; /* log2 (Block size in bytes) */
++ __le32 log_blocks_per_seg; /* log2 (Number of blocks per segment) */
++ __le32 segs_per_sec; /* Number of segments per section */
++ __le32 secs_per_zone; /* Number of sections per zone */
++ __le32 checksum_offset; /* Checksum position in this super block */
++ __le64 block_count; /* Total number of blocks */
++ __le32 section_count; /* Total number of sections */
++ __le32 segment_count; /* Total number of segments */
++ __le32 segment_count_ckpt; /* Total number of segments
++ in Checkpoint area */
++ __le32 segment_count_sit; /* Total number of segments
++ in Segment information table */
++ __le32 segment_count_nat; /* Total number of segments
++ in Node address table */
++ /*Total number of segments in Segment summary area */
++ __le32 segment_count_ssa;
++ /* Total number of segments in Main area */
++ __le32 segment_count_main;
++ __le32 failure_safe_block_distance;
++ __le32 segment0_blkaddr; /* Start block address of Segment 0 */
++ __le32 start_segment_checkpoint; /* Start block address of ckpt */
++ __le32 sit_blkaddr; /* Start block address of SIT */
++ __le32 nat_blkaddr; /* Start block address of NAT */
++ __le32 ssa_blkaddr; /* Start block address of SSA */
++ __le32 main_blkaddr; /* Start block address of Main area */
++ __le32 root_ino; /* Root directory inode number */
++ __le32 node_ino; /* node inode number */
++ __le32 meta_ino; /* meta inode number */
++ __le32 volume_serial_number; /* VSN is optional field */
++ __le16 volume_name[512]; /* Volume Name */
++ __le32 extension_count;
++ __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */
++} __packed;
++
++/*
++ * For checkpoint
++ */
++struct f2fs_checkpoint {
++ __le64 checkpoint_ver; /* Checkpoint block version number */
++ __le64 user_block_count; /* # of user blocks */
++ __le64 valid_block_count; /* # of valid blocks in Main area */
++ __le32 rsvd_segment_count; /* # of reserved segments for gc */
++ __le32 overprov_segment_count; /* # of overprovision segments */
++ __le32 free_segment_count; /* # of free segments in Main area */
++
++ /* information of current node segments */
++ __le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
++ __le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
++ __le16 nat_upd_blkoff[MAX_ACTIVE_NODE_LOGS];
++ /* information of current data segments */
++ __le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
++ __le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
++ __le32 ckpt_flags; /* Flags : umount and journal_present */
++ __le32 cp_pack_total_block_count;
++ __le32 cp_pack_start_sum; /* start block number of data summary */
++ __le32 valid_node_count; /* Total number of valid nodes */
++ __le32 valid_inode_count; /* Total number of valid inodes */
++ __le32 next_free_nid; /* Next free node number */
++ __le32 sit_ver_bitmap_bytesize; /* Default value 64 */
++ __le32 nat_ver_bitmap_bytesize; /* Default value 256 */
++ __le32 checksum_offset; /* Checksum position
++ in this checkpoint block */
++ __le64 elapsed_time; /* elapsed time while partition
++ is mounted */
++ /* allocation type of current segment */
++ unsigned char alloc_type[MAX_ACTIVE_LOGS];
++
++ /* SIT and NAT version bitmap */
++ unsigned char sit_nat_version_bitmap[1];
++} __packed;
++
++/*
++ * For orphan inode management
++ */
++#define F2FS_ORPHANS_PER_BLOCK 1020
++
++struct f2fs_orphan_block {
++ __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */
++ __le32 reserved;
++ __le16 blk_addr; /* block index in current CP */
++ __le16 blk_count; /* Number of orphan inode blocks in CP */
++ __le32 entry_count; /* Total number of orphan nodes in current CP */
++ __le32 check_sum; /* CRC32 for orphan inode block */
++} __packed;
++
++/*
++ * For NODE structure
++ */
++struct f2fs_extent {
++ __le32 fofs;
++ __le32 blk_addr;
++ __le32 len;
++} __packed;
++
++#define F2FS_MAX_NAME_LEN 256
++#define ADDRS_PER_INODE 927 /* Address Pointers in an Inode */
++#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */
++#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */
++
++struct f2fs_inode {
++ __le16 i_mode; /* File mode */
++ __u8 i_advise; /* File hints */
++ __u8 i_reserved; /* Reserved */
++ __le32 i_uid; /* User ID */
++ __le32 i_gid; /* Group ID */
++ __le32 i_links; /* Links count */
++ __le64 i_size; /* File size in bytes */
++ __le64 i_blocks; /* File size in blocks */
++ __le64 i_ctime; /* Inode change time */
++ __le64 i_mtime; /* Modification time */
++ __le32 i_ctime_nsec;
++ __le32 i_mtime_nsec;
++ __le32 current_depth;
++ __le32 i_xattr_nid; /* nid to save xattr */
++ __le32 i_flags; /* file attributes */
++ __le32 i_pino; /* parent inode number */
++ __le32 i_namelen; /* file name length */
++ __u8 i_name[F2FS_MAX_NAME_LEN]; /* file name for SPOR */
++
++ struct f2fs_extent i_ext; /* caching a largest extent */
++
++ __le32 i_addr[ADDRS_PER_INODE]; /* Pointers to data blocks */
++
++ __le32 i_nid[5]; /* direct(2), indirect(2),
++ double_indirect(1) node id */
++} __packed;
++
++struct direct_node {
++ __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */
++} __packed;
++
++struct indirect_node {
++ __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */
++} __packed;
++
++enum {
++ COLD_BIT_SHIFT = 0,
++ FSYNC_BIT_SHIFT,
++ DENT_BIT_SHIFT,
++ OFFSET_BIT_SHIFT
++};
++
++struct node_footer {
++ __le32 nid; /* node id */
++ __le32 ino; /* inode nunmber */
++ __le32 flag; /* include cold/fsync/dentry marks and offset */
++ __le64 cp_ver; /* checkpoint version */
++ __le32 next_blkaddr; /* next node page block address */
++} __packed;
++
++struct f2fs_node {
++ union {
++ struct f2fs_inode i;
++ struct direct_node dn;
++ struct indirect_node in;
++ };
++ struct node_footer footer;
++} __packed;
++
++/*
++ * For NAT entries
++ */
++#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry))
++
++struct f2fs_nat_entry {
++ __u8 version;
++ __le32 ino;
++ __le32 block_addr;
++} __packed;
++
++struct f2fs_nat_block {
++ struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK];
++} __packed;
++
++/*
++ * For SIT entries
++ */
++#define SIT_VBLOCK_MAP_SIZE 64
++#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry))
++
++struct f2fs_sit_entry {
++ __le16 vblocks;
++ __u8 valid_map[SIT_VBLOCK_MAP_SIZE];
++ __le64 mtime;
++} __packed;
++
++struct f2fs_sit_block {
++ struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK];
++} __packed;
++
++/**
++ * For segment summary
++ *
++ * NOTE : For initializing fields, you must use set_summary
++ *
++ * - If data page, nid represents dnode's nid
++ * - If node page, nid represents the node page's nid.
++ *
++ * The ofs_in_node is used by only data page. It represents offset
++ * from node's page's beginning to get a data block address.
++ * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node)
++ */
++struct f2fs_summary {
++ __le32 nid;
++ union {
++ __u8 reserved[3];
++ struct {
++ __u8 version;
++ __le16 ofs_in_node;
++ } __packed;
++ };
++} __packed;
++
++struct summary_footer {
++ unsigned char entry_type;
++ __u32 check_sum;
++} __packed;
++
++#define SUMMARY_SIZE (sizeof(struct f2fs_summary))
++#define SUM_FOOTER_SIZE (sizeof(struct summary_footer))
++#define ENTRIES_IN_SUM 512
++#define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM)
++#define SUM_JOURNAL_SIZE (PAGE_CACHE_SIZE - SUM_FOOTER_SIZE -\
++ SUM_ENTRY_SIZE)
++struct nat_journal_entry {
++ __le32 nid;
++ struct f2fs_nat_entry ne;
++} __packed;
++
++struct sit_journal_entry {
++ __le32 segno;
++ struct f2fs_sit_entry se;
++} __packed;
++
++#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
++ sizeof(struct nat_journal_entry))
++#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
++ sizeof(struct nat_journal_entry))
++#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\
++ sizeof(struct sit_journal_entry))
++#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\
++ sizeof(struct sit_journal_entry))
++enum {
++ NAT_JOURNAL = 0,
++ SIT_JOURNAL
++};
++
++struct nat_journal {
++ struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
++ __u8 reserved[NAT_JOURNAL_RESERVED];
++} __packed;
++
++struct sit_journal {
++ struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
++ __u8 reserved[SIT_JOURNAL_RESERVED];
++} __packed;
++
++struct f2fs_summary_block {
++ struct f2fs_summary entries[ENTRIES_IN_SUM];
++ union {
++ __le16 n_nats;
++ __le16 n_sits;
++ };
++ union {
++ struct nat_journal nat_j;
++ struct sit_journal sit_j;
++ };
++ struct summary_footer footer;
++} __packed;
++
++/*
++ * For directory operations
++ */
++#define F2FS_DOT_HASH 0
++#define F2FS_DDOT_HASH F2FS_DOT_HASH
++#define F2FS_MAX_HASH (~((0x3ULL) << 62))
++#define F2FS_HASH_COL_BIT ((0x1ULL) << 63)
++
++typedef __le32 f2fs_hash_t;
++
++#define F2FS_NAME_LEN 8
++#define NR_DENTRY_IN_BLOCK 214 /* the number of dentry in a block */
++#define MAX_DIR_HASH_DEPTH 63 /* MAX level for dir lookup */
++
++#define SIZE_OF_DIR_ENTRY 11 /* by byte */
++#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \
++ BITS_PER_BYTE)
++#define SIZE_OF_RESERVED (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \
++ F2FS_NAME_LEN) * \
++ NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP))
++
++struct f2fs_dir_entry {
++ __le32 hash_code; /* hash code of file name */
++ __le32 ino; /* node number of inode */
++ __le16 name_len; /* the size of file name
++ length in unicode characters */
++ __u8 file_type;
++} __packed;
++
++struct f2fs_dentry_block {
++ __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP];
++ __u8 reserved[SIZE_OF_RESERVED];
++ struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK];
++ __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_NAME_LEN];
++} __packed;
++
++enum {
++ F2FS_FT_UNKNOWN,
++ F2FS_FT_REG_FILE,
++ F2FS_FT_DIR,
++ F2FS_FT_CHRDEV,
++ F2FS_FT_BLKDEV,
++ F2FS_FT_FIFO,
++ F2FS_FT_SOCK,
++ F2FS_FT_SYMLINK,
++ F2FS_FT_MAX
++};
++
++#endif /* _LINUX_F2FS_FS_H */
diff --git a/patches/linux-3.7/0102-f2fs-add-superblock-and-major-in-memory-structure.patch b/patches/linux-3.7/0102-f2fs-add-superblock-and-major-in-memory-structure.patch
new file mode 100644
index 0000000..25cfa81
--- /dev/null
+++ b/patches/linux-3.7/0102-f2fs-add-superblock-and-major-in-memory-structure.patch
@@ -0,0 +1,1961 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:26:49 +0000
+Subject: [PATCH] f2fs: add superblock and major in-memory structure
+
+This adds the following major in-memory structures in f2fs.
+
+- f2fs_sb_info:
+ contains f2fs-specific information, two special inode pointers for node and
+ meta address spaces, and orphan inode management.
+
+- f2fs_inode_info:
+ contains vfs_inode and other fs-specific information.
+
+- f2fs_nm_info:
+ contains node manager information such as NAT entry cache, free nid list,
+ and NAT page management.
+
+- f2fs_node_info:
+ represents a node as node id, inode number, block address, and its version.
+
+- f2fs_sm_info:
+ contains segment manager information such as SIT entry cache, free segment
+ map, current active logs, dirty segment management, and segment utilization.
+ The specific structures are sit_info, free_segmap_info, dirty_seglist_info,
+ curseg_info.
+
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/f2fs.h | 982 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/node.h | 330 ++++++++++++++++++
+ fs/f2fs/segment.h | 594 ++++++++++++++++++++++++++++++++
+ 3 files changed, 1906 insertions(+)
+ create mode 100644 fs/f2fs/f2fs.h
+ create mode 100644 fs/f2fs/node.h
+ create mode 100644 fs/f2fs/segment.h
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+new file mode 100644
+index 0000000..bbe2f02
+--- /dev/null
++++ b/fs/f2fs/f2fs.h
+@@ -0,0 +1,982 @@
++/**
++ * fs/f2fs/f2fs.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _LINUX_F2FS_H
++#define _LINUX_F2FS_H
++
++#include <linux/types.h>
++#include <linux/page-flags.h>
++#include <linux/buffer_head.h>
++#include <linux/version.h>
++#include <linux/slab.h>
++#include <linux/crc32.h>
++
++/**
++ * For mount options
++ */
++#define F2FS_MOUNT_BG_GC 0x00000001
++#define F2FS_MOUNT_DISABLE_ROLL_FORWARD 0x00000002
++#define F2FS_MOUNT_DISCARD 0x00000004
++#define F2FS_MOUNT_NOHEAP 0x00000008
++#define F2FS_MOUNT_XATTR_USER 0x00000010
++#define F2FS_MOUNT_POSIX_ACL 0x00000020
++#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000040
++
++#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
++#define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
++#define test_opt(sbi, option) (sbi->mount_opt.opt & F2FS_MOUNT_##option)
++
++#define ver_after(a, b) (typecheck(unsigned long long, a) && \
++ typecheck(unsigned long long, b) && \
++ ((long long)((a) - (b)) > 0))
++
++typedef u64 block_t;
++typedef u32 nid_t;
++
++struct f2fs_mount_info {
++ unsigned int opt;
++};
++
++static inline __u32 f2fs_crc32(void *buff, size_t len)
++{
++ return crc32_le(F2FS_SUPER_MAGIC, buff, len);
++}
++
++static inline bool f2fs_crc_valid(__u32 blk_crc, void *buff, size_t buff_size)
++{
++ return f2fs_crc32(buff, buff_size) == blk_crc;
++}
++
++/**
++ * For checkpoint manager
++ */
++#define CP_ERROR_FLAG 0x00000008
++#define CP_COMPACT_SUM_FLAG 0x00000004
++#define CP_ORPHAN_PRESENT_FLAG 0x00000002
++#define CP_UMOUNT_FLAG 0x00000001
++
++enum {
++ NAT_BITMAP,
++ SIT_BITMAP
++};
++
++struct orphan_inode_entry {
++ struct list_head list;
++ nid_t ino;
++};
++
++struct dir_inode_entry {
++ struct list_head list;
++ struct inode *inode;
++};
++
++struct fsync_inode_entry {
++ struct list_head list;
++ struct inode *inode;
++ block_t blkaddr;
++};
++
++#define nats_in_cursum(sum) (le16_to_cpu(sum->n_nats))
++#define sits_in_cursum(sum) (le16_to_cpu(sum->n_sits))
++
++#define nat_in_journal(sum, i) (sum->nat_j.entries[i].ne)
++#define nid_in_journal(sum, i) (sum->nat_j.entries[i].nid)
++#define sit_in_journal(sum, i) (sum->sit_j.entries[i].se)
++#define segno_in_journal(sum, i) (sum->sit_j.entries[i].segno)
++
++static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i)
++{
++ int before = nats_in_cursum(rs);
++ rs->n_nats = cpu_to_le16(before + i);
++ return before;
++}
++
++static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
++{
++ int before = sits_in_cursum(rs);
++ rs->n_sits = cpu_to_le16(before + i);
++ return before;
++}
++
++/**
++ * For INODE and NODE manager
++ */
++#define XATTR_NODE_OFFSET (-1)
++#define RDONLY_NODE 1
++#define F2FS_LINK_MAX 32000
++
++struct extent_info {
++ rwlock_t ext_lock;
++ unsigned int fofs;
++ u32 blk_addr;
++ unsigned int len;
++};
++
++#define FADVISE_COLD_BIT 0x01
++/*
++ * i_advise uses FADVISE_XXX_BIT. We can add additional hints later.
++ */
++struct f2fs_inode_info {
++ struct inode vfs_inode;
++ unsigned long i_flags;
++ unsigned long flags;
++ unsigned long long data_version;
++ atomic_t dirty_dents;
++ unsigned int current_depth;
++ f2fs_hash_t chash;
++ unsigned int clevel;
++ nid_t i_xattr_nid;
++ struct extent_info ext;
++ umode_t i_acl_mode;
++ unsigned char i_advise; /* If true, this is cold data */
++};
++
++static inline void get_extent_info(struct extent_info *ext,
++ struct f2fs_extent i_ext)
++{
++ write_lock(&ext->ext_lock);
++ ext->fofs = le32_to_cpu(i_ext.fofs);
++ ext->blk_addr = le32_to_cpu(i_ext.blk_addr);
++ ext->len = le32_to_cpu(i_ext.len);
++ write_unlock(&ext->ext_lock);
++}
++
++static inline void set_raw_extent(struct extent_info *ext,
++ struct f2fs_extent *i_ext)
++{
++ read_lock(&ext->ext_lock);
++ i_ext->fofs = cpu_to_le32(ext->fofs);
++ i_ext->blk_addr = cpu_to_le32(ext->blk_addr);
++ i_ext->len = cpu_to_le32(ext->len);
++ read_unlock(&ext->ext_lock);
++}
++
++struct f2fs_nm_info {
++ block_t nat_blkaddr; /* base disk address of NAT */
++ unsigned int nat_segs; /* the number of nat segments */
++ unsigned int nat_blocks; /* the number of nat blocks of
++ one size */
++ nid_t max_nid;
++ unsigned int nat_cnt; /* the number of nodes in NAT Buffer */
++ struct radix_tree_root nat_root;
++ rwlock_t nat_tree_lock; /* Protect nat_tree_lock */
++ struct list_head nat_entries; /* cached nat entry list (clean) */
++ struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */
++
++ unsigned int fcnt; /* the number of free node id */
++ struct mutex build_lock; /* lock for build free nids */
++
++ int nat_upd_blkoff[3]; /* Block offset
++ in the current journal segment
++ where the last NAT update happened */
++ int lst_upd_blkoff[3]; /* Block offset
++ in current journal segment */
++
++ unsigned int written_valid_node_count;
++ unsigned int written_valid_inode_count;
++ char *nat_bitmap; /* NAT bitmap pointer */
++ int bitmap_size; /* bitmap size */
++
++ nid_t init_scan_nid; /* the first nid to be scanned */
++ nid_t next_scan_nid; /* the next nid to be scanned */
++ struct list_head free_nid_list;
++ spinlock_t free_nid_list_lock; /* Protect free nid list */
++};
++
++struct dnode_of_data {
++ struct inode *inode;
++ struct page *inode_page;
++ struct page *node_page;
++ nid_t nid;
++ unsigned int ofs_in_node;
++ bool inode_page_locked;
++ block_t data_blkaddr;
++};
++
++static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
++ struct page *ipage, struct page *npage, nid_t nid)
++{
++ dn->inode = inode;
++ dn->inode_page = ipage;
++ dn->node_page = npage;
++ dn->nid = nid;
++ dn->inode_page_locked = 0;
++}
++
++/**
++ * For SIT manager
++ */
++#define NR_CURSEG_DATA_TYPE (3)
++#define NR_CURSEG_NODE_TYPE (3)
++#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
++
++enum {
++ CURSEG_HOT_DATA = 0,
++ CURSEG_WARM_DATA,
++ CURSEG_COLD_DATA,
++ CURSEG_HOT_NODE,
++ CURSEG_WARM_NODE,
++ CURSEG_COLD_NODE,
++ NO_CHECK_TYPE
++};
++
++struct f2fs_sm_info {
++ /* SIT information */
++ struct sit_info *sit_info;
++
++ /* Free segmap infomation */
++ struct free_segmap_info *free_info;
++
++ /* Dirty segments list information for GC victim */
++ struct dirty_seglist_info *dirty_info;
++
++ /* Current working segments(i.e. logging point) information array */
++ struct curseg_info *curseg_array;
++
++ /* list head of all under-writeback pages for flush handling */
++ struct list_head wblist_head;
++ spinlock_t wblist_lock;
++
++ block_t seg0_blkaddr;
++ block_t main_blkaddr;
++ unsigned int segment_count;
++ unsigned int rsvd_segment_count;
++ unsigned int main_segment_count;
++ block_t ssa_blkaddr;
++ unsigned int segment_count_ssa;
++};
++
++/**
++ * For Garbage Collection
++ */
++struct f2fs_gc_info {
++#ifdef CONFIG_F2FS_STAT_FS
++ struct list_head stat_list;
++ struct f2fs_stat_info *stat_info;
++#endif
++ int cause;
++ int rsvd_segment_count;
++ int overp_segment_count;
++};
++
++/**
++ * For directory operation
++ */
++#define F2FS_INODE_SIZE (17 * 4 + F2FS_MAX_NAME_LEN)
++#define NODE_DIR1_BLOCK (ADDRS_PER_INODE + 1)
++#define NODE_DIR2_BLOCK (ADDRS_PER_INODE + 2)
++#define NODE_IND1_BLOCK (ADDRS_PER_INODE + 3)
++#define NODE_IND2_BLOCK (ADDRS_PER_INODE + 4)
++#define NODE_DIND_BLOCK (ADDRS_PER_INODE + 5)
++
++/**
++ * For superblock
++ */
++enum count_type {
++ F2FS_WRITEBACK,
++ F2FS_DIRTY_DENTS,
++ F2FS_DIRTY_NODES,
++ F2FS_DIRTY_META,
++ NR_COUNT_TYPE,
++};
++
++/*
++ * FS_LOCK nesting subclasses for the lock validator:
++ *
++ * The locking order between these classes is
++ * RENAME -> DENTRY_OPS -> DATA_WRITE -> DATA_NEW
++ * -> DATA_TRUNC -> NODE_WRITE -> NODE_NEW -> NODE_TRUNC
++ */
++enum lock_type {
++ RENAME, /* for renaming operations */
++ DENTRY_OPS, /* for directory operations */
++ DATA_WRITE, /* for data write */
++ DATA_NEW, /* for data allocation */
++ DATA_TRUNC, /* for data truncate */
++ NODE_NEW, /* for node allocation */
++ NODE_TRUNC, /* for node truncate */
++ NODE_WRITE, /* for node write */
++ NR_LOCK_TYPE,
++};
++
++/*
++ * The below are the page types of bios used in submti_bio().
++ * The available types are:
++ * DATA User data pages. It operates as async mode.
++ * NODE Node pages. It operates as async mode.
++ * META FS metadata pages such as SIT, NAT, CP.
++ * NR_PAGE_TYPE The number of page types.
++ * META_FLUSH Make sure the previous pages are written
++ * with waiting the bio's completion
++ * ... Only can be used with META.
++ */
++enum page_type {
++ DATA,
++ NODE,
++ META,
++ NR_PAGE_TYPE,
++ META_FLUSH,
++};
++
++struct f2fs_sb_info {
++ struct super_block *sb; /* Pointer to VFS super block */
++ int s_dirty;
++ struct f2fs_super_block *raw_super; /* Pointer to the super block
++ in the buffer */
++ struct buffer_head *raw_super_buf; /* Buffer containing
++ the f2fs raw super block */
++ struct f2fs_checkpoint *ckpt; /* Pointer to the checkpoint
++ in the buffer */
++ struct mutex orphan_inode_mutex;
++ spinlock_t dir_inode_lock;
++ struct mutex cp_mutex;
++ /* orphan Inode list to be written in Journal block during CP */
++ struct list_head orphan_inode_list;
++ struct list_head dir_inode_list;
++ unsigned int n_orphans, n_dirty_dirs;
++
++ unsigned int log_sectorsize;
++ unsigned int log_sectors_per_block;
++ unsigned int log_blocksize;
++ unsigned int blocksize;
++ unsigned int root_ino_num; /* Root Inode Number*/
++ unsigned int node_ino_num; /* Root Inode Number*/
++ unsigned int meta_ino_num; /* Root Inode Number*/
++ unsigned int log_blocks_per_seg;
++ unsigned int blocks_per_seg;
++ unsigned int segs_per_sec;
++ unsigned int secs_per_zone;
++ unsigned int total_sections;
++ unsigned int total_node_count;
++ unsigned int total_valid_node_count;
++ unsigned int total_valid_inode_count;
++ unsigned int segment_count[2];
++ unsigned int block_count[2];
++ unsigned int last_victim[2];
++ int active_logs;
++ block_t user_block_count;
++ block_t total_valid_block_count;
++ block_t alloc_valid_block_count;
++ block_t last_valid_block_count;
++ atomic_t nr_pages[NR_COUNT_TYPE];
++
++ struct f2fs_mount_info mount_opt;
++
++ /* related to NM */
++ struct f2fs_nm_info *nm_info; /* Node Manager information */
++
++ /* related to SM */
++ struct f2fs_sm_info *sm_info; /* Segment Manager
++ information */
++ int total_hit_ext, read_hit_ext;
++ int rr_flush;
++
++ /* related to GC */
++ struct proc_dir_entry *s_proc;
++ struct f2fs_gc_info *gc_info; /* Garbage Collector
++ information */
++ struct mutex gc_mutex; /* mutex for GC */
++ struct mutex fs_lock[NR_LOCK_TYPE]; /* mutex for GP */
++ struct mutex write_inode; /* mutex for write inode */
++ struct mutex writepages; /* mutex for writepages() */
++ struct f2fs_gc_kthread *gc_thread; /* GC thread */
++ int bg_gc;
++ int last_gc_status;
++ int por_doing;
++
++ struct inode *node_inode;
++ struct inode *meta_inode;
++
++ struct bio *bio[NR_PAGE_TYPE];
++ sector_t last_block_in_bio[NR_PAGE_TYPE];
++ struct rw_semaphore bio_sem;
++ spinlock_t stat_lock; /* lock for handling the number
++ of valid blocks and
++ valid nodes */
++};
++
++/**
++ * Inline functions
++ */
++static inline struct f2fs_inode_info *F2FS_I(struct inode *inode)
++{
++ return container_of(inode, struct f2fs_inode_info, vfs_inode);
++}
++
++static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb)
++{
++ return sb->s_fs_info;
++}
++
++static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_super_block *)(sbi->raw_super);
++}
++
++static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_checkpoint *)(sbi->ckpt);
++}
++
++static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_nm_info *)(sbi->nm_info);
++}
++
++static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi)
++{
++ return (struct f2fs_sm_info *)(sbi->sm_info);
++}
++
++static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi)
++{
++ return (struct sit_info *)(SM_I(sbi)->sit_info);
++}
++
++static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi)
++{
++ return (struct free_segmap_info *)(SM_I(sbi)->free_info);
++}
++
++static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi)
++{
++ return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
++}
++
++static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
++{
++ sbi->s_dirty = 1;
++}
++
++static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi)
++{
++ sbi->s_dirty = 0;
++}
++
++static inline void mutex_lock_op(struct f2fs_sb_info *sbi, enum lock_type t)
++{
++ mutex_lock_nested(&sbi->fs_lock[t], t);
++}
++
++static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, enum lock_type t)
++{
++ mutex_unlock(&sbi->fs_lock[t]);
++}
++
++/**
++ * Check whether the given nid is within node id range.
++ */
++static inline void check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ BUG_ON((nid >= NM_I(sbi)->max_nid));
++}
++
++#define F2FS_DEFAULT_ALLOCATED_BLOCKS 1
++
++/**
++ * Check whether the inode has blocks or not
++ */
++static inline int F2FS_HAS_BLOCKS(struct inode *inode)
++{
++ if (F2FS_I(inode)->i_xattr_nid)
++ return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
++ else
++ return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
++}
++
++static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
++ struct inode *inode, blkcnt_t count)
++{
++ block_t valid_block_count;
++
++ spin_lock(&sbi->stat_lock);
++ valid_block_count =
++ sbi->total_valid_block_count + (block_t)count;
++ if (valid_block_count > sbi->user_block_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++ inode->i_blocks += count;
++ sbi->total_valid_block_count = valid_block_count;
++ sbi->alloc_valid_block_count += (block_t)count;
++ spin_unlock(&sbi->stat_lock);
++ return true;
++}
++
++static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ blkcnt_t count)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(sbi->total_valid_block_count < (block_t) count);
++ BUG_ON(inode->i_blocks < count);
++ inode->i_blocks -= count;
++ sbi->total_valid_block_count -= (block_t)count;
++ spin_unlock(&sbi->stat_lock);
++ return 0;
++}
++
++static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
++{
++ atomic_inc(&sbi->nr_pages[count_type]);
++ F2FS_SET_SB_DIRT(sbi);
++}
++
++static inline void inode_inc_dirty_dents(struct inode *inode)
++{
++ atomic_inc(&F2FS_I(inode)->dirty_dents);
++}
++
++static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type)
++{
++ atomic_dec(&sbi->nr_pages[count_type]);
++}
++
++static inline void inode_dec_dirty_dents(struct inode *inode)
++{
++ atomic_dec(&F2FS_I(inode)->dirty_dents);
++}
++
++static inline int get_pages(struct f2fs_sb_info *sbi, int count_type)
++{
++ return atomic_read(&sbi->nr_pages[count_type]);
++}
++
++static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_block_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++
++ /* return NAT or SIT bitmap */
++ if (flag == NAT_BITMAP)
++ return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
++ else if (flag == SIT_BITMAP)
++ return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
++
++ return 0;
++}
++
++static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ int offset = (flag == NAT_BITMAP) ? ckpt->sit_ver_bitmap_bytesize : 0;
++ return &ckpt->sit_nat_version_bitmap + offset;
++}
++
++static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
++{
++ block_t start_addr;
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ unsigned long long ckpt_version = le64_to_cpu(ckpt->checkpoint_ver);
++
++ start_addr = le64_to_cpu(F2FS_RAW_SUPER(sbi)->start_segment_checkpoint);
++
++ /*
++ * odd numbered checkpoint shoukd at cp segment 0
++ * and even segent must be at cp segment 1
++ */
++ if (!(ckpt_version & 1))
++ start_addr += sbi->blocks_per_seg;
++
++ return start_addr;
++}
++
++static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi)
++{
++ return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
++}
++
++static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ unsigned int count)
++{
++ block_t valid_block_count;
++ unsigned int valid_node_count;
++
++ spin_lock(&sbi->stat_lock);
++
++ valid_block_count = sbi->total_valid_block_count + (block_t)count;
++ sbi->alloc_valid_block_count += (block_t)count;
++ valid_node_count = sbi->total_valid_node_count + count;
++
++ if (valid_block_count > sbi->user_block_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++
++ if (valid_node_count > sbi->total_node_count) {
++ spin_unlock(&sbi->stat_lock);
++ return false;
++ }
++
++ if (inode)
++ inode->i_blocks += count;
++ sbi->total_valid_node_count = valid_node_count;
++ sbi->total_valid_block_count = valid_block_count;
++ spin_unlock(&sbi->stat_lock);
++
++ return true;
++}
++
++static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
++ struct inode *inode,
++ unsigned int count)
++{
++ spin_lock(&sbi->stat_lock);
++
++ BUG_ON(sbi->total_valid_block_count < count);
++ BUG_ON(sbi->total_valid_node_count < count);
++ BUG_ON(inode->i_blocks < count);
++
++ inode->i_blocks -= count;
++ sbi->total_valid_node_count -= count;
++ sbi->total_valid_block_count -= (block_t)count;
++
++ spin_unlock(&sbi->stat_lock);
++}
++
++static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi)
++{
++ unsigned int ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_node_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(sbi->total_valid_inode_count == sbi->total_node_count);
++ sbi->total_valid_inode_count++;
++ spin_unlock(&sbi->stat_lock);
++}
++
++static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ spin_lock(&sbi->stat_lock);
++ BUG_ON(!sbi->total_valid_inode_count);
++ sbi->total_valid_inode_count--;
++ spin_unlock(&sbi->stat_lock);
++ return 0;
++}
++
++static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
++{
++ unsigned int ret;
++ spin_lock(&sbi->stat_lock);
++ ret = sbi->total_valid_inode_count;
++ spin_unlock(&sbi->stat_lock);
++ return ret;
++}
++
++static inline void f2fs_put_page(struct page *page, int unlock)
++{
++ if (!page || IS_ERR(page))
++ return;
++
++ if (unlock) {
++ BUG_ON(!PageLocked(page));
++ unlock_page(page);
++ }
++ page_cache_release(page);
++}
++
++static inline void f2fs_put_dnode(struct dnode_of_data *dn)
++{
++ if (dn->node_page)
++ f2fs_put_page(dn->node_page, 1);
++ if (dn->inode_page && dn->node_page != dn->inode_page)
++ f2fs_put_page(dn->inode_page, 0);
++ dn->node_page = NULL;
++ dn->inode_page = NULL;
++}
++
++static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name,
++ size_t size, void (*ctor)(void *))
++{
++ return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor);
++}
++
++#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino)
++
++static inline bool IS_INODE(struct page *page)
++{
++ struct f2fs_node *p = (struct f2fs_node *)page_address(page);
++ return RAW_IS_INODE(p);
++}
++
++static inline __le32 *blkaddr_in_node(struct f2fs_node *node)
++{
++ return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr;
++}
++
++static inline block_t datablock_addr(struct page *node_page,
++ unsigned int offset)
++{
++ struct f2fs_node *raw_node;
++ __le32 *addr_array;
++ raw_node = (struct f2fs_node *)page_address(node_page);
++ addr_array = blkaddr_in_node(raw_node);
++ return le32_to_cpu(addr_array[offset]);
++}
++
++static inline int f2fs_test_bit(unsigned int nr, char *addr)
++{
++ int mask;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ return mask & *addr;
++}
++
++static inline int f2fs_set_bit(unsigned int nr, char *addr)
++{
++ int mask;
++ int ret;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ ret = mask & *addr;
++ *addr |= mask;
++ return ret;
++}
++
++static inline int f2fs_clear_bit(unsigned int nr, char *addr)
++{
++ int mask;
++ int ret;
++
++ addr += (nr >> 3);
++ mask = 1 << (7 - (nr & 0x07));
++ ret = mask & *addr;
++ *addr &= ~mask;
++ return ret;
++}
++
++enum {
++ FI_NEW_INODE,
++ FI_NEED_CP,
++ FI_INC_LINK,
++ FI_ACL_MODE,
++ FI_NO_ALLOC,
++};
++
++static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ set_bit(flag, &fi->flags);
++}
++
++static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag)
++{
++ return test_bit(flag, &fi->flags);
++}
++
++static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ clear_bit(flag, &fi->flags);
++}
++
++static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode)
++{
++ fi->i_acl_mode = mode;
++ set_inode_flag(fi, FI_ACL_MODE);
++}
++
++static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag)
++{
++ if (is_inode_flag_set(fi, FI_ACL_MODE)) {
++ clear_inode_flag(fi, FI_ACL_MODE);
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * file.c
++ */
++int f2fs_sync_file(struct file *, loff_t, loff_t, int);
++void truncate_data_blocks(struct dnode_of_data *);
++void f2fs_truncate(struct inode *);
++int f2fs_setattr(struct dentry *, struct iattr *);
++int truncate_hole(struct inode *, pgoff_t, pgoff_t);
++long f2fs_ioctl(struct file *, unsigned int, unsigned long);
++
++/**
++ * inode.c
++ */
++void f2fs_set_inode_flags(struct inode *);
++struct inode *f2fs_iget_nowait(struct super_block *, unsigned long);
++struct inode *f2fs_iget(struct super_block *, unsigned long);
++void update_inode(struct inode *, struct page *);
++int f2fs_write_inode(struct inode *, struct writeback_control *);
++void f2fs_evict_inode(struct inode *);
++
++/**
++ * dir.c
++ */
++struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
++ struct page **);
++struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
++void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
++ struct page *, struct inode *);
++void init_dent_inode(struct dentry *, struct page *);
++int f2fs_add_link(struct dentry *, struct inode *);
++void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *);
++int f2fs_make_empty(struct inode *, struct inode *);
++bool f2fs_empty_dir(struct inode *);
++
++/**
++ * super.c
++ */
++int f2fs_sync_fs(struct super_block *, int);
++
++/**
++ * hash.c
++ */
++f2fs_hash_t f2fs_dentry_hash(const char *, int);
++
++/**
++ * node.c
++ */
++struct dnode_of_data;
++struct node_info;
++
++int is_checkpointed_node(struct f2fs_sb_info *, nid_t);
++void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *);
++int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
++int truncate_inode_blocks(struct inode *, pgoff_t);
++int remove_inode_page(struct inode *);
++int new_inode_page(struct inode *, struct dentry *);
++struct page *new_node_page(struct dnode_of_data *, unsigned int);
++void ra_node_page(struct f2fs_sb_info *, nid_t);
++struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
++struct page *get_node_page_ra(struct page *, int);
++void sync_inode_page(struct dnode_of_data *);
++int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
++bool alloc_nid(struct f2fs_sb_info *, nid_t *);
++void alloc_nid_done(struct f2fs_sb_info *, nid_t);
++void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
++void recover_node_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, struct node_info *, block_t);
++int recover_inode_page(struct f2fs_sb_info *, struct page *);
++int restore_node_summary(struct f2fs_sb_info *, unsigned int,
++ struct f2fs_summary_block *);
++void flush_nat_entries(struct f2fs_sb_info *);
++int build_node_manager(struct f2fs_sb_info *);
++void destroy_node_manager(struct f2fs_sb_info *);
++int create_node_manager_caches(void);
++void destroy_node_manager_caches(void);
++
++/**
++ * segment.c
++ */
++void f2fs_balance_fs(struct f2fs_sb_info *);
++void invalidate_blocks(struct f2fs_sb_info *, block_t);
++void locate_dirty_segment(struct f2fs_sb_info *, unsigned int);
++void clear_prefree_segments(struct f2fs_sb_info *);
++int npages_for_summary_flush(struct f2fs_sb_info *);
++void allocate_new_segments(struct f2fs_sb_info *);
++struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
++struct bio *f2fs_bio_alloc(struct block_device *, sector_t, int, gfp_t);
++void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool sync);
++int write_meta_page(struct f2fs_sb_info *, struct page *,
++ struct writeback_control *);
++void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
++ block_t, block_t *);
++void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
++ block_t, block_t *);
++void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
++void recover_data_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, block_t, block_t);
++void rewrite_node_page(struct f2fs_sb_info *, struct page *,
++ struct f2fs_summary *, block_t, block_t);
++void write_data_summaries(struct f2fs_sb_info *, block_t);
++void write_node_summaries(struct f2fs_sb_info *, block_t);
++int lookup_journal_in_cursum(struct f2fs_summary_block *,
++ int, unsigned int, int);
++void flush_sit_entries(struct f2fs_sb_info *);
++int build_segment_manager(struct f2fs_sb_info *);
++void reset_victim_segmap(struct f2fs_sb_info *);
++void destroy_segment_manager(struct f2fs_sb_info *);
++
++/**
++ * checkpoint.c
++ */
++struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t);
++struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t);
++long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
++int check_orphan_space(struct f2fs_sb_info *);
++void add_orphan_inode(struct f2fs_sb_info *, nid_t);
++void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
++int recover_orphan_inodes(struct f2fs_sb_info *);
++int get_valid_checkpoint(struct f2fs_sb_info *);
++void set_dirty_dir_page(struct inode *, struct page *);
++void remove_dirty_dir_inode(struct inode *);
++void sync_dirty_dir_inodes(struct f2fs_sb_info *);
++void block_operations(struct f2fs_sb_info *);
++void write_checkpoint(struct f2fs_sb_info *, bool, bool);
++void init_orphan_info(struct f2fs_sb_info *);
++int create_checkpoint_caches(void);
++void destroy_checkpoint_caches(void);
++
++/**
++ * data.c
++ */
++int reserve_new_block(struct dnode_of_data *);
++void update_extent_cache(block_t, struct dnode_of_data *);
++struct page *find_data_page(struct inode *, pgoff_t);
++struct page *get_lock_data_page(struct inode *, pgoff_t);
++struct page *get_new_data_page(struct inode *, pgoff_t, bool);
++int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
++int do_write_data_page(struct page *);
++
++/**
++ * gc.c
++ */
++int start_gc_thread(struct f2fs_sb_info *);
++void stop_gc_thread(struct f2fs_sb_info *);
++block_t start_bidx_of_node(unsigned int);
++int f2fs_gc(struct f2fs_sb_info *, int);
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *);
++void f2fs_update_gc_metric(struct f2fs_sb_info *);
++int f2fs_stat_init(struct f2fs_sb_info *);
++void f2fs_stat_exit(struct f2fs_sb_info *);
++#endif
++int build_gc_manager(struct f2fs_sb_info *);
++void destroy_gc_manager(struct f2fs_sb_info *);
++int create_gc_caches(void);
++void destroy_gc_caches(void);
++
++/**
++ * recovery.c
++ */
++void recover_fsync_data(struct f2fs_sb_info *);
++bool space_for_roll_forward(struct f2fs_sb_info *);
++
++extern const struct file_operations f2fs_dir_operations;
++extern const struct file_operations f2fs_file_operations;
++extern const struct inode_operations f2fs_file_inode_operations;
++extern const struct address_space_operations f2fs_dblock_aops;
++extern const struct address_space_operations f2fs_node_aops;
++extern const struct address_space_operations f2fs_meta_aops;
++extern const struct inode_operations f2fs_dir_inode_operations;
++extern const struct inode_operations f2fs_symlink_inode_operations;
++extern const struct inode_operations f2fs_special_inode_operations;
++#endif
+diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
+new file mode 100644
+index 0000000..99ac689
+--- /dev/null
++++ b/fs/f2fs/node.h
+@@ -0,0 +1,330 @@
++/**
++ * fs/f2fs/node.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#define START_NID(nid) ((nid / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK)
++#define NAT_BLOCK_OFFSET(start_nid) (start_nid / NAT_ENTRY_PER_BLOCK)
++
++#define FREE_NID_PAGES 4
++#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
++
++#define MAX_RA_NODE 128 /* Max. readahead size for node */
++#define NM_WOUT_THRESHOLD (64 * NAT_ENTRY_PER_BLOCK)
++#define NATVEC_SIZE 64
++
++/**
++ * For node information
++ */
++struct node_info {
++ nid_t nid; /* node id */
++ nid_t ino; /* inode number of the node's owner */
++ block_t blk_addr; /* block address of the node */
++ unsigned char version; /* version of the node */
++};
++
++static inline unsigned char inc_node_version(unsigned char version)
++{
++ return ++version;
++}
++
++struct nat_entry {
++ struct list_head list; /* for clean or dirty nat list */
++ bool checkpointed;
++ struct node_info ni;
++};
++
++#define nat_get_nid(nat) (nat->ni.nid)
++#define nat_set_nid(nat, n) (nat->ni.nid = n)
++#define nat_get_blkaddr(nat) (nat->ni.blk_addr)
++#define nat_set_blkaddr(nat, b) (nat->ni.blk_addr = b)
++#define nat_get_ino(nat) (nat->ni.ino)
++#define nat_set_ino(nat, i) (nat->ni.ino = i)
++#define nat_get_version(nat) (nat->ni.version)
++#define nat_set_version(nat, v) (nat->ni.version = v)
++#define __set_nat_cache_dirty(nm_i, ne) \
++ list_move_tail(&ne->list, &nm_i->dirty_nat_entries);
++#define __clear_nat_cache_dirty(nm_i, ne) \
++ list_move_tail(&ne->list, &nm_i->nat_entries);
++
++static inline void node_info_from_raw_nat(struct node_info *ni,
++ struct f2fs_nat_entry *raw_ne)
++{
++ ni->ino = le32_to_cpu(raw_ne->ino);
++ ni->blk_addr = le32_to_cpu(raw_ne->block_addr);
++ ni->version = raw_ne->version;
++}
++
++/**
++ * For free nid mangement
++ */
++enum nid_state {
++ NID_NEW,
++ NID_ALLOC
++};
++
++struct free_nid {
++ nid_t nid;
++ int state;
++ struct list_head list;
++};
++
++static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *fnid;
++
++ if (nm_i->fcnt <= 0)
++ return -1;
++ spin_lock(&nm_i->free_nid_list_lock);
++ fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list);
++ *nid = fnid->nid;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return 0;
++}
++
++/**
++ * inline functions
++ */
++static inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size);
++}
++
++static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ pgoff_t block_off;
++ pgoff_t block_addr;
++ int seg_off;
++
++ block_off = NAT_BLOCK_OFFSET(start);
++ seg_off = block_off >> sbi->log_blocks_per_seg;
++
++ block_addr = (pgoff_t)(nm_i->nat_blkaddr +
++ (seg_off << sbi->log_blocks_per_seg << 1) +
++ (block_off & ((1 << sbi->log_blocks_per_seg) - 1)));
++
++ if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
++ block_addr += sbi->blocks_per_seg;
++
++ return block_addr;
++}
++
++static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi,
++ pgoff_t block_addr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ block_addr -= nm_i->nat_blkaddr;
++ if ((block_addr >> sbi->log_blocks_per_seg) % 2)
++ block_addr -= sbi->blocks_per_seg;
++ else
++ block_addr += sbi->blocks_per_seg;
++
++ return block_addr + nm_i->nat_blkaddr;
++}
++
++static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid)
++{
++ unsigned int block_off = NAT_BLOCK_OFFSET(start_nid);
++
++ if (f2fs_test_bit(block_off, nm_i->nat_bitmap))
++ f2fs_clear_bit(block_off, nm_i->nat_bitmap);
++ else
++ f2fs_set_bit(block_off, nm_i->nat_bitmap);
++}
++
++static inline void fill_node_footer(struct page *page, nid_t nid,
++ nid_t ino, unsigned int ofs, bool reset)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ if (reset)
++ memset(rn, 0, sizeof(*rn));
++ rn->footer.nid = cpu_to_le32(nid);
++ rn->footer.ino = cpu_to_le32(ino);
++ rn->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT);
++}
++
++static inline void copy_node_footer(struct page *dst, struct page *src)
++{
++ void *src_addr = page_address(src);
++ void *dst_addr = page_address(dst);
++ struct f2fs_node *src_rn = (struct f2fs_node *)src_addr;
++ struct f2fs_node *dst_rn = (struct f2fs_node *)dst_addr;
++ memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer));
++}
++
++static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ rn->footer.cp_ver = ckpt->checkpoint_ver;
++ rn->footer.next_blkaddr = blkaddr;
++}
++
++static inline nid_t ino_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.ino);
++}
++
++static inline nid_t nid_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.nid);
++}
++
++static inline unsigned int ofs_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned flag = le32_to_cpu(rn->footer.flag);
++ return flag >> OFFSET_BIT_SHIFT;
++}
++
++static inline unsigned long long cpver_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le64_to_cpu(rn->footer.cp_ver);
++}
++
++static inline block_t next_blkaddr_of_node(struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ return le32_to_cpu(rn->footer.next_blkaddr);
++}
++
++static inline bool IS_DNODE(struct page *node_page)
++{
++ unsigned int ofs = ofs_of_node(node_page);
++ if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK ||
++ ofs == 5 + 2 * NIDS_PER_BLOCK)
++ return false;
++ if (ofs >= 6 + 2 * NIDS_PER_BLOCK) {
++ ofs -= 6 + 2 * NIDS_PER_BLOCK;
++ if ((long int)ofs % (NIDS_PER_BLOCK + 1))
++ return false;
++ }
++ return true;
++}
++
++static inline void set_nid(struct page *p, int off, nid_t nid, bool i)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
++
++ wait_on_page_writeback(p);
++
++ if (i)
++ rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid);
++ else
++ rn->in.nid[off] = cpu_to_le32(nid);
++ set_page_dirty(p);
++}
++
++static inline nid_t get_nid(struct page *p, int off, bool i)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(p);
++ if (i)
++ return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]);
++ return le32_to_cpu(rn->in.nid[off]);
++}
++
++/**
++ * Coldness identification:
++ * - Mark cold files in f2fs_inode_info
++ * - Mark cold node blocks in their node footer
++ * - Mark cold data pages in page cache
++ */
++static inline int is_cold_file(struct inode *inode)
++{
++ return F2FS_I(inode)->i_advise & FADVISE_COLD_BIT;
++}
++
++static inline int is_cold_data(struct page *page)
++{
++ return PageChecked(page);
++}
++
++static inline void set_cold_data(struct page *page)
++{
++ SetPageChecked(page);
++}
++
++static inline void clear_cold_data(struct page *page)
++{
++ ClearPageChecked(page);
++}
++
++static inline int is_cold_node(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << COLD_BIT_SHIFT);
++}
++
++static inline unsigned char is_fsync_dnode(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << FSYNC_BIT_SHIFT);
++}
++
++static inline unsigned char is_dent_dnode(struct page *page)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ return flag & (0x1 << DENT_BIT_SHIFT);
++}
++
++static inline void set_cold_node(struct inode *inode, struct page *page)
++{
++ struct f2fs_node *rn = (struct f2fs_node *)page_address(page);
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++
++ if (S_ISDIR(inode->i_mode))
++ flag &= ~(0x1 << COLD_BIT_SHIFT);
++ else
++ flag |= (0x1 << COLD_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
++
++static inline void set_fsync_mark(struct page *page, int mark)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ if (mark)
++ flag |= (0x1 << FSYNC_BIT_SHIFT);
++ else
++ flag &= ~(0x1 << FSYNC_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
++
++static inline void set_dentry_mark(struct page *page, int mark)
++{
++ void *kaddr = page_address(page);
++ struct f2fs_node *rn = (struct f2fs_node *)kaddr;
++ unsigned int flag = le32_to_cpu(rn->footer.flag);
++ if (mark)
++ flag |= (0x1 << DENT_BIT_SHIFT);
++ else
++ flag &= ~(0x1 << DENT_BIT_SHIFT);
++ rn->footer.flag = cpu_to_le32(flag);
++}
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+new file mode 100644
+index 0000000..cd6268e
+--- /dev/null
++++ b/fs/f2fs/segment.h
+@@ -0,0 +1,594 @@
++/**
++ * fs/f2fs/segment.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/* constant macro */
++#define NULL_SEGNO ((unsigned int)(~0))
++#define SUM_TYPE_NODE (1)
++#define SUM_TYPE_DATA (0)
++
++/* V: Logical segment # in volume, R: Relative segment # in main area */
++#define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno)
++#define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno)
++
++#define IS_DATASEG(t) \
++ ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) || \
++ (t == CURSEG_WARM_DATA))
++
++#define IS_NODESEG(t) \
++ ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) || \
++ (t == CURSEG_WARM_NODE))
++
++#define IS_CURSEG(sbi, segno) \
++ ((segno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \
++ (segno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
++
++#define IS_CURSEC(sbi, secno) \
++ ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \
++ sbi->segs_per_sec) || \
++ (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \
++ sbi->segs_per_sec)) \
++
++#define START_BLOCK(sbi, segno) \
++ (SM_I(sbi)->seg0_blkaddr + \
++ (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg))
++#define NEXT_FREE_BLKADDR(sbi, curseg) \
++ (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff)
++
++#define MAIN_BASE_BLOCK(sbi) (SM_I(sbi)->main_blkaddr)
++
++#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) \
++ ((blk_addr) - SM_I(sbi)->seg0_blkaddr)
++#define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \
++ (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
++#define GET_SEGNO(sbi, blk_addr) \
++ (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ? \
++ NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
++ GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
++#define GET_SECNO(sbi, segno) \
++ ((segno) / sbi->segs_per_sec)
++#define GET_ZONENO_FROM_SEGNO(sbi, segno) \
++ ((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
++
++#define GET_SUM_BLOCK(sbi, segno) \
++ ((sbi->sm_info->ssa_blkaddr) + segno)
++
++#define GET_SUM_TYPE(footer) ((footer)->entry_type)
++#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
++
++#define SIT_ENTRY_OFFSET(sit_i, segno) \
++ (segno % sit_i->sents_per_block)
++#define SIT_BLOCK_OFFSET(sit_i, segno) \
++ (segno / SIT_ENTRY_PER_BLOCK)
++#define START_SEGNO(sit_i, segno) \
++ (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK)
++#define f2fs_bitmap_size(nr) \
++ (BITS_TO_LONGS(nr) * sizeof(unsigned long))
++#define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segment_count)
++
++enum {
++ LFS = 0,
++ SSR
++};
++
++enum {
++ ALLOC_RIGHT = 0,
++ ALLOC_LEFT
++};
++
++#define SET_SSR_TYPE(type) (((type) + 1) << 16)
++#define GET_SSR_TYPE(type) (((type) >> 16) - 1)
++#define IS_SSR_TYPE(type) ((type) >= (0x1 << 16))
++#define IS_NEXT_SEG(sbi, curseg, type) \
++ (DIRTY_I(sbi)->v_ops->get_victim(sbi, &(curseg)->next_segno, \
++ BG_GC, SET_SSR_TYPE(type)))
++/**
++ * The MSB 6 bits of f2fs_sit_entry->vblocks has segment type,
++ * and LSB 10 bits has valid blocks.
++ */
++#define VBLOCKS_MASK ((1 << 10) - 1)
++
++#define GET_SIT_VBLOCKS(raw_sit) \
++ (le16_to_cpu((raw_sit)->vblocks) & VBLOCKS_MASK)
++#define GET_SIT_TYPE(raw_sit) \
++ ((le16_to_cpu((raw_sit)->vblocks) & ~VBLOCKS_MASK) >> 10)
++
++struct bio_private {
++ struct f2fs_sb_info *sbi;
++ bool is_sync;
++ void *wait;
++};
++
++enum {
++ GC_CB = 0,
++ GC_GREEDY
++};
++
++struct victim_sel_policy {
++ int alloc_mode;
++ int gc_mode;
++ int type;
++ unsigned long *dirty_segmap;
++ unsigned int offset;
++ unsigned int ofs_unit;
++ unsigned int min_cost;
++ unsigned int min_segno;
++};
++
++struct seg_entry {
++ unsigned short valid_blocks;
++ unsigned char *cur_valid_map;
++ unsigned short ckpt_valid_blocks;
++ unsigned char *ckpt_valid_map;
++ unsigned char type;
++ unsigned long long mtime;
++};
++
++struct sec_entry {
++ unsigned int valid_blocks;
++};
++
++struct segment_allocation {
++ void (*allocate_segment)(struct f2fs_sb_info *, int, bool);
++};
++
++struct sit_info {
++ const struct segment_allocation *s_ops;
++
++ block_t sit_base_addr;
++ block_t sit_blocks;
++ block_t written_valid_blocks; /* total number of valid blocks
++ in main area */
++ char *sit_bitmap; /* SIT bitmap pointer */
++ unsigned int bitmap_size;
++
++ unsigned int dirty_sentries; /* # of dirty sentries */
++ unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */
++ unsigned int sents_per_block; /* number of SIT entries
++ per SIT block */
++ struct mutex sentry_lock; /* to protect SIT entries */
++ struct seg_entry *sentries;
++ struct sec_entry *sec_entries;
++
++ unsigned long long elapsed_time;
++ unsigned long long mounted_time;
++ unsigned long long min_mtime;
++ unsigned long long max_mtime;
++};
++
++struct free_segmap_info {
++ unsigned int start_segno;
++ unsigned int free_segments;
++ unsigned int free_sections;
++ rwlock_t segmap_lock; /* free segmap lock */
++ unsigned long *free_segmap;
++ unsigned long *free_secmap;
++};
++
++/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */
++enum dirty_type {
++ DIRTY_HOT_DATA, /* a few valid blocks in a data segment */
++ DIRTY_WARM_DATA,
++ DIRTY_COLD_DATA,
++ DIRTY_HOT_NODE, /* a few valid blocks in a node segment */
++ DIRTY_WARM_NODE,
++ DIRTY_COLD_NODE,
++ DIRTY,
++ PRE, /* no valid blocks in a segment */
++ NR_DIRTY_TYPE
++};
++
++enum {
++ BG_GC,
++ FG_GC
++};
++
++struct dirty_seglist_info {
++ const struct victim_selection *v_ops;
++ struct mutex seglist_lock;
++ unsigned long *dirty_segmap[NR_DIRTY_TYPE];
++ int nr_dirty[NR_DIRTY_TYPE];
++ unsigned long *victim_segmap[2]; /* BG_GC, FG_GC */
++};
++
++struct victim_selection {
++ int (*get_victim)(struct f2fs_sb_info *, unsigned int *, int, int);
++};
++
++struct curseg_info {
++ struct mutex curseg_mutex;
++ struct f2fs_summary_block *sum_blk;
++ unsigned char alloc_type;
++ unsigned int segno;
++ unsigned short next_blkoff;
++ unsigned int zone;
++ unsigned int next_segno;
++};
++
++/**
++ * inline functions
++ */
++static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type)
++{
++ return (struct curseg_info *)(SM_I(sbi)->curseg_array + type);
++}
++
++static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return &sit_i->sentries[segno];
++}
++
++static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return &sit_i->sec_entries[GET_SECNO(sbi, segno)];
++}
++
++static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
++ unsigned int segno, int section)
++{
++ if (section > 1)
++ return get_sec_entry(sbi, segno)->valid_blocks;
++ else
++ return get_seg_entry(sbi, segno)->valid_blocks;
++}
++
++static inline void seg_info_from_raw_sit(struct seg_entry *se,
++ struct f2fs_sit_entry *rs)
++{
++ se->valid_blocks = GET_SIT_VBLOCKS(rs);
++ se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs);
++ memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ se->type = GET_SIT_TYPE(rs);
++ se->mtime = le64_to_cpu(rs->mtime);
++}
++
++static inline void seg_info_to_raw_sit(struct seg_entry *se,
++ struct f2fs_sit_entry *rs)
++{
++ unsigned short raw_vblocks = (se->type << 10) | se->valid_blocks;
++ rs->vblocks = cpu_to_le16(raw_vblocks);
++ memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE);
++ memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE);
++ se->ckpt_valid_blocks = se->valid_blocks;
++ rs->mtime = cpu_to_le64(se->mtime);
++}
++
++static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
++ unsigned int max, unsigned int segno)
++{
++ unsigned int ret;
++ read_lock(&free_i->segmap_lock);
++ ret = find_next_bit(free_i->free_segmap, max, segno);
++ read_unlock(&free_i->segmap_lock);
++ return ret;
++}
++
++static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ unsigned int start_segno = secno * sbi->segs_per_sec;
++ unsigned int next;
++
++ write_lock(&free_i->segmap_lock);
++ clear_bit(segno, free_i->free_segmap);
++ free_i->free_segments++;
++
++ next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno);
++ if (next >= start_segno + sbi->segs_per_sec) {
++ clear_bit(secno, free_i->free_secmap);
++ free_i->free_sections++;
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void __set_inuse(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ set_bit(segno, free_i->free_segmap);
++ free_i->free_segments--;
++ if (!test_and_set_bit(secno, free_i->free_secmap))
++ free_i->free_sections--;
++}
++
++static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ unsigned int start_segno = secno * sbi->segs_per_sec;
++ unsigned int next;
++
++ write_lock(&free_i->segmap_lock);
++ if (test_and_clear_bit(segno, free_i->free_segmap)) {
++ free_i->free_segments++;
++
++ next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi),
++ start_segno);
++ if (next >= start_segno + sbi->segs_per_sec) {
++ if (test_and_clear_bit(secno, free_i->free_secmap))
++ free_i->free_sections++;
++ }
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int secno = segno / sbi->segs_per_sec;
++ write_lock(&free_i->segmap_lock);
++ if (!test_and_set_bit(segno, free_i->free_segmap)) {
++ free_i->free_segments--;
++ if (!test_and_set_bit(secno, free_i->free_secmap))
++ free_i->free_sections--;
++ }
++ write_unlock(&free_i->segmap_lock);
++}
++
++static inline void get_sit_bitmap(struct f2fs_sb_info *sbi,
++ void *dst_addr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size);
++}
++
++static inline block_t written_block_count(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ block_t vblocks;
++
++ mutex_lock(&sit_i->sentry_lock);
++ vblocks = sit_i->written_valid_blocks;
++ mutex_unlock(&sit_i->sentry_lock);
++
++ return vblocks;
++}
++
++static inline unsigned int free_segments(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int free_segs;
++
++ read_lock(&free_i->segmap_lock);
++ free_segs = free_i->free_segments;
++ read_unlock(&free_i->segmap_lock);
++
++ return free_segs;
++}
++
++static inline int reserved_segments(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return gc_i->rsvd_segment_count;
++}
++
++static inline unsigned int free_sections(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int free_secs;
++
++ read_lock(&free_i->segmap_lock);
++ free_secs = free_i->free_sections;
++ read_unlock(&free_i->segmap_lock);
++
++ return free_secs;
++}
++
++static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi)
++{
++ return DIRTY_I(sbi)->nr_dirty[PRE];
++}
++
++static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi)
++{
++ return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] +
++ DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE];
++}
++
++static inline int overprovision_segments(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return gc_i->overp_segment_count;
++}
++
++static inline int overprovision_sections(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return ((unsigned int) gc_i->overp_segment_count) / sbi->segs_per_sec;
++}
++
++static inline int reserved_sections(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ return ((unsigned int) gc_i->rsvd_segment_count) / sbi->segs_per_sec;
++}
++
++static inline bool need_SSR(struct f2fs_sb_info *sbi)
++{
++ return (free_sections(sbi) < overprovision_sections(sbi));
++}
++
++static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi)
++{
++ return free_sections(sbi) <= reserved_sections(sbi);
++}
++
++static inline int utilization(struct f2fs_sb_info *sbi)
++{
++ return (long int)valid_user_blocks(sbi) * 100 /
++ (long int)sbi->user_block_count;
++}
++
++/* Disable In-Place-Update by default */
++#define MIN_IPU_UTIL 100
++static inline bool need_inplace_update(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (S_ISDIR(inode->i_mode))
++ return false;
++ if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL)
++ return true;
++ return false;
++}
++
++static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi,
++ int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->segno;
++}
++
++static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi,
++ int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->alloc_type;
++}
++
++static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ return curseg->next_blkoff;
++}
++
++static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ unsigned int end_segno = SM_I(sbi)->segment_count - 1;
++ BUG_ON(segno > end_segno);
++}
++
++/*
++ * This function is used for only debugging.
++ * NOTE: In future, we have to remove this function.
++ */
++static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg;
++ block_t start_addr = sm_info->seg0_blkaddr;
++ block_t end_addr = start_addr + total_blks - 1;
++ BUG_ON(blk_addr < start_addr);
++ BUG_ON(blk_addr > end_addr);
++}
++
++/**
++ * Summary block is always treated as invalid block
++ */
++static inline void check_block_count(struct f2fs_sb_info *sbi,
++ int segno, struct f2fs_sit_entry *raw_sit)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ unsigned int end_segno = sm_info->segment_count - 1;
++ int valid_blocks = 0;
++ int i;
++
++ /* check segment usage */
++ BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg);
++
++ /* check boundary of a given segment number */
++ BUG_ON(segno > end_segno);
++
++ /* check bitmap with valid block count */
++ for (i = 0; i < sbi->blocks_per_seg; i++)
++ if (f2fs_test_bit(i, raw_sit->valid_map))
++ valid_blocks++;
++ BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
++}
++
++static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
++ unsigned int start)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start);
++ block_t blk_addr = sit_i->sit_base_addr + offset;
++
++ check_seg_range(sbi, start);
++
++ /* calculate sit block address */
++ if (f2fs_test_bit(offset, sit_i->sit_bitmap))
++ blk_addr += sit_i->sit_blocks;
++
++ return blk_addr;
++}
++
++static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi,
++ pgoff_t block_addr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ block_addr -= sit_i->sit_base_addr;
++ if (block_addr < sit_i->sit_blocks)
++ block_addr += sit_i->sit_blocks;
++ else
++ block_addr -= sit_i->sit_blocks;
++
++ return block_addr + sit_i->sit_base_addr;
++}
++
++static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
++{
++ unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start);
++
++ if (f2fs_test_bit(block_off, sit_i->sit_bitmap))
++ f2fs_clear_bit(block_off, sit_i->sit_bitmap);
++ else
++ f2fs_set_bit(block_off, sit_i->sit_bitmap);
++}
++
++static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec -
++ sit_i->mounted_time;
++}
++
++static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
++ unsigned int ofs_in_node, unsigned char version)
++{
++ sum->nid = cpu_to_le32(nid);
++ sum->ofs_in_node = cpu_to_le16(ofs_in_node);
++ sum->version = version;
++}
++
++static inline block_t start_sum_block(struct f2fs_sb_info *sbi)
++{
++ return __start_cp_addr(sbi) +
++ le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum);
++}
++
++static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
++{
++ return __start_cp_addr(sbi) +
++ le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count)
++ - (base + 1) + type;
++}
diff --git a/patches/linux-3.7/0103-f2fs-add-super-block-operations.patch b/patches/linux-3.7/0103-f2fs-add-super-block-operations.patch
new file mode 100644
index 0000000..420a742
--- /dev/null
+++ b/patches/linux-3.7/0103-f2fs-add-super-block-operations.patch
@@ -0,0 +1,611 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:27:13 +0000
+Subject: [PATCH] f2fs: add super block operations
+
+This adds the implementation of superblock operations for f2fs, which includes
+- init_f2fs_fs/exit_f2fs_fs
+- f2fs_mount
+- super_operations of f2fs
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/super.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 590 insertions(+)
+ create mode 100644 fs/f2fs/super.c
+
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+new file mode 100644
+index 0000000..8e608a0
+--- /dev/null
++++ b/fs/f2fs/super.c
+@@ -0,0 +1,590 @@
++/**
++ * fs/f2fs/super.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/fs.h>
++#include <linux/statfs.h>
++#include <linux/proc_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/backing-dev.h>
++#include <linux/kthread.h>
++#include <linux/parser.h>
++#include <linux/mount.h>
++#include <linux/seq_file.h>
++#include <linux/f2fs_fs.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "xattr.h"
++
++static struct kmem_cache *f2fs_inode_cachep;
++static struct proc_dir_entry *f2fs_proc_root;
++
++enum {
++ Opt_gc_background_off,
++ Opt_disable_roll_forward,
++ Opt_discard,
++ Opt_noheap,
++ Opt_nouser_xattr,
++ Opt_noacl,
++ Opt_active_logs,
++ Opt_disable_ext_identify,
++ Opt_err,
++};
++
++static match_table_t f2fs_tokens = {
++ {Opt_gc_background_off, "background_gc_off"},
++ {Opt_disable_roll_forward, "disable_roll_forward"},
++ {Opt_discard, "discard"},
++ {Opt_noheap, "no_heap"},
++ {Opt_nouser_xattr, "nouser_xattr"},
++ {Opt_noacl, "noacl"},
++ {Opt_active_logs, "active_logs=%u"},
++ {Opt_disable_ext_identify, "disable_ext_identify"},
++ {Opt_err, NULL},
++};
++
++static void init_once(void *foo)
++{
++ struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
++
++ memset(fi, 0, sizeof(*fi));
++ inode_init_once(&fi->vfs_inode);
++}
++
++static struct inode *f2fs_alloc_inode(struct super_block *sb)
++{
++ struct f2fs_inode_info *fi;
++
++ fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_NOFS | __GFP_ZERO);
++ if (!fi)
++ return NULL;
++
++ init_once((void *) fi);
++
++ /* Initilize f2fs-specific inode info */
++ fi->vfs_inode.i_version = 1;
++ atomic_set(&fi->dirty_dents, 0);
++ fi->current_depth = 1;
++ fi->i_advise = 0;
++ rwlock_init(&fi->ext.ext_lock);
++
++ set_inode_flag(fi, FI_NEW_INODE);
++
++ return &fi->vfs_inode;
++}
++
++static void f2fs_i_callback(struct rcu_head *head)
++{
++ struct inode *inode = container_of(head, struct inode, i_rcu);
++ kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode));
++}
++
++void f2fs_destroy_inode(struct inode *inode)
++{
++ call_rcu(&inode->i_rcu, f2fs_i_callback);
++}
++
++static void f2fs_put_super(struct super_block *sb)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++
++#ifdef CONFIG_F2FS_STAT_FS
++ if (sbi->s_proc) {
++ f2fs_stat_exit(sbi);
++ remove_proc_entry(sb->s_id, f2fs_proc_root);
++ }
++#endif
++ stop_gc_thread(sbi);
++
++ write_checkpoint(sbi, false, true);
++
++ iput(sbi->node_inode);
++ iput(sbi->meta_inode);
++
++ /* destroy f2fs internal modules */
++ destroy_gc_manager(sbi);
++ destroy_node_manager(sbi);
++ destroy_segment_manager(sbi);
++
++ kfree(sbi->ckpt);
++
++ sb->s_fs_info = NULL;
++ brelse(sbi->raw_super_buf);
++ kfree(sbi);
++}
++
++int f2fs_sync_fs(struct super_block *sb, int sync)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ int ret = 0;
++
++ if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
++ return 0;
++
++ if (sync)
++ write_checkpoint(sbi, false, false);
++
++ return ret;
++}
++
++static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct super_block *sb = dentry->d_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ block_t total_count, user_block_count, start_count, ovp_count;
++
++ total_count = le64_to_cpu(sbi->raw_super->block_count);
++ user_block_count = sbi->user_block_count;
++ start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr);
++ ovp_count = sbi->gc_info->overp_segment_count
++ << sbi->log_blocks_per_seg;
++ buf->f_type = F2FS_SUPER_MAGIC;
++ buf->f_bsize = sbi->blocksize;
++
++ buf->f_blocks = total_count - start_count;
++ buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
++ buf->f_bavail = user_block_count - valid_user_blocks(sbi);
++
++ buf->f_files = valid_inode_count(sbi);
++ buf->f_ffree = sbi->total_node_count - valid_node_count(sbi);
++
++ buf->f_namelen = F2FS_MAX_NAME_LEN;
++
++ return 0;
++}
++
++static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb);
++
++ if (test_opt(sbi, BG_GC))
++ seq_puts(seq, ",background_gc_on");
++ else
++ seq_puts(seq, ",background_gc_off");
++ if (test_opt(sbi, DISABLE_ROLL_FORWARD))
++ seq_puts(seq, ",disable_roll_forward");
++ if (test_opt(sbi, DISCARD))
++ seq_puts(seq, ",discard");
++ if (test_opt(sbi, NOHEAP))
++ seq_puts(seq, ",no_heap_alloc");
++#ifdef CONFIG_F2FS_FS_XATTR
++ if (test_opt(sbi, XATTR_USER))
++ seq_puts(seq, ",user_xattr");
++ else
++ seq_puts(seq, ",nouser_xattr");
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ if (test_opt(sbi, POSIX_ACL))
++ seq_puts(seq, ",acl");
++ else
++ seq_puts(seq, ",noacl");
++#endif
++ if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
++ seq_puts(seq, ",disable_ext_indentify");
++
++ seq_printf(seq, ",active_logs=%u", sbi->active_logs);
++
++ return 0;
++}
++
++static struct super_operations f2fs_sops = {
++ .alloc_inode = f2fs_alloc_inode,
++ .destroy_inode = f2fs_destroy_inode,
++ .write_inode = f2fs_write_inode,
++ .show_options = f2fs_show_options,
++ .evict_inode = f2fs_evict_inode,
++ .put_super = f2fs_put_super,
++ .sync_fs = f2fs_sync_fs,
++ .statfs = f2fs_statfs,
++};
++
++static int parse_options(struct f2fs_sb_info *sbi, char *options)
++{
++ substring_t args[MAX_OPT_ARGS];
++ char *p;
++ int arg = 0;
++
++ if (!options)
++ return 0;
++
++ while ((p = strsep(&options, ",")) != NULL) {
++ int token;
++ if (!*p)
++ continue;
++ /*
++ * Initialize args struct so we know whether arg was
++ * found; some options take optional arguments.
++ */
++ args[0].to = args[0].from = NULL;
++ token = match_token(p, f2fs_tokens, args);
++
++ switch (token) {
++ case Opt_gc_background_off:
++ clear_opt(sbi, BG_GC);
++ break;
++ case Opt_disable_roll_forward:
++ set_opt(sbi, DISABLE_ROLL_FORWARD);
++ break;
++ case Opt_discard:
++ set_opt(sbi, DISCARD);
++ break;
++ case Opt_noheap:
++ set_opt(sbi, NOHEAP);
++ break;
++#ifdef CONFIG_F2FS_FS_XATTR
++ case Opt_nouser_xattr:
++ clear_opt(sbi, XATTR_USER);
++ break;
++#else
++ case Opt_nouser_xattr:
++ pr_info("nouser_xattr options not supported\n");
++ break;
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ case Opt_noacl:
++ clear_opt(sbi, POSIX_ACL);
++ break;
++#else
++ case Opt_noacl:
++ pr_info("noacl options not supported\n");
++ break;
++#endif
++ case Opt_active_logs:
++ if (args->from && match_int(args, &arg))
++ return -EINVAL;
++ if (arg != 2 && arg != 4 && arg != 6)
++ return -EINVAL;
++ sbi->active_logs = arg;
++ break;
++ case Opt_disable_ext_identify:
++ set_opt(sbi, DISABLE_EXT_IDENTIFY);
++ break;
++ default:
++ return -EINVAL;
++ }
++ }
++ return 0;
++}
++
++static loff_t max_file_size(unsigned bits)
++{
++ loff_t result = ADDRS_PER_INODE;
++ loff_t leaf_count = ADDRS_PER_BLOCK;
++
++ result += (leaf_count * 2);
++
++ leaf_count *= NIDS_PER_BLOCK;
++ result += (leaf_count * 2);
++
++ leaf_count *= NIDS_PER_BLOCK;
++ result += (leaf_count * 2);
++
++ result <<= bits;
++ return result;
++}
++
++static int sanity_check_raw_super(struct f2fs_super_block *raw_super)
++{
++ unsigned int blocksize;
++
++ if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic))
++ return 1;
++
++ /* Currently, support only 4KB block size */
++ blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
++ if (blocksize != PAGE_CACHE_SIZE)
++ return 1;
++ if (le32_to_cpu(raw_super->log_sectorsize) != 9)
++ return 1;
++ if (le32_to_cpu(raw_super->log_sectors_per_block) != 3)
++ return 1;
++ return 0;
++}
++
++static int sanity_check_ckpt(struct f2fs_super_block *raw_super,
++ struct f2fs_checkpoint *ckpt)
++{
++ unsigned int total, fsmeta;
++
++ total = le32_to_cpu(raw_super->segment_count);
++ fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
++ fsmeta += le32_to_cpu(raw_super->segment_count_sit);
++ fsmeta += le32_to_cpu(raw_super->segment_count_nat);
++ fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
++ fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
++
++ if (fsmeta >= total)
++ return 1;
++ return 0;
++}
++
++static void init_sb_info(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = sbi->raw_super;
++ int i;
++
++ sbi->log_sectorsize = le32_to_cpu(raw_super->log_sectorsize);
++ sbi->log_sectors_per_block =
++ le32_to_cpu(raw_super->log_sectors_per_block);
++ sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
++ sbi->blocksize = 1 << sbi->log_blocksize;
++ sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
++ sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
++ sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
++ sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
++ sbi->total_sections = le32_to_cpu(raw_super->section_count);
++ sbi->total_node_count =
++ (le32_to_cpu(raw_super->segment_count_nat) / 2)
++ * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
++ sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
++ sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
++ sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
++
++ for (i = 0; i < NR_COUNT_TYPE; i++)
++ atomic_set(&sbi->nr_pages[i], 0);
++}
++
++static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
++{
++ struct f2fs_sb_info *sbi;
++ struct f2fs_super_block *raw_super;
++ struct buffer_head *raw_super_buf;
++ struct inode *root;
++ int i;
++
++ /* allocate memory for f2fs-specific super block info */
++ sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
++ if (!sbi)
++ return -ENOMEM;
++
++ /* set a temporary block size */
++ if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
++ goto free_sbi;
++
++ /* read f2fs raw super block */
++ raw_super_buf = sb_bread(sb, F2FS_SUPER_OFFSET);
++ if (!raw_super_buf)
++ goto free_sbi;
++ raw_super = (struct f2fs_super_block *) ((char *)raw_super_buf->b_data);
++
++ /* init some FS parameters */
++ sbi->active_logs = NR_CURSEG_TYPE;
++
++ set_opt(sbi, BG_GC);
++
++#ifdef CONFIG_F2FS_FS_XATTR
++ set_opt(sbi, XATTR_USER);
++#endif
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ set_opt(sbi, POSIX_ACL);
++#endif
++ /* parse mount options */
++ if (parse_options(sbi, (char *)data))
++ goto free_sb_buf;
++
++ /* sanity checking of raw super */
++ if (sanity_check_raw_super(raw_super))
++ goto free_sb_buf;
++
++ sb->s_maxbytes = max_file_size(raw_super->log_blocksize);
++ sb->s_max_links = F2FS_LINK_MAX;
++
++ sb->s_op = &f2fs_sops;
++ sb->s_xattr = f2fs_xattr_handlers;
++ sb->s_magic = F2FS_SUPER_MAGIC;
++ sb->s_fs_info = sbi;
++ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
++ (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0);
++
++ /* init f2fs-specific super block info */
++ sbi->sb = sb;
++ sbi->raw_super = raw_super;
++ sbi->raw_super_buf = raw_super_buf;
++ mutex_init(&sbi->gc_mutex);
++ mutex_init(&sbi->write_inode);
++ mutex_init(&sbi->writepages);
++ mutex_init(&sbi->cp_mutex);
++ for (i = 0; i < NR_LOCK_TYPE; i++)
++ mutex_init(&sbi->fs_lock[i]);
++ sbi->por_doing = 0;
++ spin_lock_init(&sbi->stat_lock);
++ init_rwsem(&sbi->bio_sem);
++ init_sb_info(sbi);
++
++ /* get an inode for meta space */
++ sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
++ if (IS_ERR(sbi->meta_inode))
++ goto free_sb_buf;
++
++ if (get_valid_checkpoint(sbi))
++ goto free_meta_inode;
++
++ /* sanity checking of checkpoint */
++ if (sanity_check_ckpt(raw_super, sbi->ckpt))
++ goto free_cp;
++
++ sbi->total_valid_node_count =
++ le32_to_cpu(sbi->ckpt->valid_node_count);
++ sbi->total_valid_inode_count =
++ le32_to_cpu(sbi->ckpt->valid_inode_count);
++ sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count);
++ sbi->total_valid_block_count =
++ le64_to_cpu(sbi->ckpt->valid_block_count);
++ sbi->last_valid_block_count = sbi->total_valid_block_count;
++ sbi->alloc_valid_block_count = 0;
++ INIT_LIST_HEAD(&sbi->dir_inode_list);
++ spin_lock_init(&sbi->dir_inode_lock);
++
++ /* init super block */
++ if (!sb_set_blocksize(sb, sbi->blocksize))
++ goto free_cp;
++
++ init_orphan_info(sbi);
++
++ /* setup f2fs internal modules */
++ if (build_segment_manager(sbi))
++ goto free_sm;
++ if (build_node_manager(sbi))
++ goto free_nm;
++ if (build_gc_manager(sbi))
++ goto free_gc;
++
++ /* get an inode for node space */
++ sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
++ if (IS_ERR(sbi->node_inode))
++ goto free_gc;
++
++ /* if there are nt orphan nodes free them */
++ if (recover_orphan_inodes(sbi))
++ goto free_node_inode;
++
++ /* read root inode and dentry */
++ root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
++ if (IS_ERR(root))
++ goto free_node_inode;
++ if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size)
++ goto free_root_inode;
++
++ sb->s_root = d_make_root(root); /* allocate root dentry */
++ if (!sb->s_root)
++ goto free_root_inode;
++
++ /* recover fsynced data */
++ if (!test_opt(sbi, DISABLE_ROLL_FORWARD))
++ recover_fsync_data(sbi);
++
++ /* After POR, we can run background GC thread */
++ if (start_gc_thread(sbi))
++ goto fail;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ if (f2fs_proc_root) {
++ sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
++ if (f2fs_stat_init(sbi))
++ goto fail;
++ }
++#endif
++ return 0;
++fail:
++ stop_gc_thread(sbi);
++free_root_inode:
++ make_bad_inode(root);
++ iput(root);
++free_node_inode:
++ make_bad_inode(sbi->node_inode);
++ iput(sbi->node_inode);
++free_gc:
++ destroy_gc_manager(sbi);
++free_nm:
++ destroy_node_manager(sbi);
++free_sm:
++ destroy_segment_manager(sbi);
++free_cp:
++ kfree(sbi->ckpt);
++free_meta_inode:
++ make_bad_inode(sbi->meta_inode);
++ iput(sbi->meta_inode);
++free_sb_buf:
++ brelse(raw_super_buf);
++free_sbi:
++ kfree(sbi);
++ return -EINVAL;
++}
++
++static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
++ const char *dev_name, void *data)
++{
++ return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super);
++}
++
++static struct file_system_type f2fs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "f2fs",
++ .mount = f2fs_mount,
++ .kill_sb = kill_block_super,
++ .fs_flags = FS_REQUIRES_DEV,
++};
++
++static int init_inodecache(void)
++{
++ f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
++ sizeof(struct f2fs_inode_info), NULL);
++ if (f2fs_inode_cachep == NULL)
++ return -ENOMEM;
++ return 0;
++}
++
++static void destroy_inodecache(void)
++{
++ /*
++ * Make sure all delayed rcu free inodes are flushed before we
++ * destroy cache.
++ */
++ rcu_barrier();
++ kmem_cache_destroy(f2fs_inode_cachep);
++}
++
++static int __init init_f2fs_fs(void)
++{
++ if (init_inodecache())
++ goto fail;
++ if (create_node_manager_caches())
++ goto fail;
++ if (create_gc_caches())
++ goto fail;
++ if (create_checkpoint_caches())
++ goto fail;
++ if (register_filesystem(&f2fs_fs_type))
++ return -EBUSY;
++
++ f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
++ return 0;
++fail:
++ return -ENOMEM;
++}
++
++static void __exit exit_f2fs_fs(void)
++{
++ remove_proc_entry("fs/f2fs", NULL);
++ unregister_filesystem(&f2fs_fs_type);
++ destroy_checkpoint_caches();
++ destroy_gc_caches();
++ destroy_node_manager_caches();
++ destroy_inodecache();
++}
++
++module_init(init_f2fs_fs)
++module_exit(exit_f2fs_fs)
++
++MODULE_AUTHOR("Samsung Electronics's Praesto Team");
++MODULE_DESCRIPTION("Flash Friendly File System");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.7/0104-f2fs-add-checkpoint-operations.patch b/patches/linux-3.7/0104-f2fs-add-checkpoint-operations.patch
new file mode 100644
index 0000000..0bbb10b
--- /dev/null
+++ b/patches/linux-3.7/0104-f2fs-add-checkpoint-operations.patch
@@ -0,0 +1,833 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:03 +0000
+Subject: [PATCH] f2fs: add checkpoint operations
+
+This adds functions required by the checkpoint operations.
+
+Basically, f2fs adopts a roll-back model with checkpoint blocks written in the
+CP area. The checkpoint procedure includes as follows.
+
+- write_checkpoint()
+1. block_operations() freezes VFS calls.
+2. submit cached bios.
+3. flush_nat_entries() writes NAT pages updated by dirty NAT entries.
+4. flush_sit_entries() writes SIT pages updated by dirty SIT entries.
+5. do_checkpoint() writes,
+ - checkpoint block (#0)
+ - orphan inode blocks
+ - summary blocks made by active logs
+ - checkpoint block (copy of #0)
+6. unblock_opeations()
+
+In order to provide an address space for meta pages, f2fs_sb_info has a special
+inode, namely meta_inode. This patch also adds the address space operations for
+meta_inode.
+
+Signed-off-by: Chul Lee <chur.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/checkpoint.c | 795 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 795 insertions(+)
+ create mode 100644 fs/f2fs/checkpoint.c
+
+diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
+new file mode 100644
+index 0000000..a0601cc
+--- /dev/null
++++ b/fs/f2fs/checkpoint.c
+@@ -0,0 +1,795 @@
++/**
++ * fs/f2fs/checkpoint.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/bio.h>
++#include <linux/mpage.h>
++#include <linux/writeback.h>
++#include <linux/blkdev.h>
++#include <linux/f2fs_fs.h>
++#include <linux/pagevec.h>
++#include <linux/swap.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *orphan_entry_slab;
++static struct kmem_cache *inode_entry_slab;
++
++/**
++ * We guarantee no failure on the returned page.
++ */
++struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct page *page = NULL;
++repeat:
++ page = grab_cache_page(mapping, index);
++ if (!page) {
++ cond_resched();
++ goto repeat;
++ }
++
++ /* We wait writeback only inside grab_meta_page() */
++ wait_on_page_writeback(page);
++ SetPageUptodate(page);
++ return page;
++}
++
++/**
++ * We guarantee no failure on the returned page.
++ */
++struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct page *page;
++repeat:
++ page = grab_cache_page(mapping, index);
++ if (!page) {
++ cond_resched();
++ goto repeat;
++ }
++ if (f2fs_readpage(sbi, page, index, READ_SYNC)) {
++ f2fs_put_page(page, 1);
++ goto repeat;
++ }
++ mark_page_accessed(page);
++
++ /* We do not allow returning an errorneous page */
++ return page;
++}
++
++static int f2fs_write_meta_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int err;
++
++ wait_on_page_writeback(page);
++
++ err = write_meta_page(sbi, page, wbc);
++ if (err) {
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ }
++
++ dec_page_count(sbi, F2FS_DIRTY_META);
++
++ /* In this case, we should not unlock this page */
++ if (err != AOP_WRITEPAGE_ACTIVATE)
++ unlock_page(page);
++ return err;
++}
++
++static int f2fs_write_meta_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ struct block_device *bdev = sbi->sb->s_bdev;
++ long written;
++
++ if (wbc->for_kupdate)
++ return 0;
++
++ if (get_pages(sbi, F2FS_DIRTY_META) == 0)
++ return 0;
++
++ /* if mounting is failed, skip writing node pages */
++ mutex_lock(&sbi->cp_mutex);
++ written = sync_meta_pages(sbi, META, bio_get_nr_vecs(bdev));
++ mutex_unlock(&sbi->cp_mutex);
++ wbc->nr_to_write -= written;
++ return 0;
++}
++
++long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
++ long nr_to_write)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ pgoff_t index = 0, end = LONG_MAX;
++ struct pagevec pvec;
++ long nwritten = 0;
++ struct writeback_control wbc = {
++ .for_reclaim = 0,
++ };
++
++ pagevec_init(&pvec, 0);
++
++ while (index <= end) {
++ int i, nr_pages;
++ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++ PAGECACHE_TAG_DIRTY,
++ min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
++ if (nr_pages == 0)
++ break;
++
++ for (i = 0; i < nr_pages; i++) {
++ struct page *page = pvec.pages[i];
++ lock_page(page);
++ BUG_ON(page->mapping != mapping);
++ BUG_ON(!PageDirty(page));
++ clear_page_dirty_for_io(page);
++ f2fs_write_meta_page(page, &wbc);
++ if (nwritten++ >= nr_to_write)
++ break;
++ }
++ pagevec_release(&pvec);
++ cond_resched();
++ }
++
++ if (nwritten)
++ f2fs_submit_bio(sbi, type, nr_to_write == LONG_MAX);
++
++ return nwritten;
++}
++
++static int f2fs_set_meta_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ inc_page_count(sbi, F2FS_DIRTY_META);
++ F2FS_SET_SB_DIRT(sbi);
++ return 1;
++ }
++ return 0;
++}
++
++const struct address_space_operations f2fs_meta_aops = {
++ .writepage = f2fs_write_meta_page,
++ .writepages = f2fs_write_meta_pages,
++ .set_page_dirty = f2fs_set_meta_page_dirty,
++};
++
++int check_orphan_space(struct f2fs_sb_info *sbi)
++{
++ unsigned int max_orphans;
++ int err = 0;
++
++ /*
++ * considering 512 blocks in a segment 5 blocks are needed for cp
++ * and log segment summaries. Remaining blocks are used to keep
++ * orphan entries with the limitation one reserved segment
++ * for cp pack we can have max 1020*507 orphan entries
++ */
++ max_orphans = (sbi->blocks_per_seg - 5) * F2FS_ORPHANS_PER_BLOCK;
++ mutex_lock(&sbi->orphan_inode_mutex);
++ if (sbi->n_orphans >= max_orphans)
++ err = -ENOSPC;
++ mutex_unlock(&sbi->orphan_inode_mutex);
++ return err;
++}
++
++void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct list_head *head, *this;
++ struct orphan_inode_entry *new = NULL, *orphan = NULL;
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++ list_for_each(this, head) {
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++ if (orphan->ino == ino)
++ goto out;
++ if (orphan->ino > ino)
++ break;
++ orphan = NULL;
++ }
++retry:
++ new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
++ if (!new) {
++ cond_resched();
++ goto retry;
++ }
++ new->ino = ino;
++ INIT_LIST_HEAD(&new->list);
++
++ /* add new_oentry into list which is sorted by inode number */
++ if (orphan) {
++ struct orphan_inode_entry *prev;
++
++ /* get previous entry */
++ prev = list_entry(orphan->list.prev, typeof(*prev), list);
++ if (&prev->list != head)
++ /* insert new orphan inode entry */
++ list_add(&new->list, &prev->list);
++ else
++ list_add(&new->list, head);
++ } else {
++ list_add_tail(&new->list, head);
++ }
++ sbi->n_orphans++;
++out:
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct list_head *this, *next, *head;
++ struct orphan_inode_entry *orphan;
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++ list_for_each_safe(this, next, head) {
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++ if (orphan->ino == ino) {
++ list_del(&orphan->list);
++ kmem_cache_free(orphan_entry_slab, orphan);
++ sbi->n_orphans--;
++ break;
++ }
++ }
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
++{
++ struct inode *inode = f2fs_iget(sbi->sb, ino);
++ BUG_ON(IS_ERR(inode));
++ clear_nlink(inode);
++
++ /* truncate all the data during iput */
++ iput(inode);
++}
++
++int recover_orphan_inodes(struct f2fs_sb_info *sbi)
++{
++ block_t start_blk, orphan_blkaddr, i, j;
++
++ if (!(F2FS_CKPT(sbi)->ckpt_flags & CP_ORPHAN_PRESENT_FLAG))
++ return 0;
++
++ sbi->por_doing = 1;
++ start_blk = __start_cp_addr(sbi) + 1;
++ orphan_blkaddr = __start_sum_addr(sbi) - 1;
++
++ for (i = 0; i < orphan_blkaddr; i++) {
++ struct page *page = get_meta_page(sbi, start_blk + i);
++ struct f2fs_orphan_block *orphan_blk;
++
++ orphan_blk = (struct f2fs_orphan_block *)page_address(page);
++ for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
++ nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
++ recover_orphan_inode(sbi, ino);
++ }
++ f2fs_put_page(page, 1);
++ }
++ /* clear Orphan Flag */
++ F2FS_CKPT(sbi)->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
++ sbi->por_doing = 0;
++ return 0;
++}
++
++static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ struct list_head *head, *this, *next;
++ struct f2fs_orphan_block *orphan_blk = NULL;
++ struct page *page = NULL;
++ unsigned int nentries = 0;
++ unsigned short index = 1;
++ unsigned short orphan_blocks;
++
++ orphan_blocks = (unsigned short)((sbi->n_orphans +
++ (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
++
++ mutex_lock(&sbi->orphan_inode_mutex);
++ head = &sbi->orphan_inode_list;
++
++ /* loop for each orphan inode entry and write them in Jornal block */
++ list_for_each_safe(this, next, head) {
++ struct orphan_inode_entry *orphan;
++
++ orphan = list_entry(this, struct orphan_inode_entry, list);
++
++ if (nentries == F2FS_ORPHANS_PER_BLOCK) {
++ /*
++ * an orphan block is full of 1020 entries,
++ * then we need to flush current orphan blocks
++ * and bring another one in memory
++ */
++ orphan_blk->blk_addr = cpu_to_le16(index);
++ orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
++ orphan_blk->entry_count = cpu_to_le32(nentries);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++ index++;
++ start_blk++;
++ nentries = 0;
++ page = NULL;
++ }
++ if (page)
++ goto page_exist;
++
++ page = grab_meta_page(sbi, start_blk);
++ orphan_blk = (struct f2fs_orphan_block *)page_address(page);
++ memset(orphan_blk, 0, sizeof(*orphan_blk));
++page_exist:
++ orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
++ }
++ if (!page)
++ goto end;
++
++ orphan_blk->blk_addr = cpu_to_le16(index);
++ orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
++ orphan_blk->entry_count = cpu_to_le32(nentries);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++end:
++ mutex_unlock(&sbi->orphan_inode_mutex);
++}
++
++static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
++ block_t cp_addr, unsigned long long *version)
++{
++ struct page *cp_page_1, *cp_page_2 = NULL;
++ unsigned long blk_size = sbi->blocksize;
++ struct f2fs_checkpoint *cp_block;
++ unsigned long long cur_version = 0, pre_version = 0;
++ unsigned int crc = 0;
++ size_t crc_offset;
++
++ /* Read the 1st cp block in this CP pack */
++ cp_page_1 = get_meta_page(sbi, cp_addr);
++
++ /* get the version number */
++ cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1);
++ crc_offset = le32_to_cpu(cp_block->checksum_offset);
++ if (crc_offset >= blk_size)
++ goto invalid_cp1;
++
++ crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
++ if (!f2fs_crc_valid(crc, cp_block, crc_offset))
++ goto invalid_cp1;
++
++ pre_version = le64_to_cpu(cp_block->checkpoint_ver);
++
++ /* Read the 2nd cp block in this CP pack */
++ cp_addr += le64_to_cpu(cp_block->cp_pack_total_block_count) - 1;
++ cp_page_2 = get_meta_page(sbi, cp_addr);
++
++ cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
++ crc_offset = le32_to_cpu(cp_block->checksum_offset);
++ if (crc_offset >= blk_size)
++ goto invalid_cp2;
++
++ crc = *(unsigned int *)((unsigned char *)cp_block + crc_offset);
++ if (!f2fs_crc_valid(crc, cp_block, crc_offset))
++ goto invalid_cp2;
++
++ cur_version = le64_to_cpu(cp_block->checkpoint_ver);
++
++ if (cur_version == pre_version) {
++ *version = cur_version;
++ f2fs_put_page(cp_page_2, 1);
++ return cp_page_1;
++ }
++invalid_cp2:
++ f2fs_put_page(cp_page_2, 1);
++invalid_cp1:
++ f2fs_put_page(cp_page_1, 1);
++ return NULL;
++}
++
++int get_valid_checkpoint(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_checkpoint *cp_block;
++ struct f2fs_super_block *fsb = sbi->raw_super;
++ struct page *cp1, *cp2, *cur_page;
++ unsigned long blk_size = sbi->blocksize;
++ unsigned long long cp1_version = 0, cp2_version = 0;
++ unsigned long long cp_start_blk_no;
++
++ sbi->ckpt = kzalloc(blk_size, GFP_KERNEL);
++ if (!sbi->ckpt)
++ return -ENOMEM;
++ /*
++ * Finding out valid cp block involves read both
++ * sets( cp pack1 and cp pack 2)
++ */
++ cp_start_blk_no = le32_to_cpu(fsb->start_segment_checkpoint);
++ cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
++
++ /* The second checkpoint pack should start at the next segment */
++ cp_start_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
++ cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
++
++ if (cp1 && cp2) {
++ if (ver_after(cp2_version, cp1_version))
++ cur_page = cp2;
++ else
++ cur_page = cp1;
++ } else if (cp1) {
++ cur_page = cp1;
++ } else if (cp2) {
++ cur_page = cp2;
++ } else {
++ goto fail_no_cp;
++ }
++
++ cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
++ memcpy(sbi->ckpt, cp_block, blk_size);
++
++ f2fs_put_page(cp1, 1);
++ f2fs_put_page(cp2, 1);
++ return 0;
++
++fail_no_cp:
++ kfree(sbi->ckpt);
++ return -EINVAL;
++}
++
++void set_dirty_dir_page(struct inode *inode, struct page *page)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct list_head *head = &sbi->dir_inode_list;
++ struct dir_inode_entry *new;
++ struct list_head *this;
++
++ if (!S_ISDIR(inode->i_mode))
++ return;
++retry:
++ new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
++ if (!new) {
++ cond_resched();
++ goto retry;
++ }
++ new->inode = inode;
++ INIT_LIST_HEAD(&new->list);
++
++ spin_lock(&sbi->dir_inode_lock);
++ list_for_each(this, head) {
++ struct dir_inode_entry *entry;
++ entry = list_entry(this, struct dir_inode_entry, list);
++ if (entry->inode == inode) {
++ kmem_cache_free(inode_entry_slab, new);
++ goto out;
++ }
++ }
++ list_add_tail(&new->list, head);
++ sbi->n_dirty_dirs++;
++
++ BUG_ON(!S_ISDIR(inode->i_mode));
++out:
++ inc_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_inc_dirty_dents(inode);
++ SetPagePrivate(page);
++
++ spin_unlock(&sbi->dir_inode_lock);
++}
++
++void remove_dirty_dir_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct list_head *head = &sbi->dir_inode_list;
++ struct list_head *this;
++
++ if (!S_ISDIR(inode->i_mode))
++ return;
++
++ spin_lock(&sbi->dir_inode_lock);
++ if (atomic_read(&F2FS_I(inode)->dirty_dents))
++ goto out;
++
++ list_for_each(this, head) {
++ struct dir_inode_entry *entry;
++ entry = list_entry(this, struct dir_inode_entry, list);
++ if (entry->inode == inode) {
++ list_del(&entry->list);
++ kmem_cache_free(inode_entry_slab, entry);
++ sbi->n_dirty_dirs--;
++ break;
++ }
++ }
++out:
++ spin_unlock(&sbi->dir_inode_lock);
++}
++
++void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi)
++{
++ struct list_head *head = &sbi->dir_inode_list;
++ struct dir_inode_entry *entry;
++ struct inode *inode;
++retry:
++ spin_lock(&sbi->dir_inode_lock);
++ if (list_empty(head)) {
++ spin_unlock(&sbi->dir_inode_lock);
++ return;
++ }
++ entry = list_entry(head->next, struct dir_inode_entry, list);
++ inode = igrab(entry->inode);
++ spin_unlock(&sbi->dir_inode_lock);
++ if (inode) {
++ filemap_flush(inode->i_mapping);
++ iput(inode);
++ } else {
++ /*
++ * We should submit bio, since it exists several
++ * wribacking dentry pages in the freeing inode.
++ */
++ f2fs_submit_bio(sbi, DATA, true);
++ }
++ goto retry;
++}
++
++/**
++ * Freeze all the FS-operations for checkpoint.
++ */
++void block_operations(struct f2fs_sb_info *sbi)
++{
++ int t;
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ /* Stop renaming operation */
++ mutex_lock_op(sbi, RENAME);
++ mutex_lock_op(sbi, DENTRY_OPS);
++
++retry_dents:
++ /* write all the dirty dentry pages */
++ sync_dirty_dir_inodes(sbi);
++
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
++ mutex_unlock_op(sbi, DATA_WRITE);
++ goto retry_dents;
++ }
++
++ /* block all the operations */
++ for (t = DATA_NEW; t <= NODE_TRUNC; t++)
++ mutex_lock_op(sbi, t);
++
++ mutex_lock(&sbi->write_inode);
++
++ /*
++ * POR: we should ensure that there is no dirty node pages
++ * until finishing nat/sit flush.
++ */
++retry:
++ sync_node_pages(sbi, 0, &wbc);
++
++ mutex_lock_op(sbi, NODE_WRITE);
++
++ if (get_pages(sbi, F2FS_DIRTY_NODES)) {
++ mutex_unlock_op(sbi, NODE_WRITE);
++ goto retry;
++ }
++ mutex_unlock(&sbi->write_inode);
++}
++
++static void unblock_operations(struct f2fs_sb_info *sbi)
++{
++ int t;
++ for (t = NODE_WRITE; t >= RENAME; t--)
++ mutex_unlock_op(sbi, t);
++}
++
++static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ nid_t last_nid = 0;
++ int nat_upd_blkoff[3];
++ block_t start_blk;
++ struct page *cp_page;
++ unsigned int data_sum_blocks, orphan_blocks;
++ void *kaddr;
++ __u32 crc32 = 0;
++ int i;
++
++ /* Flush all the NAT/SIT pages */
++ while (get_pages(sbi, F2FS_DIRTY_META))
++ sync_meta_pages(sbi, META, LONG_MAX);
++
++ next_free_nid(sbi, &last_nid);
++
++ /*
++ * modify checkpoint
++ * version number is already updated
++ */
++ ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
++ ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
++ ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
++ for (i = 0; i < 3; i++) {
++ ckpt->cur_node_segno[i] =
++ cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
++ ckpt->cur_node_blkoff[i] =
++ cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE));
++ nat_upd_blkoff[i] = NM_I(sbi)->nat_upd_blkoff[i];
++ ckpt->nat_upd_blkoff[i] = cpu_to_le16(nat_upd_blkoff[i]);
++ ckpt->alloc_type[i + CURSEG_HOT_NODE] =
++ curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
++ }
++ for (i = 0; i < 3; i++) {
++ ckpt->cur_data_segno[i] =
++ cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
++ ckpt->cur_data_blkoff[i] =
++ cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA));
++ ckpt->alloc_type[i + CURSEG_HOT_DATA] =
++ curseg_alloc_type(sbi, i + CURSEG_HOT_DATA);
++ }
++
++ ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
++ ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
++ ckpt->next_free_nid = cpu_to_le32(last_nid);
++
++ /* 2 cp + n data seg summary + orphan inode blocks */
++ data_sum_blocks = npages_for_summary_flush(sbi);
++ if (data_sum_blocks < 3)
++ ckpt->ckpt_flags |= CP_COMPACT_SUM_FLAG;
++ else
++ ckpt->ckpt_flags &= (~CP_COMPACT_SUM_FLAG);
++
++ orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
++ / F2FS_ORPHANS_PER_BLOCK;
++ ckpt->cp_pack_start_sum = 1 + orphan_blocks;
++ ckpt->cp_pack_total_block_count = 2 + data_sum_blocks + orphan_blocks;
++
++ if (is_umount) {
++ ckpt->ckpt_flags |= CP_UMOUNT_FLAG;
++ ckpt->cp_pack_total_block_count += NR_CURSEG_NODE_TYPE;
++ } else {
++ ckpt->ckpt_flags &= (~CP_UMOUNT_FLAG);
++ }
++
++ if (sbi->n_orphans)
++ ckpt->ckpt_flags |= CP_ORPHAN_PRESENT_FLAG;
++ else
++ ckpt->ckpt_flags &= (~CP_ORPHAN_PRESENT_FLAG);
++
++ /* update SIT/NAT bitmap */
++ get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
++ get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
++
++ crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
++ *(__u32 *)((unsigned char *)ckpt +
++ le32_to_cpu(ckpt->checksum_offset))
++ = cpu_to_le32(crc32);
++
++ start_blk = __start_cp_addr(sbi);
++
++ /* write out checkpoint buffer at block 0 */
++ cp_page = grab_meta_page(sbi, start_blk++);
++ kaddr = page_address(cp_page);
++ memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
++ set_page_dirty(cp_page);
++ f2fs_put_page(cp_page, 1);
++
++ if (sbi->n_orphans) {
++ write_orphan_inodes(sbi, start_blk);
++ start_blk += orphan_blocks;
++ }
++
++ write_data_summaries(sbi, start_blk);
++ start_blk += data_sum_blocks;
++ if (is_umount) {
++ write_node_summaries(sbi, start_blk);
++ start_blk += NR_CURSEG_NODE_TYPE;
++ }
++
++ /* writeout checkpoint block */
++ cp_page = grab_meta_page(sbi, start_blk);
++ kaddr = page_address(cp_page);
++ memcpy(kaddr, ckpt, (1 << sbi->log_blocksize));
++ set_page_dirty(cp_page);
++ f2fs_put_page(cp_page, 1);
++
++ /* wait for previous submitted node/meta pages writeback */
++ while (get_pages(sbi, F2FS_WRITEBACK))
++ congestion_wait(BLK_RW_ASYNC, HZ / 50);
++
++ filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
++ filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
++
++ /* update user_block_counts */
++ sbi->last_valid_block_count = sbi->total_valid_block_count;
++ sbi->alloc_valid_block_count = 0;
++
++ /* Here, we only have one bio having CP pack */
++ if (sbi->ckpt->ckpt_flags & CP_ERROR_FLAG)
++ sbi->sb->s_flags |= MS_RDONLY;
++ else
++ sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
++
++ clear_prefree_segments(sbi);
++ F2FS_RESET_SB_DIRT(sbi);
++}
++
++/**
++ * We guarantee that this checkpoint procedure should not fail.
++ */
++void write_checkpoint(struct f2fs_sb_info *sbi, bool blocked, bool is_umount)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ unsigned long long ckpt_ver;
++
++ if (!blocked) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ }
++
++ f2fs_submit_bio(sbi, DATA, true);
++ f2fs_submit_bio(sbi, NODE, true);
++ f2fs_submit_bio(sbi, META, true);
++
++ /*
++ * update checkpoint pack index
++ * Increase the version number so that
++ * SIT entries and seg summaries are written at correct place
++ */
++ ckpt_ver = le64_to_cpu(ckpt->checkpoint_ver);
++ ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
++
++ /* write cached NAT/SIT entries to NAT/SIT area */
++ flush_nat_entries(sbi);
++ flush_sit_entries(sbi);
++
++ reset_victim_segmap(sbi);
++
++ /* unlock all the fs_lock[] in do_checkpoint() */
++ do_checkpoint(sbi, is_umount);
++
++ unblock_operations(sbi);
++ mutex_unlock(&sbi->cp_mutex);
++}
++
++void init_orphan_info(struct f2fs_sb_info *sbi)
++{
++ mutex_init(&sbi->orphan_inode_mutex);
++ INIT_LIST_HEAD(&sbi->orphan_inode_list);
++ sbi->n_orphans = 0;
++}
++
++int create_checkpoint_caches(void)
++{
++ orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
++ sizeof(struct orphan_inode_entry), NULL);
++ if (unlikely(!orphan_entry_slab))
++ return -ENOMEM;
++ inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry",
++ sizeof(struct dir_inode_entry), NULL);
++ if (unlikely(!inode_entry_slab)) {
++ kmem_cache_destroy(orphan_entry_slab);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void destroy_checkpoint_caches(void)
++{
++ kmem_cache_destroy(orphan_entry_slab);
++ kmem_cache_destroy(inode_entry_slab);
++}
diff --git a/patches/linux-3.7/0105-f2fs-add-node-operations.patch b/patches/linux-3.7/0105-f2fs-add-node-operations.patch
new file mode 100644
index 0000000..f8f47b6
--- /dev/null
+++ b/patches/linux-3.7/0105-f2fs-add-node-operations.patch
@@ -0,0 +1,1823 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:19 +0000
+Subject: [PATCH] f2fs: add node operations
+
+This adds specific functions to manage NAT pages, a cache for NAT entries, free
+nids, direct/indirect node blocks for indexing data, and address space for node
+pages.
+
+- The key information of an NAT entry consists of a node id and a block address.
+
+- An NAT page is composed of block addresses covered by a certain range of NAT
+ entries, which is maintained by the address space of meta_inode.
+
+- A radix tree structure is used to cache NAT entries. The index for the tree
+ is a node id.
+
+- When there is no free nid, F2FS should scan NAT entries to find new one. In
+ order to avoid scanning frequently, F2FS manages a list containing a number of
+ free nids in memory. Only when free nids in the list are exhausted, scanning
+ process, build_free_nids(), is triggered.
+
+- F2FS has direct and indirect node blocks for indexing data. This patch adds
+ fuctions related to the node block management such as getting, allocating, and
+ truncating node blocks to index data.
+
+- In order to cache node blocks in memory, F2FS has a node_inode with an address
+ space for node pages. This patch also adds the address space operations for
+ node_inode.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/node.c | 1782 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 1782 insertions(+)
+ create mode 100644 fs/f2fs/node.c
+
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+new file mode 100644
+index 0000000..df69058
+--- /dev/null
++++ b/fs/f2fs/node.c
+@@ -0,0 +1,1782 @@
++/**
++ * fs/f2fs/node.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/mpage.h>
++#include <linux/backing-dev.h>
++#include <linux/blkdev.h>
++#include <linux/pagevec.h>
++#include <linux/swap.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *nat_entry_slab;
++static struct kmem_cache *free_nid_slab;
++
++static void clear_node_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ unsigned int long flags;
++
++ if (PageDirty(page)) {
++ spin_lock_irqsave(&mapping->tree_lock, flags);
++ radix_tree_tag_clear(&mapping->page_tree,
++ page_index(page),
++ PAGECACHE_TAG_DIRTY);
++ spin_unlock_irqrestore(&mapping->tree_lock, flags);
++
++ clear_page_dirty_for_io(page);
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ }
++ ClearPageUptodate(page);
++}
++
++static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ pgoff_t index = current_nat_addr(sbi, nid);
++ return get_meta_page(sbi, index);
++}
++
++static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct page *src_page;
++ struct page *dst_page;
++ pgoff_t src_off;
++ pgoff_t dst_off;
++ void *src_addr;
++ void *dst_addr;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ src_off = current_nat_addr(sbi, nid);
++ dst_off = next_nat_addr(sbi, src_off);
++
++ /* get current nat block page with lock */
++ src_page = get_meta_page(sbi, src_off);
++
++ /* Dirty src_page means that it is already the new target NAT page. */
++ if (PageDirty(src_page))
++ return src_page;
++
++ dst_page = grab_meta_page(sbi, dst_off);
++
++ src_addr = page_address(src_page);
++ dst_addr = page_address(dst_page);
++ memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
++ set_page_dirty(dst_page);
++ f2fs_put_page(src_page, 1);
++
++ set_to_next_nat(nm_i, nid);
++
++ return dst_page;
++}
++
++/**
++ * Readahead NAT pages
++ */
++static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid)
++{
++ struct address_space *mapping = sbi->meta_inode->i_mapping;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct page *page;
++ pgoff_t index;
++ int i;
++
++ for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) {
++ if (nid >= nm_i->max_nid)
++ nid = 0;
++ index = current_nat_addr(sbi, nid);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ continue;
++ if (f2fs_readpage(sbi, page, index, READ)) {
++ f2fs_put_page(page, 1);
++ continue;
++ }
++ page_cache_release(page);
++ }
++}
++
++static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
++{
++ return radix_tree_lookup(&nm_i->nat_root, n);
++}
++
++static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
++ nid_t start, unsigned int nr, struct nat_entry **ep)
++{
++ return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
++}
++
++static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
++{
++ list_del(&e->list);
++ radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
++ nm_i->nat_cnt--;
++ kmem_cache_free(nat_entry_slab, e);
++}
++
++int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct nat_entry *e;
++ int is_cp = 1;
++
++ read_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (e && !e->checkpointed)
++ is_cp = 0;
++ read_unlock(&nm_i->nat_tree_lock);
++ return is_cp;
++}
++
++static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct nat_entry *new;
++
++ new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC);
++ if (!new)
++ return NULL;
++ if (radix_tree_insert(&nm_i->nat_root, nid, new)) {
++ kmem_cache_free(nat_entry_slab, new);
++ return NULL;
++ }
++ memset(new, 0, sizeof(struct nat_entry));
++ nat_set_nid(new, nid);
++ list_add_tail(&new->list, &nm_i->nat_entries);
++ nm_i->nat_cnt++;
++ return new;
++}
++
++static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid,
++ struct f2fs_nat_entry *ne)
++{
++ struct nat_entry *e;
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (!e) {
++ e = grab_nat_entry(nm_i, nid);
++ if (!e) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
++ nat_set_ino(e, le32_to_cpu(ne->ino));
++ nat_set_version(e, ne->version);
++ e->checkpointed = true;
++ }
++ write_unlock(&nm_i->nat_tree_lock);
++}
++
++static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
++ block_t new_blkaddr)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct nat_entry *e;
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, ni->nid);
++ if (!e) {
++ e = grab_nat_entry(nm_i, ni->nid);
++ if (!e) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ e->ni = *ni;
++ e->checkpointed = true;
++ BUG_ON(ni->blk_addr == NEW_ADDR);
++ } else if (new_blkaddr == NEW_ADDR) {
++ /*
++ * when nid is reallocated,
++ * previous nat entry can be remained in nat cache.
++ * So, reinitialize it with new information.
++ */
++ e->ni = *ni;
++ BUG_ON(ni->blk_addr != NULL_ADDR);
++ }
++
++ if (new_blkaddr == NEW_ADDR)
++ e->checkpointed = false;
++
++ /* sanity check */
++ BUG_ON(nat_get_blkaddr(e) != ni->blk_addr);
++ BUG_ON(nat_get_blkaddr(e) == NULL_ADDR &&
++ new_blkaddr == NULL_ADDR);
++ BUG_ON(nat_get_blkaddr(e) == NEW_ADDR &&
++ new_blkaddr == NEW_ADDR);
++ BUG_ON(nat_get_blkaddr(e) != NEW_ADDR &&
++ nat_get_blkaddr(e) != NULL_ADDR &&
++ new_blkaddr == NEW_ADDR);
++
++ /* increament version no as node is removed */
++ if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
++ unsigned char version = nat_get_version(e);
++ nat_set_version(e, inc_node_version(version));
++ }
++
++ /* change address */
++ nat_set_blkaddr(e, new_blkaddr);
++ __set_nat_cache_dirty(nm_i, e);
++ write_unlock(&nm_i->nat_tree_lock);
++}
++
++static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++
++ if (nm_i->nat_cnt < 2 * NM_WOUT_THRESHOLD)
++ return 0;
++
++ write_lock(&nm_i->nat_tree_lock);
++ while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
++ struct nat_entry *ne;
++ ne = list_first_entry(&nm_i->nat_entries,
++ struct nat_entry, list);
++ __del_from_nat_cache(nm_i, ne);
++ nr_shrink--;
++ }
++ write_unlock(&nm_i->nat_tree_lock);
++ return nr_shrink;
++}
++
++/**
++ * This function returns always success
++ */
++void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ nid_t start_nid = START_NID(nid);
++ struct f2fs_nat_block *nat_blk;
++ struct page *page = NULL;
++ struct f2fs_nat_entry ne;
++ struct nat_entry *e;
++ int i;
++
++ ni->nid = nid;
++
++ /* Check nat cache */
++ read_lock(&nm_i->nat_tree_lock);
++ e = __lookup_nat_cache(nm_i, nid);
++ if (e) {
++ ni->ino = nat_get_ino(e);
++ ni->blk_addr = nat_get_blkaddr(e);
++ ni->version = nat_get_version(e);
++ }
++ read_unlock(&nm_i->nat_tree_lock);
++ if (e)
++ return;
++
++ /* Check current segment summary */
++ mutex_lock(&curseg->curseg_mutex);
++ i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
++ if (i >= 0) {
++ ne = nat_in_journal(sum, i);
++ node_info_from_raw_nat(ni, &ne);
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++ if (i >= 0)
++ goto cache;
++
++ /* Fill node_info from nat page */
++ page = get_current_nat_page(sbi, start_nid);
++ nat_blk = (struct f2fs_nat_block *)page_address(page);
++ ne = nat_blk->entries[nid - start_nid];
++ node_info_from_raw_nat(ni, &ne);
++ f2fs_put_page(page, 1);
++cache:
++ /* cache nat entry */
++ cache_nat_entry(NM_I(sbi), nid, &ne);
++}
++
++/**
++ * The maximum depth is four.
++ * Offset[0] will have raw inode offset.
++ */
++static int get_node_path(long block, int offset[4], unsigned int noffset[4])
++{
++ const long direct_index = ADDRS_PER_INODE;
++ const long direct_blks = ADDRS_PER_BLOCK;
++ const long dptrs_per_blk = NIDS_PER_BLOCK;
++ const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
++ const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
++ int n = 0;
++ int level = 0;
++
++ noffset[0] = 0;
++
++ if (block < direct_index) {
++ offset[n++] = block;
++ level = 0;
++ goto got;
++ }
++ block -= direct_index;
++ if (block < direct_blks) {
++ offset[n++] = NODE_DIR1_BLOCK;
++ noffset[n] = 1;
++ offset[n++] = block;
++ level = 1;
++ goto got;
++ }
++ block -= direct_blks;
++ if (block < direct_blks) {
++ offset[n++] = NODE_DIR2_BLOCK;
++ noffset[n] = 2;
++ offset[n++] = block;
++ level = 1;
++ goto got;
++ }
++ block -= direct_blks;
++ if (block < indirect_blks) {
++ offset[n++] = NODE_IND1_BLOCK;
++ noffset[n] = 3;
++ offset[n++] = block / direct_blks;
++ noffset[n] = 4 + offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 2;
++ goto got;
++ }
++ block -= indirect_blks;
++ if (block < indirect_blks) {
++ offset[n++] = NODE_IND2_BLOCK;
++ noffset[n] = 4 + dptrs_per_blk;
++ offset[n++] = block / direct_blks;
++ noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 2;
++ goto got;
++ }
++ block -= indirect_blks;
++ if (block < dindirect_blks) {
++ offset[n++] = NODE_DIND_BLOCK;
++ noffset[n] = 5 + (dptrs_per_blk * 2);
++ offset[n++] = block / indirect_blks;
++ noffset[n] = 6 + (dptrs_per_blk * 2) +
++ offset[n - 1] * (dptrs_per_blk + 1);
++ offset[n++] = (block / direct_blks) % dptrs_per_blk;
++ noffset[n] = 7 + (dptrs_per_blk * 2) +
++ offset[n - 2] * (dptrs_per_blk + 1) +
++ offset[n - 1];
++ offset[n++] = block % direct_blks;
++ level = 3;
++ goto got;
++ } else {
++ BUG();
++ }
++got:
++ return level;
++}
++
++/*
++ * Caller should call f2fs_put_dnode(dn).
++ */
++int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *npage[4];
++ struct page *parent;
++ int offset[4];
++ unsigned int noffset[4];
++ nid_t nids[4];
++ int level, i;
++ int err = 0;
++
++ level = get_node_path(index, offset, noffset);
++
++ nids[0] = dn->inode->i_ino;
++ npage[0] = get_node_page(sbi, nids[0]);
++ if (IS_ERR(npage[0]))
++ return PTR_ERR(npage[0]);
++
++ parent = npage[0];
++ nids[1] = get_nid(parent, offset[0], true);
++ dn->inode_page = npage[0];
++ dn->inode_page_locked = true;
++
++ /* get indirect or direct nodes */
++ for (i = 1; i <= level; i++) {
++ bool done = false;
++
++ if (!nids[i] && !ro) {
++ mutex_lock_op(sbi, NODE_NEW);
++
++ /* alloc new node */
++ if (!alloc_nid(sbi, &(nids[i]))) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = -ENOSPC;
++ goto release_pages;
++ }
++
++ dn->nid = nids[i];
++ npage[i] = new_node_page(dn, noffset[i]);
++ if (IS_ERR(npage[i])) {
++ alloc_nid_failed(sbi, nids[i]);
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = PTR_ERR(npage[i]);
++ goto release_pages;
++ }
++
++ set_nid(parent, offset[i - 1], nids[i], i == 1);
++ alloc_nid_done(sbi, nids[i]);
++ mutex_unlock_op(sbi, NODE_NEW);
++ done = true;
++ } else if (ro && i == level && level > 1) {
++ npage[i] = get_node_page_ra(parent, offset[i - 1]);
++ if (IS_ERR(npage[i])) {
++ err = PTR_ERR(npage[i]);
++ goto release_pages;
++ }
++ done = true;
++ }
++ if (i == 1) {
++ dn->inode_page_locked = false;
++ unlock_page(parent);
++ } else {
++ f2fs_put_page(parent, 1);
++ }
++
++ if (!done) {
++ npage[i] = get_node_page(sbi, nids[i]);
++ if (IS_ERR(npage[i])) {
++ err = PTR_ERR(npage[i]);
++ f2fs_put_page(npage[0], 0);
++ goto release_out;
++ }
++ }
++ if (i < level) {
++ parent = npage[i];
++ nids[i + 1] = get_nid(parent, offset[i], false);
++ }
++ }
++ dn->nid = nids[level];
++ dn->ofs_in_node = offset[level];
++ dn->node_page = npage[level];
++ dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
++ return 0;
++
++release_pages:
++ f2fs_put_page(parent, 1);
++ if (i > 1)
++ f2fs_put_page(npage[0], 0);
++release_out:
++ dn->inode_page = NULL;
++ dn->node_page = NULL;
++ return err;
++}
++
++static void truncate_node(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct node_info ni;
++
++ get_node_info(sbi, dn->nid, &ni);
++ BUG_ON(ni.blk_addr == NULL_ADDR);
++
++ if (ni.blk_addr != NULL_ADDR)
++ invalidate_blocks(sbi, ni.blk_addr);
++
++ /* Deallocate node address */
++ dec_valid_node_count(sbi, dn->inode, 1);
++ set_node_addr(sbi, &ni, NULL_ADDR);
++
++ if (dn->nid == dn->inode->i_ino) {
++ remove_orphan_inode(sbi, dn->nid);
++ dec_valid_inode_count(sbi);
++ } else {
++ sync_inode_page(dn);
++ }
++
++ clear_node_page_dirty(dn->node_page);
++ F2FS_SET_SB_DIRT(sbi);
++
++ f2fs_put_page(dn->node_page, 1);
++ dn->node_page = NULL;
++}
++
++static int truncate_dnode(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *page;
++
++ if (dn->nid == 0)
++ return 1;
++
++ /* get direct node */
++ page = get_node_page(sbi, dn->nid);
++ if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
++ return 1;
++ else if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ /* Make dnode_of_data for parameter */
++ dn->node_page = page;
++ dn->ofs_in_node = 0;
++ truncate_data_blocks(dn);
++ truncate_node(dn);
++ return 1;
++}
++
++static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
++ int ofs, int depth)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct dnode_of_data rdn = *dn;
++ struct page *page;
++ struct f2fs_node *rn;
++ nid_t child_nid;
++ unsigned int child_nofs;
++ int freed = 0;
++ int i, ret;
++
++ if (dn->nid == 0)
++ return NIDS_PER_BLOCK + 1;
++
++ page = get_node_page(sbi, dn->nid);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ rn = (struct f2fs_node *)page_address(page);
++ if (depth < 3) {
++ for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
++ child_nid = le32_to_cpu(rn->in.nid[i]);
++ if (child_nid == 0)
++ continue;
++ rdn.nid = child_nid;
++ ret = truncate_dnode(&rdn);
++ if (ret < 0)
++ goto out_err;
++ set_nid(page, i, 0, false);
++ }
++ } else {
++ child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
++ for (i = ofs; i < NIDS_PER_BLOCK; i++) {
++ child_nid = le32_to_cpu(rn->in.nid[i]);
++ if (child_nid == 0) {
++ child_nofs += NIDS_PER_BLOCK + 1;
++ continue;
++ }
++ rdn.nid = child_nid;
++ ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
++ if (ret == (NIDS_PER_BLOCK + 1)) {
++ set_nid(page, i, 0, false);
++ child_nofs += ret;
++ } else if (ret < 0 && ret != -ENOENT) {
++ goto out_err;
++ }
++ }
++ freed = child_nofs;
++ }
++
++ if (!ofs) {
++ /* remove current indirect node */
++ dn->node_page = page;
++ truncate_node(dn);
++ freed++;
++ } else {
++ f2fs_put_page(page, 1);
++ }
++ return freed;
++
++out_err:
++ f2fs_put_page(page, 1);
++ return ret;
++}
++
++static int truncate_partial_nodes(struct dnode_of_data *dn,
++ struct f2fs_inode *ri, int *offset, int depth)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct page *pages[2];
++ nid_t nid[3];
++ nid_t child_nid;
++ int err = 0;
++ int i;
++ int idx = depth - 2;
++
++ nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
++ if (!nid[0])
++ return 0;
++
++ /* get indirect nodes in the path */
++ for (i = 0; i < depth - 1; i++) {
++ /* refernece count'll be increased */
++ pages[i] = get_node_page(sbi, nid[i]);
++ if (IS_ERR(pages[i])) {
++ depth = i + 1;
++ err = PTR_ERR(pages[i]);
++ goto fail;
++ }
++ nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
++ }
++
++ /* free direct nodes linked to a partial indirect node */
++ for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) {
++ child_nid = get_nid(pages[idx], i, false);
++ if (!child_nid)
++ continue;
++ dn->nid = child_nid;
++ err = truncate_dnode(dn);
++ if (err < 0)
++ goto fail;
++ set_nid(pages[idx], i, 0, false);
++ }
++
++ if (offset[depth - 1] == 0) {
++ dn->node_page = pages[idx];
++ dn->nid = nid[idx];
++ truncate_node(dn);
++ } else {
++ f2fs_put_page(pages[idx], 1);
++ }
++ offset[idx]++;
++ offset[depth - 1] = 0;
++fail:
++ for (i = depth - 3; i >= 0; i--)
++ f2fs_put_page(pages[i], 1);
++ return err;
++}
++
++/**
++ * All the block addresses of data and nodes should be nullified.
++ */
++int truncate_inode_blocks(struct inode *inode, pgoff_t from)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int err = 0, cont = 1;
++ int level, offset[4], noffset[4];
++ unsigned int nofs;
++ struct f2fs_node *rn;
++ struct dnode_of_data dn;
++ struct page *page;
++
++ level = get_node_path(from, offset, noffset);
++
++ page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++
++ set_new_dnode(&dn, inode, page, NULL, 0);
++ unlock_page(page);
++
++ rn = page_address(page);
++ switch (level) {
++ case 0:
++ case 1:
++ nofs = noffset[1];
++ break;
++ case 2:
++ nofs = noffset[1];
++ if (!offset[level - 1])
++ goto skip_partial;
++ err = truncate_partial_nodes(&dn, &rn->i, offset, level);
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ nofs += 1 + NIDS_PER_BLOCK;
++ break;
++ case 3:
++ nofs = 5 + 2 * NIDS_PER_BLOCK;
++ if (!offset[level - 1])
++ goto skip_partial;
++ err = truncate_partial_nodes(&dn, &rn->i, offset, level);
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ break;
++ default:
++ BUG();
++ }
++
++skip_partial:
++ while (cont) {
++ dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]);
++ switch (offset[0]) {
++ case NODE_DIR1_BLOCK:
++ case NODE_DIR2_BLOCK:
++ err = truncate_dnode(&dn);
++ break;
++
++ case NODE_IND1_BLOCK:
++ case NODE_IND2_BLOCK:
++ err = truncate_nodes(&dn, nofs, offset[1], 2);
++ break;
++
++ case NODE_DIND_BLOCK:
++ err = truncate_nodes(&dn, nofs, offset[1], 3);
++ cont = 0;
++ break;
++
++ default:
++ BUG();
++ }
++ if (err < 0 && err != -ENOENT)
++ goto fail;
++ if (offset[1] == 0 &&
++ rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) {
++ lock_page(page);
++ wait_on_page_writeback(page);
++ rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
++ set_page_dirty(page);
++ unlock_page(page);
++ }
++ offset[1] = 0;
++ offset[0]++;
++ nofs += err;
++ }
++fail:
++ f2fs_put_page(page, 0);
++ return err > 0 ? 0 : err;
++}
++
++int remove_inode_page(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ nid_t ino = inode->i_ino;
++ struct dnode_of_data dn;
++
++ mutex_lock_op(sbi, NODE_TRUNC);
++ page = get_node_page(sbi, ino);
++ if (IS_ERR(page)) {
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return PTR_ERR(page);
++ }
++
++ if (F2FS_I(inode)->i_xattr_nid) {
++ nid_t nid = F2FS_I(inode)->i_xattr_nid;
++ struct page *npage = get_node_page(sbi, nid);
++
++ if (IS_ERR(npage)) {
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return PTR_ERR(npage);
++ }
++
++ F2FS_I(inode)->i_xattr_nid = 0;
++ set_new_dnode(&dn, inode, page, npage, nid);
++ dn.inode_page_locked = 1;
++ truncate_node(&dn);
++ }
++ if (inode->i_blocks == 1) {
++ /* inernally call f2fs_put_page() */
++ set_new_dnode(&dn, inode, page, page, ino);
++ truncate_node(&dn);
++ } else if (inode->i_blocks == 0) {
++ struct node_info ni;
++ get_node_info(sbi, inode->i_ino, &ni);
++
++ /* called after f2fs_new_inode() is failed */
++ BUG_ON(ni.blk_addr != NULL_ADDR);
++ f2fs_put_page(page, 1);
++ } else {
++ BUG();
++ }
++ mutex_unlock_op(sbi, NODE_TRUNC);
++ return 0;
++}
++
++int new_inode_page(struct inode *inode, struct dentry *dentry)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ struct dnode_of_data dn;
++
++ /* allocate inode page for new inode */
++ set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
++ mutex_lock_op(sbi, NODE_NEW);
++ page = new_node_page(&dn, 0);
++ init_dent_inode(dentry, page);
++ mutex_unlock_op(sbi, NODE_NEW);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ f2fs_put_page(page, 1);
++ return 0;
++}
++
++struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct node_info old_ni, new_ni;
++ struct page *page;
++ int err;
++
++ if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
++ return ERR_PTR(-EPERM);
++
++ page = grab_cache_page(mapping, dn->nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ get_node_info(sbi, dn->nid, &old_ni);
++
++ SetPageUptodate(page);
++ fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
++
++ /* Reinitialize old_ni with new node page */
++ BUG_ON(old_ni.blk_addr != NULL_ADDR);
++ new_ni = old_ni;
++ new_ni.ino = dn->inode->i_ino;
++
++ if (!inc_valid_node_count(sbi, dn->inode, 1)) {
++ err = -ENOSPC;
++ goto fail;
++ }
++ set_node_addr(sbi, &new_ni, NEW_ADDR);
++
++ dn->node_page = page;
++ sync_inode_page(dn);
++ set_page_dirty(page);
++ set_cold_node(dn->inode, page);
++ if (ofs == 0)
++ inc_valid_inode_count(sbi);
++
++ return page;
++
++fail:
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++}
++
++static int read_node_page(struct page *page, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ struct node_info ni;
++
++ get_node_info(sbi, page->index, &ni);
++
++ if (ni.blk_addr == NULL_ADDR)
++ return -ENOENT;
++ return f2fs_readpage(sbi, page, ni.blk_addr, type);
++}
++
++/**
++ * Readahead a node page
++ */
++void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct page *apage;
++
++ apage = find_get_page(mapping, nid);
++ if (apage && PageUptodate(apage))
++ goto release_out;
++ f2fs_put_page(apage, 0);
++
++ apage = grab_cache_page(mapping, nid);
++ if (!apage)
++ return;
++
++ if (read_node_page(apage, READA))
++ goto unlock_out;
++
++ page_cache_release(apage);
++ return;
++
++unlock_out:
++ unlock_page(apage);
++release_out:
++ page_cache_release(apage);
++}
++
++struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
++{
++ int err;
++ struct page *page;
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++
++ page = grab_cache_page(mapping, nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = read_node_page(page, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++
++ BUG_ON(nid != nid_of_node(page));
++ mark_page_accessed(page);
++ return page;
++}
++
++/**
++ * Return a locked page for the desired node page.
++ * And, readahead MAX_RA_NODE number of node pages.
++ */
++struct page *get_node_page_ra(struct page *parent, int start)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ int i, end;
++ int err = 0;
++ nid_t nid;
++ struct page *page;
++
++ /* First, try getting the desired direct node. */
++ nid = get_nid(parent, start, false);
++ if (!nid)
++ return ERR_PTR(-ENOENT);
++
++ page = find_get_page(mapping, nid);
++ if (page && PageUptodate(page))
++ goto page_hit;
++ f2fs_put_page(page, 0);
++
++repeat:
++ page = grab_cache_page(mapping, nid);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = read_node_page(page, READA);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++
++ /* Then, try readahead for siblings of the desired node */
++ end = start + MAX_RA_NODE;
++ end = min(end, NIDS_PER_BLOCK);
++ for (i = start + 1; i < end; i++) {
++ nid = get_nid(parent, i, false);
++ if (!nid)
++ continue;
++ ra_node_page(sbi, nid);
++ }
++
++page_hit:
++ lock_page(page);
++ if (PageError(page)) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(-EIO);
++ }
++
++ /* Has the page been truncated? */
++ if (page->mapping != mapping) {
++ f2fs_put_page(page, 1);
++ goto repeat;
++ }
++ return page;
++}
++
++void sync_inode_page(struct dnode_of_data *dn)
++{
++ if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
++ update_inode(dn->inode, dn->node_page);
++ } else if (dn->inode_page) {
++ if (!dn->inode_page_locked)
++ lock_page(dn->inode_page);
++ update_inode(dn->inode, dn->inode_page);
++ if (!dn->inode_page_locked)
++ unlock_page(dn->inode_page);
++ } else {
++ f2fs_write_inode(dn->inode, NULL);
++ }
++}
++
++int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
++ struct writeback_control *wbc)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ pgoff_t index, end;
++ struct pagevec pvec;
++ int step = ino ? 2 : 0;
++ int nwritten = 0, wrote = 0;
++
++ pagevec_init(&pvec, 0);
++
++next_step:
++ index = 0;
++ end = LONG_MAX;
++
++ while (index <= end) {
++ int i, nr_pages;
++ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
++ PAGECACHE_TAG_DIRTY,
++ min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
++ if (nr_pages == 0)
++ break;
++
++ for (i = 0; i < nr_pages; i++) {
++ struct page *page = pvec.pages[i];
++
++ /*
++ * flushing sequence with step:
++ * 0. indirect nodes
++ * 1. dentry dnodes
++ * 2. file dnodes
++ */
++ if (step == 0 && IS_DNODE(page))
++ continue;
++ if (step == 1 && (!IS_DNODE(page) ||
++ is_cold_node(page)))
++ continue;
++ if (step == 2 && (!IS_DNODE(page) ||
++ !is_cold_node(page)))
++ continue;
++
++ /*
++ * If an fsync mode,
++ * we should not skip writing node pages.
++ */
++ if (ino && ino_of_node(page) == ino)
++ lock_page(page);
++ else if (!trylock_page(page))
++ continue;
++
++ if (unlikely(page->mapping != mapping)) {
++continue_unlock:
++ unlock_page(page);
++ continue;
++ }
++ if (ino && ino_of_node(page) != ino)
++ goto continue_unlock;
++
++ if (!PageDirty(page)) {
++ /* someone wrote it for us */
++ goto continue_unlock;
++ }
++
++ if (!clear_page_dirty_for_io(page))
++ goto continue_unlock;
++
++ /* called by fsync() */
++ if (ino && IS_DNODE(page)) {
++ int mark = !is_checkpointed_node(sbi, ino);
++ set_fsync_mark(page, 1);
++ if (IS_INODE(page))
++ set_dentry_mark(page, mark);
++ nwritten++;
++ } else {
++ set_fsync_mark(page, 0);
++ set_dentry_mark(page, 0);
++ }
++ mapping->a_ops->writepage(page, wbc);
++ wrote++;
++
++ if (--wbc->nr_to_write == 0)
++ break;
++ }
++ pagevec_release(&pvec);
++ cond_resched();
++
++ if (wbc->nr_to_write == 0) {
++ step = 2;
++ break;
++ }
++ }
++
++ if (step < 2) {
++ step++;
++ goto next_step;
++ }
++
++ if (wrote)
++ f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL);
++
++ return nwritten;
++}
++
++static int f2fs_write_node_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ nid_t nid;
++ unsigned int nofs;
++ block_t new_addr;
++ struct node_info ni;
++
++ if (wbc->for_reclaim) {
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ return AOP_WRITEPAGE_ACTIVATE;
++ }
++
++ wait_on_page_writeback(page);
++
++ mutex_lock_op(sbi, NODE_WRITE);
++
++ /* get old block addr of this node page */
++ nid = nid_of_node(page);
++ nofs = ofs_of_node(page);
++ BUG_ON(page->index != nid);
++
++ get_node_info(sbi, nid, &ni);
++
++ /* This page is already truncated */
++ if (ni.blk_addr == NULL_ADDR)
++ return 0;
++
++ set_page_writeback(page);
++
++ /* insert node offset */
++ write_node_page(sbi, page, nid, ni.blk_addr, &new_addr);
++ set_node_addr(sbi, &ni, new_addr);
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++
++ mutex_unlock_op(sbi, NODE_WRITE);
++ unlock_page(page);
++ return 0;
++}
++
++static int f2fs_write_node_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++ struct block_device *bdev = sbi->sb->s_bdev;
++ long nr_to_write = wbc->nr_to_write;
++
++ if (wbc->for_kupdate)
++ return 0;
++
++ if (get_pages(sbi, F2FS_DIRTY_NODES) == 0)
++ return 0;
++
++ if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
++ write_checkpoint(sbi, false, false);
++ return 0;
++ }
++
++ /* if mounting is failed, skip writing node pages */
++ wbc->nr_to_write = bio_get_nr_vecs(bdev);
++ sync_node_pages(sbi, 0, wbc);
++ wbc->nr_to_write = nr_to_write -
++ (bio_get_nr_vecs(bdev) - wbc->nr_to_write);
++ return 0;
++}
++
++static int f2fs_set_node_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ inc_page_count(sbi, F2FS_DIRTY_NODES);
++ SetPagePrivate(page);
++ return 1;
++ }
++ return 0;
++}
++
++static void f2fs_invalidate_node_page(struct page *page, unsigned long offset)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (PageDirty(page))
++ dec_page_count(sbi, F2FS_DIRTY_NODES);
++ ClearPagePrivate(page);
++}
++
++static int f2fs_release_node_page(struct page *page, gfp_t wait)
++{
++ ClearPagePrivate(page);
++ return 0;
++}
++
++/**
++ * Structure of the f2fs node operations
++ */
++const struct address_space_operations f2fs_node_aops = {
++ .writepage = f2fs_write_node_page,
++ .writepages = f2fs_write_node_pages,
++ .set_page_dirty = f2fs_set_node_page_dirty,
++ .invalidatepage = f2fs_invalidate_node_page,
++ .releasepage = f2fs_release_node_page,
++};
++
++static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
++{
++ struct list_head *this;
++ struct free_nid *i = NULL;
++ list_for_each(this, head) {
++ i = list_entry(this, struct free_nid, list);
++ if (i->nid == n)
++ break;
++ i = NULL;
++ }
++ return i;
++}
++
++static void __del_from_free_nid_list(struct free_nid *i)
++{
++ list_del(&i->list);
++ kmem_cache_free(free_nid_slab, i);
++}
++
++static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct free_nid *i;
++
++ if (nm_i->fcnt > 2 * MAX_FREE_NIDS)
++ return 0;
++retry:
++ i = kmem_cache_alloc(free_nid_slab, GFP_NOFS);
++ if (!i) {
++ cond_resched();
++ goto retry;
++ }
++ i->nid = nid;
++ i->state = NID_NEW;
++
++ spin_lock(&nm_i->free_nid_list_lock);
++ if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
++ spin_unlock(&nm_i->free_nid_list_lock);
++ kmem_cache_free(free_nid_slab, i);
++ return 0;
++ }
++ list_add_tail(&i->list, &nm_i->free_nid_list);
++ nm_i->fcnt++;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return 1;
++}
++
++static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
++{
++ struct free_nid *i;
++ spin_lock(&nm_i->free_nid_list_lock);
++ i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
++ if (i && i->state == NID_NEW) {
++ __del_from_free_nid_list(i);
++ nm_i->fcnt--;
++ }
++ spin_unlock(&nm_i->free_nid_list_lock);
++}
++
++static int scan_nat_page(struct f2fs_nm_info *nm_i,
++ struct page *nat_page, nid_t start_nid)
++{
++ struct f2fs_nat_block *nat_blk = page_address(nat_page);
++ block_t blk_addr;
++ int fcnt = 0;
++ int i;
++
++ /* 0 nid should not be used */
++ if (start_nid == 0)
++ ++start_nid;
++
++ i = start_nid % NAT_ENTRY_PER_BLOCK;
++
++ for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
++ blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
++ BUG_ON(blk_addr == NEW_ADDR);
++ if (blk_addr == NULL_ADDR)
++ fcnt += add_free_nid(nm_i, start_nid);
++ }
++ return fcnt;
++}
++
++static void build_free_nids(struct f2fs_sb_info *sbi)
++{
++ struct free_nid *fnid, *next_fnid;
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ nid_t nid = 0;
++ bool is_cycled = false;
++ int fcnt = 0;
++ int i;
++
++ nid = nm_i->next_scan_nid;
++ nm_i->init_scan_nid = nid;
++
++ ra_nat_pages(sbi, nid);
++
++ while (1) {
++ struct page *page = get_current_nat_page(sbi, nid);
++
++ fcnt += scan_nat_page(nm_i, page, nid);
++ f2fs_put_page(page, 1);
++
++ nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
++
++ if (nid >= nm_i->max_nid) {
++ nid = 0;
++ is_cycled = true;
++ }
++ if (fcnt > MAX_FREE_NIDS)
++ break;
++ if (is_cycled && nm_i->init_scan_nid <= nid)
++ break;
++ }
++
++ nm_i->next_scan_nid = nid;
++
++ /* find free nids from current sum_pages */
++ mutex_lock(&curseg->curseg_mutex);
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr);
++ nid = le32_to_cpu(nid_in_journal(sum, i));
++ if (addr == NULL_ADDR)
++ add_free_nid(nm_i, nid);
++ else
++ remove_free_nid(nm_i, nid);
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /* remove the free nids from current allocated nids */
++ list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) {
++ struct nat_entry *ne;
++
++ read_lock(&nm_i->nat_tree_lock);
++ ne = __lookup_nat_cache(nm_i, fnid->nid);
++ if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
++ remove_free_nid(nm_i, fnid->nid);
++ read_unlock(&nm_i->nat_tree_lock);
++ }
++}
++
++/*
++ * If this function returns success, caller can obtain a new nid
++ * from second parameter of this function.
++ * The returned nid could be used ino as well as nid when inode is created.
++ */
++bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i = NULL;
++ struct list_head *this;
++retry:
++ mutex_lock(&nm_i->build_lock);
++ if (!nm_i->fcnt) {
++ /* scan NAT in order to build free nid list */
++ build_free_nids(sbi);
++ if (!nm_i->fcnt) {
++ mutex_unlock(&nm_i->build_lock);
++ return false;
++ }
++ }
++ mutex_unlock(&nm_i->build_lock);
++
++ /*
++ * We check fcnt again since previous check is racy as
++ * we didn't hold free_nid_list_lock. So other thread
++ * could consume all of free nids.
++ */
++ spin_lock(&nm_i->free_nid_list_lock);
++ if (!nm_i->fcnt) {
++ spin_unlock(&nm_i->free_nid_list_lock);
++ goto retry;
++ }
++
++ BUG_ON(list_empty(&nm_i->free_nid_list));
++ list_for_each(this, &nm_i->free_nid_list) {
++ i = list_entry(this, struct free_nid, list);
++ if (i->state == NID_NEW)
++ break;
++ }
++
++ BUG_ON(i->state != NID_NEW);
++ *nid = i->nid;
++ i->state = NID_ALLOC;
++ nm_i->fcnt--;
++ spin_unlock(&nm_i->free_nid_list_lock);
++ return true;
++}
++
++/**
++ * alloc_nid() should be called prior to this function.
++ */
++void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i;
++
++ spin_lock(&nm_i->free_nid_list_lock);
++ i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
++ if (i) {
++ BUG_ON(i->state != NID_ALLOC);
++ __del_from_free_nid_list(i);
++ }
++ spin_unlock(&nm_i->free_nid_list_lock);
++}
++
++/**
++ * alloc_nid() should be called prior to this function.
++ */
++void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
++{
++ alloc_nid_done(sbi, nid);
++ add_free_nid(NM_I(sbi), nid);
++}
++
++void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
++ struct f2fs_summary *sum, struct node_info *ni,
++ block_t new_blkaddr)
++{
++ rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
++ set_node_addr(sbi, ni, new_blkaddr);
++ clear_node_page_dirty(page);
++}
++
++int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
++{
++ struct address_space *mapping = sbi->node_inode->i_mapping;
++ struct f2fs_node *rn;
++ void *src, *dst;
++ nid_t ino = ino_of_node(page);
++ struct node_info old_ni, new_ni;
++ struct page *ipage;
++
++ ipage = grab_cache_page(mapping, ino);
++ if (!ipage)
++ return -ENOMEM;
++
++ /* Should not use this inode from free nid list */
++ remove_free_nid(NM_I(sbi), ino);
++
++ get_node_info(sbi, ino, &old_ni);
++ SetPageUptodate(ipage);
++ fill_node_footer(ipage, ino, ino, 0, true);
++
++ src = kmap_atomic(page);
++ dst = kmap_atomic(ipage);
++
++ memcpy(dst, src, F2FS_INODE_SIZE);
++ rn = (struct f2fs_node *)dst;
++ rn->i.i_size = 0;
++ rn->i.i_blocks = 1;
++ rn->i.i_links = 1;
++ rn->i.i_xattr_nid = 0;
++ kunmap_atomic(dst);
++ kunmap_atomic(src);
++
++ new_ni = old_ni;
++ new_ni.ino = ino;
++
++ set_node_addr(sbi, &new_ni, NEW_ADDR);
++ inc_valid_inode_count(sbi);
++
++ f2fs_put_page(ipage, 1);
++ return 0;
++}
++
++int restore_node_summary(struct f2fs_sb_info *sbi,
++ unsigned int segno, struct f2fs_summary_block *sum)
++{
++ struct f2fs_node *rn;
++ struct f2fs_summary *sum_entry;
++ struct page *page;
++ block_t addr;
++ int i, last_offset;
++
++ /* alloc temporal page for read node */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ lock_page(page);
++
++ /* scan the node segment */
++ last_offset = sbi->blocks_per_seg;
++ addr = START_BLOCK(sbi, segno);
++ sum_entry = &sum->entries[0];
++
++ for (i = 0; i < last_offset; i++, sum_entry++) {
++ if (f2fs_readpage(sbi, page, addr, READ_SYNC))
++ goto out;
++
++ rn = (struct f2fs_node *)page_address(page);
++ sum_entry->nid = rn->footer.nid;
++ sum_entry->version = 0;
++ sum_entry->ofs_in_node = 0;
++ addr++;
++
++ /*
++ * In order to read next node page,
++ * we must clear PageUptodate flag.
++ */
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++ return 0;
++}
++
++static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ int i;
++
++ mutex_lock(&curseg->curseg_mutex);
++
++ if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) {
++ mutex_unlock(&curseg->curseg_mutex);
++ return false;
++ }
++
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ struct nat_entry *ne;
++ struct f2fs_nat_entry raw_ne;
++ nid_t nid = le32_to_cpu(nid_in_journal(sum, i));
++
++ raw_ne = nat_in_journal(sum, i);
++retry:
++ write_lock(&nm_i->nat_tree_lock);
++ ne = __lookup_nat_cache(nm_i, nid);
++ if (ne) {
++ __set_nat_cache_dirty(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++ continue;
++ }
++ ne = grab_nat_entry(nm_i, nid);
++ if (!ne) {
++ write_unlock(&nm_i->nat_tree_lock);
++ goto retry;
++ }
++ nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr));
++ nat_set_ino(ne, le32_to_cpu(raw_ne.ino));
++ nat_set_version(ne, raw_ne.version);
++ __set_nat_cache_dirty(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++ }
++ update_nats_in_cursum(sum, -i);
++ mutex_unlock(&curseg->curseg_mutex);
++ return true;
++}
++
++/**
++ * This function is called during the checkpointing process.
++ */
++void flush_nat_entries(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ struct list_head *cur, *n;
++ struct page *page = NULL;
++ struct f2fs_nat_block *nat_blk = NULL;
++ nid_t start_nid = 0, end_nid = 0;
++ bool flushed;
++
++ flushed = flush_nats_in_journal(sbi);
++
++ if (!flushed)
++ mutex_lock(&curseg->curseg_mutex);
++
++ /* 1) flush dirty nat caches */
++ list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) {
++ struct nat_entry *ne;
++ nid_t nid;
++ struct f2fs_nat_entry raw_ne;
++ int offset = -1;
++ block_t old_blkaddr, new_blkaddr;
++
++ ne = list_entry(cur, struct nat_entry, list);
++ nid = nat_get_nid(ne);
++
++ if (nat_get_blkaddr(ne) == NEW_ADDR)
++ continue;
++ if (flushed)
++ goto to_nat_page;
++
++ /* if there is room for nat enries in curseg->sumpage */
++ offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);
++ if (offset >= 0) {
++ raw_ne = nat_in_journal(sum, offset);
++ old_blkaddr = le32_to_cpu(raw_ne.block_addr);
++ goto flush_now;
++ }
++to_nat_page:
++ if (!page || (start_nid > nid || nid > end_nid)) {
++ if (page) {
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++ start_nid = START_NID(nid);
++ end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1;
++
++ /*
++ * get nat block with dirty flag, increased reference
++ * count, mapped and lock
++ */
++ page = get_next_nat_page(sbi, start_nid);
++ nat_blk = page_address(page);
++ }
++
++ BUG_ON(!nat_blk);
++ raw_ne = nat_blk->entries[nid - start_nid];
++ old_blkaddr = le32_to_cpu(raw_ne.block_addr);
++flush_now:
++ new_blkaddr = nat_get_blkaddr(ne);
++
++ raw_ne.ino = cpu_to_le32(nat_get_ino(ne));
++ raw_ne.block_addr = cpu_to_le32(new_blkaddr);
++ raw_ne.version = nat_get_version(ne);
++
++ if (offset < 0) {
++ nat_blk->entries[nid - start_nid] = raw_ne;
++ } else {
++ nat_in_journal(sum, offset) = raw_ne;
++ nid_in_journal(sum, offset) = cpu_to_le32(nid);
++ }
++
++ if (nat_get_blkaddr(ne) == NULL_ADDR) {
++ write_lock(&nm_i->nat_tree_lock);
++ __del_from_nat_cache(nm_i, ne);
++ write_unlock(&nm_i->nat_tree_lock);
++
++ /* We can reuse this freed nid at this point */
++ add_free_nid(NM_I(sbi), nid);
++ } else {
++ write_lock(&nm_i->nat_tree_lock);
++ __clear_nat_cache_dirty(nm_i, ne);
++ ne->checkpointed = true;
++ write_unlock(&nm_i->nat_tree_lock);
++ }
++ }
++ if (!flushed)
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /*
++ * set block offset in cur_journal_segno1/2
++ * where the last NAT update happened
++ */
++ memcpy(nm_i->nat_upd_blkoff,
++ nm_i->lst_upd_blkoff, sizeof(int) * 3);
++ f2fs_put_page(page, 1);
++
++ /* 2) shrink nat caches if necessary */
++ try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD);
++}
++
++static int init_node_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ unsigned char *version_bitmap;
++ int i;
++
++ nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
++
++ /* segment_count_nat includes pair segment so divide to 2. */
++ nm_i->nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
++ nm_i->nat_blocks = nm_i->nat_segs <<
++ le32_to_cpu(sb_raw->log_blocks_per_seg);
++ nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks;
++ nm_i->fcnt = 0;
++ nm_i->nat_cnt = 0;
++
++ INIT_LIST_HEAD(&nm_i->free_nid_list);
++ INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
++ INIT_LIST_HEAD(&nm_i->nat_entries);
++ INIT_LIST_HEAD(&nm_i->dirty_nat_entries);
++
++ mutex_init(&nm_i->build_lock);
++ spin_lock_init(&nm_i->free_nid_list_lock);
++ rwlock_init(&nm_i->nat_tree_lock);
++
++ for (i = 0; i < 3; i++) {
++ nm_i->lst_upd_blkoff[i] =
++ le16_to_cpu(sbi->ckpt->nat_upd_blkoff[i]);
++ nm_i->nat_upd_blkoff[i] =
++ le16_to_cpu(sbi->ckpt->nat_upd_blkoff[i]);
++ }
++
++ nm_i->written_valid_node_count = sbi->total_valid_node_count;
++ nm_i->written_valid_inode_count = sbi->total_valid_inode_count;
++
++ nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
++ nm_i->init_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
++ nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
++
++ nm_i->nat_bitmap = kzalloc(nm_i->bitmap_size, GFP_KERNEL);
++ if (!nm_i->nat_bitmap)
++ return -ENOMEM;
++ version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
++ if (!version_bitmap)
++ return -EFAULT;
++
++ /* copy version bitmap */
++ memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size);
++ return 0;
++}
++
++int build_node_manager(struct f2fs_sb_info *sbi)
++{
++ sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL);
++ if (!sbi->nm_info)
++ return -ENOMEM;
++
++ if (init_node_manager(sbi))
++ return -EINVAL;
++
++ build_free_nids(sbi);
++ return 0;
++}
++
++void destroy_node_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_nm_info *nm_i = NM_I(sbi);
++ struct free_nid *i, *next_i;
++ struct nat_entry *natvec[NATVEC_SIZE];
++ nid_t nid = 0;
++ unsigned int found;
++
++ if (!nm_i)
++ return;
++
++ /* destroy free nid list */
++ spin_lock(&nm_i->free_nid_list_lock);
++ list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
++ BUG_ON(i->state == NID_ALLOC);
++ __del_from_free_nid_list(i);
++ nm_i->fcnt--;
++ }
++ BUG_ON(nm_i->fcnt);
++ spin_unlock(&nm_i->free_nid_list_lock);
++
++ /* destroy nat cache */
++ write_lock(&nm_i->nat_tree_lock);
++ while ((found = __gang_lookup_nat_cache(nm_i,
++ nid, NATVEC_SIZE, natvec))) {
++ unsigned idx;
++ for (idx = 0; idx < found; idx++) {
++ struct nat_entry *e = natvec[idx];
++ nid = nat_get_nid(e) + 1;
++ __del_from_nat_cache(nm_i, e);
++ }
++ }
++ BUG_ON(nm_i->nat_cnt);
++ write_unlock(&nm_i->nat_tree_lock);
++
++ kfree(nm_i->nat_bitmap);
++ sbi->nm_info = NULL;
++ kfree(nm_i);
++}
++
++int create_node_manager_caches(void)
++{
++ nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
++ sizeof(struct nat_entry), NULL);
++ if (!nat_entry_slab)
++ return -ENOMEM;
++
++ free_nid_slab = f2fs_kmem_cache_create("free_nid",
++ sizeof(struct free_nid), NULL);
++ if (!free_nid_slab) {
++ kmem_cache_destroy(nat_entry_slab);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void destroy_node_manager_caches(void)
++{
++ kmem_cache_destroy(free_nid_slab);
++ kmem_cache_destroy(nat_entry_slab);
++}
diff --git a/patches/linux-3.7/0106-f2fs-add-segment-operations.patch b/patches/linux-3.7/0106-f2fs-add-segment-operations.patch
new file mode 100644
index 0000000..27b1327
--- /dev/null
+++ b/patches/linux-3.7/0106-f2fs-add-segment-operations.patch
@@ -0,0 +1,1842 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:28:47 +0000
+Subject: [PATCH] f2fs: add segment operations
+
+This adds specific functions not only to manage dirty/free segments, SIT pages,
+a cache for SIT entries, and summary entries, but also to allocate free blocks
+and write three types of pages: data, node, and meta.
+
+- F2FS maintains three types of bitmaps in memory, which indicate free, prefree,
+ and dirty segments respectively.
+
+- The key information of an SIT entry consists of a segment number, the number
+ of valid blocks in the segment, a bitmap to identify there-in valid or invalid
+ blocks.
+
+- An SIT page is composed of a certain range of SIT entries, which is maintained
+ by the address space of meta_inode.
+
+- To cache SIT entries, a simple array is used. The index for the array is the
+ segment number.
+
+- A summary entry for data contains the parent node information. A summary entry
+ for node contains its node offset from the inode.
+
+- F2FS manages information about six active logs and those summary entries in
+ memory. Whenever one of them is changed, its summary entries are flushed to
+ its SIT page maintained by the address space of meta_inode.
+
+- This patch adds a default block allocation function which supports heap-based
+ allocation policy.
+
+- This patch adds core functions to write data, node, and meta pages. Since LFS
+ basically produces a series of sequential writes, F2FS merges sequential bios
+ with a single one as much as possible to reduce the IO scheduling overhead.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/segment.c | 1795 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 1795 insertions(+)
+ create mode 100644 fs/f2fs/segment.c
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+new file mode 100644
+index 0000000..57d0931
+--- /dev/null
++++ b/fs/f2fs/segment.c
+@@ -0,0 +1,1795 @@
++/**
++ * fs/f2fs/segment.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/bio.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "segment.h"
++#include "node.h"
++
++static int need_to_flush(struct f2fs_sb_info *sbi)
++{
++ unsigned int pages_per_sec = (1 << sbi->log_blocks_per_seg) *
++ sbi->segs_per_sec;
++ int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++
++ if (sbi->por_doing)
++ return 0;
++
++ if (free_sections(sbi) <= (node_secs + 2 * dent_secs +
++ reserved_sections(sbi)))
++ return 1;
++ return 0;
++}
++
++/**
++ * This function balances dirty node and dentry pages.
++ * In addition, it controls garbage collection.
++ */
++void f2fs_balance_fs(struct f2fs_sb_info *sbi)
++{
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ if (sbi->por_doing)
++ return;
++
++ /*
++ * We should do checkpoint when there are so many dirty node pages
++ * with enough free segments. After then, we should do GC.
++ */
++ if (need_to_flush(sbi)) {
++ sync_dirty_dir_inodes(sbi);
++ sync_node_pages(sbi, 0, &wbc);
++ }
++
++ if (has_not_enough_free_secs(sbi)) {
++ mutex_lock(&sbi->gc_mutex);
++ f2fs_gc(sbi, 1);
++ }
++}
++
++static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ /* need not be added */
++ if (IS_CURSEG(sbi, segno))
++ return;
++
++ if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]++;
++
++ if (dirty_type == DIRTY) {
++ struct seg_entry *sentry = get_seg_entry(sbi, segno);
++ dirty_type = sentry->type;
++ if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]++;
++ }
++}
++
++static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]--;
++
++ if (dirty_type == DIRTY) {
++ struct seg_entry *sentry = get_seg_entry(sbi, segno);
++ dirty_type = sentry->type;
++ if (test_and_clear_bit(segno,
++ dirty_i->dirty_segmap[dirty_type]))
++ dirty_i->nr_dirty[dirty_type]--;
++ clear_bit(segno, dirty_i->victim_segmap[FG_GC]);
++ clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
++ }
++}
++
++/**
++ * Should not occur error such as -ENOMEM.
++ * Adding dirty entry into seglist is not critical operation.
++ * If a given segment is one of current working segments, it won't be added.
++ */
++void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned short valid_blocks;
++
++ if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno))
++ return;
++
++ mutex_lock(&dirty_i->seglist_lock);
++
++ valid_blocks = get_valid_blocks(sbi, segno, 0);
++
++ if (valid_blocks == 0) {
++ __locate_dirty_segment(sbi, segno, PRE);
++ __remove_dirty_segment(sbi, segno, DIRTY);
++ } else if (valid_blocks < sbi->blocks_per_seg) {
++ __locate_dirty_segment(sbi, segno, DIRTY);
++ } else {
++ /* Recovery routine with SSR needs this */
++ __remove_dirty_segment(sbi, segno, DIRTY);
++ }
++
++ mutex_unlock(&dirty_i->seglist_lock);
++ return;
++}
++
++/**
++ * Should call clear_prefree_segments after checkpoint is done.
++ */
++static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno, offset = 0;
++ unsigned int total_segs = TOTAL_SEGS(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ while (1) {
++ segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
++ offset);
++ if (segno >= total_segs)
++ break;
++ __set_test_and_free(sbi, segno);
++ offset = segno + 1;
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++void clear_prefree_segments(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno, offset = 0;
++ unsigned int total_segs = TOTAL_SEGS(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ while (1) {
++ segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
++ offset);
++ if (segno >= total_segs)
++ break;
++
++ offset = segno + 1;
++ if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE]))
++ dirty_i->nr_dirty[PRE]--;
++
++ /* Let's use trim */
++ if (test_opt(sbi, DISCARD))
++ blkdev_issue_discard(sbi->sb->s_bdev,
++ START_BLOCK(sbi, segno) <<
++ sbi->log_sectors_per_block,
++ 1 << (sbi->log_sectors_per_block +
++ sbi->log_blocks_per_seg),
++ GFP_NOFS, 0);
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap))
++ sit_i->dirty_sentries++;
++}
++
++static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type,
++ unsigned int segno, int modified)
++{
++ struct seg_entry *se = get_seg_entry(sbi, segno);
++ se->type = type;
++ if (modified)
++ __mark_sit_entry_dirty(sbi, segno);
++}
++
++static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
++{
++ struct seg_entry *se;
++ unsigned int segno, offset;
++ long int new_vblocks;
++
++ segno = GET_SEGNO(sbi, blkaddr);
++
++ se = get_seg_entry(sbi, segno);
++ new_vblocks = se->valid_blocks + del;
++ offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
++
++ BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) ||
++ (new_vblocks > sbi->blocks_per_seg)));
++
++ se->valid_blocks = new_vblocks;
++ se->mtime = get_mtime(sbi);
++ SIT_I(sbi)->max_mtime = se->mtime;
++
++ /* Update valid block bitmap */
++ if (del > 0) {
++ if (f2fs_set_bit(offset, se->cur_valid_map))
++ BUG();
++ } else {
++ if (!f2fs_clear_bit(offset, se->cur_valid_map))
++ BUG();
++ }
++ if (!f2fs_test_bit(offset, se->ckpt_valid_map))
++ se->ckpt_valid_blocks += del;
++
++ __mark_sit_entry_dirty(sbi, segno);
++
++ /* update total number of valid blocks to be written in ckpt area */
++ SIT_I(sbi)->written_valid_blocks += del;
++
++ if (sbi->segs_per_sec > 1)
++ get_sec_entry(sbi, segno)->valid_blocks += del;
++}
++
++static void refresh_sit_entry(struct f2fs_sb_info *sbi,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ update_sit_entry(sbi, new_blkaddr, 1);
++ if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
++ update_sit_entry(sbi, old_blkaddr, -1);
++}
++
++void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
++{
++ unsigned int segno = GET_SEGNO(sbi, addr);
++ struct sit_info *sit_i = SIT_I(sbi);
++
++ BUG_ON(addr == NULL_ADDR);
++ if (addr == NEW_ADDR)
++ return;
++
++ /* add it into sit main buffer */
++ mutex_lock(&sit_i->sentry_lock);
++
++ update_sit_entry(sbi, addr, -1);
++
++ /* add it into dirty seglist */
++ locate_dirty_segment(sbi, segno);
++
++ mutex_unlock(&sit_i->sentry_lock);
++}
++
++/**
++ * This function should be resided under the curseg_mutex lock
++ */
++static void __add_sum_entry(struct f2fs_sb_info *sbi, int type,
++ struct f2fs_summary *sum, unsigned short offset)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ void *addr = curseg->sum_blk;
++ addr += offset * sizeof(struct f2fs_summary);
++ memcpy(addr, sum, sizeof(struct f2fs_summary));
++ return;
++}
++
++/**
++ * Calculate the number of current summary pages for writing
++ */
++int npages_for_summary_flush(struct f2fs_sb_info *sbi)
++{
++ int total_size_bytes = 0;
++ int valid_sum_count = 0;
++ int i, sum_space;
++
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ if (sbi->ckpt->alloc_type[i] == SSR)
++ valid_sum_count += sbi->blocks_per_seg;
++ else
++ valid_sum_count += curseg_blkoff(sbi, i);
++ }
++
++ total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1)
++ + sizeof(struct nat_journal) + 2
++ + sizeof(struct sit_journal) + 2;
++ sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE;
++ if (total_size_bytes < sum_space)
++ return 1;
++ else if (total_size_bytes < 2 * sum_space)
++ return 2;
++ return 3;
++}
++
++/**
++ * Caller should put this summary page
++ */
++struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
++}
++
++static void write_sum_page(struct f2fs_sb_info *sbi,
++ struct f2fs_summary_block *sum_blk, block_t blk_addr)
++{
++ struct page *page = grab_meta_page(sbi, blk_addr);
++ void *kaddr = page_address(page);
++ memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++}
++
++static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi,
++ int ofs_unit, int type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE];
++ unsigned int segno, next_segno, i;
++ int ofs = 0;
++
++ /*
++ * If there is not enough reserved sections,
++ * we should not reuse prefree segments.
++ */
++ if (has_not_enough_free_secs(sbi))
++ return NULL_SEGNO;
++
++ /*
++ * NODE page should not reuse prefree segment,
++ * since those information is used for SPOR.
++ */
++ if (IS_NODESEG(type))
++ return NULL_SEGNO;
++next:
++ segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs++);
++ ofs = ((segno / ofs_unit) * ofs_unit) + ofs_unit;
++ if (segno < TOTAL_SEGS(sbi)) {
++ /* skip intermediate segments in a section */
++ if (segno % ofs_unit)
++ goto next;
++
++ /* skip if whole section is not prefree */
++ next_segno = find_next_zero_bit(prefree_segmap,
++ TOTAL_SEGS(sbi), segno + 1);
++ if (next_segno - segno < ofs_unit)
++ goto next;
++
++ /* skip if whole section was not free at the last checkpoint */
++ for (i = 0; i < ofs_unit; i++)
++ if (get_seg_entry(sbi, segno)->ckpt_valid_blocks)
++ goto next;
++ return segno;
++ }
++ return NULL_SEGNO;
++}
++
++/**
++ * Find a new segment from the free segments bitmap to right order
++ * This function should be returned with success, otherwise BUG
++ */
++static void get_new_segment(struct f2fs_sb_info *sbi,
++ unsigned int *newseg, bool new_sec, int dir)
++{
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int total_secs = sbi->total_sections;
++ unsigned int segno, secno, zoneno;
++ unsigned int total_zones = sbi->total_sections / sbi->secs_per_zone;
++ unsigned int hint = *newseg / sbi->segs_per_sec;
++ unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg);
++ unsigned int left_start = hint;
++ bool init = true;
++ int go_left = 0;
++ int i;
++
++ write_lock(&free_i->segmap_lock);
++
++ if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) {
++ segno = find_next_zero_bit(free_i->free_segmap,
++ TOTAL_SEGS(sbi), *newseg + 1);
++ if (segno < TOTAL_SEGS(sbi))
++ goto got_it;
++ }
++find_other_zone:
++ secno = find_next_zero_bit(free_i->free_secmap, total_secs, hint);
++ if (secno >= total_secs) {
++ if (dir == ALLOC_RIGHT) {
++ secno = find_next_zero_bit(free_i->free_secmap,
++ total_secs, 0);
++ BUG_ON(secno >= total_secs);
++ } else {
++ go_left = 1;
++ left_start = hint - 1;
++ }
++ }
++ if (go_left == 0)
++ goto skip_left;
++
++ while (test_bit(left_start, free_i->free_secmap)) {
++ if (left_start > 0) {
++ left_start--;
++ continue;
++ }
++ left_start = find_next_zero_bit(free_i->free_secmap,
++ total_secs, 0);
++ BUG_ON(left_start >= total_secs);
++ break;
++ }
++ secno = left_start;
++skip_left:
++ hint = secno;
++ segno = secno * sbi->segs_per_sec;
++ zoneno = secno / sbi->secs_per_zone;
++
++ /* give up on finding another zone */
++ if (!init)
++ goto got_it;
++ if (sbi->secs_per_zone == 1)
++ goto got_it;
++ if (zoneno == old_zoneno)
++ goto got_it;
++ if (dir == ALLOC_LEFT) {
++ if (!go_left && zoneno + 1 >= total_zones)
++ goto got_it;
++ if (go_left && zoneno == 0)
++ goto got_it;
++ }
++ for (i = 0; i < NR_CURSEG_TYPE; i++)
++ if (CURSEG_I(sbi, i)->zone == zoneno)
++ break;
++
++ if (i < NR_CURSEG_TYPE) {
++ /* zone is in user, try another */
++ if (go_left)
++ hint = zoneno * sbi->secs_per_zone - 1;
++ else if (zoneno + 1 >= total_zones)
++ hint = 0;
++ else
++ hint = (zoneno + 1) * sbi->secs_per_zone;
++ init = false;
++ goto find_other_zone;
++ }
++got_it:
++ /* set it as dirty segment in free segmap */
++ BUG_ON(test_bit(segno, free_i->free_segmap));
++ __set_inuse(sbi, segno);
++ *newseg = segno;
++ write_unlock(&free_i->segmap_lock);
++}
++
++static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ struct summary_footer *sum_footer;
++
++ curseg->segno = curseg->next_segno;
++ curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno);
++ curseg->next_blkoff = 0;
++ curseg->next_segno = NULL_SEGNO;
++
++ sum_footer = &(curseg->sum_blk->footer);
++ memset(sum_footer, 0, sizeof(struct summary_footer));
++ if (IS_DATASEG(type))
++ SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA);
++ if (IS_NODESEG(type))
++ SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE);
++ __set_sit_entry_type(sbi, type, curseg->segno, modified);
++}
++
++/**
++ * Allocate a current working segment.
++ * This function always allocates a free segment in LFS manner.
++ */
++static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int segno = curseg->segno;
++ int dir = ALLOC_LEFT;
++
++ write_sum_page(sbi, curseg->sum_blk,
++ GET_SUM_BLOCK(sbi, curseg->segno));
++ if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA)
++ dir = ALLOC_RIGHT;
++
++ if (test_opt(sbi, NOHEAP))
++ dir = ALLOC_RIGHT;
++
++ get_new_segment(sbi, &segno, new_sec, dir);
++ curseg->next_segno = segno;
++ reset_curseg(sbi, type, 1);
++ curseg->alloc_type = LFS;
++}
++
++static void __next_free_blkoff(struct f2fs_sb_info *sbi,
++ struct curseg_info *seg, block_t start)
++{
++ struct seg_entry *se = get_seg_entry(sbi, seg->segno);
++ block_t ofs;
++ for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) {
++ if (!f2fs_test_bit(ofs, se->ckpt_valid_map)
++ && !f2fs_test_bit(ofs, se->cur_valid_map))
++ break;
++ }
++ seg->next_blkoff = ofs;
++}
++
++/**
++ * If a segment is written by LFS manner, next block offset is just obtained
++ * by increasing the current block offset. However, if a segment is written by
++ * SSR manner, next block offset obtained by calling __next_free_blkoff
++ */
++static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
++ struct curseg_info *seg)
++{
++ if (seg->alloc_type == SSR)
++ __next_free_blkoff(sbi, seg, seg->next_blkoff + 1);
++ else
++ seg->next_blkoff++;
++}
++
++/**
++ * This function always allocates a used segment (from dirty seglist) by SSR
++ * manner, so it should recover the existing segment information of valid blocks
++ */
++static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int new_segno = curseg->next_segno;
++ struct f2fs_summary_block *sum_node;
++ struct page *sum_page;
++
++ write_sum_page(sbi, curseg->sum_blk,
++ GET_SUM_BLOCK(sbi, curseg->segno));
++ __set_test_and_inuse(sbi, new_segno);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ __remove_dirty_segment(sbi, new_segno, PRE);
++ __remove_dirty_segment(sbi, new_segno, DIRTY);
++ mutex_unlock(&dirty_i->seglist_lock);
++
++ reset_curseg(sbi, type, 1);
++ curseg->alloc_type = SSR;
++ __next_free_blkoff(sbi, curseg, 0);
++
++ if (reuse) {
++ sum_page = get_sum_page(sbi, new_segno);
++ sum_node = (struct f2fs_summary_block *)page_address(sum_page);
++ memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
++ f2fs_put_page(sum_page, 1);
++ }
++}
++
++/*
++ * flush out current segment and replace it with new segment
++ * This function should be returned with success, otherwise BUG
++ */
++static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
++ int type, bool force)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ unsigned int ofs_unit;
++
++ if (force) {
++ new_curseg(sbi, type, true);
++ goto out;
++ }
++
++ ofs_unit = need_SSR(sbi) ? 1 : sbi->segs_per_sec;
++ curseg->next_segno = check_prefree_segments(sbi, ofs_unit, type);
++
++ if (curseg->next_segno != NULL_SEGNO)
++ change_curseg(sbi, type, false);
++ else if (type == CURSEG_WARM_NODE)
++ new_curseg(sbi, type, false);
++ else if (need_SSR(sbi) && IS_NEXT_SEG(sbi, curseg, type))
++ change_curseg(sbi, type, true);
++ else
++ new_curseg(sbi, type, false);
++out:
++ sbi->segment_count[curseg->alloc_type]++;
++}
++
++void allocate_new_segments(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *curseg;
++ unsigned int old_curseg;
++ int i;
++
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ curseg = CURSEG_I(sbi, i);
++ old_curseg = curseg->segno;
++ SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true);
++ locate_dirty_segment(sbi, old_curseg);
++ }
++}
++
++static const struct segment_allocation default_salloc_ops = {
++ .allocate_segment = allocate_segment_by_default,
++};
++
++static void f2fs_end_io_write(struct bio *bio, int err)
++{
++ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
++ struct bio_private *p = bio->bi_private;
++
++ do {
++ struct page *page = bvec->bv_page;
++
++ if (--bvec >= bio->bi_io_vec)
++ prefetchw(&bvec->bv_page->flags);
++ if (!uptodate) {
++ SetPageError(page);
++ if (page->mapping)
++ set_bit(AS_EIO, &page->mapping->flags);
++ p->sbi->ckpt->ckpt_flags |= CP_ERROR_FLAG;
++ set_page_dirty(page);
++ }
++ end_page_writeback(page);
++ dec_page_count(p->sbi, F2FS_WRITEBACK);
++ } while (bvec >= bio->bi_io_vec);
++
++ if (p->is_sync)
++ complete(p->wait);
++ kfree(p);
++ bio_put(bio);
++}
++
++struct bio *f2fs_bio_alloc(struct block_device *bdev, sector_t first_sector,
++ int nr_vecs, gfp_t gfp_flags)
++{
++ struct bio *bio;
++repeat:
++ /* allocate new bio */
++ bio = bio_alloc(gfp_flags, nr_vecs);
++
++ if (bio == NULL && (current->flags & PF_MEMALLOC)) {
++ while (!bio && (nr_vecs /= 2))
++ bio = bio_alloc(gfp_flags, nr_vecs);
++ }
++ if (bio) {
++ bio->bi_bdev = bdev;
++ bio->bi_sector = first_sector;
++retry:
++ bio->bi_private = kmalloc(sizeof(struct bio_private),
++ GFP_NOFS | __GFP_HIGH);
++ if (!bio->bi_private) {
++ cond_resched();
++ goto retry;
++ }
++ }
++ if (bio == NULL) {
++ cond_resched();
++ goto repeat;
++ }
++ return bio;
++}
++
++static void do_submit_bio(struct f2fs_sb_info *sbi,
++ enum page_type type, bool sync)
++{
++ int rw = sync ? WRITE_SYNC : WRITE;
++ enum page_type btype = type > META ? META : type;
++
++ if (type >= META_FLUSH)
++ rw = WRITE_FLUSH_FUA;
++
++ if (sbi->bio[btype]) {
++ struct bio_private *p = sbi->bio[btype]->bi_private;
++ p->sbi = sbi;
++ sbi->bio[btype]->bi_end_io = f2fs_end_io_write;
++ if (type == META_FLUSH) {
++ DECLARE_COMPLETION_ONSTACK(wait);
++ p->is_sync = true;
++ p->wait = &wait;
++ submit_bio(rw, sbi->bio[btype]);
++ wait_for_completion(&wait);
++ } else {
++ p->is_sync = false;
++ submit_bio(rw, sbi->bio[btype]);
++ }
++ sbi->bio[btype] = NULL;
++ }
++}
++
++void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync)
++{
++ down_write(&sbi->bio_sem);
++ do_submit_bio(sbi, type, sync);
++ up_write(&sbi->bio_sem);
++}
++
++static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t blk_addr, enum page_type type)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++
++ verify_block_addr(sbi, blk_addr);
++
++ down_write(&sbi->bio_sem);
++
++ inc_page_count(sbi, F2FS_WRITEBACK);
++
++ if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1)
++ do_submit_bio(sbi, type, false);
++alloc_new:
++ if (sbi->bio[type] == NULL)
++ sbi->bio[type] = f2fs_bio_alloc(bdev,
++ blk_addr << (sbi->log_blocksize - 9),
++ bio_get_nr_vecs(bdev), GFP_NOFS | __GFP_HIGH);
++
++ if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) <
++ PAGE_CACHE_SIZE) {
++ do_submit_bio(sbi, type, false);
++ goto alloc_new;
++ }
++
++ sbi->last_block_in_bio[type] = blk_addr;
++
++ up_write(&sbi->bio_sem);
++}
++
++static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, type);
++ if (curseg->next_blkoff < sbi->blocks_per_seg)
++ return true;
++ return false;
++}
++
++static int __get_segment_type_2(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA)
++ return CURSEG_HOT_DATA;
++ else
++ return CURSEG_HOT_NODE;
++}
++
++static int __get_segment_type_4(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA) {
++ struct inode *inode = page->mapping->host;
++
++ if (S_ISDIR(inode->i_mode))
++ return CURSEG_HOT_DATA;
++ else
++ return CURSEG_COLD_DATA;
++ } else {
++ if (IS_DNODE(page) && !is_cold_node(page))
++ return CURSEG_HOT_NODE;
++ else
++ return CURSEG_COLD_NODE;
++ }
++}
++
++static int __get_segment_type_6(struct page *page, enum page_type p_type)
++{
++ if (p_type == DATA) {
++ struct inode *inode = page->mapping->host;
++
++ if (S_ISDIR(inode->i_mode))
++ return CURSEG_HOT_DATA;
++ else if (is_cold_data(page) || is_cold_file(inode))
++ return CURSEG_COLD_DATA;
++ else
++ return CURSEG_WARM_DATA;
++ } else {
++ if (IS_DNODE(page))
++ return is_cold_node(page) ? CURSEG_WARM_NODE :
++ CURSEG_HOT_NODE;
++ else
++ return CURSEG_COLD_NODE;
++ }
++}
++
++static int __get_segment_type(struct page *page, enum page_type p_type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
++ switch (sbi->active_logs) {
++ case 2:
++ return __get_segment_type_2(page, p_type);
++ case 4:
++ return __get_segment_type_4(page, p_type);
++ case 6:
++ return __get_segment_type_6(page, p_type);
++ default:
++ BUG();
++ }
++}
++
++static void do_write_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t old_blkaddr, block_t *new_blkaddr,
++ struct f2fs_summary *sum, enum page_type p_type)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg;
++ unsigned int old_cursegno;
++ int type;
++
++ type = __get_segment_type(page, p_type);
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++
++ *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
++ old_cursegno = curseg->segno;
++
++ /*
++ * __add_sum_entry should be resided under the curseg_mutex
++ * because, this function updates a summary entry in the
++ * current summary block.
++ */
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ mutex_lock(&sit_i->sentry_lock);
++ __refresh_next_blkoff(sbi, curseg);
++ sbi->block_count[curseg->alloc_type]++;
++
++ /*
++ * SIT information should be updated before segment allocation,
++ * since SSR needs latest valid block information.
++ */
++ refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr);
++
++ if (!__has_curseg_space(sbi, type))
++ sit_i->s_ops->allocate_segment(sbi, type, false);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++ mutex_unlock(&sit_i->sentry_lock);
++
++ if (p_type == NODE)
++ fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
++
++ /* writeout dirty page into bdev */
++ submit_write_page(sbi, page, *new_blkaddr, p_type);
++
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++int write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
++ struct writeback_control *wbc)
++{
++ if (wbc->for_reclaim)
++ return AOP_WRITEPAGE_ACTIVATE;
++
++ set_page_writeback(page);
++ submit_write_page(sbi, page, page->index, META);
++ return 0;
++}
++
++void write_node_page(struct f2fs_sb_info *sbi, struct page *page,
++ unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr)
++{
++ struct f2fs_summary sum;
++ set_summary(&sum, nid, 0, 0);
++ do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE);
++}
++
++void write_data_page(struct inode *inode, struct page *page,
++ struct dnode_of_data *dn, block_t old_blkaddr,
++ block_t *new_blkaddr)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_summary sum;
++ struct node_info ni;
++
++ BUG_ON(old_blkaddr == NULL_ADDR);
++ get_node_info(sbi, dn->nid, &ni);
++ set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
++
++ do_write_page(sbi, page, old_blkaddr,
++ new_blkaddr, &sum, DATA);
++}
++
++void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page,
++ block_t old_blk_addr)
++{
++ submit_write_page(sbi, page, old_blk_addr, DATA);
++}
++
++void recover_data_page(struct f2fs_sb_info *sbi,
++ struct page *page, struct f2fs_summary *sum,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg;
++ unsigned int segno, old_cursegno;
++ struct seg_entry *se;
++ int type;
++
++ segno = GET_SEGNO(sbi, new_blkaddr);
++ se = get_seg_entry(sbi, segno);
++ type = se->type;
++
++ if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) {
++ if (old_blkaddr == NULL_ADDR)
++ type = CURSEG_COLD_DATA;
++ else
++ type = CURSEG_WARM_DATA;
++ }
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ old_cursegno = curseg->segno;
++
++ /* change the current segment */
++ if (segno != curseg->segno) {
++ curseg->next_segno = segno;
++ change_curseg(sbi, type, true);
++ }
++
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++void rewrite_node_page(struct f2fs_sb_info *sbi,
++ struct page *page, struct f2fs_summary *sum,
++ block_t old_blkaddr, block_t new_blkaddr)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ int type = CURSEG_WARM_NODE;
++ struct curseg_info *curseg;
++ unsigned int segno, old_cursegno;
++ block_t next_blkaddr = next_blkaddr_of_node(page);
++ unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
++
++ curseg = CURSEG_I(sbi, type);
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ segno = GET_SEGNO(sbi, new_blkaddr);
++ old_cursegno = curseg->segno;
++
++ /* change the current segment */
++ if (segno != curseg->segno) {
++ curseg->next_segno = segno;
++ change_curseg(sbi, type, true);
++ }
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ __add_sum_entry(sbi, type, sum, curseg->next_blkoff);
++
++ /* change the current log to the next block addr in advance */
++ if (next_segno != segno) {
++ curseg->next_segno = next_segno;
++ change_curseg(sbi, type, true);
++ }
++ curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) &
++ (sbi->blocks_per_seg - 1);
++
++ /* rewrite node page */
++ set_page_writeback(page);
++ submit_write_page(sbi, page, new_blkaddr, NODE);
++ f2fs_submit_bio(sbi, NODE, true);
++ refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
++
++ locate_dirty_segment(sbi, old_cursegno);
++ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
++
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++}
++
++static int read_compacted_summaries(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct curseg_info *seg_i;
++ unsigned char *kaddr;
++ struct page *page;
++ block_t start;
++ int i, j, offset;
++
++ start = start_sum_block(sbi);
++
++ page = get_meta_page(sbi, start++);
++ kaddr = (unsigned char *)page_address(page);
++
++ /* Step 1: restore nat cache */
++ seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE);
++
++ /* Step 2: restore sit cache */
++ seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE,
++ SUM_JOURNAL_SIZE);
++ offset = 2 * SUM_JOURNAL_SIZE;
++
++ /* Step 3: restore summary entries */
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ unsigned short blk_off;
++ unsigned int segno;
++
++ seg_i = CURSEG_I(sbi, i);
++ segno = le32_to_cpu(ckpt->cur_data_segno[i]);
++ blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]);
++ seg_i->next_segno = segno;
++ reset_curseg(sbi, i, 0);
++ seg_i->alloc_type = ckpt->alloc_type[i];
++ seg_i->next_blkoff = blk_off;
++
++ if (seg_i->alloc_type == SSR)
++ blk_off = sbi->blocks_per_seg;
++
++ for (j = 0; j < blk_off; j++) {
++ struct f2fs_summary *s;
++ s = (struct f2fs_summary *)(kaddr + offset);
++ seg_i->sum_blk->entries[j] = *s;
++ offset += SUMMARY_SIZE;
++ if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
++ SUM_FOOTER_SIZE)
++ continue;
++
++ f2fs_put_page(page, 1);
++ page = NULL;
++
++ page = get_meta_page(sbi, start++);
++ kaddr = (unsigned char *)page_address(page);
++ offset = 0;
++ }
++ }
++ f2fs_put_page(page, 1);
++ return 0;
++}
++
++static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
++{
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct f2fs_summary_block *sum;
++ struct curseg_info *curseg;
++ struct page *new;
++ unsigned short blk_off;
++ unsigned int segno = 0;
++ block_t blk_addr = 0;
++
++ /* get segment number and block addr */
++ if (IS_DATASEG(type)) {
++ segno = le32_to_cpu(ckpt->cur_data_segno[type]);
++ blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type -
++ CURSEG_HOT_DATA]);
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type);
++ else
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type);
++ } else {
++ segno = le32_to_cpu(ckpt->cur_node_segno[type -
++ CURSEG_HOT_NODE]);
++ blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type -
++ CURSEG_HOT_NODE]);
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE,
++ type - CURSEG_HOT_NODE);
++ else
++ blk_addr = GET_SUM_BLOCK(sbi, segno);
++ }
++
++ new = get_meta_page(sbi, blk_addr);
++ sum = (struct f2fs_summary_block *)page_address(new);
++
++ if (IS_NODESEG(type)) {
++ if (ckpt->ckpt_flags & CP_UMOUNT_FLAG) {
++ struct f2fs_summary *ns = &sum->entries[0];
++ int i;
++ for (i = 0; i < sbi->blocks_per_seg; i++, ns++) {
++ ns->version = 0;
++ ns->ofs_in_node = 0;
++ }
++ } else {
++ if (restore_node_summary(sbi, segno, sum)) {
++ f2fs_put_page(new, 1);
++ return -EINVAL;
++ }
++ }
++ }
++
++ /* set uncompleted segment to curseg */
++ curseg = CURSEG_I(sbi, type);
++ mutex_lock(&curseg->curseg_mutex);
++ memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE);
++ curseg->next_segno = segno;
++ reset_curseg(sbi, type, 0);
++ curseg->alloc_type = ckpt->alloc_type[type];
++ curseg->next_blkoff = blk_off;
++ mutex_unlock(&curseg->curseg_mutex);
++ f2fs_put_page(new, 1);
++ return 0;
++}
++
++static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
++{
++ int type = CURSEG_HOT_DATA;
++
++ if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG) {
++ /* restore for compacted data summary */
++ if (read_compacted_summaries(sbi))
++ return -EINVAL;
++ type = CURSEG_HOT_NODE;
++ }
++
++ for (; type <= CURSEG_COLD_NODE; type++)
++ if (read_normal_summaries(sbi, type))
++ return -EINVAL;
++ return 0;
++}
++
++static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
++{
++ struct page *page;
++ unsigned char *kaddr;
++ struct f2fs_summary *summary;
++ struct curseg_info *seg_i;
++ int written_size = 0;
++ int i, j;
++
++ page = grab_meta_page(sbi, blkaddr++);
++ kaddr = (unsigned char *)page_address(page);
++
++ /* Step 1: write nat cache */
++ seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
++ memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE);
++ written_size += SUM_JOURNAL_SIZE;
++
++ /* Step 2: write sit cache */
++ seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits,
++ SUM_JOURNAL_SIZE);
++ written_size += SUM_JOURNAL_SIZE;
++
++ set_page_dirty(page);
++
++ /* Step 3: write summary entries */
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
++ unsigned short blkoff;
++ seg_i = CURSEG_I(sbi, i);
++ if (sbi->ckpt->alloc_type[i] == SSR)
++ blkoff = sbi->blocks_per_seg;
++ else
++ blkoff = curseg_blkoff(sbi, i);
++
++ for (j = 0; j < blkoff; j++) {
++ if (!page) {
++ page = grab_meta_page(sbi, blkaddr++);
++ kaddr = (unsigned char *)page_address(page);
++ written_size = 0;
++ }
++ summary = (struct f2fs_summary *)(kaddr + written_size);
++ *summary = seg_i->sum_blk->entries[j];
++ written_size += SUMMARY_SIZE;
++ set_page_dirty(page);
++
++ if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
++ SUM_FOOTER_SIZE)
++ continue;
++
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++ }
++ if (page)
++ f2fs_put_page(page, 1);
++}
++
++static void write_normal_summaries(struct f2fs_sb_info *sbi,
++ block_t blkaddr, int type)
++{
++ int i, end;
++ if (IS_DATASEG(type))
++ end = type + NR_CURSEG_DATA_TYPE;
++ else
++ end = type + NR_CURSEG_NODE_TYPE;
++
++ for (i = type; i < end; i++) {
++ struct curseg_info *sum = CURSEG_I(sbi, i);
++ mutex_lock(&sum->curseg_mutex);
++ write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type));
++ mutex_unlock(&sum->curseg_mutex);
++ }
++}
++
++void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ if (sbi->ckpt->ckpt_flags & CP_COMPACT_SUM_FLAG)
++ write_compacted_summaries(sbi, start_blk);
++ else
++ write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
++}
++
++void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
++{
++ if (sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG)
++ write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
++ return;
++}
++
++int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type,
++ unsigned int val, int alloc)
++{
++ int i;
++
++ if (type == NAT_JOURNAL) {
++ for (i = 0; i < nats_in_cursum(sum); i++) {
++ if (le32_to_cpu(nid_in_journal(sum, i)) == val)
++ return i;
++ }
++ if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES)
++ return update_nats_in_cursum(sum, 1);
++ } else if (type == SIT_JOURNAL) {
++ for (i = 0; i < sits_in_cursum(sum); i++)
++ if (le32_to_cpu(segno_in_journal(sum, i)) == val)
++ return i;
++ if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES)
++ return update_sits_in_cursum(sum, 1);
++ }
++ return -1;
++}
++
++static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
++ unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno);
++ block_t blk_addr = sit_i->sit_base_addr + offset;
++
++ check_seg_range(sbi, segno);
++
++ /* calculate sit block address */
++ if (f2fs_test_bit(offset, sit_i->sit_bitmap))
++ blk_addr += sit_i->sit_blocks;
++
++ return get_meta_page(sbi, blk_addr);
++}
++
++static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
++ unsigned int start)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct page *src_page, *dst_page;
++ pgoff_t src_off, dst_off;
++ void *src_addr, *dst_addr;
++
++ src_off = current_sit_addr(sbi, start);
++ dst_off = next_sit_addr(sbi, src_off);
++
++ /* get current sit block page without lock */
++ src_page = get_meta_page(sbi, src_off);
++ dst_page = grab_meta_page(sbi, dst_off);
++ BUG_ON(PageDirty(src_page));
++
++ src_addr = page_address(src_page);
++ dst_addr = page_address(dst_page);
++ memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
++
++ set_page_dirty(dst_page);
++ f2fs_put_page(src_page, 1);
++
++ set_to_next_sit(sit_i, start);
++
++ return dst_page;
++}
++
++static bool flush_sits_in_journal(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ int i;
++
++ /*
++ * If the journal area in the current summary is full of sit entries,
++ * all the sit entries will be flushed. Otherwise the sit entries
++ * are not able to replace with newly hot sit entries.
++ */
++ if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) {
++ for (i = sits_in_cursum(sum) - 1; i >= 0; i--) {
++ unsigned int segno;
++ segno = le32_to_cpu(segno_in_journal(sum, i));
++ __mark_sit_entry_dirty(sbi, segno);
++ }
++ update_sits_in_cursum(sum, -sits_in_cursum(sum));
++ return 1;
++ }
++ return 0;
++}
++
++/**
++ * CP calls this function, which flushes SIT entries including sit_journal,
++ * and moves prefree segs to free segs.
++ */
++void flush_sit_entries(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned long *bitmap = sit_i->dirty_sentries_bitmap;
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ unsigned long nsegs = TOTAL_SEGS(sbi);
++ struct page *page = NULL;
++ struct f2fs_sit_block *raw_sit = NULL;
++ unsigned int start = 0, end = 0;
++ unsigned int segno = -1;
++ bool flushed;
++
++ mutex_lock(&curseg->curseg_mutex);
++ mutex_lock(&sit_i->sentry_lock);
++
++ /*
++ * "flushed" indicates whether sit entries in journal are flushed
++ * to the SIT area or not.
++ */
++ flushed = flush_sits_in_journal(sbi);
++
++ while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) {
++ struct seg_entry *se = get_seg_entry(sbi, segno);
++ int sit_offset, offset;
++
++ sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
++
++ if (flushed)
++ goto to_sit_page;
++
++ offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1);
++ if (offset >= 0) {
++ segno_in_journal(sum, offset) = cpu_to_le32(segno);
++ seg_info_to_raw_sit(se, &sit_in_journal(sum, offset));
++ goto flush_done;
++ }
++to_sit_page:
++ if (!page || (start > segno) || (segno > end)) {
++ if (page) {
++ f2fs_put_page(page, 1);
++ page = NULL;
++ }
++
++ start = START_SEGNO(sit_i, segno);
++ end = start + SIT_ENTRY_PER_BLOCK - 1;
++
++ /* read sit block that will be updated */
++ page = get_next_sit_page(sbi, start);
++ raw_sit = page_address(page);
++ }
++
++ /* udpate entry in SIT block */
++ seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]);
++flush_done:
++ __clear_bit(segno, bitmap);
++ sit_i->dirty_sentries--;
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ mutex_unlock(&curseg->curseg_mutex);
++
++ /* writeout last modified SIT block */
++ f2fs_put_page(page, 1);
++
++ set_prefree_as_free_segments(sbi);
++}
++
++static int build_sit_info(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct sit_info *sit_i;
++ unsigned int sit_segs, start;
++ char *src_bitmap, *dst_bitmap;
++ unsigned int bitmap_size;
++
++ /* allocate memory for SIT information */
++ sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL);
++ if (!sit_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->sit_info = sit_i;
++
++ sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry));
++ if (!sit_i->sentries)
++ return -ENOMEM;
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!sit_i->dirty_sentries_bitmap)
++ return -ENOMEM;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ sit_i->sentries[start].cur_valid_map
++ = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
++ sit_i->sentries[start].ckpt_valid_map
++ = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL);
++ if (!sit_i->sentries[start].cur_valid_map
++ || !sit_i->sentries[start].ckpt_valid_map)
++ return -ENOMEM;
++ }
++
++ if (sbi->segs_per_sec > 1) {
++ sit_i->sec_entries = vzalloc(sbi->total_sections *
++ sizeof(struct sec_entry));
++ if (!sit_i->sec_entries)
++ return -ENOMEM;
++ }
++
++ /* get information related with SIT */
++ sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1;
++
++ /* setup SIT bitmap from ckeckpoint pack */
++ bitmap_size = __bitmap_size(sbi, SIT_BITMAP);
++ src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP);
++
++ dst_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!dst_bitmap)
++ return -ENOMEM;
++ memcpy(dst_bitmap, src_bitmap, bitmap_size);
++
++ /* init SIT information */
++ sit_i->s_ops = &default_salloc_ops;
++
++ sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr);
++ sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg;
++ sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count);
++ sit_i->sit_bitmap = dst_bitmap;
++ sit_i->bitmap_size = bitmap_size;
++ sit_i->dirty_sentries = 0;
++ sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
++ sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
++ sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec;
++ mutex_init(&sit_i->sentry_lock);
++ return 0;
++}
++
++static int build_free_segmap(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ struct free_segmap_info *free_i;
++ unsigned int bitmap_size, sec_bitmap_size;
++
++ /* allocate memory for free segmap information */
++ free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL);
++ if (!free_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->free_info = free_i;
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL);
++ if (!free_i->free_segmap)
++ return -ENOMEM;
++
++ sec_bitmap_size = f2fs_bitmap_size(sbi->total_sections);
++ free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL);
++ if (!free_i->free_secmap)
++ return -ENOMEM;
++
++ /* set all segments as dirty temporarily */
++ memset(free_i->free_segmap, 0xff, bitmap_size);
++ memset(free_i->free_secmap, 0xff, sec_bitmap_size);
++
++ /* init free segmap information */
++ free_i->start_segno =
++ (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr);
++ free_i->free_segments = 0;
++ free_i->free_sections = 0;
++ rwlock_init(&free_i->segmap_lock);
++ return 0;
++}
++
++static int build_curseg(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *array = NULL;
++ int i;
++
++ array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
++ if (!array)
++ return -ENOMEM;
++
++ SM_I(sbi)->curseg_array = array;
++
++ for (i = 0; i < NR_CURSEG_TYPE; i++) {
++ mutex_init(&array[i].curseg_mutex);
++ array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL);
++ if (!array[i].sum_blk)
++ return -ENOMEM;
++ array[i].segno = NULL_SEGNO;
++ array[i].next_blkoff = 0;
++ }
++ return restore_curseg_summaries(sbi);
++}
++
++static void build_sit_entries(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA);
++ struct f2fs_summary_block *sum = curseg->sum_blk;
++ unsigned int start;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ struct seg_entry *se = &sit_i->sentries[start];
++ struct f2fs_sit_block *sit_blk;
++ struct f2fs_sit_entry sit;
++ struct page *page;
++ int i;
++
++ mutex_lock(&curseg->curseg_mutex);
++ for (i = 0; i < sits_in_cursum(sum); i++) {
++ if (le32_to_cpu(segno_in_journal(sum, i)) == start) {
++ sit = sit_in_journal(sum, i);
++ mutex_unlock(&curseg->curseg_mutex);
++ goto got_it;
++ }
++ }
++ mutex_unlock(&curseg->curseg_mutex);
++ page = get_current_sit_page(sbi, start);
++ sit_blk = (struct f2fs_sit_block *)page_address(page);
++ sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)];
++ f2fs_put_page(page, 1);
++got_it:
++ check_block_count(sbi, start, &sit);
++ seg_info_from_raw_sit(se, &sit);
++ if (sbi->segs_per_sec > 1) {
++ struct sec_entry *e = get_sec_entry(sbi, start);
++ e->valid_blocks += se->valid_blocks;
++ }
++ }
++}
++
++static void init_free_segmap(struct f2fs_sb_info *sbi)
++{
++ unsigned int start;
++ int type;
++
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ struct seg_entry *sentry = get_seg_entry(sbi, start);
++ if (!sentry->valid_blocks)
++ __set_free(sbi, start);
++ }
++
++ /* set use the current segments */
++ for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) {
++ struct curseg_info *curseg_t = CURSEG_I(sbi, type);
++ __set_test_and_inuse(sbi, curseg_t->segno);
++ }
++}
++
++static void init_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct free_segmap_info *free_i = FREE_I(sbi);
++ unsigned int segno = 0, offset = 0;
++ unsigned short valid_blocks;
++
++ while (segno < TOTAL_SEGS(sbi)) {
++ /* find dirty segment based on free segmap */
++ segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset);
++ if (segno >= TOTAL_SEGS(sbi))
++ break;
++ offset = segno + 1;
++ valid_blocks = get_valid_blocks(sbi, segno, 0);
++ if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks)
++ continue;
++ mutex_lock(&dirty_i->seglist_lock);
++ __locate_dirty_segment(sbi, segno, DIRTY);
++ mutex_unlock(&dirty_i->seglist_lock);
++ }
++}
++
++static int init_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ dirty_i->victim_segmap[FG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
++ dirty_i->victim_segmap[BG_GC] = kzalloc(bitmap_size, GFP_KERNEL);
++ if (!dirty_i->victim_segmap[FG_GC] || !dirty_i->victim_segmap[BG_GC])
++ return -ENOMEM;
++ return 0;
++}
++
++static int build_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i;
++ unsigned int bitmap_size, i;
++
++ /* allocate memory for dirty segments list information */
++ dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL);
++ if (!dirty_i)
++ return -ENOMEM;
++
++ SM_I(sbi)->dirty_info = dirty_i;
++ mutex_init(&dirty_i->seglist_lock);
++
++ bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ for (i = 0; i < NR_DIRTY_TYPE; i++) {
++ dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL);
++ dirty_i->nr_dirty[i] = 0;
++ if (!dirty_i->dirty_segmap[i])
++ return -ENOMEM;
++ }
++
++ init_dirty_segmap(sbi);
++ return init_victim_segmap(sbi);
++}
++
++/**
++ * Update min, max modified time for cost-benefit GC algorithm
++ */
++static void init_min_max_mtime(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno;
++
++ mutex_lock(&sit_i->sentry_lock);
++
++ sit_i->min_mtime = LLONG_MAX;
++
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ unsigned int i;
++ unsigned long long mtime = 0;
++
++ for (i = 0; i < sbi->segs_per_sec; i++)
++ mtime += get_seg_entry(sbi, segno + i)->mtime;
++
++ mtime = div_u64(mtime, sbi->segs_per_sec);
++
++ if (sit_i->min_mtime > mtime)
++ sit_i->min_mtime = mtime;
++ }
++ sit_i->max_mtime = get_mtime(sbi);
++ mutex_unlock(&sit_i->sentry_lock);
++}
++
++int build_segment_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
++ struct f2fs_sm_info *sm_info = NULL;
++
++ sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL);
++ if (!sm_info)
++ return -ENOMEM;
++
++ /* init sm info */
++ sbi->sm_info = sm_info;
++ INIT_LIST_HEAD(&sm_info->wblist_head);
++ spin_lock_init(&sm_info->wblist_lock);
++ sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
++ sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
++ sm_info->segment_count = le32_to_cpu(raw_super->segment_count);
++ sm_info->rsvd_segment_count =
++ le32_to_cpu(ckpt->rsvd_segment_count);
++ sm_info->main_segment_count =
++ le32_to_cpu(raw_super->segment_count_main);
++ sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
++ sm_info->segment_count_ssa =
++ le32_to_cpu(raw_super->segment_count_ssa);
++
++ if (build_sit_info(sbi))
++ return -EINVAL;
++ if (build_free_segmap(sbi))
++ return -EINVAL;
++ if (build_curseg(sbi))
++ return -EINVAL;
++
++ /* reinit free segmap based on SIT */
++ build_sit_entries(sbi);
++
++ init_free_segmap(sbi);
++ if (build_dirty_segmap(sbi))
++ return -EINVAL;
++
++ init_min_max_mtime(sbi);
++ return 0;
++}
++
++static void discard_dirty_segmap(struct f2fs_sb_info *sbi,
++ enum dirty_type dirty_type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ mutex_lock(&dirty_i->seglist_lock);
++ kfree(dirty_i->dirty_segmap[dirty_type]);
++ dirty_i->nr_dirty[dirty_type] = 0;
++ mutex_unlock(&dirty_i->seglist_lock);
++}
++
++void reset_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ memset(DIRTY_I(sbi)->victim_segmap[FG_GC], 0, bitmap_size);
++}
++
++static void destroy_victim_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ kfree(dirty_i->victim_segmap[FG_GC]);
++ kfree(dirty_i->victim_segmap[BG_GC]);
++}
++
++static void destroy_dirty_segmap(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ int i;
++
++ if (!dirty_i)
++ return;
++
++ /* discard pre-free/dirty segments list */
++ for (i = 0; i < NR_DIRTY_TYPE; i++)
++ discard_dirty_segmap(sbi, i);
++
++ destroy_victim_segmap(sbi);
++ SM_I(sbi)->dirty_info = NULL;
++ kfree(dirty_i);
++}
++
++static void destroy_curseg(struct f2fs_sb_info *sbi)
++{
++ struct curseg_info *array = SM_I(sbi)->curseg_array;
++ int i;
++
++ if (!array)
++ return;
++ SM_I(sbi)->curseg_array = NULL;
++ for (i = 0; i < NR_CURSEG_TYPE; i++)
++ kfree(array[i].sum_blk);
++ kfree(array);
++}
++
++static void destroy_free_segmap(struct f2fs_sb_info *sbi)
++{
++ struct free_segmap_info *free_i = SM_I(sbi)->free_info;
++ if (!free_i)
++ return;
++ SM_I(sbi)->free_info = NULL;
++ kfree(free_i->free_segmap);
++ kfree(free_i->free_secmap);
++ kfree(free_i);
++}
++
++static void destroy_sit_info(struct f2fs_sb_info *sbi)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int start;
++
++ if (!sit_i)
++ return;
++
++ if (sit_i->sentries) {
++ for (start = 0; start < TOTAL_SEGS(sbi); start++) {
++ kfree(sit_i->sentries[start].cur_valid_map);
++ kfree(sit_i->sentries[start].ckpt_valid_map);
++ }
++ }
++ vfree(sit_i->sentries);
++ vfree(sit_i->sec_entries);
++ kfree(sit_i->dirty_sentries_bitmap);
++
++ SM_I(sbi)->sit_info = NULL;
++ kfree(sit_i->sit_bitmap);
++ kfree(sit_i);
++}
++
++void destroy_segment_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_sm_info *sm_info = SM_I(sbi);
++ destroy_dirty_segmap(sbi);
++ destroy_curseg(sbi);
++ destroy_free_segmap(sbi);
++ destroy_sit_info(sbi);
++ sbi->sm_info = NULL;
++ kfree(sm_info);
++}
diff --git a/patches/linux-3.7/0107-f2fs-add-file-operations.patch b/patches/linux-3.7/0107-f2fs-add-file-operations.patch
new file mode 100644
index 0000000..1739ca8
--- /dev/null
+++ b/patches/linux-3.7/0107-f2fs-add-file-operations.patch
@@ -0,0 +1,660 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:29:21 +0000
+Subject: [PATCH] f2fs: add file operations
+
+This adds memory operations and file/file_inode operations.
+
+- F2FS supports fallocate(), mmap(), fsync(), and basic ioctl().
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/file.c | 640 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 640 insertions(+)
+ create mode 100644 fs/f2fs/file.c
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+new file mode 100644
+index 0000000..81b1fd0
+--- /dev/null
++++ b/fs/f2fs/file.c
+@@ -0,0 +1,640 @@
++/**
++ * fs/f2fs/file.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/stat.h>
++#include <linux/buffer_head.h>
++#include <linux/writeback.h>
++#include <linux/falloc.h>
++#include <linux/types.h>
++#include <linux/uaccess.h>
++#include <linux/mount.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "xattr.h"
++#include "acl.h"
++
++static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
++ struct vm_fault *vmf)
++{
++ struct page *page = vmf->page;
++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *node_page;
++ block_t old_blk_addr;
++ struct dnode_of_data dn;
++ int err;
++
++ f2fs_balance_fs(sbi);
++
++ sb_start_pagefault(inode->i_sb);
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ /* block allocation */
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, page->index, 0);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ goto out;
++ }
++
++ old_blk_addr = dn.data_blkaddr;
++ node_page = dn.node_page;
++
++ if (old_blk_addr == NULL_ADDR) {
++ err = reserve_new_block(&dn);
++ if (err) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ goto out;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ lock_page(page);
++ if (page->mapping != inode->i_mapping ||
++ page_offset(page) >= i_size_read(inode) ||
++ !PageUptodate(page)) {
++ unlock_page(page);
++ err = -EFAULT;
++ goto out;
++ }
++
++ /*
++ * check to see if the page is mapped already (no holes)
++ */
++ if (PageMappedToDisk(page))
++ goto out;
++
++ /* fill the page */
++ wait_on_page_writeback(page);
++
++ /* page is wholly or partially inside EOF */
++ if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) {
++ unsigned offset;
++ offset = i_size_read(inode) & ~PAGE_CACHE_MASK;
++ zero_user_segment(page, offset, PAGE_CACHE_SIZE);
++ }
++ set_page_dirty(page);
++ SetPageUptodate(page);
++
++ file_update_time(vma->vm_file);
++out:
++ sb_end_pagefault(inode->i_sb);
++ return block_page_mkwrite_return(err);
++}
++
++static const struct vm_operations_struct f2fs_file_vm_ops = {
++ .fault = filemap_fault,
++ .page_mkwrite = f2fs_vm_page_mkwrite,
++};
++
++static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
++{
++ struct dentry *dentry;
++ nid_t pino;
++
++ inode = igrab(inode);
++ dentry = d_find_any_alias(inode);
++ if (!dentry) {
++ iput(inode);
++ return 0;
++ }
++ pino = dentry->d_parent->d_inode->i_ino;
++ dput(dentry);
++ iput(inode);
++ return !is_checkpointed_node(sbi, pino);
++}
++
++int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
++{
++ struct inode *inode = file->f_mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ unsigned long long cur_version;
++ int ret = 0;
++ bool need_cp = false;
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++
++ ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
++ if (ret)
++ return ret;
++
++ mutex_lock(&inode->i_mutex);
++
++ if (inode->i_sb->s_flags & MS_RDONLY)
++ goto out;
++ if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
++ goto out;
++
++ mutex_lock(&sbi->cp_mutex);
++ cur_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
++ mutex_unlock(&sbi->cp_mutex);
++
++ if (F2FS_I(inode)->data_version != cur_version &&
++ !(inode->i_state & I_DIRTY))
++ goto out;
++ F2FS_I(inode)->data_version--;
++
++ if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
++ need_cp = true;
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEED_CP))
++ need_cp = true;
++ if (!space_for_roll_forward(sbi))
++ need_cp = true;
++ if (need_to_sync_dir(sbi, inode))
++ need_cp = true;
++
++ f2fs_write_inode(inode, NULL);
++
++ if (need_cp) {
++ /* all the dirty node pages should be flushed for POR */
++ ret = f2fs_sync_fs(inode->i_sb, 1);
++ clear_inode_flag(F2FS_I(inode), FI_NEED_CP);
++ } else {
++ while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0)
++ f2fs_write_inode(inode, NULL);
++ filemap_fdatawait_range(sbi->node_inode->i_mapping,
++ 0, LONG_MAX);
++ }
++out:
++ mutex_unlock(&inode->i_mutex);
++ return ret;
++}
++
++static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ file_accessed(file);
++ vma->vm_ops = &f2fs_file_vm_ops;
++ return 0;
++}
++
++static int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
++{
++ int nr_free = 0, ofs = dn->ofs_in_node;
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++ struct f2fs_node *raw_node;
++ __le32 *addr;
++
++ raw_node = page_address(dn->node_page);
++ addr = blkaddr_in_node(raw_node) + ofs;
++
++ for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
++ block_t blkaddr = le32_to_cpu(*addr);
++ if (blkaddr == NULL_ADDR)
++ continue;
++
++ update_extent_cache(NULL_ADDR, dn);
++ invalidate_blocks(sbi, blkaddr);
++ dec_valid_block_count(sbi, dn->inode, 1);
++ nr_free++;
++ }
++ if (nr_free) {
++ set_page_dirty(dn->node_page);
++ sync_inode_page(dn);
++ }
++ dn->ofs_in_node = ofs;
++ return nr_free;
++}
++
++void truncate_data_blocks(struct dnode_of_data *dn)
++{
++ truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
++}
++
++static void truncate_partial_data_page(struct inode *inode, u64 from)
++{
++ unsigned offset = from & (PAGE_CACHE_SIZE - 1);
++ struct page *page;
++
++ if (!offset)
++ return;
++
++ page = find_data_page(inode, from >> PAGE_CACHE_SHIFT);
++ if (IS_ERR(page))
++ return;
++
++ lock_page(page);
++ wait_on_page_writeback(page);
++ zero_user(page, offset, PAGE_CACHE_SIZE - offset);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++}
++
++static int truncate_blocks(struct inode *inode, u64 from)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ unsigned int blocksize = inode->i_sb->s_blocksize;
++ struct dnode_of_data dn;
++ pgoff_t free_from;
++ int count = 0;
++ int err;
++
++ free_from = (pgoff_t)
++ ((from + blocksize - 1) >> (sbi->log_blocksize));
++
++ mutex_lock_op(sbi, DATA_TRUNC);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
++ if (err) {
++ if (err == -ENOENT)
++ goto free_next;
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ return err;
++ }
++
++ if (IS_INODE(dn.node_page))
++ count = ADDRS_PER_INODE;
++ else
++ count = ADDRS_PER_BLOCK;
++
++ count -= dn.ofs_in_node;
++ BUG_ON(count < 0);
++ if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
++ truncate_data_blocks_range(&dn, count);
++ free_from += count;
++ }
++
++ f2fs_put_dnode(&dn);
++free_next:
++ err = truncate_inode_blocks(inode, free_from);
++ mutex_unlock_op(sbi, DATA_TRUNC);
++
++ /* lastly zero out the first data page */
++ truncate_partial_data_page(inode, from);
++
++ return err;
++}
++
++void f2fs_truncate(struct inode *inode)
++{
++ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
++ S_ISLNK(inode->i_mode)))
++ return;
++
++ if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
++ return;
++
++ if (!truncate_blocks(inode, i_size_read(inode))) {
++ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(inode);
++ }
++
++ f2fs_balance_fs(F2FS_SB(inode->i_sb));
++}
++
++static int f2fs_getattr(struct vfsmount *mnt,
++ struct dentry *dentry, struct kstat *stat)
++{
++ struct inode *inode = dentry->d_inode;
++ generic_fillattr(inode, stat);
++ stat->blocks <<= 3;
++ return 0;
++}
++
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++static void __setattr_copy(struct inode *inode, const struct iattr *attr)
++{
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ unsigned int ia_valid = attr->ia_valid;
++
++ if (ia_valid & ATTR_UID)
++ inode->i_uid = attr->ia_uid;
++ if (ia_valid & ATTR_GID)
++ inode->i_gid = attr->ia_gid;
++ if (ia_valid & ATTR_ATIME)
++ inode->i_atime = timespec_trunc(attr->ia_atime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MTIME)
++ inode->i_mtime = timespec_trunc(attr->ia_mtime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_CTIME)
++ inode->i_ctime = timespec_trunc(attr->ia_ctime,
++ inode->i_sb->s_time_gran);
++ if (ia_valid & ATTR_MODE) {
++ umode_t mode = attr->ia_mode;
++
++ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
++ mode &= ~S_ISGID;
++ set_acl_inode(fi, mode);
++ }
++}
++#else
++#define __setattr_copy setattr_copy
++#endif
++
++int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
++{
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ int err;
++
++ err = inode_change_ok(inode, attr);
++ if (err)
++ return err;
++
++ if ((attr->ia_valid & ATTR_SIZE) &&
++ attr->ia_size != i_size_read(inode)) {
++ truncate_setsize(inode, attr->ia_size);
++ f2fs_truncate(inode);
++ }
++
++ __setattr_copy(inode, attr);
++
++ if (attr->ia_valid & ATTR_MODE) {
++ err = f2fs_acl_chmod(inode);
++ if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
++ inode->i_mode = fi->i_acl_mode;
++ clear_inode_flag(fi, FI_ACL_MODE);
++ }
++ }
++
++ mark_inode_dirty(inode);
++ return err;
++}
++
++const struct inode_operations f2fs_file_inode_operations = {
++ .getattr = f2fs_getattr,
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++static void fill_zero(struct inode *inode, pgoff_t index,
++ loff_t start, loff_t len)
++{
++ struct page *page;
++
++ if (!len)
++ return;
++
++ page = get_new_data_page(inode, index, false);
++
++ if (!IS_ERR(page)) {
++ wait_on_page_writeback(page);
++ zero_user(page, start, len);
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++ }
++}
++
++int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
++{
++ pgoff_t index;
++ int err;
++
++ for (index = pg_start; index < pg_end; index++) {
++ struct dnode_of_data dn;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++
++ mutex_lock_op(sbi, DATA_TRUNC);
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ if (err == -ENOENT)
++ continue;
++ return err;
++ }
++
++ if (dn.data_blkaddr != NULL_ADDR)
++ truncate_data_blocks_range(&dn, 1);
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_TRUNC);
++ }
++ return 0;
++}
++
++static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
++{
++ pgoff_t pg_start, pg_end;
++ loff_t off_start, off_end;
++ int ret = 0;
++
++ pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
++ pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
++
++ off_start = offset & (PAGE_CACHE_SIZE - 1);
++ off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
++
++ if (pg_start == pg_end) {
++ fill_zero(inode, pg_start, off_start,
++ off_end - off_start);
++ } else {
++ if (off_start)
++ fill_zero(inode, pg_start++, off_start,
++ PAGE_CACHE_SIZE - off_start);
++ if (off_end)
++ fill_zero(inode, pg_end, 0, off_end);
++
++ if (pg_start < pg_end) {
++ struct address_space *mapping = inode->i_mapping;
++ loff_t blk_start, blk_end;
++
++ blk_start = pg_start << PAGE_CACHE_SHIFT;
++ blk_end = pg_end << PAGE_CACHE_SHIFT;
++ truncate_inode_pages_range(mapping, blk_start,
++ blk_end - 1);
++ ret = truncate_hole(inode, pg_start, pg_end);
++ }
++ }
++
++ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
++ i_size_read(inode) <= (offset + len)) {
++ i_size_write(inode, offset);
++ mark_inode_dirty(inode);
++ }
++
++ return ret;
++}
++
++static int expand_inode_data(struct inode *inode, loff_t offset,
++ loff_t len, int mode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ pgoff_t index, pg_start, pg_end;
++ loff_t new_size = i_size_read(inode);
++ loff_t off_start, off_end;
++ int ret = 0;
++
++ ret = inode_newsize_ok(inode, (len + offset));
++ if (ret)
++ return ret;
++
++ pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
++ pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
++
++ off_start = offset & (PAGE_CACHE_SIZE - 1);
++ off_end = (offset + len) & (PAGE_CACHE_SIZE - 1);
++
++ for (index = pg_start; index <= pg_end; index++) {
++ struct dnode_of_data dn;
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ ret = get_dnode_of_data(&dn, index, 0);
++ if (ret) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ break;
++ }
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ ret = reserve_new_block(&dn);
++ if (ret) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ break;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ if (pg_start == pg_end)
++ new_size = offset + len;
++ else if (index == pg_start && off_start)
++ new_size = (index + 1) << PAGE_CACHE_SHIFT;
++ else if (index == pg_end)
++ new_size = (index << PAGE_CACHE_SHIFT) + off_end;
++ else
++ new_size += PAGE_CACHE_SIZE;
++ }
++
++ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
++ i_size_read(inode) < new_size) {
++ i_size_write(inode, new_size);
++ mark_inode_dirty(inode);
++ }
++
++ return ret;
++}
++
++static long f2fs_fallocate(struct file *file, int mode,
++ loff_t offset, loff_t len)
++{
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ long ret;
++
++ if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
++ return -EOPNOTSUPP;
++
++ if (mode & FALLOC_FL_PUNCH_HOLE)
++ ret = punch_hole(inode, offset, len, mode);
++ else
++ ret = expand_inode_data(inode, offset, len, mode);
++
++ f2fs_balance_fs(sbi);
++ return ret;
++}
++
++#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
++#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
++
++static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
++{
++ if (S_ISDIR(mode))
++ return flags;
++ else if (S_ISREG(mode))
++ return flags & F2FS_REG_FLMASK;
++ else
++ return flags & F2FS_OTHER_FLMASK;
++}
++
++long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++{
++ struct inode *inode = filp->f_dentry->d_inode;
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ unsigned int flags;
++ int ret;
++
++ switch (cmd) {
++ case FS_IOC_GETFLAGS:
++ flags = fi->i_flags & FS_FL_USER_VISIBLE;
++ return put_user(flags, (int __user *) arg);
++ case FS_IOC_SETFLAGS:
++ {
++ unsigned int oldflags;
++
++ ret = mnt_want_write(filp->f_path.mnt);
++ if (ret)
++ return ret;
++
++ if (!inode_owner_or_capable(inode)) {
++ ret = -EACCES;
++ goto out;
++ }
++
++ if (get_user(flags, (int __user *) arg)) {
++ ret = -EFAULT;
++ goto out;
++ }
++
++ flags = f2fs_mask_flags(inode->i_mode, flags);
++
++ mutex_lock(&inode->i_mutex);
++
++ oldflags = fi->i_flags;
++
++ if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
++ if (!capable(CAP_LINUX_IMMUTABLE)) {
++ mutex_unlock(&inode->i_mutex);
++ ret = -EPERM;
++ goto out;
++ }
++ }
++
++ flags = flags & FS_FL_USER_MODIFIABLE;
++ flags |= oldflags & ~FS_FL_USER_MODIFIABLE;
++ fi->i_flags = flags;
++ mutex_unlock(&inode->i_mutex);
++
++ f2fs_set_inode_flags(inode);
++ inode->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(inode);
++out:
++ mnt_drop_write(filp->f_path.mnt);
++ return ret;
++ }
++ default:
++ return -ENOTTY;
++ }
++}
++
++const struct file_operations f2fs_file_operations = {
++ .llseek = generic_file_llseek,
++ .read = do_sync_read,
++ .write = do_sync_write,
++ .aio_read = generic_file_aio_read,
++ .aio_write = generic_file_aio_write,
++ .open = generic_file_open,
++ .mmap = f2fs_file_mmap,
++ .fsync = f2fs_sync_file,
++ .fallocate = f2fs_fallocate,
++ .unlocked_ioctl = f2fs_ioctl,
++ .splice_read = generic_file_splice_read,
++ .splice_write = generic_file_splice_write,
++};
diff --git a/patches/linux-3.7/0108-f2fs-add-address-space-operations-for-data.patch b/patches/linux-3.7/0108-f2fs-add-address-space-operations-for-data.patch
new file mode 100644
index 0000000..b2a51bf
--- /dev/null
+++ b/patches/linux-3.7/0108-f2fs-add-address-space-operations-for-data.patch
@@ -0,0 +1,723 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:29:49 +0000
+Subject: [PATCH] f2fs: add address space operations for data
+
+This adds address space operations for data.
+
+- F2FS supports readpages(), writepages(), and direct_IO().
+
+- Because of out-of-place writes, f2fs_direct_IO() does not write data in place.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/data.c | 701 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 701 insertions(+)
+ create mode 100644 fs/f2fs/data.c
+
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+new file mode 100644
+index 0000000..c2fd0a8
+--- /dev/null
++++ b/fs/f2fs/data.c
+@@ -0,0 +1,701 @@
++/**
++ * fs/f2fs/data.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/mpage.h>
++#include <linux/writeback.h>
++#include <linux/backing-dev.h>
++#include <linux/blkdev.h>
++#include <linux/bio.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++/**
++ * Lock ordering for the change of data block address:
++ * ->data_page
++ * ->node_page
++ * update block addresses in the node page
++ */
++static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr)
++{
++ struct f2fs_node *rn;
++ __le32 *addr_array;
++ struct page *node_page = dn->node_page;
++ unsigned int ofs_in_node = dn->ofs_in_node;
++
++ wait_on_page_writeback(node_page);
++
++ rn = (struct f2fs_node *)page_address(node_page);
++
++ /* Get physical address of data block */
++ addr_array = blkaddr_in_node(rn);
++ addr_array[ofs_in_node] = cpu_to_le32(new_addr);
++ set_page_dirty(node_page);
++}
++
++int reserve_new_block(struct dnode_of_data *dn)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
++
++ if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))
++ return -EPERM;
++ if (!inc_valid_block_count(sbi, dn->inode, 1))
++ return -ENOSPC;
++
++ __set_data_blkaddr(dn, NEW_ADDR);
++ dn->data_blkaddr = NEW_ADDR;
++ sync_inode_page(dn);
++ return 0;
++}
++
++static int check_extent_cache(struct inode *inode, pgoff_t pgofs,
++ struct buffer_head *bh_result)
++{
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ pgoff_t start_fofs, end_fofs;
++ block_t start_blkaddr;
++
++ read_lock(&fi->ext.ext_lock);
++ if (fi->ext.len == 0) {
++ read_unlock(&fi->ext.ext_lock);
++ return 0;
++ }
++
++ sbi->total_hit_ext++;
++ start_fofs = fi->ext.fofs;
++ end_fofs = fi->ext.fofs + fi->ext.len - 1;
++ start_blkaddr = fi->ext.blk_addr;
++
++ if (pgofs >= start_fofs && pgofs <= end_fofs) {
++ unsigned int blkbits = inode->i_sb->s_blocksize_bits;
++ size_t count;
++
++ clear_buffer_new(bh_result);
++ map_bh(bh_result, inode->i_sb,
++ start_blkaddr + pgofs - start_fofs);
++ count = end_fofs - pgofs + 1;
++ if (count < (UINT_MAX >> blkbits))
++ bh_result->b_size = (count << blkbits);
++ else
++ bh_result->b_size = UINT_MAX;
++
++ sbi->read_hit_ext++;
++ read_unlock(&fi->ext.ext_lock);
++ return 1;
++ }
++ read_unlock(&fi->ext.ext_lock);
++ return 0;
++}
++
++void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn)
++{
++ struct f2fs_inode_info *fi = F2FS_I(dn->inode);
++ pgoff_t fofs, start_fofs, end_fofs;
++ block_t start_blkaddr, end_blkaddr;
++
++ BUG_ON(blk_addr == NEW_ADDR);
++ fofs = start_bidx_of_node(ofs_of_node(dn->node_page)) + dn->ofs_in_node;
++
++ /* Update the page address in the parent node */
++ __set_data_blkaddr(dn, blk_addr);
++
++ write_lock(&fi->ext.ext_lock);
++
++ start_fofs = fi->ext.fofs;
++ end_fofs = fi->ext.fofs + fi->ext.len - 1;
++ start_blkaddr = fi->ext.blk_addr;
++ end_blkaddr = fi->ext.blk_addr + fi->ext.len - 1;
++
++ /* Drop and initialize the matched extent */
++ if (fi->ext.len == 1 && fofs == start_fofs)
++ fi->ext.len = 0;
++
++ /* Initial extent */
++ if (fi->ext.len == 0) {
++ if (blk_addr != NULL_ADDR) {
++ fi->ext.fofs = fofs;
++ fi->ext.blk_addr = blk_addr;
++ fi->ext.len = 1;
++ }
++ goto end_update;
++ }
++
++ /* Frone merge */
++ if (fofs == start_fofs - 1 && blk_addr == start_blkaddr - 1) {
++ fi->ext.fofs--;
++ fi->ext.blk_addr--;
++ fi->ext.len++;
++ goto end_update;
++ }
++
++ /* Back merge */
++ if (fofs == end_fofs + 1 && blk_addr == end_blkaddr + 1) {
++ fi->ext.len++;
++ goto end_update;
++ }
++
++ /* Split the existing extent */
++ if (fi->ext.len > 1 &&
++ fofs >= start_fofs && fofs <= end_fofs) {
++ if ((end_fofs - fofs) < (fi->ext.len >> 1)) {
++ fi->ext.len = fofs - start_fofs;
++ } else {
++ fi->ext.fofs = fofs + 1;
++ fi->ext.blk_addr = start_blkaddr +
++ fofs - start_fofs + 1;
++ fi->ext.len -= fofs - start_fofs + 1;
++ }
++ goto end_update;
++ }
++ write_unlock(&fi->ext.ext_lock);
++ return;
++
++end_update:
++ write_unlock(&fi->ext.ext_lock);
++ sync_inode_page(dn);
++ return;
++}
++
++struct page *find_data_page(struct inode *inode, pgoff_t index)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct dnode_of_data dn;
++ struct page *page;
++ int err;
++
++ page = find_get_page(mapping, index);
++ if (page && PageUptodate(page))
++ return page;
++ f2fs_put_page(page, 0);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err)
++ return ERR_PTR(err);
++ f2fs_put_dnode(&dn);
++
++ if (dn.data_blkaddr == NULL_ADDR)
++ return ERR_PTR(-ENOENT);
++
++ /* By fallocate(), there is no cached page, but with NEW_ADDR */
++ if (dn.data_blkaddr == NEW_ADDR)
++ return ERR_PTR(-EINVAL);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ unlock_page(page);
++ return page;
++}
++
++/**
++ * If it tries to access a hole, return an error.
++ * Because, the callers, functions in dir.c and GC, should be able to know
++ * whether this page exists or not.
++ */
++struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct dnode_of_data dn;
++ struct page *page;
++ int err;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, RDONLY_NODE);
++ if (err)
++ return ERR_PTR(err);
++ f2fs_put_dnode(&dn);
++
++ if (dn.data_blkaddr == NULL_ADDR)
++ return ERR_PTR(-ENOENT);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ if (PageUptodate(page))
++ return page;
++
++ BUG_ON(dn.data_blkaddr == NEW_ADDR);
++ BUG_ON(dn.data_blkaddr == NULL_ADDR);
++
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ return page;
++}
++
++/**
++ * Caller ensures that this data page is never allocated.
++ * A new zero-filled data page is allocated in the page cache.
++ */
++struct page *get_new_data_page(struct inode *inode, pgoff_t index,
++ bool new_i_size)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct address_space *mapping = inode->i_mapping;
++ struct page *page;
++ struct dnode_of_data dn;
++ int err;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, 0);
++ if (err)
++ return ERR_PTR(err);
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ if (reserve_new_block(&dn)) {
++ f2fs_put_dnode(&dn);
++ return ERR_PTR(-ENOSPC);
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ page = grab_cache_page(mapping, index);
++ if (!page)
++ return ERR_PTR(-ENOMEM);
++
++ if (PageUptodate(page))
++ return page;
++
++ if (dn.data_blkaddr == NEW_ADDR) {
++ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
++ } else {
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return ERR_PTR(err);
++ }
++ }
++ SetPageUptodate(page);
++
++ if (new_i_size &&
++ i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) {
++ i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT));
++ mark_inode_dirty_sync(inode);
++ }
++ return page;
++}
++
++static void read_end_io(struct bio *bio, int err)
++{
++ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
++ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
++
++ do {
++ struct page *page = bvec->bv_page;
++
++ if (--bvec >= bio->bi_io_vec)
++ prefetchw(&bvec->bv_page->flags);
++
++ if (uptodate) {
++ SetPageUptodate(page);
++ } else {
++ ClearPageUptodate(page);
++ SetPageError(page);
++ }
++ unlock_page(page);
++ } while (bvec >= bio->bi_io_vec);
++ kfree(bio->bi_private);
++ bio_put(bio);
++}
++
++/**
++ * Fill the locked page with data located in the block address.
++ * Read operation is synchronous, and caller must unlock the page.
++ */
++int f2fs_readpage(struct f2fs_sb_info *sbi, struct page *page,
++ block_t blk_addr, int type)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++ bool sync = (type == READ_SYNC);
++ struct bio *bio;
++
++ /* This page can be already read by other threads */
++ if (PageUptodate(page)) {
++ if (!sync)
++ unlock_page(page);
++ return 0;
++ }
++
++ down_read(&sbi->bio_sem);
++
++ /* Allocate a new bio */
++ bio = f2fs_bio_alloc(bdev, blk_addr << (sbi->log_blocksize - 9),
++ 1, GFP_NOFS | __GFP_HIGH);
++
++ /* Initialize the bio */
++ bio->bi_end_io = read_end_io;
++ if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) {
++ kfree(bio->bi_private);
++ bio_put(bio);
++ up_read(&sbi->bio_sem);
++ return -EFAULT;
++ }
++
++ submit_bio(type, bio);
++ up_read(&sbi->bio_sem);
++
++ /* wait for read completion if sync */
++ if (sync) {
++ lock_page(page);
++ if (PageError(page))
++ return -EIO;
++ }
++ return 0;
++}
++
++/**
++ * This function should be used by the data read flow only where it
++ * does not check the "create" flag that indicates block allocation.
++ * The reason for this special functionality is to exploit VFS readahead
++ * mechanism.
++ */
++static int get_data_block_ro(struct inode *inode, sector_t iblock,
++ struct buffer_head *bh_result, int create)
++{
++ unsigned int blkbits = inode->i_sb->s_blocksize_bits;
++ unsigned maxblocks = bh_result->b_size >> blkbits;
++ struct dnode_of_data dn;
++ pgoff_t pgofs;
++ int err;
++
++ /* Get the page offset from the block offset(iblock) */
++ pgofs = (pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits));
++
++ if (check_extent_cache(inode, pgofs, bh_result))
++ return 0;
++
++ /* When reading holes, we need its node page */
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
++ if (err)
++ return (err == -ENOENT) ? 0 : err;
++
++ /* It does not support data allocation */
++ BUG_ON(create);
++
++ if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) {
++ int i;
++ unsigned int end_offset;
++
++ end_offset = IS_INODE(dn.node_page) ?
++ ADDRS_PER_INODE :
++ ADDRS_PER_BLOCK;
++
++ clear_buffer_new(bh_result);
++
++ /* Give more consecutive addresses for the read ahead */
++ for (i = 0; i < end_offset - dn.ofs_in_node; i++)
++ if (((datablock_addr(dn.node_page,
++ dn.ofs_in_node + i))
++ != (dn.data_blkaddr + i)) || maxblocks == i)
++ break;
++ map_bh(bh_result, inode->i_sb, dn.data_blkaddr);
++ bh_result->b_size = (i << blkbits);
++ }
++ f2fs_put_dnode(&dn);
++ return 0;
++}
++
++static int f2fs_read_data_page(struct file *file, struct page *page)
++{
++ return mpage_readpage(page, get_data_block_ro);
++}
++
++static int f2fs_read_data_pages(struct file *file,
++ struct address_space *mapping,
++ struct list_head *pages, unsigned nr_pages)
++{
++ return mpage_readpages(mapping, pages, nr_pages, get_data_block_ro);
++}
++
++int do_write_data_page(struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ block_t old_blk_addr, new_blk_addr;
++ struct dnode_of_data dn;
++ int err = 0;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
++ if (err)
++ return err;
++
++ old_blk_addr = dn.data_blkaddr;
++
++ /* This page is already truncated */
++ if (old_blk_addr == NULL_ADDR)
++ goto out_writepage;
++
++ set_page_writeback(page);
++
++ /*
++ * If current allocation needs SSR,
++ * it had better in-place writes for updated data.
++ */
++ if (old_blk_addr != NEW_ADDR && !is_cold_data(page) &&
++ need_inplace_update(inode)) {
++ rewrite_data_page(F2FS_SB(inode->i_sb), page,
++ old_blk_addr);
++ } else {
++ write_data_page(inode, page, &dn,
++ old_blk_addr, &new_blk_addr);
++ update_extent_cache(new_blk_addr, &dn);
++ F2FS_I(inode)->data_version =
++ le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver);
++ }
++out_writepage:
++ f2fs_put_dnode(&dn);
++ return err;
++}
++
++static int f2fs_write_data_page(struct page *page,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ loff_t i_size = i_size_read(inode);
++ const pgoff_t end_index = ((unsigned long long) i_size)
++ >> PAGE_CACHE_SHIFT;
++ unsigned offset;
++ int err = 0;
++
++ if (page->index < end_index)
++ goto out;
++
++ /*
++ * If the offset is out-of-range of file size,
++ * this page does not have to be written to disk.
++ */
++ offset = i_size & (PAGE_CACHE_SIZE - 1);
++ if ((page->index >= end_index + 1) || !offset) {
++ if (S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ goto unlock_out;
++ }
++
++ zero_user_segment(page, offset, PAGE_CACHE_SIZE);
++out:
++ if (sbi->por_doing)
++ goto redirty_out;
++
++ if (wbc->for_reclaim && !S_ISDIR(inode->i_mode) && !is_cold_data(page))
++ goto redirty_out;
++
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ err = do_write_data_page(page);
++ if (err && err != -ENOENT) {
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ }
++ mutex_unlock_op(sbi, DATA_WRITE);
++
++ if (wbc->for_reclaim)
++ f2fs_submit_bio(sbi, DATA, true);
++
++ if (err == -ENOENT)
++ goto unlock_out;
++
++ clear_cold_data(page);
++ unlock_page(page);
++
++ if (!wbc->for_reclaim && !S_ISDIR(inode->i_mode))
++ f2fs_balance_fs(sbi);
++ return 0;
++
++unlock_out:
++ unlock_page(page);
++ return (err == -ENOENT) ? 0 : err;
++
++redirty_out:
++ wbc->pages_skipped++;
++ set_page_dirty(page);
++ return AOP_WRITEPAGE_ACTIVATE;
++}
++
++#define MAX_DESIRED_PAGES_WP 4096
++
++int f2fs_write_data_pages(struct address_space *mapping,
++ struct writeback_control *wbc)
++{
++ struct inode *inode = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int ret;
++ long excess_nrtw = 0, desired_nrtw;
++
++ if (wbc->nr_to_write < MAX_DESIRED_PAGES_WP) {
++ desired_nrtw = MAX_DESIRED_PAGES_WP;
++ excess_nrtw = desired_nrtw - wbc->nr_to_write;
++ wbc->nr_to_write = desired_nrtw;
++ }
++
++ if (!S_ISDIR(inode->i_mode))
++ mutex_lock(&sbi->writepages);
++ ret = generic_writepages(mapping, wbc);
++ if (!S_ISDIR(inode->i_mode))
++ mutex_unlock(&sbi->writepages);
++ f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
++
++ remove_dirty_dir_inode(inode);
++
++ wbc->nr_to_write -= excess_nrtw;
++ return ret;
++}
++
++static int f2fs_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{
++ struct inode *inode = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *page;
++ pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
++ struct dnode_of_data dn;
++ int err = 0;
++
++ /* for nobh_write_end */
++ *fsdata = NULL;
++
++ f2fs_balance_fs(sbi);
++
++ page = grab_cache_page_write_begin(mapping, index, flags);
++ if (!page)
++ return -ENOMEM;
++ *pagep = page;
++
++ mutex_lock_op(sbi, DATA_NEW);
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ err = get_dnode_of_data(&dn, index, 0);
++ if (err) {
++ mutex_unlock_op(sbi, DATA_NEW);
++ f2fs_put_page(page, 1);
++ return err;
++ }
++
++ if (dn.data_blkaddr == NULL_ADDR) {
++ err = reserve_new_block(&dn);
++ if (err) {
++ f2fs_put_dnode(&dn);
++ mutex_unlock_op(sbi, DATA_NEW);
++ f2fs_put_page(page, 1);
++ return err;
++ }
++ }
++ f2fs_put_dnode(&dn);
++
++ mutex_unlock_op(sbi, DATA_NEW);
++
++ if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
++ return 0;
++
++ if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
++ unsigned start = pos & (PAGE_CACHE_SIZE - 1);
++ unsigned end = start + len;
++
++ /* Reading beyond i_size is simple: memset to zero */
++ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
++ return 0;
++ }
++
++ if (dn.data_blkaddr == NEW_ADDR) {
++ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
++ } else {
++ err = f2fs_readpage(sbi, page, dn.data_blkaddr, READ_SYNC);
++ if (err) {
++ f2fs_put_page(page, 1);
++ return err;
++ }
++ }
++ SetPageUptodate(page);
++ clear_cold_data(page);
++ return 0;
++}
++
++static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb,
++ const struct iovec *iov, loff_t offset, unsigned long nr_segs)
++{
++ struct file *file = iocb->ki_filp;
++ struct inode *inode = file->f_mapping->host;
++
++ if (rw == WRITE)
++ return 0;
++
++ /* Needs synchronization with the cleaner */
++ return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
++ get_data_block_ro);
++}
++
++static void f2fs_invalidate_data_page(struct page *page, unsigned long offset)
++{
++ struct inode *inode = page->mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ if (S_ISDIR(inode->i_mode) && PageDirty(page)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ ClearPagePrivate(page);
++}
++
++static int f2fs_release_data_page(struct page *page, gfp_t wait)
++{
++ ClearPagePrivate(page);
++ return 0;
++}
++
++static int f2fs_set_data_page_dirty(struct page *page)
++{
++ struct address_space *mapping = page->mapping;
++ struct inode *inode = mapping->host;
++
++ SetPageUptodate(page);
++ if (!PageDirty(page)) {
++ __set_page_dirty_nobuffers(page);
++ set_dirty_dir_page(inode, page);
++ return 1;
++ }
++ return 0;
++}
++
++const struct address_space_operations f2fs_dblock_aops = {
++ .readpage = f2fs_read_data_page,
++ .readpages = f2fs_read_data_pages,
++ .writepage = f2fs_write_data_page,
++ .writepages = f2fs_write_data_pages,
++ .write_begin = f2fs_write_begin,
++ .write_end = nobh_write_end,
++ .set_page_dirty = f2fs_set_data_page_dirty,
++ .invalidatepage = f2fs_invalidate_data_page,
++ .releasepage = f2fs_release_data_page,
++ .direct_IO = f2fs_direct_IO,
++};
diff --git a/patches/linux-3.7/0109-f2fs-add-core-inode-operations.patch b/patches/linux-3.7/0109-f2fs-add-core-inode-operations.patch
new file mode 100644
index 0000000..d0c5018
--- /dev/null
+++ b/patches/linux-3.7/0109-f2fs-add-core-inode-operations.patch
@@ -0,0 +1,281 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:30:16 +0000
+Subject: [PATCH] f2fs: add core inode operations
+
+This adds core functions to get, read, write, and evict an inode.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/inode.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 262 insertions(+)
+ create mode 100644 fs/f2fs/inode.c
+
+diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
+new file mode 100644
+index 0000000..0cf61da
+--- /dev/null
++++ b/fs/f2fs/inode.c
+@@ -0,0 +1,262 @@
++/**
++ * fs/f2fs/inode.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/buffer_head.h>
++#include <linux/writeback.h>
++
++#include "f2fs.h"
++#include "node.h"
++
++struct f2fs_iget_args {
++ u64 ino;
++ int on_free;
++};
++
++void f2fs_set_inode_flags(struct inode *inode)
++{
++ unsigned int flags = F2FS_I(inode)->i_flags;
++
++ inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE |
++ S_NOATIME | S_DIRSYNC);
++
++ if (flags & FS_SYNC_FL)
++ inode->i_flags |= S_SYNC;
++ if (flags & FS_APPEND_FL)
++ inode->i_flags |= S_APPEND;
++ if (flags & FS_IMMUTABLE_FL)
++ inode->i_flags |= S_IMMUTABLE;
++ if (flags & FS_NOATIME_FL)
++ inode->i_flags |= S_NOATIME;
++ if (flags & FS_DIRSYNC_FL)
++ inode->i_flags |= S_DIRSYNC;
++}
++
++static int f2fs_iget_test(struct inode *inode, void *data)
++{
++ struct f2fs_iget_args *args = data;
++
++ if (inode->i_ino != args->ino)
++ return 0;
++ if (inode->i_state & (I_FREEING | I_WILL_FREE)) {
++ args->on_free = 1;
++ return 0;
++ }
++ return 1;
++}
++
++struct inode *f2fs_iget_nowait(struct super_block *sb, unsigned long ino)
++{
++ struct f2fs_iget_args args = {
++ .ino = ino,
++ .on_free = 0
++ };
++ struct inode *inode = ilookup5(sb, ino, f2fs_iget_test, &args);
++
++ if (inode)
++ return inode;
++ if (!args.on_free)
++ return f2fs_iget(sb, ino);
++ return ERR_PTR(-ENOENT);
++}
++
++static int do_read_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct page *node_page;
++ struct f2fs_node *rn;
++ struct f2fs_inode *ri;
++
++ /* Check if ino is within scope */
++ check_nid_range(sbi, inode->i_ino);
++
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page))
++ return PTR_ERR(node_page);
++
++ rn = page_address(node_page);
++ ri = &(rn->i);
++
++ inode->i_mode = le16_to_cpu(ri->i_mode);
++ i_uid_write(inode, le32_to_cpu(ri->i_uid));
++ i_gid_write(inode, le32_to_cpu(ri->i_gid));
++ set_nlink(inode, le32_to_cpu(ri->i_links));
++ inode->i_size = le64_to_cpu(ri->i_size);
++ inode->i_blocks = le64_to_cpu(ri->i_blocks);
++
++ inode->i_atime.tv_sec = le64_to_cpu(ri->i_mtime);
++ inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime);
++ inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime);
++ inode->i_atime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
++ inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
++ inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
++
++ fi->current_depth = le32_to_cpu(ri->current_depth);
++ fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
++ fi->i_flags = le32_to_cpu(ri->i_flags);
++ fi->flags = 0;
++ fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
++ fi->i_advise = ri->i_advise;
++ get_extent_info(&fi->ext, ri->i_ext);
++ f2fs_put_page(node_page, 1);
++ return 0;
++}
++
++struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ int ret;
++
++ inode = iget_locked(sb, ino);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++ if (!(inode->i_state & I_NEW))
++ return inode;
++ if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
++ goto make_now;
++
++ ret = do_read_inode(inode);
++ if (ret)
++ goto bad_inode;
++
++ if (!sbi->por_doing && inode->i_nlink == 0) {
++ ret = -ENOENT;
++ goto bad_inode;
++ }
++
++make_now:
++ if (ino == F2FS_NODE_INO(sbi)) {
++ inode->i_mapping->a_ops = &f2fs_node_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_MOVABLE);
++ } else if (ino == F2FS_META_INO(sbi)) {
++ inode->i_mapping->a_ops = &f2fs_meta_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_MOVABLE);
++ } else if (S_ISREG(inode->i_mode)) {
++ inode->i_op = &f2fs_file_inode_operations;
++ inode->i_fop = &f2fs_file_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ } else if (S_ISDIR(inode->i_mode)) {
++ inode->i_op = &f2fs_dir_inode_operations;
++ inode->i_fop = &f2fs_dir_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER_MOVABLE |
++ __GFP_ZERO);
++ } else if (S_ISLNK(inode->i_mode)) {
++ inode->i_op = &f2fs_symlink_inode_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
++ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
++ inode->i_op = &f2fs_special_inode_operations;
++ init_special_inode(inode, inode->i_mode, inode->i_rdev);
++ } else {
++ ret = -EIO;
++ goto bad_inode;
++ }
++ unlock_new_inode(inode);
++
++ return inode;
++
++bad_inode:
++ iget_failed(inode);
++ return ERR_PTR(ret);
++}
++
++void update_inode(struct inode *inode, struct page *node_page)
++{
++ struct f2fs_node *rn;
++ struct f2fs_inode *ri;
++
++ wait_on_page_writeback(node_page);
++
++ rn = page_address(node_page);
++ ri = &(rn->i);
++
++ ri->i_mode = cpu_to_le16(inode->i_mode);
++ ri->i_advise = F2FS_I(inode)->i_advise;
++ ri->i_uid = cpu_to_le32(i_uid_read(inode));
++ ri->i_gid = cpu_to_le32(i_gid_read(inode));
++ ri->i_links = cpu_to_le32(inode->i_nlink);
++ ri->i_size = cpu_to_le64(i_size_read(inode));
++ ri->i_blocks = cpu_to_le64(inode->i_blocks);
++ set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext);
++
++ ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
++ ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
++ ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
++ ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
++ ri->current_depth = cpu_to_le32(F2FS_I(inode)->current_depth);
++ ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
++ ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
++ set_page_dirty(node_page);
++}
++
++int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct page *node_page;
++ bool need_lock = false;
++
++ if (inode->i_ino == F2FS_NODE_INO(sbi) ||
++ inode->i_ino == F2FS_META_INO(sbi))
++ return 0;
++
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page))
++ return PTR_ERR(node_page);
++
++ if (!PageDirty(node_page)) {
++ need_lock = true;
++ f2fs_put_page(node_page, 1);
++ mutex_lock(&sbi->write_inode);
++ node_page = get_node_page(sbi, inode->i_ino);
++ if (IS_ERR(node_page)) {
++ mutex_unlock(&sbi->write_inode);
++ return PTR_ERR(node_page);
++ }
++ }
++ update_inode(inode, node_page);
++ f2fs_put_page(node_page, 1);
++ if (need_lock)
++ mutex_unlock(&sbi->write_inode);
++ return 0;
++}
++
++/**
++ * Called at the last iput() if i_nlink is zero
++ */
++void f2fs_evict_inode(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++
++ truncate_inode_pages(&inode->i_data, 0);
++
++ if (inode->i_ino == F2FS_NODE_INO(sbi) ||
++ inode->i_ino == F2FS_META_INO(sbi))
++ goto no_delete;
++
++ BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
++ remove_dirty_dir_inode(inode);
++
++ if (inode->i_nlink || is_bad_inode(inode))
++ goto no_delete;
++
++ set_inode_flag(F2FS_I(inode), FI_NO_ALLOC);
++ i_size_write(inode, 0);
++
++ if (F2FS_HAS_BLOCKS(inode))
++ f2fs_truncate(inode);
++
++ remove_inode_page(inode);
++no_delete:
++ clear_inode(inode);
++}
diff --git a/patches/linux-3.7/0110-f2fs-add-inode-operations-for-special-inodes.patch b/patches/linux-3.7/0110-f2fs-add-inode-operations-for-special-inodes.patch
new file mode 100644
index 0000000..0171957
--- /dev/null
+++ b/patches/linux-3.7/0110-f2fs-add-inode-operations-for-special-inodes.patch
@@ -0,0 +1,513 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:30:45 +0000
+Subject: [PATCH] f2fs: add inode operations for special inodes
+
+This adds inode operations for directory, symlink, and special inodes.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/namei.c | 494 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 494 insertions(+)
+ create mode 100644 fs/f2fs/namei.c
+
+diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
+new file mode 100644
+index 0000000..899d144
+--- /dev/null
++++ b/fs/f2fs/namei.c
+@@ -0,0 +1,494 @@
++/**
++ * fs/f2fs/namei.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/pagemap.h>
++#include <linux/sched.h>
++#include <linux/ctype.h>
++
++#include "f2fs.h"
++#include "xattr.h"
++#include "acl.h"
++
++static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ nid_t ino;
++ struct inode *inode;
++ bool nid_free = false;
++ int err;
++
++ inode = new_inode(sb);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++
++ mutex_lock_op(sbi, NODE_NEW);
++ if (!alloc_nid(sbi, &ino)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ err = -ENOSPC;
++ goto fail;
++ }
++ mutex_unlock_op(sbi, NODE_NEW);
++
++ inode->i_uid = current_fsuid();
++
++ if (dir->i_mode & S_ISGID) {
++ inode->i_gid = dir->i_gid;
++ if (S_ISDIR(mode))
++ mode |= S_ISGID;
++ } else {
++ inode->i_gid = current_fsgid();
++ }
++
++ inode->i_ino = ino;
++ inode->i_mode = mode;
++ inode->i_blocks = 0;
++ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++
++ err = insert_inode_locked(inode);
++ if (err) {
++ err = -EINVAL;
++ nid_free = true;
++ goto out;
++ }
++
++ mark_inode_dirty(inode);
++ return inode;
++
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++fail:
++ iput(inode);
++ if (nid_free)
++ alloc_nid_failed(sbi, ino);
++ return ERR_PTR(err);
++}
++
++static int is_multimedia_file(const unsigned char *s, const char *sub)
++{
++ int slen = strlen(s);
++ int sublen = strlen(sub);
++ int ret;
++
++ if (sublen > slen)
++ return 1;
++
++ ret = memcmp(s + slen - sublen, sub, sublen);
++ if (ret) { /* compare upper case */
++ int i;
++ char upper_sub[8];
++ for (i = 0; i < sublen && i < sizeof(upper_sub); i++)
++ upper_sub[i] = toupper(sub[i]);
++ return memcmp(s + slen - sublen, upper_sub, sublen);
++ }
++
++ return ret;
++}
++
++/**
++ * Set multimedia files as cold files for hot/cold data separation
++ */
++static inline void set_cold_file(struct f2fs_sb_info *sbi, struct inode *inode,
++ const unsigned char *name)
++{
++ int i;
++ __u8 (*extlist)[8] = sbi->raw_super->extension_list;
++
++ int count = le32_to_cpu(sbi->raw_super->extension_count);
++ for (i = 0; i < count; i++) {
++ if (!is_multimedia_file(name, extlist[i])) {
++ F2FS_I(inode)->i_advise |= FADVISE_COLD_BIT;
++ break;
++ }
++ }
++}
++
++static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++ bool excl)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ nid_t ino = 0;
++ int err;
++
++ inode = f2fs_new_inode(dir, mode);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
++ set_cold_file(sbi, inode, dentry->d_name.name);
++
++ inode->i_op = &f2fs_file_inode_operations;
++ inode->i_fop = &f2fs_file_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ ino = inode->i_ino;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ alloc_nid_done(sbi, ino);
++
++ if (!sbi->por_doing)
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, ino);
++ return err;
++}
++
++static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *dentry)
++{
++ struct inode *inode = old_dentry->d_inode;
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ int err;
++
++ inode->i_ctime = CURRENT_TIME;
++ atomic_inc(&inode->i_count);
++
++ set_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ d_instantiate(dentry, inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++out:
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ iput(inode);
++ return err;
++}
++
++static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
++ unsigned int flags)
++{
++ struct inode *inode = NULL;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++
++ if (dentry->d_name.len > F2FS_MAX_NAME_LEN)
++ return ERR_PTR(-ENAMETOOLONG);
++
++ de = f2fs_find_entry(dir, &dentry->d_name, &page);
++ if (de) {
++ nid_t ino = le32_to_cpu(de->ino);
++ kunmap(page);
++ f2fs_put_page(page, 0);
++
++ inode = f2fs_iget(dir->i_sb, ino);
++ if (IS_ERR(inode))
++ return ERR_CAST(inode);
++ }
++
++ return d_splice_alias(inode, dentry);
++}
++
++static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++ int err = -ENOENT;
++
++ de = f2fs_find_entry(dir, &dentry->d_name, &page);
++ if (!de)
++ goto fail;
++
++ err = check_orphan_space(sbi);
++ if (err) {
++ kunmap(page);
++ f2fs_put_page(page, 0);
++ goto fail;
++ }
++
++ f2fs_delete_entry(de, page, inode);
++
++ /* In order to evict this inode, we set it dirty */
++ mark_inode_dirty(inode);
++ f2fs_balance_fs(sbi);
++fail:
++ return err;
++}
++
++static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ unsigned symlen = strlen(symname) + 1;
++ int err;
++
++ inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ inode->i_op = &f2fs_symlink_inode_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ err = page_symlink(inode, symname, symlen);
++ alloc_nid_done(sbi, inode->i_ino);
++
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++
++ return err;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ struct inode *inode;
++ int err;
++
++ inode = f2fs_new_inode(dir, S_IFDIR | mode);
++ err = PTR_ERR(inode);
++ if (IS_ERR(inode))
++ return err;
++
++ inode->i_op = &f2fs_dir_inode_operations;
++ inode->i_fop = &f2fs_dir_operations;
++ inode->i_mapping->a_ops = &f2fs_dblock_aops;
++ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS | __GFP_ZERO);
++
++ set_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out_fail;
++
++ alloc_nid_done(sbi, inode->i_ino);
++
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++
++out_fail:
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ struct inode *inode = dentry->d_inode;
++ if (f2fs_empty_dir(inode))
++ return f2fs_unlink(dir, dentry);
++ return -ENOTEMPTY;
++}
++
++static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
++ umode_t mode, dev_t rdev)
++{
++ struct super_block *sb = dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *inode;
++ int err = 0;
++
++ if (!new_valid_dev(rdev))
++ return -EINVAL;
++
++ inode = f2fs_new_inode(dir, mode);
++ if (IS_ERR(inode))
++ return PTR_ERR(inode);
++
++ init_special_inode(inode, inode->i_mode, rdev);
++ inode->i_op = &f2fs_special_inode_operations;
++
++ err = f2fs_add_link(dentry, inode);
++ if (err)
++ goto out;
++
++ alloc_nid_done(sbi, inode->i_ino);
++ d_instantiate(dentry, inode);
++ unlock_new_inode(inode);
++
++ f2fs_balance_fs(sbi);
++
++ return 0;
++out:
++ clear_nlink(inode);
++ unlock_new_inode(inode);
++ iput(inode);
++ alloc_nid_failed(sbi, inode->i_ino);
++ return err;
++}
++
++static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ struct super_block *sb = old_dir->i_sb;
++ struct f2fs_sb_info *sbi = F2FS_SB(sb);
++ struct inode *old_inode = old_dentry->d_inode;
++ struct inode *new_inode = new_dentry->d_inode;
++ struct page *old_dir_page;
++ struct page *old_page;
++ struct f2fs_dir_entry *old_dir_entry = NULL;
++ struct f2fs_dir_entry *old_entry;
++ struct f2fs_dir_entry *new_entry;
++ int err = -ENOENT;
++
++ old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
++ if (!old_entry)
++ goto out;
++
++ if (S_ISDIR(old_inode->i_mode)) {
++ err = -EIO;
++ old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page);
++ if (!old_dir_entry)
++ goto out_old;
++ }
++
++ mutex_lock_op(sbi, RENAME);
++
++ if (new_inode) {
++ struct page *new_page;
++
++ err = -ENOTEMPTY;
++ if (old_dir_entry && !f2fs_empty_dir(new_inode))
++ goto out_dir;
++
++ err = -ENOENT;
++ new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,
++ &new_page);
++ if (!new_entry)
++ goto out_dir;
++
++ f2fs_set_link(new_dir, new_entry, new_page, old_inode);
++
++ new_inode->i_ctime = CURRENT_TIME;
++ if (old_dir_entry)
++ drop_nlink(new_inode);
++ drop_nlink(new_inode);
++ if (!new_inode->i_nlink)
++ add_orphan_inode(sbi, new_inode->i_ino);
++ f2fs_write_inode(new_inode, NULL);
++ } else {
++ err = f2fs_add_link(new_dentry, old_inode);
++ if (err)
++ goto out_dir;
++
++ if (old_dir_entry) {
++ inc_nlink(new_dir);
++ f2fs_write_inode(new_dir, NULL);
++ }
++ }
++
++ old_inode->i_ctime = CURRENT_TIME;
++ set_inode_flag(F2FS_I(old_inode), FI_NEED_CP);
++ mark_inode_dirty(old_inode);
++
++ f2fs_delete_entry(old_entry, old_page, NULL);
++
++ if (old_dir_entry) {
++ if (old_dir != new_dir) {
++ f2fs_set_link(old_inode, old_dir_entry,
++ old_dir_page, new_dir);
++ } else {
++ kunmap(old_dir_page);
++ f2fs_put_page(old_dir_page, 0);
++ }
++ drop_nlink(old_dir);
++ f2fs_write_inode(old_dir, NULL);
++ }
++
++ mutex_unlock_op(sbi, RENAME);
++
++ f2fs_balance_fs(sbi);
++ return 0;
++
++out_dir:
++ if (old_dir_entry) {
++ kunmap(old_dir_page);
++ f2fs_put_page(old_dir_page, 0);
++ }
++ mutex_unlock_op(sbi, RENAME);
++out_old:
++ kunmap(old_page);
++ f2fs_put_page(old_page, 0);
++out:
++ return err;
++}
++
++const struct inode_operations f2fs_dir_inode_operations = {
++ .create = f2fs_create,
++ .lookup = f2fs_lookup,
++ .link = f2fs_link,
++ .unlink = f2fs_unlink,
++ .symlink = f2fs_symlink,
++ .mkdir = f2fs_mkdir,
++ .rmdir = f2fs_rmdir,
++ .mknod = f2fs_mknod,
++ .rename = f2fs_rename,
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++const struct inode_operations f2fs_symlink_inode_operations = {
++ .readlink = generic_readlink,
++ .follow_link = page_follow_link_light,
++ .put_link = page_put_link,
++ .setattr = f2fs_setattr,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
++
++const struct inode_operations f2fs_special_inode_operations = {
++ .setattr = f2fs_setattr,
++ .get_acl = f2fs_get_acl,
++#ifdef CONFIG_F2FS_FS_XATTR
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = f2fs_listxattr,
++ .removexattr = generic_removexattr,
++#endif
++};
diff --git a/patches/linux-3.7/0111-f2fs-add-core-directory-operations.patch b/patches/linux-3.7/0111-f2fs-add-core-directory-operations.patch
new file mode 100644
index 0000000..60b6b2f
--- /dev/null
+++ b/patches/linux-3.7/0111-f2fs-add-core-directory-operations.patch
@@ -0,0 +1,781 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:31:34 +0000
+Subject: [PATCH] f2fs: add core directory operations
+
+This adds core functions to find, add, delete, and link dentries.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/dir.c | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/hash.c | 98 +++++++++
+ 2 files changed, 755 insertions(+)
+ create mode 100644 fs/f2fs/dir.c
+ create mode 100644 fs/f2fs/hash.c
+
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+new file mode 100644
+index 0000000..f3de333
+--- /dev/null
++++ b/fs/f2fs/dir.c
+@@ -0,0 +1,657 @@
++/**
++ * fs/f2fs/dir.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "acl.h"
++
++static unsigned long dir_blocks(struct inode *inode)
++{
++ return ((unsigned long long) (i_size_read(inode) + PAGE_CACHE_SIZE - 1))
++ >> PAGE_CACHE_SHIFT;
++}
++
++static unsigned int dir_buckets(unsigned int level)
++{
++ if (level < MAX_DIR_HASH_DEPTH / 2)
++ return 1 << level;
++ else
++ return 1 << ((MAX_DIR_HASH_DEPTH / 2) - 1);
++}
++
++static unsigned int bucket_blocks(unsigned int level)
++{
++ if (level < MAX_DIR_HASH_DEPTH / 2)
++ return 2;
++ else
++ return 4;
++}
++
++static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = {
++ [F2FS_FT_UNKNOWN] = DT_UNKNOWN,
++ [F2FS_FT_REG_FILE] = DT_REG,
++ [F2FS_FT_DIR] = DT_DIR,
++ [F2FS_FT_CHRDEV] = DT_CHR,
++ [F2FS_FT_BLKDEV] = DT_BLK,
++ [F2FS_FT_FIFO] = DT_FIFO,
++ [F2FS_FT_SOCK] = DT_SOCK,
++ [F2FS_FT_SYMLINK] = DT_LNK,
++};
++
++#define S_SHIFT 12
++static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
++ [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE,
++ [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR,
++ [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV,
++ [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV,
++ [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO,
++ [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK,
++ [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK,
++};
++
++static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode)
++{
++ mode_t mode = inode->i_mode;
++ de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
++}
++
++static unsigned long dir_block_index(unsigned int level, unsigned int idx)
++{
++ unsigned long i;
++ unsigned long bidx = 0;
++
++ for (i = 0; i < level; i++)
++ bidx += dir_buckets(i) * bucket_blocks(i);
++ bidx += idx * bucket_blocks(level);
++ return bidx;
++}
++
++static bool early_match_name(const char *name, int namelen,
++ f2fs_hash_t namehash, struct f2fs_dir_entry *de)
++{
++ if (le16_to_cpu(de->name_len) != namelen)
++ return false;
++
++ if (le32_to_cpu(de->hash_code) != namehash)
++ return false;
++
++ return true;
++}
++
++static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
++ const char *name, int namelen, int *max_slots,
++ f2fs_hash_t namehash, struct page **res_page)
++{
++ struct f2fs_dir_entry *de;
++ unsigned long bit_pos, end_pos, next_pos;
++ struct f2fs_dentry_block *dentry_blk = kmap(dentry_page);
++ int slots;
++
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK, 0);
++ while (bit_pos < NR_DENTRY_IN_BLOCK) {
++ de = &dentry_blk->dentry[bit_pos];
++ slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1) /
++ F2FS_NAME_LEN;
++
++ if (early_match_name(name, namelen, namehash, de)) {
++ if (!memcmp(dentry_blk->filename[bit_pos],
++ name, namelen)) {
++ *res_page = dentry_page;
++ goto found;
++ }
++ }
++ next_pos = bit_pos + slots;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK, next_pos);
++ if (bit_pos >= NR_DENTRY_IN_BLOCK)
++ end_pos = NR_DENTRY_IN_BLOCK;
++ else
++ end_pos = bit_pos;
++ if (*max_slots < end_pos - next_pos)
++ *max_slots = end_pos - next_pos;
++ }
++
++ de = NULL;
++ kunmap(dentry_page);
++found:
++ return de;
++}
++
++static struct f2fs_dir_entry *find_in_level(struct inode *dir,
++ unsigned int level, const char *name, int namelen,
++ f2fs_hash_t namehash, struct page **res_page)
++{
++ int s = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
++ unsigned int nbucket, nblock;
++ unsigned int bidx, end_block;
++ struct page *dentry_page;
++ struct f2fs_dir_entry *de = NULL;
++ bool room = false;
++ int max_slots = 0;
++
++ BUG_ON(level > MAX_DIR_HASH_DEPTH);
++
++ nbucket = dir_buckets(level);
++ nblock = bucket_blocks(level);
++
++ bidx = dir_block_index(level, namehash % nbucket);
++ end_block = bidx + nblock;
++
++ for (; bidx < end_block; bidx++) {
++ /* no need to allocate new dentry pages to all the indices */
++ dentry_page = find_data_page(dir, bidx);
++ if (IS_ERR(dentry_page)) {
++ room = true;
++ continue;
++ }
++
++ de = find_in_block(dentry_page, name, namelen,
++ &max_slots, namehash, res_page);
++ if (de)
++ break;
++
++ if (max_slots >= s)
++ room = true;
++ f2fs_put_page(dentry_page, 0);
++ }
++
++ if (!de && room && F2FS_I(dir)->chash != namehash) {
++ F2FS_I(dir)->chash = namehash;
++ F2FS_I(dir)->clevel = level;
++ }
++
++ return de;
++}
++
++/*
++ * Find an entry in the specified directory with the wanted name.
++ * It returns the page where the entry was found (as a parameter - res_page),
++ * and the entry itself. Page is returned mapped and unlocked.
++ * Entry is guaranteed to be valid.
++ */
++struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
++ struct qstr *child, struct page **res_page)
++{
++ const char *name = child->name;
++ int namelen = child->len;
++ unsigned long npages = dir_blocks(dir);
++ struct f2fs_dir_entry *de = NULL;
++ f2fs_hash_t name_hash;
++ unsigned int max_depth;
++ unsigned int level;
++
++ if (npages == 0)
++ return NULL;
++
++ *res_page = NULL;
++
++ name_hash = f2fs_dentry_hash(name, namelen);
++ max_depth = F2FS_I(dir)->current_depth;
++
++ for (level = 0; level < max_depth; level++) {
++ de = find_in_level(dir, level, name,
++ namelen, name_hash, res_page);
++ if (de)
++ break;
++ }
++ if (!de && F2FS_I(dir)->chash != name_hash) {
++ F2FS_I(dir)->chash = name_hash;
++ F2FS_I(dir)->clevel = level - 1;
++ }
++ return de;
++}
++
++struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
++{
++ struct page *page = NULL;
++ struct f2fs_dir_entry *de = NULL;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++
++ page = get_lock_data_page(dir, 0);
++ if (IS_ERR(page))
++ return NULL;
++
++ dentry_blk = kmap(page);
++ de = &dentry_blk->dentry[1];
++ *p = page;
++ unlock_page(page);
++ return de;
++}
++
++void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
++ struct page *page, struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++
++ mutex_lock_op(sbi, DENTRY_OPS);
++ lock_page(page);
++ wait_on_page_writeback(page);
++ de->ino = cpu_to_le32(inode->i_ino);
++ set_de_type(de, inode);
++ kunmap(page);
++ set_page_dirty(page);
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ mark_inode_dirty(dir);
++ f2fs_put_page(page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++}
++
++void init_dent_inode(struct dentry *dentry, struct page *ipage)
++{
++ struct inode *dir = dentry->d_parent->d_inode;
++ struct f2fs_node *rn;
++
++ if (IS_ERR(ipage))
++ return;
++
++ wait_on_page_writeback(ipage);
++
++ /* copy dentry info. to this inode page */
++ rn = (struct f2fs_node *)page_address(ipage);
++ rn->i.i_pino = cpu_to_le32(dir->i_ino);
++ rn->i.i_namelen = cpu_to_le32(dentry->d_name.len);
++ memcpy(rn->i.i_name, dentry->d_name.name, dentry->d_name.len);
++ set_page_dirty(ipage);
++}
++
++static int init_inode_metadata(struct inode *inode, struct dentry *dentry)
++{
++ struct inode *dir = dentry->d_parent->d_inode;
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
++ int err;
++ err = new_inode_page(inode, dentry);
++ if (err)
++ return err;
++
++ if (S_ISDIR(inode->i_mode)) {
++ err = f2fs_make_empty(inode, dir);
++ if (err) {
++ remove_inode_page(inode);
++ return err;
++ }
++ }
++
++ err = f2fs_init_acl(inode, dir);
++ if (err) {
++ remove_inode_page(inode);
++ return err;
++ }
++ } else {
++ struct page *ipage;
++ ipage = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
++ if (IS_ERR(ipage))
++ return PTR_ERR(ipage);
++ init_dent_inode(dentry, ipage);
++ f2fs_put_page(ipage, 1);
++ }
++ if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) {
++ inc_nlink(inode);
++ f2fs_write_inode(inode, NULL);
++ }
++ return 0;
++}
++
++static void update_parent_metadata(struct inode *dir, struct inode *inode,
++ unsigned int current_depth)
++{
++ bool need_dir_update = false;
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) {
++ if (S_ISDIR(inode->i_mode)) {
++ inc_nlink(dir);
++ need_dir_update = true;
++ }
++ clear_inode_flag(F2FS_I(inode), FI_NEW_INODE);
++ }
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ if (F2FS_I(dir)->current_depth != current_depth) {
++ F2FS_I(dir)->current_depth = current_depth;
++ need_dir_update = true;
++ }
++
++ if (need_dir_update)
++ f2fs_write_inode(dir, NULL);
++ else
++ mark_inode_dirty(dir);
++
++ if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK))
++ clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
++}
++
++static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots)
++{
++ int bit_start = 0;
++ int zero_start, zero_end;
++next:
++ zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_start);
++ if (zero_start >= NR_DENTRY_IN_BLOCK)
++ return NR_DENTRY_IN_BLOCK;
++
++ zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ zero_start);
++ if (zero_end - zero_start >= slots)
++ return zero_start;
++
++ bit_start = zero_end + 1;
++
++ if (zero_end + 1 >= NR_DENTRY_IN_BLOCK)
++ return NR_DENTRY_IN_BLOCK;
++ goto next;
++}
++
++int f2fs_add_link(struct dentry *dentry, struct inode *inode)
++{
++ unsigned int bit_pos;
++ unsigned int level;
++ unsigned int current_depth;
++ unsigned long bidx, block;
++ f2fs_hash_t dentry_hash;
++ struct f2fs_dir_entry *de;
++ unsigned int nbucket, nblock;
++ struct inode *dir = dentry->d_parent->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ const char *name = dentry->d_name.name;
++ int namelen = dentry->d_name.len;
++ struct page *dentry_page = NULL;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++ int slots = (namelen + F2FS_NAME_LEN - 1) / F2FS_NAME_LEN;
++ int err = 0;
++ int i;
++
++ dentry_hash = f2fs_dentry_hash(name, dentry->d_name.len);
++ level = 0;
++ current_depth = F2FS_I(dir)->current_depth;
++ if (F2FS_I(dir)->chash == dentry_hash) {
++ level = F2FS_I(dir)->clevel;
++ F2FS_I(dir)->chash = 0;
++ }
++
++start:
++ if (current_depth == MAX_DIR_HASH_DEPTH)
++ return -ENOSPC;
++
++ /* Increase the depth, if required */
++ if (level == current_depth)
++ ++current_depth;
++
++ nbucket = dir_buckets(level);
++ nblock = bucket_blocks(level);
++
++ bidx = dir_block_index(level, (dentry_hash % nbucket));
++
++ for (block = bidx; block <= (bidx + nblock - 1); block++) {
++ mutex_lock_op(sbi, DENTRY_OPS);
++ dentry_page = get_new_data_page(dir, block, true);
++ if (IS_ERR(dentry_page)) {
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ return PTR_ERR(dentry_page);
++ }
++
++ dentry_blk = kmap(dentry_page);
++ bit_pos = room_for_filename(dentry_blk, slots);
++ if (bit_pos < NR_DENTRY_IN_BLOCK)
++ goto add_dentry;
++
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ }
++
++ /* Move to next level to find the empty slot for new dentry */
++ ++level;
++ goto start;
++add_dentry:
++ err = init_inode_metadata(inode, dentry);
++ if (err)
++ goto fail;
++
++ wait_on_page_writeback(dentry_page);
++
++ de = &dentry_blk->dentry[bit_pos];
++ de->hash_code = cpu_to_le32(dentry_hash);
++ de->name_len = cpu_to_le16(namelen);
++ memcpy(dentry_blk->filename[bit_pos], name, namelen);
++ de->ino = cpu_to_le32(inode->i_ino);
++ set_de_type(de, inode);
++ for (i = 0; i < slots; i++)
++ test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
++ set_page_dirty(dentry_page);
++ update_parent_metadata(dir, inode, current_depth);
++fail:
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ mutex_unlock_op(sbi, DENTRY_OPS);
++ return err;
++}
++
++/**
++ * It only removes the dentry from the dentry page,corresponding name
++ * entry in name page does not need to be touched during deletion.
++ */
++void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
++ struct inode *inode)
++{
++ struct f2fs_dentry_block *dentry_blk;
++ unsigned int bit_pos;
++ struct address_space *mapping = page->mapping;
++ struct inode *dir = mapping->host;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ int slots = (le16_to_cpu(dentry->name_len) + F2FS_NAME_LEN - 1) /
++ F2FS_NAME_LEN;
++ void *kaddr = page_address(page);
++ int i;
++
++ mutex_lock_op(sbi, DENTRY_OPS);
++
++ lock_page(page);
++ wait_on_page_writeback(page);
++
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++ bit_pos = dentry - (struct f2fs_dir_entry *)dentry_blk->dentry;
++ for (i = 0; i < slots; i++)
++ test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap);
++
++ /* Let's check and deallocate this dentry page */
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ 0);
++ kunmap(page); /* kunmap - pair of f2fs_find_entry */
++ set_page_dirty(page);
++
++ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++
++ if (inode && S_ISDIR(inode->i_mode)) {
++ drop_nlink(dir);
++ f2fs_write_inode(dir, NULL);
++ } else {
++ mark_inode_dirty(dir);
++ }
++
++ if (inode) {
++ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ drop_nlink(inode);
++ if (S_ISDIR(inode->i_mode)) {
++ drop_nlink(inode);
++ i_size_write(inode, 0);
++ }
++ f2fs_write_inode(inode, NULL);
++ if (inode->i_nlink == 0)
++ add_orphan_inode(sbi, inode->i_ino);
++ }
++
++ if (bit_pos == NR_DENTRY_IN_BLOCK) {
++ loff_t page_offset;
++ truncate_hole(dir, page->index, page->index + 1);
++ clear_page_dirty_for_io(page);
++ ClearPageUptodate(page);
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(dir);
++ page_offset = page->index << PAGE_CACHE_SHIFT;
++ f2fs_put_page(page, 1);
++ } else {
++ f2fs_put_page(page, 1);
++ }
++ mutex_unlock_op(sbi, DENTRY_OPS);
++}
++
++int f2fs_make_empty(struct inode *inode, struct inode *parent)
++{
++ struct page *dentry_page;
++ struct f2fs_dentry_block *dentry_blk;
++ struct f2fs_dir_entry *de;
++ void *kaddr;
++
++ dentry_page = get_new_data_page(inode, 0, true);
++ if (IS_ERR(dentry_page))
++ return PTR_ERR(dentry_page);
++
++ kaddr = kmap_atomic(dentry_page);
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++
++ de = &dentry_blk->dentry[0];
++ de->name_len = cpu_to_le16(1);
++ de->hash_code = 0;
++ de->ino = cpu_to_le32(inode->i_ino);
++ memcpy(dentry_blk->filename[0], ".", 1);
++ set_de_type(de, inode);
++
++ de = &dentry_blk->dentry[1];
++ de->hash_code = 0;
++ de->name_len = cpu_to_le16(2);
++ de->ino = cpu_to_le32(parent->i_ino);
++ memcpy(dentry_blk->filename[1], "..", 2);
++ set_de_type(de, inode);
++
++ test_and_set_bit_le(0, &dentry_blk->dentry_bitmap);
++ test_and_set_bit_le(1, &dentry_blk->dentry_bitmap);
++ kunmap_atomic(kaddr);
++
++ set_page_dirty(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ return 0;
++}
++
++bool f2fs_empty_dir(struct inode *dir)
++{
++ unsigned long bidx;
++ struct page *dentry_page;
++ unsigned int bit_pos;
++ struct f2fs_dentry_block *dentry_blk;
++ unsigned long nblock = dir_blocks(dir);
++
++ for (bidx = 0; bidx < nblock; bidx++) {
++ void *kaddr;
++ dentry_page = get_lock_data_page(dir, bidx);
++ if (IS_ERR(dentry_page)) {
++ if (PTR_ERR(dentry_page) == -ENOENT)
++ continue;
++ else
++ return false;
++ }
++
++ kaddr = kmap_atomic(dentry_page);
++ dentry_blk = (struct f2fs_dentry_block *)kaddr;
++ if (bidx == 0)
++ bit_pos = 2;
++ else
++ bit_pos = 0;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_pos);
++ kunmap_atomic(kaddr);
++
++ f2fs_put_page(dentry_page, 1);
++
++ if (bit_pos < NR_DENTRY_IN_BLOCK)
++ return false;
++ }
++ return true;
++}
++
++static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ unsigned long pos = file->f_pos;
++ struct inode *inode = file->f_dentry->d_inode;
++ unsigned long npages = dir_blocks(inode);
++ unsigned char *types = NULL;
++ unsigned int bit_pos = 0, start_bit_pos = 0;
++ int over = 0;
++ struct f2fs_dentry_block *dentry_blk = NULL;
++ struct f2fs_dir_entry *de = NULL;
++ struct page *dentry_page = NULL;
++ unsigned int n = 0;
++ unsigned char *ptr = NULL;
++ unsigned char d_type = DT_UNKNOWN;
++ int slots;
++
++ types = f2fs_filetype_table;
++ bit_pos = (pos % NR_DENTRY_IN_BLOCK);
++ n = (pos / NR_DENTRY_IN_BLOCK);
++
++ for ( ; n < npages; n++) {
++ dentry_page = get_lock_data_page(inode, n);
++ if (IS_ERR(dentry_page))
++ continue;
++
++ start_bit_pos = bit_pos;
++ dentry_blk = kmap(dentry_page);
++ while (bit_pos < NR_DENTRY_IN_BLOCK) {
++ d_type = DT_UNKNOWN;
++ bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap,
++ NR_DENTRY_IN_BLOCK,
++ bit_pos);
++ if (bit_pos >= NR_DENTRY_IN_BLOCK)
++ break;
++
++ de = &dentry_blk->dentry[bit_pos];
++ if (types && de->file_type < F2FS_FT_MAX)
++ d_type = types[de->file_type];
++
++ ptr = dentry_blk->filename[bit_pos];
++ over = filldir(dirent,
++ dentry_blk->filename[bit_pos],
++ le16_to_cpu(de->name_len),
++ (n * NR_DENTRY_IN_BLOCK) + bit_pos,
++ le32_to_cpu(de->ino), d_type);
++ if (over) {
++ file->f_pos += bit_pos - start_bit_pos;
++ goto success;
++ }
++ slots = (le16_to_cpu(de->name_len) + F2FS_NAME_LEN - 1)
++ / F2FS_NAME_LEN;
++ bit_pos += slots;
++ }
++ bit_pos = 0;
++ file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK;
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ dentry_page = NULL;
++ }
++success:
++ if (dentry_page && !IS_ERR(dentry_page)) {
++ kunmap(dentry_page);
++ f2fs_put_page(dentry_page, 1);
++ }
++
++ return 0;
++}
++
++const struct file_operations f2fs_dir_operations = {
++ .read = generic_read_dir,
++ .readdir = f2fs_readdir,
++ .fsync = f2fs_sync_file,
++ .unlocked_ioctl = f2fs_ioctl,
++};
+diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c
+new file mode 100644
+index 0000000..098a196
+--- /dev/null
++++ b/fs/f2fs/hash.c
+@@ -0,0 +1,98 @@
++/**
++ * fs/f2fs/hash.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext3/hash.c
++ *
++ * Copyright (C) 2002 by Theodore Ts'o
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/cryptohash.h>
++#include <linux/pagemap.h>
++
++#include "f2fs.h"
++
++/*
++ * Hashing code copied from ext3
++ */
++#define DELTA 0x9E3779B9
++
++static void TEA_transform(unsigned int buf[4], unsigned int const in[])
++{
++ __u32 sum = 0;
++ __u32 b0 = buf[0], b1 = buf[1];
++ __u32 a = in[0], b = in[1], c = in[2], d = in[3];
++ int n = 16;
++
++ do {
++ sum += DELTA;
++ b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
++ b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
++ } while (--n);
++
++ buf[0] += b0;
++ buf[1] += b1;
++}
++
++static void str2hashbuf(const char *msg, int len, unsigned int *buf, int num)
++{
++ unsigned pad, val;
++ int i;
++
++ pad = (__u32)len | ((__u32)len << 8);
++ pad |= pad << 16;
++
++ val = pad;
++ if (len > num * 4)
++ len = num * 4;
++ for (i = 0; i < len; i++) {
++ if ((i % 4) == 0)
++ val = pad;
++ val = msg[i] + (val << 8);
++ if ((i % 4) == 3) {
++ *buf++ = val;
++ val = pad;
++ num--;
++ }
++ }
++ if (--num >= 0)
++ *buf++ = val;
++ while (--num >= 0)
++ *buf++ = pad;
++}
++
++f2fs_hash_t f2fs_dentry_hash(const char *name, int len)
++{
++ __u32 hash, minor_hash;
++ f2fs_hash_t f2fs_hash;
++ const char *p;
++ __u32 in[8], buf[4];
++
++ /* Initialize the default seed for the hash checksum functions */
++ buf[0] = 0x67452301;
++ buf[1] = 0xefcdab89;
++ buf[2] = 0x98badcfe;
++ buf[3] = 0x10325476;
++
++ p = name;
++ while (len > 0) {
++ str2hashbuf(p, len, in, 4);
++ TEA_transform(buf, in);
++ len -= 16;
++ p += 16;
++ }
++ hash = buf[0];
++ minor_hash = buf[1];
++
++ f2fs_hash = hash;
++ f2fs_hash &= ~F2FS_HASH_COL_BIT;
++ return f2fs_hash;
++}
diff --git a/patches/linux-3.7/0112-f2fs-add-xattr-and-acl-functionalities.patch b/patches/linux-3.7/0112-f2fs-add-xattr-and-acl-functionalities.patch
new file mode 100644
index 0000000..165a8f4
--- /dev/null
+++ b/patches/linux-3.7/0112-f2fs-add-xattr-and-acl-functionalities.patch
@@ -0,0 +1,1101 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:31:46 +0000
+Subject: [PATCH] f2fs: add xattr and acl functionalities
+
+This implements xattr and acl functionalities.
+
+- F2FS uses a node page to contain use extended attributes.
+
+Signed-off-by: Changman Lee <cm224.lee@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/acl.c | 465 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/acl.h | 57 +++++++
+ fs/f2fs/xattr.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/xattr.h | 145 +++++++++++++++++
+ 4 files changed, 1056 insertions(+)
+ create mode 100644 fs/f2fs/acl.c
+ create mode 100644 fs/f2fs/acl.h
+ create mode 100644 fs/f2fs/xattr.c
+ create mode 100644 fs/f2fs/xattr.h
+
+diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
+new file mode 100644
+index 0000000..dff2a2b
+--- /dev/null
++++ b/fs/f2fs/acl.c
+@@ -0,0 +1,465 @@
++/**
++ * fs/f2fs/acl.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/acl.c
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "xattr.h"
++#include "acl.h"
++
++#define get_inode_mode(i) ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
++ (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
++
++static inline size_t f2fs_acl_size(int count)
++{
++ if (count <= 4) {
++ return sizeof(struct f2fs_acl_header) +
++ count * sizeof(struct f2fs_acl_entry_short);
++ } else {
++ return sizeof(struct f2fs_acl_header) +
++ 4 * sizeof(struct f2fs_acl_entry_short) +
++ (count - 4) * sizeof(struct f2fs_acl_entry);
++ }
++}
++
++static inline int f2fs_acl_count(size_t size)
++{
++ ssize_t s;
++ size -= sizeof(struct f2fs_acl_header);
++ s = size - 4 * sizeof(struct f2fs_acl_entry_short);
++ if (s < 0) {
++ if (size % sizeof(struct f2fs_acl_entry_short))
++ return -1;
++ return size / sizeof(struct f2fs_acl_entry_short);
++ } else {
++ if (s % sizeof(struct f2fs_acl_entry))
++ return -1;
++ return s / sizeof(struct f2fs_acl_entry) + 4;
++ }
++}
++
++static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
++{
++ int i, count;
++ struct posix_acl *acl;
++ struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
++ struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
++ const char *end = value + size;
++
++ if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION))
++ return ERR_PTR(-EINVAL);
++
++ count = f2fs_acl_count(size);
++ if (count < 0)
++ return ERR_PTR(-EINVAL);
++ if (count == 0)
++ return NULL;
++
++ acl = posix_acl_alloc(count, GFP_KERNEL);
++ if (!acl)
++ return ERR_PTR(-ENOMEM);
++
++ for (i = 0; i < count; i++) {
++
++ if ((char *)entry > end)
++ goto fail;
++
++ acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag);
++ acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
++
++ switch (acl->a_entries[i].e_tag) {
++ case ACL_USER_OBJ:
++ case ACL_GROUP_OBJ:
++ case ACL_MASK:
++ case ACL_OTHER:
++ acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry_short));
++ break;
++
++ case ACL_USER:
++ acl->a_entries[i].e_uid =
++ make_kuid(&init_user_ns,
++ le32_to_cpu(entry->e_id));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_GROUP:
++ acl->a_entries[i].e_gid =
++ make_kgid(&init_user_ns,
++ le32_to_cpu(entry->e_id));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ default:
++ goto fail;
++ }
++ }
++ if ((char *)entry != end)
++ goto fail;
++ return acl;
++fail:
++ posix_acl_release(acl);
++ return ERR_PTR(-EINVAL);
++}
++
++static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size)
++{
++ struct f2fs_acl_header *f2fs_acl;
++ struct f2fs_acl_entry *entry;
++ int i;
++
++ f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count *
++ sizeof(struct f2fs_acl_entry), GFP_KERNEL);
++ if (!f2fs_acl)
++ return ERR_PTR(-ENOMEM);
++
++ f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION);
++ entry = (struct f2fs_acl_entry *)(f2fs_acl + 1);
++
++ for (i = 0; i < acl->a_count; i++) {
++
++ entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag);
++ entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm);
++
++ switch (acl->a_entries[i].e_tag) {
++ case ACL_USER:
++ entry->e_id = cpu_to_le32(
++ from_kuid(&init_user_ns,
++ acl->a_entries[i].e_uid));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_GROUP:
++ entry->e_id = cpu_to_le32(
++ from_kgid(&init_user_ns,
++ acl->a_entries[i].e_gid));
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry));
++ break;
++ case ACL_USER_OBJ:
++ case ACL_GROUP_OBJ:
++ case ACL_MASK:
++ case ACL_OTHER:
++ entry = (struct f2fs_acl_entry *)((char *)entry +
++ sizeof(struct f2fs_acl_entry_short));
++ break;
++ default:
++ goto fail;
++ }
++ }
++ *size = f2fs_acl_size(acl->a_count);
++ return (void *)f2fs_acl;
++
++fail:
++ kfree(f2fs_acl);
++ return ERR_PTR(-EINVAL);
++}
++
++struct posix_acl *f2fs_get_acl(struct inode *inode, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
++ void *value = NULL;
++ struct posix_acl *acl;
++ int retval;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return NULL;
++
++ acl = get_cached_acl(inode, type);
++ if (acl != ACL_NOT_CACHED)
++ return acl;
++
++ if (type == ACL_TYPE_ACCESS)
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
++
++ retval = f2fs_getxattr(inode, name_index, "", NULL, 0);
++ if (retval > 0) {
++ value = kmalloc(retval, GFP_KERNEL);
++ if (!value)
++ return ERR_PTR(-ENOMEM);
++ retval = f2fs_getxattr(inode, name_index, "", value, retval);
++ }
++
++ if (retval < 0) {
++ if (retval == -ENODATA)
++ acl = NULL;
++ else
++ acl = ERR_PTR(retval);
++ } else {
++ acl = f2fs_acl_from_disk(value, retval);
++ }
++ kfree(value);
++ if (!IS_ERR(acl))
++ set_cached_acl(inode, type, acl);
++
++ return acl;
++}
++
++static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ int name_index;
++ void *value = NULL;
++ size_t size = 0;
++ int error;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++ if (S_ISLNK(inode->i_mode))
++ return -EOPNOTSUPP;
++
++ switch (type) {
++ case ACL_TYPE_ACCESS:
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
++ if (acl) {
++ error = posix_acl_equiv_mode(acl, &inode->i_mode);
++ if (error < 0)
++ return error;
++ set_acl_inode(fi, inode->i_mode);
++ if (error == 0)
++ acl = NULL;
++ }
++ break;
++
++ case ACL_TYPE_DEFAULT:
++ name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT;
++ if (!S_ISDIR(inode->i_mode))
++ return acl ? -EACCES : 0;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ if (acl) {
++ value = f2fs_acl_to_disk(acl, &size);
++ if (IS_ERR(value)) {
++ cond_clear_inode_flag(fi, FI_ACL_MODE);
++ return (int)PTR_ERR(value);
++ }
++ }
++
++ error = f2fs_setxattr(inode, name_index, "", value, size);
++
++ kfree(value);
++ if (!error)
++ set_cached_acl(inode, type, acl);
++
++ cond_clear_inode_flag(fi, FI_ACL_MODE);
++ return error;
++}
++
++int f2fs_init_acl(struct inode *inode, struct inode *dir)
++{
++ struct posix_acl *acl = NULL;
++ struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
++ int error = 0;
++
++ if (!S_ISLNK(inode->i_mode)) {
++ if (test_opt(sbi, POSIX_ACL)) {
++ acl = f2fs_get_acl(dir, ACL_TYPE_DEFAULT);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ }
++ if (!acl)
++ inode->i_mode &= ~current_umask();
++ }
++
++ if (test_opt(sbi, POSIX_ACL) && acl) {
++
++ if (S_ISDIR(inode->i_mode)) {
++ error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
++ if (error)
++ goto cleanup;
++ }
++ error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
++ if (error < 0)
++ return error;
++ if (error > 0)
++ error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
++ }
++cleanup:
++ posix_acl_release(acl);
++ return error;
++}
++
++int f2fs_acl_chmod(struct inode *inode)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct posix_acl *acl;
++ int error;
++ mode_t mode = get_inode_mode(inode);
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++ if (S_ISLNK(mode))
++ return -EOPNOTSUPP;
++
++ acl = f2fs_get_acl(inode, ACL_TYPE_ACCESS);
++ if (IS_ERR(acl) || !acl)
++ return PTR_ERR(acl);
++
++ error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
++ if (error)
++ return error;
++ error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
++ posix_acl_release(acl);
++ return error;
++}
++
++static size_t f2fs_xattr_list_acl(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ const char *xname = POSIX_ACL_XATTR_DEFAULT;
++ size_t size;
++
++ if (!test_opt(sbi, POSIX_ACL))
++ return 0;
++
++ if (type == ACL_TYPE_ACCESS)
++ xname = POSIX_ACL_XATTR_ACCESS;
++
++ size = strlen(xname) + 1;
++ if (list && size <= list_size)
++ memcpy(list, xname, size);
++ return size;
++}
++
++static int f2fs_xattr_get_acl(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ struct posix_acl *acl;
++ int error;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!test_opt(sbi, POSIX_ACL))
++ return -EOPNOTSUPP;
++
++ acl = f2fs_get_acl(dentry->d_inode, type);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ if (!acl)
++ return -ENODATA;
++ error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
++ posix_acl_release(acl);
++
++ return error;
++}
++
++static int f2fs_xattr_set_acl(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ struct inode *inode = dentry->d_inode;
++ struct posix_acl *acl = NULL;
++ int error;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!test_opt(sbi, POSIX_ACL))
++ return -EOPNOTSUPP;
++ if (!inode_owner_or_capable(inode))
++ return -EPERM;
++
++ if (value) {
++ acl = posix_acl_from_xattr(&init_user_ns, value, size);
++ if (IS_ERR(acl))
++ return PTR_ERR(acl);
++ if (acl) {
++ error = posix_acl_valid(acl);
++ if (error)
++ goto release_and_out;
++ }
++ } else {
++ acl = NULL;
++ }
++
++ error = f2fs_set_acl(inode, type, acl);
++
++release_and_out:
++ posix_acl_release(acl);
++ return error;
++}
++
++const struct xattr_handler f2fs_xattr_acl_default_handler = {
++ .prefix = POSIX_ACL_XATTR_DEFAULT,
++ .flags = ACL_TYPE_DEFAULT,
++ .list = f2fs_xattr_list_acl,
++ .get = f2fs_xattr_get_acl,
++ .set = f2fs_xattr_set_acl,
++};
++
++const struct xattr_handler f2fs_xattr_acl_access_handler = {
++ .prefix = POSIX_ACL_XATTR_ACCESS,
++ .flags = ACL_TYPE_ACCESS,
++ .list = f2fs_xattr_list_acl,
++ .get = f2fs_xattr_get_acl,
++ .set = f2fs_xattr_set_acl,
++};
++
++static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
++ size_t size;
++
++ if (type != F2FS_XATTR_INDEX_ADVISE)
++ return 0;
++
++ size = strlen(xname) + 1;
++ if (list && size <= list_size)
++ memcpy(list, xname, size);
++ return size;
++}
++
++static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++
++ *((char *)buffer) = F2FS_I(inode)->i_advise;
++ return sizeof(char);
++}
++
++static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (strcmp(name, "") != 0)
++ return -EINVAL;
++ if (!inode_owner_or_capable(inode))
++ return -EPERM;
++ if (value == NULL)
++ return -EINVAL;
++
++ F2FS_I(inode)->i_advise |= *(char *)value;
++ return 0;
++}
++
++const struct xattr_handler f2fs_xattr_advise_handler = {
++ .prefix = F2FS_SYSTEM_ADVISE_PREFIX,
++ .flags = F2FS_XATTR_INDEX_ADVISE,
++ .list = f2fs_xattr_advise_list,
++ .get = f2fs_xattr_advise_get,
++ .set = f2fs_xattr_advise_set,
++};
+diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
+new file mode 100644
+index 0000000..c97675e
+--- /dev/null
++++ b/fs/f2fs/acl.h
+@@ -0,0 +1,57 @@
++/**
++ * fs/f2fs/acl.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/acl.h
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __F2FS_ACL_H__
++#define __F2FS_ACL_H__
++
++#include <linux/posix_acl_xattr.h>
++
++#define F2FS_ACL_VERSION 0x0001
++
++struct f2fs_acl_entry {
++ __le16 e_tag;
++ __le16 e_perm;
++ __le32 e_id;
++};
++
++struct f2fs_acl_entry_short {
++ __le16 e_tag;
++ __le16 e_perm;
++};
++
++struct f2fs_acl_header {
++ __le32 a_version;
++};
++
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++
++extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type);
++extern int f2fs_acl_chmod(struct inode *inode);
++extern int f2fs_init_acl(struct inode *inode, struct inode *dir);
++#else
++#define f2fs_check_acl NULL
++#define f2fs_get_acl NULL
++#define f2fs_set_acl NULL
++
++static inline int f2fs_acl_chmod(struct inode *inode)
++{
++ return 0;
++}
++
++static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
++{
++ return 0;
++}
++#endif
++#endif /* __F2FS_ACL_H__ */
+diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
+new file mode 100644
+index 0000000..aca50fe
+--- /dev/null
++++ b/fs/f2fs/xattr.c
+@@ -0,0 +1,389 @@
++/**
++ * fs/f2fs/xattr.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/xattr.c
++ *
++ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
++ *
++ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
++ * Extended attributes for symlinks and special files added per
++ * suggestion of Luka Renko <luka.renko@hermes.si>.
++ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
++ * Red Hat Inc.
++ *
++ * 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/rwsem.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "xattr.h"
++
++static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
++ size_t list_size, const char *name, size_t name_len, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++ int total_len, prefix_len = 0;
++ const char *prefix = NULL;
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ prefix = XATTR_USER_PREFIX;
++ prefix_len = XATTR_USER_PREFIX_LEN;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ prefix = XATTR_TRUSTED_PREFIX;
++ prefix_len = XATTR_TRUSTED_PREFIX_LEN;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ total_len = prefix_len + name_len + 1;
++ if (list && total_len <= list_size) {
++ memcpy(list, prefix, prefix_len);
++ memcpy(list+prefix_len, name, name_len);
++ list[prefix_len + name_len] = '\0';
++ }
++ return total_len;
++}
++
++static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++ return f2fs_getxattr(dentry->d_inode, type, name,
++ buffer, size);
++}
++
++static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int type)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++
++ switch (type) {
++ case F2FS_XATTR_INDEX_USER:
++ if (!test_opt(sbi, XATTR_USER))
++ return -EOPNOTSUPP;
++ break;
++ case F2FS_XATTR_INDEX_TRUSTED:
++ if (!capable(CAP_SYS_ADMIN))
++ return -EPERM;
++ break;
++ default:
++ return -EINVAL;
++ }
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++
++ return f2fs_setxattr(dentry->d_inode, type, name, value, size);
++}
++
++const struct xattr_handler f2fs_xattr_user_handler = {
++ .prefix = XATTR_USER_PREFIX,
++ .flags = F2FS_XATTR_INDEX_USER,
++ .list = f2fs_xattr_generic_list,
++ .get = f2fs_xattr_generic_get,
++ .set = f2fs_xattr_generic_set,
++};
++
++const struct xattr_handler f2fs_xattr_trusted_handler = {
++ .prefix = XATTR_TRUSTED_PREFIX,
++ .flags = F2FS_XATTR_INDEX_TRUSTED,
++ .list = f2fs_xattr_generic_list,
++ .get = f2fs_xattr_generic_get,
++ .set = f2fs_xattr_generic_set,
++};
++
++static const struct xattr_handler *f2fs_xattr_handler_map[] = {
++ [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
++ [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
++#endif
++ [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
++ [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
++};
++
++const struct xattr_handler *f2fs_xattr_handlers[] = {
++ &f2fs_xattr_user_handler,
++#ifdef CONFIG_F2FS_FS_POSIX_ACL
++ &f2fs_xattr_acl_access_handler,
++ &f2fs_xattr_acl_default_handler,
++#endif
++ &f2fs_xattr_trusted_handler,
++ &f2fs_xattr_advise_handler,
++ NULL,
++};
++
++static inline const struct xattr_handler *f2fs_xattr_handler(int name_index)
++{
++ const struct xattr_handler *handler = NULL;
++
++ if (name_index > 0 && name_index < ARRAY_SIZE(f2fs_xattr_handler_map))
++ handler = f2fs_xattr_handler_map[name_index];
++ return handler;
++}
++
++int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_entry *entry;
++ struct page *page;
++ void *base_addr;
++ int error = 0, found = 0;
++ int value_len, name_len;
++
++ if (name == NULL)
++ return -EINVAL;
++ name_len = strlen(name);
++
++ if (!fi->i_xattr_nid)
++ return -ENODATA;
++
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++
++ list_for_each_xattr(entry, base_addr) {
++ if (entry->e_name_index != name_index)
++ continue;
++ if (entry->e_name_len != name_len)
++ continue;
++ if (!memcmp(entry->e_name, name, name_len)) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ error = -ENODATA;
++ goto cleanup;
++ }
++
++ value_len = le16_to_cpu(entry->e_value_size);
++
++ if (buffer && value_len > buffer_size) {
++ error = -ERANGE;
++ goto cleanup;
++ }
++
++ if (buffer) {
++ char *pval = entry->e_name + entry->e_name_len;
++ memcpy(buffer, pval, value_len);
++ }
++ error = value_len;
++
++cleanup:
++ f2fs_put_page(page, 1);
++ return error;
++}
++
++ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
++{
++ struct inode *inode = dentry->d_inode;
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_entry *entry;
++ struct page *page;
++ void *base_addr;
++ int error = 0;
++ size_t rest = buffer_size;
++
++ if (!fi->i_xattr_nid)
++ return 0;
++
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++
++ list_for_each_xattr(entry, base_addr) {
++ const struct xattr_handler *handler =
++ f2fs_xattr_handler(entry->e_name_index);
++ size_t size;
++
++ if (!handler)
++ continue;
++
++ size = handler->list(dentry, buffer, rest, entry->e_name,
++ entry->e_name_len, handler->flags);
++ if (buffer && size > rest) {
++ error = -ERANGE;
++ goto cleanup;
++ }
++
++ if (buffer)
++ buffer += size;
++ rest -= size;
++ }
++ error = buffer_size - rest;
++cleanup:
++ f2fs_put_page(page, 1);
++ return error;
++}
++
++int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
++ const void *value, size_t value_len)
++{
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ struct f2fs_inode_info *fi = F2FS_I(inode);
++ struct f2fs_xattr_header *header = NULL;
++ struct f2fs_xattr_entry *here, *last;
++ struct page *page;
++ void *base_addr;
++ int error, found, free, name_len, newsize;
++ char *pval;
++
++ if (name == NULL)
++ return -EINVAL;
++ name_len = strlen(name);
++
++ if (value == NULL)
++ value_len = 0;
++
++ if (name_len > 255 || value_len > MAX_VALUE_LEN)
++ return -ERANGE;
++
++ mutex_lock_op(sbi, NODE_NEW);
++ if (!fi->i_xattr_nid) {
++ /* Allocate new attribute block */
++ struct dnode_of_data dn;
++
++ if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ return -ENOSPC;
++ }
++ set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
++ mark_inode_dirty(inode);
++
++ page = new_node_page(&dn, XATTR_NODE_OFFSET);
++ if (IS_ERR(page)) {
++ alloc_nid_failed(sbi, fi->i_xattr_nid);
++ fi->i_xattr_nid = 0;
++ mutex_unlock_op(sbi, NODE_NEW);
++ return PTR_ERR(page);
++ }
++
++ alloc_nid_done(sbi, fi->i_xattr_nid);
++ base_addr = page_address(page);
++ header = XATTR_HDR(base_addr);
++ header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
++ header->h_refcount = cpu_to_le32(1);
++ } else {
++ /* The inode already has an extended attribute block. */
++ page = get_node_page(sbi, fi->i_xattr_nid);
++ if (IS_ERR(page)) {
++ mutex_unlock_op(sbi, NODE_NEW);
++ return PTR_ERR(page);
++ }
++
++ base_addr = page_address(page);
++ header = XATTR_HDR(base_addr);
++ }
++
++ if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
++ error = -EIO;
++ goto cleanup;
++ }
++
++ /* find entry with wanted name. */
++ found = 0;
++ list_for_each_xattr(here, base_addr) {
++ if (here->e_name_index != name_index)
++ continue;
++ if (here->e_name_len != name_len)
++ continue;
++ if (!memcmp(here->e_name, name, name_len)) {
++ found = 1;
++ break;
++ }
++ }
++
++ last = here;
++
++ while (!IS_XATTR_LAST_ENTRY(last))
++ last = XATTR_NEXT_ENTRY(last);
++
++ newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
++ name_len + value_len);
++
++ /* 1. Check space */
++ if (value) {
++ /* If value is NULL, it is remove operation.
++ * In case of update operation, we caculate free.
++ */
++ free = MIN_OFFSET - ((char *)last - (char *)header);
++ if (found)
++ free = free - ENTRY_SIZE(here);
++
++ if (free < newsize) {
++ error = -ENOSPC;
++ goto cleanup;
++ }
++ }
++
++ /* 2. Remove old entry */
++ if (found) {
++ /* If entry is found, remove old entry.
++ * If not found, remove operation is not needed.
++ */
++ struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
++ int oldsize = ENTRY_SIZE(here);
++
++ memmove(here, next, (char *)last - (char *)next);
++ last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
++ memset(last, 0, oldsize);
++ }
++
++ /* 3. Write new entry */
++ if (value) {
++ /* Before we come here, old entry is removed.
++ * We just write new entry. */
++ memset(last, 0, newsize);
++ last->e_name_index = name_index;
++ last->e_name_len = name_len;
++ memcpy(last->e_name, name, name_len);
++ pval = last->e_name + name_len;
++ memcpy(pval, value, value_len);
++ last->e_value_size = cpu_to_le16(value_len);
++ }
++
++ set_page_dirty(page);
++ f2fs_put_page(page, 1);
++
++ if (is_inode_flag_set(fi, FI_ACL_MODE)) {
++ inode->i_mode = fi->i_acl_mode;
++ inode->i_ctime = CURRENT_TIME;
++ clear_inode_flag(fi, FI_ACL_MODE);
++ }
++ f2fs_write_inode(inode, NULL);
++ mutex_unlock_op(sbi, NODE_NEW);
++
++ return 0;
++cleanup:
++ f2fs_put_page(page, 1);
++ mutex_unlock_op(sbi, NODE_NEW);
++ return error;
++}
+diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
+new file mode 100644
+index 0000000..29b0a08
+--- /dev/null
++++ b/fs/f2fs/xattr.h
+@@ -0,0 +1,145 @@
++/**
++ * fs/f2fs/xattr.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * Portions of this code from linux/fs/ext2/xattr.h
++ *
++ * On-disk format of extended attributes for the ext2 filesystem.
++ *
++ * (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
++ *
++ * 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 __F2FS_XATTR_H__
++#define __F2FS_XATTR_H__
++
++#include <linux/init.h>
++#include <linux/xattr.h>
++
++/* Magic value in attribute blocks */
++#define F2FS_XATTR_MAGIC 0xF2F52011
++
++/* Maximum number of references to one attribute block */
++#define F2FS_XATTR_REFCOUNT_MAX 1024
++
++/* Name indexes */
++#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise"
++#define F2FS_XATTR_INDEX_USER 1
++#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2
++#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3
++#define F2FS_XATTR_INDEX_TRUSTED 4
++#define F2FS_XATTR_INDEX_LUSTRE 5
++#define F2FS_XATTR_INDEX_SECURITY 6
++#define F2FS_XATTR_INDEX_ADVISE 7
++
++struct f2fs_xattr_header {
++ __le32 h_magic; /* magic number for identification */
++ __le32 h_refcount; /* reference count */
++ __u32 h_reserved[4]; /* zero right now */
++};
++
++struct f2fs_xattr_entry {
++ __u8 e_name_index;
++ __u8 e_name_len;
++ __le16 e_value_size; /* size of attribute value */
++ char e_name[0]; /* attribute name */
++};
++
++#define XATTR_HDR(ptr) ((struct f2fs_xattr_header *)(ptr))
++#define XATTR_ENTRY(ptr) ((struct f2fs_xattr_entry *)(ptr))
++#define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr)+1))
++#define XATTR_ROUND (3)
++
++#define XATTR_ALIGN(size) ((size + XATTR_ROUND) & ~XATTR_ROUND)
++
++#define ENTRY_SIZE(entry) (XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + \
++ entry->e_name_len + le16_to_cpu(entry->e_value_size)))
++
++#define XATTR_NEXT_ENTRY(entry) ((struct f2fs_xattr_entry *)((char *)(entry) +\
++ ENTRY_SIZE(entry)))
++
++#define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
++
++#define list_for_each_xattr(entry, addr) \
++ for (entry = XATTR_FIRST_ENTRY(addr);\
++ !IS_XATTR_LAST_ENTRY(entry);\
++ entry = XATTR_NEXT_ENTRY(entry))
++
++
++#define MIN_OFFSET XATTR_ALIGN(PAGE_SIZE - \
++ sizeof(struct node_footer) - \
++ sizeof(__u32))
++
++#define MAX_VALUE_LEN (MIN_OFFSET - sizeof(struct f2fs_xattr_header) - \
++ sizeof(struct f2fs_xattr_entry))
++
++/**
++ * On-disk structure of f2fs_xattr
++ * We use only 1 block for xattr.
++ *
++ * +--------------------+
++ * | f2fs_xattr_header |
++ * | |
++ * +--------------------+
++ * | f2fs_xattr_entry |
++ * | .e_name_index = 1 |
++ * | .e_name_len = 3 |
++ * | .e_value_size = 14 |
++ * | .e_name = "foo" |
++ * | "value_of_xattr" |<- value_offs = e_name + e_name_len
++ * +--------------------+
++ * | f2fs_xattr_entry |
++ * | .e_name_index = 4 |
++ * | .e_name = "bar" |
++ * +--------------------+
++ * | |
++ * | Free |
++ * | |
++ * +--------------------+<- MIN_OFFSET
++ * | node_footer |
++ * | (nid, ino, offset) |
++ * +--------------------+
++ *
++ **/
++
++#ifdef CONFIG_F2FS_FS_XATTR
++extern const struct xattr_handler f2fs_xattr_user_handler;
++extern const struct xattr_handler f2fs_xattr_trusted_handler;
++extern const struct xattr_handler f2fs_xattr_acl_access_handler;
++extern const struct xattr_handler f2fs_xattr_acl_default_handler;
++extern const struct xattr_handler f2fs_xattr_advise_handler;
++
++extern const struct xattr_handler *f2fs_xattr_handlers[];
++
++extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
++ const void *value, size_t value_len);
++extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
++ void *buffer, size_t buffer_size);
++extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
++ size_t buffer_size);
++
++#else
++
++#define f2fs_xattr_handlers NULL
++static inline int f2fs_setxattr(struct inode *inode, int name_index,
++ const char *name, const void *value, size_t value_len)
++{
++ return -EOPNOTSUPP;
++}
++static inline int f2fs_getxattr(struct inode *inode, int name_index,
++ const char *name, void *buffer, size_t buffer_size)
++{
++ return -EOPNOTSUPP;
++}
++static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
++ size_t buffer_size)
++{
++ return -EOPNOTSUPP;
++}
++#endif
++
++#endif /* __F2FS_XATTR_H__ */
diff --git a/patches/linux-3.7/0113-f2fs-add-garbage-collection-functions.patch b/patches/linux-3.7/0113-f2fs-add-garbage-collection-functions.patch
new file mode 100644
index 0000000..736984b
--- /dev/null
+++ b/patches/linux-3.7/0113-f2fs-add-garbage-collection-functions.patch
@@ -0,0 +1,1394 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:32:20 +0000
+Subject: [PATCH] f2fs: add garbage collection functions
+
+This adds on-demand and background cleaning functions.
+
+- The basic background cleaning policy is trying to do cleaning jobs as much as
+ possible whenever the system is idle. Once the background cleaning is done,
+ the cleaner sleeps an amount of time not to interfere with VFS calls. The time
+ is dynamically adjusted according to the status of whole segments, which is
+ decreased when the following conditions are satisfied.
+
+ . GC is not conducted currently, and
+ . IO subsystem is idle by checking the number of requets in bdev's request
+ list, and
+ . There are enough dirty segments.
+
+ Otherwise, the time is increased incrementally until to the maximum time.
+ Note that, min and max times are 10 secs and 30 secs by default.
+
+- F2FS adopts a default victim selection policy where background cleaning uses
+ a cost-benefit algorithm, while on-demand cleaning uses a greedy algorithm.
+
+- The method of moving data during the cleaning is slightly different between
+ background and on-demand cleaning schemes. In the case of background cleaning,
+ F2FS loads the data, and marks them as dirty. Then, F2FS expects that the data
+ will be moved by flusher or VM. In the case of on-demand cleaning, F2FS should
+ move the data right away.
+
+- In order to identify valid blocks in a victim segment, F2FS scans the bitmap
+ of the segment managed as an SIT entry.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/gc.c | 1139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/gc.h | 203 +++++++++++
+ 2 files changed, 1342 insertions(+)
+ create mode 100644 fs/f2fs/gc.c
+ create mode 100644 fs/f2fs/gc.h
+
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+new file mode 100644
+index 0000000..753b05e
+--- /dev/null
++++ b/fs/f2fs/gc.c
+@@ -0,0 +1,1139 @@
++/**
++ * fs/f2fs/gc.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/backing-dev.h>
++#include <linux/proc_fs.h>
++#include <linux/init.h>
++#include <linux/f2fs_fs.h>
++#include <linux/kthread.h>
++#include <linux/delay.h>
++#include <linux/freezer.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "gc.h"
++
++static LIST_HEAD(f2fs_stat_list);
++static struct kmem_cache *winode_slab;
++
++static int gc_thread_func(void *data)
++{
++ struct f2fs_sb_info *sbi = data;
++ wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
++ long wait_ms;
++
++ wait_ms = GC_THREAD_MIN_SLEEP_TIME;
++
++ do {
++ if (try_to_freeze())
++ continue;
++ else
++ wait_event_interruptible_timeout(*wq,
++ kthread_should_stop(),
++ msecs_to_jiffies(wait_ms));
++ if (kthread_should_stop())
++ break;
++
++ f2fs_balance_fs(sbi);
++
++ if (!test_opt(sbi, BG_GC))
++ continue;
++
++ /*
++ * [GC triggering condition]
++ * 0. GC is not conducted currently.
++ * 1. There are enough dirty segments.
++ * 2. IO subsystem is idle by checking the # of writeback pages.
++ * 3. IO subsystem is idle by checking the # of requests in
++ * bdev's request list.
++ *
++ * Note) We have to avoid triggering GCs too much frequently.
++ * Because it is possible that some segments can be
++ * invalidated soon after by user update or deletion.
++ * So, I'd like to wait some time to collect dirty segments.
++ */
++ if (!mutex_trylock(&sbi->gc_mutex))
++ continue;
++
++ if (!is_idle(sbi)) {
++ wait_ms = increase_sleep_time(wait_ms);
++ mutex_unlock(&sbi->gc_mutex);
++ continue;
++ }
++
++ if (has_enough_invalid_blocks(sbi))
++ wait_ms = decrease_sleep_time(wait_ms);
++ else
++ wait_ms = increase_sleep_time(wait_ms);
++
++ sbi->bg_gc++;
++
++ if (f2fs_gc(sbi, 1) == GC_NONE)
++ wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
++ else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
++ wait_ms = GC_THREAD_MAX_SLEEP_TIME;
++
++ } while (!kthread_should_stop());
++ return 0;
++}
++
++int start_gc_thread(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_kthread *gc_th = NULL;
++
++ gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
++ if (!gc_th)
++ return -ENOMEM;
++
++ sbi->gc_thread = gc_th;
++ init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
++ sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
++ GC_THREAD_NAME);
++ if (IS_ERR(gc_th->f2fs_gc_task)) {
++ kfree(gc_th);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++void stop_gc_thread(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
++ if (!gc_th)
++ return;
++ kthread_stop(gc_th->f2fs_gc_task);
++ kfree(gc_th);
++ sbi->gc_thread = NULL;
++}
++
++static int select_gc_type(int gc_type)
++{
++ return (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
++}
++
++static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
++ int type, struct victim_sel_policy *p)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++
++ if (IS_SSR_TYPE(type)) {
++ p->alloc_mode = SSR;
++ p->gc_mode = GC_GREEDY;
++ p->type = GET_SSR_TYPE(type);
++ p->dirty_segmap = dirty_i->dirty_segmap[p->type];
++ p->ofs_unit = 1;
++ } else {
++ p->alloc_mode = LFS;
++ p->gc_mode = select_gc_type(gc_type);
++ p->type = 0;
++ p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
++ p->ofs_unit = sbi->segs_per_sec;
++ }
++ p->offset = sbi->last_victim[p->gc_mode];
++}
++
++static unsigned int get_max_cost(struct f2fs_sb_info *sbi,
++ struct victim_sel_policy *p)
++{
++ if (p->gc_mode == GC_GREEDY)
++ return (1 << sbi->log_blocks_per_seg) * p->ofs_unit;
++ else if (p->gc_mode == GC_CB)
++ return UINT_MAX;
++ else /* No other gc_mode */
++ return 0;
++}
++
++static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ unsigned int segno;
++
++ /*
++ * If the gc_type is FG_GC, we can select victim segments
++ * selected by background GC before.
++ * Those segments guarantee they have small valid blocks.
++ */
++ segno = find_next_bit(dirty_i->victim_segmap[BG_GC],
++ TOTAL_SEGS(sbi), 0);
++ if (segno < TOTAL_SEGS(sbi)) {
++ clear_bit(segno, dirty_i->victim_segmap[BG_GC]);
++ return segno;
++ }
++ return NULL_SEGNO;
++}
++
++static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int secno = GET_SECNO(sbi, segno);
++ unsigned int start = secno * sbi->segs_per_sec;
++ unsigned long long mtime = 0;
++ unsigned int vblocks;
++ unsigned char age = 0;
++ unsigned char u;
++ unsigned int i;
++
++ for (i = 0; i < sbi->segs_per_sec; i++)
++ mtime += get_seg_entry(sbi, start + i)->mtime;
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++
++ mtime = div_u64(mtime, sbi->segs_per_sec);
++ vblocks = div_u64(vblocks, sbi->segs_per_sec);
++
++ u = (vblocks * 100) >> sbi->log_blocks_per_seg;
++
++ /* Handle if the system time is changed by user */
++ if (mtime < sit_i->min_mtime)
++ sit_i->min_mtime = mtime;
++ if (mtime > sit_i->max_mtime)
++ sit_i->max_mtime = mtime;
++ if (sit_i->max_mtime != sit_i->min_mtime)
++ age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime),
++ sit_i->max_mtime - sit_i->min_mtime);
++
++ return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
++}
++
++static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
++ struct victim_sel_policy *p)
++{
++ if (p->alloc_mode == SSR)
++ return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
++
++ /* alloc_mode == LFS */
++ if (p->gc_mode == GC_GREEDY)
++ return get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ else
++ return get_cb_cost(sbi, segno);
++}
++
++/**
++ * This function is called from two pathes.
++ * One is garbage collection and the other is SSR segment selection.
++ * When it is called during GC, it just gets a victim segment
++ * and it does not remove it from dirty seglist.
++ * When it is called from SSR segment selection, it finds a segment
++ * which has minimum valid blocks and removes it from dirty seglist.
++ */
++static int get_victim_by_default(struct f2fs_sb_info *sbi,
++ unsigned int *result, int gc_type, int type)
++{
++ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
++ struct victim_sel_policy p;
++ unsigned int segno;
++ int nsearched = 0;
++
++ select_policy(sbi, gc_type, type, &p);
++
++ p.min_segno = NULL_SEGNO;
++ p.min_cost = get_max_cost(sbi, &p);
++
++ mutex_lock(&dirty_i->seglist_lock);
++
++ if (p.alloc_mode == LFS && gc_type == FG_GC) {
++ p.min_segno = check_bg_victims(sbi);
++ if (p.min_segno != NULL_SEGNO)
++ goto got_it;
++ }
++
++ while (1) {
++ unsigned long cost;
++
++ segno = find_next_bit(p.dirty_segmap,
++ TOTAL_SEGS(sbi), p.offset);
++ if (segno >= TOTAL_SEGS(sbi)) {
++ if (sbi->last_victim[p.gc_mode]) {
++ sbi->last_victim[p.gc_mode] = 0;
++ p.offset = 0;
++ continue;
++ }
++ break;
++ }
++ p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
++
++ if (test_bit(segno, dirty_i->victim_segmap[FG_GC]))
++ continue;
++ if (gc_type == BG_GC &&
++ test_bit(segno, dirty_i->victim_segmap[BG_GC]))
++ continue;
++ if (IS_CURSEC(sbi, GET_SECNO(sbi, segno)))
++ continue;
++
++ cost = get_gc_cost(sbi, segno, &p);
++
++ if (p.min_cost > cost) {
++ p.min_segno = segno;
++ p.min_cost = cost;
++ }
++
++ if (cost == get_max_cost(sbi, &p))
++ continue;
++
++ if (nsearched++ >= MAX_VICTIM_SEARCH) {
++ sbi->last_victim[p.gc_mode] = segno;
++ break;
++ }
++ }
++got_it:
++ if (p.min_segno != NULL_SEGNO) {
++ *result = (p.min_segno / p.ofs_unit) * p.ofs_unit;
++ if (p.alloc_mode == LFS) {
++ int i;
++ for (i = 0; i < p.ofs_unit; i++)
++ set_bit(*result + i,
++ dirty_i->victim_segmap[gc_type]);
++ }
++ }
++ mutex_unlock(&dirty_i->seglist_lock);
++
++ return (p.min_segno == NULL_SEGNO) ? 0 : 1;
++}
++
++static const struct victim_selection default_v_ops = {
++ .get_victim = get_victim_by_default,
++};
++
++static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist)
++{
++ struct list_head *this;
++ struct inode_entry *ie;
++
++ list_for_each(this, ilist) {
++ ie = list_entry(this, struct inode_entry, list);
++ if (ie->inode->i_ino == ino)
++ return ie->inode;
++ }
++ return NULL;
++}
++
++static void add_gc_inode(struct inode *inode, struct list_head *ilist)
++{
++ struct list_head *this;
++ struct inode_entry *new_ie, *ie;
++
++ list_for_each(this, ilist) {
++ ie = list_entry(this, struct inode_entry, list);
++ if (ie->inode == inode) {
++ iput(inode);
++ return;
++ }
++ }
++repeat:
++ new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS);
++ if (!new_ie) {
++ cond_resched();
++ goto repeat;
++ }
++ new_ie->inode = inode;
++ list_add_tail(&new_ie->list, ilist);
++}
++
++static void put_gc_inode(struct list_head *ilist)
++{
++ struct inode_entry *ie, *next_ie;
++ list_for_each_entry_safe(ie, next_ie, ilist, list) {
++ iput(ie->inode);
++ list_del(&ie->list);
++ kmem_cache_free(winode_slab, ie);
++ }
++}
++
++static int check_valid_map(struct f2fs_sb_info *sbi,
++ unsigned int segno, int offset)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ struct seg_entry *sentry;
++ int ret;
++
++ mutex_lock(&sit_i->sentry_lock);
++ sentry = get_seg_entry(sbi, segno);
++ ret = f2fs_test_bit(offset, sentry->cur_valid_map);
++ mutex_unlock(&sit_i->sentry_lock);
++ return ret ? GC_OK : GC_NEXT;
++}
++
++/**
++ * This function compares node address got in summary with that in NAT.
++ * On validity, copy that node with cold status, otherwise (invalid node)
++ * ignore that.
++ */
++static int gc_node_segment(struct f2fs_sb_info *sbi,
++ struct f2fs_summary *sum, unsigned int segno, int gc_type)
++{
++ bool initial = true;
++ struct f2fs_summary *entry;
++ int off;
++
++next_step:
++ entry = sum;
++ for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
++ nid_t nid = le32_to_cpu(entry->nid);
++ struct page *node_page;
++ int err;
++
++ /*
++ * It makes sure that free segments are able to write
++ * all the dirty node pages before CP after this CP.
++ * So let's check the space of dirty node pages.
++ */
++ if (should_do_checkpoint(sbi)) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ return GC_BLOCKED;
++ }
++
++ err = check_valid_map(sbi, segno, off);
++ if (err == GC_ERROR)
++ return err;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (initial) {
++ ra_node_page(sbi, nid);
++ continue;
++ }
++ node_page = get_node_page(sbi, nid);
++ if (IS_ERR(node_page))
++ continue;
++
++ /* set page dirty and write it */
++ if (!PageWriteback(node_page))
++ set_page_dirty(node_page);
++ f2fs_put_page(node_page, 1);
++ gc_stat_inc_node_blk_count(sbi, 1);
++ }
++ if (initial) {
++ initial = false;
++ goto next_step;
++ }
++
++ if (gc_type == FG_GC) {
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_ALL,
++ .nr_to_write = LONG_MAX,
++ .for_reclaim = 0,
++ };
++ sync_node_pages(sbi, 0, &wbc);
++ }
++ return GC_DONE;
++}
++
++/**
++ * Calculate start block index that this node page contains
++ */
++block_t start_bidx_of_node(unsigned int node_ofs)
++{
++ block_t start_bidx;
++ unsigned int bidx, indirect_blks;
++ int dec;
++
++ indirect_blks = 2 * NIDS_PER_BLOCK + 4;
++
++ start_bidx = 1;
++ if (node_ofs == 0) {
++ start_bidx = 0;
++ } else if (node_ofs <= 2) {
++ bidx = node_ofs - 1;
++ } else if (node_ofs <= indirect_blks) {
++ dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1);
++ bidx = node_ofs - 2 - dec;
++ } else {
++ dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1);
++ bidx = node_ofs - 5 - dec;
++ }
++
++ if (start_bidx)
++ start_bidx = bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE;
++ return start_bidx;
++}
++
++static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
++ struct node_info *dni, block_t blkaddr, unsigned int *nofs)
++{
++ struct page *node_page;
++ nid_t nid;
++ unsigned int ofs_in_node;
++ block_t source_blkaddr;
++
++ nid = le32_to_cpu(sum->nid);
++ ofs_in_node = le16_to_cpu(sum->ofs_in_node);
++
++ node_page = get_node_page(sbi, nid);
++ if (IS_ERR(node_page))
++ return GC_NEXT;
++
++ get_node_info(sbi, nid, dni);
++
++ if (sum->version != dni->version) {
++ f2fs_put_page(node_page, 1);
++ return GC_NEXT;
++ }
++
++ *nofs = ofs_of_node(node_page);
++ source_blkaddr = datablock_addr(node_page, ofs_in_node);
++ f2fs_put_page(node_page, 1);
++
++ if (source_blkaddr != blkaddr)
++ return GC_NEXT;
++ return GC_OK;
++}
++
++static void move_data_page(struct inode *inode, struct page *page, int gc_type)
++{
++ if (page->mapping != inode->i_mapping)
++ goto out;
++
++ if (inode != page->mapping->host)
++ goto out;
++
++ if (PageWriteback(page))
++ goto out;
++
++ if (gc_type == BG_GC) {
++ set_page_dirty(page);
++ set_cold_data(page);
++ } else {
++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
++ mutex_lock_op(sbi, DATA_WRITE);
++ if (clear_page_dirty_for_io(page) &&
++ S_ISDIR(inode->i_mode)) {
++ dec_page_count(sbi, F2FS_DIRTY_DENTS);
++ inode_dec_dirty_dents(inode);
++ }
++ set_cold_data(page);
++ do_write_data_page(page);
++ mutex_unlock_op(sbi, DATA_WRITE);
++ clear_cold_data(page);
++ }
++out:
++ f2fs_put_page(page, 1);
++}
++
++/**
++ * This function tries to get parent node of victim data block, and identifies
++ * data block validity. If the block is valid, copy that with cold status and
++ * modify parent node.
++ * If the parent node is not valid or the data block address is different,
++ * the victim data block is ignored.
++ */
++static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
++ struct list_head *ilist, unsigned int segno, int gc_type)
++{
++ struct super_block *sb = sbi->sb;
++ struct f2fs_summary *entry;
++ block_t start_addr;
++ int err, off;
++ int phase = 0;
++
++ start_addr = START_BLOCK(sbi, segno);
++
++next_step:
++ entry = sum;
++ for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
++ struct page *data_page;
++ struct inode *inode;
++ struct node_info dni; /* dnode info for the data */
++ unsigned int ofs_in_node, nofs;
++ block_t start_bidx;
++
++ /*
++ * It makes sure that free segments are able to write
++ * all the dirty node pages before CP after this CP.
++ * So let's check the space of dirty node pages.
++ */
++ if (should_do_checkpoint(sbi)) {
++ mutex_lock(&sbi->cp_mutex);
++ block_operations(sbi);
++ err = GC_BLOCKED;
++ goto stop;
++ }
++
++ err = check_valid_map(sbi, segno, off);
++ if (err == GC_ERROR)
++ goto stop;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (phase == 0) {
++ ra_node_page(sbi, le32_to_cpu(entry->nid));
++ continue;
++ }
++
++ /* Get an inode by ino with checking validity */
++ err = check_dnode(sbi, entry, &dni, start_addr + off, &nofs);
++ if (err == GC_ERROR)
++ goto stop;
++ else if (err == GC_NEXT)
++ continue;
++
++ if (phase == 1) {
++ ra_node_page(sbi, dni.ino);
++ continue;
++ }
++
++ start_bidx = start_bidx_of_node(nofs);
++ ofs_in_node = le16_to_cpu(entry->ofs_in_node);
++
++ if (phase == 2) {
++ inode = f2fs_iget_nowait(sb, dni.ino);
++ if (IS_ERR(inode))
++ continue;
++
++ data_page = find_data_page(inode,
++ start_bidx + ofs_in_node);
++ if (IS_ERR(data_page))
++ goto next_iput;
++
++ f2fs_put_page(data_page, 0);
++ add_gc_inode(inode, ilist);
++ } else {
++ inode = find_gc_inode(dni.ino, ilist);
++ if (inode) {
++ data_page = get_lock_data_page(inode,
++ start_bidx + ofs_in_node);
++ if (IS_ERR(data_page))
++ continue;
++ move_data_page(inode, data_page, gc_type);
++ gc_stat_inc_data_blk_count(sbi, 1);
++ }
++ }
++ continue;
++next_iput:
++ iput(inode);
++ }
++ if (++phase < 4)
++ goto next_step;
++ err = GC_DONE;
++stop:
++ if (gc_type == FG_GC)
++ f2fs_submit_bio(sbi, DATA, true);
++ return err;
++}
++
++static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
++ int gc_type, int type)
++{
++ struct sit_info *sit_i = SIT_I(sbi);
++ int ret;
++ mutex_lock(&sit_i->sentry_lock);
++ ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, result, gc_type, type);
++ mutex_unlock(&sit_i->sentry_lock);
++ return ret;
++}
++
++static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno,
++ struct list_head *ilist, int gc_type)
++{
++ struct page *sum_page;
++ struct f2fs_summary_block *sum;
++ int ret = GC_DONE;
++
++ /* read segment summary of victim */
++ sum_page = get_sum_page(sbi, segno);
++ if (IS_ERR(sum_page))
++ return GC_ERROR;
++
++ /*
++ * CP needs to lock sum_page. In this time, we don't need
++ * to lock this page, because this summary page is not gone anywhere.
++ * Also, this page is not gonna be updated before GC is done.
++ */
++ unlock_page(sum_page);
++ sum = page_address(sum_page);
++
++ switch (GET_SUM_TYPE((&sum->footer))) {
++ case SUM_TYPE_NODE:
++ ret = gc_node_segment(sbi, sum->entries, segno, gc_type);
++ break;
++ case SUM_TYPE_DATA:
++ ret = gc_data_segment(sbi, sum->entries, ilist, segno, gc_type);
++ break;
++ }
++ gc_stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer)));
++ gc_stat_inc_call_count(sbi->gc_info);
++
++ f2fs_put_page(sum_page, 0);
++ return ret;
++}
++
++int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
++{
++ unsigned int segno;
++ int old_free_secs, cur_free_secs;
++ int gc_status, nfree;
++ struct list_head ilist;
++ int gc_type = BG_GC;
++
++ INIT_LIST_HEAD(&ilist);
++gc_more:
++ nfree = 0;
++ gc_status = GC_NONE;
++
++ if (has_not_enough_free_secs(sbi))
++ old_free_secs = reserved_sections(sbi);
++ else
++ old_free_secs = free_sections(sbi);
++
++ while (sbi->sb->s_flags & MS_ACTIVE) {
++ int i;
++ if (has_not_enough_free_secs(sbi))
++ gc_type = FG_GC;
++
++ cur_free_secs = free_sections(sbi) + nfree;
++
++ /* We got free space successfully. */
++ if (nGC < cur_free_secs - old_free_secs)
++ break;
++
++ if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
++ break;
++
++ for (i = 0; i < sbi->segs_per_sec; i++) {
++ /*
++ * do_garbage_collect will give us three gc_status:
++ * GC_ERROR, GC_DONE, and GC_BLOCKED.
++ * If GC is finished uncleanly, we have to return
++ * the victim to dirty segment list.
++ */
++ gc_status = do_garbage_collect(sbi, segno + i,
++ &ilist, gc_type);
++ if (gc_status != GC_DONE)
++ goto stop;
++ nfree++;
++ }
++ }
++stop:
++ if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
++ write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
++ if (nfree)
++ goto gc_more;
++ }
++ sbi->last_gc_status = gc_status;
++ mutex_unlock(&sbi->gc_mutex);
++
++ put_gc_inode(&ilist);
++ BUG_ON(!list_empty(&ilist));
++ return gc_status;
++}
++
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ int i;
++
++ /* valid check of the segment numbers */
++ si->hit_ext = sbi->read_hit_ext;
++ si->total_ext = sbi->total_hit_ext;
++ si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
++ si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
++ si->ndirty_dirs = sbi->n_dirty_dirs;
++ si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
++ si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++ si->rsvd_segs = reserved_segments(sbi);
++ si->overp_segs = overprovision_segments(sbi);
++ si->valid_count = valid_user_blocks(sbi);
++ si->valid_node_count = valid_node_count(sbi);
++ si->valid_inode_count = valid_inode_count(sbi);
++ si->utilization = utilization(sbi);
++
++ si->free_segs = free_segments(sbi);
++ si->free_secs = free_sections(sbi);
++ si->prefree_count = prefree_segments(sbi);
++ si->dirty_count = dirty_segments(sbi);
++ si->node_pages = sbi->node_inode->i_mapping->nrpages;
++ si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
++ si->nats = NM_I(sbi)->nat_cnt;
++ si->sits = SIT_I(sbi)->dirty_sentries;
++ si->fnids = NM_I(sbi)->fcnt;
++ si->bg_gc = sbi->bg_gc;
++ si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_valid = (int)(written_block_count(sbi) >>
++ sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_invalid = 50 - si->util_free - si->util_valid;
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ si->curseg[i] = curseg->segno;
++ si->cursec[i] = curseg->segno / sbi->segs_per_sec;
++ si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
++ }
++
++ for (i = 0; i < 2; i++) {
++ si->segment_count[i] = sbi->segment_count[i];
++ si->block_count[i] = sbi->block_count[i];
++ }
++}
++
++/**
++ * This function calculates BDF of every segments
++ */
++void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno, vblocks;
++ int ndirty = 0;
++
++ bimodal = 0;
++ total_vblocks = 0;
++ blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
++ hblks_per_sec = blks_per_sec / 2;
++ mutex_lock(&sit_i->sentry_lock);
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ dist = abs(vblocks - hblks_per_sec);
++ bimodal += dist * dist;
++
++ if (vblocks > 0 && vblocks < blks_per_sec) {
++ total_vblocks += vblocks;
++ ndirty++;
++ }
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
++ si->bimodal = bimodal / dist;
++ if (si->dirty_count)
++ si->avg_vblocks = total_vblocks / ndirty;
++ else
++ si->avg_vblocks = 0;
++}
++
++static int f2fs_read_gc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++ int i = 0;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ int j;
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_stat(si->sbi);
++
++ buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
++ buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ buf += sprintf(buf, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count,
++ si->free_segs,
++ si->free_secs);
++ buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
++ buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
++ buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
++ buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
++ buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
++ buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ buf += sprintf(buf, "\nBalancing F2FS Async:\n");
++ buf += sprintf(buf, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ buf += sprintf(buf, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ buf += sprintf(buf, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ buf += sprintf(buf, "\nDistribution of User Blocks:");
++ buf += sprintf(buf, " [ valid | invalid | free ]\n");
++ buf += sprintf(buf, " [");
++ for (j = 0; j < si->util_valid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_invalid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_free; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "]\n\n");
++ buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_sit(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_gc_metric(si->sbi);
++
++ buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_mem(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
++ unsigned npages;
++ unsigned base_mem = 0, cache_mem = 0;
++
++ si = gc_i->stat_info;
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
++ base_mem += 2 * sizeof(struct f2fs_inode_info);
++ base_mem += sizeof(*sbi->ckpt);
++
++ /* build sm */
++ base_mem += sizeof(struct f2fs_sm_info);
++
++ /* build sit */
++ base_mem += sizeof(struct sit_info);
++ base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
++ if (sbi->segs_per_sec > 1)
++ base_mem += sbi->total_sections *
++ sizeof(struct sec_entry);
++ base_mem += __bitmap_size(sbi, SIT_BITMAP);
++
++ /* build free segmap */
++ base_mem += sizeof(struct free_segmap_info);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += f2fs_bitmap_size(sbi->total_sections);
++
++ /* build curseg */
++ base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
++ base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
++
++ /* build dirty segmap */
++ base_mem += sizeof(struct dirty_seglist_info);
++ base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ /* buld nm */
++ base_mem += sizeof(struct f2fs_nm_info);
++ base_mem += __bitmap_size(sbi, NAT_BITMAP);
++
++ /* build gc */
++ base_mem += sizeof(struct f2fs_gc_info);
++ base_mem += sizeof(struct f2fs_gc_kthread);
++
++ /* free nids */
++ cache_mem += NM_I(sbi)->fcnt;
++ cache_mem += NM_I(sbi)->nat_cnt;
++ npages = sbi->node_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ npages = sbi->meta_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
++ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
++
++ buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10,
++ cache_mem >> 10);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++int f2fs_stat_init(struct f2fs_sb_info *sbi)
++{
++ struct proc_dir_entry *entry;
++
++ entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
++ if (!entry)
++ return -ENOMEM;
++ entry->read_proc = f2fs_read_gc;
++ entry->write_proc = NULL;
++
++ entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_sit;
++ entry->write_proc = NULL;
++ entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_mem;
++ entry->write_proc = NULL;
++ return 0;
++}
++
++void f2fs_stat_exit(struct f2fs_sb_info *sbi)
++{
++ if (sbi->s_proc) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
++ }
++}
++#endif
++
++int build_gc_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i;
++ struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
++#ifdef CONFIG_F2FS_STAT_FS
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_stat_info *si;
++#endif
++
++ gc_i = kzalloc(sizeof(struct f2fs_gc_info), GFP_KERNEL);
++ if (!gc_i)
++ return -ENOMEM;
++
++ sbi->gc_info = gc_i;
++ gc_i->rsvd_segment_count = le32_to_cpu(ckp->rsvd_segment_count);
++ gc_i->overp_segment_count = le32_to_cpu(ckp->overprov_segment_count);
++
++ DIRTY_I(sbi)->v_ops = &default_v_ops;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
++ GFP_KERNEL);
++ if (!gc_i->stat_info)
++ return -ENOMEM;
++ si = gc_i->stat_info;
++ mutex_init(&si->stat_list);
++ list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
++
++ si->all_area_segs = le32_to_cpu(raw_super->segment_count);
++ si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
++ si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
++ si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
++ si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
++ si->main_area_sections = le32_to_cpu(raw_super->section_count);
++ si->main_area_zones = si->main_area_sections /
++ le32_to_cpu(raw_super->secs_per_zone);
++ si->sbi = sbi;
++#endif
++ return 0;
++}
++
++void destroy_gc_manager(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++#ifdef CONFIG_F2FS_STAT_FS
++ struct f2fs_stat_info *si = gc_i->stat_info;
++#endif
++ if (!gc_i)
++ return;
++
++#ifdef CONFIG_F2FS_STAT_FS
++ list_del(&gc_i->stat_list);
++ mutex_lock(&si->stat_list);
++ si->sbi = NULL;
++ mutex_unlock(&si->stat_list);
++ kfree(gc_i->stat_info);
++#endif
++ sbi->gc_info = NULL;
++ kfree(gc_i);
++}
++
++int create_gc_caches(void)
++{
++ winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
++ sizeof(struct inode_entry), NULL);
++ if (!winode_slab)
++ return -ENOMEM;
++ return 0;
++}
++
++void destroy_gc_caches(void)
++{
++ kmem_cache_destroy(winode_slab);
++}
+diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
+new file mode 100644
+index 0000000..29b345d
+--- /dev/null
++++ b/fs/f2fs/gc.h
+@@ -0,0 +1,203 @@
++/**
++ * fs/f2fs/gc.h
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#define GC_THREAD_NAME "f2fs_gc_task"
++#define GC_THREAD_MIN_WB_PAGES 1 /*
++ * a threshold to determine
++ * whether IO subsystem is idle
++ * or not
++ */
++#define GC_THREAD_MIN_SLEEP_TIME 10000 /* milliseconds */
++#define GC_THREAD_MAX_SLEEP_TIME 30000
++#define GC_THREAD_NOGC_SLEEP_TIME 10000
++#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */
++#define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */
++
++/* Search max. number of dirty segments to select a victim segment */
++#define MAX_VICTIM_SEARCH 20
++
++enum {
++ GC_NONE = 0,
++ GC_ERROR,
++ GC_OK,
++ GC_NEXT,
++ GC_BLOCKED,
++ GC_DONE,
++};
++
++#ifdef CONFIG_F2FS_STAT_FS
++struct f2fs_stat_info {
++ struct f2fs_sb_info *sbi;
++ struct mutex stat_list;
++ int all_area_segs;
++ int sit_area_segs;
++ int nat_area_segs;
++ int ssa_area_segs;
++ int main_area_segs;
++ int main_area_sections;
++ int main_area_zones;
++ int hit_ext, total_ext;
++ int ndirty_node;
++ int ndirty_dent;
++ int ndirty_dirs;
++ int ndirty_meta;
++ int nats, sits, fnids;
++ int total_count;
++ int utilization;
++ int bg_gc;
++ unsigned int valid_count;
++ unsigned int valid_node_count;
++ unsigned int valid_inode_count;
++ unsigned int bimodal, avg_vblocks;
++ int util_free, util_valid, util_invalid;
++ int rsvd_segs, overp_segs;
++ int dirty_count;
++ int node_pages;
++ int meta_pages;
++ int prefree_count;
++ int call_count;
++ int tot_segs;
++ int node_segs;
++ int data_segs;
++ int free_segs;
++ int free_secs;
++ int tot_blks;
++ int data_blks;
++ int node_blks;
++ int curseg[6];
++ int cursec[6];
++ int curzone[6];
++
++ unsigned int segment_count[2];
++ unsigned int block_count[2];
++};
++
++#define GC_STAT_I(gi) ((gi)->stat_info)
++
++#define gc_stat_inc_call_count(gi) ((GC_STAT_I(gi))->call_count++)
++
++#define gc_stat_inc_seg_count(sbi, type) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ GC_STAT_I(gi)->tot_segs++; \
++ if (type == SUM_TYPE_DATA) \
++ GC_STAT_I(gi)->data_segs++; \
++ else \
++ GC_STAT_I(gi)->node_segs++; \
++ } while (0)
++
++#define gc_stat_inc_tot_blk_count(gi, blks) \
++ ((GC_STAT_I(gi)->tot_blks) += (blks))
++
++#define gc_stat_inc_data_blk_count(sbi, blks) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ gc_stat_inc_tot_blk_count(gi, blks); \
++ GC_STAT_I(gi)->data_blks += (blks); \
++ } while (0)
++
++#define gc_stat_inc_node_blk_count(sbi, blks) \
++ do { \
++ struct f2fs_gc_info *gi = sbi->gc_info; \
++ gc_stat_inc_tot_blk_count(gi, blks); \
++ GC_STAT_I(gi)->node_blks += (blks); \
++ } while (0)
++
++#else
++#define gc_stat_inc_call_count(gi)
++#define gc_stat_inc_seg_count(gi, type)
++#define gc_stat_inc_tot_blk_count(gi, blks)
++#define gc_stat_inc_data_blk_count(gi, blks)
++#define gc_stat_inc_node_blk_count(sbi, blks)
++#endif
++
++struct f2fs_gc_kthread {
++ struct task_struct *f2fs_gc_task;
++ wait_queue_head_t gc_wait_queue_head;
++};
++
++struct inode_entry {
++ struct list_head list;
++ struct inode *inode;
++};
++
++/**
++ * inline functions
++ */
++static inline block_t free_user_blocks(struct f2fs_sb_info *sbi)
++{
++ if (free_segments(sbi) < overprovision_segments(sbi))
++ return 0;
++ else
++ return (free_segments(sbi) - overprovision_segments(sbi))
++ << sbi->log_blocks_per_seg;
++}
++
++static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi)
++{
++ return (long)(sbi->user_block_count * LIMIT_INVALID_BLOCK) / 100;
++}
++
++static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t reclaimable_user_blocks = sbi->user_block_count -
++ written_block_count(sbi);
++ return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100;
++}
++
++static inline long increase_sleep_time(long wait)
++{
++ wait += GC_THREAD_MIN_SLEEP_TIME;
++ if (wait > GC_THREAD_MAX_SLEEP_TIME)
++ wait = GC_THREAD_MAX_SLEEP_TIME;
++ return wait;
++}
++
++static inline long decrease_sleep_time(long wait)
++{
++ wait -= GC_THREAD_MIN_SLEEP_TIME;
++ if (wait <= GC_THREAD_MIN_SLEEP_TIME)
++ wait = GC_THREAD_MIN_SLEEP_TIME;
++ return wait;
++}
++
++static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
++{
++ block_t invalid_user_blocks = sbi->user_block_count -
++ written_block_count(sbi);
++ /*
++ * Background GC is triggered with the following condition.
++ * 1. There are a number of invalid blocks.
++ * 2. There is not enough free space.
++ */
++ if (invalid_user_blocks > limit_invalid_user_blocks(sbi) &&
++ free_user_blocks(sbi) < limit_free_user_blocks(sbi))
++ return true;
++ return false;
++}
++
++static inline int is_idle(struct f2fs_sb_info *sbi)
++{
++ struct block_device *bdev = sbi->sb->s_bdev;
++ struct request_queue *q = bdev_get_queue(bdev);
++ struct request_list *rl = &q->root_rl;
++ return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
++}
++
++static bool should_do_checkpoint(struct f2fs_sb_info *sbi)
++{
++ unsigned int pages_per_sec = sbi->segs_per_sec *
++ (1 << sbi->log_blocks_per_seg);
++ int node_secs = ((get_pages(sbi, F2FS_DIRTY_NODES) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ int dent_secs = ((get_pages(sbi, F2FS_DIRTY_DENTS) + pages_per_sec - 1)
++ >> sbi->log_blocks_per_seg) / sbi->segs_per_sec;
++ return free_sections(sbi) <= (node_secs + 2 * dent_secs + 2);
++}
diff --git a/patches/linux-3.7/0114-f2fs-add-recovery-routines-for-roll-forward.patch b/patches/linux-3.7/0114-f2fs-add-recovery-routines-for-roll-forward.patch
new file mode 100644
index 0000000..6edde8e
--- /dev/null
+++ b/patches/linux-3.7/0114-f2fs-add-recovery-routines-for-roll-forward.patch
@@ -0,0 +1,410 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:32:56 +0000
+Subject: [PATCH] f2fs: add recovery routines for roll-forward
+
+This adds roll-forward routines to recover fsynced data.
+
+- F2FS uses basically roll-back model with checkpointing.
+
+- In order to implement fsync(), there are two approaches as follows.
+
+1. A roll-back model with checkpointing at every fsync()
+ : This is a naive method, but suffers from very low performance.
+
+2. A roll-forward model
+ : F2FS adopts this model where all the fsynced data should be recovered, which
+ were written after checkpointing was done. In order to figure out the data,
+ F2FS keeps a "fsync" mark in direct node blocks. In addition, F2FS remains
+ the location of next node block in each direct node block for reconstructing
+ the chain of node blocks during the recovery.
+
+- In order to enhance the performance, F2FS keeps a "dentry" mark also in direct
+ node blocks. If this is set during the recovery, F2FS replays adding a dentry.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/f2fs/recovery.c | 375 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 375 insertions(+)
+ create mode 100644 fs/f2fs/recovery.c
+
+diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
+new file mode 100644
+index 0000000..59b6331
+--- /dev/null
++++ b/fs/f2fs/recovery.c
+@@ -0,0 +1,375 @@
++/**
++ * fs/f2fs/recovery.c
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/fs.h>
++#include <linux/f2fs_fs.h>
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++
++static struct kmem_cache *fsync_entry_slab;
++
++bool space_for_roll_forward(struct f2fs_sb_info *sbi)
++{
++ if (sbi->last_valid_block_count + sbi->alloc_valid_block_count
++ > sbi->user_block_count)
++ return false;
++ return true;
++}
++
++static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
++ nid_t ino)
++{
++ struct list_head *this;
++ struct fsync_inode_entry *entry;
++
++ list_for_each(this, head) {
++ entry = list_entry(this, struct fsync_inode_entry, list);
++ if (entry->inode->i_ino == ino)
++ return entry;
++ }
++ return NULL;
++}
++
++static int recover_dentry(struct page *ipage, struct inode *inode)
++{
++ struct f2fs_node *raw_node = (struct f2fs_node *)kmap(ipage);
++ struct f2fs_inode *raw_inode = &(raw_node->i);
++ struct dentry dent, parent;
++ struct f2fs_dir_entry *de;
++ struct page *page;
++ struct inode *dir;
++ int err = 0;
++
++ if (!is_dent_dnode(ipage))
++ goto out;
++
++ dir = f2fs_iget(inode->i_sb, le32_to_cpu(raw_inode->i_pino));
++ if (IS_ERR(dir)) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ parent.d_inode = dir;
++ dent.d_parent = &parent;
++ dent.d_name.len = le32_to_cpu(raw_inode->i_namelen);
++ dent.d_name.name = raw_inode->i_name;
++
++ de = f2fs_find_entry(dir, &dent.d_name, &page);
++ if (de) {
++ kunmap(page);
++ f2fs_put_page(page, 0);
++ } else {
++ f2fs_add_link(&dent, inode);
++ }
++ iput(dir);
++out:
++ kunmap(ipage);
++ return err;
++}
++
++static int recover_inode(struct inode *inode, struct page *node_page)
++{
++ void *kaddr = page_address(node_page);
++ struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
++ struct f2fs_inode *raw_inode = &(raw_node->i);
++
++ inode->i_mode = le32_to_cpu(raw_inode->i_mode);
++ i_size_write(inode, le64_to_cpu(raw_inode->i_size));
++ inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
++ inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
++ inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
++ inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
++ inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
++ inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
++
++ return recover_dentry(node_page, inode);
++}
++
++static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
++{
++ unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
++ struct curseg_info *curseg;
++ struct page *page;
++ block_t blkaddr;
++ int err = 0;
++
++ /* get node pages in the current segment */
++ curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
++ blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;
++
++ /* read node page */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return PTR_ERR(page);
++ lock_page(page);
++
++ while (1) {
++ struct fsync_inode_entry *entry;
++
++ if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
++ goto out;
++
++ if (cp_ver != cpver_of_node(page))
++ goto out;
++
++ if (!is_fsync_dnode(page))
++ goto next;
++
++ entry = get_fsync_inode(head, ino_of_node(page));
++ if (entry) {
++ entry->blkaddr = blkaddr;
++ if (IS_INODE(page) && is_dent_dnode(page))
++ set_inode_flag(F2FS_I(entry->inode),
++ FI_INC_LINK);
++ } else {
++ if (IS_INODE(page) && is_dent_dnode(page)) {
++ if (recover_inode_page(sbi, page)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ }
++
++ /* add this fsync inode to the list */
++ entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
++ if (!entry) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&entry->list);
++ list_add_tail(&entry->list, head);
++
++ entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
++ if (IS_ERR(entry->inode)) {
++ err = PTR_ERR(entry->inode);
++ goto out;
++ }
++ entry->blkaddr = blkaddr;
++ }
++ if (IS_INODE(page)) {
++ err = recover_inode(entry->inode, page);
++ if (err)
++ goto out;
++ }
++next:
++ /* check next segment */
++ blkaddr = next_blkaddr_of_node(page);
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++ return err;
++}
++
++static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
++ struct list_head *head)
++{
++ struct list_head *this;
++ struct fsync_inode_entry *entry;
++ list_for_each(this, head) {
++ entry = list_entry(this, struct fsync_inode_entry, list);
++ iput(entry->inode);
++ list_del(&entry->list);
++ kmem_cache_free(fsync_entry_slab, entry);
++ }
++}
++
++static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
++ block_t blkaddr)
++{
++ struct seg_entry *sentry;
++ unsigned int segno = GET_SEGNO(sbi, blkaddr);
++ unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
++ (sbi->blocks_per_seg - 1);
++ struct f2fs_summary sum;
++ nid_t ino;
++ void *kaddr;
++ struct inode *inode;
++ struct page *node_page;
++ block_t bidx;
++ int i;
++
++ sentry = get_seg_entry(sbi, segno);
++ if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
++ return;
++
++ /* Get the previous summary */
++ for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ if (curseg->segno == segno) {
++ sum = curseg->sum_blk->entries[blkoff];
++ break;
++ }
++ }
++ if (i > CURSEG_COLD_DATA) {
++ struct page *sum_page = get_sum_page(sbi, segno);
++ struct f2fs_summary_block *sum_node;
++ kaddr = page_address(sum_page);
++ sum_node = (struct f2fs_summary_block *)kaddr;
++ sum = sum_node->entries[blkoff];
++ f2fs_put_page(sum_page, 1);
++ }
++
++ /* Get the node page */
++ node_page = get_node_page(sbi, le32_to_cpu(sum.nid));
++ bidx = start_bidx_of_node(ofs_of_node(node_page)) +
++ le16_to_cpu(sum.ofs_in_node);
++ ino = ino_of_node(node_page);
++ f2fs_put_page(node_page, 1);
++
++ /* Deallocate previous index in the node page */
++ inode = f2fs_iget_nowait(sbi->sb, ino);
++ truncate_hole(inode, bidx, bidx + 1);
++ iput(inode);
++}
++
++static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
++ struct page *page, block_t blkaddr)
++{
++ unsigned int start, end;
++ struct dnode_of_data dn;
++ struct f2fs_summary sum;
++ struct node_info ni;
++
++ start = start_bidx_of_node(ofs_of_node(page));
++ if (IS_INODE(page))
++ end = start + ADDRS_PER_INODE;
++ else
++ end = start + ADDRS_PER_BLOCK;
++
++ set_new_dnode(&dn, inode, NULL, NULL, 0);
++ if (get_dnode_of_data(&dn, start, 0))
++ return;
++
++ wait_on_page_writeback(dn.node_page);
++
++ get_node_info(sbi, dn.nid, &ni);
++ BUG_ON(ni.ino != ino_of_node(page));
++ BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page));
++
++ for (; start < end; start++) {
++ block_t src, dest;
++
++ src = datablock_addr(dn.node_page, dn.ofs_in_node);
++ dest = datablock_addr(page, dn.ofs_in_node);
++
++ if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
++ if (src == NULL_ADDR) {
++ int err = reserve_new_block(&dn);
++ /* We should not get -ENOSPC */
++ BUG_ON(err);
++ }
++
++ /* Check the previous node page having this index */
++ check_index_in_prev_nodes(sbi, dest);
++
++ set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
++
++ /* write dummy data page */
++ recover_data_page(sbi, NULL, &sum, src, dest);
++ update_extent_cache(dest, &dn);
++ }
++ dn.ofs_in_node++;
++ }
++
++ /* write node page in place */
++ set_summary(&sum, dn.nid, 0, 0);
++ if (IS_INODE(dn.node_page))
++ sync_inode_page(&dn);
++
++ copy_node_footer(dn.node_page, page);
++ fill_node_footer(dn.node_page, dn.nid, ni.ino,
++ ofs_of_node(page), false);
++ set_page_dirty(dn.node_page);
++
++ recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
++ f2fs_put_dnode(&dn);
++}
++
++static void recover_data(struct f2fs_sb_info *sbi,
++ struct list_head *head, int type)
++{
++ unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
++ struct curseg_info *curseg;
++ struct page *page;
++ block_t blkaddr;
++
++ /* get node pages in the current segment */
++ curseg = CURSEG_I(sbi, type);
++ blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
++
++ /* read node page */
++ page = alloc_page(GFP_NOFS | __GFP_ZERO);
++ if (IS_ERR(page))
++ return;
++ lock_page(page);
++
++ while (1) {
++ struct fsync_inode_entry *entry;
++
++ if (f2fs_readpage(sbi, page, blkaddr, READ_SYNC))
++ goto out;
++
++ if (cp_ver != cpver_of_node(page))
++ goto out;
++
++ entry = get_fsync_inode(head, ino_of_node(page));
++ if (!entry)
++ goto next;
++
++ do_recover_data(sbi, entry->inode, page, blkaddr);
++
++ if (entry->blkaddr == blkaddr) {
++ iput(entry->inode);
++ list_del(&entry->list);
++ kmem_cache_free(fsync_entry_slab, entry);
++ }
++next:
++ /* check next segment */
++ blkaddr = next_blkaddr_of_node(page);
++ ClearPageUptodate(page);
++ }
++out:
++ unlock_page(page);
++ __free_pages(page, 0);
++
++ allocate_new_segments(sbi);
++}
++
++void recover_fsync_data(struct f2fs_sb_info *sbi)
++{
++ struct list_head inode_list;
++
++ fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
++ sizeof(struct fsync_inode_entry), NULL);
++ if (unlikely(!fsync_entry_slab))
++ return;
++
++ INIT_LIST_HEAD(&inode_list);
++
++ /* step #1: find fsynced inode numbers */
++ if (find_fsync_dnodes(sbi, &inode_list))
++ goto out;
++
++ if (list_empty(&inode_list))
++ goto out;
++
++ /* step #2: recover data */
++ sbi->por_doing = 1;
++ recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
++ sbi->por_doing = 0;
++ BUG_ON(!list_empty(&inode_list));
++out:
++ destroy_fsync_dnodes(sbi, &inode_list);
++ kmem_cache_destroy(fsync_entry_slab);
++ write_checkpoint(sbi, false, false);
++}
diff --git a/patches/linux-3.7/0115-f2fs-update-Kconfig-and-Makefile.patch b/patches/linux-3.7/0115-f2fs-update-Kconfig-and-Makefile.patch
new file mode 100644
index 0000000..24c8d01
--- /dev/null
+++ b/patches/linux-3.7/0115-f2fs-update-Kconfig-and-Makefile.patch
@@ -0,0 +1,114 @@
+From: ??? <jaegeuk.kim@samsung.com>
+Date: Tue, 23 Oct 2012 02:33:28 +0000
+Subject: [PATCH] f2fs: update Kconfig and Makefile
+
+This adds Makefile and Kconfig for f2fs, and updates Makefile and Kconfig files
+in the fs directory.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
+---
+ fs/Kconfig | 1 +
+ fs/Makefile | 1 +
+ fs/f2fs/Kconfig | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/Makefile | 6 ++++++
+ 4 files changed, 63 insertions(+)
+ create mode 100644 fs/f2fs/Kconfig
+ create mode 100644 fs/f2fs/Makefile
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index f95ae3a..e352b37 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -220,6 +220,7 @@ source "fs/pstore/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
+ source "fs/exofs/Kconfig"
++source "fs/f2fs/Kconfig"
+
+ endif # MISC_FILESYSTEMS
+
+diff --git a/fs/Makefile b/fs/Makefile
+index 1d7af79..9d53192 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -123,6 +123,7 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/
+ obj-$(CONFIG_OCFS2_FS) += ocfs2/
+ obj-$(CONFIG_BTRFS_FS) += btrfs/
+ obj-$(CONFIG_GFS2_FS) += gfs2/
++obj-$(CONFIG_F2FS_FS) += f2fs/
+ obj-y += exofs/ # Multiple modules
+ obj-$(CONFIG_CEPH_FS) += ceph/
+ obj-$(CONFIG_PSTORE) += pstore/
+diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
+new file mode 100644
+index 0000000..8821c6a
+--- /dev/null
++++ b/fs/f2fs/Kconfig
+@@ -0,0 +1,55 @@
++config F2FS_FS
++ tristate "F2FS filesystem support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ F2FS is based on Log-structured File System (LFS), which supports
++ versatile "flash-friendly" features. The design has been focused on
++ addressing the fundamental issues in LFS, which are snowball effect
++ of wandering tree and high cleaning overhead.
++
++ Since flash-based storages show different characteristics according to
++ the internal geometry or flash memory management schemes aka FTL, F2FS
++ and tools support various parameters not only for configuring on-disk
++ layout, but also for selecting allocation and cleaning algorithms.
++
++ If unsure, say N.
++
++config F2FS_STAT_FS
++ bool "F2FS Status Information"
++ depends on F2FS_FS
++ default y
++ help
++ /proc/fs/f2fs/ contains information about partitions mounted as f2fs.
++ For each partition, a corresponding directory, named as its device
++ name, is provided with the following proc entries.
++
++ f2fs_stat major file system information managed by f2fs currently
++ f2fs_sit_stat average SIT information about whole segments
++ f2fs_mem_stat current memory footprint consumed by f2fs
++
++ e.g., in /proc/fs/f2fs/sdb1/
++
++config F2FS_FS_XATTR
++ bool "F2FS extended attributes"
++ depends on F2FS_FS
++ default y
++ help
++ Extended attributes are name:value pairs associated with inodes by
++ the kernel or by users (see the attr(5) manual page, or visit
++ <http://acl.bestbits.at/> for details).
++
++ If unsure, say N.
++
++config F2FS_FS_POSIX_ACL
++ bool "F2FS Access Control Lists"
++ depends on F2FS_FS_XATTR
++ select FS_POSIX_ACL
++ default y
++ help
++ Posix Access Control Lists (ACLs) support permissions for users and
++ gourps beyond the owner/group/world scheme.
++
++ To learn more about Access Control Lists, visit the POSIX ACLs for
++ Linux website <http://acl.bestbits.at/>.
++
++ If you don't know what Access Control Lists are, say N
+diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
+new file mode 100644
+index 0000000..72fcf9a
+--- /dev/null
++++ b/fs/f2fs/Makefile
+@@ -0,0 +1,6 @@
++obj-$(CONFIG_F2FS_FS) += f2fs.o
++
++f2fs-y := dir.o file.o inode.o namei.o hash.o super.o
++f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
++f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
++f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
diff --git a/patches/linux-3.7/0116-f2fs-gc.h-make-should_do_checkpoint-inline.patch b/patches/linux-3.7/0116-f2fs-gc.h-make-should_do_checkpoint-inline.patch
new file mode 100644
index 0000000..bc3fa43
--- /dev/null
+++ b/patches/linux-3.7/0116-f2fs-gc.h-make-should_do_checkpoint-inline.patch
@@ -0,0 +1,25 @@
+From: "gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 18:21:46 +0000
+Subject: [PATCH] f2fs: gc.h: make should_do_checkpoint() inline
+
+This should be an inline function, not a "real" function. Now other
+files can properly include gc.h.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
+index 29b345d..b70366f 100644
+--- a/fs/f2fs/gc.h
++++ b/fs/f2fs/gc.h
+@@ -191,7 +191,7 @@ static inline int is_idle(struct f2fs_sb_info *sbi)
+ return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
+ }
+
+-static bool should_do_checkpoint(struct f2fs_sb_info *sbi)
++static inline bool should_do_checkpoint(struct f2fs_sb_info *sbi)
+ {
+ unsigned int pages_per_sec = sbi->segs_per_sec *
+ (1 << sbi->log_blocks_per_seg);
diff --git a/patches/linux-3.7/0117-f2fs-move-statistics-code-into-one-file.patch b/patches/linux-3.7/0117-f2fs-move-statistics-code-into-one-file.patch
new file mode 100644
index 0000000..cee899f
--- /dev/null
+++ b/patches/linux-3.7/0117-f2fs-move-statistics-code-into-one-file.patch
@@ -0,0 +1,966 @@
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 18:22:41 +0000
+Subject: [PATCH] f2fs: move statistics code into one file
+
+This moves all of the procfs statistics code into one file, debug.c and
+removes the #ifdefs from the core f2fs code when calling statistic
+functions.
+
+This will make it more obvious how to move from procfs to debugfs, no
+functionality was changed here at all.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/Makefile | 1 +
+ fs/f2fs/debug.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h | 25 +++-
+ fs/f2fs/gc.c | 373 +-----------------------------------------------
+ fs/f2fs/super.c | 21 +--
+ 5 files changed, 442 insertions(+), 392 deletions(-)
+ create mode 100644 fs/f2fs/debug.c
+
+diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile
+index 72fcf9a..27a0820 100644
+--- a/fs/f2fs/Makefile
++++ b/fs/f2fs/Makefile
+@@ -2,5 +2,6 @@ obj-$(CONFIG_F2FS_FS) += f2fs.o
+
+ f2fs-y := dir.o file.o inode.o namei.o hash.o super.o
+ f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
++f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
+ f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+ f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+new file mode 100644
+index 0000000..0145b02
+--- /dev/null
++++ b/fs/f2fs/debug.c
+@@ -0,0 +1,414 @@
++/**
++ * f2fs debugging statistics
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ * Copyright (c) 2012 Linux Foundation
++ * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/fs.h>
++#include <linux/backing-dev.h>
++#include <linux/proc_fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "gc.h"
++
++static LIST_HEAD(f2fs_stat_list);
++static struct proc_dir_entry *f2fs_proc_root;
++
++
++void f2fs_update_stat(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ int i;
++
++ /* valid check of the segment numbers */
++ si->hit_ext = sbi->read_hit_ext;
++ si->total_ext = sbi->total_hit_ext;
++ si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
++ si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
++ si->ndirty_dirs = sbi->n_dirty_dirs;
++ si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
++ si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++ si->rsvd_segs = reserved_segments(sbi);
++ si->overp_segs = overprovision_segments(sbi);
++ si->valid_count = valid_user_blocks(sbi);
++ si->valid_node_count = valid_node_count(sbi);
++ si->valid_inode_count = valid_inode_count(sbi);
++ si->utilization = utilization(sbi);
++
++ si->free_segs = free_segments(sbi);
++ si->free_secs = free_sections(sbi);
++ si->prefree_count = prefree_segments(sbi);
++ si->dirty_count = dirty_segments(sbi);
++ si->node_pages = sbi->node_inode->i_mapping->nrpages;
++ si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
++ si->nats = NM_I(sbi)->nat_cnt;
++ si->sits = SIT_I(sbi)->dirty_sentries;
++ si->fnids = NM_I(sbi)->fcnt;
++ si->bg_gc = sbi->bg_gc;
++ si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_valid = (int)(written_block_count(sbi) >>
++ sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_invalid = 50 - si->util_free - si->util_valid;
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ si->curseg[i] = curseg->segno;
++ si->cursec[i] = curseg->segno / sbi->segs_per_sec;
++ si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
++ }
++
++ for (i = 0; i < 2; i++) {
++ si->segment_count[i] = sbi->segment_count[i];
++ si->block_count[i] = sbi->block_count[i];
++ }
++}
++
++/**
++ * This function calculates BDF of every segments
++ */
++static void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno, vblocks;
++ int ndirty = 0;
++
++ bimodal = 0;
++ total_vblocks = 0;
++ blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
++ hblks_per_sec = blks_per_sec / 2;
++ mutex_lock(&sit_i->sentry_lock);
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ dist = abs(vblocks - hblks_per_sec);
++ bimodal += dist * dist;
++
++ if (vblocks > 0 && vblocks < blks_per_sec) {
++ total_vblocks += vblocks;
++ ndirty++;
++ }
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
++ si->bimodal = bimodal / dist;
++ if (si->dirty_count)
++ si->avg_vblocks = total_vblocks / ndirty;
++ else
++ si->avg_vblocks = 0;
++}
++
++static int f2fs_read_gc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++ int i = 0;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ int j;
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_stat(si->sbi);
++
++ buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
++ buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ buf += sprintf(buf, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count,
++ si->free_segs,
++ si->free_secs);
++ buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
++ buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
++ buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
++ buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
++ buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
++ buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ buf += sprintf(buf, "\nBalancing F2FS Async:\n");
++ buf += sprintf(buf, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ buf += sprintf(buf, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ buf += sprintf(buf, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ buf += sprintf(buf, "\nDistribution of User Blocks:");
++ buf += sprintf(buf, " [ valid | invalid | free ]\n");
++ buf += sprintf(buf, " [");
++ for (j = 0; j < si->util_valid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_invalid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_free; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "]\n\n");
++ buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_sit(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_gc_metric(si->sbi);
++
++ buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_mem(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
++ unsigned npages;
++ unsigned base_mem = 0, cache_mem = 0;
++
++ si = gc_i->stat_info;
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
++ base_mem += 2 * sizeof(struct f2fs_inode_info);
++ base_mem += sizeof(*sbi->ckpt);
++
++ /* build sm */
++ base_mem += sizeof(struct f2fs_sm_info);
++
++ /* build sit */
++ base_mem += sizeof(struct sit_info);
++ base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
++ if (sbi->segs_per_sec > 1)
++ base_mem += sbi->total_sections *
++ sizeof(struct sec_entry);
++ base_mem += __bitmap_size(sbi, SIT_BITMAP);
++
++ /* build free segmap */
++ base_mem += sizeof(struct free_segmap_info);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += f2fs_bitmap_size(sbi->total_sections);
++
++ /* build curseg */
++ base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
++ base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
++
++ /* build dirty segmap */
++ base_mem += sizeof(struct dirty_seglist_info);
++ base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ /* buld nm */
++ base_mem += sizeof(struct f2fs_nm_info);
++ base_mem += __bitmap_size(sbi, NAT_BITMAP);
++
++ /* build gc */
++ base_mem += sizeof(struct f2fs_gc_info);
++ base_mem += sizeof(struct f2fs_gc_kthread);
++
++ /* free nids */
++ cache_mem += NM_I(sbi)->fcnt;
++ cache_mem += NM_I(sbi)->nat_cnt;
++ npages = sbi->node_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ npages = sbi->meta_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
++ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
++
++ buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10,
++ cache_mem >> 10);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int init_stats(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_stat_info *si;
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++
++ gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
++ GFP_KERNEL);
++ if (!gc_i->stat_info)
++ return -ENOMEM;
++ si = gc_i->stat_info;
++ mutex_init(&si->stat_list);
++ list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
++
++ si->all_area_segs = le32_to_cpu(raw_super->segment_count);
++ si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
++ si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
++ si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
++ si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
++ si->main_area_sections = le32_to_cpu(raw_super->section_count);
++ si->main_area_zones = si->main_area_sections /
++ le32_to_cpu(raw_super->secs_per_zone);
++ si->sbi = sbi;
++ return 0;
++}
++
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i)
++{
++ struct f2fs_stat_info *si = gc_i->stat_info;
++
++ list_del(&gc_i->stat_list);
++ mutex_lock(&si->stat_list);
++ si->sbi = NULL;
++ mutex_unlock(&si->stat_list);
++ kfree(gc_i->stat_info);
++}
++
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ struct proc_dir_entry *entry;
++ int retval;
++
++ if (!f2fs_proc_root)
++ f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
++
++ sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
++
++ retval = init_stats(sbi);
++ if (retval)
++ return retval;
++
++ entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
++ if (!entry)
++ return -ENOMEM;
++ entry->read_proc = f2fs_read_gc;
++ entry->write_proc = NULL;
++
++ entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_sit;
++ entry->write_proc = NULL;
++ entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_mem;
++ entry->write_proc = NULL;
++ return 0;
++}
++
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ if (sbi->s_proc) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
++ remove_proc_entry(sb->s_id, f2fs_proc_root);
++ }
++}
++
++void f2fs_remove_stats(void)
++{
++ remove_proc_entry("fs/f2fs", NULL);
++}
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index bbe2f02..7f508b2 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -953,12 +953,6 @@ int start_gc_thread(struct f2fs_sb_info *);
+ void stop_gc_thread(struct f2fs_sb_info *);
+ block_t start_bidx_of_node(unsigned int);
+ int f2fs_gc(struct f2fs_sb_info *, int);
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *);
+-void f2fs_update_gc_metric(struct f2fs_sb_info *);
+-int f2fs_stat_init(struct f2fs_sb_info *);
+-void f2fs_stat_exit(struct f2fs_sb_info *);
+-#endif
+ int build_gc_manager(struct f2fs_sb_info *);
+ void destroy_gc_manager(struct f2fs_sb_info *);
+ int create_gc_caches(void);
+@@ -970,6 +964,25 @@ void destroy_gc_caches(void);
+ void recover_fsync_data(struct f2fs_sb_info *);
+ bool space_for_roll_forward(struct f2fs_sb_info *);
+
++/**
++ * debug.c
++ */
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *);
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i);
++void f2fs_remove_stats(void);
++#else
++static inline void f2fs_update_stat(struct f2fs_sb_info *sbi) { }
++static inline int f2fs_stat_init(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { return 0; }
++static inline void f2fs_stat_exit(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { }
++static inline void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i) { }
++static inline void f2fs_remove_stats(void) { }
++#endif
++
+ extern const struct file_operations f2fs_dir_operations;
+ extern const struct file_operations f2fs_file_operations;
+ extern const struct inode_operations f2fs_file_inode_operations;
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 753b05e..cfdbd2c 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -24,7 +24,6 @@
+ #include "segment.h"
+ #include "gc.h"
+
+-static LIST_HEAD(f2fs_stat_list);
+ static struct kmem_cache *winode_slab;
+
+ static int gc_thread_func(void *data)
+@@ -727,350 +726,10 @@ stop:
+ return gc_status;
+ }
+
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- int i;
+-
+- /* valid check of the segment numbers */
+- si->hit_ext = sbi->read_hit_ext;
+- si->total_ext = sbi->total_hit_ext;
+- si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
+- si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
+- si->ndirty_dirs = sbi->n_dirty_dirs;
+- si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
+- si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
+- si->rsvd_segs = reserved_segments(sbi);
+- si->overp_segs = overprovision_segments(sbi);
+- si->valid_count = valid_user_blocks(sbi);
+- si->valid_node_count = valid_node_count(sbi);
+- si->valid_inode_count = valid_inode_count(sbi);
+- si->utilization = utilization(sbi);
+-
+- si->free_segs = free_segments(sbi);
+- si->free_secs = free_sections(sbi);
+- si->prefree_count = prefree_segments(sbi);
+- si->dirty_count = dirty_segments(sbi);
+- si->node_pages = sbi->node_inode->i_mapping->nrpages;
+- si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
+- si->nats = NM_I(sbi)->nat_cnt;
+- si->sits = SIT_I(sbi)->dirty_sentries;
+- si->fnids = NM_I(sbi)->fcnt;
+- si->bg_gc = sbi->bg_gc;
+- si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_valid = (int)(written_block_count(sbi) >>
+- sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_invalid = 50 - si->util_free - si->util_valid;
+- for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
+- struct curseg_info *curseg = CURSEG_I(sbi, i);
+- si->curseg[i] = curseg->segno;
+- si->cursec[i] = curseg->segno / sbi->segs_per_sec;
+- si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
+- }
+-
+- for (i = 0; i < 2; i++) {
+- si->segment_count[i] = sbi->segment_count[i];
+- si->block_count[i] = sbi->block_count[i];
+- }
+-}
+-
+-/**
+- * This function calculates BDF of every segments
+- */
+-void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
+- struct sit_info *sit_i = SIT_I(sbi);
+- unsigned int segno, vblocks;
+- int ndirty = 0;
+-
+- bimodal = 0;
+- total_vblocks = 0;
+- blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
+- hblks_per_sec = blks_per_sec / 2;
+- mutex_lock(&sit_i->sentry_lock);
+- for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+- vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+- dist = abs(vblocks - hblks_per_sec);
+- bimodal += dist * dist;
+-
+- if (vblocks > 0 && vblocks < blks_per_sec) {
+- total_vblocks += vblocks;
+- ndirty++;
+- }
+- }
+- mutex_unlock(&sit_i->sentry_lock);
+- dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+- si->bimodal = bimodal / dist;
+- if (si->dirty_count)
+- si->avg_vblocks = total_vblocks / ndirty;
+- else
+- si->avg_vblocks = 0;
+-}
+-
+-static int f2fs_read_gc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+- int i = 0;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- int j;
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_stat(si->sbi);
+-
+- buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
+- buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+- si->nat_area_segs, si->sit_area_segs);
+- buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
+- si->ssa_area_segs, si->main_area_segs);
+- buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
+- si->overp_segs, si->rsvd_segs);
+- buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
+- si->utilization, si->valid_count);
+- buf += sprintf(buf, " - Node: %u (Inode: %u, ",
+- si->valid_node_count, si->valid_inode_count);
+- buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
+- si->valid_node_count - si->valid_inode_count,
+- si->valid_count - si->valid_node_count);
+- buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
+- si->main_area_segs, si->main_area_sections,
+- si->main_area_zones);
+- buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_DATA],
+- si->cursec[CURSEG_COLD_DATA],
+- si->curzone[CURSEG_COLD_DATA]);
+- buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_DATA],
+- si->cursec[CURSEG_WARM_DATA],
+- si->curzone[CURSEG_WARM_DATA]);
+- buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_DATA],
+- si->cursec[CURSEG_HOT_DATA],
+- si->curzone[CURSEG_HOT_DATA]);
+- buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_NODE],
+- si->cursec[CURSEG_HOT_NODE],
+- si->curzone[CURSEG_HOT_NODE]);
+- buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_NODE],
+- si->cursec[CURSEG_WARM_NODE],
+- si->curzone[CURSEG_WARM_NODE]);
+- buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_NODE],
+- si->cursec[CURSEG_COLD_NODE],
+- si->curzone[CURSEG_COLD_NODE]);
+- buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
+- si->main_area_segs - si->dirty_count -
+- si->prefree_count - si->free_segs,
+- si->dirty_count);
+- buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
+- si->prefree_count,
+- si->free_segs,
+- si->free_secs);
+- buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
+- si->call_count, si->bg_gc);
+- buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
+- buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
+- buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
+- buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
+- buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
+- buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
+- si->hit_ext, si->total_ext);
+- buf += sprintf(buf, "\nBalancing F2FS Async:\n");
+- buf += sprintf(buf, " - nodes %4d in %4d\n",
+- si->ndirty_node, si->node_pages);
+- buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
+- si->ndirty_dent, si->ndirty_dirs);
+- buf += sprintf(buf, " - meta %4d in %4d\n",
+- si->ndirty_meta, si->meta_pages);
+- buf += sprintf(buf, " - NATs %5d > %lu\n",
+- si->nats, NM_WOUT_THRESHOLD);
+- buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
+- si->sits, si->fnids);
+- buf += sprintf(buf, "\nDistribution of User Blocks:");
+- buf += sprintf(buf, " [ valid | invalid | free ]\n");
+- buf += sprintf(buf, " [");
+- for (j = 0; j < si->util_valid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_invalid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_free; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "]\n\n");
+- buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
+- si->block_count[SSR], si->segment_count[SSR]);
+- buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
+- si->block_count[LFS], si->segment_count[LFS]);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_sit(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_gc_metric(si->sbi);
+-
+- buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
+- si->bimodal, si->avg_vblocks);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_mem(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
+- unsigned npages;
+- unsigned base_mem = 0, cache_mem = 0;
+-
+- si = gc_i->stat_info;
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
+- base_mem += 2 * sizeof(struct f2fs_inode_info);
+- base_mem += sizeof(*sbi->ckpt);
+-
+- /* build sm */
+- base_mem += sizeof(struct f2fs_sm_info);
+-
+- /* build sit */
+- base_mem += sizeof(struct sit_info);
+- base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
+- if (sbi->segs_per_sec > 1)
+- base_mem += sbi->total_sections *
+- sizeof(struct sec_entry);
+- base_mem += __bitmap_size(sbi, SIT_BITMAP);
+-
+- /* build free segmap */
+- base_mem += sizeof(struct free_segmap_info);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += f2fs_bitmap_size(sbi->total_sections);
+-
+- /* build curseg */
+- base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
+- base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
+-
+- /* build dirty segmap */
+- base_mem += sizeof(struct dirty_seglist_info);
+- base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+-
+- /* buld nm */
+- base_mem += sizeof(struct f2fs_nm_info);
+- base_mem += __bitmap_size(sbi, NAT_BITMAP);
+-
+- /* build gc */
+- base_mem += sizeof(struct f2fs_gc_info);
+- base_mem += sizeof(struct f2fs_gc_kthread);
+-
+- /* free nids */
+- cache_mem += NM_I(sbi)->fcnt;
+- cache_mem += NM_I(sbi)->nat_cnt;
+- npages = sbi->node_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- npages = sbi->meta_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+- cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+-
+- buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
+- (base_mem + cache_mem) >> 10,
+- base_mem >> 10,
+- cache_mem >> 10);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-int f2fs_stat_init(struct f2fs_sb_info *sbi)
+-{
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
+- if (!entry)
+- return -ENOMEM;
+- entry->read_proc = f2fs_read_gc;
+- entry->write_proc = NULL;
+-
+- entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_sit;
+- entry->write_proc = NULL;
+- entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_mem;
+- entry->write_proc = NULL;
+- return 0;
+-}
+-
+-void f2fs_stat_exit(struct f2fs_sb_info *sbi)
+-{
+- if (sbi->s_proc) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
+- }
+-}
+-#endif
+-
+ int build_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i;
+ struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+- struct f2fs_stat_info *si;
+-#endif
+
+ gc_i = kzalloc(sizeof(struct f2fs_gc_info), GFP_KERNEL);
+ if (!gc_i)
+@@ -1082,44 +741,18 @@ int build_gc_manager(struct f2fs_sb_info *sbi)
+
+ DIRTY_I(sbi)->v_ops = &default_v_ops;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
+- GFP_KERNEL);
+- if (!gc_i->stat_info)
+- return -ENOMEM;
+- si = gc_i->stat_info;
+- mutex_init(&si->stat_list);
+- list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
+-
+- si->all_area_segs = le32_to_cpu(raw_super->segment_count);
+- si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
+- si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
+- si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
+- si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
+- si->main_area_sections = le32_to_cpu(raw_super->section_count);
+- si->main_area_zones = si->main_area_sections /
+- le32_to_cpu(raw_super->secs_per_zone);
+- si->sbi = sbi;
+-#endif
+ return 0;
+ }
+
+ void destroy_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i = sbi->gc_info;
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_stat_info *si = gc_i->stat_info;
+-#endif
++
+ if (!gc_i)
+ return;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- list_del(&gc_i->stat_list);
+- mutex_lock(&si->stat_list);
+- si->sbi = NULL;
+- mutex_unlock(&si->stat_list);
+- kfree(gc_i->stat_info);
+-#endif
++ f2fs_destroy_gci_stats(gc_i);
++
+ sbi->gc_info = NULL;
+ kfree(gc_i);
+ }
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index 8e608a0..65feb4b 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -26,7 +26,6 @@
+ #include "xattr.h"
+
+ static struct kmem_cache *f2fs_inode_cachep;
+-static struct proc_dir_entry *f2fs_proc_root;
+
+ enum {
+ Opt_gc_background_off,
+@@ -97,12 +96,7 @@ static void f2fs_put_super(struct super_block *sb)
+ {
+ struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (sbi->s_proc) {
+- f2fs_stat_exit(sbi);
+- remove_proc_entry(sb->s_id, f2fs_proc_root);
+- }
+-#endif
++ f2fs_stat_exit(sb, sbi);
+ stop_gc_thread(sbi);
+
+ write_checkpoint(sbi, false, true);
+@@ -486,13 +480,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
+ if (start_gc_thread(sbi))
+ goto fail;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (f2fs_proc_root) {
+- sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+- if (f2fs_stat_init(sbi))
+- goto fail;
+- }
+-#endif
++ if (f2fs_stat_init(sb, sbi))
++ goto fail;
++
+ return 0;
+ fail:
+ stop_gc_thread(sbi);
+@@ -566,7 +556,6 @@ static int __init init_f2fs_fs(void)
+ if (register_filesystem(&f2fs_fs_type))
+ return -EBUSY;
+
+- f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
+ return 0;
+ fail:
+ return -ENOMEM;
+@@ -574,7 +563,7 @@ fail:
+
+ static void __exit exit_f2fs_fs(void)
+ {
+- remove_proc_entry("fs/f2fs", NULL);
++ f2fs_remove_stats();
+ unregister_filesystem(&f2fs_fs_type);
+ destroy_checkpoint_caches();
+ destroy_gc_caches();
diff --git a/patches/linux-3.7/0118-f2fs-move-proc-files-to-debugfs.patch b/patches/linux-3.7/0118-f2fs-move-proc-files-to-debugfs.patch
new file mode 100644
index 0000000..1ae0d1a
--- /dev/null
+++ b/patches/linux-3.7/0118-f2fs-move-proc-files-to-debugfs.patch
@@ -0,0 +1,448 @@
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 23 Oct 2012 19:20:28 +0000
+Subject: [PATCH] f2fs: move proc files to debugfs
+
+This moves all of the f2fs debugging files into debugfs. The files are
+located in /sys/kernel/debug/f2fs/
+
+Note, I think we are generating all of the same information in each of
+the files for every unique f2fs filesystem in the machine. This copies
+the functionality that was present in the proc files, but this should be
+fixed up in the future.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/Kconfig | 8 +-
+ fs/f2fs/debug.c | 294 ++++++++++++++++++++++++++++++-------------------------
+ fs/f2fs/f2fs.h | 2 +-
+ 3 files changed, 165 insertions(+), 139 deletions(-)
+
+diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
+index 8821c6a..dd181c6 100644
+--- a/fs/f2fs/Kconfig
++++ b/fs/f2fs/Kconfig
+@@ -16,18 +16,18 @@ config F2FS_FS
+
+ config F2FS_STAT_FS
+ bool "F2FS Status Information"
+- depends on F2FS_FS
++ depends on F2FS_FS && DEBUG_FS
+ default y
+ help
+- /proc/fs/f2fs/ contains information about partitions mounted as f2fs.
++ /sys/kernel/debug/f2fs/ contains information about partitions mounted as f2fs.
+ For each partition, a corresponding directory, named as its device
+- name, is provided with the following proc entries.
++ name, is provided with the following files:
+
+ f2fs_stat major file system information managed by f2fs currently
+ f2fs_sit_stat average SIT information about whole segments
+ f2fs_mem_stat current memory footprint consumed by f2fs
+
+- e.g., in /proc/fs/f2fs/sdb1/
++ e.g., in /sys/kernel/debug/f2fs/sdb1/
+
+ config F2FS_FS_XATTR
+ bool "F2FS extended attributes"
+diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
+index 0145b02..ec5beba 100644
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -16,6 +16,8 @@
+ #include <linux/proc_fs.h>
+ #include <linux/f2fs_fs.h>
+ #include <linux/blkdev.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
+
+ #include "f2fs.h"
+ #include "node.h"
+@@ -23,7 +25,7 @@
+ #include "gc.h"
+
+ static LIST_HEAD(f2fs_stat_list);
+-static struct proc_dir_entry *f2fs_proc_root;
++static struct dentry *debugfs_root;
+
+
+ void f2fs_update_stat(struct f2fs_sb_info *sbi)
+@@ -114,16 +116,14 @@ static void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
+ si->avg_vblocks = 0;
+ }
+
+-static int f2fs_read_gc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static int stat_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+ int i = 0;
++ int j;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- int j;
+ si = gc_i->stat_info;
+
+ mutex_lock(&si->stat_list);
+@@ -133,102 +133,111 @@ static int f2fs_read_gc(char *page, char **start, off_t off,
+ }
+ f2fs_update_stat(si->sbi);
+
+- buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
+- buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+- si->nat_area_segs, si->sit_area_segs);
+- buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
+- si->ssa_area_segs, si->main_area_segs);
+- buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
+- si->overp_segs, si->rsvd_segs);
+- buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
+- si->utilization, si->valid_count);
+- buf += sprintf(buf, " - Node: %u (Inode: %u, ",
+- si->valid_node_count, si->valid_inode_count);
+- buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
+- si->valid_node_count - si->valid_inode_count,
+- si->valid_count - si->valid_node_count);
+- buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
+- si->main_area_segs, si->main_area_sections,
+- si->main_area_zones);
+- buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_DATA],
+- si->cursec[CURSEG_COLD_DATA],
+- si->curzone[CURSEG_COLD_DATA]);
+- buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_DATA],
+- si->cursec[CURSEG_WARM_DATA],
+- si->curzone[CURSEG_WARM_DATA]);
+- buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_DATA],
+- si->cursec[CURSEG_HOT_DATA],
+- si->curzone[CURSEG_HOT_DATA]);
+- buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_NODE],
+- si->cursec[CURSEG_HOT_NODE],
+- si->curzone[CURSEG_HOT_NODE]);
+- buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_NODE],
+- si->cursec[CURSEG_WARM_NODE],
+- si->curzone[CURSEG_WARM_NODE]);
+- buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_NODE],
+- si->cursec[CURSEG_COLD_NODE],
+- si->curzone[CURSEG_COLD_NODE]);
+- buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
+- si->main_area_segs - si->dirty_count -
+- si->prefree_count - si->free_segs,
+- si->dirty_count);
+- buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
+- si->prefree_count,
+- si->free_segs,
+- si->free_secs);
+- buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
+- si->call_count, si->bg_gc);
+- buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
+- buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
+- buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
+- buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
+- buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
+- buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
+- si->hit_ext, si->total_ext);
+- buf += sprintf(buf, "\nBalancing F2FS Async:\n");
+- buf += sprintf(buf, " - nodes %4d in %4d\n",
+- si->ndirty_node, si->node_pages);
+- buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
+- si->ndirty_dent, si->ndirty_dirs);
+- buf += sprintf(buf, " - meta %4d in %4d\n",
+- si->ndirty_meta, si->meta_pages);
+- buf += sprintf(buf, " - NATs %5d > %lu\n",
+- si->nats, NM_WOUT_THRESHOLD);
+- buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
+- si->sits, si->fnids);
+- buf += sprintf(buf, "\nDistribution of User Blocks:");
+- buf += sprintf(buf, " [ valid | invalid | free ]\n");
+- buf += sprintf(buf, " [");
++ seq_printf(s, "=====[ partition info. #%d ]=====\n", i++);
++ seq_printf(s, "=====[ partition info. #%d ]=====\n", i++);
++ seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ seq_printf(s, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ seq_printf(s, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ seq_printf(s, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ seq_printf(s, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ seq_printf(s, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ seq_printf(s, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ seq_printf(s, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ seq_printf(s, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ seq_printf(s, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ seq_printf(s, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count, si->free_segs, si->free_secs);
++ seq_printf(s, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ seq_printf(s, " - data segments : %d\n", si->data_segs);
++ seq_printf(s, " - node segments : %d\n", si->node_segs);
++ seq_printf(s, "Try to move %d blocks\n", si->tot_blks);
++ seq_printf(s, " - data blocks : %d\n", si->data_blks);
++ seq_printf(s, " - node blocks : %d\n", si->node_blks);
++ seq_printf(s, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ seq_printf(s, "\nBalancing F2FS Async:\n");
++ seq_printf(s, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ seq_printf(s, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ seq_printf(s, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ seq_printf(s, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ seq_printf(s, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ seq_printf(s, "\nDistribution of User Blocks:");
++ seq_printf(s, " [ valid | invalid | free ]\n");
++ seq_printf(s, " [");
+ for (j = 0; j < si->util_valid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
++ seq_printf(s, "-");
++ seq_printf(s, "|");
+ for (j = 0; j < si->util_invalid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
++ seq_printf(s, "-");
++ seq_printf(s, "|");
+ for (j = 0; j < si->util_free; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "]\n\n");
+- buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
+- si->block_count[SSR], si->segment_count[SSR]);
+- buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
+- si->block_count[LFS], si->segment_count[LFS]);
++ seq_printf(s, "-");
++ seq_printf(s, "]\n\n");
++ seq_printf(s, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ seq_printf(s, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
+ }
+
+-static int f2fs_read_sit(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static int stat_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, stat_show, inode->i_private);
++}
++
++static const struct file_operations stat_fops = {
++ .open = stat_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int sit_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+ si = gc_i->stat_info;
+@@ -240,19 +249,29 @@ static int f2fs_read_sit(char *page, char **start, off_t off,
+ }
+ f2fs_update_gc_metric(si->sbi);
+
+- buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
+- si->bimodal, si->avg_vblocks);
++ seq_printf(s, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
++}
++
++static int sit_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, sit_show, inode->i_private);
+ }
+
+-static int f2fs_read_mem(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
++static const struct file_operations sit_fops = {
++ .open = sit_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static int mem_show(struct seq_file *s, void *v)
+ {
+ struct f2fs_gc_info *gc_i, *next;
+ struct f2fs_stat_info *si;
+- char *buf = page;
+
+ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
+@@ -314,15 +333,27 @@ static int f2fs_read_mem(char *page, char **start, off_t off,
+ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+
+- buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
+- (base_mem + cache_mem) >> 10,
+- base_mem >> 10,
+- cache_mem >> 10);
++ seq_printf(s, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10, cache_mem >> 10);
+ mutex_unlock(&si->stat_list);
+ }
+- return buf - page;
++ return 0;
++}
++
++static int mem_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, mem_show, inode->i_private);
+ }
+
++static const struct file_operations mem_fops = {
++ .open = mem_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++
+ static int init_stats(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_stat_info *si;
+@@ -362,53 +393,48 @@ void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i)
+
+ int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *sbi)
+ {
+- struct proc_dir_entry *entry;
+ int retval;
+
+- if (!f2fs_proc_root)
+- f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
+-
+- sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+-
+ retval = init_stats(sbi);
+ if (retval)
+ return retval;
+
+- entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
+- if (!entry)
+- return -ENOMEM;
+- entry->read_proc = f2fs_read_gc;
+- entry->write_proc = NULL;
++ if (!debugfs_root)
++ debugfs_root = debugfs_create_dir("f2fs", NULL);
++
++ sbi->s_debug = debugfs_create_dir(sb->s_id, debugfs_root);
++ if (!sbi->s_debug)
++ return -EINVAL;
++
++ if (!debugfs_create_file("f2fs_stat", S_IRUGO, sbi->s_debug,
++ NULL, &stat_fops))
++ goto failed;
++
++ if (!debugfs_create_file("f2fs_sit_stat", S_IRUGO, sbi->s_debug,
++ NULL, &sit_fops))
++ goto failed;
++
++ if (!debugfs_create_file("f2fs_mem_stat", S_IRUGO, sbi->s_debug,
++ NULL, &mem_fops))
++ goto failed;
+
+- entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_sit;
+- entry->write_proc = NULL;
+- entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_mem;
+- entry->write_proc = NULL;
+ return 0;
++failed:
++ debugfs_remove_recursive(sbi->s_debug);
++ sbi->s_debug = NULL;
++ return -EINVAL;
+ }
+
+ void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *sbi)
+ {
+- if (sbi->s_proc) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
+- remove_proc_entry(sb->s_id, f2fs_proc_root);
++ if (sbi->s_debug) {
++ debugfs_remove_recursive(sbi->s_debug);
++ sbi->s_debug = NULL;
+ }
+ }
+
+ void f2fs_remove_stats(void)
+ {
+- remove_proc_entry("fs/f2fs", NULL);
++ debugfs_remove_recursive(debugfs_root);
++ debugfs_root = NULL;
+ }
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 7f508b2..dc8045c 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -379,7 +379,7 @@ struct f2fs_sb_info {
+ int rr_flush;
+
+ /* related to GC */
+- struct proc_dir_entry *s_proc;
++ struct dentry *s_debug;
+ struct f2fs_gc_info *gc_info; /* Garbage Collector
+ information */
+ struct mutex gc_mutex; /* mutex for GC */
diff --git a/patches/linux-3.7/0119-f2fs-compile-fix.patch b/patches/linux-3.7/0119-f2fs-compile-fix.patch
new file mode 100644
index 0000000..70024ff
--- /dev/null
+++ b/patches/linux-3.7/0119-f2fs-compile-fix.patch
@@ -0,0 +1,21 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 24 Oct 2012 11:34:54 +0200
+Subject: [PATCH] f2fs: compile fix
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ fs/f2fs/segment.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 57d0931..5bab838 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -12,6 +12,7 @@
+ #include <linux/f2fs_fs.h>
+ #include <linux/bio.h>
+ #include <linux/blkdev.h>
++#include <linux/vmalloc.h>
+
+ #include "f2fs.h"
+ #include "segment.h"
diff --git a/patches/linux-3.7/0121-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch b/patches/linux-3.7/0121-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
new file mode 100644
index 0000000..5833c3c
--- /dev/null
+++ b/patches/linux-3.7/0121-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
@@ -0,0 +1,40 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Jun 2012 19:45:33 +0000
+Subject: [PATCH] 6lowpan: lowpan_is_iid_16_bit_compressable() does not detect
+ compressable address correctly
+
+The current test is not RFC6282 compliant. The same issue has been found
+out and fixed in Contiki. This patch is basicaly a port of their fix.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.h | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
+index 8c2251f..efd1a57 100644
+--- a/net/ieee802154/6lowpan.h
++++ b/net/ieee802154/6lowpan.h
+@@ -87,14 +87,16 @@
+ #define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE)
+
+ /*
+- * check whether we can compress the IID to 16 bits,
+- * it's possible for unicast adresses with first 49 bits are zero only.
+- */
++* check whether we can compress the IID to 16 bits,
++* it's possible for unicast adresses with first 49 bits are zero only.
++*/
+ #define lowpan_is_iid_16_bit_compressable(a) \
+ ((((a)->s6_addr16[4]) == 0) && \
+- (((a)->s6_addr16[5]) == 0) && \
+- (((a)->s6_addr16[6]) == 0) && \
+- ((((a)->s6_addr[14]) & 0x80) == 0))
++ (((a)->s6_addr[10]) == 0) && \
++ (((a)->s6_addr[11]) == 0xff) && \
++ (((a)->s6_addr[12]) == 0xfe) && \
++ (((a)->s6_addr[13]) == 0))
++
+
+ /* multicast address */
+ #define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF)
diff --git a/patches/linux-3.7/0122-6lowpan-next-header-is-not-properly-set-upon-decompr.patch b/patches/linux-3.7/0122-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
new file mode 100644
index 0000000..ba2d639
--- /dev/null
+++ b/patches/linux-3.7/0122-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
@@ -0,0 +1,30 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Jun 2012 19:45:45 +0000
+Subject: [PATCH] 6lowpan: next header is not properly set upon decompression
+ of a UDP header.
+
+This causes a drop of the UDP packet.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 6d42c17..b53a71a4 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -913,9 +913,12 @@ lowpan_process_data(struct sk_buff *skb)
+ }
+
+ /* UDP data uncompression */
+- if (iphc0 & LOWPAN_IPHC_NH_C)
++ if (iphc0 & LOWPAN_IPHC_NH_C) {
+ if (lowpan_uncompress_udp_header(skb))
+ goto drop;
++ hdr.nexthdr = UIP_PROTO_UDP;
++ }
++
+
+ /* Not fragmented package */
+ hdr.payload_len = htons(skb->len);
diff --git a/patches/linux-3.7/0123-6lowpan-always-enable-link-layer-acknowledgments.patch b/patches/linux-3.7/0123-6lowpan-always-enable-link-layer-acknowledgments.patch
new file mode 100644
index 0000000..3b333ca
--- /dev/null
+++ b/patches/linux-3.7/0123-6lowpan-always-enable-link-layer-acknowledgments.patch
@@ -0,0 +1,30 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 25 Jun 2012 19:48:12 +0000
+Subject: [PATCH] 6lowpan: always enable link-layer acknowledgments
+
+This feature is especially important when using fragmentation, because
+the reassembly mechanism can not recover from the loss of a fragment.
+
+Note that some hardware ignore this flag and not will not transmit any
+acknowledgments if this is set.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index b53a71a4..49d91df 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -589,6 +589,10 @@ static int lowpan_header_create(struct sk_buff *skb,
+
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+
++ /* request acknowledgment when possible */
++ if (!lowpan_is_addr_broadcast(daddr))
++ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
++
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+ type, (void *)&da, (void *)&sa, skb->len);
+ }
diff --git a/patches/linux-3.7/0124-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch b/patches/linux-3.7/0124-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
new file mode 100644
index 0000000..e809fd5
--- /dev/null
+++ b/patches/linux-3.7/0124-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
@@ -0,0 +1,22 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Tue, 17 Jul 2012 17:59:39 -0400
+Subject: [PATCH] mac802154: turn on ACK when enabled by the upper layers
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/wpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
+index f30f6d4..d6aea7f 100644
+--- a/net/mac802154/wpan.c
++++ b/net/mac802154/wpan.c
+@@ -149,6 +149,8 @@ static int mac802154_header_create(struct sk_buff *skb,
+
+ head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
+ fc = mac_cb_type(skb);
++ if (mac_cb_is_ackreq(skb))
++ fc |= IEEE802154_FC_ACK_REQ;
+
+ if (!saddr) {
+ spin_lock_bh(&priv->mib_lock);
diff --git a/patches/linux-3.7/0125-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch b/patches/linux-3.7/0125-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
new file mode 100644
index 0000000..ec2ade7
--- /dev/null
+++ b/patches/linux-3.7/0125-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
@@ -0,0 +1,52 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Tue, 4 Sep 2012 23:48:13 -0400
+Subject: [PATCH] 6lowpan: use short IEEE 802.15.4 addresses for broadcast
+ destination
+
+It is intended that the IEEE 802.15.4 standard uses the 0xFFFF short address (2
+bytes) for message broadcasting.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 49d91df..8a2ee95 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -577,21 +577,26 @@ static int lowpan_header_create(struct sk_buff *skb,
+ * this isn't implemented in mainline yet, so currently we assign 0xff
+ */
+ {
++ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+ sa.pan_id = 0xff;
+-
+- da.addr_type = IEEE802154_ADDR_LONG;
+- da.pan_id = 0xff;
+-
+- memcpy(&(da.hwaddr), daddr, 8);
+ memcpy(&(sa.hwaddr), saddr, 8);
+
+- mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++ da.pan_id = 0xff;
++ /* if the destination address is the broadcast address,
++ use short address */
++ if (lowpan_is_addr_broadcast(daddr)) {
++ da.addr_type = IEEE802154_ADDR_SHORT;
++ da.short_addr = IEEE802154_ADDR_BROADCAST;
++ } else {
++ da.addr_type = IEEE802154_ADDR_LONG;
++ memcpy(&(da.hwaddr), daddr, 8);
+
+- /* request acknowledgment when possible */
+- if (!lowpan_is_addr_broadcast(daddr))
++ /* request acknowledgment */
+ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
++ }
+
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+ type, (void *)&da, (void *)&sa, skb->len);
diff --git a/patches/linux-3.7/0126-6lowpan-fix-first-fragment-FRAG1-handling.patch b/patches/linux-3.7/0126-6lowpan-fix-first-fragment-FRAG1-handling.patch
new file mode 100644
index 0000000..6abdd9d
--- /dev/null
+++ b/patches/linux-3.7/0126-6lowpan-fix-first-fragment-FRAG1-handling.patch
@@ -0,0 +1,136 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Sat, 8 Sep 2012 00:15:54 -0400
+Subject: [PATCH] 6lowpan: fix first fragment (FRAG1) handling
+
+The first fragment, FRAG1, must contain some payload according to the
+specs. However, as it is currently written, the first fragment will
+remain empty and only contain the 6lowpan headers.
+
+This patch also extract the transport layer information from the first
+fragment. This information is later on use when uncompressing UDP
+header.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 54 +++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 42 insertions(+), 12 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 8a2ee95..38cecaf 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -654,7 +654,7 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
+ }
+
+ static struct lowpan_fragment *
+-lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag)
++lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
+ {
+ struct lowpan_fragment *frame;
+
+@@ -735,6 +735,18 @@ lowpan_process_data(struct sk_buff *skb)
+ /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
+ len = ((iphc0 & 7) << 8) | slen;
+
++ if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) {
++ pr_debug("%s received a FRAG1 packet (tag: %d, "
++ "size of the entire IP packet: %d)"
++ , __func__, tag, len);
++ } else { /* FRAGN */
++ if (lowpan_fetch_skb_u8(skb, &offset))
++ goto unlock_and_drop;
++ pr_debug("%s received a FRAGN packet (tag: %d, "
++ "size of the entire IP packet: %d, "
++ "offset: %d)", __func__, tag, len, offset * 8);
++ }
++
+ /*
+ * check if frame assembling with the same tag is
+ * already in progress
+@@ -749,17 +761,13 @@ lowpan_process_data(struct sk_buff *skb)
+
+ /* alloc new frame structure */
+ if (!found) {
++ pr_debug("%s first fragment received for tag %d, "
++ "begin packet reassembly", __func__, tag);
+ frame = lowpan_alloc_new_frame(skb, len, tag);
+ if (!frame)
+ goto unlock_and_drop;
+ }
+
+- if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
+- goto unlock_and_drop;
+-
+- if (lowpan_fetch_skb_u8(skb, &offset)) /* fetch offset */
+- goto unlock_and_drop;
+-
+ /* if payload fits buffer, copy it */
+ if (likely((offset * 8 + skb->len) <= frame->length))
+ skb_copy_to_linear_data_offset(frame->skb, offset * 8,
+@@ -777,6 +785,10 @@ lowpan_process_data(struct sk_buff *skb)
+ list_del(&frame->list);
+ spin_unlock_bh(&flist_lock);
+
++ pr_debug("%s successfully reassembled fragment "
++ "(tag %d)", __func__, tag);
++
++
+ dev_kfree_skb(skb);
+ skb = frame->skb;
+ kfree(frame);
+@@ -976,13 +988,13 @@ static int lowpan_get_mac_header_length(struct sk_buff *skb)
+
+ static int
+ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
+- int mlen, int plen, int offset)
++ int mlen, int plen, int offset, int type)
+ {
+ struct sk_buff *frag;
+ int hlen, ret;
+
+- /* if payload length is zero, therefore it's a first fragment */
+- hlen = (plen == 0 ? LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE);
++ hlen = (type == LOWPAN_DISPATCH_FRAG1 ? LOWPAN_FRAG1_HEAD_SIZE :
++ LOWPAN_FRAGN_HEAD_SIZE);
+
+ lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
+
+@@ -1025,7 +1037,18 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+ head[2] = tag >> 8;
+ head[3] = tag & 0xff;
+
+- err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
++ err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
++ 0, LOWPAN_DISPATCH_FRAG1);
++
++ if (err) {
++#if DEBUG
++ pr_debug("%s unable to send FRAG1 packet (tag: %d)",
++ __func__, tag);
++#endif /* DEBUG */
++ goto exit;
++ }
++
++ offset = LOWPAN_FRAG_SIZE;
+
+ /* next fragment header */
+ head[0] &= ~LOWPAN_DISPATCH_FRAG1;
+@@ -1040,10 +1063,17 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
+ len = payload_length - offset;
+
+ err = lowpan_fragment_xmit(skb, head, header_length,
+- len, offset);
++ len, offset, LOWPAN_DISPATCH_FRAGN);
++ if (err) {
++ pr_debug("%s unable to send a subsequent FRAGN packet "
++ "(tag: %d, offset: %d", __func__, tag, offset);
++ goto exit;
++ }
++
+ offset += len;
+ }
+
++exit:
+ return err;
+ }
+
diff --git a/patches/linux-3.7/0127-6lowpan-store-fragment-tag-values-per-device-instead.patch b/patches/linux-3.7/0127-6lowpan-store-fragment-tag-values-per-device-instead.patch
new file mode 100644
index 0000000..06052e6
--- /dev/null
+++ b/patches/linux-3.7/0127-6lowpan-store-fragment-tag-values-per-device-instead.patch
@@ -0,0 +1,64 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Fri, 6 Jul 2012 17:39:22 -0400
+Subject: [PATCH] 6lowpan: store fragment tag values per device instead of net
+ stack wide
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 38cecaf..eb8003b 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -104,6 +104,7 @@ static const u8 lowpan_llprefix[] = {0xfe, 0x80};
+ struct lowpan_dev_info {
+ struct net_device *real_dev; /* real WPAN device ptr */
+ struct mutex dev_list_mtx; /* mutex for list ops */
++ unsigned short fragment_tag;
+ };
+
+ struct lowpan_dev_record {
+@@ -120,7 +121,6 @@ struct lowpan_fragment {
+ struct list_head list; /* fragments list */
+ };
+
+-static unsigned short fragment_tag;
+ static LIST_HEAD(lowpan_fragments);
+ static DEFINE_SPINLOCK(flist_lock);
+
+@@ -1022,14 +1022,14 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
+ }
+
+ static int
+-lowpan_skb_fragmentation(struct sk_buff *skb)
++lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev)
+ {
+ int err, header_length, payload_length, tag, offset = 0;
+ u8 head[5];
+
+ header_length = lowpan_get_mac_header_length(skb);
+ payload_length = skb->len - header_length;
+- tag = fragment_tag++;
++ tag = lowpan_dev_info(dev)->fragment_tag++;
+
+ /* first fragment header */
+ head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7);
+@@ -1095,7 +1095,7 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ pr_debug("frame is too big, fragmentation is needed\n");
+- err = lowpan_skb_fragmentation(skb);
++ err = lowpan_skb_fragmentation(skb, dev);
+ error:
+ dev_kfree_skb(skb);
+ out:
+@@ -1216,6 +1216,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
+ return -ENODEV;
+
+ lowpan_dev_info(dev)->real_dev = real_dev;
++ lowpan_dev_info(dev)->fragment_tag = 0;
+ mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
+
+ entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
diff --git a/patches/linux-3.7/0128-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch b/patches/linux-3.7/0128-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
new file mode 100644
index 0000000..69a86be
--- /dev/null
+++ b/patches/linux-3.7/0128-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
@@ -0,0 +1,47 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Fri, 6 Jul 2012 17:46:37 -0400
+Subject: [PATCH] 6lowpan: obtain IEEE802.15.4 sequence number from the MAC
+ layer
+
+This patch sets the sequence number in the frame format. Without this
+fix, the sequence number is always set to 0. This makes trafic analysis
+very hard.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index eb8003b..24b83fa 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -578,6 +578,7 @@ static int lowpan_header_create(struct sk_buff *skb,
+ */
+ {
+ mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
++ mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+@@ -1123,6 +1124,12 @@ static u16 lowpan_get_short_addr(const struct net_device *dev)
+ return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
+ }
+
++static u8 lowpan_get_dsn(const struct net_device *dev)
++{
++ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
++ return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev);
++}
++
+ static struct header_ops lowpan_header_ops = {
+ .create = lowpan_header_create,
+ };
+@@ -1136,6 +1143,7 @@ static struct ieee802154_mlme_ops lowpan_mlme = {
+ .get_pan_id = lowpan_get_pan_id,
+ .get_phy = lowpan_get_phy,
+ .get_short_addr = lowpan_get_short_addr,
++ .get_dsn = lowpan_get_dsn,
+ };
+
+ static void lowpan_setup(struct net_device *dev)
diff --git a/patches/linux-3.7/0129-6lowpan-add-a-new-parameter-in-sysfs-to-turn-on-off-.patch b/patches/linux-3.7/0129-6lowpan-add-a-new-parameter-in-sysfs-to-turn-on-off-.patch
new file mode 100644
index 0000000..e1100aa
--- /dev/null
+++ b/patches/linux-3.7/0129-6lowpan-add-a-new-parameter-in-sysfs-to-turn-on-off-.patch
@@ -0,0 +1,44 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Thu, 12 Jul 2012 17:47:39 -0400
+Subject: [PATCH] 6lowpan: add a new parameter in sysfs to turn on/off ACK
+ request at MAC layer
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 24b83fa..f8fcdae 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -62,6 +62,8 @@
+
+ #include "6lowpan.h"
+
++static bool req_802154_ack;
++
+ /* TTL uncompression values */
+ static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
+
+@@ -596,7 +598,8 @@ static int lowpan_header_create(struct sk_buff *skb,
+ memcpy(&(da.hwaddr), daddr, 8);
+
+ /* request acknowledgment */
+- mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
++ if (req_802154_ack)
++ mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
+ }
+
+ return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
+@@ -1366,6 +1369,10 @@ static void __exit lowpan_cleanup_module(void)
+ }
+
+ module_init(lowpan_init_module);
++
++module_param(req_802154_ack, bool, 0644);
++MODULE_PARM_DESC(req_802154_ack, "request link-layer (i.e. IEEE 802.15.4) acknowledgments");
++
+ module_exit(lowpan_cleanup_module);
+ MODULE_LICENSE("GPL");
+ MODULE_ALIAS_RTNL_LINK("lowpan");
diff --git a/patches/linux-3.7/0130-6lowpan-use-the-PANID-provided-by-the-device-instead.patch b/patches/linux-3.7/0130-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
new file mode 100644
index 0000000..8e90874
--- /dev/null
+++ b/patches/linux-3.7/0130-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
@@ -0,0 +1,29 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 24 Sep 2012 23:11:46 -0400
+Subject: [PATCH] 6lowpan: use the PANID provided by the device instead of a
+ static value
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index f8fcdae..9711038 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -584,10 +584,12 @@ static int lowpan_header_create(struct sk_buff *skb,
+
+ /* prepare wpan address data */
+ sa.addr_type = IEEE802154_ADDR_LONG;
+- sa.pan_id = 0xff;
++ sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
++
+ memcpy(&(sa.hwaddr), saddr, 8);
++ /* intra-PAN communications */
++ da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+
+- da.pan_id = 0xff;
+ /* if the destination address is the broadcast address,
+ use short address */
+ if (lowpan_is_addr_broadcast(daddr)) {
diff --git a/patches/linux-3.7/0131-6lowpan-modify-udp-compression-uncompression-to-matc.patch b/patches/linux-3.7/0131-6lowpan-modify-udp-compression-uncompression-to-matc.patch
new file mode 100644
index 0000000..e99cc9a
--- /dev/null
+++ b/patches/linux-3.7/0131-6lowpan-modify-udp-compression-uncompression-to-matc.patch
@@ -0,0 +1,89 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 24 Sep 2012 22:56:51 -0400
+Subject: [PATCH] 6lowpan: modify udp compression/uncompression to match the
+ standard
+
+The previous code would just compress the UDP header and send the compressed
+UDP header along with the uncompressed one.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 36 +++++++++++++++++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 3 deletions(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 9711038..9c7ac2e 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -286,6 +286,9 @@ lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
+ /* checksum is always inline */
+ memcpy(*hc06_ptr, &uh->check, 2);
+ *hc06_ptr += 2;
++
++ /* skip the UDP header */
++ skb_pull(skb, sizeof(struct udphdr));
+ }
+
+ static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
+@@ -311,9 +314,8 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
+ }
+
+ static int
+-lowpan_uncompress_udp_header(struct sk_buff *skb)
++lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
+ {
+- struct udphdr *uh = udp_hdr(skb);
+ u8 tmp;
+
+ if (!uh)
+@@ -354,12 +356,19 @@ lowpan_uncompress_udp_header(struct sk_buff *skb)
+ break;
+ }
+
++
+ pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+ uh->source, uh->dest);
+
+ /* copy checksum */
+ memcpy(&uh->check, &skb->data[0], 2);
+ skb_pull(skb, 2);
++
++ /* UDP lenght needs to be infered from the lower layers
++ here, we obtain the hint from the remaining size of the
++ frame */
++ uh->len = htons(skb->len + sizeof(struct udphdr));
++ pr_debug("uncompressed UDP length: src = %d", uh->len);
+ } else {
+ pr_debug("ERROR: unsupported NH format\n");
+ goto err;
+@@ -941,8 +950,29 @@ lowpan_process_data(struct sk_buff *skb)
+
+ /* UDP data uncompression */
+ if (iphc0 & LOWPAN_IPHC_NH_C) {
+- if (lowpan_uncompress_udp_header(skb))
++ struct udphdr uh;
++ struct sk_buff *new;
++ if (lowpan_uncompress_udp_header(skb, &uh))
+ goto drop;
++
++ /* place the real UDP header instead of the
++ compressed UDP header */
++ new = skb_copy_expand(skb, sizeof(struct udphdr),
++ skb_tailroom(skb), GFP_ATOMIC);
++ kfree_skb(skb);
++
++ if (!new)
++ return -ENOMEM;
++
++ skb = new ;
++
++ skb_push(skb, sizeof(struct udphdr));
++ skb_reset_transport_header(skb);
++ skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
++
++ lowpan_raw_dump_table(__func__, "raw UDP header dump",
++ (u8 *)&uh, sizeof(uh));
++
+ hdr.nexthdr = UIP_PROTO_UDP;
+ }
+
diff --git a/patches/linux-3.7/0132-6lowpan-make-memory-allocation-atomic-during-6lowpan.patch b/patches/linux-3.7/0132-6lowpan-make-memory-allocation-atomic-during-6lowpan.patch
new file mode 100644
index 0000000..a4fc7be
--- /dev/null
+++ b/patches/linux-3.7/0132-6lowpan-make-memory-allocation-atomic-during-6lowpan.patch
@@ -0,0 +1,26 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Mon, 3 Sep 2012 23:26:27 -0400
+Subject: [PATCH] 6lowpan: make memory allocation atomic during 6lowpan header
+ creation
+
+This is prevent various crashes when using the serial driver (not yet in
+the tree).
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/ieee802154/6lowpan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 9c7ac2e..70ff171 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -396,7 +396,7 @@ static int lowpan_header_create(struct sk_buff *skb,
+ /* TODO:
+ * if this package isn't ipv6 one, where should it be routed?
+ */
+- head = kzalloc(100, GFP_KERNEL);
++ head = kzalloc(100, GFP_ATOMIC);
+ if (head == NULL)
+ return -ENOMEM;
+
diff --git a/patches/linux-3.7/0133-mac802154-make-mem-alloc-ATOMIC-to-prevent-schedulin.patch b/patches/linux-3.7/0133-mac802154-make-mem-alloc-ATOMIC-to-prevent-schedulin.patch
new file mode 100644
index 0000000..1159c0a
--- /dev/null
+++ b/patches/linux-3.7/0133-mac802154-make-mem-alloc-ATOMIC-to-prevent-schedulin.patch
@@ -0,0 +1,25 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Tue, 10 Jul 2012 11:36:28 -0400
+Subject: [PATCH] mac802154: make mem alloc ATOMIC to prevent "scheduling
+ while atomic" crashes
+
+These crashes occur mainly with the serial driver (not yet in the tree).
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/wpan.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
+index d6aea7f..49ba8df 100644
+--- a/net/mac802154/wpan.c
++++ b/net/mac802154/wpan.c
+@@ -143,7 +143,7 @@ static int mac802154_header_create(struct sk_buff *skb,
+ if (!daddr)
+ return -EINVAL;
+
+- head = kzalloc(MAC802154_FRAME_HARD_HEADER_LEN, GFP_KERNEL);
++ head = kzalloc(MAC802154_FRAME_HARD_HEADER_LEN, GFP_ATOMIC);
+ if (head == NULL)
+ return -ENOMEM;
+
diff --git a/patches/linux-3.7/0134-mac802154-remove-unnecessary-spinlocks.patch b/patches/linux-3.7/0134-mac802154-remove-unnecessary-spinlocks.patch
new file mode 100644
index 0000000..0bc9c07
--- /dev/null
+++ b/patches/linux-3.7/0134-mac802154-remove-unnecessary-spinlocks.patch
@@ -0,0 +1,50 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Thu, 20 Sep 2012 23:44:19 -0400
+Subject: [PATCH] mac802154: remove unnecessary spinlocks
+
+These spinlock protects an int variable, that is always accessible in an
+atomic fashion.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/mib.c | 14 ++------------
+ 1 file changed, 2 insertions(+), 12 deletions(-)
+
+diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
+index f47781a..2339f8d 100644
+--- a/net/mac802154/mib.c
++++ b/net/mac802154/mib.c
+@@ -103,15 +103,10 @@ void mac802154_dev_set_short_addr(struct net_device *dev, u16 val)
+ u16 mac802154_dev_get_short_addr(const struct net_device *dev)
+ {
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+- u16 ret;
+
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+- spin_lock_bh(&priv->mib_lock);
+- ret = priv->short_addr;
+- spin_unlock_bh(&priv->mib_lock);
+-
+- return ret;
++ return priv->short_addr;
+ }
+
+ void mac802154_dev_set_ieee_addr(struct net_device *dev)
+@@ -131,15 +126,10 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev)
+ u16 mac802154_dev_get_pan_id(const struct net_device *dev)
+ {
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+- u16 ret;
+
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+- spin_lock_bh(&priv->mib_lock);
+- ret = priv->pan_id;
+- spin_unlock_bh(&priv->mib_lock);
+-
+- return ret;
++ return priv->pan_id;
+ }
+
+ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
diff --git a/patches/linux-3.7/0135-mac802154-re-introduce-MAC-primitives-required-to-se.patch b/patches/linux-3.7/0135-mac802154-re-introduce-MAC-primitives-required-to-se.patch
new file mode 100644
index 0000000..510c783
--- /dev/null
+++ b/patches/linux-3.7/0135-mac802154-re-introduce-MAC-primitives-required-to-se.patch
@@ -0,0 +1,100 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Thu, 20 Sep 2012 23:48:11 -0400
+Subject: [PATCH] mac802154: re-introduce MAC primitives required to
+ send/receive packets
+
+- mlme_assoc_req() and mlme_assoc_resp() are just place holder for the
+ moment (they prevent the two corresponding function pointers in the
+ mac802154_mlme_wpan structure to be left uninitialized)
+- mac802514_dev_get_bsn() and mac802514_dev_get_dsn() MAC primitives
+ were present in the Linux-Zigbee kernel and are being re-introduced.
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ net/mac802154/mac802154.h | 2 ++
+ net/mac802154/mac_cmd.c | 22 +++++++++++++++++++++-
+ net/mac802154/mib.c | 19 +++++++++++++++++++
+ 3 files changed, 42 insertions(+), 1 deletion(-)
+
+diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
+index a4dcaf1..18d4044 100644
+--- a/net/mac802154/mac802154.h
++++ b/net/mac802154/mac802154.h
+@@ -114,5 +114,7 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev);
+ u16 mac802154_dev_get_pan_id(const struct net_device *dev);
+ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
+ void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
++u8 mac802154_dev_get_dsn(const struct net_device *dev);
++u8 mac802154_dev_get_bsn(const struct net_device *dev);
+
+ #endif /* MAC802154_H */
+diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
+index d8d2770..8e46e7b 100644
+--- a/net/mac802154/mac_cmd.c
++++ b/net/mac802154/mac_cmd.c
+@@ -33,6 +33,22 @@
+
+ #include "mac802154.h"
+
++static int mac802154_mlme_assoc_req(struct net_device *dev,
++ struct ieee802154_addr *addr,
++ u8 channel, u8 page, u8 cap)
++{
++ /* TBD */
++ return 0;
++}
++
++static int mac802154_mlme_assoc_resp(struct net_device *dev,
++ struct ieee802154_addr *addr,
++ u16 short_addr, u8 status)
++{
++ /* TBD */
++ return 0;
++}
++
+ static int mac802154_mlme_start_req(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 channel, u8 page,
+@@ -70,7 +86,11 @@ struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = {
+
+ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
+ .get_phy = mac802154_get_phy,
+- .start_req = mac802154_mlme_start_req,
+ .get_pan_id = mac802154_dev_get_pan_id,
+ .get_short_addr = mac802154_dev_get_short_addr,
++ .get_dsn = mac802154_dev_get_dsn,
++ .get_bsn = mac802154_dev_get_bsn,
++ .start_req = mac802154_mlme_start_req,
++ .assoc_req = mac802154_mlme_assoc_req,
++ .assoc_resp = mac802154_mlme_assoc_resp
+ };
+diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
+index 2339f8d..70ab6ca 100644
+--- a/net/mac802154/mib.c
++++ b/net/mac802154/mib.c
+@@ -149,6 +149,25 @@ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
+ }
+ }
+
++u8 mac802154_dev_get_dsn(const struct net_device *dev)
++{
++ struct mac802154_sub_if_data *priv = netdev_priv(dev);
++
++ BUG_ON(dev->type != ARPHRD_IEEE802154);
++
++ return priv->dsn++;
++}
++
++u8 mac802154_dev_get_bsn(const struct net_device *dev)
++{
++ struct mac802154_sub_if_data *priv = netdev_priv(dev);
++
++ BUG_ON(dev->type != ARPHRD_IEEE802154);
++
++ return priv->bsn++;
++}
++
++
+ static void phy_chan_notify(struct work_struct *work)
+ {
+ struct phy_chan_notify_work *nw = container_of(work,
diff --git a/patches/linux-3.7/0136-serial-initial-import-of-the-IEEE-802.15.4-serial-dr.patch b/patches/linux-3.7/0136-serial-initial-import-of-the-IEEE-802.15.4-serial-dr.patch
new file mode 100644
index 0000000..3b798e2
--- /dev/null
+++ b/patches/linux-3.7/0136-serial-initial-import-of-the-IEEE-802.15.4-serial-dr.patch
@@ -0,0 +1,1323 @@
+From: Tony Cheneau <tony.cheneau@amnesiak.org>
+Date: Tue, 11 Sep 2012 23:42:51 -0400
+Subject: [PATCH] serial: initial import of the IEEE 802.15.4 serial driver
+
+The initial code has been imported from the Linux ZigBee project. It
+supports RedBee Econotag device type.
+
+Patches from Mariano Alvira has been applied against the drivers.
+
+Initialisation of the driver now send CLOSE command before sending OPEN
+command. This effectively re-initiate the devices (empty buffers).
+
+Signed-off-by: Tony Cheneau <tony.cheneau@amnesiak.org>
+---
+ drivers/net/ieee802154/Kconfig | 4 +
+ drivers/net/ieee802154/Makefile | 1 +
+ drivers/net/ieee802154/serial.c | 1228 +++++++++++++++++++++++++++++++++++++++
+ include/linux/nl802154.h | 3 +-
+ include/uapi/linux/tty.h | 1 +
+ net/ieee802154/6lowpan.c | 2 +
+ 6 files changed, 1238 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ieee802154/serial.c
+
+diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
+index 08ae465..c982fa8 100644
+--- a/drivers/net/ieee802154/Kconfig
++++ b/drivers/net/ieee802154/Kconfig
+@@ -45,3 +45,7 @@ config IEEE802154_MRF24J40
+
+ This driver can also be built as a module. To do so, say M here.
+ the module will be called 'mrf24j40'.
++
++config IEEE802154_SERIAL
++ depends on IEEE802154_DRIVERS && MAC802154
++ tristate "Simple LR-WPAN UART driver"
+diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
+index abb0c08..5c7d9cb 100644
+--- a/drivers/net/ieee802154/Makefile
++++ b/drivers/net/ieee802154/Makefile
+@@ -2,3 +2,4 @@ obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
+ obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
+ obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
+ obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
++obj-$(CONFIG_IEEE802154_SERIAL) += serial.o
+diff --git a/drivers/net/ieee802154/serial.c b/drivers/net/ieee802154/serial.c
+new file mode 100644
+index 0000000..950893a
+--- /dev/null
++++ b/drivers/net/ieee802154/serial.c
+@@ -0,0 +1,1228 @@
++/*
++ * ZigBee TTY line discipline.
++ *
++ * Provides interface between ZigBee stack and IEEE 802.15.4 compatible
++ * firmware over serial line. Communication protocol is described below.
++ *
++ * Copyright (C) 2007, 2008, 2009 Siemens AG
++ *
++ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Written by:
++ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
++ * Maxim Osipov <maxim.osipov@siemens.com>
++ * Sergey Lapin <slapin@ossfans.org>
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/completion.h>
++#include <linux/tty.h>
++#include <linux/skbuff.h>
++#include <linux/sched.h>
++#include <net/mac802154.h>
++#include <net/wpan-phy.h>
++
++
++/* NOTE: be sure to use here the same values as in the firmware */
++#define START_BYTE1 'z'
++#define START_BYTE2 'b'
++#define MAX_DATA_SIZE 127
++
++#define TIMEOUT 1000
++
++#define IDLE_MODE 0x00
++#define RX_MODE 0x02
++#define TX_MODE 0x03
++#define FORCE_TRX_OFF 0xF0
++
++#define STATUS_SUCCESS 0
++#define STATUS_RX_ON 1
++#define STATUS_TX_ON 2
++#define STATUS_TRX_OFF 3
++#define STATUS_IDLE 4
++#define STATUS_BUSY 5
++#define STATUS_BUSY_RX 6
++#define STATUS_BUSY_TX 7
++#define STATUS_ERR 8
++
++#define STATUS_WAIT ((u8) -1) /* waiting for the answer */
++
++/* We re-use PPP ioctl for our purposes */
++#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
++
++/*
++ * The following messages are used to control ZigBee firmware.
++ * All communication has request/response format,
++ * except of asynchronous incoming data stream (DATA_RECV_* messages).
++ */
++enum {
++ NO_ID = 0, /* means no pending id */
++
++ /* Driver to Firmware */
++ CMD_OPEN = 0x01, /* u8 id */
++ CMD_CLOSE = 0x02, /* u8 id */
++ CMD_SET_CHANNEL = 0x04, /* u8 id, u8 channel */
++ CMD_ED = 0x05, /* u8 id */
++ CMD_SET_STATE = 0x07, /* u8 id, u8 flag */
++ DATA_XMIT_BLOCK = 0x09, /* u8 id, u8 len, u8 data[len] */
++ RESP_RECV_BLOCK = 0x0b, /* u8 id, u8 status */
++ CMD_ADDRESS = 0x0d, /* u8 id */
++ CMD_SET_PAN_ID = 0x0f, /* u8 id, u8 u8 panid (MSB first) */
++ CMD_SET_SHORT_ADDRESS = 0x10, /* u8 id, u8 u8 address (MSB first)*/
++ CMD_SET_LONG_ADDRESS = 0x11, /* u8 id, u8 u8 u8 u8 u8 u8 u8 u8 address (MSB first) */
++
++ /* Firmware to Driver */
++ RESP_OPEN = 0x81, /* u8 id, u8 status */
++ RESP_CLOSE = 0x82, /* u8 id, u8 status */
++ RESP_SET_CHANNEL = 0x84, /* u8 id, u8 status */
++ RESP_ED = 0x85, /* u8 id, u8 status, u8 level */
++ RESP_SET_STATE = 0x87, /* u8 id, u8 status */
++ RESP_XMIT_BLOCK = 0x89, /* u8 id, u8 status */
++ DATA_RECV_BLOCK = 0x8b, /* u8 id, u8 lq, u8 len, u8 data[len] */
++ RESP_ADDRESS = 0x8d, /* u8 id, u8 status, u8 u8 u8 u8 u8 u8 u8 u8 address */
++ RESP_SET_PAN_ID = 0x8f, /* u8 id, u8 status */
++ RESP_SET_SHORT_ADDRESS = 0x90, /* u8 id, u8 status */
++ RESP_SET_LONG_ADDRESS = 0x91, /* u8 id, u8 status */
++};
++
++enum {
++ STATE_WAIT_START1,
++ STATE_WAIT_START2,
++ STATE_WAIT_COMMAND,
++ STATE_WAIT_PARAM1,
++ STATE_WAIT_PARAM2,
++ STATE_WAIT_DATA
++};
++
++struct zb_device {
++ /* Relative devices */
++ struct tty_struct *tty;
++ struct ieee802154_dev *dev;
++
++ /* locks the ldisc for the command */
++ struct mutex mutex;
++
++ /* command completition */
++ wait_queue_head_t wq;
++ u8 status;
++ u8 ed;
++
++ /* Internal state */
++ struct completion open_done;
++ struct completion close_done;
++ unsigned char opened;
++ u8 pending_id;
++ unsigned int pending_size;
++ u8 *pending_data;
++ /* FIXME: WE NEED LOCKING!!! */
++
++ /* Command (rx) processing */
++ int state;
++ unsigned char id;
++ unsigned char param1;
++ unsigned char param2;
++ unsigned char index;
++ unsigned char data[MAX_DATA_SIZE];
++};
++
++/*****************************************************************************
++ * ZigBee serial device protocol handling
++ *****************************************************************************/
++static int _open_dev(struct zb_device *zbdev);
++static int _close_dev(struct zb_device *zbdev);
++
++static void
++cleanup(struct zb_device *zbdev)
++{
++ zbdev->state = STATE_WAIT_START1;
++ zbdev->id = 0;
++ zbdev->param1 = 0;
++ zbdev->param2 = 0;
++ zbdev->index = 0;
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++
++ if (zbdev->pending_data)
++ {
++ kfree(zbdev->pending_data);
++ zbdev->pending_data = NULL;
++ }
++}
++
++static int
++_send_pending_data(struct zb_device *zbdev)
++{
++ struct tty_struct *tty;
++
++ BUG_ON(!zbdev);
++ tty = zbdev->tty;
++ if (!tty)
++ return -ENODEV;
++
++ zbdev->status = STATUS_WAIT;
++
++ /* Debug info */
++ printk(KERN_INFO "%s, %d bytes\n", __func__,
++ zbdev->pending_size);
++#ifdef DEBUG
++ print_hex_dump_bytes("send_pending_data ", DUMP_PREFIX_NONE,
++ zbdev->pending_data, zbdev->pending_size);
++#endif
++
++ if (tty->driver->ops->write(tty, zbdev->pending_data,
++ zbdev->pending_size) != zbdev->pending_size) {
++ printk(KERN_ERR "%s: device write failed\n", __func__);
++ return -1;
++ }
++
++ return 0;
++}
++
++static int
++send_cmd(struct zb_device *zbdev, u8 id)
++{
++ u8 len = 0;
++ /* 4 because of 2 start bytes, id and optional extra */
++ u8 buf[4];
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++
++ if (!zbdev->opened) {
++ if (!_close_dev(zbdev) || !_open_dev(zbdev))
++ return -EAGAIN;
++ }
++
++ pr_debug("%s(): id = %u\n", __func__, id);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++ //BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = id;
++
++ zbdev->pending_id = id;
++ zbdev->pending_size = len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_ATOMIC);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ return _send_pending_data(zbdev);
++}
++
++static int
++send_cmd2(struct zb_device *zbdev, u8 id, u8 extra)
++{
++ u8 len = 0;
++ /* 4 because of 2 start bytes, id and optional extra */
++ u8 buf[4];
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++
++ if (!zbdev->opened) {
++ if (!_close_dev(zbdev) || !_open_dev(zbdev))
++ return -EAGAIN;
++ }
++
++ pr_debug("%s(): id = %u\n", __func__, id);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++// BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = id;
++ buf[len++] = extra;
++
++ zbdev->pending_id = id;
++ zbdev->pending_size = len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_ATOMIC);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ return _send_pending_data(zbdev);
++}
++
++static int
++send_cmd3(struct zb_device *zbdev, u8 id, u8 extra1, u8 extra2)
++{
++ u8 len = 0;
++ /* 5 because of 2 start bytes, id, extra1, extra2 */
++ u8 buf[5];
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++
++ if (!zbdev->opened) {
++ if (!_close_dev(zbdev) || !_open_dev(zbdev))
++ return -EAGAIN;
++ }
++
++ pr_debug("%s(): id = %u\n", __func__, id);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++// BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = id;
++ buf[len++] = extra1;
++ buf[len++] = extra2;
++
++ zbdev->pending_id = id;
++ zbdev->pending_size = len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_ATOMIC);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ return _send_pending_data(zbdev);
++}
++
++static int
++send_block(struct zb_device *zbdev, u8 len, u8 *data)
++{
++ u8 i = 0, buf[4]; /* 4 because of 2 start bytes, id and len */
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++
++ if (!zbdev->opened) {
++ if (!_close_dev(zbdev) || !_open_dev(zbdev))
++ return -EAGAIN;
++ }
++
++ pr_debug("%s(): id = %u\n", __func__, DATA_XMIT_BLOCK);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++ //BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[i++] = START_BYTE1;
++ buf[i++] = START_BYTE2;
++ buf[i++] = DATA_XMIT_BLOCK;
++ buf[i++] = len;
++
++ zbdev->pending_id = DATA_XMIT_BLOCK;
++ zbdev->pending_size = i + len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_ATOMIC);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, i);
++ memcpy(zbdev->pending_data + i, data, len);
++
++ return _send_pending_data(zbdev);
++}
++
++
++static int
++is_command(unsigned char c)
++{
++ switch (c) {
++ /* ids we can get here: */
++ case RESP_OPEN:
++ case RESP_CLOSE:
++ case RESP_SET_CHANNEL:
++ case RESP_ED:
++ case RESP_XMIT_BLOCK:
++ case DATA_RECV_BLOCK:
++ case RESP_ADDRESS:
++ case RESP_SET_PAN_ID:
++ case RESP_SET_SHORT_ADDRESS:
++ case RESP_SET_LONG_ADDRESS:
++ return 1;
++ }
++ return 0;
++}
++
++static int
++_match_pending_id(struct zb_device *zbdev)
++{
++ return ((CMD_OPEN == zbdev->pending_id &&
++ RESP_OPEN == zbdev->id) ||
++ (CMD_CLOSE == zbdev->pending_id &&
++ RESP_CLOSE == zbdev->id) ||
++ (CMD_SET_CHANNEL == zbdev->pending_id &&
++ RESP_SET_CHANNEL == zbdev->id) ||
++ (CMD_ED == zbdev->pending_id &&
++ RESP_ED == zbdev->id) ||
++ (DATA_XMIT_BLOCK == zbdev->pending_id &&
++ RESP_XMIT_BLOCK == zbdev->id) ||
++ (DATA_RECV_BLOCK == zbdev->id) ||
++ (CMD_ADDRESS == zbdev->pending_id &&
++ RESP_ADDRESS == zbdev->id)) ||
++ (CMD_SET_PAN_ID == zbdev->pending_id &&
++ RESP_SET_PAN_ID == zbdev->id) ||
++ (CMD_SET_SHORT_ADDRESS == zbdev->pending_id &&
++ RESP_SET_SHORT_ADDRESS == zbdev->id) ||
++ (CMD_SET_LONG_ADDRESS == zbdev->pending_id &&
++ RESP_SET_LONG_ADDRESS == zbdev->id);
++}
++
++static void serial_net_rx(struct zb_device *zbdev)
++{
++ /* zbdev->param1 is LQI
++ * zbdev->param2 is length of data
++ * zbdev->data is data itself
++ */
++ struct sk_buff *skb;
++ skb = alloc_skb(zbdev->param2, GFP_ATOMIC);
++ skb_put(skb, zbdev->param2);
++ skb_copy_to_linear_data(skb, zbdev->data, zbdev->param2);
++ ieee802154_rx_irqsafe(zbdev->dev, skb, zbdev->param1);
++}
++
++static void
++process_command(struct zb_device *zbdev)
++{
++ /* Command processing */
++ if (!_match_pending_id(zbdev))
++ {
++ cleanup(zbdev);
++ return;
++ }
++
++ if (RESP_OPEN == zbdev->id && STATUS_SUCCESS == zbdev->param1) {
++ zbdev->opened = 1;
++ pr_debug("Opened device\n");
++ complete(&zbdev->open_done);
++ /* Input is not processed during output, so
++ * using completion is not possible during output.
++ * so we need to handle open as any other command
++ * and hope for best
++ */
++ return;
++ }
++
++ if (RESP_CLOSE == zbdev->id && STATUS_SUCCESS == zbdev->param1) {
++ zbdev->opened = 0;
++ pr_debug("Closed device\n");
++ complete(&zbdev->close_done);
++ /* Input is not processed during output, so
++ * using completion is not possible during output.
++ * so we need to handle open as any other command
++ * and hope for best
++ */
++ return;
++ }
++
++ if (!zbdev->opened)
++ {
++ cleanup(zbdev);
++ return;
++ }
++
++
++ zbdev->pending_id = 0;
++ kfree(zbdev->pending_data);
++ zbdev->pending_data = NULL;
++ zbdev->pending_size = 0;
++
++ if (zbdev->id != DATA_RECV_BLOCK) {
++ /* XXX: w/around for old FW, REMOVE */
++ if (zbdev->param1 == STATUS_IDLE)
++ zbdev->status = STATUS_SUCCESS;
++ else
++ zbdev->status = zbdev->param1;
++ }
++
++ switch (zbdev->id) {
++ case RESP_ED:
++ zbdev->ed = zbdev->param2;
++ break;
++ case DATA_RECV_BLOCK:
++ pr_debug("Received block, lqi %02x, len %02x\n",
++ zbdev->param1, zbdev->param2);
++ /* zbdev->param1 is LQ, zbdev->param2 is length */
++ serial_net_rx(zbdev);
++ break;
++ case RESP_ADDRESS:
++ pr_debug("Received address, %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
++ zbdev->data[0], zbdev->data[1], zbdev->data[2], zbdev->data[3],
++ zbdev->data[4], zbdev->data[5], zbdev->data[6], zbdev->data[7]);
++ break;
++ }
++
++ cleanup(zbdev);
++
++ wake_up(&zbdev->wq);
++}
++
++static void
++process_char(struct zb_device *zbdev, unsigned char c)
++{
++ /* Data processing */
++ switch (zbdev->state) {
++ case STATE_WAIT_START1:
++ if (START_BYTE1 == c)
++ zbdev->state = STATE_WAIT_START2;
++ else
++ cleanup(zbdev);
++ break;
++
++ case STATE_WAIT_START2:
++ if (START_BYTE2 == c)
++ zbdev->state = STATE_WAIT_COMMAND;
++ else
++ cleanup(zbdev);
++ break;
++
++ case STATE_WAIT_COMMAND:
++ if (is_command(c)) {
++ zbdev->id = c;
++ zbdev->state = STATE_WAIT_PARAM1;
++ } else {
++ cleanup(zbdev);
++ printk(KERN_ERR "%s, unexpected command id: %x\n",
++ __func__, c);
++ }
++ break;
++
++ case STATE_WAIT_PARAM1:
++ zbdev->param1 = c;
++ if ((RESP_ED == zbdev->id) || (DATA_RECV_BLOCK == zbdev->id))
++ zbdev->state = STATE_WAIT_PARAM2;
++ else if (RESP_ADDRESS == zbdev->id) {
++ zbdev->param2 = 8;
++ zbdev->state = STATE_WAIT_DATA;
++ } else
++ process_command(zbdev);
++ break;
++
++ case STATE_WAIT_PARAM2:
++ zbdev->param2 = c;
++ if (RESP_ED == zbdev->id)
++ process_command(zbdev);
++ else if (DATA_RECV_BLOCK == zbdev->id)
++ zbdev->state = STATE_WAIT_DATA;
++ else
++ cleanup(zbdev);
++ break;
++
++ case STATE_WAIT_DATA:
++ if ((zbdev->index < sizeof(zbdev->data)) &&
++ (zbdev->param2 <= sizeof(zbdev->data))) {
++
++ zbdev->data[zbdev->index] = c;
++ zbdev->index++;
++ /*
++ * Pending data is received,
++ * param2 is length for DATA_RECV_BLOCK
++ */
++ if (zbdev->index == zbdev->param2) {
++ zbdev->state = STATE_WAIT_START1;
++ process_command(zbdev);
++ }
++ } else {
++ printk(KERN_ERR "%s(): data size is greater "
++ "than buffer available\n", __func__);
++ cleanup(zbdev);
++ }
++ break;
++
++ default:
++ cleanup(zbdev);
++ }
++}
++
++/*****************************************************************************
++ * Device operations for IEEE 802.15.4 PHY side interface ZigBee stack
++ *****************************************************************************/
++
++static int _open_dev(struct zb_device *zbdev)
++{
++ int retries;
++ u8 len = 0;
++ /* 4 because of 2 start bytes, id and optional extra */
++ u8 buf[4];
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++ if (zbdev->opened)
++ return 1;
++
++ pr_debug("%s()\n", __func__);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++ //BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = CMD_OPEN;
++
++
++ zbdev->pending_id = CMD_OPEN;
++ zbdev->pending_size = len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ retries = 5;
++ while (!zbdev->opened && retries) {
++
++ if (_send_pending_data(zbdev) != 0)
++ return 0;
++
++ /* 3 second before retransmission */
++ wait_for_completion_interruptible_timeout(
++ &zbdev->open_done, msecs_to_jiffies(TIMEOUT));
++ --retries;
++ }
++
++ cleanup(zbdev);
++
++ if (zbdev->opened) {
++ printk(KERN_INFO "Opened connection to device\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++static int _close_dev(struct zb_device *zbdev)
++{
++ int retries;
++ u8 len = 0;
++ /* 4 because of 2 start bytes, id and optional extra */
++ u8 buf[4];
++
++ /* Check arguments */
++ BUG_ON(!zbdev);
++
++ pr_debug("%s()\n", __func__);
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++ //BUG();
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = CMD_CLOSE;
++
++ zbdev->pending_id = CMD_CLOSE;
++ zbdev->pending_size = len;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_KERNEL);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ retries = 5;
++ do{
++
++ if (_send_pending_data(zbdev) !=0)
++ return 0;
++
++ /* 1 second before retransmission */
++ wait_for_completion_interruptible_timeout(
++ &zbdev->close_done, msecs_to_jiffies(TIMEOUT));
++ --retries;
++ } while (zbdev->opened && retries) ;
++
++ cleanup(zbdev);
++
++ if (!zbdev->opened)
++ {
++ printk(KERN_INFO "Closed connection to device\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++/* Valid channels: 1-16 */
++static int
++ieee802154_serial_set_channel(struct ieee802154_dev *dev, int page, int channel)
++{
++ struct zb_device *zbdev;
++ int ret = 0;
++
++ pr_debug("%s %d\n", __func__, channel);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ BUG_ON(page != 0);
++ /* Our channels are actually from 11 to 26
++ * We have IEEE802.15.4 channel no from 0 to 26.
++ * channels 0-10 are not valid for us */
++ BUG_ON(channel < 11 || channel > 26);
++ /* ... but our crappy firmware numbers channels from 1 to 16
++ * which is a mystery. We suould enforce that using PIB API
++ * but additional checking here won't kill, and gcc will
++ * optimize this stuff anyway. */
++ BUG_ON((channel - 10) < 1 && (channel - 10) > 16);
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++ ret = send_cmd2(zbdev, CMD_SET_CHANNEL, channel - 10);
++ if (ret)
++ goto out;
++
++ if (wait_event_interruptible_timeout(zbdev->wq,
++ zbdev->status != STATUS_WAIT,
++ msecs_to_jiffies(TIMEOUT)) > 0) {
++ if (zbdev->status != STATUS_SUCCESS)
++ ret = -EBUSY;
++ } else
++ ret = -EINTR;
++
++ if (!ret)
++ zbdev->dev->phy->current_channel = channel;
++out:
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++static int
++ieee802154_serial_ed(struct ieee802154_dev *dev, u8 *level)
++{
++ struct zb_device *zbdev;
++ int ret = 0;
++
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++
++ ret = send_cmd(zbdev, CMD_ED);
++ if (ret)
++ goto out;
++
++ if (wait_event_interruptible_timeout(zbdev->wq,
++ zbdev->status != STATUS_WAIT,
++ msecs_to_jiffies(TIMEOUT)) > 0) {
++ *level = zbdev->ed;
++ if (zbdev->status != STATUS_SUCCESS)
++ ret = -EBUSY;
++ } else
++ ret = -ETIMEDOUT;
++out:
++
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++static int
++ieee802154_serial_set_laddr(struct zb_device *zbdev, u8 addr[IEEE802154_ADDR_LEN])
++{
++ int ret = 0;
++ uint8_t len = 0;
++ /* 11 because of 2 start bytes, id and 8 bytes addr */
++ uint8_t buf[11];
++
++ pr_debug("%s\n", __func__);
++
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++
++
++ if (zbdev->pending_size) {
++ printk(KERN_ERR "%s(): cmd is already pending, id = %u\n",
++ __func__, zbdev->pending_id);
++ cleanup(zbdev);
++ return -EAGAIN;
++ }
++
++ /* Prepare a message */
++ buf[len++] = START_BYTE1;
++ buf[len++] = START_BYTE2;
++ buf[len++] = CMD_SET_LONG_ADDRESS;
++
++ memcpy(&buf[len], addr, IEEE802154_ADDR_LEN);
++
++ zbdev->pending_id = CMD_SET_LONG_ADDRESS;
++ zbdev->pending_size = len + IEEE802154_ADDR_LEN;
++ zbdev->pending_data = kzalloc(zbdev->pending_size, GFP_ATOMIC);
++ if (!zbdev->pending_data) {
++ printk(KERN_ERR "%s(): unable to allocate memory\n", __func__);
++ zbdev->pending_id = 0;
++ zbdev->pending_size = 0;
++ return -ENOMEM;
++ }
++ memcpy(zbdev->pending_data, buf, len);
++
++ ret = _send_pending_data(zbdev);
++
++ if (ret)
++ goto out;
++
++ if (wait_event_interruptible_timeout(zbdev->wq,
++ zbdev->status != STATUS_WAIT,
++ msecs_to_jiffies(TIMEOUT)) > 0) {
++ if (zbdev->status != STATUS_SUCCESS)
++ ret = -EBUSY;
++ } else
++ ret = -ETIMEDOUT;
++
++out:
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++static int
++ieee802154_serial_get_laddr(struct ieee802154_dev *dev, u8 addr[IEEE802154_ADDR_LEN])
++{
++ struct zb_device *zbdev;
++ int ret = 0;
++
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++
++ ret = send_cmd(zbdev, CMD_ADDRESS);
++ if (ret)
++ goto out;
++
++ if (wait_event_interruptible_timeout(zbdev->wq,
++ zbdev->status != STATUS_WAIT,
++ msecs_to_jiffies(TIMEOUT)) > 0) {
++ memcpy(addr, zbdev->data, IEEE802154_ADDR_LEN);
++ if (zbdev->status != STATUS_SUCCESS)
++ ret = -EBUSY;
++ } else
++ ret = -ETIMEDOUT;
++out:
++
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++static int
++ieee802154_serial_set_hw_addr_filt(struct ieee802154_dev *dev,
++ struct ieee802154_hw_addr_filt *filt,
++ unsigned long changed)
++{
++ struct zb_device *zbdev;
++ int ret = 0;
++
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++
++ switch (changed)
++ {
++ case IEEE802515_AFILT_SADDR_CHANGED:
++ send_cmd3(zbdev, CMD_SET_SHORT_ADDRESS, filt->short_addr & 0xff, filt->short_addr >> 8);
++ break;
++ case IEEE802515_AFILT_PANID_CHANGED:
++ send_cmd3(zbdev, CMD_SET_PAN_ID, filt->pan_id & 0xff, filt->pan_id >> 8);
++ break;
++ case IEEE802515_AFILT_IEEEADDR_CHANGED:
++ ret = ieee802154_serial_set_laddr(zbdev, filt->ieee_addr);
++ break;
++ default:
++ printk(KERN_ERR "%s: unable to apply change, not supported\n", __func__);
++ break;
++ }
++
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++static int
++ieee802154_serial_start(struct ieee802154_dev *dev)
++{
++ struct zb_device *zbdev;
++ int ret = 0;
++
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ pr_debug("%s end (retval: %d)\n", __func__, ret);
++ return ret;
++}
++
++static void
++ieee802154_serial_stop(struct ieee802154_dev *dev)
++{
++ struct zb_device *zbdev;
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return;
++ }
++
++ pr_debug("%s end\n", __func__);
++}
++
++static int
++ieee802154_serial_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
++{
++ struct zb_device *zbdev;
++ int ret;
++
++ pr_debug("%s\n", __func__);
++
++ zbdev = dev->priv;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s: wrong phy\n", __func__);
++ return -EINVAL;
++ }
++
++ if (mutex_lock_interruptible(&zbdev->mutex))
++ return -EINTR;
++
++ ret = send_block(zbdev, skb->len, skb->data);
++ if (ret)
++ goto out;
++
++ if (wait_event_interruptible_timeout(zbdev->wq,
++ zbdev->status != STATUS_WAIT,
++ msecs_to_jiffies(TIMEOUT)) > 0) {
++ if (zbdev->status != STATUS_SUCCESS) {
++ ret = -EBUSY;
++ goto out;
++ }
++ } else {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++out:
++
++ mutex_unlock(&zbdev->mutex);
++ pr_debug("%s end\n", __func__);
++ return ret;
++}
++
++/*****************************************************************************
++ * Line discipline interface for IEEE 802.15.4 serial device
++ *****************************************************************************/
++
++static struct ieee802154_ops serial_ops = {
++ .owner = THIS_MODULE,
++ .xmit = ieee802154_serial_xmit,
++ .ed = ieee802154_serial_ed,
++ .set_channel = ieee802154_serial_set_channel,
++ .start = ieee802154_serial_start,
++ .stop = ieee802154_serial_stop,
++// .set_hw_addr_filt = ieee802154_serial_set_hw_addr_filt,
++ .ieee_addr = ieee802154_serial_get_laddr,
++};
++
++/*
++ * Called when a tty is put into ZB line discipline. Called in process context.
++ * Returns 0 on success.
++ */
++static int
++ieee802154_tty_open(struct tty_struct *tty)
++{
++ struct zb_device *zbdev = tty->disc_data;
++ struct ieee802154_dev *dev;
++ int err;
++
++ pr_debug("Openning ldisc\n");
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++
++ if (tty->disc_data)
++ return -EBUSY;
++
++ dev = ieee802154_alloc_device(sizeof(*zbdev), &serial_ops);
++ if (!dev)
++ return -ENOMEM;
++
++ zbdev = dev->priv;
++ zbdev->dev = dev;
++
++ mutex_init(&zbdev->mutex);
++ init_completion(&zbdev->open_done);
++ init_completion(&zbdev->close_done);
++ init_waitqueue_head(&zbdev->wq);
++
++ dev->extra_tx_headroom = 0;
++ /* only 2.4 GHz band */
++ dev->phy->channels_supported[0] = 0x7fff800;
++
++ dev->flags = IEEE802154_HW_OMIT_CKSUM;
++
++ dev->parent = tty->dev;
++
++ zbdev->tty = tty_kref_get(tty);
++
++ cleanup(zbdev);
++
++ tty->disc_data = zbdev;
++ tty->receive_room = MAX_DATA_SIZE;
++ // TC: why was it removed ?
++ // why does it crash one of my computer each times, and the other one is fine
++ // tty->low_latency = 1;
++
++ /* FIXME: why is this needed. Note don't use ldisc_ref here as the
++ open path is before the ldisc is referencable */
++
++ if (tty->ldisc->ops->flush_buffer)
++ tty->ldisc->ops->flush_buffer(tty);
++ tty_driver_flush_buffer(tty);
++
++ err = ieee802154_register_device(dev);
++ if (err) {
++ printk(KERN_ERR "%s: device register failed\n", __func__);
++ goto out_free;
++ }
++
++ return 0;
++
++
++out_free:
++ tty->disc_data = NULL;
++ tty_kref_put(tty);
++ zbdev->tty = NULL;
++
++ ieee802154_unregister_device(zbdev->dev);
++ ieee802154_free_device(zbdev->dev);
++
++ return err;
++}
++
++/*
++ * Called when the tty is put into another line discipline or it hangs up. We
++ * have to wait for any cpu currently executing in any of the other zb_tty_*
++ * routines to finish before we can call zb_tty_close and free the
++ * zb_serial_dev struct. This routine must be called from process context, not
++ * interrupt or softirq context.
++ */
++static void
++ieee802154_tty_close(struct tty_struct *tty)
++{
++ struct zb_device *zbdev;
++
++ zbdev = tty->disc_data;
++ if (NULL == zbdev) {
++ printk(KERN_WARNING "%s: match is not found\n", __func__);
++ return;
++ }
++
++ tty->disc_data = NULL;
++ tty_kref_put(tty);
++ zbdev->tty = NULL;
++ mutex_destroy(&zbdev->mutex);
++
++ ieee802154_unregister_device(zbdev->dev);
++
++ tty_ldisc_flush(tty);
++ tty_driver_flush_buffer(tty);
++
++ ieee802154_free_device(zbdev->dev);
++}
++
++/*
++ * Called on tty hangup in process context.
++ */
++static int
++ieee802154_tty_hangup(struct tty_struct *tty)
++{
++ ieee802154_tty_close(tty);
++ return 0;
++}
++
++/*
++ * Called in process context only. May be re-entered
++ * by multiple ioctl calling threads.
++ */
++static int
++ieee802154_tty_ioctl(struct tty_struct *tty, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ struct zb_device *zbdev;
++
++ pr_debug("cmd = 0x%x\n", cmd);
++
++ zbdev = tty->disc_data;
++ if (NULL == zbdev) {
++ pr_debug("match is not found\n");
++ return -EINVAL;
++ }
++
++ switch (cmd) {
++ case TCFLSH:
++ return tty_perform_flush(tty, arg);
++ default:
++ /* Try the mode commands */
++ return tty_mode_ioctl(tty, file, cmd, arg);
++ }
++}
++
++
++/*
++ * This can now be called from hard interrupt level as well
++ * as soft interrupt level or mainline.
++ */
++static void
++ieee802154_tty_receive(struct tty_struct *tty, const unsigned char *buf,
++ char *cflags, int count)
++{
++ struct zb_device *zbdev;
++ int i;
++
++ /* Debug info */
++ printk(KERN_INFO "%s, received %d bytes\n", __func__,
++ count);
++#ifdef DEBUG
++ print_hex_dump_bytes("ieee802154_tty_receive ", DUMP_PREFIX_NONE,
++ buf, count);
++#endif
++
++ /* Actual processing */
++ zbdev = tty->disc_data;
++ if (NULL == zbdev) {
++ printk(KERN_ERR "%s(): record for tty is not found\n",
++ __func__);
++ return;
++ }
++ for (i = 0; i < count; ++i)
++ process_char(zbdev, buf[i]);
++#if 0
++ if (tty->driver->flush_chars)
++ tty->driver->flush_chars(tty);
++#endif
++ tty_unthrottle(tty);
++}
++
++/*
++ * Line discipline device structure
++ */
++static struct tty_ldisc_ops ieee802154_ldisc = {
++ .owner = THIS_MODULE,
++ .magic = TTY_LDISC_MAGIC,
++ .name = "ieee802154-ldisc",
++ .open = ieee802154_tty_open,
++ .close = ieee802154_tty_close,
++ .hangup = ieee802154_tty_hangup,
++ .receive_buf = ieee802154_tty_receive,
++ .ioctl = ieee802154_tty_ioctl,
++};
++
++/*****************************************************************************
++ * Module service routinues
++ *****************************************************************************/
++
++static int __init ieee802154_serial_init(void)
++{
++ printk(KERN_INFO "Initializing ZigBee TTY interface\n");
++
++ if (tty_register_ldisc(N_IEEE802154, &ieee802154_ldisc) != 0) {
++ printk(KERN_ERR "%s: line discipline register failed\n",
++ __func__);
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static void __exit ieee802154_serial_cleanup(void)
++{
++ if (tty_unregister_ldisc(N_IEEE802154) != 0)
++ printk(KERN_CRIT
++ "failed to unregister ZigBee line discipline.\n");
++}
++
++module_init(ieee802154_serial_init);
++module_exit(ieee802154_serial_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_LDISC(N_IEEE802154);
+diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
+index fd4f2d1..25ed3ec 100644
+--- a/include/linux/nl802154.h
++++ b/include/linux/nl802154.h
+@@ -21,6 +21,8 @@
+ #ifndef NL802154_H
+ #define NL802154_H
+
++#include <net/netlink.h>
++
+ #define IEEE802154_NL_NAME "802.15.4 MAC"
+ #define IEEE802154_MCAST_COORD_NAME "coordinator"
+ #define IEEE802154_MCAST_BEACON_NAME "beacon"
+@@ -132,7 +134,6 @@ enum {
+
+ IEEE802154_DEV_WPAN,
+ IEEE802154_DEV_MONITOR,
+-
+ __IEEE802154_DEV_MAX,
+ };
+
+diff --git a/include/uapi/linux/tty.h b/include/uapi/linux/tty.h
+index dac199a..96233b1 100644
+--- a/include/uapi/linux/tty.h
++++ b/include/uapi/linux/tty.h
+@@ -34,5 +34,6 @@
+ #define N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */
+ #define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
+ #define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
++#define N_IEEE802154 25 /* Serial / USB serial IEEE802154.4 devices */
+
+ #endif /* _UAPI_LINUX_TTY_H */
+diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
+index 70ff171..85bf4a9 100644
+--- a/net/ieee802154/6lowpan.c
++++ b/net/ieee802154/6lowpan.c
+@@ -59,6 +59,8 @@
+ #include <net/ieee802154.h>
+ #include <net/ieee802154_netdev.h>
+ #include <net/ipv6.h>
++#include <net/mac802154.h>
++
+
+ #include "6lowpan.h"
+
diff --git a/patches/linux-3.7/0138-i2c-EEPROM-Export-memory-accessor.patch b/patches/linux-3.7/0138-i2c-EEPROM-Export-memory-accessor.patch
new file mode 100644
index 0000000..171e5c0
--- /dev/null
+++ b/patches/linux-3.7/0138-i2c-EEPROM-Export-memory-accessor.patch
@@ -0,0 +1,88 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:06:48 +0300
+Subject: [PATCH] i2c-EEPROM: Export memory accessor
+
+Various platforms need access to the EEPROM in other
+places besides their platform registration callbacks.
+Export the memory accessor to the i2c_client and implement
+it for the at24 driver.
+---
+ drivers/misc/eeprom/at24.c | 5 +++++
+ include/linux/i2c.h | 24 ++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index ab1ad41..4f88ae65 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -609,6 +609,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+
+ at24->client[0] = client;
+
++ /* export accessor */
++ client->macc = &at24->macc;
++
+ /* use dummy devices for multiple-address chips */
+ for (i = 1; i < num_addresses; i++) {
+ at24->client[i] = i2c_new_dummy(client->adapter,
+@@ -619,6 +622,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ err = -EADDRINUSE;
+ goto err_clients;
+ }
++ at24->client[i]->macc = &at24->macc;
+ }
+
+ err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
+@@ -637,6 +641,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+ I2C_SMBUS_WORD_DATA ? "word" : "byte");
+ }
+
++
+ /* export data to kernel code */
+ if (chip.setup)
+ chip.setup(&at24->macc, chip.context);
+diff --git a/include/linux/i2c.h b/include/linux/i2c.h
+index 800de22..e20ad4e 100644
+--- a/include/linux/i2c.h
++++ b/include/linux/i2c.h
+@@ -33,6 +33,7 @@
+ #include <linux/of.h> /* for struct device_node */
+ #include <linux/swab.h> /* for swab16 */
+ #include <uapi/linux/i2c.h>
++#include <linux/memory.h>
+
+ extern struct bus_type i2c_bus_type;
+ extern struct device_type i2c_adapter_type;
+@@ -229,9 +230,32 @@ struct i2c_client {
+ struct device dev; /* the device structure */
+ int irq; /* irq issued by device */
+ struct list_head detected;
++
++ /* export accessor */
++ struct memory_accessor *macc;
+ };
+ #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
+
++static inline ssize_t i2c_memory_read(struct i2c_client *client, char *buf, off_t offset,
++ size_t count)
++{
++ struct memory_accessor *macc = client->macc;
++
++ if (macc == NULL || macc->read == NULL)
++ return -ENODEV;
++ return (*client->macc->read)(macc, buf, offset, count);
++}
++
++static inline ssize_t i2c_memory_write(struct i2c_client *client, const char *buf, off_t offset,
++ size_t count)
++{
++ struct memory_accessor *macc = client->macc;
++
++ if (macc == NULL || macc->write == NULL)
++ return -ENODEV;
++ return (*client->macc->write)(macc, buf, offset, count);
++}
++
+ extern struct i2c_client *i2c_verify_client(struct device *dev);
+ extern struct i2c_adapter *i2c_verify_adapter(struct device *dev);
+
diff --git a/patches/linux-3.7/0139-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch b/patches/linux-3.7/0139-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
new file mode 100644
index 0000000..1ff3680
--- /dev/null
+++ b/patches/linux-3.7/0139-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
@@ -0,0 +1,70 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 13 Oct 2012 16:34:44 +0300
+Subject: [PATCH] omap: Export
+ omap_hwmod_lookup/omap_device_build/omap_device_build_ss
+
+These functions can be used just fine by modules, there's no need not
+to have them exported.
+---
+ arch/arm/mach-omap2/omap_hwmod.c | 2 ++
+ arch/arm/plat-omap/omap_device.c | 6 ++++--
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
+index 87cc6d0..f3c0947 100644
+--- a/arch/arm/mach-omap2/omap_hwmod.c
++++ b/arch/arm/mach-omap2/omap_hwmod.c
+@@ -138,6 +138,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
+ #include <linux/bootmem.h>
++#include <linux/export.h>
+
+ #include <plat/clock.h>
+ #include <plat/omap_hwmod.h>
+@@ -3076,6 +3077,7 @@ struct omap_hwmod *omap_hwmod_lookup(const char *name)
+
+ return oh;
+ }
++EXPORT_SYMBOL(omap_hwmod_lookup);
+
+ /**
+ * omap_hwmod_for_each - call function for each registered omap_hwmod
+diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
+index 7a7d1f2..a15b715 100644
+--- a/arch/arm/plat-omap/omap_device.c
++++ b/arch/arm/plat-omap/omap_device.c
+@@ -663,7 +663,7 @@ void omap_device_delete(struct omap_device *od)
+ * information. Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
+ * passes along the return value of omap_device_build_ss().
+ */
+-struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
++struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
+ struct omap_hwmod *oh, void *pdata,
+ int pdata_len,
+ struct omap_device_pm_latency *pm_lats,
+@@ -678,6 +678,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev
+ pdata_len, pm_lats, pm_lats_cnt,
+ is_early_device);
+ }
++EXPORT_SYMBOL(omap_device_build);
+
+ /**
+ * omap_device_build_ss - build and register an omap_device with multiple hwmods
+@@ -696,7 +697,7 @@ struct platform_device __init *omap_device_build(const char *pdev_name, int pdev
+ * platform_device record. Returns an ERR_PTR() on error, or passes
+ * along the return value of omap_device_register().
+ */
+-struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
++struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
+ struct omap_hwmod **ohs, int oh_cnt,
+ void *pdata, int pdata_len,
+ struct omap_device_pm_latency *pm_lats,
+@@ -751,6 +752,7 @@ odbs_exit:
+
+ return ERR_PTR(ret);
+ }
++EXPORT_SYMBOL(omap_device_build_ss);
+
+ /**
+ * omap_early_device_register - register an omap_device as an early platform
diff --git a/patches/linux-3.7/0140-gpio-keys-Pinctrl-fy.patch b/patches/linux-3.7/0140-gpio-keys-Pinctrl-fy.patch
new file mode 100644
index 0000000..5faafc4
--- /dev/null
+++ b/patches/linux-3.7/0140-gpio-keys-Pinctrl-fy.patch
@@ -0,0 +1,39 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 20:17:36 +0300
+Subject: [PATCH] gpio-keys: Pinctrl-fy
+
+---
+ drivers/input/keyboard/gpio_keys.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
+index 6a68041..e421082 100644
+--- a/drivers/input/keyboard/gpio_keys.c
++++ b/drivers/input/keyboard/gpio_keys.c
+@@ -29,6 +29,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/of_gpio.h>
+ #include <linux/spinlock.h>
++#include <linux/pinctrl/consumer.h>
+
+ struct gpio_button_data {
+ const struct gpio_keys_button *button;
+@@ -666,6 +667,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+ struct input_dev *input;
+ int i, error;
+ int wakeup = 0;
++ struct pinctrl *pinctrl;
+
+ if (!pdata) {
+ pdata = gpio_keys_get_devtree_pdata(dev);
+@@ -731,6 +733,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
+ goto fail3;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ /* get current state of buttons that are connected to GPIOs */
+ for (i = 0; i < pdata->nbuttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
diff --git a/patches/linux-3.7/0141-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch b/patches/linux-3.7/0141-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
new file mode 100644
index 0000000..2ae0319
--- /dev/null
+++ b/patches/linux-3.7/0141-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
@@ -0,0 +1,194 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 17 Oct 2012 20:17:57 +0300
+Subject: [PATCH] tps65217: Allow placement elsewhere than parent mfd device.
+
+The current code expect the configuration of the backlight to stay
+constant after initialization. This patch allows to move it around.
+---
+ drivers/video/backlight/tps65217_bl.c | 103 +++++++++++++++++++++++++++++----
+ 1 file changed, 92 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
+index 7088163..69c1dfe 100644
+--- a/drivers/video/backlight/tps65217_bl.c
++++ b/drivers/video/backlight/tps65217_bl.c
+@@ -24,8 +24,11 @@
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
+
+ struct tps65217_bl {
++ struct i2c_client *i2c_client;
+ struct tps65217 *tps;
+ struct device *dev;
+ struct backlight_device *bl;
+@@ -98,8 +101,6 @@ static int tps65217_bl_update_status(struct backlight_device *bl)
+ return rc;
+ }
+
+- dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
+-
+ if (!tps65217_bl->is_enabled)
+ rc = tps65217_bl_enable(tps65217_bl);
+ } else {
+@@ -187,14 +188,69 @@ static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
+
+ #ifdef CONFIG_OF
+ static struct tps65217_bl_pdata *
+-tps65217_bl_parse_dt(struct platform_device *pdev)
++tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
++ int *brightnessp)
+ {
+- struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+- struct device_node *node = of_node_get(tps->dev->of_node);
++ struct i2c_client *i2c_client;
++ struct tps65217 *tps;
++ struct device_node *node, *rnode, *pnode;
+ struct tps65217_bl_pdata *pdata, *err;
++ u32 tps_handle;
+ u32 val;
+
+- node = of_find_node_by_name(node, "backlight");
++ tps = NULL;
++ node = NULL;
++ *brightnessp = 0;
++
++ /* our node (compatible) */
++ pnode = pdev->dev.of_node;
++ if (pnode != NULL &&
++ of_property_read_u32(pnode, "tps", &tps_handle) == 0) {
++ /* we are not instantiated from the mfd */
++ node = of_find_node_by_phandle(tps_handle);
++ if (node == NULL) {
++ dev_err(&pdev->dev, "failed to find the tps node\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++ i2c_client = of_find_i2c_device_by_node(node);
++ if (i2c_client == NULL) {
++ dev_err(&pdev->dev, "failed to find the i2c device "
++ "of tps node\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++ /* yeah this is gross; the whole concept is */
++ tps = i2c_get_clientdata(i2c_client);
++ if (tps == NULL) {
++ dev_err(&pdev->dev, "failed to get tps structure\n");
++ err = ERR_PTR(-EINVAL);
++ goto err;
++ }
++
++ /* read default brightness */
++ val = 0;
++ of_property_read_u32(pnode, "brightness", &val);
++ if (val >= 100)
++ val = 100;
++
++ *brightnessp = val;
++
++ /* no need for this anymore */
++ of_node_put(node);
++
++ dev_info(&pdev->dev, "got tps=%p from handle 0x%x\n", tps, tps_handle);
++ }
++
++ if (tps == NULL)
++ tps = dev_get_drvdata(pdev->dev.parent);
++
++ rnode = of_node_get(tps->dev->of_node);
++
++ node = of_find_node_by_name(rnode, "backlight");
++ of_node_put(rnode);
++ rnode = NULL;
++
+ if (!node)
+ return ERR_PTR(-ENODEV);
+
+@@ -247,6 +303,7 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
+
+ of_node_put(node);
+
++ *tpsp = tps;
+ return pdata;
+
+ err:
+@@ -254,9 +311,16 @@ err:
+
+ return err;
+ }
++
++static struct of_device_id tps65217_backlight_of_match[] = {
++ { .compatible = "tps65217-backlight" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, tps65217_backlight_of_match);
+ #else
+ static struct tps65217_bl_pdata *
+-tps65217_bl_parse_dt(struct platform_device *pdev)
++tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
++ int *brightnessp)
+ {
+ return NULL;
+ }
+@@ -265,13 +329,16 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
+ static int tps65217_bl_probe(struct platform_device *pdev)
+ {
+ int rc;
+- struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
++ struct tps65217 *tps;
+ struct tps65217_bl *tps65217_bl;
+ struct tps65217_bl_pdata *pdata;
+ struct backlight_properties bl_props;
++ int brightness = 0;
+
+- if (tps->dev->of_node) {
+- pdata = tps65217_bl_parse_dt(pdev);
++ tps = NULL;
++
++ if (pdev->dev.of_node) {
++ pdata = tps65217_bl_parse_dt(pdev, &tps, &brightness);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ } else {
+@@ -281,6 +348,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
+ }
+
+ pdata = pdev->dev.platform_data;
++
++ /* get the parent device */
++ tps = dev_get_drvdata(pdev->dev.parent);
++ }
++
++ if (tps == NULL) {
++ dev_err(&pdev->dev, "failed to find tps\n");
++ return -EINVAL;
+ }
+
+ tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
+@@ -311,9 +386,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
+ return PTR_ERR(tps65217_bl->bl);
+ }
+
+- tps65217_bl->bl->props.brightness = 0;
++ tps65217_bl->bl->props.brightness = brightness;
+ platform_set_drvdata(pdev, tps65217_bl);
+
++ /* update with initial settings */
++ tps65217_bl_update_status(tps65217_bl->bl);
++
++ dev_info(&pdev->dev, "OK.\n");
++
+ return 0;
+ }
+
+@@ -332,6 +412,7 @@ static struct platform_driver tps65217_bl_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tps65217-bl",
++ .of_match_table = of_match_ptr(tps65217_backlight_of_match),
+ },
+ };
+
diff --git a/patches/linux-3.7/0142-pwm-export-of_pwm_request.patch b/patches/linux-3.7/0142-pwm-export-of_pwm_request.patch
new file mode 100644
index 0000000..cd81c81
--- /dev/null
+++ b/patches/linux-3.7/0142-pwm-export-of_pwm_request.patch
@@ -0,0 +1,66 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 19 Oct 2012 10:38:00 +0300
+Subject: [PATCH] pwm: export of_pwm_request
+
+No need to hide this, it's useful.
+---
+ drivers/pwm/core.c | 6 +++++-
+ include/linux/pwm.h | 7 +++++++
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index f5acdaa..f8c7e6b 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -457,7 +457,7 @@ static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
+ * becomes mandatory for devices that look up the PWM device via the con_id
+ * parameter.
+ */
+-static struct pwm_device *of_pwm_request(struct device_node *np,
++struct pwm_device *of_pwm_request(struct device_node *np,
+ const char *con_id)
+ {
+ struct pwm_device *pwm = NULL;
+@@ -466,6 +466,9 @@ static struct pwm_device *of_pwm_request(struct device_node *np,
+ int index = 0;
+ int err;
+
++ if (!np)
++ return ERR_PTR(-ENODEV);
++
+ if (con_id) {
+ index = of_property_match_string(np, "pwm-names", con_id);
+ if (index < 0)
+@@ -516,6 +519,7 @@ put:
+
+ return pwm;
+ }
++EXPORT_SYMBOL(of_pwm_request);
+
+ /**
+ * pwm_add_table() - register PWM device consumers
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index 112b314..fafbb1c 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -171,6 +171,7 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ unsigned int index,
+ const char *label);
+
++struct pwm_device *of_pwm_request(struct device_node *np, const char *consumer);
+ struct pwm_device *pwm_get(struct device *dev, const char *consumer);
+ void pwm_put(struct pwm_device *pwm);
+
+@@ -204,6 +205,12 @@ static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ return ERR_PTR(-ENODEV);
+ }
+
++static inline struct pwm_device *of_pwm_request(struct device_node *np,
++ const char *consumer)
++{
++ return ERR_PTR(-ENODEV);
++}
++
+ static inline struct pwm_device *pwm_get(struct device *dev,
+ const char *consumer)
+ {
diff --git a/patches/linux-3.7/0143-i2c-Export-capability-to-probe-devices.patch b/patches/linux-3.7/0143-i2c-Export-capability-to-probe-devices.patch
new file mode 100644
index 0000000..3a888e2
--- /dev/null
+++ b/patches/linux-3.7/0143-i2c-Export-capability-to-probe-devices.patch
@@ -0,0 +1,64 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Sat, 20 Oct 2012 14:08:17 +0300
+Subject: [PATCH] i2c: Export capability to probe devices
+
+Probe devices for a node other that the adapter node.
+---
+ drivers/of/of_i2c.c | 14 ++++++++++----
+ include/linux/of_i2c.h | 3 +++
+ 2 files changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
+index 3550f3b..7f36b05 100644
+--- a/drivers/of/of_i2c.c
++++ b/drivers/of/of_i2c.c
+@@ -18,18 +18,18 @@
+ #include <linux/of_irq.h>
+ #include <linux/module.h>
+
+-void of_i2c_register_devices(struct i2c_adapter *adap)
++void of_i2c_register_node_devices(struct i2c_adapter *adap,
++ struct device_node *parent_node)
+ {
+ void *result;
+ struct device_node *node;
+
+- /* Only register child devices if the adapter has a node pointer set */
+- if (!adap->dev.of_node)
++ if (!parent_node)
+ return;
+
+ dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
+
+- for_each_child_of_node(adap->dev.of_node, node) {
++ for_each_child_of_node(parent_node, node) {
+ struct i2c_board_info info = {};
+ struct dev_archdata dev_ad = {};
+ const __be32 *addr;
+@@ -76,6 +76,12 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
+ }
+ }
+ }
++EXPORT_SYMBOL(of_i2c_register_node_devices);
++
++void of_i2c_register_devices(struct i2c_adapter *adap)
++{
++ of_i2c_register_node_devices(adap, adap->dev.of_node);
++}
+ EXPORT_SYMBOL(of_i2c_register_devices);
+
+ static int of_dev_node_match(struct device *dev, void *data)
+diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h
+index 1cb775f..d2f8ebb6 100644
+--- a/include/linux/of_i2c.h
++++ b/include/linux/of_i2c.h
+@@ -15,6 +15,9 @@
+ #if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE)
+ #include <linux/i2c.h>
+
++extern void of_i2c_register_node_devices(struct i2c_adapter *adap,
++ struct device_node *parent_node);
++
+ extern void of_i2c_register_devices(struct i2c_adapter *adap);
+
+ /* must call put_device() when done with returned i2c_client device */
diff --git a/patches/linux-3.7/0144-pwm-backlight-Pinctrl-fy.patch b/patches/linux-3.7/0144-pwm-backlight-Pinctrl-fy.patch
new file mode 100644
index 0000000..c18e0d5
--- /dev/null
+++ b/patches/linux-3.7/0144-pwm-backlight-Pinctrl-fy.patch
@@ -0,0 +1,36 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 23 Oct 2012 11:48:58 +0300
+Subject: [PATCH] pwm-backlight: Pinctrl-fy
+
+---
+ drivers/video/backlight/pwm_bl.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
+index 0c91023..f3b6194 100644
+--- a/drivers/video/backlight/pwm_bl.c
++++ b/drivers/video/backlight/pwm_bl.c
+@@ -20,6 +20,8 @@
+ #include <linux/pwm.h>
+ #include <linux/pwm_backlight.h>
+ #include <linux/slab.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ struct pwm_bl_data {
+ struct pwm_device *pwm;
+@@ -180,9 +182,14 @@ static int pwm_backlight_probe(struct platform_device *pdev)
+ struct backlight_properties props;
+ struct backlight_device *bl;
+ struct pwm_bl_data *pb;
++ struct pinctrl *pinctrl;
+ unsigned int max;
+ int ret;
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ if (!data) {
+ ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
+ if (ret < 0) {
diff --git a/patches/linux-3.7/0145-spi-Export-OF-interfaces-for-capebus-use.patch b/patches/linux-3.7/0145-spi-Export-OF-interfaces-for-capebus-use.patch
new file mode 100644
index 0000000..754ebfb
--- /dev/null
+++ b/patches/linux-3.7/0145-spi-Export-OF-interfaces-for-capebus-use.patch
@@ -0,0 +1,118 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 23 Oct 2012 13:23:14 +0300
+Subject: [PATCH] spi: Export OF interfaces for capebus use.
+
+---
+ drivers/spi/spi.c | 31 +++++++++++++++++++++++--------
+ include/linux/spi/spi.h | 18 ++++++++++++++++++
+ 2 files changed, 41 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 84c2861..f8de2f2 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -801,14 +801,17 @@ err_init_queue:
+ /*-------------------------------------------------------------------------*/
+
+ #if defined(CONFIG_OF) && !defined(CONFIG_SPARC)
++
+ /**
+- * of_register_spi_devices() - Register child devices onto the SPI bus
++ * of_register_node_spi_devices() - Register child devices onto the SPI bus
+ * @master: Pointer to spi_master device
++ * @parent_node: Pointer to the device node containg the devices
+ *
+ * Registers an spi_device for each child node of master node which has a 'reg'
+ * property.
+ */
+-static void of_register_spi_devices(struct spi_master *master)
++void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node)
+ {
+ struct spi_device *spi;
+ struct device_node *nc;
+@@ -816,10 +819,10 @@ static void of_register_spi_devices(struct spi_master *master)
+ int rc;
+ int len;
+
+- if (!master->dev.of_node)
++ if (!parent_node)
+ return;
+
+- for_each_child_of_node(master->dev.of_node, nc) {
++ for_each_child_of_node(parent_node, nc) {
+ /* Alloc an spi_device */
+ spi = spi_alloc_device(master);
+ if (!spi) {
+@@ -884,8 +887,20 @@ static void of_register_spi_devices(struct spi_master *master)
+
+ }
+ }
+-#else
+-static void of_register_spi_devices(struct spi_master *master) { }
++EXPORT_SYMBOL_GPL(of_register_node_spi_devices);
++
++/**
++ * of_register_spi_devices() - Register child devices onto the SPI bus
++ * @master: Pointer to spi_master device
++ *
++ * Registers an spi_device for each child node of master node which has a 'reg'
++ * property.
++ */
++void of_register_spi_devices(struct spi_master *master)
++{
++ of_register_node_spi_devices(master, master->dev.of_node);
++}
++EXPORT_SYMBOL_GPL(of_register_spi_devices);
+ #endif
+
+ static void spi_master_release(struct device *dev)
+@@ -896,12 +911,12 @@ static void spi_master_release(struct device *dev)
+ kfree(master);
+ }
+
+-static struct class spi_master_class = {
++struct class spi_master_class = {
+ .name = "spi_master",
+ .owner = THIS_MODULE,
+ .dev_release = spi_master_release,
+ };
+-
++EXPORT_SYMBOL_GPL(spi_master_class);
+
+
+ /**
+diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
+index fa702ae..618aa5e 100644
+--- a/include/linux/spi/spi.h
++++ b/include/linux/spi/spi.h
+@@ -30,6 +30,8 @@
+ */
+ extern struct bus_type spi_bus_type;
+
++extern struct class spi_master_class;
++
+ /**
+ * struct spi_device - Master side proxy for an SPI slave device
+ * @dev: Driver model representation of the device.
+@@ -856,4 +858,20 @@ spi_unregister_device(struct spi_device *spi)
+ extern const struct spi_device_id *
+ spi_get_device_id(const struct spi_device *sdev);
+
++#if defined(CONFIG_OF) && !defined(CONFIG_SPARC)
++
++void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node);
++
++void of_register_spi_devices(struct spi_master *master);
++
++#else
++
++static inline void of_register_node_spi_devices(struct spi_master *master,
++ struct device_node *parent_node) { }
++
++static inline void of_register_spi_devices(struct spi_master *master) { }
++
++#endif
++
+ #endif /* __LINUX_SPI_H */
diff --git a/patches/linux-3.7/0146-w1-gpio-Pinctrl-fy.patch b/patches/linux-3.7/0146-w1-gpio-Pinctrl-fy.patch
new file mode 100644
index 0000000..6292b73
--- /dev/null
+++ b/patches/linux-3.7/0146-w1-gpio-Pinctrl-fy.patch
@@ -0,0 +1,35 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 24 Oct 2012 09:54:37 +0300
+Subject: [PATCH] w1-gpio: Pinctrl-fy
+
+---
+ drivers/w1/masters/w1-gpio.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index 6012c4e..aec35bd 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -16,6 +16,8 @@
+ #include <linux/gpio.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_gpio.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ #include "../w1.h"
+ #include "../w1_int.h"
+@@ -85,8 +87,13 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ {
+ struct w1_bus_master *master;
+ struct w1_gpio_platform_data *pdata;
++ struct pinctrl *pinctrl;
+ int err;
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ err = w1_gpio_probe_dt(pdev);
+ if (err < 0)
+ return err;
diff --git a/patches/linux-3.7/0147-w1-gpio-Simplify-get-rid-of-defines.patch b/patches/linux-3.7/0147-w1-gpio-Simplify-get-rid-of-defines.patch
new file mode 100644
index 0000000..125cf6d
--- /dev/null
+++ b/patches/linux-3.7/0147-w1-gpio-Simplify-get-rid-of-defines.patch
@@ -0,0 +1,140 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 24 Oct 2012 16:49:53 +0300
+Subject: [PATCH] w1-gpio: Simplify & get rid of defines
+
+---
+ drivers/w1/masters/w1-gpio.c | 58 +++++++++++++++++++-----------------------
+ 1 file changed, 26 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
+index aec35bd..85b363a 100644
+--- a/drivers/w1/masters/w1-gpio.c
++++ b/drivers/w1/masters/w1-gpio.c
+@@ -18,6 +18,7 @@
+ #include <linux/of_gpio.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/err.h>
++#include <linux/of.h>
+
+ #include "../w1.h"
+ #include "../w1_int.h"
+@@ -46,7 +47,6 @@ static u8 w1_gpio_read_bit(void *data)
+ return gpio_get_value(pdata->pin) ? 1 : 0;
+ }
+
+-#ifdef CONFIG_OF
+ static struct of_device_id w1_gpio_dt_ids[] = {
+ { .compatible = "w1-gpio" },
+ {}
+@@ -57,11 +57,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
+ {
+ struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
+- const struct of_device_id *of_id =
+- of_match_device(w1_gpio_dt_ids, &pdev->dev);
+-
+- if (!of_id)
+- return 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+@@ -76,12 +71,6 @@ static int w1_gpio_probe_dt(struct platform_device *pdev)
+
+ return 0;
+ }
+-#else
+-static int w1_gpio_probe_dt(struct platform_device *pdev)
+-{
+- return 0;
+-}
+-#endif
+
+ static int __init w1_gpio_probe(struct platform_device *pdev)
+ {
+@@ -94,28 +83,41 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ if (IS_ERR(pinctrl))
+ dev_warn(&pdev->dev, "unable to select pin group\n");
+
+- err = w1_gpio_probe_dt(pdev);
+- if (err < 0)
+- return err;
++ if (of_have_populated_dt()) {
++ err = w1_gpio_probe_dt(pdev);
++ if (err < 0) {
++ dev_err(&pdev->dev, "Failed to parse DT\n");
++ return err;
++ }
++ }
+
+ pdata = pdev->dev.platform_data;
+
+- if (!pdata)
++ if (!pdata) {
++ dev_err(&pdev->dev, "No configuration data\n");
+ return -ENXIO;
++ }
+
+ master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+- if (!master)
++ if (!master) {
++ dev_err(&pdev->dev, "Out of memory\n");
+ return -ENOMEM;
++ }
+
+ err = gpio_request(pdata->pin, "w1");
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "gpio_request (pin) failed\n");
+ goto free_master;
++ }
+
+ if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
+ err = gpio_request_one(pdata->ext_pullup_enable_pin,
+ GPIOF_INIT_LOW, "w1 pullup");
+- if (err < 0)
++ if (err < 0) {
++ dev_err(&pdev->dev, "gpio_request_one "
++ "(ext_pullup_enable_pin) failed\n");
+ goto free_gpio;
++ }
+ }
+
+ master->data = pdata;
+@@ -130,8 +132,10 @@ static int __init w1_gpio_probe(struct platform_device *pdev)
+ }
+
+ err = w1_add_master_device(master);
+- if (err)
++ if (err) {
++ dev_err(&pdev->dev, "w1_add_master device failed\n");
+ goto free_gpio_ext_pu;
++ }
+
+ if (pdata->enable_external_pullup)
+ pdata->enable_external_pullup(1);
+@@ -205,23 +209,13 @@ static struct platform_driver w1_gpio_driver = {
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(w1_gpio_dt_ids),
+ },
++ .probe = w1_gpio_probe,
+ .remove = __exit_p(w1_gpio_remove),
+ .suspend = w1_gpio_suspend,
+ .resume = w1_gpio_resume,
+ };
+
+-static int __init w1_gpio_init(void)
+-{
+- return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
+-}
+-
+-static void __exit w1_gpio_exit(void)
+-{
+- platform_driver_unregister(&w1_gpio_driver);
+-}
+-
+-module_init(w1_gpio_init);
+-module_exit(w1_gpio_exit);
++module_platform_driver(w1_gpio_driver);
+
+ MODULE_DESCRIPTION("GPIO w1 bus master driver");
+ MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
diff --git a/patches/linux-3.7/0148-arm-dt-Enable-DT-proc-updates.patch b/patches/linux-3.7/0148-arm-dt-Enable-DT-proc-updates.patch
new file mode 100644
index 0000000..a21d13a
--- /dev/null
+++ b/patches/linux-3.7/0148-arm-dt-Enable-DT-proc-updates.patch
@@ -0,0 +1,21 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 26 Oct 2012 16:11:46 +0300
+Subject: [PATCH] arm-dt: Enable DT proc updates.
+
+---
+ arch/arm/include/asm/prom.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
+index aeae9c6..6d65ba2 100644
+--- a/arch/arm/include/asm/prom.h
++++ b/arch/arm/include/asm/prom.h
+@@ -11,6 +11,8 @@
+ #ifndef __ASMARM_PROM_H
+ #define __ASMARM_PROM_H
+
++#define HAVE_ARCH_DEVTREE_FIXUPS
++
+ #ifdef CONFIG_OF
+
+ extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
diff --git a/patches/linux-3.7/0149-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch b/patches/linux-3.7/0149-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
new file mode 100644
index 0000000..ebca33b
--- /dev/null
+++ b/patches/linux-3.7/0149-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
@@ -0,0 +1,56 @@
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Tue, 2 Aug 2011 15:30:09 +0100
+Subject: [PATCH] ARM: CUSTOM: Build a uImage with dtb already appended
+
+Do not commit to mainline; this is a useful hack only for now.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+
+Conflicts:
+
+ arch/arm/Makefile
+---
+ arch/arm/Makefile | 3 +++
+ arch/arm/boot/Makefile | 7 +++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 5f914fc..05df486 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -291,6 +291,9 @@ zImage Image xipImage bootpImage uImage: vmlinux
+ zinstall uinstall install: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+
++uImage-dtb.%:
++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
++
+ %.dtb: scripts
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
+index 9137df5..416fbe9 100644
+--- a/arch/arm/boot/Makefile
++++ b/arch/arm/boot/Makefile
+@@ -57,6 +57,9 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+ $(call if_changed,objcopy)
+ @$(kecho) ' Kernel: $@ is ready'
+
++$(obj)/zImage-dtb.%: $(obj)/%.dtb $(obj)/zImage
++ cat $(obj)/zImage $< > $@
++
+ endif
+
+ targets += $(dtb-y)
+@@ -92,6 +95,10 @@ $(obj)/uImage: $(obj)/zImage FORCE
+ $(call if_changed,uimage)
+ @$(kecho) ' Image $@ is ready'
+
++$(obj)/uImage-dtb.%: $(obj)/zImage-dtb.% FORCE
++ $(call if_changed,uimage)
++ @echo ' Image $@ is ready'
++
+ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
+ $(Q)$(MAKE) $(build)=$(obj)/bootp $@
+ @:
diff --git a/patches/linux-3.7/0150-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch b/patches/linux-3.7/0150-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
new file mode 100644
index 0000000..769e162
--- /dev/null
+++ b/patches/linux-3.7/0150-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
@@ -0,0 +1,500 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Tue, 30 Oct 2012 12:30:18 +0100
+Subject: [PATCH] beaglebone: create a shared dtsi for beaglebone based boards
+ and add a new dts for bonelt
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/Makefile | 3 +-
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 201 +++++++++++++++++++++++++
+ arch/arm/boot/dts/am335x-bone.dts | 233 +----------------------------
+ arch/arm/boot/dts/am335x-bonelt.dts | 17 +++
+ 4 files changed, 221 insertions(+), 233 deletions(-)
+ create mode 100644 arch/arm/boot/dts/am335x-bone-common.dtsi
+ create mode 100644 arch/arm/boot/dts/am335x-bonelt.dts
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index f37cf9f..607114b 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -72,7 +72,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+ omap4-sdp.dtb \
+ omap5-evm.dtb \
+ am335x-evm.dtb \
+- am335x-bone.dtb
++ am335x-bone.dtb \
++ am335x-bonelt.dtb
+ dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+ dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
+ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+new file mode 100644
+index 0000000..e674a19
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -0,0 +1,201 @@
++/*
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/include/ "am33xx.dtsi"
++
++/ {
++ model = "TI AM335x BeagleBone";
++ compatible = "ti,am335x-bone", "ti,am33xx";
++
++ cpus {
++ cpu@0 {
++ cpu0-supply = <&dcdc2_reg>;
++ };
++ };
++
++ memory {
++ device_type = "memory";
++ reg = <0x80000000 0x10000000>; /* 256 MB */
++ };
++
++ am3358_pinmux: pinmux@44e10800 {
++ spi1_pins: pinmux_spi1_pins {
++ pinctrl-single,pins = <
++ 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
++ 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
++ 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
++ 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
++ >;
++ };
++ lcd_pins: pinmux_lcd_pins {
++ pinctrl-single,pins = <
++ 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
++ 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++ gpevt_pins: pinmux_gpevt_pins {
++ pinctrl-single,pins = <
++ 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
++ >;
++ };
++ userled_pins: pinmux_userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ >;
++ };
++ };
++
++ ocp {
++ uart1: serial@44e09000 {
++ status = "okay";
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&userled_pins>;
++
++ led0 {
++ label = "beaglebone:green:usr0";
++ gpios = <&gpio2 21 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ led1 {
++ label = "beaglebone:green:usr1";
++ gpios = <&gpio2 22 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++
++ led2 {
++ label = "beaglebone:green:usr2";
++ gpios = <&gpio2 23 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++
++ led3 {
++ label = "beaglebone:green:usr3";
++ gpios = <&gpio2 24 0>;
++ default-state = "off";
++ };
++ };
++
++ i2c1: i2c@44e0b000 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ };
++
++ gpevt {
++ compatible = "gpevt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&gpevt_pins>;
++ dmas = <&edma 12>;
++ dma-names = "gpioevt";
++ gpio-evt = <&gpio3 2 0>;
++ };
++ };
++
++ backlight {
++ compatible = "pwm-backlight";
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
++};
++
++/include/ "tps65217.dtsi"
++
++&tps {
++ regulators {
++ dcdc1_reg: regulator@0 {
++ regulator-always-on;
++ };
++
++ dcdc2_reg: regulator@1 {
++ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
++ regulator-name = "vdd_mpu";
++ regulator-min-microvolt = <925000>;
++ regulator-max-microvolt = <1325000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ dcdc3_reg: regulator@2 {
++ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
++ regulator-name = "vdd_core";
++ regulator-min-microvolt = <925000>;
++ regulator-max-microvolt = <1150000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ ldo1_reg: regulator@3 {
++ regulator-always-on;
++ };
++
++ ldo2_reg: regulator@4 {
++ regulator-always-on;
++ };
++
++ ldo3_reg: regulator@5 {
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ ldo4_reg: regulator@6 {
++ regulator-always-on;
++ };
++ };
++};
++
++&mmc1 {
++ vmmc-supply = <&ldo3_reg>;
++};
++
++&spi1 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi1_pins>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++};
++
++&edma {
++ ti,edma-xbar-event-map = <32 12>;
++};
++
++&cpsw_emac0 {
++ phy_id = "4a101000.mdio:00";
++};
++
++&cpsw_emac1 {
++ phy_id = "4a101000.mdio:01";
++};
+diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
+index 667842d..7f0b0df 100644
+--- a/arch/arm/boot/dts/am335x-bone.dts
++++ b/arch/arm/boot/dts/am335x-bone.dts
+@@ -8,235 +8,4 @@
+ /dts-v1/;
+
+ /include/ "am33xx.dtsi"
+-
+-/ {
+- model = "TI AM335x BeagleBone";
+- compatible = "ti,am335x-bone", "ti,am33xx";
+-
+- cpus {
+- cpu@0 {
+- cpu0-supply = <&dcdc2_reg>;
+- };
+- };
+-
+- memory {
+- device_type = "memory";
+- reg = <0x80000000 0x10000000>; /* 256 MB */
+- };
+-
+- am3358_pinmux: pinmux@44e10800 {
+- spi1_pins: pinmux_spi1_pins {
+- pinctrl-single,pins = <
+- 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
+- 0x194 0x33 /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+- 0x198 0x13 /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+- 0x19c 0x13 /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+- >;
+- };
+- lcd_pins: pinmux_lcd_pins {
+- pinctrl-single,pins = <
+- 0x1a4 0x17 /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+- 0x1ac 0x17 /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+- gpevt_pins: pinmux_gpevt_pins {
+- pinctrl-single,pins = <
+- 0x090 0x37 /* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+- >;
+- };
+- userled_pins: pinmux_userled_pins {
+- pinctrl-single,pins = <
+- 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
+- 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
+- 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
+- 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+- >;
+- };
+- i2c2_pins: pinmux_i2c2_pins {
+- pinctrl-single,pins = <
+- 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+- 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+- >;
+- };
+- };
+-
+- ocp {
+- uart1: serial@44e09000 {
+- status = "okay";
+- };
+-
+- gpio-leds {
+- compatible = "gpio-leds";
+- pinctrl-names = "default";
+- pinctrl-0 = <&userled_pins>;
+-
+- led0 {
+- label = "beaglebone:green:usr0";
+- gpios = <&gpio2 21 0>;
+- linux,default-trigger = "heartbeat";
+- default-state = "off";
+- };
+-
+- led1 {
+- label = "beaglebone:green:usr1";
+- gpios = <&gpio2 22 0>;
+- linux,default-trigger = "mmc0";
+- default-state = "off";
+- };
+-
+- led2 {
+- label = "beaglebone:green:usr2";
+- gpios = <&gpio2 23 0>;
+- linux,default-trigger = "cpu0";
+- default-state = "off";
+- };
+-
+- led3 {
+- label = "beaglebone:green:usr3";
+- gpios = <&gpio2 24 0>;
+- default-state = "off";
+- };
+- };
+-
+- gpevt {
+- compatible = "gpevt";
+- pinctrl-names = "default";
+- pinctrl-0 = <&gpevt_pins>;
+- dmas = <&edma 12>;
+- dma-names = "gpioevt";
+- gpio-evt = <&gpio3 2 0>;
+- };
+- };
+-
+- backlight {
+- compatible = "pwm-backlight";
+- pwms = <&ehrpwm1 0 500000 0>;
+- pwm-names = "st7735fb";
+- brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+- default-brightness-level = <50>; /* index to the array above */
+- };
+-};
+-
+-&i2c0 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- baseboard_eeprom: baseboard_eeprom@50 {
+- compatible = "at,24c256";
+- reg = <0x50>;
+- };
+-
+-};
+-
+-&i2c2 {
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&i2c2_pins>;
+-
+- clock-frequency = <100000>;
+-
+- /* OK, I know these are cape but for now it will do */
+- cape_eeprom_0: cape_eeprom_0@54 {
+- compatible = "at,24c256";
+- reg = <0x54>;
+- };
+-
+- cape_eeprom_1: cape_eeprom_1@55 {
+- compatible = "at,24c256";
+- reg = <0x55>;
+- };
+-
+- cape_eeprom_2: cape_eeprom_2@56 {
+- compatible = "at,24c256";
+- reg = <0x56>;
+- };
+-
+- cape_eeprom_3: cape_eeprom_3@57 {
+- compatible = "at,24c256";
+- reg = <0x57>;
+- };
+-};
+-
+-/include/ "tps65217.dtsi"
+-
+-&tps {
+- regulators {
+- dcdc1_reg: regulator@0 {
+- regulator-always-on;
+- };
+-
+- dcdc2_reg: regulator@1 {
+- /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+- regulator-name = "vdd_mpu";
+- regulator-min-microvolt = <925000>;
+- regulator-max-microvolt = <1325000>;
+- regulator-boot-on;
+- regulator-always-on;
+- };
+-
+- dcdc3_reg: regulator@2 {
+- /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+- regulator-name = "vdd_core";
+- regulator-min-microvolt = <925000>;
+- regulator-max-microvolt = <1150000>;
+- regulator-boot-on;
+- regulator-always-on;
+- };
+-
+- ldo1_reg: regulator@3 {
+- regulator-always-on;
+- };
+-
+- ldo2_reg: regulator@4 {
+- regulator-always-on;
+- };
+-
+- ldo3_reg: regulator@5 {
+- regulator-min-microvolt = <1800000>;
+- regulator-max-microvolt = <3300000>;
+- regulator-always-on;
+- };
+-
+- ldo4_reg: regulator@6 {
+- regulator-always-on;
+- };
+- };
+-};
+-
+-&mmc1 {
+- vmmc-supply = <&ldo3_reg>;
+-};
+-
+-&spi1 {
+- status = "okay";
+- pinctrl-names = "default";
+- pinctrl-0 = <&spi1_pins>;
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- pinctrl-names = "default";
+- pinctrl-0 = <&lcd_pins>;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+-};
+-
+-&edma {
+- ti,edma-xbar-event-map = <32 12>;
+-};
+-
+-&cpsw_emac0 {
+- phy_id = "4a101000.mdio:00";
+-};
+-
+-&cpsw_emac1 {
+- phy_id = "4a101000.mdio:01";
+-};
++/include/ "am335x-bone-common.dtsi"
+diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts
+new file mode 100644
+index 0000000..03c875f
+--- /dev/null
++++ b/arch/arm/boot/dts/am335x-bonelt.dts
+@@ -0,0 +1,17 @@
++/*
++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++/dts-v1/;
++
++/include/ "am335x-bone-common.dtsi"
++
++&mmc2 {
++ vmmc-supply = <&ldo3_reg>;
++ bus-width = <4>;
++ ti,non-removable;
++ status = "okay";
++};
diff --git a/patches/linux-3.7/0151-beaglebone-enable-emmc-for-bonelt.patch b/patches/linux-3.7/0151-beaglebone-enable-emmc-for-bonelt.patch
new file mode 100644
index 0000000..d0aaa27
--- /dev/null
+++ b/patches/linux-3.7/0151-beaglebone-enable-emmc-for-bonelt.patch
@@ -0,0 +1,48 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Wed, 24 Oct 2012 11:47:13 +0200
+Subject: [PATCH] beaglebone: enable emmc for bonelt
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 1 +
+ arch/arm/boot/dts/am335x-bonelt.dts | 15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index e674a19..99240a5 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -88,6 +88,7 @@
+ label = "beaglebone:green:usr3";
+ gpios = <&gpio2 24 0>;
+ default-state = "off";
++ linux,default-trigger = "mmc1";
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts
+index 03c875f..87257ac 100644
+--- a/arch/arm/boot/dts/am335x-bonelt.dts
++++ b/arch/arm/boot/dts/am335x-bonelt.dts
+@@ -9,6 +9,21 @@
+
+ /include/ "am335x-bone-common.dtsi"
+
++&userled_pins {
++ pinctrl-single,pins = <
++ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */
++ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */
++ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */
++ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
++ 0x00c 0x31 /* P8_6 gpmc_ad3.mmc1_dat1 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x008 0x31 /* P8_5 gpmc_ad2.mmc1_dat2 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x004 0x31 /* P8_24 gpmc_ad1.mmc1_dat1 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x000 0x31 /* P8_25 gpmc_ad0.mmc1_dat0 PIN_INPUT_PULLUP | OMAP_MUX_MODE1 */
++ 0x084 0x32 /* P8_20 gpmc_csn2.mmc1_cmd OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP} */
++ 0x080 0x32 /* P8_21 gpmc_csn1.immc1_clk OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP} */
++ >;
++};
++
+ &mmc2 {
+ vmmc-supply = <&ldo3_reg>;
+ bus-width = <4>;
diff --git a/patches/linux-3.7/0152-da8xx-dt-Create-da8xx-DT-adapter-device.patch b/patches/linux-3.7/0152-da8xx-dt-Create-da8xx-DT-adapter-device.patch
new file mode 100644
index 0000000..06ea0b4
--- /dev/null
+++ b/patches/linux-3.7/0152-da8xx-dt-Create-da8xx-DT-adapter-device.patch
@@ -0,0 +1,232 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 1 Nov 2012 15:19:35 +0200
+Subject: [PATCH] da8xx-dt: Create da8xx DT adapter device
+
+omap_device is going private.
+
+Move the da8xx-dt adapter device to arch/arm/mach-omap2.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/Makefile | 3 +
+ arch/arm/mach-omap2/da8xx-dt.c | 197 ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 200 insertions(+)
+ create mode 100644 arch/arm/mach-omap2/da8xx-dt.c
+
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index fe40d9e..3a9a0ff 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -200,6 +200,9 @@ ifneq ($(CONFIG_DRM_OMAP),)
+ obj-y += drm.o
+ endif
+
++# AM3XX Device Tree adapters for legacy drivers
++obj-$(CONFIG_SOC_AM33XX) += da8xx-dt.o
++
+ # Specific board support
+ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
+diff --git a/arch/arm/mach-omap2/da8xx-dt.c b/arch/arm/mach-omap2/da8xx-dt.c
+new file mode 100644
+index 0000000..d3c6f48
+--- /dev/null
++++ b/arch/arm/mach-omap2/da8xx-dt.c
+@@ -0,0 +1,197 @@
++/*
++ * DA8XX-DT: Device tree adapter using the legacy driver
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <video/da8xx-fb.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/clk.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++
++struct da8xx_priv {
++ struct da8xx_lcdc_platform_data lcd_pdata;
++ struct lcd_ctrl_config lcd_cfg;
++ struct display_panel lcd_panel;
++ struct platform_device *lcdc_pdev;
++ struct omap_hwmod *lcdc_oh;
++ struct resource lcdc_res[1];
++ int power_dn_gpio;
++};
++
++static const struct of_device_id of_da8xx_dt_match[] = {
++ { .compatible = "da8xx-dt", },
++ {},
++};
++
++static int __devinit da8xx_dt_probe(struct platform_device *pdev)
++{
++ struct da8xx_priv *priv;
++ struct clk *disp_pll;
++ struct pinctrl *pinctrl;
++ u32 disp_pll_val;
++ const char *panel_type;
++ int ret = -EINVAL;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++ priv->power_dn_gpio = -1;
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ ret = of_property_read_u32(pdev->dev.of_node, "disp-pll",
++ &disp_pll_val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read disp-pll property\n");
++ return ret;
++ }
++
++ ret = of_property_read_string(pdev->dev.of_node, "panel-type",
++ &panel_type);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read panel-type property\n");
++ return ret;
++ }
++
++ /* conf_disp_pll(disp_pll); */
++ disp_pll = clk_get(NULL, "dpll_disp_ck");
++ if (IS_ERR(disp_pll)) {
++ dev_err(&pdev->dev, "Cannot clk_get disp_pll\n");
++ return PTR_ERR(disp_pll);
++ }
++ ret = clk_set_rate(disp_pll, disp_pll_val);
++ clk_put(disp_pll);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to set disp_pll\n");
++ return ret;
++ }
++
++ ret = of_get_named_gpio_flags(pdev->dev.of_node, "powerdn-gpio",
++ 0, NULL);
++ if (IS_ERR_VALUE(ret)) {
++ dev_info(&pdev->dev, "No power down GPIO\n");
++ } else {
++ priv->power_dn_gpio = ret;
++
++ ret = devm_gpio_request(&pdev->dev, priv->power_dn_gpio,
++ "da8xx-dt:PDN");
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to gpio_request\n");
++ return ret;
++ }
++
++ ret = gpio_direction_output(priv->power_dn_gpio, 1);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to set powerdn to 1\n");
++ return ret;
++ }
++ }
++
++ /* display_panel */
++ priv->lcd_panel.panel_type = QVGA;
++ priv->lcd_panel.max_bpp = 16;
++ priv->lcd_panel.min_bpp = 16;
++ priv->lcd_panel.panel_shade = COLOR_ACTIVE;
++
++ /* lcd_ctrl_config */
++ priv->lcd_cfg.p_disp_panel = &priv->lcd_panel;
++ priv->lcd_cfg.ac_bias = 255;
++ priv->lcd_cfg.ac_bias_intrpt = 0;
++ priv->lcd_cfg.dma_burst_sz = 16;
++ priv->lcd_cfg.bpp = 16;
++ priv->lcd_cfg.fdd = 0x80;
++ priv->lcd_cfg.tft_alt_mode = 0;
++ priv->lcd_cfg.stn_565_mode = 0;
++ priv->lcd_cfg.mono_8bit_mode = 0;
++ priv->lcd_cfg.invert_line_clock = 1;
++ priv->lcd_cfg.invert_frm_clock = 1;
++ priv->lcd_cfg.sync_edge = 0;
++ priv->lcd_cfg.sync_ctrl = 1;
++ priv->lcd_cfg.raster_order = 0;
++
++ /* da8xx_lcdc_platform_data */
++ strcpy(priv->lcd_pdata.manu_name, "BBToys");
++ priv->lcd_pdata.controller_data = &priv->lcd_cfg;
++ strcpy(priv->lcd_pdata.type, panel_type);
++
++ priv->lcdc_oh = omap_hwmod_lookup("lcdc");
++ if (priv->lcdc_oh == NULL) {
++ dev_err(&pdev->dev, "Failed to lookup omap_hwmod lcdc\n");
++ return -ENODEV;
++ }
++
++ priv->lcdc_pdev = omap_device_build("da8xx_lcdc", 0, priv->lcdc_oh,
++ &priv->lcd_pdata,
++ sizeof(struct da8xx_lcdc_platform_data),
++ NULL, 0, 0);
++ if (priv->lcdc_pdev == NULL) {
++ dev_err(&pdev->dev, "Failed to build LCDC device\n");
++ return -ENODEV;
++ }
++
++ dev_info(&pdev->dev, "Registered bone LCDC OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++}
++
++static int __devexit da8xx_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver da8xx_dt_driver = {
++ .probe = da8xx_dt_probe,
++ .remove = __devexit_p(da8xx_dt_remove),
++ .driver = {
++ .name = "da8xx-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_da8xx_dt_match,
++ },
++};
++
++static __init int da8xx_dt_init(void)
++{
++ return platform_driver_register(&da8xx_dt_driver);
++}
++
++static __exit void da8xx_dt_exit(void)
++{
++ platform_driver_unregister(&da8xx_dt_driver);
++}
++
++postcore_initcall(da8xx_dt_init);
++module_exit(da8xx_dt_exit);
diff --git a/patches/linux-3.7/0153-ti-tscadc-dt-Create-ti-tscadc-dt-DT-adapter-device.patch b/patches/linux-3.7/0153-ti-tscadc-dt-Create-ti-tscadc-dt-DT-adapter-device.patch
new file mode 100644
index 0000000..28e6ac6
--- /dev/null
+++ b/patches/linux-3.7/0153-ti-tscadc-dt-Create-ti-tscadc-dt-DT-adapter-device.patch
@@ -0,0 +1,188 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Thu, 1 Nov 2012 15:44:39 +0200
+Subject: [PATCH] ti-tscadc-dt: Create ti-tscadc-dt DT adapter device
+
+omap_device is going private.
+
+Move the ti-tscadc-dt adapter device to arch/arm/mach-omap2.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/mach-omap2/Makefile | 1 +
+ arch/arm/mach-omap2/ti-tscadc-dt.c | 155 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 156 insertions(+)
+ create mode 100644 arch/arm/mach-omap2/ti-tscadc-dt.c
+
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 3a9a0ff..1eab37b 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -202,6 +202,7 @@ endif
+
+ # AM3XX Device Tree adapters for legacy drivers
+ obj-$(CONFIG_SOC_AM33XX) += da8xx-dt.o
++obj-$(CONFIG_SOC_AM33XX) += ti-tscadc-dt.o
+
+ # Specific board support
+ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
+diff --git a/arch/arm/mach-omap2/ti-tscadc-dt.c b/arch/arm/mach-omap2/ti-tscadc-dt.c
+new file mode 100644
+index 0000000..0a1a17a
+--- /dev/null
++++ b/arch/arm/mach-omap2/ti-tscadc-dt.c
+@@ -0,0 +1,155 @@
++/*
++ * TI-TSCADC-DT: Device tree adapter using the legacy driver
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/clk.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++
++struct ti_tscadc_priv {
++ struct omap_hwmod *tsc_oh;
++ struct tsc_data tsc_data;
++ struct adc_data adc_data;
++ struct mfd_tscadc_board tscadc_data;
++ struct platform_device *tscadc_pdev;
++};
++
++static const struct of_device_id of_ti_tscadc_dt_match[] = {
++ { .compatible = "ti-tscadc-dt", },
++ {},
++};
++
++static int __devinit ti_tscadc_dt_probe(struct platform_device *pdev)
++{
++ struct ti_tscadc_priv *priv;
++ struct pinctrl *pinctrl;
++ u32 val;
++ int ret;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev,
++ "pins are not configured from the driver\n");
++
++ ret = of_property_read_u32(pdev->dev.of_node, "tsc-wires", &val);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "no tsc-wires property; disabling TSC\n");
++ val = 0;
++ }
++ priv->tsc_data.wires = val;
++
++ if (priv->tsc_data.wires > 0) {
++ ret = of_property_read_u32(pdev->dev.of_node,
++ "tsc-x-plate-resistance", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read "
++ "tsc-x-plate-resistance property\n");
++ return ret;
++ }
++ priv->tsc_data.x_plate_resistance = val;
++
++ ret = of_property_read_u32(pdev->dev.of_node,
++ "tsc-steps", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to read "
++ "tsc-steps property\n");
++ return ret;
++ }
++ priv->tsc_data.steps_to_configure = val;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "adc-channels", &val);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "No adc-channels property; "
++ "disabling adc\n");
++ val = 0;
++ }
++ priv->adc_data.adc_channels = val;
++
++ priv->tscadc_data.tsc_init = &priv->tsc_data;
++ priv->tscadc_data.adc_init = &priv->adc_data;
++
++ priv->tsc_oh = omap_hwmod_lookup("adc_tsc");
++ if (priv->tsc_oh == NULL) {
++ dev_err(&pdev->dev, "Could not lookup HWMOD %s\n", "adc_tsc");
++ return -ENODEV;
++ }
++
++ priv->tscadc_pdev = omap_device_build("ti_tscadc", -1, priv->tsc_oh,
++ &priv->tscadc_data, sizeof(priv->tscadc_data),
++ NULL, 0, 0);
++ if (priv->tscadc_pdev == NULL) {
++ dev_err(&pdev->dev, "Could not create tsc_adc device\n");
++ return -ENODEV;
++ }
++
++ dev_info(&pdev->dev, "TI tscadc pdev created OK\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++}
++
++static int __devexit ti_tscadc_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver ti_tscadc_dt_driver = {
++ .probe = ti_tscadc_dt_probe,
++ .remove = __devexit_p(ti_tscadc_dt_remove),
++ .driver = {
++ .name = "ti_tscadc-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_ti_tscadc_dt_match,
++ },
++};
++
++static __init int ti_tscadc_dt_init(void)
++{
++ return platform_driver_register(&ti_tscadc_dt_driver);
++}
++
++static __exit void ti_tscadc_dt_exit(void)
++{
++ platform_driver_unregister(&ti_tscadc_dt_driver);
++}
++
++postcore_initcall(ti_tscadc_dt_init);
++module_exit(ti_tscadc_dt_exit);
diff --git a/patches/linux-3.7/0154-capebus-Core-capebus-support.patch b/patches/linux-3.7/0154-capebus-Core-capebus-support.patch
new file mode 100644
index 0000000..14b1f73
--- /dev/null
+++ b/patches/linux-3.7/0154-capebus-Core-capebus-support.patch
@@ -0,0 +1,1395 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:06:06 +0200
+Subject: [PATCH] capebus: Core capebus support
+
+Introducing capebus; a bus that allows small boards (capes) to connect
+to a complex SoC using simple expansion connectors.
+
+Up to now to support these kind of boards, one had to hack the board files,
+and do all sort of gymnastics to handle all the different cases of
+conflict resolution.
+
+Capebus provides abstractions that keep the pain to a minimum.
+
+This part of the series is introducing the core capebus functionality
+dealing with the basic bus & driver probe functions.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/Kconfig | 2 +
+ drivers/Makefile | 3 +
+ drivers/capebus/Kconfig | 17 ++
+ drivers/capebus/Makefile | 8 +
+ drivers/capebus/capebus-driver.c | 608 ++++++++++++++++++++++++++++++++++++++
+ drivers/capebus/capebus-probe.c | 320 ++++++++++++++++++++
+ drivers/capebus/capebus-sysfs.c | 52 ++++
+ include/linux/capebus.h | 298 +++++++++++++++++++
+ 8 files changed, 1308 insertions(+)
+ create mode 100644 drivers/capebus/Kconfig
+ create mode 100644 drivers/capebus/Makefile
+ create mode 100644 drivers/capebus/capebus-driver.c
+ create mode 100644 drivers/capebus/capebus-probe.c
+ create mode 100644 drivers/capebus/capebus-sysfs.c
+ create mode 100644 include/linux/capebus.h
+
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index dbdefa3..bfbe1d1 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -156,4 +156,6 @@ source "drivers/pwm/Kconfig"
+
+ source "drivers/irqchip/Kconfig"
+
++source "drivers/capebus/Kconfig"
++
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index a16a8d0..d7a103b 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -145,3 +145,6 @@ obj-$(CONFIG_EXTCON) += extcon/
+ obj-$(CONFIG_MEMORY) += memory/
+ obj-$(CONFIG_IIO) += iio/
+ obj-$(CONFIG_VME_BUS) += vme/
++
++# Capebus
++obj-$(CONFIG_CAPEBUS) += capebus/
+diff --git a/drivers/capebus/Kconfig b/drivers/capebus/Kconfig
+new file mode 100644
+index 0000000..cea1b68
+--- /dev/null
++++ b/drivers/capebus/Kconfig
+@@ -0,0 +1,17 @@
++#
++# Capebus core support
++#
++
++menu "CAPEBUS support"
++
++config CAPEBUS
++ bool "Capebus support"
++ default n
++ help
++ Enable to support capebus devices.
++
++source "drivers/capebus/boards/Kconfig"
++
++source "drivers/capebus/capes/Kconfig"
++
++endmenu
+diff --git a/drivers/capebus/Makefile b/drivers/capebus/Makefile
+new file mode 100644
+index 0000000..45aa303
+--- /dev/null
++++ b/drivers/capebus/Makefile
+@@ -0,0 +1,8 @@
++#
++# Makefile for CAPEBUS devices
++#
++
++obj-$(CONFIG_CAPEBUS) += capebus-probe.o \
++ capebus-driver.o capebus-sysfs.o
++obj-$(CONFIG_CAPEBUS) += boards/
++obj-$(CONFIG_CAPEBUS) += capes/
+diff --git a/drivers/capebus/capebus-driver.c b/drivers/capebus/capebus-driver.c
+new file mode 100644
+index 0000000..82b1d1b
+--- /dev/null
++++ b/drivers/capebus/capebus-driver.c
+@@ -0,0 +1,608 @@
++/*
++ * Capebus driver infrastructure
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/mempolicy.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/cpu.h>
++#include <linux/pm_runtime.h>
++#include <linux/suspend.h>
++
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_platform.h>
++
++#include <linux/capebus.h>
++
++/**
++ * capebus_match_device - Tell if a cape device structure has a
++ * matching cape device id structure
++ * @drv: the cape driver to match against
++ * @dev: the cape device structure to match against
++ *
++ * Used by a driver to check whether a cape device present in the
++ * system is in its list of supported devices. Returns the matching
++ * cape_device_id structure or %NULL if there is no match.
++ */
++static const struct cape_device_id *capebus_match_device(
++ struct cape_driver *drv, struct cape_dev *dev)
++{
++ struct cape_bus *bus = dev->bus;
++ struct cape_slot *slot = dev->slot;
++
++ BUG_ON(bus == NULL);
++ BUG_ON(slot == NULL);
++ BUG_ON(bus->ops == NULL);
++ BUG_ON(bus->ops->get_dev_id == NULL);
++
++ return bus->ops->get_dev_id(slot);
++}
++
++/**
++ * capebus_device_probe - check if a driver wants to claim a
++ * specific cape device
++ * @dev: cape device being probed
++ *
++ * returns 0 on success, else error.
++ * side-effect: cape_dev->driver is set to drv when drv claims cape_dev.
++ */
++static int capebus_device_probe(struct device *dev)
++{
++ const struct cape_device_id *id;
++ int error = 0;
++ struct cape_driver *drv;
++ struct cape_dev *cape_dev;
++ struct device *parent;
++
++ drv = to_cape_driver(dev->driver);
++ cape_dev = to_cape_dev(dev);
++ cape_dev = capebus_dev_get(cape_dev);
++
++ /* sanity checks */
++ if (cape_dev == NULL ||
++ cape_dev->bus == NULL || cape_dev->bus->ops == NULL ||
++ cape_dev->driver != NULL || drv->probe == NULL) {
++ error = -EINVAL;
++ goto err_no_sanity;
++ }
++
++ id = capebus_match_device(drv, cape_dev);
++ if (!id) {
++ error = -ENODEV;
++ goto err_no_match;
++ }
++
++ /* The parent device must be in active state when probing */
++ parent = cape_dev->dev.parent;
++ if (parent)
++ pm_runtime_get_sync(parent);
++
++ /* Unbound cape devices are always set to disabled and suspended.
++ * During probe, the device is set to enabled and active and the
++ * usage count is incremented. If the driver supports runtime PM,
++ * it should call pm_runtime_put_noidle() in its probe routine and
++ * pm_runtime_get_noresume() in its remove routine.
++ */
++ pm_runtime_get_noresume(&cape_dev->dev);
++ pm_runtime_set_active(&cape_dev->dev);
++ pm_runtime_enable(&cape_dev->dev);
++
++ /* call the driver's probe method */
++ error = drv->probe(cape_dev, id);
++
++ /* release the parent no matter what */
++ if (parent)
++ pm_runtime_put(parent);
++
++ if (error != 0)
++ goto err_probe_fail;
++
++ /* call the probed bus method */
++ if (cape_dev->bus->ops->dev_probed != NULL) {
++ error = cape_dev->bus->ops->dev_probed(cape_dev);
++ if (error != 0)
++ goto err_dev_probed_fail;
++ }
++
++ /* all is fine... */
++ cape_dev->driver = drv;
++ cape_dev->added = 1;
++
++ return 0;
++
++err_dev_probed_fail:
++ if (drv->remove) {
++ pm_runtime_get_sync(&cape_dev->dev);
++ drv->remove(cape_dev);
++ pm_runtime_put_noidle(&cape_dev->dev);
++ }
++err_probe_fail:
++ pm_runtime_disable(&cape_dev->dev);
++ pm_runtime_set_suspended(&cape_dev->dev);
++ pm_runtime_put_noidle(&cape_dev->dev);
++err_no_match:
++ /* nothing */
++err_no_sanity:
++ capebus_dev_put(cape_dev);
++ return error;
++}
++
++static int capebus_device_remove(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *drv = cape_dev->driver;
++
++ if (drv) {
++ /* call the removed bus method (if added prev.) */
++ if (cape_dev->added) {
++ BUG_ON(cape_dev->bus == NULL);
++ BUG_ON(cape_dev->bus->ops == NULL);
++ if (cape_dev->bus->ops->dev_removed)
++ cape_dev->bus->ops->dev_removed(cape_dev);
++ cape_dev->added = 0;
++ }
++ if (drv->remove) {
++ pm_runtime_get_sync(dev);
++ drv->remove(cape_dev);
++ pm_runtime_put_noidle(dev);
++ }
++ cape_dev->driver = NULL;
++ }
++
++ /* Undo the runtime PM settings in local_capebus_probe() */
++ pm_runtime_disable(dev);
++ pm_runtime_set_suspended(dev);
++ pm_runtime_put_noidle(dev);
++
++ capebus_dev_put(cape_dev);
++ return 0;
++}
++
++static void capebus_device_shutdown(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *drv = cape_dev->driver;
++
++ if (drv && drv->shutdown)
++ drv->shutdown(cape_dev);
++
++ capebus_disable_device(cape_dev);
++
++ if (!device_may_wakeup(dev))
++ capebus_enable_wake(cape_dev, false);
++}
++
++static int capebus_bus_match(struct device *dev, struct device_driver *drv);
++static int capebus_device_probe(struct device *dev);
++static int capebus_device_remove(struct device *dev);
++static void capebus_device_shutdown(struct device *dev);
++
++struct bus_type capebus_bus_type = {
++ .name = "capebus",
++ .match = capebus_bus_match,
++ .probe = capebus_device_probe,
++ .remove = capebus_device_remove,
++ .shutdown = capebus_device_shutdown,
++ .dev_attrs = capebus_dev_attrs,
++ .bus_attrs = capebus_bus_attrs,
++ .pm = NULL, /* No PM for now */
++};
++EXPORT_SYMBOL(capebus_bus_type);
++
++/**
++ * __capebus_register_driver - register a new capebus driver
++ * @drv: the driver structure to register
++ * @owner: owner module of drv
++ * @mod_name: module name string
++ *
++ * Adds the driver structure to the list of registered drivers.
++ * Returns a negative value on error, otherwise 0.
++ * If no error occurred, the driver remains registered even if
++ * no device was claimed during registration.
++ */
++int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
++ const char *mod_name)
++{
++ /* initialize common driver fields */
++ drv->driver.bus = &capebus_bus_type;
++ drv->driver.owner = owner;
++ drv->driver.mod_name = mod_name;
++
++ /* register with core */
++ return driver_register(&drv->driver);
++}
++EXPORT_SYMBOL(__capebus_register_driver);
++
++/**
++ * capebus_unregister_driver - unregister a capebus driver
++ * @drv: the driver structure to unregister
++ *
++ * Deletes the driver structure from the list of registered cape drivers,
++ * gives it a chance to clean up by calling its remove() function for
++ * each device it was responsible for, and marks those devices as
++ * driverless.
++ */
++
++void
++capebus_unregister_driver(struct cape_driver *drv)
++{
++ /* TODO: not really working properly */
++ driver_unregister(&drv->driver);
++}
++EXPORT_SYMBOL(capebus_unregister_driver);
++
++/**
++ * capebus_bus_match - Tell if a cape device structure has a matching
++ * cape device id structure
++ * @dev: the cape device structure to match against
++ * @drv: the device driver to search for matching cape device id structures
++ *
++ * Used by a driver to check whether a cape device present in the
++ * system is in its list of supported devices. Returns the matching
++ * cape_device_id structure or %NULL if there is no match.
++ */
++static int capebus_bus_match(struct device *dev, struct device_driver *drv)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++ struct cape_driver *cape_drv = to_cape_driver(drv);
++ const struct cape_device_id *found_id;
++
++ found_id = capebus_match_device(cape_drv, cape_dev);
++ if (found_id)
++ return 1;
++
++ return 0;
++}
++
++/**
++ * capebus_dev_get - increments the reference count of the capebus
++ * device structure
++ * @dev: the device being referenced
++ *
++ * Each live reference to a device should be refcounted.
++ *
++ * Drivers for cape devices should normally record such references in
++ * their probe() methods, when they bind to a device, and release
++ * them by calling capebus_dev_put(), in their disconnect() methods.
++ *
++ * A pointer to the device with the incremented reference counter is returned.
++ */
++struct cape_dev *capebus_dev_get(struct cape_dev *dev)
++{
++ if (dev)
++ get_device(&dev->dev);
++ return dev;
++}
++EXPORT_SYMBOL(capebus_dev_get);
++
++/**
++ * capebus_dev_put - release a use of the capebus 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 capebus_dev_put(struct cape_dev *dev)
++{
++ if (dev)
++ put_device(&dev->dev);
++}
++EXPORT_SYMBOL(capebus_dev_put);
++
++static int __init capebus_driver_init(void)
++{
++ return bus_register(&capebus_bus_type);
++}
++
++postcore_initcall(capebus_driver_init);
++
++const struct of_device_id *
++capebus_of_match_device(struct cape_dev *cdev,
++ const char *property, const char *value)
++{
++ struct cape_bus *bus = cdev->bus;
++ struct device *dev = &cdev->dev;
++ struct device_node *pnode = cape_bus_to_parent_of_node(bus);
++ struct device_node *node;
++ const struct of_device_id *match;
++ const char* cp;
++ int cplen, l;
++
++ dev_dbg(dev, "Iterating on parent of node "
++ "name='%s' type='%s' full_name='%s'\n",
++ pnode->name, pnode->type, pnode->full_name);
++
++ match = NULL;
++ for_each_child_of_node(pnode, node) {
++
++ dev->of_node = node;
++ match = of_match_device(dev->driver->of_match_table, dev);
++ if (!match)
++ goto next_node;
++
++ cp = of_get_property(node, property, &cplen);
++ if (cp == NULL)
++ goto next_node;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, value, strlen(value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* matched */
++ if (cplen > 0)
++ break;
++next_node:
++ match = NULL;
++ dev->of_node = NULL;
++ }
++
++ if (match == NULL) {
++ dev_dbg(dev, "Failed to find matching child-node\n");
++ return NULL;
++ }
++
++ dev_dbg(dev, "Found matching child node "
++ "name='%s' type='%s' "
++ "full_name='%s' (compatible='%s')\n",
++ node->name, node->type, node->full_name,
++ match->compatible);
++
++ return match;
++}
++EXPORT_SYMBOL(capebus_of_match_device);
++
++struct device_node *
++capebus_of_compatible_device_property_match(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *prop, const char *prop_value)
++{
++ const struct of_device_id *match;
++ struct device_node *node, *cnode;
++ const char* cp;
++ int cplen, l;
++
++ if (prop == NULL || prop_value == NULL)
++ goto try_non_property;
++
++ /* at first try secondary match */
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ cp = of_get_property(node, prop, &cplen);
++ if (cp == NULL)
++ continue;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, prop_value,
++ strlen(prop_value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* not matched */
++ if (cplen <= 0)
++ continue;
++
++ /* now iterate in the children nodes */
++ for_each_child_of_node(node, cnode) {
++
++ match = of_match_node(matches, cnode);
++ if (match) {
++ /* release reference to parent, keep this one */
++ of_node_put(node);
++ return cnode;
++ }
++ }
++ }
++
++try_non_property:
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ match = of_match_node(matches, node);
++ if (match)
++ return node;
++ }
++
++ return NULL;
++}
++EXPORT_SYMBOL(capebus_of_compatible_device_property_match);
++
++struct platform_device *
++capebus_of_platform_compatible_device_create(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *pdev_name,
++ const char *prop, const char *prop_value)
++{
++ struct device_node *node;
++ struct platform_device *pdev;
++
++ node = capebus_of_compatible_device_property_match(dev, matches, prop,
++ prop_value);
++ if (node == NULL)
++ return ERR_PTR(-ENXIO);
++
++ pdev = of_platform_device_create(node, pdev_name, dev->bus->dev.parent);
++
++ /* release the reference to the node */
++ of_node_put(node);
++ node = NULL;
++
++ if (pdev == NULL) {
++ dev_err(&dev->dev, "Failed to create platform device '%s'\n",
++ pdev_name);
++ return ERR_PTR(-ENODEV);
++ }
++
++ return pdev;
++}
++EXPORT_SYMBOL(capebus_of_platform_compatible_device_create);
++
++struct device_node *
++capebus_of_find_property_node(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name)
++{
++ struct device_node *node;
++ const char* cp;
++ int cplen, l;
++ struct property *pp;
++
++ node = NULL;
++ if (prop == NULL || prop_value == NULL)
++ goto find_direct;
++
++ /* at first try secondary match */
++ for_each_child_of_node(dev->dev.of_node, node) {
++
++ cp = of_get_property(node, prop, &cplen);
++ if (cp == NULL)
++ continue;
++
++ while (cplen > 0) {
++ if (of_compat_cmp(cp, prop_value,
++ strlen(prop_value)) == 0)
++ break;
++ l = strlen(cp) + 1;
++ cp += l;
++ cplen -= l;
++ }
++
++ /* not matched */
++ if (cplen <= 0)
++ continue;
++
++ /* found ? */
++ pp = of_find_property(node, name, NULL);
++ if (pp != NULL)
++ return node;
++ }
++find_direct:
++ pp = of_find_property(dev->dev.of_node, name, NULL);
++ if (pp == NULL)
++ return NULL;
++
++ return of_node_get(dev->dev.of_node);
++}
++EXPORT_SYMBOL_GPL(capebus_of_find_property_node);
++
++struct property *
++capebus_of_find_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp)
++{
++ struct device_node *node;
++ struct property *pp;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ if (node == NULL)
++ return NULL;
++
++ pp = of_find_property(node, name, lenp);
++
++ of_node_put(node);
++
++ return pp;
++}
++EXPORT_SYMBOL_GPL(capebus_of_find_property);
++
++const void *capebus_of_get_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp)
++{
++ struct property *pp;
++
++ pp = capebus_of_find_property(dev, prop, prop_value, name, lenp);
++ return pp ? pp->value : NULL;
++}
++EXPORT_SYMBOL_GPL(capebus_of_get_property);
++
++/* node exists, but it's not available? make it so */
++int capebus_of_device_node_enable(struct device_node *node)
++{
++ struct property *prop;
++ int ret;
++
++ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
++ if (prop == NULL)
++ goto err_no_prop_mem;
++
++ prop->name = kstrdup("status", GFP_KERNEL);
++ if (prop->name == NULL)
++ goto err_no_name_mem;
++
++ prop->value = kstrdup("okay", GFP_KERNEL);
++ if (prop->value == NULL)
++ goto err_no_value_mem;
++
++ prop->length = strlen(prop->value) + 1;
++ set_bit(OF_DYNAMIC, &prop->_flags);
++
++ ret = prom_update_property(node, prop);
++ if (ret != 0)
++ goto err_update_failed;
++
++ return 0;
++
++err_update_failed:
++ kfree(prop->value);
++err_no_value_mem:
++ kfree(prop->name);
++err_no_name_mem:
++ kfree(prop);
++err_no_prop_mem:
++ return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(capebus_of_device_node_enable);
++
++/* Make sure this node is activated (even if it was disabled) */
++int capebus_of_platform_device_enable(struct device_node *node)
++{
++ struct platform_device *pdev, *ppdev;
++ int ret;
++
++ if (of_device_is_available(node))
++ return 0;
++
++ ret = capebus_of_device_node_enable(node);
++ if (ret != 0)
++ return ret;
++
++ /* now we need to find the parent of the node */
++ ppdev = of_find_device_by_node(node->parent);
++
++ pdev = of_platform_device_create(node, NULL,
++ ppdev ? &ppdev->dev : NULL);
++ if (IS_ERR_OR_NULL(pdev)) {
++ ret = pdev ? PTR_ERR(pdev) : -ENODEV;
++ return ret;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(capebus_of_platform_device_enable);
+diff --git a/drivers/capebus/capebus-probe.c b/drivers/capebus/capebus-probe.c
+new file mode 100644
+index 0000000..b46e915
+--- /dev/null
++++ b/drivers/capebus/capebus-probe.c
+@@ -0,0 +1,320 @@
++/*
++ * Capebus bus infrastructure
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_i2c.h>
++#include <linux/of_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/err.h>
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++
++#include <linux/capebus.h>
++
++LIST_HEAD(cape_buses);
++EXPORT_SYMBOL(cape_buses);
++
++DEFINE_MUTEX(cape_buses_mutex);
++EXPORT_SYMBOL(cape_buses_mutex);
++
++/*
++ * Cape Bus Class
++ */
++static void release_capebus_dev(struct device *dev)
++{
++ struct cape_dev *cape_dev = to_cape_dev(dev);
++
++ kfree(cape_dev);
++}
++
++static struct class capebus_class = {
++ .name = "capebus",
++ .dev_release = &release_capebus_dev,
++};
++
++static int __init capebus_class_init(void)
++{
++ return class_register(&capebus_class);
++}
++postcore_initcall(capebus_class_init);
++
++static struct cape_bus *cape_bus_find(const char *name, int busno)
++{
++ struct cape_bus *bus;
++ int found;
++
++ if (busno < 0)
++ return NULL;
++
++ found = 0;
++ cape_bus_for_each(bus) {
++ if (strcmp(name, bus->name) == 0 && bus->busno == busno) {
++ found = 1;
++ break;
++ }
++ }
++ return found ? bus : NULL;
++}
++
++static int cape_bus_pick_busno(const char *name, int busno)
++{
++ struct cape_bus *bus;
++
++ BUG_ON(name == NULL);
++
++ /* fixed id */
++ if (busno >= 0)
++ return busno;
++
++ /* dynamic id */
++ busno = -1;
++ cape_bus_for_each(bus) {
++ /* name must match */
++ if (strcmp(name, bus->name) != 0)
++ continue;
++ busno = max(busno, bus->busno);
++ }
++ return busno + 1;
++}
++
++int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
++ struct device *parent, struct cape_bus_ops *ops)
++{
++ struct cape_bus *b2;
++ int r;
++
++ if (name == NULL)
++ return -EINVAL;
++
++ INIT_LIST_HEAD(&bus->node);
++ INIT_LIST_HEAD(&bus->devices);
++ INIT_LIST_HEAD(&bus->slots);
++
++ /* do everything under lock */
++ mutex_lock(&cape_buses_mutex);
++
++ b2 = cape_bus_find(name, busno);
++ if (b2 != NULL) {
++ if (parent != NULL)
++ dev_err(parent, "capebus %s:%d in use\n", name, busno);
++ else
++ pr_err("capebus %s:%d in use\n", name, busno);
++ r = -EBUSY;
++ goto err_unlock;
++ }
++ bus->name = name;
++ bus->busno = cape_bus_pick_busno(name, busno);
++ bus->ops = ops;
++
++ bus->dev.class = &capebus_class;
++ bus->dev.parent = parent;
++ dev_set_name(&bus->dev, "%s:%d", bus->name, bus->busno);
++ r = device_register(&bus->dev);
++ if (r != 0) {
++ if (parent != NULL)
++ dev_err(parent, "capebus #%d failed to register dev\n",
++ bus->busno);
++ else
++ pr_err("capebus #%d failed to register dev\n",
++ bus->busno);
++ goto err_unlock;
++ }
++
++ list_add_tail(&bus->node, &cape_buses);
++ mutex_unlock(&cape_buses_mutex);
++
++ dev_info(&bus->dev, "Registered\n");
++
++ return 0;
++err_unlock:
++ mutex_unlock(&cape_buses_mutex);
++ return r;
++}
++
++int cape_bus_deregister(struct cape_bus *bus)
++{
++ return -EINVAL; /* not yet supported */
++}
++
++/* must have cape_buses_mutex */
++struct cape_slot *cape_slot_find(struct cape_bus *bus, int slotno)
++{
++ struct cape_slot *slot;
++ int found;
++
++ found = 0;
++ cape_slot_for_each(bus, slot) {
++ if (slot->slotno == slotno) {
++ found = 1;
++ break;
++ }
++ }
++ return found ? slot : NULL;
++}
++
++/**
++ * cape_bus_release_dev - free a cape device structure when all users
++ * of it are finished.
++ * @dev: device that's been disconnected
++ *
++ * Will be called only by the device core when all users of this cape device are
++ * done.
++ */
++static void cape_bus_release_dev(struct device *dev)
++{
++ struct cape_dev *cdev;
++
++ cdev = to_cape_dev(dev);
++ /* cape_release_capabilities(cdev); TODO */
++ /* cape_release_of_node(cdev); TODO */
++ kfree(cdev);
++}
++
++/* mutex lock must be held */
++static struct cape_dev *cape_bus_scan_slot(struct cape_slot *slot)
++{
++ struct cape_bus *bus = slot->bus;
++ struct cape_dev *dev;
++ const struct cape_device_id *id;
++
++ /* get the ID (if a device exists) */
++ id = bus->ops->get_dev_id(slot);
++ if (id == NULL)
++ return ERR_PTR(-ENODEV);
++
++ /* slot must not have a device yet */
++ dev = slot->dev;
++ if (dev == NULL) {
++ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
++ if (dev == NULL) {
++ dev_info(&bus->dev, "Failed to allocate cape device "
++ "for slot #%d\n", slot->slotno);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ INIT_LIST_HEAD(&dev->bus_list);
++ dev->bus = bus;
++ dev->slot = slot;
++ }
++
++ dev->id = id;
++ dev->text_id = bus->ops->get_text_dev_id(slot);
++
++ /* capebus_set_of_node(dev); TODO */
++
++ return dev;
++}
++
++int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot)
++{
++ struct cape_dev *dev;
++ int r;
++
++ mutex_lock(&cape_buses_mutex);
++
++ dev = slot->dev;
++ if (dev == NULL) {
++
++ dev = cape_bus_scan_slot(slot);
++ if (IS_ERR(dev)) {
++ r = PTR_ERR(dev);
++ goto err_out;
++ }
++
++ dev_info(&bus->dev, "Slot #%d id='%s'\n", slot->slotno,
++ dev->text_id ? dev->text_id : "");
++
++ slot->dev = dev;
++
++ dev->dev.release = cape_bus_release_dev;
++ dev->dev.parent = &dev->bus->dev;
++ dev->dev.bus = &capebus_bus_type;
++ dev_set_name(&dev->dev, "%s-%d:%d",
++ dev->bus->name, dev->bus->busno,
++ dev->slot->slotno);
++
++ list_add_tail(&dev->bus_list, &bus->devices);
++
++ } else {
++ dev_info(&bus->dev, "Slot #%d id='%s' - rescan\n", slot->slotno,
++ dev->text_id ? dev->text_id : "");
++
++ if (dev->added) {
++ r = -EEXIST;
++ goto err_out;
++ }
++ }
++
++ r = device_register(&dev->dev);
++ if (r != 0) {
++ dev_info(&bus->dev, "Slot #%d id='%s' - "
++ "Failed to register\n",
++ slot->slotno,
++ dev->text_id ? dev->text_id : "");
++ r = 0;
++ } else {
++ if (dev->bus->ops->dev_registered)
++ dev->bus->ops->dev_registered(dev);
++ }
++
++err_out:
++ mutex_unlock(&cape_buses_mutex);
++
++ return r;
++}
++
++int cape_bus_register_slot(struct cape_bus *bus, struct cape_slot *slot,
++ int slotno)
++{
++ struct cape_slot *s2;
++ int r;
++
++ r = 0;
++
++ /* invalid (slot must always be numbered - no hotplug) */
++ if (slotno < 0) {
++ dev_err(&bus->dev, "Slot registration #%d failed\n", slotno);
++ return -EINVAL;
++ }
++
++ mutex_lock(&cape_buses_mutex);
++ s2 = cape_slot_find(bus, slotno);
++ if (s2 != NULL) {
++ dev_err(&bus->dev, "Slot #%d already exists\n", slotno);
++ mutex_unlock(&cape_buses_mutex);
++ return -EINVAL;
++ }
++
++ INIT_LIST_HEAD(&slot->node);
++ slot->bus = bus;
++ list_add(&slot->node, &bus->slots);
++ slot->slotno = slotno;
++ slot->dev = NULL;
++ mutex_unlock(&cape_buses_mutex);
++
++ dev_info(&bus->dev, "Slot #%d registered\n", slot->slotno);
++
++ return cape_bus_scan_one_slot(bus, slot);
++}
+diff --git a/drivers/capebus/capebus-sysfs.c b/drivers/capebus/capebus-sysfs.c
+new file mode 100644
+index 0000000..81c21fe
+--- /dev/null
++++ b/drivers/capebus/capebus-sysfs.c
+@@ -0,0 +1,52 @@
++/*
++ * drivers/capebus/capebus-sysfs.c
++ *
++ * sysfs for capebus devices
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You 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.
++ *
++ * Modeled after PCI's pci-sysfs.c
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/stat.h>
++#include <linux/export.h>
++#include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++
++#include <linux/capebus.h>
++
++static ssize_t id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev;
++
++ cdev = to_cape_dev(dev);
++ return sprintf(buf, "%s\n", cdev->text_id);
++}
++
++struct device_attribute capebus_dev_attrs[] = {
++ __ATTR_RO(id),
++ __ATTR_NULL,
++};
++
++struct bus_attribute capebus_bus_attrs[] = {
++ __ATTR_NULL
++};
+diff --git a/include/linux/capebus.h b/include/linux/capebus.h
+new file mode 100644
+index 0000000..7524401
+--- /dev/null
++++ b/include/linux/capebus.h
+@@ -0,0 +1,298 @@
++/*
++ * capebus.h
++ *
++ * Cape bus defines and function prototypes
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef LINUX_CAPEBUS_H
++#define LINUX_CAPEBUS_H
++
++#include <linux/list.h>
++#include <linux/device.h>
++#include <linux/spinlock.h>
++#include <linux/types.h>
++#include <linux/atomic.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++
++struct cape_device_id {
++ const char *cntrlboard; /* controlling board; i.e. "beaglebone" */
++ int len; /* opaque addressing data */
++ const void *data;
++};
++
++struct cape_dev;
++struct cape_bus;
++struct cape_slot;
++
++struct cape_slot {
++ struct list_head node;
++ struct cape_bus *bus; /* the bus this slot is on */
++ int slotno; /* index of this slot */
++ struct cape_dev *dev; /* the device (if found) */
++};
++
++struct cape_driver {
++ struct list_head node;
++ int (*probe)(struct cape_dev *dev, const struct cape_device_id *id);
++ void (*remove)(struct cape_dev *dev);
++ int (*suspend) (struct cape_dev *dev, pm_message_t state);
++ int (*suspend_late) (struct cape_dev *dev, pm_message_t state);
++ int (*resume_early) (struct cape_dev *dev);
++ int (*resume) (struct cape_dev *dev);
++ void (*shutdown) (struct cape_dev *dev);
++ struct device_driver driver;
++};
++
++/*
++ * capebus_register_driver must be a macro so that
++ * KBUILD_MODNAME can be expanded
++ */
++#define capebus_register_driver(driver) \
++ __capebus_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
++
++int __capebus_register_driver(struct cape_driver *drv, struct module *owner,
++ const char *mod_name);
++
++void capebus_unregister_driver(struct cape_driver *dev);
++
++/**
++ * module_capebus_driver() - Helper macro for registering a capebus driver
++ * @__capebus_driver: capebus_driver struct
++ *
++ * Helper macro for capebus drivers which do not do anything special in module
++ * init/exit. This eliminates a lot of boilerplate. Each module may only
++ * use this macro once, and calling it replaces module_init() and module_exit()
++ */
++#define module_capebus_driver(__capebus_driver) \
++ module_driver(__capebus_driver, capebus_register_driver, \
++ capebus_unregister_driver)
++
++#define to_cape_driver(n) container_of(n, struct cape_driver, driver)
++
++struct cape_bus_ops {
++ const struct cape_device_id *(*get_dev_id)(struct cape_slot *slot);
++ const char *(*get_text_dev_id)(struct cape_slot *slot);
++ int (*dev_probed)(struct cape_dev *dev); /* probed succesfully */
++ void (*dev_removed)(struct cape_dev *dev); /* removed */
++ int (*dev_registered)(struct cape_dev *dev); /* registered OK */
++};
++
++struct cape_bus {
++ struct list_head node;
++ const char *name;
++ struct list_head devices;
++ struct cape_dev *self;
++ struct list_head slots;
++ struct cape_bus_ops *ops;
++ int busno;
++ struct device dev;
++ /* TODO: resources.... */
++};
++
++#define to_cape_bus(n) container_of(n, struct cape_bus, dev)
++
++#define cape_bus_to_parent_of_node(n) ((n)->dev.parent->of_node)
++
++struct cape_dev {
++ struct list_head bus_list; /* node in per-bus list */
++ struct cape_bus *bus; /* bus this device is on */
++ struct cape_slot *slot; /* cape slot of this device */
++ struct cape_driver *driver; /* driver of this device */
++ struct device dev;
++ atomic_t enable_cnt; /* capebus_enable_device */
++ /* has been called */
++ const struct cape_device_id *id;
++ const char *text_id;
++ unsigned int added : 1; /* device has been added */
++ void *drv_priv; /* driver private data */
++};
++
++#define to_cape_dev(n) container_of(n, struct cape_dev, dev)
++
++struct cape_dev *capebus_dev_get(struct cape_dev *dev);
++void capebus_dev_put(struct cape_dev *dev);
++
++/* must have cape_buses_mutex */
++#define cape_bus_for_each(_bus) \
++ list_for_each_entry(_bus, &cape_buses, node)
++
++#define cape_bus_for_each_safe(_bus, _busn) \
++ list_for_each_entry_safe(_bus, _busn, &cape_buses, node)
++
++int cape_bus_register(struct cape_bus *bus, const char *name, int busno,
++ struct device *parent, struct cape_bus_ops *ops);
++
++/* must have cape_buses_mutex */
++#define cape_slot_for_each(_bus, _slot) \
++ list_for_each_entry(_slot, &(_bus)->slots, node)
++
++#define cape_slot_for_each_safe(_bus, _slot, _slotn) \
++ list_for_each_entry_safe(_slot, _slotn, &(_bus)->slots, node)
++
++int cape_bus_register_slot(struct cape_bus *bus,
++ struct cape_slot *slot, int slotno);
++
++int cape_bus_scan_one_slot(struct cape_bus *bus, struct cape_slot *slot);
++int cape_bus_scan(struct cape_bus *bus);
++
++extern struct list_head cape_buses;
++extern struct mutex cape_buses_mutex;
++
++static inline int capebus_is_enabled(struct cape_dev *cdev)
++{
++ return atomic_read(&cdev->enable_cnt) > 0;
++}
++
++static inline int capebus_enable_device(struct cape_dev *cdev)
++{
++ if (atomic_add_return(1, &cdev->enable_cnt) > 1)
++ return 0; /* already enabled */
++
++ /* XXX do enable */
++
++ return 0;
++}
++
++static inline void capebus_disable_device(struct cape_dev *cdev)
++{
++ if (atomic_sub_return(1, &cdev->enable_cnt) != 0)
++ return;
++
++ /* callback to disable device? */
++}
++
++static inline int capebus_enable_wake(struct cape_dev *dev, int what)
++{
++ return 0;
++}
++
++extern struct device_attribute capebus_dev_attrs[];
++extern struct bus_attribute capebus_bus_attrs[];
++
++extern struct bus_type capebus_bus_type;
++
++const struct of_device_id *
++capebus_of_match_device(struct cape_dev *cdev,
++ const char *property, const char *value);
++
++struct device_node *
++capebus_of_compatible_device_property_match(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *prop, const char *prop_value);
++
++struct platform_device *
++capebus_of_platform_compatible_device_create(struct cape_dev *dev,
++ const struct of_device_id *matches,
++ const char *pdev_name,
++ const char *prop, const char *prop_value);
++
++/* of tree support */
++
++struct device_node *
++capebus_of_find_property_node(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name);
++
++struct property *
++capebus_of_find_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp);
++
++const void *capebus_of_get_property(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int *lenp);
++
++static inline int capebus_of_property_read_u32_array(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u32 *out_values, size_t sz)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_u32_array(node, name, out_values, sz);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_u32(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u32 *out_value)
++{
++ return capebus_of_property_read_u32_array(dev, prop,
++ prop_value, name, out_value, 1);
++}
++
++static inline bool capebus_of_property_read_bool(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name)
++{
++ struct device_node *node;
++ bool ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_bool(node, name);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_string(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, const char **out_string)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_string(node, name, out_string);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_string_index(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, int index, const char **out_string)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_string_index(node, name, index, out_string);
++ of_node_put(node);
++ return ret;
++}
++
++static inline int capebus_of_property_read_u64(struct cape_dev *dev,
++ const char *prop, const char *prop_value,
++ const char *name, u64 *out_value)
++{
++ struct device_node *node;
++ int ret;
++
++ node = capebus_of_find_property_node(dev, prop, prop_value, name);
++ ret = of_property_read_u64(node, name, out_value);
++ of_node_put(node);
++ return ret;
++}
++
++int capebus_of_device_node_enable(struct device_node *node);
++int capebus_of_platform_device_enable(struct device_node *node);
++
++#endif
diff --git a/patches/linux-3.7/0155-capebus-Add-beaglebone-board-support.patch b/patches/linux-3.7/0155-capebus-Add-beaglebone-board-support.patch
new file mode 100644
index 0000000..2cafc5d
--- /dev/null
+++ b/patches/linux-3.7/0155-capebus-Add-beaglebone-board-support.patch
@@ -0,0 +1,1693 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:07:50 +0200
+Subject: [PATCH] capebus: Add beaglebone board support
+
+Introduce beaglebone capebus board support.
+
+This patch creates the beaglebone's board cape bus controller.
+
+The board controller is responsible for the probing of capes
+at the well defined I2C address for capes, parsing the EEPROM
+info and matching them to specific cape drivers.
+
+On top of that, adapter DT enabled devices are created for
+am33xx devices that have no DT bindings yet, as well as generic
+devices that can be used as building blocks for the cape drivers.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/capebus/boards/Kconfig | 6 +
+ drivers/capebus/boards/Makefile | 3 +
+ drivers/capebus/boards/capebus-bone-generic.c | 237 +++++++
+ drivers/capebus/boards/capebus-bone-pdevs.c | 328 +++++++++
+ drivers/capebus/boards/capebus-bone.c | 931 +++++++++++++++++++++++++
+ include/linux/capebus/capebus-bone.h | 120 ++++
+ 6 files changed, 1625 insertions(+)
+ create mode 100644 drivers/capebus/boards/Kconfig
+ create mode 100644 drivers/capebus/boards/Makefile
+ create mode 100644 drivers/capebus/boards/capebus-bone-generic.c
+ create mode 100644 drivers/capebus/boards/capebus-bone-pdevs.c
+ create mode 100644 drivers/capebus/boards/capebus-bone.c
+ create mode 100644 include/linux/capebus/capebus-bone.h
+
+diff --git a/drivers/capebus/boards/Kconfig b/drivers/capebus/boards/Kconfig
+new file mode 100644
+index 0000000..76b0f94
+--- /dev/null
++++ b/drivers/capebus/boards/Kconfig
+@@ -0,0 +1,6 @@
++config CAPEBUS_BONE_CONTROLLER
++ bool "Beaglebone capebus board controller"
++ depends on CAPEBUS && ARCH_OMAP2PLUS && OF && I2C
++ default n
++ help
++ "Select this to enable the beaglebone capebus board controller"
+diff --git a/drivers/capebus/boards/Makefile b/drivers/capebus/boards/Makefile
+new file mode 100644
+index 0000000..9048231
+--- /dev/null
++++ b/drivers/capebus/boards/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_CAPEBUS_BONE_CONTROLLER) += capebus-bone.o \
++ capebus-bone-pdevs.o \
++ capebus-bone-generic.o \
+diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
+new file mode 100644
+index 0000000..b1b79eb
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone-generic.c
+@@ -0,0 +1,237 @@
++/*
++ * TI Beaglebone capebus controller - Generic devices
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <video/da8xx-fb.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <asm/barrier.h>
++#include <plat/clock.h>
++#include <plat/omap_device.h>
++#include <linux/clkdev.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++int bone_capebus_probe_prolog(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ const struct of_device_id *match;
++ struct pinctrl *pinctrl;
++
++ /* get the board name (also matches the cntrlboard before checking) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ if (board_name == NULL)
++ return -ENODEV;
++
++ /* match compatible? */
++ match = capebus_of_match_device(dev, "board-name", board_name);
++ if (match == NULL)
++ return -ENODEV;
++
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++ if (version == NULL)
++ return -ENODEV;
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
++
++ dev_info(&dev->dev, "%s: V=%s '%s'\n", board_name,
++ version, match->compatible);
++
++ return 0;
++}
++EXPORT_SYMBOL(bone_capebus_probe_prolog);
++
++static const struct bone_capebus_generic_device_data gendevs[] = {
++ {
++ .name = "leds",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "gpio-leds", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "tps-bl",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "tps65217-backlight", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "keys",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "gpio-keys", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "tscadc",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "ti-tscadc-dt", }, { },
++ },
++ .units = 1,
++ }, {
++ .name = "lcdc",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "da8xx-dt", }, { },
++ },
++ .units = 1,
++ },{
++ .name = "i2c-dt",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "i2c-dt", }, { },
++ },
++ .units = 0,
++ }, {
++ .name = "w1-gpio",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "w1-gpio", }, { },
++ },
++ .units = 0,
++ }, {
++ .name = "pwm-backlight",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "pwm-backlight", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
++ .name = "spi-dt",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "spi-dt", }, { },
++ },
++ .units = 0, /* no limit */
++ }
++};
++
++struct bone_capebus_generic_info *
++bone_capebus_probe_generic(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ struct bone_capebus_generic_info *info;
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ struct platform_device *pdev;
++ const struct bone_capebus_generic_device_data *dd;
++ struct bone_capebus_generic_device_entry *de;
++ int i;
++
++ /* get the board name (also matches the cntrlboard before checking) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++
++ /* should never happen, but it doesn't hurt to play it safe */
++ if (board_name == NULL || version == NULL)
++ return ERR_PTR(-ENODEV);
++
++ info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
++ if (info == NULL) {
++ dev_err(&dev->dev, "Failed to allocate info\n");
++ return ERR_PTR(-ENOMEM);
++ }
++ info->dev = dev;
++ INIT_LIST_HEAD(&info->pdev_list);
++
++ /* iterate over the supported devices */
++ for (i = 0, dd = gendevs; i < ARRAY_SIZE(gendevs); i++, dd++) {
++
++ pdev = capebus_of_platform_compatible_device_create(dev,
++ dd->of_match, dd->name, "version", version);
++
++ /* node not found (mostly harmless) */
++ if (IS_ERR(pdev) && PTR_ERR(pdev) == -ENXIO) {
++ /* TODO: deal with required nodes */
++ continue;
++ }
++
++ /* failed to create due to an error; fatal */
++ if (IS_ERR_OR_NULL(pdev)) {
++ dev_err(&dev->dev, "failed to create device %s\n",
++ dd->name);
++ goto err_fail;
++ }
++
++ de = devm_kzalloc(&dev->dev, sizeof(*de), GFP_KERNEL);
++ if (de == NULL) {
++ dev_err(&dev->dev, "failed to allocate entry for %s\n",
++ dd->name);
++ goto err_fail;
++ }
++
++ /* add it to the list */
++ de->data = dd;
++ de->pdev = pdev;
++ list_add_tail(&de->node, &info->pdev_list);
++ }
++
++ return info;
++
++err_fail:
++ bone_capebus_remove_generic(info);
++ return NULL;
++}
++EXPORT_SYMBOL(bone_capebus_probe_generic);
++
++void bone_capebus_remove_generic(struct bone_capebus_generic_info *info)
++{
++ struct list_head *lh, *lhn;
++ struct bone_capebus_generic_device_entry *de;
++
++ if (info == NULL || info->dev == NULL)
++ return;
++
++ list_for_each_safe(lh, lhn, &info->pdev_list) {
++ de = list_entry(lh, struct bone_capebus_generic_device_entry,
++ node);
++ list_del(lh);
++ platform_device_unregister(de->pdev);
++ devm_kfree(&info->dev->dev, de);
++ }
++ devm_kfree(&info->dev->dev, info);
++}
++EXPORT_SYMBOL(bone_capebus_remove_generic);
+diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
+new file mode 100644
+index 0000000..f32134a
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone-pdevs.c
+@@ -0,0 +1,328 @@
++/*
++ * TI Beaglebone capebus controller - Platform adapters
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <asm/barrier.h>
++#include <linux/i2c.h>
++#include <linux/of_i2c.h>
++#include <linux/spi/spi.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++struct i2c_priv {
++ struct i2c_adapter *i2c_adapter;
++ phandle parent_handle;
++};
++
++static const struct of_device_id of_i2c_dt_match[] = {
++ { .compatible = "i2c-dt", },
++ {},
++};
++
++static int __devinit i2c_dt_probe(struct platform_device *pdev)
++{
++ struct i2c_priv *priv = NULL;
++ int ret = -EINVAL;
++ struct device_node *adap_node;
++ u32 val;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find parent property\n");
++ goto err_prop_fail;
++ }
++ priv->parent_handle = val;
++
++ adap_node = of_find_node_by_phandle(priv->parent_handle);
++ if (adap_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
++ ret = -EINVAL;
++ goto err_node_fail;
++ }
++
++ ret = capebus_of_platform_device_enable(adap_node);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "I2C adapter platform device failed "
++ "to enable\n");
++ goto err_enable_fail;
++ }
++
++ priv->i2c_adapter = of_find_i2c_adapter_by_node(adap_node);
++ if (priv->i2c_adapter == NULL) {
++ dev_err(&pdev->dev, "Failed to find i2c adapter node\n");
++ ret = -EINVAL;
++ goto err_adap_fail;
++ }
++
++ of_i2c_register_node_devices(priv->i2c_adapter, pdev->dev.of_node);
++
++ of_node_put(adap_node);
++
++ dev_info(&pdev->dev, "Registered bone I2C OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++err_adap_fail:
++ of_node_put(adap_node);
++err_enable_fail:
++ /* nothing */
++err_node_fail:
++ /* nothing */
++err_prop_fail:
++ devm_kfree(&pdev->dev, priv);
++ return ret;
++}
++
++static int __devexit i2c_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver i2c_dt_driver = {
++ .probe = i2c_dt_probe,
++ .remove = __devexit_p(i2c_dt_remove),
++ .driver = {
++ .name = "i2c-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_i2c_dt_match,
++ },
++};
++
++struct spi_priv {
++ struct spi_master *master;
++ phandle parent_handle;
++};
++
++static const struct of_device_id of_spi_dt_match[] = {
++ { .compatible = "spi-dt", },
++ {},
++};
++
++static int of_dev_node_match(struct device *dev, void *data)
++{
++ return dev->of_node == data;
++}
++
++/* must call put_device() when done with returned i2c_adapter device */
++static struct spi_master *of_find_spi_master_by_node(struct device_node *node)
++{
++ struct device *dev;
++ struct spi_master *master;
++
++ dev = class_find_device(&spi_master_class, NULL, node,
++ of_dev_node_match);
++ if (!dev)
++ return NULL;
++
++ master = container_of(dev, struct spi_master, dev);
++
++ /* TODO: No checks what-so-ever... be careful. */
++ return master;
++}
++
++static int __devinit spi_dt_probe(struct platform_device *pdev)
++{
++ struct spi_priv *priv = NULL;
++ int ret = -EINVAL;
++ struct device_node *master_node;
++ u32 val;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find parent property\n");
++ goto err_prop_fail;
++ }
++ priv->parent_handle = val;
++
++ master_node = of_find_node_by_phandle(priv->parent_handle);
++ if (master_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find spi bus master node\n");
++ ret = -EINVAL;
++ goto err_node_fail;
++ }
++
++ ret = capebus_of_platform_device_enable(master_node);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "SPI platform device failed to enable\n");
++ goto err_enable_fail;
++ }
++
++ priv->master = of_find_spi_master_by_node(master_node);
++ if (priv->master == NULL) {
++ dev_err(&pdev->dev, "Failed to find bus master node\n");
++ ret = -EINVAL;
++ goto err_master_fail;
++ }
++
++ of_register_node_spi_devices(priv->master, pdev->dev.of_node);
++
++ of_node_put(master_node);
++
++ dev_info(&pdev->dev, "Registered bone SPI OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++err_master_fail:
++ of_node_put(master_node);
++err_enable_fail:
++ /* nothing */
++err_node_fail:
++ /* nothing */
++err_prop_fail:
++ devm_kfree(&pdev->dev, priv);
++ return ret;
++}
++
++static int __devexit spi_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver spi_dt_driver = {
++ .probe = spi_dt_probe,
++ .remove = __devexit_p(spi_dt_remove),
++ .driver = {
++ .name = "spi-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_spi_dt_match,
++ },
++};
++
++/*
++ *
++ */
++struct bone_capebus_pdev_driver {
++ struct platform_driver *driver;
++ unsigned int registered : 1;
++ /* more? */
++};
++
++static struct bone_capebus_pdev_driver pdev_drivers[] = {
++ {
++ .driver = &i2c_dt_driver,
++ },
++ {
++ .driver = &spi_dt_driver,
++ },
++ {
++ .driver = NULL,
++ }
++};
++
++int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus)
++{
++ struct bone_capebus_pdev_driver *drvp;
++ int err;
++
++ /* first check if we do it twice */
++ for (drvp = pdev_drivers; drvp->driver != NULL; drvp++)
++ if (drvp->registered)
++ return -EBUSY;
++
++ for (drvp = pdev_drivers; drvp->driver != NULL; drvp++) {
++
++ err = platform_driver_register(drvp->driver);
++ if (err != 0)
++ goto err_out;
++
++ drvp->registered = 1;
++
++ dev_info(bus->dev, "Registered %s "
++ "platform driver\n", drvp->driver->driver.name);
++ }
++
++ return 0;
++
++err_out:
++ dev_err(bus->dev, "Failed to register %s "
++ "platform driver\n", drvp->driver->driver.name);
++
++ /* unregister */
++ while (--drvp >= pdev_drivers) {
++
++ if (!drvp->registered)
++ continue;
++
++ platform_driver_unregister(drvp->driver);
++ }
++
++ return err;
++}
++
++void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus)
++{
++ struct bone_capebus_pdev_driver *drvp;
++
++ /* unregister */
++ drvp = &pdev_drivers[ARRAY_SIZE(pdev_drivers)];
++ while (--drvp >= pdev_drivers) {
++
++ if (drvp->driver == NULL) /* skip terminator */
++ continue;
++
++ if (!drvp->registered)
++ continue;
++
++ platform_driver_unregister(drvp->driver);
++
++ drvp->registered = 0;
++ }
++}
+diff --git a/drivers/capebus/boards/capebus-bone.c b/drivers/capebus/boards/capebus-bone.c
+new file mode 100644
+index 0000000..33a6bde
+--- /dev/null
++++ b/drivers/capebus/boards/capebus-bone.c
+@@ -0,0 +1,931 @@
++/*
++ * TI Beaglebone capebus controller
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/completion.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/of.h>
++#include <linux/of_i2c.h>
++#include <linux/of_device.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
++#include <linux/ctype.h>
++
++#include <linux/capebus.h>
++#include <linux/capebus/capebus-bone.h>
++
++/* what to fill in to the cntrlboard field of the id */
++#define BONE_CAPEBUS_CNTRLBOARD "beaglebone"
++
++/* various EEPROM definition for the bone */
++struct bone_capebus_eeprom_field {
++ const char *name;
++ int start;
++ int size;
++ unsigned int ascii : 1;
++ unsigned int strip_trailing_dots : 1;
++ const char *override;
++};
++
++static const struct bone_capebus_eeprom_field eeprom_fields[] = {
++ [BONE_CAPEBUS_HEADER] = {
++ .name = "header",
++ .start = 0,
++ .size = 4,
++ .ascii = 0,
++ .override = "\xaa\x55\x33\xee", /* AA 55 33 EE */
++ },
++ [BONE_CAPEBUS_EEPROM_REV] = {
++ .name = "eeprom-format-revision",
++ .start = 4,
++ .size = 2,
++ .ascii = 1,
++ .override = "A0",
++ },
++ [BONE_CAPEBUS_BOARD_NAME] = {
++ .name = "board-name",
++ .start = 6,
++ .size = 32,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Board Name",
++ },
++ [BONE_CAPEBUS_VERSION] = {
++ .name = "version",
++ .start = 38,
++ .size = 4,
++ .ascii = 1,
++ .override = "00A0",
++ },
++ [BONE_CAPEBUS_MANUFACTURER] = {
++ .name = "manufacturer",
++ .start = 42,
++ .size = 16,
++ .ascii = 1,
++ .strip_trailing_dots = 1,
++ .override = "Override Manuf",
++ },
++ [BONE_CAPEBUS_PART_NUMBER] = {
++ .name = "part-number",
++ .start = 58,
++ .size = 16,
++ .ascii = 1,
++ .override = "Override Part#",
++ },
++ [BONE_CAPEBUS_NUMBER_OF_PINS] = {
++ .name = "number-of-pins",
++ .start = 74,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_SERIAL_NUMBER] = {
++ .name = "serial-number",
++ .start = 76,
++ .size = 12,
++ .ascii = 1,
++ .override = "0000000000",
++ },
++ [BONE_CAPEBUS_PIN_USAGE] = {
++ .name = "pin-usage",
++ .start = 88,
++ .size = 140,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_VDD_3V3EXP] = {
++ .name = "vdd-3v3exp",
++ .start = 228,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_VDD_5V] = {
++ .name = "vdd-5v",
++ .start = 230,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_SYS_5V] = {
++ .name = "sys-5v",
++ .start = 232,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++ [BONE_CAPEBUS_DC_SUPPLIED] = {
++ .name = "dc-supplied",
++ .start = 234,
++ .size = 2,
++ .ascii = 0,
++ .override = NULL,
++ },
++};
++
++char *bone_capebus_id_get_field(const struct cape_device_id *id,
++ int field, char *buf, int bufsz)
++{
++ const struct bone_capebus_eeprom_field *ee_field;
++ int len;
++
++ /* make sure the ID is valid for the bone */
++ if (bone_capebus_match_cntrlboard(id) != 0)
++ return NULL;
++
++ if ((unsigned int)field >= ARRAY_SIZE(eeprom_fields))
++ return NULL;
++
++ ee_field = &eeprom_fields[field];
++
++ /* enough space? */
++ if (bufsz < ee_field->size + ee_field->ascii)
++ return NULL;
++
++ memcpy(buf, (char *)id->data + ee_field->start, ee_field->size);
++
++ /* terminate ascii field */
++ if (ee_field->ascii)
++ buf[ee_field->size] = '\0';;
++
++ if (ee_field->strip_trailing_dots) {
++ len = strlen(buf);
++ while (len > 1 && buf[len - 1] == '.')
++ buf[--len] = '\0';
++ }
++
++ return buf;
++}
++EXPORT_SYMBOL(bone_capebus_id_get_field);
++
++int bone_capebus_match_cntrlboard(const struct cape_device_id *id)
++{
++ if (strcmp(id->cntrlboard, BONE_CAPEBUS_CNTRLBOARD) != 0)
++ return -ENODEV;
++ return 0;
++}
++EXPORT_SYMBOL(bone_capebus_match_cntrlboard);
++
++int bone_capebus_match_board(const struct cape_device_id *id,
++ const char **board_names)
++{
++ char rname[33];
++ const char *s;
++ int ret;
++ int i;
++
++ /* be safe; check for matching cntrlboard */
++ ret = bone_capebus_match_cntrlboard(id);
++ if (ret != 0)
++ return ret;
++
++ s = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ rname, sizeof(rname));
++ if (s == NULL)
++ return -EINVAL;
++
++ i = 0;
++ while (*board_names) {
++ if (strcmp(rname, *board_names) == 0)
++ return i;
++ board_names++;
++ }
++
++ return -1;
++}
++EXPORT_SYMBOL(bone_capebus_match_board);
++
++#ifdef CONFIG_OF
++static const struct of_device_id bone_capebus_of_match[] = {
++ {
++ .compatible = "bone-capebus",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bone_capebus_of_match);
++
++static const struct of_device_id slot_override_of_match[] = {
++ {
++ .compatible = "bone-capebus-slot-override",
++ },
++ { },
++};
++
++#endif
++
++const struct cape_device_id *bone_capebus_get_dev_id(struct cape_slot *slot)
++{
++ struct cape_bus *bus = slot->bus;
++ struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
++ struct i2c_client *client = bone_slot->client;
++ struct cape_device_id *id;
++ const u8 *p;
++ int r;
++ char board_name[32+1];
++ char version[4+1];
++ char manufacturer[16+1];
++ char part_number[16+1];
++
++ id = &bone_slot->id;
++
++ /* need to read EEPROM? */
++ if (!bone_slot->eeprom_probed) {
++
++ bone_slot->eeprom_probed = 1;
++
++ if (!bone_slot->eeprom_override) {
++ r = i2c_memory_read(bone_slot->client,
++ bone_slot->eeprom_signature, 0,
++ sizeof(bone_slot->eeprom_signature));
++ if (r != sizeof(bone_slot->eeprom_signature)) {
++ dev_err(&bus->dev,
++ "bone: Failed to read EEPROM at "
++ "slot %d (addr 0x%02x)\n",
++ slot->slotno, client->addr & 0x7f);
++ bone_slot->eeprom_failed = 1;
++ return NULL;
++ }
++ } else
++ dev_info(&bus->dev,
++ "bone: Using override eeprom data at slot %d\n",
++ slot->slotno);
++
++ p = bone_slot->eeprom_signature;
++ if (BONE_CAPEBUS_MAKE_HEADER(p) != BONE_CAPEBUS_HEADER_VALID) {
++ dev_err(&bus->dev, "bone: Invalid EEPROM signature "
++ "'%08x' at slot %d (addr 0x%02x)\n",
++ BONE_CAPEBUS_MAKE_HEADER(p),
++ slot->slotno, client->addr & 0x7f);
++ bone_slot->eeprom_failed = 1;
++ return NULL;
++ }
++
++ bone_slot->id.cntrlboard = BONE_CAPEBUS_CNTRLBOARD;
++ bone_slot->id.len = sizeof(bone_slot->eeprom_signature);
++ bone_slot->id.data = bone_slot->eeprom_signature;
++
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ board_name, sizeof(board_name));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ version, sizeof(version));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_MANUFACTURER,
++ manufacturer, sizeof(manufacturer));
++ bone_capebus_id_get_field(id, BONE_CAPEBUS_PART_NUMBER,
++ part_number, sizeof(part_number));
++
++ /* board_name,version,manufacturer,part_number */
++ snprintf(bone_slot->text_id, sizeof(bone_slot->text_id) - 1,
++ "%s,%s,%s,%s", board_name, version,
++ manufacturer, part_number);
++
++ /* terminate always */
++ bone_slot->text_id[sizeof(bone_slot->text_id) - 1] = '\0';
++
++ }
++
++ /* slot has failed and we don't support hotpluging */
++ if (bone_slot->eeprom_failed)
++ return NULL;
++
++ return id;
++}
++
++const char *bone_capebus_get_text_dev_id(struct cape_slot *slot)
++{
++ struct bone_capebus_slot *bone_slot = to_bone_capebus_slot(slot);
++
++ if (bone_slot->eeprom_failed || !bone_slot->eeprom_probed)
++ return NULL;
++
++ return bone_slot->text_id;
++}
++
++struct bonedev_ee_attribute {
++ struct device_attribute devattr;
++ unsigned int field;
++};
++#define to_bonedev_ee_attribute(x) \
++ container_of((x), struct bonedev_ee_attribute, devattr)
++
++static ssize_t bonedev_ee_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct bonedev_ee_attribute *ee_attr = to_bonedev_ee_attribute(attr);
++ struct cape_dev *cdev = to_cape_dev(dev);
++ const struct cape_device_id *id = cdev->id;
++ const struct bone_capebus_eeprom_field *ee_field;
++ int i, len;
++ char *p, *s;
++ u16 val;
++
++ if (id == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields */
++ ee_field = &eeprom_fields[ee_attr->field];
++
++ len = ee_field->size + ee_field->ascii;
++ p = kmalloc(len, GFP_KERNEL);
++ if (p == NULL)
++ return -ENOMEM;
++
++ s = bone_capebus_id_get_field(id, ee_attr->field, p, len);
++ if (s == NULL)
++ return -EINVAL;
++
++ /* add newline for ascii fields and return */
++ if (ee_field->ascii) {
++ len = sprintf(buf, "%s\n", s);
++ goto out;
++ }
++
++ /* case by case handling */
++ switch (ee_attr->field) {
++ case BONE_CAPEBUS_HEADER:
++ len = sprintf(buf, "%02x %02x %02x %02x\n",
++ s[0], s[1], s[2], s[3]);
++ break;
++
++ /* 2 bytes */
++ case BONE_CAPEBUS_NUMBER_OF_PINS:
++ case BONE_CAPEBUS_VDD_3V3EXP:
++ case BONE_CAPEBUS_VDD_5V:
++ case BONE_CAPEBUS_SYS_5V:
++ case BONE_CAPEBUS_DC_SUPPLIED:
++ /* the bone is LE */
++ val = s[0] & (s[1] << 8);
++ len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
++ break;
++
++ case BONE_CAPEBUS_PIN_USAGE:
++
++ len = 0;
++ for (i = 0; i < ee_field->size / 2; i++) {
++ /* the bone is LE */
++ val = s[0] & (s[1] << 8);
++ sprintf(buf, "%04x\n", val);
++ buf += 5;
++ len += 5;
++ s += 2;
++ }
++
++ break;
++
++ default:
++ *buf = '\0';
++ len = 0;
++ break;
++ }
++
++out:
++ kfree(p);
++
++ return len;
++}
++
++#define BONEDEV_EE_ATTR(_name, _field) \
++ { \
++ .devattr = __ATTR(_name, 0440, bonedev_ee_show, NULL), \
++ .field = BONE_CAPEBUS_##_field , \
++ }
++
++struct bonedev_ee_attribute ee_attrs[] = {
++ BONEDEV_EE_ATTR(header, HEADER),
++ BONEDEV_EE_ATTR(eeprom-format-revision, EEPROM_REV),
++ BONEDEV_EE_ATTR(board-name, BOARD_NAME),
++ BONEDEV_EE_ATTR(version, VERSION),
++ BONEDEV_EE_ATTR(manufacturer, MANUFACTURER),
++ BONEDEV_EE_ATTR(part-number, PART_NUMBER),
++ BONEDEV_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
++ BONEDEV_EE_ATTR(serial-number, SERIAL_NUMBER),
++ BONEDEV_EE_ATTR(pin-usage, PIN_USAGE),
++ BONEDEV_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
++ BONEDEV_EE_ATTR(vdd-5v, VDD_5V),
++ BONEDEV_EE_ATTR(sys-5v, SYS_5V),
++ BONEDEV_EE_ATTR(dc-supplied, DC_SUPPLIED),
++};
++
++static struct attribute *ee_attrs_flat[] = {
++ &ee_attrs[BONE_CAPEBUS_HEADER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_EEPROM_REV ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_BOARD_NAME ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VERSION ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_MANUFACTURER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_PART_NUMBER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_NUMBER_OF_PINS ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_SERIAL_NUMBER ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_PIN_USAGE ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VDD_3V3EXP ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_VDD_5V ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_SYS_5V ].devattr.attr,
++ &ee_attrs[BONE_CAPEBUS_DC_SUPPLIED ].devattr.attr,
++ NULL,
++};
++
++static const struct attribute_group bone_ee_attrgroup = {
++ .name = "ee-fields",
++ .is_visible = NULL,
++ .attrs = ee_attrs_flat,
++};
++
++static int bone_capebus_sysfs_register(struct cape_dev *dev)
++{
++ return sysfs_create_group(&dev->dev.kobj, &bone_ee_attrgroup);
++}
++
++static void bone_capebus_sysfs_unregister(struct cape_dev *dev)
++{
++ sysfs_remove_group(&dev->dev.kobj, &bone_ee_attrgroup);
++}
++
++static int bone_capebus_dev_probed(struct cape_dev *dev)
++{
++ return 0;
++}
++
++static void bone_capebus_dev_removed(struct cape_dev *dev)
++{
++ bone_capebus_sysfs_unregister(dev);
++}
++
++static int bone_capebus_dev_registered(struct cape_dev *dev)
++{
++ int ret;
++
++ ret = bone_capebus_sysfs_register(dev);
++ if (ret != 0) {
++ dev_err(&dev->dev, "bone_capebus sysfs registration failed\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static struct cape_bus_ops bone_capebus_ops = {
++ .get_dev_id = bone_capebus_get_dev_id,
++ .get_text_dev_id = bone_capebus_get_text_dev_id,
++ .dev_probed = bone_capebus_dev_probed,
++ .dev_removed = bone_capebus_dev_removed,
++ .dev_registered = bone_capebus_dev_registered,
++};
++
++static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ struct bone_capebus_slot *slot;
++ ssize_t len, sz;
++ int i;
++
++ sz = 0;
++
++ for (i = 0; i < bus->slots_nr; i++) {
++ slot = &bus->slots[i];
++
++ len = sprintf(buf, "%02x:%c%c%c%c %s\n",
++ (int)slot->eeprom_addr & 0x7f,
++ slot->eeprom_probed ? 'P' : '-',
++ slot->eeprom_failed ? 'F' : '-',
++ slot->eeprom_override ? 'O' : '-',
++ (slot->cape_slot.dev && slot->cape_slot.dev->added) ? 'A' : '-',
++ slot->text_id);
++
++ buf += len;
++ sz += len;
++ }
++ return sz;
++}
++
++static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ int slotno, err, i, len;
++ char *s, *board_name, *version, *p;
++ const struct bone_capebus_eeprom_field *ee_field, *eebrd, *eevrs;
++ struct bone_capebus_slot *slot;
++
++ eebrd = &eeprom_fields[BONE_CAPEBUS_BOARD_NAME];
++ eevrs = &eeprom_fields[BONE_CAPEBUS_VERSION];
++
++ slotno = simple_strtoul(buf, &s, 10);
++ if (slotno < 0 || slotno >= bus->slots_nr)
++ return -EINVAL;
++ slot = &bus->slots[slotno];
++ if (slot->eeprom_override || (slot->cape_slot.dev && slot->cape_slot.dev->added))
++ return -EINVAL;
++
++ board_name = kzalloc(eebrd->size + 1 + eevrs->size + 1, GFP_KERNEL);
++ if (board_name == NULL)
++ return -ENOMEM;
++ version = board_name + eebrd->size + 1;
++
++ s = strchr(s, ':');
++ if (s == NULL) {
++ kfree(board_name);
++ return -EINVAL;
++ }
++ s++;
++ p = strchr(s, ':');
++ if (p == NULL) {
++ len = strlen(s);
++ strncpy(board_name, s, eebrd->size);
++ strcpy(version, "00A0");
++ } else {
++ len = p - s;
++ if (len > eebrd->size)
++ len = p - s;
++ memcpy(board_name, s, len);
++ board_name[len] = '\0';
++ strncpy(version, p + 1, eevrs->size);
++ }
++ board_name[eebrd->size] = '\0';
++ version[eevrs->size] = '\0';
++
++ /* strip trailing spaces, dots & newlines */
++ s = board_name + strlen(board_name);
++ while (s > board_name &&
++ (isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
++ *--s = '\0';
++
++ printk(KERN_INFO "Override for slot #%d, board-name '%s', version '%s'\n",
++ slotno, board_name, version);
++
++ slot->eeprom_override = 1;
++ slot->eeprom_failed = 0;
++ slot->eeprom_probed = 0;
++
++ /* zero out signature */
++ memset(slot->eeprom_signature, 0,
++ sizeof(slot->eeprom_signature));
++
++ /* create an eeprom field */
++ for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
++
++ ee_field = &eeprom_fields[i];
++
++ /* point to the entry */
++ p = slot->eeprom_signature + ee_field->start;
++
++ /* if no such property, assign default */
++ if (i != BONE_CAPEBUS_BOARD_NAME) {
++
++ if (ee_field->override)
++ memcpy(p, ee_field->override,
++ ee_field->size);
++ else
++ memset(p, 0, ee_field->size);
++
++ continue;
++ }
++
++ /* copy it to the eeprom signature buf */
++ len = strlen(board_name);
++ if (len > ee_field->size)
++ len = ee_field->size;
++
++ /* copy and zero out rest */
++ memcpy(p, board_name, len);
++ if (len < ee_field->size)
++ memset(p + len, 0, ee_field->size - len);
++ }
++
++ printk(KERN_INFO "calling cape_bus_scan_one_slot\n");
++ err = cape_bus_scan_one_slot(&bus->cape_bus, &slot->cape_slot);
++
++ printk(KERN_INFO "cape_bus_scan_one_slot returned %d\n", err);
++
++ /* failed to scan... */
++ if (err != 0)
++ slot->eeprom_override = 0;
++
++ kfree(board_name);
++
++ return strlen(buf);
++}
++
++static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
++
++static int bone_capebus_bus_sysfs_register(struct bone_capebus_bus *bus)
++{
++ return device_create_file(bus->dev, &dev_attr_slots);
++}
++
++static void bone_capebus_bus_sysfs_unregister(struct bone_capebus_bus *bus)
++{
++ device_remove_file(bus->dev, &dev_attr_slots);
++}
++
++static int __devinit
++bone_capebus_probe(struct platform_device *pdev)
++{
++ struct bone_capebus_bus *bus;
++ struct device_node *pnode = pdev->dev.of_node;
++ const struct of_device_id *cntrlboard_match;
++ const struct of_device_id *dev_match;
++ struct bone_capebus_slot *slot;
++ const struct bone_capebus_eeprom_field *ee_field;
++ struct property *prop;
++ int length;
++ int r;
++ struct device_node *node;
++ struct i2c_client *client;
++ phandle handle;
++ u32 *slot_handles = NULL;
++ u32 val;
++ const char *str;
++ u8 *p;
++ int i, len;
++
++ /* we don't use platform_data */
++
++ bus = devm_kzalloc(&pdev->dev,
++ sizeof(struct bone_capebus_bus), GFP_KERNEL);
++ if (!bus) {
++ dev_err(&pdev->dev, "Failed to allocate device structure\n");
++ return -ENOMEM;
++ }
++
++ /* register the cape bus */
++ r = cape_bus_register(&bus->cape_bus, "bone", 0, &pdev->dev,
++ &bone_capebus_ops);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register the cape device\n");
++ return r;
++ }
++
++ cntrlboard_match = of_match_device(of_match_ptr(bone_capebus_of_match),
++ &pdev->dev);
++ if (!cntrlboard_match) {
++ dev_err(&pdev->dev, "Failed to configure bone capebus\n");
++ return -ENODEV;
++ }
++ bus->dev = &pdev->dev;
++
++ prop = of_find_property(pnode, "slots", &length);
++ if (prop == NULL) {
++ dev_err(&pdev->dev, "Unable to find required "
++ "property 'slots'\n");
++ return -EINVAL;
++ }
++ bus->slots_nr = length / sizeof(u32);
++ bus->slots = devm_kzalloc(&pdev->dev,
++ sizeof(bus->slots[0]) * bus->slots_nr, GFP_KERNEL);
++ if (!bus->slots) {
++ dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
++ bus->slots_nr);
++ return -ENOMEM;
++ }
++ slot_handles = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
++ if (!slot_handles) {
++ dev_err(&pdev->dev, "Failed to allocate %d slot areas\n",
++ bus->slots_nr);
++ return -ENOMEM;
++ }
++ r = of_property_read_u32_array(pnode, "slots",
++ slot_handles, bus->slots_nr);
++ if (r < 0) {
++ dev_err(&pdev->dev, "Failed to read %d slot handles\n",
++ bus->slots_nr);
++ return r;
++ }
++
++ /* now we iterate over any overrides */
++ for_each_child_of_node(pnode, node) {
++
++ dev_match = of_match_node(slot_override_of_match, node);
++ if (!dev_match)
++ continue;
++
++ /* no reg property */
++ if (of_property_read_u32(node, "slot", &val) != 0) {
++ dev_warn(&pdev->dev, "override: Failed to read "
++ "slot property\n");
++ continue;
++ }
++
++ if (val >= bus->slots_nr) {
++ dev_warn(&pdev->dev, "override: invalid slot #%u\n",
++ val);
++ continue;
++ }
++
++ slot = &bus->slots[val];
++
++ if (slot->eeprom_override) {
++ dev_warn(&pdev->dev, "override: slot #%u is already "
++ "overriden\n", val);
++ continue;
++ }
++
++ slot->eeprom_override = 1;
++
++ /* zero out signature */
++ memset(slot->eeprom_signature, 0,
++ sizeof(slot->eeprom_signature));
++
++ /* for any matching field assign them */
++ for (i = 0; i < ARRAY_SIZE(eeprom_fields); i++) {
++
++ ee_field = &eeprom_fields[i];
++
++ /* point to the entry */
++ p = slot->eeprom_signature + ee_field->start;
++
++ /* if no such property, assign default */
++ if (of_property_read_string(node, ee_field->name,
++ &str) != 0) {
++
++ if (ee_field->override)
++ memcpy(p, ee_field->override,
++ ee_field->size);
++ else
++ memset(p, 0, ee_field->size);
++
++ continue;
++ }
++
++ /* copy it to the eeprom signature buf */
++ len = strlen(str);
++ if (len > ee_field->size)
++ len = ee_field->size;
++
++ /* copy and zero out rest */
++ memcpy(p, str, len);
++ if (len < ee_field->size)
++ memset(p + len, 0, ee_field->size - len);
++ }
++ }
++
++ platform_set_drvdata(pdev, bus);
++
++ /* now find the i2c clients */
++ for (i = 0; i < bus->slots_nr; i++) {
++
++ slot = &bus->slots[i];
++
++ handle = slot_handles[i];
++ node = of_find_node_by_phandle(handle);
++ if (node == NULL) {
++ dev_warn(&pdev->dev, "Failed to find node with phandle "
++ "0x%x (#%d)\n", handle, i);
++ continue;
++ }
++ dev_dbg(&pdev->dev, "Found device node for phandle "
++ "0x%x (#%d)\n", handle, i);
++
++ client = of_find_i2c_device_by_node(node);
++ if (client == NULL) {
++ dev_warn(&pdev->dev, "Invalid I2C client node with "
++ "phandle 0x%x (#%d)\n", handle, i);
++ continue;
++ }
++
++ slot->client = i2c_use_client(client);
++ /* no use for this anymore */
++ of_node_put(node);
++
++ /* save handle */
++ client = slot->client; /* get again */
++ slot->eeprom_addr = client->addr;
++ dev_dbg(&pdev->dev, "Found i2c_client at #%d "
++ "(address = 0x%02x)\n",
++ i, slot->eeprom_addr);
++
++ r = cape_bus_register_slot(&bus->cape_bus, &slot->cape_slot, i);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register slot #%d\n", i);
++ continue;
++ }
++
++ dev_info(&pdev->dev, "Registered slot #%d OK\n", i);
++ }
++
++ /* we don't need the handles anymore */
++ devm_kfree(&pdev->dev, slot_handles);
++ slot_handles = NULL;
++
++ r = bone_capebus_register_pdev_adapters(bus);
++ if (r != 0) {
++ dev_err(&pdev->dev, "Failed to register the pdev adapters\n");
++ goto err_no_pdevs;
++ }
++
++ pm_runtime_enable(bus->dev);
++ r = pm_runtime_get_sync(bus->dev);
++ if (IS_ERR_VALUE(r)) {
++ dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
++ goto err_exit;
++ }
++
++ pm_runtime_put(bus->dev);
++
++ bone_capebus_bus_sysfs_register(bus);
++
++ dev_info(&pdev->dev, "initialized OK.\n");
++
++ return 0;
++
++err_exit:
++ bone_capebus_unregister_pdev_adapters(bus);
++err_no_pdevs:
++ platform_set_drvdata(pdev, NULL);
++
++ return r;
++}
++
++static int __devexit bone_capebus_remove(struct platform_device *pdev)
++{
++ struct bone_capebus_bus *bus = platform_get_drvdata(pdev);
++ int ret;
++
++ bone_capebus_bus_sysfs_unregister(bus);
++ bone_capebus_unregister_pdev_adapters(bus);
++
++ platform_set_drvdata(pdev, NULL);
++
++ ret = pm_runtime_get_sync(&pdev->dev);
++ if (IS_ERR_VALUE(ret))
++ return ret;
++
++ pm_runtime_put(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++#ifdef CONFIG_PM_RUNTIME
++static int bone_capebus_runtime_suspend(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++
++static int bone_capebus_runtime_resume(struct device *dev)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct bone_capebus_bus *_dev = platform_get_drvdata(pdev);
++
++ (void)_dev;
++ return 0;
++}
++#endif /* CONFIG_PM_RUNTIME */
++
++static struct dev_pm_ops bone_capebus_pm_ops = {
++ SET_RUNTIME_PM_OPS(bone_capebus_runtime_suspend,
++ bone_capebus_runtime_resume, NULL)
++};
++#define BONE_CAPEBUS_PM_OPS (&bone_capebus_pm_ops)
++#else
++#define BONE_CAPEBUS_PM_OPS NULL
++#endif /* CONFIG_PM */
++
++static struct platform_driver bone_capebus_driver = {
++ .probe = bone_capebus_probe,
++ .remove = __devexit_p(bone_capebus_remove),
++ .driver = {
++ .name = "bone-capebus",
++ .owner = THIS_MODULE,
++ .pm = BONE_CAPEBUS_PM_OPS,
++ .of_match_table = of_match_ptr(bone_capebus_of_match),
++ },
++};
++
++module_platform_driver(bone_capebus_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone cape bus controller");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:capebus_bone");
+diff --git a/include/linux/capebus/capebus-bone.h b/include/linux/capebus/capebus-bone.h
+new file mode 100644
+index 0000000..e394304
+--- /dev/null
++++ b/include/linux/capebus/capebus-bone.h
+@@ -0,0 +1,120 @@
++/*
++ * capebus-bone.h
++ *
++ * Cape bus defines and function prototypes for the beaglebone
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++#ifndef LINUX_CAPEBUS_BONE_H
++#define LINUX_CAPEBUS_BONE_H
++
++#include <linux/list.h>
++#include <linux/capebus.h>
++
++struct bone_capebus_slot {
++ struct cape_slot cape_slot;
++ u32 slot_handle;
++ int eeprom_addr;
++ struct i2c_client *client;
++ unsigned int eeprom_probed : 1;
++ unsigned int eeprom_failed : 1;
++ unsigned int eeprom_override : 1;
++ struct cape_device_id id;
++ char text_id[256];
++ char eeprom_signature[256];
++};
++
++#define to_bone_capebus_slot(n) \
++ container_of(n, struct bone_capebus_slot, cape_slot)
++
++struct bone_capebus_bus {
++ struct cape_bus cape_bus;
++ struct device *dev; /* pdev->dev */
++ int slots_nr;
++ struct bone_capebus_slot *slots;
++};
++
++#define to_bone_capebus_bus(n) \
++ container_of(n, struct bone_capebus_bus, cape_bus)
++
++#define BONE_CAPEBUS_HEADER 0
++#define BONE_CAPEBUS_EEPROM_REV 1
++#define BONE_CAPEBUS_BOARD_NAME 2
++#define BONE_CAPEBUS_VERSION 3
++#define BONE_CAPEBUS_MANUFACTURER 4
++#define BONE_CAPEBUS_PART_NUMBER 5
++#define BONE_CAPEBUS_NUMBER_OF_PINS 6
++#define BONE_CAPEBUS_SERIAL_NUMBER 7
++#define BONE_CAPEBUS_PIN_USAGE 8
++#define BONE_CAPEBUS_VDD_3V3EXP 9
++#define BONE_CAPEBUS_VDD_5V 10
++#define BONE_CAPEBUS_SYS_5V 11
++#define BONE_CAPEBUS_DC_SUPPLIED 12
++#define BONE_CAPEBUS_FIELDS_NR 13
++
++#define BONE_CAPEBUS_MAKE_HEADER(p) \
++ ({ \
++ const u8 *_p = (p); \
++ (((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
++ ((u32)_p[2] << 8) | (u32)_p[3] ); \
++ })
++
++#define BONE_CAPEBUS_HEADER_VALID 0xaa5533ee
++
++char *bone_capebus_id_get_field(const struct cape_device_id *id,
++ int field, char *buf, int bufsz);
++
++int bone_capebus_match_cntrlboard(const struct cape_device_id *id);
++
++int bone_capebus_match_board(const struct cape_device_id *id,
++ const char **board_names);
++
++/* in pdevs */
++int bone_capebus_register_pdev_adapters(struct bone_capebus_bus *bus);
++void bone_capebus_unregister_pdev_adapters(struct bone_capebus_bus *bus);
++
++/* generic cape support */
++
++struct bone_capebus_generic_device_data {
++ const char *name;
++ const struct of_device_id *of_match;
++ unsigned int units;
++};
++
++struct bone_capebus_generic_device_entry {
++ struct list_head node;
++ const struct bone_capebus_generic_device_data *data;
++ struct platform_device *pdev;
++};
++
++struct bone_capebus_generic_info {
++ struct cape_dev *dev;
++ struct list_head pdev_list;
++};
++
++int bone_capebus_probe_prolog(struct cape_dev *dev,
++ const struct cape_device_id *id);
++
++struct bone_capebus_generic_info *
++bone_capebus_probe_generic(struct cape_dev *dev,
++ const struct cape_device_id *id);
++
++void bone_capebus_remove_generic(
++ struct bone_capebus_generic_info *info);
++
++#endif
diff --git a/patches/linux-3.7/0156-capebus-Beaglebone-generic-cape-support.patch b/patches/linux-3.7/0156-capebus-Beaglebone-generic-cape-support.patch
new file mode 100644
index 0000000..959deee
--- /dev/null
+++ b/patches/linux-3.7/0156-capebus-Beaglebone-generic-cape-support.patch
@@ -0,0 +1,123 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:09:49 +0200
+Subject: [PATCH] capebus: Beaglebone generic cape support
+
+Introducing beaglebone generic cape support.
+
+With this you can create almost any kind of cape driver
+that doesn't require complex interconnection of the parts.
+
+Most beaglebone capes can be created with this, including
+all the display capes (DVI/VGA/LCD) with touchscreen or not,
+capes that only use i2c or spi devices, gpio-keys, leds etc.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/capebus/capes/Kconfig | 6 +++
+ drivers/capebus/capes/Makefile | 1 +
+ drivers/capebus/capes/bone-generic-cape.c | 75 +++++++++++++++++++++++++++++
+ 3 files changed, 82 insertions(+)
+ create mode 100644 drivers/capebus/capes/Kconfig
+ create mode 100644 drivers/capebus/capes/Makefile
+ create mode 100644 drivers/capebus/capes/bone-generic-cape.c
+
+diff --git a/drivers/capebus/capes/Kconfig b/drivers/capebus/capes/Kconfig
+new file mode 100644
+index 0000000..bfe54a6
+--- /dev/null
++++ b/drivers/capebus/capes/Kconfig
+@@ -0,0 +1,6 @@
++config CAPEBUS_BONE_GENERIC
++ tristate "Beaglebone Generic cape driver"
++ depends on CAPEBUS_BONE_CONTROLLER
++ default n
++ help
++ "Select this to enable a generic cape driver; LCD/DVI capes etc"
+diff --git a/drivers/capebus/capes/Makefile b/drivers/capebus/capes/Makefile
+new file mode 100644
+index 0000000..83da381
+--- /dev/null
++++ b/drivers/capebus/capes/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_CAPEBUS_BONE_GENERIC) += bone-generic-cape.o
+diff --git a/drivers/capebus/capes/bone-generic-cape.c b/drivers/capebus/capes/bone-generic-cape.c
+new file mode 100644
+index 0000000..b364614
+--- /dev/null
++++ b/drivers/capebus/capes/bone-generic-cape.c
+@@ -0,0 +1,75 @@
++/*
++ * Generic cape support
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
++ * Copyright (C) 2012 Texas Instruments Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/err.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++/* fwd decl. */
++extern struct cape_driver bonegeneric_driver;
++
++static const struct of_device_id bonegeneric_of_match[] = {
++ {
++ .compatible = "bone-generic-cape",
++ }, { },
++};
++MODULE_DEVICE_TABLE(of, bonegeneric_of_match);
++
++static int bonegeneric_probe(struct cape_dev *dev,
++ const struct cape_device_id *id)
++{
++ struct bone_capebus_generic_info *ginfo;
++ int err;
++
++ err = bone_capebus_probe_prolog(dev, id);
++ if (err != 0)
++ return err;
++
++ ginfo = bone_capebus_probe_generic(dev, id);
++ if (IS_ERR_OR_NULL(ginfo))
++ return IS_ERR(ginfo) ? PTR_ERR(ginfo) : -ENODEV;
++ dev->drv_priv = ginfo;
++ return 0;
++}
++
++static void bonegeneric_remove(struct cape_dev *dev)
++{
++ bone_capebus_remove_generic(dev->drv_priv);
++}
++
++struct cape_driver bonegeneric_driver = {
++ .driver = {
++ .name = "bonegeneric",
++ .owner = THIS_MODULE,
++ .of_match_table = bonegeneric_of_match,
++ },
++ .probe = bonegeneric_probe,
++ .remove = bonegeneric_remove,
++};
++
++module_capebus_driver(bonegeneric_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone generic cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-generic-cape");
diff --git a/patches/linux-3.7/0157-capebus-Beaglebone-geiger-cape-support.patch b/patches/linux-3.7/0157-capebus-Beaglebone-geiger-cape-support.patch
new file mode 100644
index 0000000..0ff2143
--- /dev/null
+++ b/patches/linux-3.7/0157-capebus-Beaglebone-geiger-cape-support.patch
@@ -0,0 +1,563 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:12:20 +0200
+Subject: [PATCH] capebus: Beaglebone geiger cape support
+
+Support beaglebone's geiger cape.
+
+The geiger cape allows you to measure the amount of
+ionising radiation in your area, and as an example
+of how to create a complex non-generic cape driver.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/capebus/capes/Kconfig | 7 +
+ drivers/capebus/capes/Makefile | 1 +
+ drivers/capebus/capes/bone-geiger-cape.c | 517 ++++++++++++++++++++++++++++++
+ 3 files changed, 525 insertions(+)
+ create mode 100644 drivers/capebus/capes/bone-geiger-cape.c
+
+diff --git a/drivers/capebus/capes/Kconfig b/drivers/capebus/capes/Kconfig
+index bfe54a6..0418bef 100644
+--- a/drivers/capebus/capes/Kconfig
++++ b/drivers/capebus/capes/Kconfig
+@@ -4,3 +4,10 @@ config CAPEBUS_BONE_GENERIC
+ default n
+ help
+ "Select this to enable a generic cape driver; LCD/DVI capes etc"
++
++config CAPEBUS_BONE_GEIGER
++ tristate "Beaglebone Geiger cape driver"
++ depends on CAPEBUS_BONE_CONTROLLER
++ default n
++ help
++ "Select this to enable a driver for the geiger cape"
+diff --git a/drivers/capebus/capes/Makefile b/drivers/capebus/capes/Makefile
+index 83da381..d6f94ce 100644
+--- a/drivers/capebus/capes/Makefile
++++ b/drivers/capebus/capes/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_CAPEBUS_BONE_GENERIC) += bone-generic-cape.o
++obj-$(CONFIG_CAPEBUS_BONE_GEIGER) += bone-geiger-cape.o
+diff --git a/drivers/capebus/capes/bone-geiger-cape.c b/drivers/capebus/capes/bone-geiger-cape.c
+new file mode 100644
+index 0000000..9b3a83d
+--- /dev/null
++++ b/drivers/capebus/capes/bone-geiger-cape.c
+@@ -0,0 +1,517 @@
++/*
++ * Driver for beaglebone Geiger cape
++ *
++ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.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.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/timer.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/err.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_gpio.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/atomic.h>
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/clkdev.h>
++#include <linux/pwm.h>
++#include <linux/math64.h>
++#include <linux/atomic.h>
++#include <linux/leds.h>
++#include <linux/input/ti_am335x_tsc.h>
++#include <linux/platform_data/ti_am335x_adc.h>
++#include <linux/mfd/ti_am335x_tscadc.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/machine.h>
++#include <linux/iio/consumer.h>
++
++#include <linux/capebus/capebus-bone.h>
++
++/* fwd decl. */
++extern struct cape_driver bonegeiger_driver;
++
++struct bone_geiger_info {
++ struct cape_dev *dev;
++ struct bone_capebus_generic_info *geninfo;
++ struct pwm_device *pwm_dev;
++ int pwm_frequency;
++ int pwm_duty_cycle;
++ int run;
++ atomic64_t counter;
++ int event_gpio;
++ int event_irq;
++ struct led_trigger *event_led; /* event detect */
++ struct led_trigger *run_led; /* running */
++ unsigned long event_blink_delay;
++ struct sysfs_dirent *counter_sd; /* notifier */
++ const char *vsense_name;
++ unsigned int vsense_scale;
++ struct iio_channel *vsense_channel;
++};
++
++static const struct of_device_id bonegeiger_of_match[] = {
++ {
++ .compatible = "bone-geiger-cape",
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, bonegeiger_of_match);
++
++static int bonegeiger_start(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++ int duty, period;
++
++ if (info->run != 0)
++ return 0;
++
++ /* checks */
++ if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
++ dev_err(&dev->dev, "Cowardly refusing to use a "
++ "frequency of %d\n",
++ info->pwm_frequency);
++ return -EINVAL;
++ }
++ if (info->pwm_duty_cycle > 80) {
++ dev_err(&dev->dev, "Cowardly refusing to use a "
++ "duty cycle of %d\n",
++ info->pwm_duty_cycle);
++ return -EINVAL;
++ }
++
++ period = div_u64(1000000000LLU, info->pwm_frequency);
++ duty = (period * info->pwm_duty_cycle) / 100;
++
++ dev_info(&dev->dev, "starting geiger tube with "
++ "duty=%duns period=%dus\n",
++ duty, period);
++
++ pwm_config(info->pwm_dev, duty, period);
++ pwm_enable(info->pwm_dev);
++
++ info->run = 1;
++ led_trigger_event(info->run_led, LED_FULL);
++
++ return 0;
++}
++
++static int bonegeiger_stop(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ if (info->run == 0)
++ return 0;
++
++ dev_info(&dev->dev, "disabling geiger tube\n");
++ pwm_config(info->pwm_dev, 0, 50000); /* 0% duty cycle, 20KHz */
++ pwm_disable(info->pwm_dev);
++
++ info->run = 0;
++ led_trigger_event(info->run_led, LED_OFF);
++
++ return 0;
++}
++
++static ssize_t bonegeiger_show_run(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ return sprintf(buf, "%d\n", info->run);
++}
++
++static ssize_t bonegeiger_store_run(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ int run, err;
++
++ if (sscanf(buf, "%i", &run) != 1)
++ return -EINVAL;
++
++ if (run)
++ err = bonegeiger_start(cdev);
++ else
++ err = bonegeiger_stop(cdev);
++
++ return err ? err : count;
++}
++
++static ssize_t bonegeiger_show_counter(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ return sprintf(buf, "%llu\n", atomic64_read(&info->counter));
++}
++
++static ssize_t bonegeiger_store_counter(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++
++ atomic64_set(&info->counter, 0); /* just reset */
++ return count;
++}
++
++static ssize_t bonegeiger_show_vsense(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct cape_dev *cdev = to_cape_dev(dev);
++ struct bone_geiger_info *info = cdev->drv_priv;
++ int ret, val;
++ u32 mvolts;
++
++ ret = iio_read_channel_raw(info->vsense_channel, &val);
++ if (ret < 0)
++ return ret;
++
++ /* V = (1800 / 4096) * val * scale) = (1.8 * val * scale / 4096) */
++ mvolts = div_u64(1800 * info->vsense_scale * (u64)val, 4096 * 100);
++
++ return sprintf(buf, "%d\n", mvolts);
++}
++
++static DEVICE_ATTR(run, S_IRUGO | S_IWUSR,
++ bonegeiger_show_run, bonegeiger_store_run);
++static DEVICE_ATTR(counter, S_IRUGO | S_IWUSR,
++ bonegeiger_show_counter, bonegeiger_store_counter);
++static DEVICE_ATTR(vsense, S_IRUGO,
++ bonegeiger_show_vsense, NULL);
++
++static int bonegeiger_sysfs_register(struct cape_dev *cdev)
++{
++ int err;
++
++ err = device_create_file(&cdev->dev, &dev_attr_run);
++ if (err != 0)
++ goto err_no_run;
++
++ err = device_create_file(&cdev->dev, &dev_attr_counter);
++ if (err != 0)
++ goto err_no_counter;
++
++ err = device_create_file(&cdev->dev, &dev_attr_vsense);
++ if (err != 0)
++ goto err_no_vsense;
++
++ return 0;
++
++err_no_vsense:
++ device_remove_file(&cdev->dev, &dev_attr_counter);
++err_no_counter:
++ device_remove_file(&cdev->dev, &dev_attr_run);
++err_no_run:
++ return err;
++}
++
++static void bonegeiger_sysfs_unregister(struct cape_dev *cdev)
++{
++ device_remove_file(&cdev->dev, &dev_attr_vsense);
++ device_remove_file(&cdev->dev, &dev_attr_counter);
++ device_remove_file(&cdev->dev, &dev_attr_run);
++}
++
++static irqreturn_t bonegeiger_irq_handler(int irq, void *dev_id)
++{
++ struct cape_dev *dev = dev_id;
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ atomic64_inc(&info->counter);
++
++ led_trigger_blink_oneshot(info->event_led,
++ &info->event_blink_delay, &info->event_blink_delay, 0);
++
++ sysfs_notify_dirent(info->counter_sd);
++
++ return IRQ_HANDLED;
++}
++
++static int bonegeiger_probe(struct cape_dev *dev, const struct cape_device_id *id)
++{
++ char boardbuf[33];
++ char versionbuf[5];
++ const char *board_name;
++ const char *version;
++ struct bone_geiger_info *info;
++ struct pinctrl *pinctrl;
++ struct device_node *node, *pwm_node;
++ phandle phandle;
++ u32 val;
++ int err;
++
++ /* boiler plate probing */
++ err = bone_capebus_probe_prolog(dev, id);
++ if (err != 0)
++ return err;
++
++ /* get the board name (after check of cntrlboard match) */
++ board_name = bone_capebus_id_get_field(id, BONE_CAPEBUS_BOARD_NAME,
++ boardbuf, sizeof(boardbuf));
++ /* get the board version */
++ version = bone_capebus_id_get_field(id, BONE_CAPEBUS_VERSION,
++ versionbuf, sizeof(versionbuf));
++ /* should never happen; but check anyway */
++ if (board_name == NULL || version == NULL)
++ return -ENODEV;
++
++ dev->drv_priv = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
++ if (dev->drv_priv == NULL) {
++ dev_err(&dev->dev, "Failed to allocate info\n");
++ err = -ENOMEM;
++ goto err_no_mem;
++ }
++ info = dev->drv_priv;
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
++
++ node = capebus_of_find_property_node(dev, "version", version, "pwms");
++ if (node == NULL) {
++ dev_err(&dev->dev, "unable to find pwms property\n");
++ err = -ENODEV;
++ goto err_no_pwm;
++ }
++
++ err = of_property_read_u32(node, "pwms", &val);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to read pwm handle\n");
++ goto err_no_pwm;
++ }
++ phandle = val;
++
++ pwm_node = of_find_node_by_phandle(phandle);
++ if (pwm_node == NULL) {
++ dev_err(&dev->dev, "Failed to pwm node\n");
++ err = -EINVAL;
++ goto err_no_pwm;
++ }
++
++ err = capebus_of_platform_device_enable(pwm_node);
++ of_node_put(pwm_node);
++ if (err != 0) {
++ dev_err(&dev->dev, "Failed to pwm node\n");
++ goto err_no_pwm;
++ }
++
++ info->pwm_dev = of_pwm_request(node, NULL);
++ of_node_put(node);
++ if (IS_ERR(info->pwm_dev)) {
++ dev_err(&dev->dev, "unable to request PWM\n");
++ err = PTR_ERR(info->pwm_dev);
++ goto err_no_pwm;
++ }
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "pwm-frequency", &val) != 0) {
++ val = 20000;
++ dev_warn(&dev->dev, "Could not read pwm-frequency property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_frequency = val;
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "pwm-duty-cycle", &val) != 0) {
++ val = 60;
++ dev_warn(&dev->dev, "Could not read pwm-duty-cycle property; "
++ "using default %u\n",
++ val);
++ }
++ info->pwm_duty_cycle = val;
++
++ node = capebus_of_find_property_node(dev, "gpios", version, "pwms");
++ info->event_gpio = of_get_gpio_flags(node, 0, NULL);
++ of_node_put(node);
++ if (IS_ERR_VALUE(info->event_gpio)) {
++ dev_err(&dev->dev, "unable to get event GPIO\n");
++ err = info->event_gpio;
++ goto err_no_gpio;
++ }
++
++ err = gpio_request_one(info->event_gpio,
++ GPIOF_DIR_IN | GPIOF_EXPORT,
++ "bone-geiger-cape-event");
++ if (err != 0) {
++ dev_err(&dev->dev, "failed to request event GPIO\n");
++ goto err_no_gpio;
++ }
++
++ atomic64_set(&info->counter, 0);
++
++ info->event_irq = gpio_to_irq(info->event_gpio);
++ if (IS_ERR_VALUE(info->event_irq)) {
++ dev_err(&dev->dev, "unable to get event GPIO IRQ\n");
++ err = info->event_irq;
++ goto err_no_irq;
++ }
++
++ err = request_irq(info->event_irq, bonegeiger_irq_handler,
++ IRQF_TRIGGER_RISING | IRQF_SHARED,
++ "bone-geiger-irq", dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to request irq\n");
++ goto err_no_irq;
++ }
++
++ err = bonegeiger_sysfs_register(dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "unable to register sysfs\n");
++ goto err_no_sysfs;
++ }
++
++ info->counter_sd = sysfs_get_dirent(dev->dev.kobj.sd, NULL, "counter");
++ if (info->counter_sd == NULL) {
++ dev_err(&dev->dev, "unable to get dirent of counter\n");
++ err = -ENODEV;
++ goto err_no_counter_dirent;
++ }
++
++ led_trigger_register_simple("geiger-event", &info->event_led);
++ led_trigger_register_simple("geiger-run", &info->run_led);
++
++ /* pick up the generics; tsc & leds */
++ info->geninfo = bone_capebus_probe_generic(dev, id);
++ if (info->geninfo == NULL) {
++ dev_err(&dev->dev, "Could not probe generic\n");
++ goto err_no_generic;
++ }
++
++ led_trigger_event(info->run_led, LED_OFF);
++
++ /* default */
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "event-blink-delay", &val) != 0) {
++ val = 30;
++ dev_warn(&dev->dev, "Could not read event-blink-delay "
++ "property; using default %u\n",
++ val);
++ }
++ info->event_blink_delay = val;
++
++ /* default */
++ if (capebus_of_property_read_string(dev,
++ "version", version,
++ "vsense-name", &info->vsense_name) != 0) {
++ info->vsense_name = "AIN5";
++ dev_warn(&dev->dev, "Could not read vsense-name property; "
++ "using default %u\n",
++ val);
++ }
++
++ if (capebus_of_property_read_u32(dev,
++ "version", version,
++ "vsense-scale", &info->vsense_scale) != 0) {
++ info->vsense_scale = 37325; /* 373.25 */
++ dev_warn(&dev->dev, "Could not read vsense-scale property; "
++ "using default %u\n",
++ info->vsense_scale);
++ }
++
++ info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
++ if (IS_ERR(info->vsense_channel)) {
++ dev_err(&dev->dev, "Could not get AIN5 analog input\n");
++ err = PTR_ERR(info->vsense_channel);
++ goto err_no_vsense;
++ }
++
++ dev_info(&dev->dev, "ready\n");
++
++ err = bonegeiger_start(dev);
++ if (err != 0) {
++ dev_err(&dev->dev, "Could not start geiger device\n");
++ goto err_no_start;
++ }
++
++ return 0;
++
++err_no_start:
++ iio_channel_release(info->vsense_channel);
++err_no_vsense:
++ bone_capebus_remove_generic(info->geninfo);
++err_no_generic:
++ led_trigger_unregister_simple(info->run_led);
++ led_trigger_unregister_simple(info->event_led);
++ sysfs_put(info->counter_sd);
++err_no_counter_dirent:
++ bonegeiger_sysfs_unregister(dev);
++err_no_sysfs:
++ free_irq(info->event_irq, dev);
++err_no_irq:
++ gpio_free(info->event_gpio);
++err_no_gpio:
++ pwm_put(info->pwm_dev);
++err_no_pwm:
++ devm_kfree(&dev->dev, info);
++err_no_mem:
++ return err;
++}
++
++static void bonegeiger_remove(struct cape_dev *dev)
++{
++ struct bone_geiger_info *info = dev->drv_priv;
++
++ dev_info(&dev->dev, "Removing geiger cape driver...\n");
++
++ bonegeiger_stop(dev);
++
++ iio_channel_release(info->vsense_channel);
++ bone_capebus_remove_generic(info->geninfo);
++ led_trigger_unregister_simple(info->run_led);
++ led_trigger_unregister_simple(info->event_led);
++ sysfs_put(info->counter_sd);
++ bonegeiger_sysfs_unregister(dev);
++ free_irq(info->event_irq, dev);
++ gpio_free(info->event_gpio);
++ pwm_put(info->pwm_dev);
++}
++
++struct cape_driver bonegeiger_driver = {
++ .driver = {
++ .name = "bonegeiger",
++ .owner = THIS_MODULE,
++ .of_match_table = bonegeiger_of_match,
++ },
++ .probe = bonegeiger_probe,
++ .remove = bonegeiger_remove,
++};
++
++module_capebus_driver(bonegeiger_driver);
++
++MODULE_AUTHOR("Pantelis Antoniou");
++MODULE_DESCRIPTION("Beaglebone geiger cape");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bone-geiger-cape");
diff --git a/patches/linux-3.7/0158-capebus-Beaglebone-capebus-DT-update.patch b/patches/linux-3.7/0158-capebus-Beaglebone-capebus-DT-update.patch
new file mode 100644
index 0000000..329b541
--- /dev/null
+++ b/patches/linux-3.7/0158-capebus-Beaglebone-capebus-DT-update.patch
@@ -0,0 +1,748 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:16:57 +0200
+Subject: [PATCH] capebus: Beaglebone capebus DT update
+
+Update the common beaglebone's DTS with the required DT
+entries for all known working capes as of now.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 689 +++++++++++++++++++++++++++--
+ 1 file changed, 659 insertions(+), 30 deletions(-)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 99240a5..46d5f27 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -51,6 +51,143 @@
+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */
+ >;
+ };
++ i2c2_pins: pinmux_i2c2_pins {
++ pinctrl-single,pins = <
++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
++ >;
++ };
++
++ bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_dvi_cape_dvi_00A0_pins: pinmux_bone_dvi_cape_dvi_00A0_pins {
++ pinctrl-single,pins = <
++ 0x1c 0x07 /* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
++
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_dvi_cape_dvi_00A1_pins: pinmux_bone_dvi_cape_dvi_00A1_pins {
++ pinctrl-single,pins = <
++ 0x84 0x07 /* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - DVIPDn */
++
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins {
++ pinctrl-single,pins = <
++ 0xe4 0x07 /* lcd_hsync.gpio2_23, OUTPUT | MODE7 */
++ 0xec 0x07 /* lcd_ac_bias_en.gpio2_25, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_geiger_cape_pins: pinmux_bone_geiger_cape_pins {
++ pinctrl-single,pins = <
++ 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ /* 0x19c 0x34 */ /* mcasp0_ahclkr.eCAP2_in_PWM2_out, OMAP_MUX_MODE4 | INPUT_PULLUP */
++ 0x19c 0x37 /* mcasp0_ahclkr.gpio3_17, OMAP_MUX_MODE4 | INPUT_PULLUP */
++ >;
++ };
++
++ bone_lcd3_cape_led_00A0_pins: pinmux_bone_lcd3_cape_led_00A0_pins {
++ pinctrl-single,pins = <
++ 0x48 0x07 /* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
++ 0x4c 0x07 /* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
++ >;
++ };
++
++ bone_lcd3_cape_lcd_pins: pinmux_bone_lcd3_cape_lcd_pins {
++ pinctrl-single,pins = <
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ bone_lcd3_cape_keys_00A0_pins: pinmux_bone_lcd3_cape_keys_00A0_pins {
++ pinctrl-single,pins = <
++ 0x040 0x2f /* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
++ 0x044 0x2f /* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
++ 0x1a4 0x2f /* mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
++ 0x078 0x2f /* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
++ 0x164 0x2f /* ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
++ >;
++ };
++
++ pwm_bl_pins: pinmux_pwm_bl_pins {
++ pinctrl-single,pins = <
++ 0x4c 0x06 /* gpmc_a3.ehrpwm1b, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ // 0x48 0x06 /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
++ weather_cape_w1_pins: pinmux_weather_cape_w1_pins {
++ pinctrl-single,pins = <
++ 0x0c 0x37 /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */
++ >;
++ };
+ };
+
+ ocp {
+@@ -92,16 +229,6 @@
+ };
+ };
+
+- i2c1: i2c@44e0b000 {
+- status = "okay";
+- clock-frequency = <400000>;
+-
+- tps: tps@24 {
+- reg = <0x24>;
+- };
+-
+- };
+-
+ gpevt {
+ compatible = "gpevt";
+ pinctrl-names = "default";
+@@ -110,15 +237,117 @@
+ dma-names = "gpioevt";
+ gpio-evt = <&gpio3 2 0>;
+ };
++
++ };
++
++ capebus: capebus@0 {
++ compatible = "bone-capebus";
++
++ bone_dvi_cape: cape@0 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_geiger_cape: cape@1 {
++ compatible = "bone-geiger-cape";
++ };
++
++ bone_lcd3_cape: cape@2 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_lcd7_cape: cape@3 {
++ compatible = "bone-lcd7-cape";
++ };
++
++ bone_weather_cape: cape@4 {
++ compatible = "bone-generic-cape";
++ };
++
++ bone_adafruit_cape: cape@5 {
++ compatible = "bone-generic-cape";
++ };
++
++ /* overrides; no EEPROM (prototyping) */
++// override@3 {
++// compatible = "bone-capebus-slot-override";
++// slot = <3>;
++// board-name = "Geiger Cape";
++// version = "00A0";
++// manufacturer = "Geiger Inc";
++// /* TODO: Add the rest */
++// };
++
++// override@2 {
++// compatible = "bone-capebus-slot-override";
++// slot = <2>;
++// board-name = "Weather Cape";
++// version = "00A0";
++// manufacturer = "CCO Inc";
++// /* TODO: Add the rest */
++// };
++
++// override@1 {
++// compatible = "bone-capebus-slot-override";
++// slot = <1>;
++// board-name = "Adafruit 1.8 Cape";
++// version = "00A0";
++// manufacturer = "Adafruit";
++// /* TODO: Add the rest */
++// };
++
++// override@0 {
++// compatible = "bone-capebus-slot-override";
++// slot = <0>;
++// board-name = "BeagleBone Weather CAPE";
++// version = "00A0";
++// manufacturer = "Beagleboardtoys";
++// /* TODO: Add the rest */
++// };
+ };
+
+- backlight {
+- compatible = "pwm-backlight";
+- pwms = <&ehrpwm1 0 500000 0>;
+- pwm-names = "st7735fb";
+- brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+- default-brightness-level = <50>; /* index to the array above */
+- };
++};
++
++&i2c0 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ tps: tps@24 {
++ reg = <0x24>;
++ };
++
++ baseboard_eeprom: baseboard_eeprom@50 {
++ compatible = "at,24c256";
++ reg = <0x50>;
++ };
++};
++
++&i2c2 {
++ status = "okay";
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2c2_pins>;
++
++ clock-frequency = <100000>;
++
++ /* OK, I know these are cape but for now it will do */
++ cape_eeprom_0: cape_eeprom_0@54 {
++ compatible = "at,24c256";
++ reg = <0x54>;
++ };
++
++ cape_eeprom_1: cape_eeprom_1@55 {
++ compatible = "at,24c256";
++ reg = <0x55>;
++ };
++
++ cape_eeprom_2: cape_eeprom_2@56 {
++ compatible = "at,24c256";
++ reg = <0x56>;
++ };
++
++ cape_eeprom_3: cape_eeprom_3@57 {
++ compatible = "at,24c256";
++ reg = <0x57>;
++ };
+ };
+
+ /include/ "tps65217.dtsi"
+@@ -165,6 +394,7 @@
+ regulator-always-on;
+ };
+ };
++
+ };
+
+ &mmc1 {
+@@ -172,21 +402,8 @@
+ };
+
+ &spi1 {
+- status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+-
+- lcd@0 {
+- compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+- spi-max-frequency = <8000000>;
+- reg = <0>;
+- spi-cpol;
+- spi-cpha;
+- pinctrl-names = "default";
+- pinctrl-0 = <&lcd_pins>;
+- st7735-rst = <&gpio4 19 0>;
+- st7735-dc = <&gpio4 21 0>;
+- };
+ };
+
+ &edma {
+@@ -200,3 +417,415 @@
+ &cpsw_emac1 {
+ phy_id = "4a101000.mdio:01";
+ };
++
++&ehrpwm1 {
++ status = "okay";
++};
++
++&capebus {
++ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
++};
++
++&bone_dvi_cape {
++ board-name = "BeagleBone DVI-D CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ version@00A0 {
++ version = "00A0";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 7 0>;
++ };
++ };
++
++ version@00A1 {
++ version = "00A1", "01";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 31 0>;
++ };
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_led_pins>;
++
++ dvi-led0 {
++ label = "dvi:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ dvi-led1 {
++ label = "dvi:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++ };
++};
++
++&bone_geiger_cape {
++ board-name = "Geiger Cape";
++
++ /* note that these can't be versioned... */
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "bone-geiger-cape";
++
++ pwm-frequency = <20000>; /* 20KHz */
++ pwm-duty-cycle = <60>; /* 60% */
++
++ event-blink-delay = <30>; /* 30ms */
++
++ gpios = <&gpio4 17 0>; /* pulse */
++
++ vsense-name = "AIN5"; /* analog vsense */
++ vsense-scale = <37325>; /* scaling */
++
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ adc-channels = <8>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_led_pins>;
++
++ geiger-led0 {
++ label = "geiger:green:usr0";
++ gpios = <&gpio3 23 0>;
++ linux,default-trigger = "geiger-run";
++ default-state = "off";
++ };
++
++ geiger-led1 {
++ label = "geiger:red:usr1";
++ gpios = <&gpio3 25 0>;
++ linux,default-trigger = "geiger-event";
++ default-state = "off";
++ };
++ };
++};
++
++&bone_lcd3_cape {
++ board-name = "BeagleBone LCD3 CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ lcd3 {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++
++ ti,hwmods = "lcdc";
++
++ disp-pll = <16000000>;
++ panel-type = "CDTech_S035Q01";
++ };
++
++ /* same thing as above */
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++ };
++
++ version@00A0 {
++ version = "00A0";
++
++ backlight {
++ compatible = "tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++
++ tps = <&tps>; /* link to the tps */
++ brightness = <100>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
++
++ lcd3-led0 {
++ label = "lcd3:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ lcd3-led1 {
++ label = "lcd3:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@1 {
++ debounce_interval = <50>;
++ linux,code = <105>;
++ label = "left";
++ gpios = <&gpio2 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@2 {
++ debounce_interval = <50>;
++ linux,code = <106>;
++ label = "right";
++ gpios = <&gpio2 17 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@3 {
++ debounce_interval = <50>;
++ linux,code = <103>;
++ label = "up";
++ gpios = <&gpio4 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio2 28 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 7 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++ };
++};
++
++&bone_lcd7_cape {
++ board-name = "BeagleBone LCD7 CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ lcd7 {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
++
++ ti,hwmods = "lcdc";
++
++ disp-pll = <60000000>;
++ panel-type = "TFC_S9700RTWV35TR_01B";
++ };
++
++ /* same thing as above */
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++ };
++
++ version@00A0 {
++ version = "00A0";
++
++ backlight {
++ compatible = "tps65217-backlight";
++ isel = <1>;
++ fdim = <200>;
++
++ tps = <&tps>; /* link to the tps */
++ brightness = <100>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
++
++ lcd3-led0 {
++ label = "lcd3:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ lcd3-led1 {
++ label = "lcd3:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "cpu0";
++ default-state = "off";
++ };
++ };
++
++ gpio_keys {
++ compatible = "gpio-keys";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ button@1 {
++ debounce_interval = <50>;
++ linux,code = <105>;
++ label = "left";
++ gpios = <&gpio2 16 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@2 {
++ debounce_interval = <50>;
++ linux,code = <106>;
++ label = "right";
++ gpios = <&gpio2 17 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@3 {
++ debounce_interval = <50>;
++ linux,code = <103>;
++ label = "up";
++ gpios = <&gpio4 19 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@4 {
++ debounce_interval = <50>;
++ linux,code = <108>;
++ label = "down";
++ gpios = <&gpio2 28 0x0>;
++ gpio-key,wakeup;
++ autorepeat;
++ };
++ button@5 {
++ debounce_interval = <50>;
++ linux,code = <28>;
++ label = "enter";
++ gpios = <&gpio1 7 0x0>;
++ gpio-key,wakeup;
++ };
++ };
++ };
++};
++
++&bone_weather_cape {
++ board-name = "BeagleBone Weather CAPE";
++
++ i2c2-devices {
++ compatible = "i2c-dt";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&i2c2>;
++
++ /* Ambient light sensor */
++ tsl2550@39 {
++ compatible = "tsl,tsl2550";
++ reg = <0x39>;
++ };
++
++ /* Humidity Sensor */
++ sht21@40 {
++ compatible = "sensiron,sht21";
++ reg = <0x40>;
++ };
++
++ /* Barometric pressure sensor */
++ bmp085@77 {
++ compatible = "bosch,bmp085";
++ reg = <0x77>;
++ };
++ };
++
++ onewire@0 {
++ compatible = "w1-gpio";
++ pinctrl-names = "default";
++ pinctrl-0 = <&weather_cape_w1_pins>;
++ status = "okay";
++
++ gpios = <&gpio2 3 0>;
++ };
++
++};
++
++&bone_adafruit_cape {
++ board-name = "Adafruit 1.8 Cape";
++
++ backlight {
++ compatible = "pwm-backlight";
++ pinctrl-names = "default";
++ pinctrl-0 = <&pwm_bl_pins>;
++
++ pwms = <&ehrpwm1 1 500000 0>;
++ pwm-names = "st7735fb";
++ brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
++ default-brightness-level = <50>; /* index to the array above */
++ };
++
++ spi1-devices {
++ compatible = "spi-dt";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&spi1>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++
++ };
++};
diff --git a/patches/linux-3.7/0159-capebus-Document-DT-bindings.patch b/patches/linux-3.7/0159-capebus-Document-DT-bindings.patch
new file mode 100644
index 0000000..f0125ec
--- /dev/null
+++ b/patches/linux-3.7/0159-capebus-Document-DT-bindings.patch
@@ -0,0 +1,471 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 31 Oct 2012 16:16:44 +0200
+Subject: [PATCH] capebus: Document DT bindings
+
+Describe capebus DT bindings in detail.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ .../capebus/bone-capebus-slot-override.txt | 28 ++++++
+ .../devicetree/bindings/capebus/bone-capebus.txt | 50 ++++++++++
+ .../bindings/capebus/bone-geiger-cape.txt | 78 ++++++++++++++++
+ .../bindings/capebus/bone-generic-cape.txt | 97 ++++++++++++++++++++
+ .../devicetree/bindings/capebus/da8xx-dt.txt | 31 +++++++
+ .../devicetree/bindings/capebus/i2c-dt.txt | 42 +++++++++
+ .../devicetree/bindings/capebus/spi-dt.txt | 37 ++++++++
+ .../devicetree/bindings/capebus/ti-tscadc-dt.txt | 34 +++++++
+ 8 files changed, 397 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/bone-capebus.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/da8xx-dt.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/i2c-dt.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/spi-dt.txt
+ create mode 100644 Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
+
+diff --git a/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt b/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
+new file mode 100644
+index 0000000..733d977
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/bone-capebus-slot-override.txt
+@@ -0,0 +1,28 @@
++* Beagle bone capebus slot override bindings
++
++The beagle bone capebus node can have slot override nodes. These nodes describe
++ an override that will take place in the specified slot.
++ Many boards during the prototype phase don't have an EEPROM (or are even
++ wired in such a way that an eeprom cannot be added). In that case you can
++ specify an override that will make everything work as if a real EEPROM was
++ there.
++
++Required properties:
++- compatible: Override node must have the form "bone-capebus-slot-override"
++- slot: Identifies the slot# to override.
++- board-name: The cape's name as if provided by the board-name EEPROM field
++
++Optional properties:
++- version: The cape's version as if provided by the version EEPROM field.
++- manufacturer: The cape's manufacturer as if provided by the manufacturer
++ EEPROM field.
++
++Example:
++
++override@1 {
++ compatible = "bone-capebus-slot-override";
++ slot = <1>;
++ board-name = "Adafruit 1.8 Cape";
++ version = "00A0";
++ manufacturer = "Adafruit";
++};
+diff --git a/Documentation/devicetree/bindings/capebus/bone-capebus.txt b/Documentation/devicetree/bindings/capebus/bone-capebus.txt
+new file mode 100644
+index 0000000..6d8a08d
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/bone-capebus.txt
+@@ -0,0 +1,50 @@
++* Beagle bone capebus bindings
++
++The beaglebone capebus implementation is using a single capebus
++node contained in the root node. A beaglebone cape is identified
++at by reading an EEPROM at on of 4 possible addresses on the I2C2 bus.
++
++Required properties:
++- compatible: Every beaglebone compatible capebus node shall have the
++ form "bone-capebus";
++- slots: An array of phandles pointing to the I2C node of an EEPROM that
++ contains the cape information.
++
++Optional properties:
++
++The child nodes of the capebus node can contain either cape nodes
++or override nodes. Those cape nodes are described in their respective
++binding files.
++
++- override nodes: Describe an override that will take place in the specified
++ slot. Many boards during the prototype phase don't have an EEPROM (or are even
++ wired in such a way that an eeprom cannot be added). In that case you can
++ specify an override that will make everything work as if a real EEPROM was
++ there.
++
++Override node required properties:
++- compatible: For override node must have the form "bone-capebus-slot-override"
++- slot: Identifies the slot# to override.
++- board-name: The cape's name as if provided by the board-name EEPROM field
++
++Override node optional properties:
++- version: The cape's version as if provided by the version EEPROM field.
++- manufacturer: The cape's manufacturer as if provided by the manufacturer
++ EEPROM field.
++
++Example:
++
++capebus: capebus@0 {
++ compatible = "bone-capebus";
++
++ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
++
++ [cape-nodes]
++ [override-nodes]
++
++ bone_adafruit_cape: cape@5 {
++ compatible = "bone-generic-cape";
++ // read the bone-generic-cape bindings for the rest
++ ...
++ };
++};
+diff --git a/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt b/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
+new file mode 100644
+index 0000000..a2ed81c
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/bone-geiger-cape.txt
+@@ -0,0 +1,78 @@
++* Beagle bone geiger cape
++
++ A geiger cape is your run of the mill particle detector measuring
++ ionizing radiation. It is also the first example of how a non-generic
++ cape can be supported by capebus.
++
++ The geiger cape can not be created via instantiation of a generic cape
++ since the component need to work together.
++
++Required properties:
++- compatible: Generic cape nodes must have the form "bone-geiger-cape"
++- board-name: The cape's name as if provided by the board-name EEPROM field
++- pwms: Pointer to the PWM we require
++- pwm-names: Name of the PWM.
++- pwm-frequency: Frequency of the PWM in Hz
++- pwm-duty-cycle: Duty cycle in percent
++- event-blink-delay: Blink delay of the event led
++- gpios: GPIO on which an event is detected
++- vsense-name: Name of the analog input for vsense
++- vsense-scale: Vsense scale to convert to mVolts
++- ti-tscadc-dt compatible node for the ADC configuration
++- gpio-leds compatible node for the LED configuration
++
++Optional properties:
++
++The geiger cape supports the standard pinctrl properties.
++
++Example:
++
++bone_geiger_cape: cape@1 {
++ compatible = "bone-geiger-cape";
++ board-name = "Geiger Cape";
++
++ /* note that these can't be versioned... */
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_pins>;
++
++ pwms = <&ehrpwm1 0 500000 0>;
++ pwm-names = "bone-geiger-cape";
++
++ pwm-frequency = <20000>; /* 20KHz */
++ pwm-duty-cycle = <60>; /* 60% */
++
++ event-blink-delay = <30>; /* 30ms */
++
++ gpios = <&gpio4 17 0>; /* pulse */
++
++ vsense-name = "AIN5"; /* analog vsense */
++ vsense-scale = <37325>; /* scaling */
++
++ tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ adc-channels = <8>;
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_geiger_cape_led_pins>;
++
++ geiger-led0 {
++ label = "geiger:green:usr0";
++ gpios = <&gpio3 23 0>;
++ linux,default-trigger = "geiger-run";
++ default-state = "off";
++ };
++
++ geiger-led1 {
++ label = "geiger:red:usr1";
++ gpios = <&gpio3 25 0>;
++ linux,default-trigger = "geiger-event";
++ default-state = "off";
++ };
++ };
++};
+diff --git a/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt b/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
+new file mode 100644
+index 0000000..71ad2f4
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/bone-generic-cape.txt
+@@ -0,0 +1,97 @@
++* Beagle bone generic cape
++
++ A generic cape is one form of cape that doesn't require any per-cape
++ driver for it to function. It is enough for the cape's node to be
++ instantiated in the right manner and the functions that the cape provides
++ will be available to Linux. A large number of capes fall in this category
++ like LCD/DVI/VGA capes, audio capes, capes with a number of gpio buttons,
++ capes with standard I2C/SPI/W1 parts etc.
++ All that's required is to describe the parts of the cape in the DT and
++ how they utilize the SoC peripherals and it will work, without having
++ to write any other driver, or modify the board support package.
++
++ As a sidenote, a large part of the complexity of capes have to do
++ with version management. A cape as it goes through various steps of evolution
++ changes. These changes are codified by the version field on the EEPROM.
++ It is important that version management can be kept as simple as possible.
++
++ The generic concept works by instantiating the child nodes that are
++ contained in the cape node. By default nodes that are present in the
++ root of the node are activated for any version. Version nodes can
++ contain per-version changes. In the example the da8xx-dt node differs
++ in the way it's instantiated, and this is expressed by the version nodes.
++
++Required properties:
++- compatible: Generic cape nodes must have the form "bone-generic-cape"
++- board-name: The cape's name as if provided by the board-name EEPROM field
++
++Optional properties:
++- version: Only valid in a version node, and it contains the list of compatible
++ versions this node contains.
++
++The standard supported nodes of the generic cape are:
++
++gpio-leds, tps65217-backlight, gpio-keys, w1-gpio, pwm-backlight
++
++The following nodes are supported via a capebus specific bridge devices, and
++their bindings described in their respective files:
++
++ti-tscadc-dt, da8xx-dt, i2c-dt, spi-dt
++
++Example:
++
++bone_dvi_cape: cape@0 {
++
++ compatible = "bone-generic-cape";
++ board-name = "BeagleBone DVI-D CAPE";
++
++ /* hacky, since this is not a proper DT platform device */
++ /* but until we have DT bindings... */
++ version@00A0 {
++ version = "00A0";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 7 0>;
++ };
++ };
++
++ version@00A1 {
++ version = "00A1", "01";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 31 0>;
++ };
++ };
++
++ gpio-leds {
++ compatible = "gpio-leds";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_led_pins>;
++
++ dvi-led0 {
++ label = "dvi:green:usr0";
++ gpios = <&gpio2 18 0>;
++ linux,default-trigger = "heartbeat";
++ default-state = "off";
++ };
++
++ dvi-led1 {
++ label = "dvi:green:usr1";
++ gpios = <&gpio2 19 0>;
++ linux,default-trigger = "mmc0";
++ default-state = "off";
++ };
++ };
++};
+diff --git a/Documentation/devicetree/bindings/capebus/da8xx-dt.txt b/Documentation/devicetree/bindings/capebus/da8xx-dt.txt
+new file mode 100644
+index 0000000..0b84063
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/da8xx-dt.txt
+@@ -0,0 +1,31 @@
++* DA8XX DT bindins
++
++ This is an adapter device for use in device tree cases, since the
++ drivers DT bindings are not yet ready. It is bound to get away once
++ they are in place. Note that there is no capebus prefix, since there's
++ not really any dependence on capebus; the drivers can be moved out of
++ capebus if need be.
++
++Required properties:
++- compatible: Must have the form "da8xx-dt"
++- ti,hwmods: Must have the form "lcdc" (until hwmod DT is complete)
++- disp-pll: PLL value
++- panel-type: Name of the panel type connected
++
++Optional properties:
++powerdn-gpio: GPIO controlling power
++
++Note that the pinctrl bindings are supported.
++
++Example:
++
++dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
++ ti,hwmods = "lcdc";
++
++ disp-pll = <560000000>;
++ panel-type = "1024x768@60";
++ powerdn-gpio = <&gpio2 7 0>;
++};
+diff --git a/Documentation/devicetree/bindings/capebus/i2c-dt.txt b/Documentation/devicetree/bindings/capebus/i2c-dt.txt
+new file mode 100644
+index 0000000..79a042a
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/i2c-dt.txt
+@@ -0,0 +1,42 @@
++* I2C DT bindings
++
++ This is an adapter device for use in device tree cases.
++ What we want to do is to add a number of I2C devices connected
++ to a specified i2c adapter node, and instantiate them on
++ successful cape match. Not only that, normally I2C adapters
++ are disabled in the DT tree, so in that case we enable them
++ first and then go about our business.
++
++Required properties:
++- compatible: Must have the form "i2c-dt"
++- parent: The phandle of the i2c adapter node
++- #address-cells: The same as the parent i2c adapter node
++- #size-cells: The same as the parent i2c adapter node
++
++Example:
++
++i2c2-devices {
++ compatible = "i2c-dt";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&i2c2>;
++
++ /* Ambient light sensor */
++ tsl2550@39 {
++ compatible = "tsl,tsl2550";
++ reg = <0x39>;
++ };
++
++ /* Humidity Sensor */
++ sht21@40 {
++ compatible = "sensiron,sht21";
++ reg = <0x40>;
++ };
++
++ /* Barometric pressure sensor */
++ bmp085@77 {
++ compatible = "bosch,bmp085";
++ reg = <0x77>;
++ };
++};
+diff --git a/Documentation/devicetree/bindings/capebus/spi-dt.txt b/Documentation/devicetree/bindings/capebus/spi-dt.txt
+new file mode 100644
+index 0000000..fd70fc4
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/spi-dt.txt
+@@ -0,0 +1,37 @@
++* SPI DT bindings
++
++ This is an adapter device for use in device tree cases.
++ What we want to do is to add a number of SPI devices connected
++ to a specified spi node, and instantiate them on
++ successful cape match. Not only that, normally SPI nodes
++ are disabled in the DT tree, so in that case we enable them
++ first and then go about our business.
++
++Required properties:
++- compatible: Must have the form "spi-dt"
++- parent: The phandle of the spi node
++- #address-cells: The same as the parent spi node
++- #size-cells: The same as the parent spi node
++
++Example:
++
++spi1-devices {
++ compatible = "spi-dt";
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ parent = <&spi1>;
++
++ lcd@0 {
++ compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
++ spi-max-frequency = <8000000>;
++ reg = <0>;
++ spi-cpol;
++ spi-cpha;
++ pinctrl-names = "default";
++ pinctrl-0 = <&lcd_pins>;
++ st7735-rst = <&gpio4 19 0>;
++ st7735-dc = <&gpio4 21 0>;
++ };
++
++};
+diff --git a/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt b/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
+new file mode 100644
+index 0000000..44ad4f2
+--- /dev/null
++++ b/Documentation/devicetree/bindings/capebus/ti-tscadc-dt.txt
+@@ -0,0 +1,34 @@
++* TI's TSCADC Device Tree adapter
++
++ This is an adapter device for use in device tree cases, since the
++ drivers DT bindings are not yet ready. It is bound to get away once
++ they are in place. Note that there is no capebus prefix, since there's
++ not really any dependence on capebus; the drivers can be moved out of
++ capebus if need be.
++
++Required properties:
++- compatible: Must have the form "ti-tscadc-dt"
++- ti,hwmods: Must have the form "adc_tsc" (until hwmod DT is complete)
++
++Optional properties:
++- adc-channels: Number of ADC channels the driver should provide.
++- tsc-wires: Number of touchscreen wires
++- tsc-x-plate-resistance: Touchscreen X plate resistance value
++- tsc-steps: Touchscreen steps
++
++Note if either adc-channels or tsc-wires are missing their respective
++values are set to 0.
++
++Example:
++
++tscadc {
++ compatible = "ti-tscadc-dt";
++
++ ti,hwmods = "adc_tsc";
++
++ tsc-wires = <4>;
++ tsc-x-plate-resistance = <200>;
++ tsc-steps = <6>;
++
++ adc-channels = <4>;
++};
diff --git a/patches/linux-3.7/0160-capebus-Documentation-capebus-summary.patch b/patches/linux-3.7/0160-capebus-Documentation-capebus-summary.patch
new file mode 100644
index 0000000..e8cc83a
--- /dev/null
+++ b/patches/linux-3.7/0160-capebus-Documentation-capebus-summary.patch
@@ -0,0 +1,58 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Wed, 31 Oct 2012 16:49:14 +0200
+Subject: [PATCH] capebus: Documentation; capebus-summary
+
+Small summary of capebus.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ Documentation/capebus/capebus-summary | 40 +++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+ create mode 100644 Documentation/capebus/capebus-summary
+
+diff --git a/Documentation/capebus/capebus-summary b/Documentation/capebus/capebus-summary
+new file mode 100644
+index 0000000..742e33c
+--- /dev/null
++++ b/Documentation/capebus/capebus-summary
+@@ -0,0 +1,40 @@
++Overview of Linux kernel Capebus support
++========================================
++
++30-Oct-2012
++
++What is Capebus?
++----------------
++Capebus is an abstract concept. There's no such thing as a vanilla physical
++capebus, what is there is a concept and a method on how various capebus
++based implementations can be made.
++
++Capebus is created to address the problem of many SoCs that can provide a
++multitude of hardware interfaces but in order to keep costs down the main
++boards only support a limited number of them. The rest are typically brought
++out to pin connectors on to which other boards, named capes are connected and
++allow those peripherals to be used.
++
++These capes connect to the SoC interfaces but might also contain various other
++parts that may need some kind of driver to work.
++
++Since SoCs have limited pins and pin muxing options, not all capes can work
++together so some kind of resource tracking (at least for the pins in use) is
++required.
++
++Before capebus all of this took place in the board support file, and frankly
++for boards with too many capes it was becoming unmanageable.
++
++Capebus provides a virtual bus, which along with a board specific controller,
++cape drivers can be written using the standard Linux device model.
++
++What kind of systems/boards capebus supports?
++---------------------------------------------
++
++The core capebus infrastructure is not depended on any specific board.
++However capebus needs a board controller to provide services to the cape devices
++it controls. Services like addressing and resource reservation are provided
++by the board controller.
++
++Capebus at the moment only support TI's Beaglebone platform.
++
diff --git a/patches/linux-3.7/0161-beaglebone-Update-default-config-for-capebus.patch b/patches/linux-3.7/0161-beaglebone-Update-default-config-for-capebus.patch
new file mode 100644
index 0000000..a48595a
--- /dev/null
+++ b/patches/linux-3.7/0161-beaglebone-Update-default-config-for-capebus.patch
@@ -0,0 +1,3909 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Tue, 30 Oct 2012 21:17:39 +0200
+Subject: [PATCH] beaglebone: Update default config for capebus
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ defconfig | 3893 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 3893 insertions(+)
+ create mode 100644 defconfig
+
+diff --git a/defconfig b/defconfig
+new file mode 100644
+index 0000000..ee51fa1
+--- /dev/null
++++ b/defconfig
+@@ -0,0 +1,3893 @@
++#
++# Automatically generated file; DO NOT EDIT.
++# Linux/arm 3.7.0-rc2 Kernel Configuration
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_HAVE_PROC_CPU=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_ARCH_HAS_CPUFREQ=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_ARM_PATCH_PHYS_VIRT=y
++CONFIG_NEED_MACH_GPIO_H=y
++CONFIG_GENERIC_BUG=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_HAVE_IRQ_WORK=y
++CONFIG_IRQ_WORK=y
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_XZ=y
++CONFIG_HAVE_KERNEL_LZO=y
++# CONFIG_KERNEL_GZIP is not set
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_XZ is not set
++CONFIG_KERNEL_LZO=y
++CONFIG_DEFAULT_HOSTNAME="(none)"
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_POSIX_MQUEUE_SYSCTL=y
++# CONFIG_FHANDLE is not set
++# CONFIG_AUDIT is not set
++CONFIG_HAVE_GENERIC_HARDIRQS=y
++
++#
++# IRQ subsystem
++#
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_GENERIC_IRQ_SHOW=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_CHIP=y
++CONFIG_IRQ_DOMAIN=y
++# CONFIG_IRQ_DOMAIN_DEBUG is not set
++CONFIG_SPARSE_IRQ=y
++CONFIG_KTIME_SCALAR=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
++
++#
++# Timers subsystem
++#
++CONFIG_TICK_ONESHOT=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++
++#
++# CPU/Task time and stats accounting
++#
++CONFIG_TICK_CPU_ACCOUNTING=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_TASKSTATS=y
++CONFIG_TASK_DELAY_ACCT=y
++CONFIG_TASK_XACCT=y
++CONFIG_TASK_IO_ACCOUNTING=y
++
++#
++# RCU Subsystem
++#
++CONFIG_TREE_RCU=y
++# CONFIG_PREEMPT_RCU is not set
++CONFIG_RCU_FANOUT=32
++CONFIG_RCU_FANOUT_LEAF=16
++# CONFIG_RCU_FANOUT_EXACT is not set
++# CONFIG_RCU_FAST_NO_HZ is not set
++# CONFIG_TREE_RCU_TRACE is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=17
++CONFIG_CGROUPS=y
++# CONFIG_CGROUP_DEBUG is not set
++# CONFIG_CGROUP_FREEZER is not set
++# CONFIG_CGROUP_DEVICE is not set
++# CONFIG_CPUSETS is not set
++# CONFIG_CGROUP_CPUACCT is not set
++# CONFIG_RESOURCE_COUNTERS is not set
++# CONFIG_CGROUP_PERF is not set
++CONFIG_CGROUP_SCHED=y
++CONFIG_FAIR_GROUP_SCHED=y
++# CONFIG_CFS_BANDWIDTH is not set
++# CONFIG_RT_GROUP_SCHED is not set
++# CONFIG_BLK_CGROUP is not set
++# CONFIG_CHECKPOINT_RESTORE is not set
++CONFIG_NAMESPACES=y
++CONFIG_UTS_NS=y
++CONFIG_IPC_NS=y
++CONFIG_PID_NS=y
++CONFIG_NET_NS=y
++CONFIG_SCHED_AUTOGROUP=y
++# CONFIG_SYSFS_DEPRECATED is not set
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_XZ is not set
++# CONFIG_RD_LZO is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EXPERT=y
++CONFIG_HAVE_UID16=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++CONFIG_KALLSYMS_ALL=y
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=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_EMBEDDED is not set
++CONFIG_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++CONFIG_PERF_EVENTS=y
++# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_COMPAT_BRK=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++CONFIG_OPROFILE=m
++CONFIG_HAVE_OPROFILE=y
++CONFIG_KPROBES=y
++# CONFIG_JUMP_LABEL is not set
++CONFIG_KRETPROBES=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_ARCH_TRACEHOOK=y
++CONFIG_HAVE_DMA_ATTRS=y
++CONFIG_HAVE_DMA_CONTIGUOUS=y
++CONFIG_USE_GENERIC_SMP_HELPERS=y
++CONFIG_GENERIC_SMP_IDLE_THREAD=y
++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
++CONFIG_HAVE_CLK=y
++CONFIG_HAVE_DMA_API_DEBUG=y
++CONFIG_HAVE_HW_BREAKPOINT=y
++CONFIG_HAVE_ARCH_JUMP_LABEL=y
++CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
++CONFIG_GENERIC_KERNEL_THREAD=y
++CONFIG_GENERIC_KERNEL_EXECVE=y
++CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
++CONFIG_MODULES_USE_ELF_REL=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_GCOV_KERNEL is not set
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_FORCE_LOAD=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++# CONFIG_MODULE_SIG is not set
++CONFIG_STOP_MACHINE=y
++CONFIG_BLOCK=y
++CONFIG_LBDAF=y
++CONFIG_BLK_DEV_BSG=y
++CONFIG_BLK_DEV_BSGLIB=y
++CONFIG_BLK_DEV_INTEGRITY=y
++
++#
++# 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 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=y
++# CONFIG_SYSV68_PARTITION is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++CONFIG_PADATA=y
++CONFIG_ASN1=m
++CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
++CONFIG_INLINE_READ_UNLOCK=y
++CONFIG_INLINE_READ_UNLOCK_IRQ=y
++CONFIG_INLINE_WRITE_UNLOCK=y
++CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
++CONFIG_MUTEX_SPIN_ON_OWNER=y
++CONFIG_FREEZER=y
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# CONFIG_ARCH_MULTIPLATFORM 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_BCM2835 is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_SIRF is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_MXS is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_LPC32XX is not set
++# CONFIG_ARCH_TEGRA is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C24XX is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_S5P64X0 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_EXYNOS is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_PLAT_SPEAR is not set
++# CONFIG_ARCH_DAVINCI is not set
++CONFIG_ARCH_OMAP=y
++# CONFIG_ARCH_VT8500 is not set
++# CONFIG_ARCH_ZYNQ is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_KEYBOARD_GPIO_POLLED is not set
++
++#
++# TI OMAP Common Features
++#
++# CONFIG_ARCH_OMAP1 is not set
++CONFIG_ARCH_OMAP2PLUS=y
++
++#
++# OMAP Feature Selections
++#
++CONFIG_OMAP_RESET_CLOCKS=y
++CONFIG_OMAP_MUX=y
++CONFIG_OMAP_MUX_DEBUG=y
++CONFIG_OMAP_MUX_WARNINGS=y
++# CONFIG_OMAP_MBOX_FWK is not set
++CONFIG_OMAP_32K_TIMER=y
++# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
++CONFIG_OMAP_32K_TIMER_HZ=128
++CONFIG_OMAP_DM_TIMER=y
++CONFIG_OMAP_PM_NOOP=y
++CONFIG_MACH_OMAP_GENERIC=y
++
++#
++# TI OMAP2/3/4 Specific Features
++#
++CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
++CONFIG_SOC_HAS_OMAP2_SDRC=y
++# CONFIG_SOC_HAS_REALTIME_COUNTER is not set
++# CONFIG_ARCH_OMAP2 is not set
++CONFIG_ARCH_OMAP3=y
++CONFIG_ARCH_OMAP4=y
++# CONFIG_SOC_OMAP5 is not set
++CONFIG_SOC_OMAP3430=y
++# CONFIG_SOC_TI81XX is not set
++CONFIG_SOC_AM33XX=y
++CONFIG_OMAP_PACKAGE_CBB=y
++CONFIG_OMAP_PACKAGE_CBL=y
++CONFIG_OMAP_PACKAGE_CBS=y
++
++#
++# OMAP Board Type
++#
++CONFIG_MACH_OMAP3_BEAGLE=y
++# CONFIG_MACH_DEVKIT8000 is not set
++# CONFIG_MACH_OMAP_LDP is not set
++# CONFIG_MACH_OMAP3530_LV_SOM is not set
++# CONFIG_MACH_OMAP3_TORPEDO is not set
++# CONFIG_MACH_OVERO is not set
++# CONFIG_MACH_OMAP3EVM is not set
++# CONFIG_MACH_OMAP3517EVM is not set
++# CONFIG_MACH_CRANEBOARD is not set
++# CONFIG_MACH_OMAP3_PANDORA is not set
++# CONFIG_MACH_TOUCHBOOK is not set
++# CONFIG_MACH_OMAP_3430SDP is not set
++# CONFIG_MACH_NOKIA_RM680 is not set
++# CONFIG_MACH_NOKIA_RX51 is not set
++# CONFIG_MACH_OMAP_ZOOM2 is not set
++# CONFIG_MACH_OMAP_ZOOM3 is not set
++# CONFIG_MACH_CM_T35 is not set
++# CONFIG_MACH_CM_T3517 is not set
++CONFIG_MACH_IGEP0020=y
++# CONFIG_MACH_IGEP0030 is not set
++# CONFIG_MACH_SBC3530 is not set
++# CONFIG_MACH_OMAP_3630SDP is not set
++# CONFIG_MACH_OMAP_4430SDP is not set
++CONFIG_MACH_OMAP4_PANDA=y
++# CONFIG_OMAP3_EMU is not set
++# CONFIG_OMAP3_SDRC_AC_TIMING is not set
++# CONFIG_OMAP4_ERRATA_I688 is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_V7=y
++CONFIG_CPU_32v6K=y
++CONFIG_CPU_32v7=y
++CONFIG_CPU_ABRT_EV7=y
++CONFIG_CPU_PABRT_V7=y
++CONFIG_CPU_CACHE_V7=y
++CONFIG_CPU_CACHE_VIPT=y
++CONFIG_CPU_COPY_V6=y
++CONFIG_CPU_TLB_V7=y
++CONFIG_CPU_HAS_ASID=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_LPAE is not set
++# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
++CONFIG_ARM_THUMB=y
++CONFIG_ARM_THUMBEE=y
++# CONFIG_ARM_VIRT_EXT is not set
++CONFIG_SWP_EMULATE=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=y
++CONFIG_OUTER_CACHE_SYNC=y
++CONFIG_CACHE_L2X0=y
++CONFIG_CACHE_PL310=y
++CONFIG_ARM_L1_CACHE_SHIFT_6=y
++CONFIG_ARM_L1_CACHE_SHIFT=6
++CONFIG_ARM_DMA_MEM_BUFFERABLE=y
++CONFIG_ARM_NR_BANKS=8
++CONFIG_MULTI_IRQ_HANDLER=y
++# CONFIG_ARM_ERRATA_430973 is not set
++# CONFIG_ARM_ERRATA_458693 is not set
++# CONFIG_ARM_ERRATA_460075 is not set
++# CONFIG_ARM_ERRATA_742230 is not set
++# CONFIG_ARM_ERRATA_742231 is not set
++CONFIG_PL310_ERRATA_588369=y
++CONFIG_ARM_ERRATA_720789=y
++CONFIG_PL310_ERRATA_727915=y
++# CONFIG_ARM_ERRATA_743622 is not set
++# CONFIG_ARM_ERRATA_751472 is not set
++# CONFIG_PL310_ERRATA_753970 is not set
++# CONFIG_ARM_ERRATA_754322 is not set
++# CONFIG_ARM_ERRATA_754327 is not set
++# CONFIG_ARM_ERRATA_764369 is not set
++# CONFIG_PL310_ERRATA_769419 is not set
++# CONFIG_ARM_ERRATA_775420 is not set
++CONFIG_ARM_GIC=y
++CONFIG_TI_PRIV_EDMA=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_HAVE_SMP=y
++CONFIG_SMP=y
++CONFIG_SMP_ON_UP=y
++CONFIG_ARM_CPU_TOPOLOGY=y
++# CONFIG_SCHED_MC is not set
++# CONFIG_SCHED_SMT is not set
++CONFIG_HAVE_ARM_SCU=y
++# CONFIG_ARM_ARCH_TIMER is not set
++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=4
++CONFIG_HOTPLUG_CPU=y
++CONFIG_LOCAL_TIMERS=y
++CONFIG_ARCH_NR_GPIO=0
++# CONFIG_PREEMPT_NONE is not set
++CONFIG_PREEMPT_VOLUNTARY=y
++# CONFIG_PREEMPT is not set
++CONFIG_HZ=128
++CONFIG_THUMB2_KERNEL=y
++CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11=y
++CONFIG_ARM_ASM_UNIFIED=y
++CONFIG_AEABI=y
++CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++CONFIG_HAVE_ARCH_PFN_VALID=y
++CONFIG_HIGHMEM=y
++# CONFIG_HIGHPTE is not set
++CONFIG_HW_PERF_EVENTS=y
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_HAVE_MEMBLOCK=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_COMPACTION is not set
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_CROSS_MEMORY_ATTACH=y
++# CONFIG_CLEANCACHE is not set
++# CONFIG_FRONTSWAP is not set
++CONFIG_FORCE_MAX_ZONEORDER=12
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++# CONFIG_SECCOMP is not set
++# CONFIG_CC_STACKPROTECTOR is not set
++# CONFIG_XEN is not set
++
++#
++# Boot options
++#
++CONFIG_USE_OF=y
++CONFIG_ATAGS=y
++# CONFIG_DEPRECATED_PARAM_STRUCT is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_ARM_APPENDED_DTB=y
++CONFIG_ARM_ATAG_DTB_COMPAT=y
++CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
++# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
++CONFIG_CMDLINE=""
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_CRASH_DUMP is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++
++#
++# CPU Frequency scaling
++#
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_STAT_DETAILS=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_GENERIC_CPUFREQ_CPU0=y
++
++#
++# ARM CPU frequency scaling drivers
++#
++# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
++# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
++CONFIG_CPU_IDLE=y
++CONFIG_CPU_IDLE_GOV_LADDER=y
++CONFIG_CPU_IDLE_GOV_MENU=y
++CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=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_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++CONFIG_BINFMT_MISC=y
++# CONFIG_COREDUMP is not set
++
++#
++# Power management options
++#
++CONFIG_SUSPEND=y
++CONFIG_SUSPEND_FREEZER=y
++CONFIG_PM_SLEEP=y
++CONFIG_PM_SLEEP_SMP=y
++# CONFIG_PM_AUTOSLEEP is not set
++# CONFIG_PM_WAKELOCKS is not set
++CONFIG_PM_RUNTIME=y
++CONFIG_PM=y
++CONFIG_PM_DEBUG=y
++# CONFIG_PM_ADVANCED_DEBUG is not set
++# CONFIG_PM_TEST_SUSPEND is not set
++CONFIG_PM_SLEEP_DEBUG=y
++# CONFIG_APM_EMULATION is not set
++CONFIG_ARCH_HAS_OPP=y
++CONFIG_PM_OPP=y
++CONFIG_PM_CLK=y
++CONFIG_CPU_PM=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_ARM_CPU_SUSPEND=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_DIAG=m
++CONFIG_UNIX=y
++CONFIG_UNIX_DIAG=m
++CONFIG_XFRM=y
++CONFIG_XFRM_ALGO=y
++CONFIG_XFRM_USER=y
++# CONFIG_XFRM_SUB_POLICY is not set
++CONFIG_XFRM_MIGRATE=y
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_XFRM_IPCOMP=m
++CONFIG_NET_KEY=y
++CONFIG_NET_KEY_MIGRATE=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++# CONFIG_IP_FIB_TRIE_STATS is not set
++# CONFIG_IP_MULTIPLE_TABLES is not set
++# CONFIG_IP_ROUTE_MULTIPATH is not set
++# CONFIG_IP_ROUTE_VERBOSE is not set
++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_DEMUX=m
++CONFIG_NET_IPGRE=m
++# CONFIG_NET_IPGRE_BROADCAST is not set
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
++# CONFIG_NET_IPVTI 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=m
++CONFIG_INET_XFRM_MODE_TUNNEL=m
++CONFIG_INET_XFRM_MODE_BEET=m
++CONFIG_INET_LRO=m
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++CONFIG_INET_UDP_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_CUBIC=y
++# CONFIG_DEFAULT_RENO is not set
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++CONFIG_IPV6_PRIVACY=y
++CONFIG_IPV6_ROUTER_PREF=y
++CONFIG_IPV6_ROUTE_INFO=y
++CONFIG_IPV6_OPTIMISTIC_DAD=y
++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_SIT_6RD is not set
++CONFIG_IPV6_NDISC_NODETYPE=y
++CONFIG_IPV6_TUNNEL=m
++CONFIG_IPV6_GRE=m
++CONFIG_IPV6_MULTIPLE_TABLES=y
++CONFIG_IPV6_SUBTREES=y
++CONFIG_IPV6_MROUTE=y
++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IPV6_PIMSM_V2=y
++# CONFIG_NETLABEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
++CONFIG_NETFILTER=y
++# CONFIG_NETFILTER_DEBUG is not set
++CONFIG_NETFILTER_ADVANCED=y
++CONFIG_BRIDGE_NETFILTER=y
++
++#
++# Core Netfilter Configuration
++#
++# CONFIG_NETFILTER_NETLINK_ACCT is not set
++# CONFIG_NETFILTER_NETLINK_QUEUE is not set
++# CONFIG_NETFILTER_NETLINK_LOG is not set
++# CONFIG_NF_CONNTRACK is not set
++# CONFIG_NETFILTER_TPROXY is not set
++CONFIG_NETFILTER_XTABLES=m
++
++#
++# Xtables combined modules
++#
++# CONFIG_NETFILTER_XT_MARK is not set
++
++#
++# Xtables targets
++#
++# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++CONFIG_NETFILTER_XT_TARGET_HL=m
++# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
++# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
++# CONFIG_NETFILTER_XT_TARGET_LED is not set
++# CONFIG_NETFILTER_XT_TARGET_LOG is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
++# CONFIG_NETFILTER_XT_TARGET_TEE is not set
++# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
++
++#
++# Xtables matches
++#
++# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_CPU is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++CONFIG_NETFILTER_XT_MATCH_ECN=m
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
++CONFIG_NETFILTER_XT_MATCH_HL=m
++# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
++# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++CONFIG_IP_VS=m
++# CONFIG_IP_VS_IPV6 is not set
++# CONFIG_IP_VS_DEBUG is not set
++CONFIG_IP_VS_TAB_BITS=12
++
++#
++# IPVS transport protocol load balancing support
++#
++# CONFIG_IP_VS_PROTO_TCP is not set
++# CONFIG_IP_VS_PROTO_UDP is not set
++# CONFIG_IP_VS_PROTO_AH_ESP is not set
++# CONFIG_IP_VS_PROTO_ESP is not set
++# CONFIG_IP_VS_PROTO_AH is not set
++# CONFIG_IP_VS_PROTO_SCTP is not set
++
++#
++# IPVS scheduler
++#
++# CONFIG_IP_VS_RR is not set
++# CONFIG_IP_VS_WRR is not set
++# CONFIG_IP_VS_LC is not set
++# CONFIG_IP_VS_WLC is not set
++# CONFIG_IP_VS_LBLC is not set
++# CONFIG_IP_VS_LBLCR is not set
++# CONFIG_IP_VS_DH is not set
++# CONFIG_IP_VS_SH is not set
++# CONFIG_IP_VS_SED is not set
++# CONFIG_IP_VS_NQ is not set
++
++#
++# IPVS SH scheduler
++#
++CONFIG_IP_VS_SH_TAB_BITS=8
++
++#
++# IPVS application helper
++#
++
++#
++# IP: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV4 is not set
++CONFIG_IP_NF_QUEUE=m
++CONFIG_IP_NF_IPTABLES=m
++CONFIG_IP_NF_MATCH_AH=m
++CONFIG_IP_NF_MATCH_ECN=m
++CONFIG_IP_NF_MATCH_RPFILTER=m
++CONFIG_IP_NF_MATCH_TTL=m
++CONFIG_IP_NF_FILTER=m
++CONFIG_IP_NF_TARGET_REJECT=m
++CONFIG_IP_NF_TARGET_ULOG=m
++CONFIG_IP_NF_MANGLE=m
++CONFIG_IP_NF_TARGET_ECN=m
++CONFIG_IP_NF_TARGET_TTL=m
++CONFIG_IP_NF_RAW=m
++CONFIG_IP_NF_SECURITY=m
++CONFIG_IP_NF_ARPTABLES=m
++CONFIG_IP_NF_ARPFILTER=m
++CONFIG_IP_NF_ARP_MANGLE=m
++
++#
++# IPv6: Netfilter Configuration
++#
++# CONFIG_NF_DEFRAG_IPV6 is not set
++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_RPFILTER=m
++CONFIG_IP6_NF_MATCH_RT=m
++CONFIG_IP6_NF_TARGET_HL=m
++CONFIG_IP6_NF_FILTER=m
++CONFIG_IP6_NF_TARGET_REJECT=m
++CONFIG_IP6_NF_MANGLE=m
++CONFIG_IP6_NF_RAW=m
++CONFIG_IP6_NF_SECURITY=m
++# CONFIG_BRIDGE_NF_EBTABLES is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++CONFIG_L2TP=m
++CONFIG_L2TP_DEBUGFS=m
++# CONFIG_L2TP_V3 is not set
++CONFIG_STP=m
++CONFIG_GARP=m
++CONFIG_BRIDGE=m
++CONFIG_BRIDGE_IGMP_SNOOPING=y
++CONFIG_NET_DSA=m
++# CONFIG_NET_DSA_TAG_DSA is not set
++# CONFIG_NET_DSA_TAG_EDSA is not set
++# CONFIG_NET_DSA_TAG_TRAILER 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_WAN_ROUTER is not set
++CONFIG_PHONET=m
++# CONFIG_IEEE802154 is not set
++CONFIG_NET_SCHED=y
++
++#
++# Queueing/Scheduling
++#
++# CONFIG_NET_SCH_CBQ is not set
++# CONFIG_NET_SCH_HTB is not set
++# CONFIG_NET_SCH_HFSC is not set
++# CONFIG_NET_SCH_PRIO is not set
++# CONFIG_NET_SCH_MULTIQ is not set
++# CONFIG_NET_SCH_RED is not set
++# CONFIG_NET_SCH_SFB is not set
++# CONFIG_NET_SCH_SFQ is not set
++# CONFIG_NET_SCH_TEQL is not set
++# CONFIG_NET_SCH_TBF is not set
++# CONFIG_NET_SCH_GRED is not set
++# CONFIG_NET_SCH_DSMARK is not set
++# CONFIG_NET_SCH_NETEM is not set
++# CONFIG_NET_SCH_DRR is not set
++# CONFIG_NET_SCH_MQPRIO is not set
++# CONFIG_NET_SCH_CHOKE is not set
++# CONFIG_NET_SCH_QFQ is not set
++CONFIG_NET_SCH_CODEL=y
++CONFIG_NET_SCH_FQ_CODEL=y
++# CONFIG_NET_SCH_PLUG is not set
++
++#
++# Classification
++#
++CONFIG_NET_CLS=y
++# CONFIG_NET_CLS_BASIC is not set
++# CONFIG_NET_CLS_TCINDEX is not set
++# CONFIG_NET_CLS_ROUTE4 is not set
++# CONFIG_NET_CLS_FW is not set
++# CONFIG_NET_CLS_U32 is not set
++# CONFIG_NET_CLS_RSVP is not set
++# CONFIG_NET_CLS_RSVP6 is not set
++# CONFIG_NET_CLS_FLOW is not set
++CONFIG_NET_CLS_CGROUP=m
++# CONFIG_NET_EMATCH is not set
++# CONFIG_NET_CLS_ACT is not set
++CONFIG_NET_SCH_FIFO=y
++# CONFIG_DCB is not set
++CONFIG_DNS_RESOLVER=y
++CONFIG_BATMAN_ADV=m
++CONFIG_BATMAN_ADV_BLA=y
++# CONFIG_BATMAN_ADV_DEBUG is not set
++CONFIG_OPENVSWITCH=m
++CONFIG_RPS=y
++CONFIG_RFS_ACCEL=y
++CONFIG_XPS=y
++CONFIG_NETPRIO_CGROUP=m
++CONFIG_BQL=y
++CONFIG_BPF_JIT=y
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NET_TCPPROBE 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
++CONFIG_CAN_GW=m
++
++#
++# CAN Device Drivers
++#
++# CONFIG_CAN_VCAN is not set
++# CONFIG_CAN_SLCAN is not set
++CONFIG_CAN_DEV=m
++CONFIG_CAN_CALC_BITTIMING=y
++CONFIG_CAN_TI_HECC=m
++CONFIG_CAN_MCP251X=m
++# CONFIG_CAN_SJA1000 is not set
++CONFIG_CAN_C_CAN=m
++CONFIG_CAN_C_CAN_PLATFORM=m
++# CONFIG_CAN_CC770 is not set
++
++#
++# CAN USB interfaces
++#
++CONFIG_CAN_EMS_USB=m
++CONFIG_CAN_ESD_USB2=m
++CONFIG_CAN_PEAK_USB=m
++# CONFIG_CAN_SOFTING is not set
++# CONFIG_CAN_DEBUG_DEVICES is not set
++CONFIG_IRDA=m
++
++#
++# IrDA protocols
++#
++CONFIG_IRLAN=m
++# CONFIG_IRNET is not set
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++
++#
++# IrDA options
++#
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++# CONFIG_IRDA_DEBUG is not set
++
++#
++# 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=m
++CONFIG_KINGSUN_DONGLE=m
++CONFIG_KSDAZZLE_DONGLE=m
++CONFIG_KS959_DONGLE=m
++
++#
++# FIR device drivers
++#
++CONFIG_USB_IRDA=m
++# CONFIG_SIGMATEL_FIR is not set
++CONFIG_MCS_FIR=m
++CONFIG_BT=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_ATH3K=y
++CONFIG_BT_HCIUART_LL=y
++CONFIG_BT_HCIUART_3WIRE=y
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++# CONFIG_BT_HCIVHCI is not set
++# CONFIG_BT_MRVL is not set
++CONFIG_BT_ATH3K=m
++# CONFIG_BT_WILINK 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_WIRELESS_EXT=y
++CONFIG_WEXT_CORE=y
++CONFIG_WEXT_PROC=y
++CONFIG_WEXT_SPY=y
++CONFIG_CFG80211=m
++# CONFIG_NL80211_TESTMODE is not set
++# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
++# CONFIG_CFG80211_REG_DEBUG is not set
++# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
++CONFIG_CFG80211_DEFAULT_PS=y
++CONFIG_CFG80211_DEBUGFS=y
++# CONFIG_CFG80211_INTERNAL_REGDB is not set
++CONFIG_CFG80211_WEXT=y
++CONFIG_LIB80211=m
++# CONFIG_LIB80211_DEBUG is not set
++CONFIG_MAC80211=m
++CONFIG_MAC80211_HAS_RC=y
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_RC_MINSTREL=y
++CONFIG_MAC80211_RC_MINSTREL_HT=y
++CONFIG_MAC80211_RC_DEFAULT_PID=y
++# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
++CONFIG_MAC80211_RC_DEFAULT="pid"
++CONFIG_MAC80211_MESH=y
++CONFIG_MAC80211_LEDS=y
++CONFIG_MAC80211_DEBUGFS=y
++# CONFIG_MAC80211_MESSAGE_TRACING is not set
++# CONFIG_MAC80211_DEBUG_MENU is not set
++CONFIG_WIMAX=m
++CONFIG_WIMAX_DEBUG_LEVEL=8
++CONFIG_RFKILL=m
++CONFIG_RFKILL_LEDS=y
++CONFIG_RFKILL_INPUT=y
++CONFIG_RFKILL_REGULATOR=m
++CONFIG_RFKILL_GPIO=m
++CONFIG_NET_9P=m
++CONFIG_NET_9P_VIRTIO=m
++# CONFIG_NET_9P_DEBUG is not set
++# CONFIG_CAIF is not set
++CONFIG_CEPH_LIB=m
++# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
++# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
++CONFIG_NFC=m
++CONFIG_NFC_NCI=m
++CONFIG_NFC_HCI=m
++CONFIG_NFC_SHDLC=y
++# CONFIG_NFC_LLCP is not set
++
++#
++# Near Field Communication (NFC) devices
++#
++CONFIG_PN544_HCI_NFC=m
++CONFIG_NFC_PN533=m
++# CONFIG_NFC_WILINK is not set
++CONFIG_HAVE_BPF_JIT=y
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH=""
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++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_GENERIC_CPU_DEVICES is not set
++CONFIG_REGMAP=y
++CONFIG_REGMAP_I2C=y
++CONFIG_REGMAP_SPI=m
++CONFIG_REGMAP_MMIO=y
++# CONFIG_DMA_SHARED_BUFFER is not set
++# CONFIG_CMA is not set
++
++#
++# Bus devices
++#
++CONFIG_OMAP_OCP2SCP=y
++CONFIG_OMAP_INTERCONNECT=y
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=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_OF_PARTS=y
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_SM_FTL is not set
++# CONFIG_MTD_OOPS is not set
++# CONFIG_MTD_SWAP is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=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_PHYSMAP_OF is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_DATAFLASH is not set
++# CONFIG_MTD_M25P80 is not set
++# CONFIG_MTD_SST25L is not set
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_DOCG3 is not set
++CONFIG_MTD_NAND_ECC=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_ECC_BCH is not set
++# CONFIG_MTD_SM_COMMON 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_BCH is not set
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_DOCG4 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
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_WL_THRESHOLD=4096
++CONFIG_MTD_UBI_BEB_LIMIT=20
++CONFIG_MTD_UBI_FASTMAP=y
++# CONFIG_MTD_UBI_GLUEBI is not set
++CONFIG_DTC=y
++CONFIG_OF=y
++
++#
++# Device Tree and Open Firmware support
++#
++CONFIG_PROC_DEVICETREE=y
++# CONFIG_OF_SELFTEST is not set
++CONFIG_OF_FLATTREE=y
++CONFIG_OF_EARLY_FLATTREE=y
++CONFIG_OF_ADDRESS=y
++CONFIG_OF_IRQ=y
++CONFIG_OF_DEVICE=y
++CONFIG_OF_I2C=y
++CONFIG_OF_NET=y
++CONFIG_OF_MDIO=y
++CONFIG_OF_MTD=y
++# 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_LOOP_MIN_COUNT=8
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_DRBD 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_VIRTIO_BLK=m
++# CONFIG_BLK_DEV_RBD is not set
++
++#
++# Misc devices
++#
++# CONFIG_SENSORS_LIS3LV02D is not set
++# CONFIG_AD525X_DPOT is not set
++# CONFIG_ATMEL_PWM is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_APDS9802ALS is not set
++# CONFIG_ISL29003 is not set
++# CONFIG_ISL29020 is not set
++CONFIG_SENSORS_TSL2550=m
++# CONFIG_SENSORS_BH1780 is not set
++# CONFIG_SENSORS_BH1770 is not set
++# CONFIG_SENSORS_APDS990X is not set
++# CONFIG_HMC6352 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_TI_DAC7512 is not set
++CONFIG_BMP085=y
++CONFIG_BMP085_I2C=m
++# CONFIG_BMP085_SPI is not set
++# CONFIG_USB_SWITCH_FSA9480 is not set
++# CONFIG_GPEVT is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++CONFIG_EEPROM_AT24=y
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_MAX6875 is not set
++CONFIG_EEPROM_93CX6=y
++# CONFIG_EEPROM_93XX46 is not set
++
++#
++# Texas Instruments shared transport line discipline
++#
++CONFIG_TI_ST=m
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_LIS3_I2C is not set
++
++#
++# Altera FPGA firmware download module
++#
++# CONFIG_ALTERA_STAPL is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=y
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++CONFIG_SCSI_SCAN_ASYNC=y
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++CONFIG_SCSI_LOWLEVEL=y
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_ISCSI_BOOT_SYSFS is not set
++# CONFIG_LIBFC is not set
++# CONFIG_LIBFCOE is not set
++# CONFIG_SCSI_DEBUG is not set
++CONFIG_SCSI_VIRTIO=m
++# CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
++# CONFIG_ATA is not set
++CONFIG_MD=y
++# CONFIG_BLK_DEV_MD is not set
++# CONFIG_BLK_DEV_DM is not set
++# CONFIG_TARGET_CORE is not set
++CONFIG_NETDEVICES=y
++CONFIG_NET_CORE=y
++# CONFIG_BONDING is not set
++# CONFIG_DUMMY is not set
++# CONFIG_EQUALIZER is not set
++CONFIG_MII=y
++# CONFIG_NET_TEAM is not set
++# CONFIG_MACVLAN is not set
++CONFIG_VXLAN=m
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++CONFIG_TUN=m
++# CONFIG_VETH is not set
++CONFIG_VIRTIO_NET=m
++
++#
++# CAIF transport drivers
++#
++
++#
++# Distributed Switch Architecture drivers
++#
++# CONFIG_NET_DSA_MV88E6XXX is not set
++# CONFIG_NET_DSA_MV88E6060 is not set
++# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
++# CONFIG_NET_DSA_MV88E6131 is not set
++# CONFIG_NET_DSA_MV88E6123_61_65 is not set
++CONFIG_ETHERNET=y
++CONFIG_NET_VENDOR_BROADCOM=y
++# CONFIG_B44 is not set
++# CONFIG_NET_CALXEDA_XGMAC is not set
++CONFIG_NET_VENDOR_CHELSIO=y
++CONFIG_NET_VENDOR_CIRRUS=y
++# CONFIG_CS89x0 is not set
++# CONFIG_DM9000 is not set
++# CONFIG_DNET is not set
++CONFIG_NET_VENDOR_FARADAY=y
++# CONFIG_FTMAC100 is not set
++# CONFIG_FTGMAC100 is not set
++CONFIG_NET_VENDOR_INTEL=y
++CONFIG_NET_VENDOR_I825XX=y
++CONFIG_NET_VENDOR_MARVELL=y
++CONFIG_NET_VENDOR_MICREL=y
++CONFIG_KS8842=m
++CONFIG_KS8851=y
++CONFIG_KS8851_MLL=y
++CONFIG_NET_VENDOR_MICROCHIP=y
++# CONFIG_ENC28J60 is not set
++CONFIG_NET_VENDOR_NATSEMI=y
++CONFIG_NET_VENDOR_8390=y
++# CONFIG_AX88796 is not set
++# CONFIG_ETHOC is not set
++CONFIG_NET_VENDOR_SEEQ=y
++# CONFIG_SEEQ8005 is not set
++CONFIG_NET_VENDOR_SMSC=y
++CONFIG_SMC91X=y
++# CONFIG_SMC911X is not set
++CONFIG_SMSC911X=y
++# CONFIG_SMSC911X_ARCH_HOOKS is not set
++CONFIG_NET_VENDOR_STMICRO=y
++# CONFIG_STMMAC_ETH is not set
++CONFIG_NET_VENDOR_TI=y
++CONFIG_TI_DAVINCI_EMAC=y
++CONFIG_TI_DAVINCI_MDIO=y
++CONFIG_TI_DAVINCI_CPDMA=y
++CONFIG_TI_CPSW=y
++CONFIG_NET_VENDOR_WIZNET=y
++# CONFIG_WIZNET_W5100 is not set
++# CONFIG_WIZNET_W5300 is not set
++CONFIG_PHYLIB=y
++
++#
++# MII PHY device drivers
++#
++# CONFIG_AMD_PHY is not set
++# 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_BCM87XX_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_MICREL_PHY is not set
++# CONFIG_FIXED_PHY is not set
++# CONFIG_MDIO_BITBANG is not set
++CONFIG_MDIO_BUS_MUX=m
++# CONFIG_MDIO_BUS_MUX_GPIO is not set
++CONFIG_MDIO_BUS_MUX_MMIOREG=m
++# CONFIG_MICREL_KS8995MA is not set
++CONFIG_PPP=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_FILTER=y
++CONFIG_PPP_MPPE=m
++CONFIG_PPP_MULTILINK=y
++CONFIG_PPPOE=m
++CONFIG_PPTP=m
++CONFIG_PPPOL2TP=m
++CONFIG_PPP_ASYNC=m
++# CONFIG_PPP_SYNC_TTY is not set
++# CONFIG_SLIP is not set
++CONFIG_SLHC=m
++
++#
++# 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=y
++CONFIG_USB_NET_AX8817X=y
++CONFIG_USB_NET_CDCETHER=y
++# CONFIG_USB_NET_CDC_EEM is not set
++CONFIG_USB_NET_CDC_NCM=y
++# CONFIG_USB_NET_DM9601 is not set
++# CONFIG_USB_NET_SMSC75XX is not set
++CONFIG_USB_NET_SMSC95XX=y
++# CONFIG_USB_NET_GL620A is not set
++CONFIG_USB_NET_NET1080=y
++# CONFIG_USB_NET_PLUSB is not set
++# CONFIG_USB_NET_MCS7830 is not set
++# CONFIG_USB_NET_RNDIS_HOST is not set
++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_CX82310_ETH is not set
++# CONFIG_USB_NET_KALMIA is not set
++# CONFIG_USB_NET_QMI_WWAN is not set
++# CONFIG_USB_HSO is not set
++# CONFIG_USB_NET_INT51X1 is not set
++# CONFIG_USB_CDC_PHONET is not set
++# CONFIG_USB_IPHETH is not set
++# CONFIG_USB_SIERRA_NET is not set
++# CONFIG_USB_VL600 is not set
++CONFIG_WLAN=y
++# CONFIG_LIBERTAS_THINFIRM is not set
++# CONFIG_AT76C50X_USB is not set
++# CONFIG_USB_ZD1201 is not set
++# CONFIG_USB_NET_RNDIS_WLAN is not set
++# CONFIG_RTL8187 is not set
++# CONFIG_MAC80211_HWSIM is not set
++# CONFIG_ATH_COMMON is not set
++# CONFIG_B43 is not set
++# CONFIG_B43LEGACY is not set
++# CONFIG_BRCMFMAC is not set
++# CONFIG_HOSTAP is not set
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++# CONFIG_LIBERTAS_SPI is not set
++CONFIG_LIBERTAS_DEBUG=y
++# CONFIG_LIBERTAS_MESH is not set
++# CONFIG_P54_COMMON is not set
++# CONFIG_RT2X00 is not set
++# CONFIG_RTL8192CU is not set
++# CONFIG_WL_TI is not set
++# CONFIG_ZD1211RW is not set
++# CONFIG_MWIFIEX is not set
++
++#
++# WiMAX Wireless Broadband devices
++#
++# CONFIG_WIMAX_I2400M_USB is not set
++# CONFIG_WAN 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
++# CONFIG_INPUT_SPARSEKMAP is not set
++CONFIG_INPUT_MATRIXKMAP=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=y
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ADP5588 is not set
++# CONFIG_KEYBOARD_ADP5589 is not set
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_QT1070 is not set
++# CONFIG_KEYBOARD_QT2160 is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_KEYBOARD_TCA6416 is not set
++# CONFIG_KEYBOARD_TCA8418 is not set
++# CONFIG_KEYBOARD_MATRIX is not set
++# CONFIG_KEYBOARD_LM8323 is not set
++# CONFIG_KEYBOARD_LM8333 is not set
++# CONFIG_KEYBOARD_MAX7359 is not set
++# CONFIG_KEYBOARD_MCS is not set
++# CONFIG_KEYBOARD_MPR121 is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_SAMSUNG is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_OMAP4 is not set
++CONFIG_KEYBOARD_TWL4030=y
++# 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_SENTELIC 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_MOUSE_SYNAPTICS_USB 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 is not set
++# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
++# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
++# CONFIG_TOUCHSCREEN_BU21013 is not set
++# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
++# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
++# CONFIG_TOUCHSCREEN_DYNAPRO is not set
++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
++# CONFIG_TOUCHSCREEN_EETI is not set
++# CONFIG_TOUCHSCREEN_EGALAX is not set
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_ILI210X is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
++# CONFIG_TOUCHSCREEN_MAX11801 is not set
++# CONFIG_TOUCHSCREEN_MCS5000 is not set
++CONFIG_TOUCHSCREEN_MMS114=m
++# 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_EDT_FT5X06=m
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
++# CONFIG_TOUCHSCREEN_PIXCIR is not set
++CONFIG_TOUCHSCREEN_WM97XX=m
++CONFIG_TOUCHSCREEN_WM9705=y
++CONFIG_TOUCHSCREEN_WM9712=y
++CONFIG_TOUCHSCREEN_WM9713=y
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
++# CONFIG_TOUCHSCREEN_TSC2005 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
++# CONFIG_TOUCHSCREEN_ST1232 is not set
++# CONFIG_TOUCHSCREEN_TPS6507X is not set
++CONFIG_INPUT_MISC=y
++# CONFIG_INPUT_AD714X is not set
++# CONFIG_INPUT_BMA150 is not set
++# CONFIG_INPUT_MMA8450 is not set
++# CONFIG_INPUT_MPU3050 is not set
++# CONFIG_INPUT_GP2A is not set
++# CONFIG_INPUT_GPIO_TILT_POLLED is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_KXTJ9 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_TWL4030_VIBRA is not set
++# CONFIG_INPUT_UINPUT is not set
++# CONFIG_INPUT_PCF8574 is not set
++# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
++# CONFIG_INPUT_ADXL34X is not set
++# CONFIG_INPUT_CMA3000 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_SERIO_ALTERA_PS2 is not set
++# CONFIG_SERIO_PS2MULT is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_VT_CONSOLE_SLEEP=y
++CONFIG_HW_CONSOLE=y
++CONFIG_VT_HW_CONSOLE_BINDING=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++# CONFIG_TRACE_SINK is not set
++CONFIG_DEVKMEM=y
++
++#
++# 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
++# CONFIG_SERIAL_8250_DW is not set
++# CONFIG_SERIAL_8250_EM is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++# CONFIG_SERIAL_MAX310X is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_OF_PLATFORM is not set
++CONFIG_SERIAL_OMAP=y
++CONFIG_SERIAL_OMAP_CONSOLE=y
++# CONFIG_SERIAL_SCCNXP is not set
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++# CONFIG_SERIAL_IFX6X60 is not set
++# CONFIG_SERIAL_XILINX_PS_UART is not set
++# CONFIG_TTY_PRINTK is not set
++CONFIG_HVC_DRIVER=y
++# CONFIG_HVC_DCC is not set
++CONFIG_VIRTIO_CONSOLE=m
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=y
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
++# CONFIG_HW_RANDOM_ATMEL is not set
++CONFIG_HW_RANDOM_VIRTIO=m
++# CONFIG_HW_RANDOM_EXYNOS 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_COMPAT=y
++CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_MUX is not set
++CONFIG_I2C_HELPER_AUTO=y
++CONFIG_I2C_ALGOBIT=m
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
++# CONFIG_I2C_GPIO is not set
++# CONFIG_I2C_OCORES is not set
++CONFIG_I2C_OMAP=y
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_PXA_PCI is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_XILINX is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_DIOLAN_U2C is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++CONFIG_SPI=y
++# CONFIG_SPI_DEBUG is not set
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++# CONFIG_SPI_ALTERA is not set
++# CONFIG_SPI_BITBANG is not set
++# CONFIG_SPI_GPIO is not set
++# CONFIG_SPI_OC_TINY is not set
++CONFIG_SPI_OMAP24XX=y
++# CONFIG_SPI_PXA2XX_PCI is not set
++CONFIG_SPI_SC18IS602=m
++CONFIG_SPI_XCOMM=m
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_SPIDEV=y
++# CONFIG_SPI_TLE62X0 is not set
++# CONFIG_HSI is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++
++#
++# PPS generators support
++#
++
++#
++# PTP clock support
++#
++
++#
++# Enable Device Drivers -> PPS to see the PTP clock options.
++#
++CONFIG_PINCTRL=y
++
++#
++# Pin controllers
++#
++CONFIG_PINMUX=y
++CONFIG_PINCONF=y
++# CONFIG_DEBUG_PINCTRL is not set
++CONFIG_PINCTRL_SINGLE=y
++# CONFIG_PINCTRL_SAMSUNG is not set
++# CONFIG_PINCTRL_EXYNOS4 is not set
++CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_OF_GPIO=y
++CONFIG_DEBUG_GPIO=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO drivers:
++#
++# CONFIG_GPIO_GENERIC_PLATFORM is not set
++# CONFIG_GPIO_EM is not set
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX7300 is not set
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCF857X is not set
++# CONFIG_GPIO_SX150X is not set
++CONFIG_GPIO_TWL4030=y
++# CONFIG_GPIO_ADP5588 is not set
++# CONFIG_GPIO_ADNP is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_GPIO_MC33880 is not set
++# CONFIG_GPIO_74X164 is not set
++
++#
++# AC97 GPIO expanders:
++#
++
++#
++# MODULbus GPIO expanders:
++#
++CONFIG_W1=y
++CONFIG_W1_CON=y
++
++#
++# 1-wire Bus Masters
++#
++CONFIG_W1_MASTER_DS2490=m
++CONFIG_W1_MASTER_DS2482=m
++CONFIG_W1_MASTER_DS1WM=m
++CONFIG_W1_MASTER_GPIO=y
++CONFIG_HDQ_MASTER_OMAP=m
++
++#
++# 1-wire Slaves
++#
++CONFIG_W1_SLAVE_THERM=y
++CONFIG_W1_SLAVE_SMEM=y
++CONFIG_W1_SLAVE_DS2408=m
++CONFIG_W1_SLAVE_DS2423=m
++CONFIG_W1_SLAVE_DS2431=m
++CONFIG_W1_SLAVE_DS2433=m
++CONFIG_W1_SLAVE_DS2433_CRC=y
++CONFIG_W1_SLAVE_DS2760=m
++CONFIG_W1_SLAVE_DS2780=m
++CONFIG_W1_SLAVE_DS2781=m
++CONFIG_W1_SLAVE_DS28E04=m
++CONFIG_W1_SLAVE_BQ27000=m
++CONFIG_POWER_SUPPLY=y
++# CONFIG_POWER_SUPPLY_DEBUG is not set
++# CONFIG_PDA_POWER is not set
++CONFIG_GENERIC_ADC_BATTERY=m
++# CONFIG_TEST_POWER is not set
++# CONFIG_BATTERY_DS2760 is not set
++# CONFIG_BATTERY_DS2780 is not set
++# CONFIG_BATTERY_DS2781 is not set
++# CONFIG_BATTERY_DS2782 is not set
++# CONFIG_BATTERY_SBS is not set
++# CONFIG_BATTERY_BQ27x00 is not set
++# CONFIG_BATTERY_MAX17040 is not set
++# CONFIG_BATTERY_MAX17042 is not set
++# CONFIG_CHARGER_ISP1704 is not set
++# CONFIG_CHARGER_MAX8903 is not set
++# CONFIG_CHARGER_TWL4030 is not set
++# CONFIG_CHARGER_LP8727 is not set
++CONFIG_CHARGER_GPIO=m
++# CONFIG_CHARGER_MANAGER is not set
++# CONFIG_CHARGER_SMB347 is not set
++# CONFIG_POWER_AVS is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Native drivers
++#
++# CONFIG_SENSORS_AD7314 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_ADT7410=m
++# CONFIG_SENSORS_ADT7411 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7475 is not set
++# CONFIG_SENSORS_ASC7621 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS620 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_GPIO_FAN=m
++CONFIG_SENSORS_HIH6130=m
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_JC42 is not set
++# CONFIG_SENSORS_LINEAGE is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM73 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_LTC4151 is not set
++# CONFIG_SENSORS_LTC4215 is not set
++# CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_LTC4261 is not set
++# CONFIG_SENSORS_LM95241 is not set
++# CONFIG_SENSORS_LM95245 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX16065 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX1668 is not set
++CONFIG_SENSORS_MAX197=m
++# CONFIG_SENSORS_MAX6639 is not set
++# CONFIG_SENSORS_MAX6642 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_MCP3021 is not set
++# CONFIG_SENSORS_NTC_THERMISTOR is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_PMBUS is not set
++# CONFIG_SENSORS_SHT15 is not set
++CONFIG_SENSORS_SHT21=m
++# CONFIG_SENSORS_SMM665 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_EMC1403 is not set
++# CONFIG_SENSORS_EMC2103 is not set
++# CONFIG_SENSORS_EMC6W201 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_SCH56XX_COMMON is not set
++# CONFIG_SENSORS_SCH5627 is not set
++# CONFIG_SENSORS_SCH5636 is not set
++# CONFIG_SENSORS_ADS1015 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_ADS7871 is not set
++# CONFIG_SENSORS_AMC6821 is not set
++# CONFIG_SENSORS_INA2XX is not set
++# CONFIG_SENSORS_THMC50 is not set
++CONFIG_SENSORS_TMP102=m
++# CONFIG_SENSORS_TMP401 is not set
++# CONFIG_SENSORS_TMP421 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_W83795 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_THERMAL=y
++CONFIG_THERMAL_HWMON=y
++CONFIG_CPU_THERMAL=y
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_CORE is not set
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_DW_WATCHDOG is not set
++# CONFIG_MPCORE_WATCHDOG is not set
++CONFIG_OMAP_WATCHDOG=y
++CONFIG_TWL4030_WATCHDOG=y
++# CONFIG_MAX63XX_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
++CONFIG_BCMA_POSSIBLE=y
++
++#
++# Broadcom specific AMBA
++#
++# CONFIG_BCMA is not set
++
++#
++# Multifunction device drivers
++#
++CONFIG_MFD_CORE=y
++# CONFIG_MFD_88PM860X is not set
++# CONFIG_MFD_88PM800 is not set
++# CONFIG_MFD_88PM805 is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_MFD_ASIC3 is not set
++CONFIG_MFD_TI_AM335X_TSCADC=y
++# CONFIG_HTC_EGPIO is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_HTC_I2CPLD is not set
++# CONFIG_UCB1400_CORE is not set
++# CONFIG_MFD_LM3533 is not set
++# CONFIG_TPS6105X is not set
++# CONFIG_TPS65010 is not set
++# CONFIG_TPS6507X is not set
++CONFIG_MFD_TPS65217=y
++# CONFIG_MFD_TPS6586X is not set
++# CONFIG_MFD_TPS65910 is not set
++# CONFIG_MFD_TPS65912_I2C is not set
++# CONFIG_MFD_TPS65912_SPI is not set
++CONFIG_TWL4030_CORE=y
++# CONFIG_TWL4030_MADC is not set
++CONFIG_TWL4030_POWER=y
++# CONFIG_MFD_TWL4030_AUDIO is not set
++# CONFIG_TWL6040_CORE is not set
++# CONFIG_MFD_STMPE is not set
++# CONFIG_MFD_TC3589X is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_T7L66XB is not set
++# CONFIG_MFD_SMSC is not set
++# CONFIG_MFD_TC6387XB is not set
++# CONFIG_MFD_TC6393XB is not set
++# CONFIG_PMIC_DA903X is not set
++# CONFIG_MFD_DA9052_SPI is not set
++# CONFIG_MFD_DA9052_I2C is not set
++# CONFIG_MFD_DA9055 is not set
++# CONFIG_PMIC_ADP5520 is not set
++# CONFIG_MFD_LP8788 is not set
++# CONFIG_MFD_MAX77686 is not set
++# CONFIG_MFD_MAX77693 is not set
++# CONFIG_MFD_MAX8907 is not set
++# CONFIG_MFD_MAX8925 is not set
++# CONFIG_MFD_MAX8997 is not set
++# CONFIG_MFD_MAX8998 is not set
++# CONFIG_MFD_SEC_CORE is not set
++# CONFIG_MFD_ARIZONA_I2C is not set
++# CONFIG_MFD_ARIZONA_SPI is not set
++# CONFIG_MFD_WM8400 is not set
++# CONFIG_MFD_WM831X_I2C is not set
++# CONFIG_MFD_WM831X_SPI is not set
++# CONFIG_MFD_WM8350_I2C is not set
++# CONFIG_MFD_WM8994 is not set
++# CONFIG_MFD_PCF50633 is not set
++# CONFIG_MFD_MC13XXX_SPI is not set
++# CONFIG_MFD_MC13XXX_I2C is not set
++# CONFIG_ABX500_CORE is not set
++# CONFIG_EZX_PCAP is not set
++CONFIG_MFD_WL1273_CORE=m
++# CONFIG_MFD_TPS65090 is not set
++# CONFIG_MFD_AAT2870_CORE is not set
++# CONFIG_MFD_RC5T583 is not set
++# CONFIG_MFD_SYSCON is not set
++# CONFIG_MFD_PALMAS is not set
++CONFIG_REGULATOR=y
++# CONFIG_REGULATOR_DEBUG is not set
++# CONFIG_REGULATOR_DUMMY is not set
++CONFIG_REGULATOR_FIXED_VOLTAGE=y
++# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
++# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
++# CONFIG_REGULATOR_GPIO is not set
++# CONFIG_REGULATOR_AD5398 is not set
++# CONFIG_REGULATOR_FAN53555 is not set
++# CONFIG_REGULATOR_ISL6271A is not set
++# CONFIG_REGULATOR_MAX1586 is not set
++# CONFIG_REGULATOR_MAX8649 is not set
++# CONFIG_REGULATOR_MAX8660 is not set
++# CONFIG_REGULATOR_MAX8952 is not set
++# CONFIG_REGULATOR_LP3971 is not set
++# CONFIG_REGULATOR_LP3972 is not set
++# CONFIG_REGULATOR_LP872X is not set
++# CONFIG_REGULATOR_TPS62360 is not set
++CONFIG_REGULATOR_TPS65023=y
++CONFIG_REGULATOR_TPS6507X=y
++CONFIG_REGULATOR_TPS65217=y
++# CONFIG_REGULATOR_TPS6524X is not set
++CONFIG_REGULATOR_TWL4030=y
++CONFIG_MEDIA_SUPPORT=m
++
++#
++# Multimedia core support
++#
++CONFIG_MEDIA_CAMERA_SUPPORT=y
++CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
++CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
++CONFIG_MEDIA_RADIO_SUPPORT=y
++CONFIG_MEDIA_RC_SUPPORT=y
++CONFIG_MEDIA_CONTROLLER=y
++CONFIG_VIDEO_DEV=m
++CONFIG_VIDEO_V4L2_SUBDEV_API=y
++CONFIG_VIDEO_V4L2=m
++# CONFIG_VIDEO_ADV_DEBUG is not set
++# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
++CONFIG_VIDEO_TUNER=m
++CONFIG_V4L2_MEM2MEM_DEV=m
++CONFIG_VIDEOBUF_GEN=m
++CONFIG_VIDEOBUF_VMALLOC=m
++CONFIG_VIDEOBUF_DMA_CONTIG=m
++CONFIG_VIDEOBUF_DVB=m
++CONFIG_VIDEOBUF2_CORE=m
++CONFIG_VIDEOBUF2_MEMOPS=m
++CONFIG_VIDEOBUF2_DMA_CONTIG=m
++CONFIG_VIDEOBUF2_VMALLOC=m
++CONFIG_DVB_CORE=m
++CONFIG_DVB_NET=y
++CONFIG_DVB_MAX_ADAPTERS=8
++CONFIG_DVB_DYNAMIC_MINORS=y
++
++#
++# Media drivers
++#
++CONFIG_RC_CORE=m
++CONFIG_RC_MAP=m
++CONFIG_RC_DECODERS=y
++CONFIG_LIRC=m
++CONFIG_IR_LIRC_CODEC=m
++CONFIG_IR_NEC_DECODER=m
++CONFIG_IR_RC5_DECODER=m
++CONFIG_IR_RC6_DECODER=m
++CONFIG_IR_JVC_DECODER=m
++CONFIG_IR_SONY_DECODER=m
++CONFIG_IR_RC5_SZ_DECODER=m
++CONFIG_IR_SANYO_DECODER=m
++CONFIG_IR_MCE_KBD_DECODER=m
++CONFIG_RC_DEVICES=y
++CONFIG_RC_ATI_REMOTE=m
++CONFIG_IR_IMON=m
++CONFIG_IR_MCEUSB=m
++CONFIG_IR_REDRAT3=m
++CONFIG_IR_STREAMZAP=m
++CONFIG_IR_IGUANA=m
++CONFIG_IR_TTUSBIR=m
++CONFIG_IR_RX51=m
++CONFIG_RC_LOOPBACK=m
++CONFIG_IR_GPIO_CIR=m
++CONFIG_MEDIA_USB_SUPPORT=y
++
++#
++# Webcam devices
++#
++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_GL860=m
++CONFIG_USB_GSPCA_BENQ=m
++CONFIG_USB_GSPCA_CONEX=m
++CONFIG_USB_GSPCA_CPIA1=m
++CONFIG_USB_GSPCA_ETOMS=m
++CONFIG_USB_GSPCA_FINEPIX=m
++CONFIG_USB_GSPCA_JEILINJ=m
++CONFIG_USB_GSPCA_JL2005BCD=m
++CONFIG_USB_GSPCA_KINECT=m
++CONFIG_USB_GSPCA_KONICA=m
++CONFIG_USB_GSPCA_MARS=m
++CONFIG_USB_GSPCA_MR97310A=m
++CONFIG_USB_GSPCA_NW80X=m
++CONFIG_USB_GSPCA_OV519=m
++CONFIG_USB_GSPCA_OV534=m
++CONFIG_USB_GSPCA_OV534_9=m
++CONFIG_USB_GSPCA_PAC207=m
++CONFIG_USB_GSPCA_PAC7302=m
++CONFIG_USB_GSPCA_PAC7311=m
++CONFIG_USB_GSPCA_SE401=m
++CONFIG_USB_GSPCA_SN9C2028=m
++CONFIG_USB_GSPCA_SN9C20X=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_SPCA1528=m
++CONFIG_USB_GSPCA_SQ905=m
++CONFIG_USB_GSPCA_SQ905C=m
++CONFIG_USB_GSPCA_SQ930X=m
++CONFIG_USB_GSPCA_STK014=m
++CONFIG_USB_GSPCA_STV0680=m
++CONFIG_USB_GSPCA_SUNPLUS=m
++CONFIG_USB_GSPCA_T613=m
++CONFIG_USB_GSPCA_TOPRO=m
++CONFIG_USB_GSPCA_TV8532=m
++CONFIG_USB_GSPCA_VC032X=m
++CONFIG_USB_GSPCA_VICAM=m
++CONFIG_USB_GSPCA_XIRLINK_CIT=m
++CONFIG_USB_GSPCA_ZC3XX=m
++CONFIG_USB_PWC=m
++# CONFIG_USB_PWC_DEBUG is not set
++CONFIG_USB_PWC_INPUT_EVDEV=y
++CONFIG_VIDEO_CPIA2=m
++CONFIG_USB_ZR364XX=m
++CONFIG_USB_STKWEBCAM=m
++CONFIG_USB_S2255=m
++CONFIG_USB_SN9C102=m
++
++#
++# Analog TV USB devices
++#
++CONFIG_VIDEO_AU0828=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_TLG2300=m
++CONFIG_VIDEO_USBVISION=m
++CONFIG_VIDEO_STK1160=m
++CONFIG_VIDEO_STK1160_AC97=y
++
++#
++# Analog/digital TV USB devices
++#
++CONFIG_VIDEO_CX231XX=m
++CONFIG_VIDEO_CX231XX_RC=y
++CONFIG_VIDEO_CX231XX_ALSA=m
++CONFIG_VIDEO_CX231XX_DVB=m
++CONFIG_VIDEO_TM6000=m
++CONFIG_VIDEO_TM6000_ALSA=m
++CONFIG_VIDEO_TM6000_DVB=m
++
++#
++# Digital TV USB devices
++#
++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=y
++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_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_PCTV452E=m
++CONFIG_DVB_USB_DW2102=m
++CONFIG_DVB_USB_CINERGY_T2=m
++CONFIG_DVB_USB_DTV5100=m
++CONFIG_DVB_USB_FRIIO=m
++CONFIG_DVB_USB_AZ6027=m
++CONFIG_DVB_USB_TECHNISAT_USB2=m
++CONFIG_DVB_USB_V2=m
++CONFIG_DVB_USB_CYPRESS_FIRMWARE=m
++CONFIG_DVB_USB_AF9015=m
++CONFIG_DVB_USB_AF9035=m
++CONFIG_DVB_USB_ANYSEE=m
++CONFIG_DVB_USB_AU6610=m
++CONFIG_DVB_USB_AZ6007=m
++CONFIG_DVB_USB_CE6230=m
++CONFIG_DVB_USB_EC168=m
++CONFIG_DVB_USB_GL861=m
++CONFIG_DVB_USB_IT913X=m
++CONFIG_DVB_USB_LME2510=m
++CONFIG_DVB_USB_MXL111SF=m
++CONFIG_DVB_USB_RTL28XXU=m
++# CONFIG_SMS_USB_DRV is not set
++CONFIG_DVB_B2C2_FLEXCOP_USB=m
++# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
++
++#
++# Webcam, TV (analog/digital) USB devices
++#
++CONFIG_VIDEO_EM28XX=m
++CONFIG_VIDEO_EM28XX_ALSA=m
++CONFIG_VIDEO_EM28XX_DVB=m
++CONFIG_VIDEO_EM28XX_RC=m
++CONFIG_TTPCI_EEPROM=m
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_VIDEO_VPSS_SYSTEM=m
++CONFIG_VIDEO_VPFE_CAPTURE=m
++CONFIG_VIDEO_DM6446_CCDC=m
++CONFIG_VIDEO_OMAP2_VOUT_VRFB=y
++CONFIG_VIDEO_OMAP2_VOUT=m
++# CONFIG_VIDEO_TIMBERDALE is not set
++CONFIG_SOC_CAMERA=m
++CONFIG_SOC_CAMERA_PLATFORM=m
++# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
++# CONFIG_VIDEO_SH_MOBILE_CEU is not set
++CONFIG_V4L_MEM2MEM_DRIVERS=y
++CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
++CONFIG_V4L_TEST_DRIVERS=y
++CONFIG_VIDEO_VIVI=m
++CONFIG_VIDEO_MEM2MEM_TESTDEV=m
++
++#
++# Supported MMC/SDIO adapters
++#
++# CONFIG_SMS_SDIO_DRV is not set
++CONFIG_RADIO_ADAPTERS=y
++CONFIG_RADIO_SI470X=y
++CONFIG_USB_SI470X=m
++CONFIG_I2C_SI470X=m
++CONFIG_USB_MR800=m
++CONFIG_USB_DSBR=m
++# CONFIG_RADIO_SHARK is not set
++CONFIG_RADIO_SHARK2=m
++CONFIG_I2C_SI4713=m
++CONFIG_RADIO_SI4713=m
++CONFIG_USB_KEENE=m
++CONFIG_RADIO_TEA5764=m
++CONFIG_RADIO_SAA7706H=m
++CONFIG_RADIO_TEF6862=m
++CONFIG_RADIO_WL1273=m
++
++#
++# Texas Instruments WL128x FM driver (ST based)
++#
++CONFIG_RADIO_WL128X=m
++CONFIG_DVB_B2C2_FLEXCOP=m
++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
++
++#
++# Media ancillary drivers (tuners, sensors, i2c, frontends)
++#
++CONFIG_VIDEO_TVEEPROM=m
++CONFIG_VIDEO_IR_I2C=m
++
++#
++# Audio decoders, processors and mixers
++#
++CONFIG_VIDEO_MSP3400=m
++CONFIG_VIDEO_CS53L32A=m
++CONFIG_VIDEO_WM8775=m
++
++#
++# RDS decoders
++#
++
++#
++# Video decoders
++#
++CONFIG_VIDEO_SAA711X=m
++CONFIG_VIDEO_TVP5150=m
++
++#
++# Video and audio decoders
++#
++CONFIG_VIDEO_CX25840=m
++
++#
++# MPEG video encoders
++#
++CONFIG_VIDEO_CX2341X=m
++
++#
++# Video encoders
++#
++
++#
++# Camera sensor devices
++#
++CONFIG_VIDEO_MT9V011=m
++
++#
++# Flash devices
++#
++
++#
++# Video improvement chips
++#
++
++#
++# Miscelaneous helper chips
++#
++
++#
++# Sensors used on soc_camera driver
++#
++
++#
++# soc_camera sensor drivers
++#
++# CONFIG_SOC_CAMERA_IMX074 is not set
++CONFIG_SOC_CAMERA_MT9M001=m
++CONFIG_SOC_CAMERA_MT9M111=m
++CONFIG_SOC_CAMERA_MT9T031=m
++CONFIG_SOC_CAMERA_MT9T112=m
++CONFIG_SOC_CAMERA_MT9V022=m
++# CONFIG_SOC_CAMERA_OV2640 is not set
++# CONFIG_SOC_CAMERA_OV5642 is not set
++# CONFIG_SOC_CAMERA_OV6650 is not set
++# CONFIG_SOC_CAMERA_OV772X is not set
++# CONFIG_SOC_CAMERA_OV9640 is not set
++# CONFIG_SOC_CAMERA_OV9740 is not set
++# CONFIG_SOC_CAMERA_RJ54N1 is not set
++# CONFIG_SOC_CAMERA_TW9910 is not set
++CONFIG_MEDIA_ATTACH=y
++CONFIG_MEDIA_TUNER=m
++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_MT2063=m
++CONFIG_MEDIA_TUNER_MT2266=m
++CONFIG_MEDIA_TUNER_QT1010=m
++CONFIG_MEDIA_TUNER_XC2028=m
++CONFIG_MEDIA_TUNER_XC5000=m
++CONFIG_MEDIA_TUNER_XC4000=m
++CONFIG_MEDIA_TUNER_MXL5005S=m
++CONFIG_MEDIA_TUNER_MXL5007T=m
++CONFIG_MEDIA_TUNER_MC44S803=m
++CONFIG_MEDIA_TUNER_MAX2165=m
++CONFIG_MEDIA_TUNER_TDA18218=m
++CONFIG_MEDIA_TUNER_FC0011=m
++CONFIG_MEDIA_TUNER_FC0012=m
++CONFIG_MEDIA_TUNER_FC0013=m
++CONFIG_MEDIA_TUNER_TDA18212=m
++CONFIG_MEDIA_TUNER_E4000=m
++CONFIG_MEDIA_TUNER_FC2580=m
++CONFIG_MEDIA_TUNER_TUA9001=m
++
++#
++# Multistandard (satellite) frontends
++#
++CONFIG_DVB_STB0899=m
++CONFIG_DVB_STB6100=m
++CONFIG_DVB_STV090x=m
++CONFIG_DVB_STV6110x=m
++
++#
++# Multistandard (cable + terrestrial) frontends
++#
++CONFIG_DVB_DRXK=m
++CONFIG_DVB_TDA18271C2DD=m
++
++#
++# DVB-S (satellite) frontends
++#
++CONFIG_DVB_CX24123=m
++CONFIG_DVB_MT312=m
++CONFIG_DVB_ZL10039=m
++CONFIG_DVB_S5H1420=m
++CONFIG_DVB_STV0288=m
++CONFIG_DVB_STB6000=m
++CONFIG_DVB_STV0299=m
++CONFIG_DVB_STV6110=m
++CONFIG_DVB_STV0900=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_DS3000=m
++CONFIG_DVB_TDA10071=m
++
++#
++# DVB-T (terrestrial) frontends
++#
++CONFIG_DVB_CX22702=m
++CONFIG_DVB_DRXD=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_EC100=m
++CONFIG_DVB_CXD2820R=m
++CONFIG_DVB_RTL2830=m
++CONFIG_DVB_RTL2832=m
++
++#
++# DVB-C (cable) frontends
++#
++CONFIG_DVB_TDA10023=m
++CONFIG_DVB_STV0297=m
++
++#
++# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
++#
++CONFIG_DVB_NXT200X=m
++CONFIG_DVB_BCM3510=m
++CONFIG_DVB_LGDT330X=m
++CONFIG_DVB_LGDT3305=m
++CONFIG_DVB_LG2160=m
++CONFIG_DVB_S5H1409=m
++CONFIG_DVB_AU8522=m
++CONFIG_DVB_AU8522_DTV=m
++CONFIG_DVB_AU8522_V4L=m
++CONFIG_DVB_S5H1411=m
++
++#
++# ISDB-T (terrestrial) frontends
++#
++CONFIG_DVB_S921=m
++CONFIG_DVB_DIB8000=m
++CONFIG_DVB_MB86A20S=m
++
++#
++# Digital terrestrial only tuners/PLL
++#
++CONFIG_DVB_PLL=m
++CONFIG_DVB_TUNER_DIB0070=m
++CONFIG_DVB_TUNER_DIB0090=m
++
++#
++# SEC control devices for DVB-S
++#
++CONFIG_DVB_LNBP21=m
++CONFIG_DVB_LNBP22=m
++CONFIG_DVB_ISL6421=m
++CONFIG_DVB_ISL6423=m
++CONFIG_DVB_A8293=m
++CONFIG_DVB_LGS8GXX=m
++CONFIG_DVB_ATBM8830=m
++CONFIG_DVB_IX2505V=m
++CONFIG_DVB_IT913X_FE=m
++CONFIG_DVB_M88RS2000=m
++CONFIG_DVB_AF9033=m
++
++#
++# Tools to develop new frontends
++#
++# CONFIG_DVB_DUMMY_FE is not set
++
++#
++# Graphics support
++#
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++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=y
++CONFIG_FB_SYS_FILLRECT=y
++CONFIG_FB_SYS_COPYAREA=y
++CONFIG_FB_SYS_IMAGEBLIT=y
++CONFIG_FB_FOREIGN_ENDIAN=y
++CONFIG_FB_BOTH_ENDIAN=y
++# CONFIG_FB_BIG_ENDIAN is not set
++# CONFIG_FB_LITTLE_ENDIAN is not set
++CONFIG_FB_SYS_FOPS=y
++# CONFIG_FB_WMT_GE_ROPS 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=y
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_UVESA is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_TMIO is not set
++# CONFIG_FB_SMSCUFX is not set
++# CONFIG_FB_UDL is not set
++CONFIG_FB_DA8XX=y
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_BROADSHEET is not set
++# CONFIG_FB_AUO_K190X is not set
++CONFIG_FB_ST7735=y
++CONFIG_OMAP2_VRAM=y
++CONFIG_OMAP2_VRFB=y
++CONFIG_OMAP2_DSS=m
++CONFIG_OMAP2_VRAM_SIZE=0
++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
++# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
++CONFIG_OMAP2_DSS_DPI=y
++CONFIG_OMAP2_DSS_RFBI=y
++CONFIG_OMAP2_DSS_VENC=y
++CONFIG_OMAP4_DSS_HDMI=y
++CONFIG_OMAP2_DSS_SDI=y
++CONFIG_OMAP2_DSS_DSI=y
++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
++CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
++CONFIG_FB_OMAP2=m
++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
++CONFIG_FB_OMAP2_NUM_FBS=3
++
++#
++# OMAP2/3 Display Device Drivers
++#
++CONFIG_PANEL_GENERIC_DPI=m
++# CONFIG_PANEL_TFP410 is not set
++# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
++CONFIG_PANEL_SHARP_LS037V7DW01=m
++CONFIG_PANEL_NEC_NL8048HL11_01B=m
++# CONFIG_PANEL_PICODLP is not set
++CONFIG_PANEL_TAAL=m
++CONFIG_PANEL_TPO_TD043MTEA1=m
++CONFIG_PANEL_ACX565AKM=m
++# CONFIG_PANEL_N8X0 is not set
++# CONFIG_EXYNOS_VIDEO is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_LCD_CLASS_DEVICE=y
++# CONFIG_LCD_L4F00242T03 is not set
++# CONFIG_LCD_LMS283GF05 is not set
++# CONFIG_LCD_LTV350QV is not set
++# CONFIG_LCD_TDO24M is not set
++# CONFIG_LCD_VGG2432A4 is not set
++CONFIG_LCD_PLATFORM=y
++# CONFIG_LCD_S6E63M0 is not set
++# CONFIG_LCD_LD9040 is not set
++# CONFIG_LCD_AMS369FG06 is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_GENERIC=m
++CONFIG_BACKLIGHT_PWM=y
++# CONFIG_BACKLIGHT_ADP8860 is not set
++# CONFIG_BACKLIGHT_ADP8870 is not set
++CONFIG_BACKLIGHT_LM3630=m
++CONFIG_BACKLIGHT_LM3639=m
++# CONFIG_BACKLIGHT_LP855X is not set
++# CONFIG_BACKLIGHT_PANDORA is not set
++CONFIG_BACKLIGHT_TPS65217=y
++
++#
++# Console display driver support
++#
++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=y
++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=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++CONFIG_SOUND=m
++CONFIG_SOUND_OSS_CORE=y
++CONFIG_SOUND_OSS_CORE_PRECLAIM=y
++CONFIG_SND=m
++CONFIG_SND_TIMER=m
++CONFIG_SND_PCM=m
++CONFIG_SND_HWDEP=m
++CONFIG_SND_RAWMIDI=m
++CONFIG_SND_COMPRESS_OFFLOAD=m
++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 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_VMASTER=y
++# 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_AC97_CODEC=m
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_ALOOP is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++CONFIG_SND_AC97_POWER_SAVE=y
++CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
++CONFIG_SND_ARM=y
++CONFIG_SND_SPI=y
++CONFIG_SND_USB=y
++CONFIG_SND_USB_AUDIO=m
++# CONFIG_SND_USB_UA101 is not set
++# CONFIG_SND_USB_CAIAQ is not set
++# CONFIG_SND_USB_6FIRE is not set
++CONFIG_SND_SOC=m
++# CONFIG_SND_DESIGNWARE_I2S is not set
++CONFIG_SND_SOC_I2C_AND_SPI=m
++# CONFIG_SND_SOC_ALL_CODECS is not set
++# CONFIG_SND_SIMPLE_CARD is not set
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=m
++
++#
++# HID support
++#
++CONFIG_HID=y
++# CONFIG_HID_BATTERY_STRENGTH is not set
++# CONFIG_HIDRAW is not set
++CONFIG_UHID=m
++CONFIG_HID_GENERIC=y
++
++#
++# Special HID drivers
++#
++# CONFIG_HID_A4TECH is not set
++# CONFIG_HID_ACRUX is not set
++# CONFIG_HID_APPLE is not set
++# CONFIG_HID_AUREAL is not set
++# CONFIG_HID_BELKIN is not set
++# CONFIG_HID_CHERRY is not set
++# CONFIG_HID_CHICONY is not set
++# CONFIG_HID_PRODIKEYS is not set
++# CONFIG_HID_CYPRESS is not set
++# CONFIG_HID_DRAGONRISE is not set
++# CONFIG_HID_EMS_FF is not set
++# CONFIG_HID_ELECOM is not set
++# CONFIG_HID_EZKEY is not set
++# CONFIG_HID_HOLTEK is not set
++# CONFIG_HID_KEYTOUCH is not set
++# CONFIG_HID_KYE is not set
++# CONFIG_HID_UCLOGIC is not set
++# CONFIG_HID_WALTOP is not set
++# CONFIG_HID_GYRATION is not set
++# CONFIG_HID_TWINHAN is not set
++# CONFIG_HID_KENSINGTON is not set
++# CONFIG_HID_LCPOWER is not set
++CONFIG_HID_LENOVO_TPKBD=m
++# CONFIG_HID_LOGITECH is not set
++# CONFIG_HID_MAGICMOUSE is not set
++# CONFIG_HID_MICROSOFT is not set
++# CONFIG_HID_MONTEREY is not set
++# CONFIG_HID_MULTITOUCH is not set
++# CONFIG_HID_NTRIG is not set
++# CONFIG_HID_ORTEK is not set
++# CONFIG_HID_PANTHERLORD is not set
++# CONFIG_HID_PETALYNX is not set
++# CONFIG_HID_PICOLCD is not set
++# CONFIG_HID_PRIMAX is not set
++CONFIG_HID_PS3REMOTE=m
++# CONFIG_HID_ROCCAT is not set
++# CONFIG_HID_SAITEK is not set
++# CONFIG_HID_SAMSUNG is not set
++# CONFIG_HID_SONY is not set
++# CONFIG_HID_SPEEDLINK is not set
++# CONFIG_HID_SUNPLUS is not set
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
++# CONFIG_HID_TIVO is not set
++# CONFIG_HID_TOPSEED is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_WACOM is not set
++# CONFIG_HID_WIIMOTE is not set
++# CONFIG_HID_ZEROPLUS is not set
++# CONFIG_HID_ZYDACRON is not set
++CONFIG_HID_SENSOR_HUB=m
++
++#
++# USB HID support
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++# CONFIG_USB_ARCH_HAS_XHCI is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_COMMON=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB=y
++CONFIG_USB_DEBUG=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++
++#
++# Miscellaneous USB options
++#
++# 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_DWC3 is not set
++CONFIG_USB_MON=y
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_EHCI_HCD is not set
++# CONFIG_USB_OXU210HP_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_ISP1362_HCD is not set
++# CONFIG_USB_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_MUSB_HDRC=y
++# CONFIG_USB_MUSB_TUSB6010 is not set
++# CONFIG_USB_MUSB_OMAP2PLUS is not set
++# CONFIG_USB_MUSB_AM35X is not set
++CONFIG_USB_MUSB_DSPS=y
++CONFIG_MUSB_PIO_ONLY=y
++# CONFIG_USB_CHIPIDEA is not set
++# CONFIG_USB_RENESAS_USBHS 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_REALTEK is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_STORAGE_ENE_UB6250 is not set
++CONFIG_USB_UAS=y
++
++#
++# USB Imaging devices
++#
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++
++#
++# USB port drivers
++#
++CONFIG_USB_SERIAL=m
++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_F81232=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_METRO=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_QCAUX=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_WWAN=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
++CONFIG_USB_SERIAL_ZIO=m
++CONFIG_USB_SERIAL_ZTE=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_QT2=m
++CONFIG_USB_SERIAL_DEBUG=m
++
++#
++# USB Miscellaneous drivers
++#
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=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=m
++CONFIG_USB_SISUSBVGA=m
++CONFIG_USB_SISUSBVGA_CON=y
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_USB_EZUSB_FX2=m
++
++#
++# USB Physical Layer drivers
++#
++CONFIG_OMAP_USB2=y
++CONFIG_USB_ISP1301=m
++CONFIG_USB_GADGET=y
++CONFIG_USB_GADGET_DEBUG=y
++CONFIG_USB_GADGET_DEBUG_FILES=y
++CONFIG_USB_GADGET_DEBUG_FS=y
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
++
++#
++# USB Peripheral Controller
++#
++# CONFIG_USB_FUSB300 is not set
++# CONFIG_USB_R8A66597 is not set
++# CONFIG_USB_MV_UDC is not set
++CONFIG_USB_GADGET_MUSB_HDRC=y
++# CONFIG_USB_M66592 is not set
++# CONFIG_USB_NET2272 is not set
++# CONFIG_USB_DUMMY_HCD is not set
++CONFIG_USB_LIBCOMPOSITE=m
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
++CONFIG_USB_ETH=m
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_ETH_EEM is not set
++# CONFIG_USB_G_NCM is not set
++CONFIG_USB_GADGETFS=m
++# CONFIG_USB_FUNCTIONFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++CONFIG_USB_MASS_STORAGE=m
++CONFIG_USB_G_SERIAL=m
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++CONFIG_USB_CDC_COMPOSITE=m
++# CONFIG_USB_G_NOKIA is not set
++# CONFIG_USB_G_ACM_MS is not set
++# CONFIG_USB_G_MULTI is not set
++CONFIG_USB_G_HID=m
++# CONFIG_USB_G_DBGP is not set
++# CONFIG_USB_G_WEBCAM is not set
++
++#
++# OTG and related infrastructure
++#
++CONFIG_USB_OTG_UTILS=y
++CONFIG_USB_GPIO_VBUS=m
++# CONFIG_USB_ULPI is not set
++CONFIG_TWL4030_USB=y
++CONFIG_TWL6030_USB=y
++CONFIG_NOP_USB_XCEIV=y
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++CONFIG_MMC_UNSAFE_RESUME=y
++# CONFIG_MMC_CLKGATE is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_MINORS=8
++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_SDHCI_PXAV3 is not set
++# CONFIG_MMC_SDHCI_PXAV2 is not set
++CONFIG_MMC_OMAP=y
++CONFIG_MMC_OMAP_HS=y
++# CONFIG_MMC_DW is not set
++# CONFIG_MMC_VUB300 is not set
++# CONFIG_MMC_USHC is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_LM3530 is not set
++CONFIG_LEDS_LM3642=m
++# CONFIG_LEDS_PCA9532 is not set
++CONFIG_LEDS_GPIO=y
++# CONFIG_LEDS_LP3944 is not set
++# CONFIG_LEDS_LP5521 is not set
++# CONFIG_LEDS_LP5523 is not set
++# CONFIG_LEDS_PCA955X is not set
++# CONFIG_LEDS_PCA9633 is not set
++# CONFIG_LEDS_DAC124S085 is not set
++# CONFIG_LEDS_REGULATOR is not set
++# CONFIG_LEDS_BD2802 is not set
++# CONFIG_LEDS_LT3593 is not set
++# CONFIG_LEDS_RENESAS_TPU is not set
++# CONFIG_LEDS_TCA6507 is not set
++CONFIG_LEDS_LM355x=m
++# CONFIG_LEDS_OT200 is not set
++CONFIG_LEDS_BLINKM=m
++CONFIG_LEDS_TRIGGERS=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_ONESHOT=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_LEDS_TRIGGER_BACKLIGHT=y
++CONFIG_LEDS_TRIGGER_CPU=y
++CONFIG_LEDS_TRIGGER_GPIO=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++
++#
++# iptables trigger is under Netfilter config (LED target)
++#
++CONFIG_LEDS_TRIGGER_TRANSIENT=y
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_EDAC is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_DS3232 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_ISL12022 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_BQ32K is not set
++CONFIG_RTC_DRV_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
++# CONFIG_RTC_DRV_EM3027 is not set
++# CONFIG_RTC_DRV_RV3029C2 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T93 is not set
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++# CONFIG_RTC_DRV_PCF2123 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_MSM6242 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_RP5C01 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++CONFIG_RTC_DRV_DS2404=m
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_SNVS=m
++CONFIG_DMADEVICES=y
++# CONFIG_DMADEVICES_DEBUG is not set
++
++#
++# DMA Devices
++#
++# CONFIG_DW_DMAC is not set
++# CONFIG_TIMB_DMA is not set
++CONFIG_TI_EDMA=y
++# CONFIG_DMA_OMAP is not set
++CONFIG_DMA_ENGINE=y
++CONFIG_DMA_VIRTUAL_CHANNELS=y
++
++#
++# DMA Clients
++#
++CONFIG_NET_DMA=y
++CONFIG_ASYNC_TX_DMA=y
++CONFIG_DMATEST=m
++# CONFIG_AUXDISPLAY is not set
++CONFIG_UIO=y
++CONFIG_UIO_PDRV=y
++CONFIG_UIO_PDRV_GENIRQ=y
++CONFIG_VIRTIO=m
++
++#
++# Virtio drivers
++#
++# CONFIG_VIRTIO_BALLOON is not set
++# CONFIG_VIRTIO_MMIO is not set
++
++#
++# Microsoft Hyper-V guest support
++#
++# CONFIG_STAGING is not set
++CONFIG_CLKDEV_LOOKUP=y
++CONFIG_HWSPINLOCK=m
++
++#
++# Hardware Spinlock drivers
++#
++CONFIG_HWSPINLOCK_OMAP=m
++CONFIG_CLKSRC_MMIO=y
++CONFIG_IOMMU_SUPPORT=y
++CONFIG_OF_IOMMU=y
++# CONFIG_OMAP_IOMMU is not set
++
++#
++# Remoteproc drivers (EXPERIMENTAL)
++#
++CONFIG_REMOTEPROC=m
++CONFIG_STE_MODEM_RPROC=m
++
++#
++# Rpmsg drivers (EXPERIMENTAL)
++#
++# CONFIG_VIRT_DRIVERS is not set
++# CONFIG_PM_DEVFREQ is not set
++# CONFIG_EXTCON is not set
++# CONFIG_MEMORY is not set
++CONFIG_IIO=y
++CONFIG_IIO_BUFFER=y
++CONFIG_IIO_KFIFO_BUF=m
++CONFIG_IIO_TRIGGERED_BUFFER=m
++CONFIG_IIO_TRIGGER=y
++CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
++
++#
++# Accelerometers
++#
++CONFIG_HID_SENSOR_ACCEL_3D=m
++
++#
++# Analog to digital converters
++#
++CONFIG_AD_SIGMA_DELTA=m
++CONFIG_AD7266=m
++CONFIG_AD7791=m
++CONFIG_AD7476=m
++CONFIG_TI_AM335X_ADC=y
++
++#
++# Amplifiers
++#
++# CONFIG_AD8366 is not set
++
++#
++# Light sensors
++#
++CONFIG_ADJD_S311=m
++CONFIG_VCNL4000=m
++CONFIG_HID_SENSOR_ALS=m
++
++#
++# Frequency Synthesizers DDS/PLL
++#
++
++#
++# Clock Generator/Distribution
++#
++CONFIG_AD9523=m
++
++#
++# Phase-Locked Loop (PLL) frequency synthesizers
++#
++CONFIG_ADF4350=m
++
++#
++# Digital to analog converters
++#
++CONFIG_AD5064=m
++CONFIG_AD5360=m
++CONFIG_AD5380=m
++CONFIG_AD5421=m
++CONFIG_AD5624R_SPI=m
++CONFIG_AD5446=m
++CONFIG_AD5504=m
++CONFIG_AD5755=m
++CONFIG_AD5764=m
++CONFIG_AD5791=m
++CONFIG_AD5686=m
++CONFIG_MAX517=m
++CONFIG_MCP4725=m
++
++#
++# Hid Sensor IIO Common
++#
++CONFIG_HID_SENSOR_IIO_COMMON=m
++CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=m
++
++#
++# Digital gyroscope sensors
++#
++CONFIG_HID_SENSOR_GYRO_3D=m
++
++#
++# Light sensors
++#
++
++#
++# Magnetometer sensors
++#
++CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
++CONFIG_PWM=y
++CONFIG_PWM_TIECAP=y
++CONFIG_PWM_TIEHRPWM=y
++# CONFIG_PWM_TWL6030 is not set
++CONFIG_EHRPWM_TEST=m
++
++#
++# CAPEBUS support
++#
++CONFIG_CAPEBUS=y
++CONFIG_CAPEBUS_BONE_CONTROLLER=y
++CONFIG_CAPEBUS_BONE_GENERIC=y
++CONFIG_CAPEBUS_BONE_GEIGER=y
++
++#
++# File systems
++#
++CONFIG_DCACHE_WORD_ACCESS=y
++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=y
++# CONFIG_EXT3_FS_XATTR is not set
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_XATTR=y
++# CONFIG_EXT4_FS_POSIX_ACL is not set
++# CONFIG_EXT4_FS_SECURITY is not set
++# CONFIG_EXT4_DEBUG is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_JBD2=y
++# CONFIG_JBD2_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++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_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++# CONFIG_XFS_DEBUG is not set
++CONFIG_GFS2_FS=m
++CONFIG_BTRFS_FS=m
++# CONFIG_BTRFS_FS_POSIX_ACL is not set
++# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
++CONFIG_NILFS2_FS=m
++CONFIG_FS_POSIX_ACL=y
++CONFIG_EXPORTFS=m
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_FANOTIFY is not set
++CONFIG_QUOTA=y
++# CONFIG_QUOTA_NETLINK_INTERFACE is not set
++CONFIG_PRINT_QUOTA_WARNING=y
++# CONFIG_QUOTA_DEBUG is not set
++CONFIG_QUOTA_TREE=y
++# CONFIG_QFMT_V1 is not set
++CONFIG_QFMT_V2=y
++CONFIG_QUOTACTL=y
++CONFIG_AUTOFS4_FS=m
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++
++#
++# 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_TMPFS_XATTR 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_ECRYPT_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_ADVANCED_COMPR is not set
++CONFIG_UBIFS_FS_LZO=y
++CONFIG_UBIFS_FS_ZLIB=y
++# CONFIG_LOGFS is not set
++CONFIG_CRAMFS=y
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_QNX6FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_PSTORE is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_F2FS_FS=y
++CONFIG_F2FS_STAT_FS=y
++CONFIG_F2FS_FS_XATTR=y
++CONFIG_F2FS_FS_POSIX_ACL=y
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V2=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_SWAP=y
++# CONFIG_NFS_V4_1 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFS_USE_LEGACY_DNS is not set
++CONFIG_NFS_USE_KERNEL_DNS=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_SWAP=y
++# CONFIG_SUNRPC_DEBUG is not set
++# CONFIG_CEPH_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++# CONFIG_9P_FS 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_MAC_ROMAN is not set
++# CONFIG_NLS_MAC_CELTIC is not set
++# CONFIG_NLS_MAC_CENTEURO is not set
++# CONFIG_NLS_MAC_CROATIAN is not set
++# CONFIG_NLS_MAC_CYRILLIC is not set
++# CONFIG_NLS_MAC_GAELIC is not set
++# CONFIG_NLS_MAC_GREEK is not set
++# CONFIG_NLS_MAC_ICELAND is not set
++# CONFIG_NLS_MAC_INUIT is not set
++# CONFIG_NLS_MAC_ROMANIAN is not set
++# CONFIG_NLS_MAC_TURKISH is not set
++# CONFIG_NLS_UTF8 is not set
++
++#
++# Kernel hacking
++#
++CONFIG_PRINTK_TIME=y
++CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_READABLE_ASM is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_SECTION_MISMATCH is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
++# CONFIG_LOCKUP_DETECTOR is not set
++# CONFIG_PANIC_ON_OOPS is not set
++CONFIG_PANIC_ON_OOPS_VALUE=0
++# CONFIG_DETECT_HUNG_TASK is not set
++CONFIG_SCHED_DEBUG=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_DEBUG_SLAB is not set
++CONFIG_HAVE_DEBUG_KMEMLEAK=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 is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_SPARSE_RCU_POINTER is not set
++# CONFIG_LOCK_STAT is not set
++# CONFIG_DEBUG_ATOMIC_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_STACK_USAGE is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_HIGHMEM is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_INFO_REDUCED=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_TEST_LIST_SORT is not set
++# CONFIG_DEBUG_SG is not set
++# CONFIG_DEBUG_NOTIFIERS is not set
++# CONFIG_DEBUG_CREDENTIALS is not set
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++CONFIG_RCU_CPU_STALL_TIMEOUT=60
++# CONFIG_RCU_CPU_STALL_INFO is not set
++# CONFIG_RCU_TRACE is not set
++# CONFIG_KPROBES_SANITY_TEST is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
++# CONFIG_DEBUG_PER_CPU_MAPS is not set
++# CONFIG_LKDTM is not set
++CONFIG_NOTIFIER_ERROR_INJECTION=m
++# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
++CONFIG_PM_NOTIFIER_ERROR_INJECT=m
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_DEBUG_PAGEALLOC is not set
++CONFIG_NOP_TRACER=y
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_HAVE_DYNAMIC_FTRACE=y
++CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
++CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
++CONFIG_HAVE_C_RECORDMCOUNT=y
++CONFIG_TRACE_CLOCK=y
++CONFIG_RING_BUFFER=y
++CONFIG_EVENT_TRACING=y
++CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
++CONFIG_CONTEXT_SWITCH_TRACER=y
++CONFIG_RING_BUFFER_ALLOW_SWAP=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_ENABLE_DEFAULT_TRACERS is not set
++# CONFIG_FTRACE_SYSCALLS 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_BLK_DEV_IO_TRACE is not set
++CONFIG_KPROBE_EVENT=y
++CONFIG_PROBE_EVENTS=y
++# CONFIG_RING_BUFFER_BENCHMARK is not set
++# CONFIG_RBTREE_TEST is not set
++# CONFIG_INTERVAL_TREE_TEST is not set
++# CONFIG_DYNAMIC_DEBUG is not set
++# CONFIG_DMA_API_DEBUG is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++# CONFIG_TEST_KSTRTOX is not set
++# CONFIG_STRICT_DEVMEM is not set
++CONFIG_ARM_UNWIND=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_LL is not set
++CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
++# CONFIG_ARM_KPROBES_TEST is not set
++# CONFIG_PID_IN_CONTEXTIDR is not set
++
++#
++# Security options
++#
++CONFIG_KEYS=y
++# CONFIG_ENCRYPTED_KEYS is not set
++# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
++# CONFIG_SECURITY_DMESG_RESTRICT is not set
++CONFIG_SECURITY=y
++CONFIG_SECURITYFS=y
++# CONFIG_SECURITY_NETWORK is not set
++# CONFIG_SECURITY_PATH is not set
++# CONFIG_SECURITY_TOMOYO is not set
++# CONFIG_SECURITY_APPARMOR is not set
++# CONFIG_SECURITY_YAMA is not set
++# CONFIG_IMA is not set
++# CONFIG_EVM is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=m
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=y
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++# CONFIG_CRYPTO_USER is not set
++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++CONFIG_CRYPTO_PCRYPT=y
++CONFIG_CRYPTO_WORKQUEUE=y
++# CONFIG_CRYPTO_CRYPTD is not set
++CONFIG_CRYPTO_AUTHENC=m
++# 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=m
++# 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 is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++CONFIG_CRYPTO_HMAC=m
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=m
++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_SHA1_ARM 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_AES_ARM=y
++# 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=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 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++CONFIG_CRYPTO_DEFLATE=y
++# CONFIG_CRYPTO_ZLIB is not set
++CONFIG_CRYPTO_LZO=y
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_USER_API_HASH is not set
++# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
++CONFIG_CRYPTO_HW=y
++# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
++# CONFIG_CRYPTO_DEV_OMAP_AES is not set
++CONFIG_ASYMMETRIC_KEY_TYPE=m
++CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
++CONFIG_PUBLIC_KEY_ALGO_RSA=m
++CONFIG_X509_CERTIFICATE_PARSER=m
++CONFIG_BINARY_PRINTF=y
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_STRNCPY_FROM_USER=y
++CONFIG_GENERIC_STRNLEN_USER=y
++CONFIG_GENERIC_PCI_IOMAP=y
++CONFIG_GENERIC_IO=y
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++CONFIG_CRC_T10DIF=y
++CONFIG_CRC_ITU_T=y
++CONFIG_CRC32=y
++# CONFIG_CRC32_SELFTEST is not set
++CONFIG_CRC32_SLICEBY8=y
++# CONFIG_CRC32_SLICEBY4 is not set
++# CONFIG_CRC32_SARWATE is not set
++# CONFIG_CRC32_BIT is not set
++CONFIG_CRC7=y
++CONFIG_LIBCRC32C=y
++# CONFIG_CRC8 is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++# CONFIG_XZ_DEC is not set
++# CONFIG_XZ_DEC_BCJ is not set
++CONFIG_DECOMPRESS_GZIP=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_CPU_RMAP=y
++CONFIG_DQL=y
++CONFIG_NLATTR=y
++CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
++CONFIG_AVERAGE=y
++CONFIG_CLZ_TAB=y
++# CONFIG_CORDIC is not set
++# CONFIG_DDR is not set
++CONFIG_MPILIB=m
++CONFIG_OID_REGISTRY=m
diff --git a/patches/linux-3.7/0162-capebus-Geiger-Cape-config-bugfixs.patch b/patches/linux-3.7/0162-capebus-Geiger-Cape-config-bugfixs.patch
new file mode 100644
index 0000000..1fc46b7
--- /dev/null
+++ b/patches/linux-3.7/0162-capebus-Geiger-Cape-config-bugfixs.patch
@@ -0,0 +1,26 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sun, 18 Nov 2012 23:26:20 +0000
+Subject: [PATCH] capebus: Geiger Cape config bugfixs
+
+The display of 'vsense-name' default is incorrect.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/capebus/capes/bone-geiger-cape.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/capebus/capes/bone-geiger-cape.c b/drivers/capebus/capes/bone-geiger-cape.c
+index 9b3a83d..d972622 100644
+--- a/drivers/capebus/capes/bone-geiger-cape.c
++++ b/drivers/capebus/capes/bone-geiger-cape.c
+@@ -428,8 +428,8 @@ static int bonegeiger_probe(struct cape_dev *dev, const struct cape_device_id *i
+ "vsense-name", &info->vsense_name) != 0) {
+ info->vsense_name = "AIN5";
+ dev_warn(&dev->dev, "Could not read vsense-name property; "
+- "using default %u\n",
+- val);
++ "using default '%s'\n",
++ info->vsense_name);
+ }
+
+ if (capebus_of_property_read_u32(dev,
diff --git a/patches/linux-3.7/0163-am335x-bone-Add-spi0-pins-defines.patch b/patches/linux-3.7/0163-am335x-bone-Add-spi0-pins-defines.patch
new file mode 100644
index 0000000..6e46fc0
--- /dev/null
+++ b/patches/linux-3.7/0163-am335x-bone-Add-spi0-pins-defines.patch
@@ -0,0 +1,43 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Sat, 24 Nov 2012 03:26:03 -0800
+Subject: [PATCH] am335x-bone: Add spi0 pins defines
+
+Sometimes you need use the other SPI bus in the device tree due to
+pin muxing this allows easy references for switching.
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 46d5f27..0378046 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -24,6 +24,14 @@
+ };
+
+ am3358_pinmux: pinmux@44e10800 {
++ spi0_pins: pinmux_spi0_pins {
++ pinctrl-single,pins = <
++ 0x150 0x10 /* spi0_sclk.gpio0_2, OUTPUT_PULLUP | MODE0 */
++ 0x154 0x30 /* spi0_d0.gpio0_3, INPUT_PULLUP | MODE0 */
++ 0x158 0x10 /* spi0_d1.i2c1_sda, OUTPUT_PULLUP | MODE0 */
++ 0x15c 0x10 /* spi0_cs0.i2c1_scl, OUTPUT_PULLUP | MODE0 */
++ >;
++ };
+ spi1_pins: pinmux_spi1_pins {
+ pinctrl-single,pins = <
+ 0x190 0x13 /* mcasp0_aclkx.spi1_sclk, OUTPUT_PULLUP | MODE3 */
+@@ -401,6 +409,11 @@
+ vmmc-supply = <&ldo3_reg>;
+ };
+
++&spi0 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spi0_pins>;
++};
++
+ &spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
diff --git a/patches/linux-3.7/0164-Allow-more-than-one-instance-of-generic-devices.patch b/patches/linux-3.7/0164-Allow-more-than-one-instance-of-generic-devices.patch
new file mode 100644
index 0000000..d266cec
--- /dev/null
+++ b/patches/linux-3.7/0164-Allow-more-than-one-instance-of-generic-devices.patch
@@ -0,0 +1,64 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:29 +0200
+Subject: [PATCH] Allow more than one instance of generic devices
+
+Generate unique name to allow more than one instance of devices.
+---
+ drivers/capebus/capebus-driver.c | 19 ++++++++++++++++++-
+ include/linux/capebus.h | 7 ++++---
+ 2 files changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/capebus/capebus-driver.c b/drivers/capebus/capebus-driver.c
+index 82b1d1b..a299c77 100644
+--- a/drivers/capebus/capebus-driver.c
++++ b/drivers/capebus/capebus-driver.c
+@@ -441,13 +441,30 @@ capebus_of_platform_compatible_device_create(struct cape_dev *dev,
+ {
+ struct device_node *node;
+ struct platform_device *pdev;
++ char *name, *buf;
+
+ node = capebus_of_compatible_device_property_match(dev, matches, prop,
+ prop_value);
+ if (node == NULL)
+ return ERR_PTR(-ENXIO);
+
+- pdev = of_platform_device_create(node, pdev_name, dev->bus->dev.parent);
++ /* create system-wide unique name */
++ buf = kasprintf(GFP_KERNEL, "%d:%d-%s.%d",
++ dev->bus->busno, dev->slot->slotno,
++ pdev_name, dev->slot->next_pdevid++);
++ if (buf == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ name = devm_kzalloc(&dev->dev, strlen(buf) + 1, GFP_KERNEL);
++ kfree(buf);
++
++ if (name == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ /* safe */
++ strcpy(name, buf);
++
++ pdev = of_platform_device_create(node, name, &dev->dev);
+
+ /* release the reference to the node */
+ of_node_put(node);
+diff --git a/include/linux/capebus.h b/include/linux/capebus.h
+index 7524401..2f8ab7b 100644
+--- a/include/linux/capebus.h
++++ b/include/linux/capebus.h
+@@ -43,9 +43,10 @@ struct cape_slot;
+
+ struct cape_slot {
+ struct list_head node;
+- struct cape_bus *bus; /* the bus this slot is on */
+- int slotno; /* index of this slot */
+- struct cape_dev *dev; /* the device (if found) */
++ struct cape_bus *bus; /* the bus this slot is on */
++ int slotno; /* index of this slot */
++ struct cape_dev *dev; /* the device (if found) */
++ unsigned int next_pdevid; /* next assigned pdev_id */
+ };
+
+ struct cape_driver {
diff --git a/patches/linux-3.7/0165-Mark-the-device-as-PRIVATE.patch b/patches/linux-3.7/0165-Mark-the-device-as-PRIVATE.patch
new file mode 100644
index 0000000..4a4c293
--- /dev/null
+++ b/patches/linux-3.7/0165-Mark-the-device-as-PRIVATE.patch
@@ -0,0 +1,52 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:31 +0200
+Subject: [PATCH] Mark the device as PRIVATE
+
+Turns out if you enable CONFIG_NET_DMA the ip stack will try
+to grab all the available non-private DMA channels sometime late in the
+boot sequence.
+
+That's bad enough, what is worse is that it brindly iterates over
+any possible channel; if the driver returns ENODEV on any of the
+channels dmaengine will remove the device from the list of available
+dma devices.
+
+Very crazy bug.
+---
+ drivers/dma/edma.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 47ba7bf..75ab2d5 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -394,8 +394,11 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
+ chan, EVENTQ_DEFAULT);
+
++ /* NOTE: DO NOT RETURN ENODEV */
++ /* It causes dmaengine to remove the device from it's list */
++
+ if (a_ch_num < 0) {
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_no_chan;
+ }
+
+@@ -403,7 +406,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ dev_err(dev, "failed to allocate requested channel %u:%u\n",
+ EDMA_CTLR(echan->ch_num),
+ EDMA_CHAN_SLOT(echan->ch_num));
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_wrong_chan;
+ }
+
+@@ -564,6 +567,7 @@ static int __devinit edma_probe(struct platform_device *pdev)
+
+ dma_cap_zero(ecc->dma_slave.cap_mask);
+ dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
++ dma_cap_set(DMA_PRIVATE, ecc->dma_slave.cap_mask);
+
+ edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+
diff --git a/patches/linux-3.7/0166-DT-overlay.patch b/patches/linux-3.7/0166-DT-overlay.patch
new file mode 100644
index 0000000..f41f1b8
--- /dev/null
+++ b/patches/linux-3.7/0166-DT-overlay.patch
@@ -0,0 +1,448 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:32 +0200
+Subject: [PATCH] DT overlay
+
+For things like uarts and mmc hosts you need to overlay DT.
+---
+ drivers/capebus/boards/capebus-bone-generic.c | 6 +
+ drivers/capebus/boards/capebus-bone-pdevs.c | 389 +++++++++++++++++++++++++
+ 2 files changed, 395 insertions(+)
+
+diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
+index b1b79eb..8c2c6cc 100644
+--- a/drivers/capebus/boards/capebus-bone-generic.c
++++ b/drivers/capebus/boards/capebus-bone-generic.c
+@@ -141,6 +141,12 @@ static const struct bone_capebus_generic_device_data gendevs[] = {
+ { .compatible = "spi-dt", }, { },
+ },
+ .units = 0, /* no limit */
++ }, {
++ .name = "dt-overlay",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "dt-overlay", }, { },
++ },
++ .units = 0, /* no limit */
+ }
+ };
+
+diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
+index f32134a..f97100b 100644
+--- a/drivers/capebus/boards/capebus-bone-pdevs.c
++++ b/drivers/capebus/boards/capebus-bone-pdevs.c
+@@ -22,6 +22,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
++#include <linux/ctype.h>
+ #include <linux/timer.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+@@ -38,6 +39,7 @@
+ #include <linux/clk.h>
+ #include <asm/barrier.h>
+ #include <linux/i2c.h>
++#include <linux/of.h>
+ #include <linux/of_i2c.h>
+ #include <linux/spi/spi.h>
+
+@@ -246,6 +248,390 @@ static struct platform_driver spi_dt_driver = {
+ },
+ };
+
++/*******************************************************************/
++
++static int of_is_printable_string(const void *data, int len)
++{
++ const char *s = data;
++ const char *ss, *se;
++
++ /* zero length is not */
++ if (len == 0)
++ return 0;
++
++ /* must terminate with zero */
++ if (s[len - 1] != '\0')
++ return 0;
++
++ se = s + len;
++
++ while (s < se) {
++ ss = s;
++ while (s < se && *s && isprint(*s))
++ s++;
++
++ /* not zero, or not done yet */
++ if (*s != '\0' || s == ss)
++ return 0;
++
++ s++;
++ }
++
++ return 1;
++}
++
++static char *of_dump_prop(struct property *prop)
++{
++ const void *data = prop->value;
++ int len = prop->length;
++ int i, tbuflen;
++ const char *p = data;
++ const char *s;
++ char *buf, *bufp, *bufe;
++
++ /* play it safe */
++ buf = kmalloc(PAGE_SIZE + len * 8, GFP_KERNEL);
++ if (buf == NULL)
++ return NULL;
++ bufp = buf;
++ bufe = buf + PAGE_SIZE + len * 8;
++
++#undef append_sprintf
++#define append_sprintf(format, ...) \
++ do { \
++ tbuflen = snprintf(NULL, 0, format, ## __VA_ARGS__); \
++ if (bufp + tbuflen + 1 >= bufe) \
++ goto err_out; \
++ snprintf(bufp, tbuflen + 1, format, ## __VA_ARGS__); \
++ bufp += tbuflen; \
++ } while(0)
++
++ if (len == 0) {
++ /* nothing; just terminate */
++ *buf = '\0';
++ return buf;
++ }
++
++ append_sprintf(" = ");
++
++ if (of_is_printable_string(data, len)) {
++ s = data;
++ do {
++ append_sprintf("\"%s\"", s);
++ s += strlen(s) + 1;
++ if (s < (const char *)data + len)
++ append_sprintf(", ");
++ } while (s < (const char *)data + len);
++
++ } else if ((len % 4) == 0) {
++ append_sprintf("<");
++ for (i = 0; i < len; i += 4)
++ append_sprintf("0x%08x%s",
++ be32_to_cpu(*(uint32_t *)(p + i)),
++ i < (len - 4) ? " " : "");
++ append_sprintf(">");
++ } else {
++ append_sprintf("[");
++ for (i = 0; i < len; i++)
++ append_sprintf("%02x%s", *(p + i),
++ i < len - 1 ? " " : "");
++ append_sprintf("]");
++ }
++
++ return buf;
++err_out:
++ kfree(buf);
++ return NULL;
++#undef append_sprintf
++}
++
++static void of_dump_tree(struct device *dev, int level,
++ struct device_node *node)
++{
++ struct device_node *child;
++ struct property *prop;
++ static const char *leveltab = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
++ int maxlevel = strlen(leveltab);
++ const char *thislevel;
++ const char *nextlevel;
++ char *propstr;
++
++ thislevel = leveltab + maxlevel - level;
++ if (thislevel < leveltab)
++ thislevel = leveltab;
++ nextlevel = thislevel - 1;
++ if (nextlevel < leveltab)
++ nextlevel = leveltab;
++
++ dev_info(dev, "%s%s {\n", thislevel, node->name);
++
++ for_each_property_of_node(node, prop) {
++
++ if (strcmp(prop->name, "name") == 0)
++ continue;
++
++ propstr = of_dump_prop(prop);
++ dev_info(dev, "%s%s%s;\n", nextlevel, prop->name,
++ propstr ? propstr : "*ERROR*");
++ kfree(propstr);
++ }
++
++ for_each_child_of_node(node, child)
++ of_dump_tree(dev, level + 1, child);
++
++ dev_info(dev, "%s};", thislevel);
++}
++
++struct dt_fragment {
++ struct list_head node;
++ struct device_node *target_node;
++ int status_changed : 1;
++ int status_new : 1;
++
++ struct device_node *saved_tree;
++};
++
++struct dt_overlay_priv {
++ struct list_head frag_list;
++};
++
++static const struct of_device_id of_dt_overlay_match[] = {
++ { .compatible = "dt-overlay", },
++ {},
++};
++
++#define for_each_property_of_node_safe(dn, pp, ppn) \
++ for (pp = dn->properties, ppn = pp ? pp->next : NULL; pp != NULL; pp = ppn, ppn = pp->next)
++
++static void of_overlay_node(struct device *dev, struct device_node *target, struct device_node *overlay)
++{
++ struct device_node *child;
++ struct device_node **childp;
++ struct property *prop, *propn;
++ struct property **propp;
++ char *propstr;
++ int found;
++
++ dev_info(dev, "Overlaying target %p with overlay %p\n", target, overlay);
++
++ while ((prop = overlay->properties) != NULL) {
++ /* remove head prop */
++ overlay->properties = prop->next;
++ prop->next = NULL;
++
++ found = 0;
++ propp = &target->properties;
++ while (*propp) {
++
++ /* found? */
++ if (of_prop_cmp((*propp)->name, prop->name) == 0) {
++ found = 1;
++ break;
++ }
++
++ propp = &(*propp)->next;
++ }
++
++ if (found) {
++ propn = (*propp)->next;
++ prop->next = propn;
++ /* propn is now dead */
++
++ }
++
++ *propp = prop;
++
++ propstr = of_dump_prop(prop);
++ dev_info(dev, "%c %s%s;\n", found ? 'U' : 'I', prop->name, propstr);
++ kfree(propstr);
++ }
++
++ /* remove each child */
++ while ((child = overlay->child) != NULL) {
++ overlay->child = child->sibling;
++ child->sibling = NULL;
++
++ found = 0;
++ childp = &target->child;
++ while (*childp) {
++
++ /* found? */
++ if ((*childp)->name && of_node_cmp((*childp)->name, child->name) == 0) {
++ found = 1;
++ break;
++ }
++
++ childp = &(*childp)->sibling;
++ }
++
++ if (found) {
++ dev_info(dev, "overlaying node '%s'\n", child->name);
++ of_overlay_node(dev, (*childp), child);
++ } else {
++ *childp = child;
++ child->parent = target;
++
++ dev_info(dev, "inserted node '%s'\n", child->name);
++ }
++ }
++}
++
++static int __devinit dt_overlay_probe(struct platform_device *pdev)
++{
++ struct dt_overlay_priv *priv = NULL;
++ struct dt_fragment *frag;
++ int ret = -EINVAL;
++ struct device_node *target_node, *node, *tnode;
++ u32 val;
++ int prev_status, new_status;
++ struct platform_device *target_pdev, *parent_pdev;
++ struct list_head *lh, *lhp;
++ unsigned long flags;
++
++ frag = NULL;
++ target_node = NULL;
++ ret = 0;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++ INIT_LIST_HEAD(&priv->frag_list);
++
++ frag = NULL;
++ target_node = NULL;
++ ret = 0;
++
++ /* iterate over fragment children */
++ for_each_child_of_node(pdev->dev.of_node, node) {
++
++ frag = NULL;
++ target_node = NULL;
++
++ frag = devm_kzalloc(&pdev->dev, sizeof(*frag), GFP_KERNEL);
++ if (frag == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate frag\n");
++ ret = -ENOMEM;
++ goto err_fail;
++ }
++
++ ret = of_property_read_u32(node, "target", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find target property\n");
++ goto err_fail;
++ }
++
++ target_node = of_find_node_by_phandle(val);
++ if (target_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find target node\n");
++ ret = -EINVAL;
++ goto err_fail;
++ }
++
++ frag->target_node = target_node;
++
++ prev_status = of_device_is_available(target_node);
++
++ tnode = of_get_child_by_name(node, "content");
++
++ dev_info(&pdev->dev, "overlay %p (before)\n", tnode);
++ of_dump_tree(&pdev->dev, 1, tnode);
++ dev_info(&pdev->dev, "\n");
++
++ dev_info(&pdev->dev, "target %p (before)\n", target_node);
++ of_dump_tree(&pdev->dev, 1, target_node);
++ dev_info(&pdev->dev, "\n");
++
++ write_lock_irqsave(&devtree_lock, flags);
++ of_overlay_node(&pdev->dev, target_node, tnode);
++ write_unlock_irqrestore(&devtree_lock, flags);
++
++ dev_info(&pdev->dev, "target %p (after)\n", target_node);
++ of_dump_tree(&pdev->dev, 1, target_node);
++ dev_info(&pdev->dev, "\n");
++
++ of_node_put(tnode);
++
++ new_status = of_device_is_available(target_node);
++
++ dev_info(&pdev->dev, "target prev %d new %d\n",
++ prev_status, new_status);
++
++ if (prev_status != new_status) {
++
++ if (new_status) {
++ parent_pdev = of_find_device_by_node(target_node->parent);
++
++ target_pdev = of_platform_device_create(target_node, NULL,
++ parent_pdev ? &parent_pdev->dev : NULL);
++ if (target_pdev == NULL) {
++ dev_info(&pdev->dev, "failed to enable platform_device\n");
++ platform_device_put(parent_pdev);
++ goto err_fail;
++ }
++ } else {
++ target_pdev = of_find_device_by_node(target_node);
++ if (target_pdev != NULL) {
++ dev_info(&pdev->dev, "Cannot find platform_device yet\n");
++ ret = -ENODEV;
++ goto err_fail;
++ }
++ platform_device_unregister(target_pdev);
++ platform_device_put(target_pdev);
++ }
++
++ frag->status_changed = 1;
++ frag->status_new = new_status;
++
++ }
++
++ list_add_tail(&frag->node, &priv->frag_list);
++ }
++
++ dev_info(&pdev->dev, "Completed.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++
++err_fail:
++ of_node_put(target_node);
++ devm_kfree(&pdev->dev, frag);
++
++ /* remove all in reverse */
++ list_for_each_prev_safe(lh, lhp, &priv->frag_list) {
++ frag = list_entry(lh, struct dt_fragment, node);
++ list_del(lh);
++
++ /* TODO: remove overlay */
++
++ of_node_put(frag->target_node);
++ devm_kfree(&pdev->dev, frag);
++ }
++ return ret;
++}
++
++static int __devexit dt_overlay_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver dt_overlay_driver = {
++ .probe = dt_overlay_probe,
++ .remove = __devexit_p(dt_overlay_remove),
++ .driver = {
++ .name = "dt-overlay",
++ .owner = THIS_MODULE,
++ .of_match_table = of_dt_overlay_match,
++ },
++};
++
+ /*
+ *
+ */
+@@ -263,6 +649,9 @@ static struct bone_capebus_pdev_driver pdev_drivers[] = {
+ .driver = &spi_dt_driver,
+ },
+ {
++ .driver = &dt_overlay_driver,
++ },
++ {
+ .driver = NULL,
+ }
+ };
diff --git a/patches/linux-3.7/0167-Bug-fixes-pinctl-gpio-reset.patch b/patches/linux-3.7/0167-Bug-fixes-pinctl-gpio-reset.patch
new file mode 100644
index 0000000..826e5a7
--- /dev/null
+++ b/patches/linux-3.7/0167-Bug-fixes-pinctl-gpio-reset.patch
@@ -0,0 +1,138 @@
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:33 +0200
+Subject: [PATCH] Bug fixes, pinctl & gpio-reset
+
+---
+ arch/arm/plat-omap/include/plat/mmc.h | 3 +++
+ drivers/mmc/host/omap_hsmmc.c | 41 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 43 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
+index 346af5b..594fc12 100644
+--- a/arch/arm/plat-omap/include/plat/mmc.h
++++ b/arch/arm/plat-omap/include/plat/mmc.h
+@@ -131,6 +131,9 @@ struct omap_mmc_platform_data {
+
+ int switch_pin; /* gpio (card detect) */
+ int gpio_wp; /* gpio (write protect) */
++ int gpio_reset; /* gpio (reset) */
++ int gpio_reset_active_low; /* 1 if reset is active low */
++ u32 gpio_reset_hold_us; /* time to hold in us */
+
+ int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
+ int (*set_power)(struct device *dev, int slot,
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 7a1283c..8a15610 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -38,6 +38,8 @@
+ #include <linux/gpio.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+ #include <mach/hardware.h>
+ #include <plat/mmc.h>
+ #include <plat/cpu.h>
+@@ -383,6 +385,7 @@ static inline int omap_hsmmc_have_reg(void)
+ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ {
+ int ret;
++ unsigned long flags;
+
+ if (gpio_is_valid(pdata->slots[0].switch_pin)) {
+ if (pdata->slots[0].cover)
+@@ -412,6 +415,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ } else
+ pdata->slots[0].gpio_wp = -EINVAL;
+
++ if (gpio_is_valid(pdata->slots[0].gpio_reset)) {
++ flags = pdata->slots[0].gpio_reset_active_low ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
++ "mmc_reset");
++ if (ret)
++ goto err_free_wp;
++
++ /* hold reset */
++ udelay(pdata->slots[0].gpio_reset_hold_us);
++
++ gpio_set_value(pdata->slots[0].gpio_reset,
++ !pdata->slots[0].gpio_reset_active_low);
++
++ } else
++ pdata->slots[0].gpio_reset = -EINVAL;
++
++
+ return 0;
+
+ err_free_wp:
+@@ -425,6 +446,8 @@ err_free_sp:
+
+ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
+ {
++ if (gpio_is_valid(pdata->slots[0].gpio_reset))
++ gpio_free(pdata->slots[0].gpio_reset);
+ if (gpio_is_valid(pdata->slots[0].gpio_wp))
+ gpio_free(pdata->slots[0].gpio_wp);
+ if (gpio_is_valid(pdata->slots[0].switch_pin))
+@@ -779,7 +802,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
+ * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
+ * a val of 0x3, rest 0x0.
+ */
+- if (cmd == host->mrq->stop)
++ if (host->mrq && cmd == host->mrq->stop)
+ cmdtype = 0x3;
+
+ cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
+@@ -821,6 +844,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
+ int dma_ch;
+ unsigned long flags;
+
++ BUG_ON(mrq == NULL);
++
+ spin_lock_irqsave(&host->irq_lock, flags);
+ host->req_in_progress = 0;
+ dma_ch = host->dma_ch;
+@@ -1704,6 +1729,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ struct omap_mmc_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ u32 bus_width;
++ enum of_gpio_flags reset_flags;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+@@ -1716,6 +1742,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ pdata->nr_slots = 1;
+ pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
+ pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
++ reset_flags = 0;
++ pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np,
++ "reset-gpios", 0, &reset_flags);
++ pdata->slots[0].gpio_reset_active_low =
++ (reset_flags & OF_GPIO_ACTIVE_LOW) != 0;
++ pdata->slots[0].gpio_reset_hold_us = 100; /* default */
++ of_property_read_u32(np, "reset-gpio-hold-us",
++ &pdata->slots[0].gpio_reset_hold_us);
+
+ if (of_find_property(np, "ti,non-removable", NULL)) {
+ pdata->slots[0].nonremovable = true;
+@@ -1753,6 +1787,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ const struct of_device_id *match;
+ dma_cap_mask_t mask;
+ unsigned tx_req, rx_req;
++ struct pinctrl *pinctrl;
+
+ match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
+ if (match) {
+@@ -1773,6 +1808,10 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ return -ENXIO;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (res == NULL || irq < 0)
diff --git a/patches/linux-3.7/0168-ARM-HSMMC-fix-error-path-when-no-gpio_reset.patch b/patches/linux-3.7/0168-ARM-HSMMC-fix-error-path-when-no-gpio_reset.patch
new file mode 100644
index 0000000..6ba5f1a
--- /dev/null
+++ b/patches/linux-3.7/0168-ARM-HSMMC-fix-error-path-when-no-gpio_reset.patch
@@ -0,0 +1,35 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Wed, 5 Dec 2012 11:12:21 -0600
+Subject: [PATCH] ARM: HSMMC: fix error path when no gpio_reset
+
+fixes: https://github.com/beagleboard/kernel/issues/12
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 8a15610..ec73df7 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -421,7 +421,7 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
+ "mmc_reset");
+ if (ret)
+- goto err_free_wp;
++ goto err_free_reset;
+
+ /* hold reset */
+ udelay(pdata->slots[0].gpio_reset_hold_us);
+@@ -442,6 +442,10 @@ err_free_cd:
+ err_free_sp:
+ gpio_free(pdata->slots[0].switch_pin);
+ return ret;
++err_free_reset:
++ gpio_free(pdata->slots[0].gpio_reset);
++ pdata->slots[0].gpio_reset = -EINVAL;
++ return 0;
+ }
+
+ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
diff --git a/patches/linux-3.7/0169-capebus-Add-PRUSS-DT-bindings.patch b/patches/linux-3.7/0169-capebus-Add-PRUSS-DT-bindings.patch
new file mode 100644
index 0000000..ad6705f
--- /dev/null
+++ b/patches/linux-3.7/0169-capebus-Add-PRUSS-DT-bindings.patch
@@ -0,0 +1,135 @@
+From: Matt Ranostay <mranostay@gmail.com>
+Date: Thu, 6 Dec 2012 20:59:14 -0800
+Subject: [PATCH] capebus: Add PRUSS DT bindings
+
+Allow capebus to enable using the PRU cores
+
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ drivers/capebus/boards/capebus-bone-generic.c | 6 ++
+ drivers/capebus/boards/capebus-bone-pdevs.c | 88 +++++++++++++++++++++++++
+ 2 files changed, 94 insertions(+)
+
+diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
+index 8c2c6cc..af6d4a3 100644
+--- a/drivers/capebus/boards/capebus-bone-generic.c
++++ b/drivers/capebus/boards/capebus-bone-generic.c
+@@ -142,6 +142,12 @@ static const struct bone_capebus_generic_device_data gendevs[] = {
+ },
+ .units = 0, /* no limit */
+ }, {
++ .name = "pruss-dt",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "pruss-dt", }, { },
++ },
++ .units = 0, /* no limit */
++ }, {
+ .name = "dt-overlay",
+ .of_match = (const struct of_device_id []) {
+ { .compatible = "dt-overlay", }, { },
+diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
+index f97100b..3eaca93 100644
+--- a/drivers/capebus/boards/capebus-bone-pdevs.c
++++ b/drivers/capebus/boards/capebus-bone-pdevs.c
+@@ -250,6 +250,91 @@ static struct platform_driver spi_dt_driver = {
+
+ /*******************************************************************/
+
++struct pruss_priv {
++ phandle parent_handle;
++};
++
++static const struct of_device_id of_pruss_dt_match[] = {
++ { .compatible = "pruss-dt", },
++ {},
++};
++
++static int __devinit pruss_dt_probe(struct platform_device *pdev)
++{
++ struct pruss_priv *priv = NULL;
++ int ret = -EINVAL;
++ struct device_node *master_node;
++ u32 val;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++
++ ret = of_property_read_u32(pdev->dev.of_node, "parent", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find parent property\n");
++ goto err_prop_fail;
++ }
++ priv->parent_handle = val;
++
++ master_node = of_find_node_by_phandle(priv->parent_handle);
++ if (master_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find PRUSS node\n");
++ ret = -EINVAL;
++ goto err_node_fail;
++ }
++
++ ret = capebus_of_platform_device_enable(master_node);
++ if (ret != 0) {
++ dev_info(&pdev->dev, "PRUSS platform device failed to enable\n");
++ goto err_enable_fail;
++ }
++
++ of_node_put(master_node);
++
++ dev_info(&pdev->dev, "Registered bone PRUSS OK.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++
++err_enable_fail:
++ /* nothing */
++err_node_fail:
++ /* nothing */
++err_prop_fail:
++ devm_kfree(&pdev->dev, priv);
++ return ret;
++}
++
++static int __devexit pruss_dt_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver pruss_dt_driver = {
++ .probe = pruss_dt_probe,
++ .remove = __devexit_p(pruss_dt_remove),
++ .driver = {
++ .name = "pruss-dt",
++ .owner = THIS_MODULE,
++ .of_match_table = of_pruss_dt_match,
++ },
++};
++
++/*******************************************************************/
++
++
++
++
++
+ static int of_is_printable_string(const void *data, int len)
+ {
+ const char *s = data;
+@@ -649,6 +734,9 @@ static struct bone_capebus_pdev_driver pdev_drivers[] = {
+ .driver = &spi_dt_driver,
+ },
+ {
++ .driver = &pruss_dt_driver,
++ },
++ {
+ .driver = &dt_overlay_driver,
+ },
+ {
diff --git a/patches/linux-3.7/0171-Import-working-HDMI-driver-from-3.2-kernel.patch b/patches/linux-3.7/0171-Import-working-HDMI-driver-from-3.2-kernel.patch
new file mode 100644
index 0000000..9bb80a1
--- /dev/null
+++ b/patches/linux-3.7/0171-Import-working-HDMI-driver-from-3.2-kernel.patch
@@ -0,0 +1,72647 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Tue, 13 Nov 2012 11:41:09 -0500
+Subject: [PATCH] Import working HDMI driver from 3.2 kernel
+
+Fixes ontop of the original driver:
+6a3b828 hdmi: Fix Video port mapping in NXP driver
+ac8ac07 Replace entire code with version recommended by NXP, add late_initcall to tda988x.c
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/nxp/MakeModules | 59 +
+ drivers/video/nxp/Makefile | 204 +
+ .../nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h | 1804 +++++
+ .../tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h | 141 +
+ .../tmbslTDA9989/inc/tmbslTDA9989_Functions.h | 3060 ++++++++
+ .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c | 1572 ++++
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h | 62 +
+ .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c | 655 ++
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h | 72 +
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c | 5101 +++++++++++++
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h | 112 +
+ .../nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c | 2512 +++++++
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h | 62 +
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_State.c | 240 +
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h | 56 +
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_local.c | 670 ++
+ .../comps/tmbslTDA9989/src/tmbslTDA9989_local.h | 2056 ++++++
+ .../tmbslTDA9989/src/tmbslTDA9989_local_otp.h | 54 +
+ .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h | 305 +
+ .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c | 436 ++
+ .../nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h | 107 +
+ .../docs/02_sw_req_an/tmdlHdmiCEC_API.zip | Bin 0 -> 148480 bytes
+ .../docs/14_user_doc/HDMI_CEC_User_Manual.pdf | Bin 0 -> 171295 bytes
+ .../video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h | 46 +
+ .../comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h | 3166 ++++++++
+ .../nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h | 1083 +++
+ .../video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c | 7575 ++++++++++++++++++++
+ .../nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c | 280 +
+ .../nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h | 221 +
+ .../tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c | 570 ++
+ .../comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c | 624 ++
+ .../video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h | 290 +
+ .../nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h | 298 +
+ .../docs/02_sw_req_an/tmdlHdmiTx_API.zip | Bin 0 -> 131083 bytes
+ .../TRANSMITTER_TDA998X_SW_UM_Devlib.pdf | Bin 0 -> 610544 bytes
+ .../video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h | 52 +
+ .../comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h | 1806 +++++
+ .../nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h | 1066 +++
+ .../video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c | 7166 ++++++++++++++++++
+ .../nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c | 342 +
+ .../nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h | 702 ++
+ drivers/video/nxp/inc/tmFlags.h | 237 +
+ drivers/video/nxp/inc/tmNxCompId.h | 1743 +++++
+ drivers/video/nxp/inc/tmNxTypes.h | 366 +
+ drivers/video/nxp/linux_hdmi_release_note.txt | 417 ++
+ drivers/video/nxp/tda998x.c | 2307 ++++++
+ drivers/video/nxp/tda998x.h | 143 +
+ drivers/video/nxp/tda998x_cec.c | 2157 ++++++
+ drivers/video/nxp/tda998x_cec.h | 140 +
+ drivers/video/nxp/tda998x_ioctl.h | 1123 +++
+ drivers/video/nxp/tda998x_version.h | 17 +
+ drivers/video/nxp/test/Makefile | 28 +
+ drivers/video/nxp/test/demo_tda.c | 758 ++
+ 53 files changed, 54063 insertions(+)
+ create mode 100755 drivers/video/nxp/MakeModules
+ create mode 100755 drivers/video/nxp/Makefile
+ create mode 100755 drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h
+ create mode 100755 drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/docs/14_user_doc/HDMI_CEC_User_Manual.pdf
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c
+ create mode 100755 drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h
+ create mode 100755 drivers/video/nxp/inc/tmFlags.h
+ create mode 100755 drivers/video/nxp/inc/tmNxCompId.h
+ create mode 100755 drivers/video/nxp/inc/tmNxTypes.h
+ create mode 100755 drivers/video/nxp/linux_hdmi_release_note.txt
+ create mode 100755 drivers/video/nxp/tda998x.c
+ create mode 100755 drivers/video/nxp/tda998x.h
+ create mode 100755 drivers/video/nxp/tda998x_cec.c
+ create mode 100755 drivers/video/nxp/tda998x_cec.h
+ create mode 100755 drivers/video/nxp/tda998x_ioctl.h
+ create mode 100755 drivers/video/nxp/tda998x_version.h
+ create mode 100755 drivers/video/nxp/test/Makefile
+ create mode 100755 drivers/video/nxp/test/demo_tda.c
+
+diff --git a/drivers/video/nxp/MakeModules b/drivers/video/nxp/MakeModules
+new file mode 100755
+index 0000000..fae8495
+--- /dev/null
++++ b/drivers/video/nxp/MakeModules
+@@ -0,0 +1,59 @@
++PACKAGE_NAME:=hdmi
++
++RULES:=compile
++
++ARCH:=arm
++CROSS_COMPILE:=/home/joel/oe-arm-angstrom-linux-gnueabi-
++VARS:= ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)
++# VARS:= V=1 ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)
++
++# module to be put in driver/video/hdmi
++
++LINUX_DIR=/home/joel/work/code/kernel/linux-dvi-audio/git/
++LINUXKERNEL_SRC=$(LINUX_DIR)
++
++all: $(RULES)
++
++compile:
++ @echo "\t-----> $(PACKAGE_NAME):$@"
++# @rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*
++# @mv tda998x_version.h temp && cat temp | awk '$$2~"PATCHLEVEL" {$$3=$$3+1};{print};' >tda998x_version.h && rm temp
++ $(MAKE) -C $(LINUXKERNEL_SRC) M=`pwd` $(VARS) modules
++# @touch $@
++
++uptx:
++ adb shell hdmi_off
++ adb shell rm hdmitx.ko
++ adb shell rmmod hdmitx
++ adb push hdmitx.ko hdmitx.ko
++ adb shell insmod hdmitx.ko verbose=1
++ adb shell hdmi_on
++
++upcec:
++ adb shell rm hdmicec.ko
++ adb shell rmmod hdmicec
++ adb push hdmicec.ko hdmicec.ko
++ adb shell insmod hdmicec.ko verbose=1 device=4
++
++strip:
++ strip -g -I elf32-little hdmitx.ko -o hdmitx_striped.ko
++ strip -g -I elf32-little hdmicec.ko -o hdmicec_striped.ko
++
++clean:
++ @echo "\t-----> $(PACKAGE_NAME):$@"
++ @rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.* *.symvers *.order
++ @if [ -e comps/tmdlHdmiTx/src ]; then cd comps/tmdlHdmiTx/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmdlHdmiTx/cfg/TDA9989 ]; then cd comps/tmdlHdmiTx/cfg/TDA9989 && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmdlHdmiCEC/src ]; then cd comps/tmdlHdmiCEC/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmdlHdmiCEC/cfg ]; then cd comps/tmdlHdmiCEC/cfg && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmdlTDA9983/src ]; then cd comps/tmdlTDA9983/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmdlTDA9983/cfg ]; then cd comps/tmdlTDA9983/cfg && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmbslTDA9989/src ]; then cd comps/tmbslTDA9989/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmbslTDA9984NoHdcp/src ]; then cd comps/tmbslTDA9984NoHdcp/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++ @if [ -e comps/tmbslTDA9983/src ]; then cd comps/tmbslTDA9983/src && rm -rf *.o *.ko *.mod.c .*.cmd .tmp_versions *.c.* *.h.*; fi
++
++ @if [ -e .compiled ]; then rm .compiled; fi
++
++# install: .install
++# .install:
++# cp ....
+diff --git a/drivers/video/nxp/Makefile b/drivers/video/nxp/Makefile
+new file mode 100755
+index 0000000..f583226
+--- /dev/null
++++ b/drivers/video/nxp/Makefile
+@@ -0,0 +1,204 @@
++
++############### select your chip + platform here ###################
++
++# TDA_TX := TDA19989
++TDA_TX := TDA19988
++# TDA_TX := TDA9984
++# TDA_TX := TDA9983
++# TDA_TX := TDA9981
++
++TDA_PLATFORM := ZOOMII
++# TDA_PLATFORM := OTHERS
++
++############### features on demand #################################
++
++#TDA_HDCP := 0
++TDA_HDCP := TMFL_HDCP_SUPPORT
++TDA_CEC := TDA9950
++
++# add this if INTERRUPT is wired, otherwise polling with timer is used
++#EXTRA_CFLAGS += -DIRQ
++
++# add this to get PC video format
++# EXTRA_CFLAGS += -DFORMAT_PC
++
++# add this to disable automatic set of input/output video resolution
++# EXTRA_CFLAGS += -DUSER_SET_INPUT_OUTPUT
++
++####################################################################
++
++EXTRA_CFLAGS += -DFUNC_PTR=" " -DCONST_DAT="const " -DRAM_DAT=" "
++EXTRA_CFLAGS += -DTDA_NAME=$(TDA_TX)
++EXTRA_CFLAGS += -DTMFL_LINUX_OS_KERNEL_DRIVER
++EXTRA_CFLAGS += -DTMFL_NO_RTOS
++# EXTRA_CFLAGS += -DI2C_DBG
++
++ifeq ($(TDA_PLATFORM),ZOOMII)
++EXTRA_CFLAGS += -DTMFL_CFG_ZOOMII
++EXTRA_CFLAGS += -DZOOMII_PATCH
++EXTRA_CFLAGS += -DTWL4030_HACK
++# EXTRA_CFLAGS += -DANDROID_DSS
++EXTRA_CFLAGS += -DGUI_OVER_HDMI
++endif
++
++ifeq ($(TDA_TX),TDA19988)
++EXTRA_CFLAGS += -DTMFL_TDA19988
++TDA_TX := TDA19989
++endif
++
++ifeq ($(TDA_TX),TDA19989)
++EXTRA_CFLAGS += -DTMFL_TDA19989 -DTMFL_TDA9989
++ifeq ($(TDA_HDCP),TMFL_HDCP_SUPPORT)
++EXTRA_CFLAGS += -D$(TDA_HDCP)
++else
++EXTRA_CFLAGS += -DNO_HDCP
++endif
++endif
++
++ifeq ($(TDA_TX),TDA9984)
++EXTRA_CFLAGS += -DNO_HDCP
++endif
++
++ifeq ($(TDA_TX),TDA9981)
++EXTRA_CFLAGS += -DTMFL_TDA9981_SUPPORT -DTMFL_RX_SENSE_ON
++endif
++
++########## devlib ##################################################
++
++ifeq ($(TDA_TX),TDA19989)
++TXSRC := comps/tmdlHdmiTx/src
++TXCFG := comps/tmdlHdmiTx/cfg/TDA9989
++CECSRC := comps/tmdlHdmiCEC/src
++CECCFG := comps/tmdlHdmiCEC/cfg
++endif
++
++ifeq ($(TDA_TX),TDA9984)
++TXSRC := comps/tmdlHdmiTx/src
++TXCFG := comps/tmdlHdmiTx/cfg/TDA9989
++endif
++
++ifeq ($(TDA_TX),TDA9983)
++TXSRC := comps/tmdlTDA9983/src
++TXCFG := comps/tmdlTDA9983/cfg
++endif
++
++ifeq ($(TDA_TX),TDA9981)
++TXSRC := comps/tmdlTDA9983/src
++TXCFG := comps/tmdlTDA9983/cfg
++endif
++
++########## board service layer #####################################
++
++ifeq ($(TDA_TX),TDA19989)
++BSL := comps/tmbslTDA9989/src
++endif
++
++ifeq ($(TDA_TX),TDA9984)
++BSL := comps/tmbslTDA9984NoHdcp/src
++endif
++
++ifeq ($(TDA_TX),TDA9983)
++BSL := comps/tmbslTDA9983/src
++endif
++
++ifeq ($(TDA_TX),TDA9981)
++BSL := comps/tmbslTDA9983/src
++endif
++
++####################################################################
++
++obj-y += hdmitx.o
++ifeq ($(TDA_CEC),TDA9950)
++obj-m += hdmicec.o
++endif
++
++# Linux module
++hdmitx-objs := tda998x.o
++hdmicec-objs := tda998x_cec.o
++
++# NXP comps
++ifeq ($(TDA_TX),TDA19989)
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx_local.o
++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_cfg.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_local.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_InOut.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_HDCP.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_State.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_Misc.o
++hdmitx-objs += $(BSL)/tmbslTDA9989_Edid.o
++hdmicec-objs += $(CECSRC)/tmdlHdmiCEC.o
++hdmicec-objs += $(CECSRC)/tmdlHdmiCEC_local.o
++hdmicec-objs += $(CECCFG)/tmdlHdmiCEC_Linux.o
++endif
++
++ifeq ($(TDA_TX),TDA9984)
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx_local.o
++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_local.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_InOut.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_HDCP.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_State.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_Misc.o
++hdmitx-objs += $(BSL)/tmbslTDA9984_Edid.o
++endif
++
++ifeq ($(TDA_TX),TDA9983)
++hdmitx-objs += $(BSL)/tmbslHdmiTx_2.o
++hdmitx-objs += $(BSL)/tmbslHdmiTx_1.o
++hdmitx-objs += $(BSL)/tmbslHdmiTx_local.o
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o
++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o
++endif
++
++ifeq ($(TDA_TX),TDA9981)
++hdmitx-objs += $(BSL)/tmbslHdmiTx_2.o
++hdmitx-objs += $(BSL)/tmbslHdmiTx_1.o
++hdmitx-objs += $(BSL)/tmbslHdmiTx_local.o
++hdmitx-objs += $(TXSRC)/tmdlHdmiTx.o
++hdmitx-objs += $(TXCFG)/tmdlHdmiTx_Linux.o
++endif
++
++####################################################################
++
++EXTRA_CFLAGS += -I$(obj)
++EXTRA_CFLAGS += -I$(obj)/inc
++
++ifeq ($(TDA_TX),TDA19989)
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslHdmiTx/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/cfg
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9989/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9989/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiCEC/cfg
++endif
++
++ifeq ($(TDA_TX),TDA9984)
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslHdmiTx/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/cfg
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlHdmiTx/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9984NoHdcp/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9984NoHdcp/src
++endif
++
++ifeq ($(TDA_TX),TDA9983)
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9983/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/cfg
++endif
++
++ifeq ($(TDA_TX),TDA9981)
++EXTRA_CFLAGS += -I$(obj)/comps/tmbslTDA9983/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/inc
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/src
++EXTRA_CFLAGS += -I$(obj)/comps/tmdlTDA9983/cfg
++endif
++
++
++
+diff --git a/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h b/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h
+new file mode 100755
+index 0000000..6827b24
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslHdmiTx/inc/tmbslHdmiTx_types.h
+@@ -0,0 +1,1804 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslHdmiTx_types.h
++ *
++ * \version $Revision: 18 $
++ *
++ * \date $Date: 17/03/08 $
++ *
++ * \brief HDMI Transmitter common types
++ *
++ * \section refs Reference Documents
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmbslHdmiTx_types.h $
++ *
++ *
++ * **************** Version 18 ******************
++ * User: G.Burnouf Date: 01/04/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1468 : add new function tmbslTDA9984GetSinkCategory
++ *
++ *
++ * **************** Version 17 ******************
++ * User: G.Burnouf Date: 17/03/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1430 : Increase size of table for
++ * Short Audio Descriptor
++ *
++ * **************** Version 16 ******************
++ * User: G.Burnouf Date: 06/03/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1406 : new reset audio fifo sequence
++ *
++ * **************** Version 15 ******************
++ * User: G.Burnouf Date: 05/02/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1251 : add new type for function
++ * tmbslTDA9984EdidGetBasicDisplayParam
++ *
++ ****************** Version 14 ******************
++ * User: G.Burnouf Date: 14/01/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR580 - Change BSL error base address
++ *
++ ****************** Version 13 ******************
++ * User: G.Burnouf Date: 10/01/08
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR606 - Apply audio port config in function
++ * of audio format
++ *
++ * **************** Version 12 ******************
++ * User: G.Burnouf Date: 10/12/07 Time: 08:30
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1145 : return DTD and monitor description
++ *
++ * ***************** Version 11 *****************
++ * User: G.Burnouf Date: 04/12/07
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR948 : add new formats, 1080p24/25/30
++ *
++ * ***************** Version 10 *****************
++ * User: C. Diehl Date: 27/11/07
++ * Updated in $/Source/tmbslHdmiTx/inc
++ * PR1030 : - Align with the common interface
++ * reworked for the LIPP4200
++ *
++ * ***************** Version 9 *****************
++ * User: J.Lamotte Date: 23/11/07 Time: 09:35
++ * Updated in $/Source/tmbslHdmiTx/src
++ * PR1078 : - update HDMI_TX_SVD_MAX_CNT from 30
++ * to 113
++ *
++ * ***************** Version 8 *****************
++ * User: G.Burnouf Date: 13/11/07 Time: 09:29
++ * Updated in $/Source/tmbslHdmiTx/src
++ * PR1008 : - update type tmbslHdmiTxHwFeature_t
++ *
++ * ***************** Version 7 *****************
++ * User: G.Burnouf Date: 16/10/07 Time: 14:32
++ * Updated in $/Source/tmbslHdmiTx/src
++ * PR882 : - add type tmbslHdmiTxPowerState_t
++ * - add type tmbslHdmiTxPktGmt_t for gamut
++ * - add new interrupt callback for VS
++ *
++ * ***************** Version 6 *****************
++ * User: G.Burnouf Date: 05/10/07 Time: 14:32
++ * Updated in $/Source/tmbslHdmiTx/src
++ * PR824 : add type for enum _tmbslHdmiTxCallbackInt
++ *
++ * ***************** Version 5 *****************
++ * User: J.Turpin Date: 13/09/07 Time: 14:32
++ * Updated in $/Source/tmbslHdmiTx/src
++ * PR693 : add black pattern functionality
++ * - add HDMITX_PATTERN_BLACK in
++ * enum tmbslHdmiTxTestPattern_t
++ *
++ * ***************** Version 4 *****************
++ * User: G.Burnouf Date: 06/09/07 Time: 17:22
++ * Updated in $/Source/tmbslTDA9984/Inc
++ * PR656 : - add HBR format
++ * - add format I2s Philips left and right justified
++ *
++ * ***************** Version 3 *****************
++ * User: G. Burnouf Date: 07/08/07 Time: 10:30
++ * Updated in $/Source/tmbslTDA9984/Inc
++ * PR572 - change type name of tmbslTDA9984_ to tmbslHdmiTx_
++ *
++ * ***************** Version 2 *****************
++ * User: B.Vereecke Date: 07/08/07 Time: 10:30
++ * Updated in $/Source/tmbslTDA9984/Inc
++ * PR551 - Add a new Pattern type in tmbslHdmiTxTestPattern_t
++ * it is used for set the bluescreen
++ *
++ * ***************** Version 1 *****************
++ * User: G. Burnouf Date: 05/07/07 Time: 17:00
++ * Updated in $/Source/tmbslTDA9984/Inc
++ * PR 414 : Add new edid management
++ *
++ \endverbatim
++ *
++*/
++
++#ifndef TMBSLHDMITX_TYPES_H
++#define TMBSLHDMITX_TYPES_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxCompId.h"
++
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++/**
++ * The maximum number of supported HDMI Transmitter units
++ */
++#define HDMITX_UNITS_MAX 2
++
++/** \name Errors
++ * The group of error codes returned by all API and internal functions
++ */
++/*@{*/
++/** The base offset for all error codes.
++ * This needs defining as non-zero if this component is integrated with others
++ * and all component error ranges are to be kept separate.
++ */
++#define TMBSL_ERR_HDMI_BASE CID_BSL_HDMITX
++
++/** Define the OK code if not defined already */
++#ifndef TM_OK
++#define TM_OK 0
++#endif
++
++/** SW interface compatibility error */
++#define TMBSL_ERR_HDMI_COMPATIBILITY (TMBSL_ERR_HDMI_BASE + 0x001U)
++
++/** SW major version error */
++#define TMBSL_ERR_HDMI_MAJOR_VERSION (TMBSL_ERR_HDMI_BASE + 0x002U)
++
++/** SW component version error */
++#define TMBSL_ERR_HDMI_COMP_VERSION (TMBSL_ERR_HDMI_BASE + 0x003U)
++
++/** Invalid device unit number */
++#define TMBSL_ERR_HDMI_BAD_UNIT_NUMBER (TMBSL_ERR_HDMI_BASE + 0x005U)
++
++/** Invalid input parameter other than unit number */
++#define TMBSL_ERR_HDMI_BAD_PARAMETER (TMBSL_ERR_HDMI_BASE + 0x009U)
++
++/* Ressource not available */
++#define TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE (TMBSL_ERR_HDMI_BASE + 0x00CU)
++
++/** Inconsistent input parameters */
++#define TMBSL_ERR_HDMI_INCONSISTENT_PARAMS (TMBSL_ERR_HDMI_BASE + 0x010U)
++
++/** Component is not initialized */
++#define TMBSL_ERR_HDMI_NOT_INITIALIZED (TMBSL_ERR_HDMI_BASE + 0x011U)
++
++/** Command not supported for current device */
++#define TMBSL_ERR_HDMI_NOT_SUPPORTED (TMBSL_ERR_HDMI_BASE + 0x013U)
++
++/** Initialization failed */
++#define TMBSL_ERR_HDMI_INIT_FAILED (TMBSL_ERR_HDMI_BASE + 0x014U)
++
++/** Component is busy and cannot do a new operation */
++#define TMBSL_ERR_HDMI_BUSY (TMBSL_ERR_HDMI_BASE + 0x015U)
++
++/** I2C read error */
++#define TMBSL_ERR_HDMI_I2C_READ (TMBSL_ERR_HDMI_BASE + 0x017U)
++
++/** I2C write error */
++#define TMBSL_ERR_HDMI_I2C_WRITE (TMBSL_ERR_HDMI_BASE + 0x018U)
++
++/** Assertion failure */
++#define TMBSL_ERR_HDMI_ASSERTION (TMBSL_ERR_HDMI_BASE + 0x049U)
++
++/** Bad EDID block checksum */
++#define TMBSL_ERR_HDMI_INVALID_STATE (TMBSL_ERR_HDMI_BASE + 0x066U)
++#define TMBSL_ERR_HDMI_INVALID_CHECKSUM TMBSL_ERR_HDMI_INVALID_STATE
++
++/** No connection to HPD pin */
++#define TMBSL_ERR_HDMI_NULL_CONNECTION (TMBSL_ERR_HDMI_BASE + 0x067U)
++
++/** Not allowed in DVI mode */
++#define TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED (TMBSL_ERR_HDMI_BASE + 0x068U)
++
++/** Maximum error code defined */
++#define TMBSL_ERR_HDMI_MAX TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED
++
++/*============================================================================*/
++
++#define HDMITX_ENABLE_VP_TABLE_LEN 3
++#define HDMITX_GROUND_VP_TABLE_LEN 3
++
++/** EDID block size */
++#define EDID_BLOCK_SIZE 128
++
++/** size descriptor block of monitor descriptor */
++#define EDID_MONITOR_DESCRIPTOR_SIZE 13
++
++/*@}*/
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++/**
++* \brief TX IP/IC versions
++*/
++typedef enum
++{
++ BSLHDMITX_UNKNOWN = 0x00, /**< IC/IP is not recognized */
++ BSLHDMITX_TDA9984, /**< IC is a TDA9984 */
++ BSLHDMITX_TDA9989, /**< IC is a TDA9989 (TDA9989N2 64 balls) */
++ BSLHDMITX_TDA9981, /**< IC is a TDA9981 */
++ BSLHDMITX_TDA9983, /**< IC is a TDA9983 */
++ BSLHDMITX_TDA19989, /**< IC is a TDA19989 */
++ BSLHDMITX_TDA19988, /**< ok, u got it, it's a 19988 :p */
++} tmbslHdmiTxVersion_t;
++
++
++/**
++ * \brief System function pointer type, to call user I2C read/write functions
++ * \param slaveAddr The I2C slave address
++ * \param firstRegister The first device register address to read or write
++ * \param lenData Length of data to read or write (i.e. no. of registers)
++ * \param pData Pointer to data to write, or to buffer to receive data
++ * \return The call result:
++ * - TM_OK: the call was successful
++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing
++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading
++ */
++typedef struct _tmbslHdmiTxSysArgs_t
++{
++ UInt8 slaveAddr;
++ UInt8 firstRegister;
++ UInt8 lenData;
++ UInt8 *pData;
++} tmbslHdmiTxSysArgs_t;
++typedef tmErrorCode_t (FUNC_PTR * ptmbslHdmiTxSysFunc_t)
++ (tmbslHdmiTxSysArgs_t *pSysArgs);
++
++/**
++ * \brief System function pointer type, to call user I2C EDID read function
++ * \param segPtrAddr The EDID segment pointer address 0 to 7Fh
++ * \param segPtr The EDID segment pointer 0 to 7Fh
++ * \param dataRegAddr The EDID data register address 0 to 7Fh
++ * \param wordOffset The first word offset 0 to FFh to read
++ * \param lenData Length of data to read (i.e. number of registers),
++ 1 to max starting at wordOffset
++ * \param pData Pointer to buffer to receive lenData data bytes
++ * \return The call result:
++ * - TM_OK: the call was successful
++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing
++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading
++ */
++typedef struct _tmbslHdmiTxSysArgsEdid_t
++{
++ UInt8 segPtrAddr;
++ UInt8 segPtr;
++ UInt8 dataRegAddr;
++ UInt8 wordOffset;
++ UInt8 lenData;
++ UInt8 *pData;
++} tmbslHdmiTxSysArgsEdid_t;
++
++
++/**
++ * \brief EDID function pointer type, to call application EDID read function
++ * \param pSysArgs pointer to the structure containing necessary information to read EDID
++ */
++typedef tmErrorCode_t (FUNC_PTR * ptmbslHdmiTxSysFuncEdid_t)
++ (tmbslHdmiTxSysArgsEdid_t *pSysArgs);
++
++/**
++ * \brief Timer function pointer type, to call an application timer
++ * \param ms delay in milliseconds
++ */
++typedef Void (FUNC_PTR * ptmbslHdmiTxSysFuncTimer_t) (UInt16 ms);
++
++/*============================================================================*/
++/**
++ * \brief Callback function pointer type, to call a user interrupt handler
++ * \param txUnit: The transmitter unit that interrupted, 0 to max
++ */
++typedef Void (FUNC_PTR * ptmbslHdmiTxCallback_t) (tmUnitSelect_t txUnit);
++
++/*============================================================================*/
++/**
++ * EIA/CEA-861B video format type
++ */
++typedef enum
++{
++ HDMITX_VFMT_NULL = 0, /**< Not a valid format... */
++ HDMITX_VFMT_NO_CHANGE = 0, /**< ...or no change required */
++ HDMITX_VFMT_TV_MIN = 1, /**< Lowest valid TV format */
++ HDMITX_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */
++ HDMITX_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */
++ HDMITX_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */
++ HDMITX_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */
++ HDMITX_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */
++ HDMITX_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */
++ HDMITX_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */
++ HDMITX_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */
++ HDMITX_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */
++ HDMITX_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */
++ HDMITX_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */
++ HDMITX_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */
++ HDMITX_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */
++ HDMITX_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */
++ HDMITX_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */
++ HDMITX_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */
++ HDMITX_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */
++ HDMITX_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */
++ HDMITX_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */
++ HDMITX_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */
++ HDMITX_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */
++ HDMITX_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */
++ HDMITX_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */
++ HDMITX_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */
++ HDMITX_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */
++ HDMITX_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */
++ HDMITX_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */
++ HDMITX_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */
++ HDMITX_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */
++ HDMITX_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */
++ HDMITX_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */
++ HDMITX_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */
++
++ HDMITX_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */
++
++ HDMITX_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */
++ HDMITX_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */
++ HDMITX_VFMT_35_2880x480p_60Hz = 35, /**< Format 35 2880 x 480p 60Hz 4:3 */
++ HDMITX_VFMT_36_2880x480p_60Hz = 36, /**< Format 36 2880 x 480p 60Hz 16:9 */
++ HDMITX_VFMT_37_2880x576p_50Hz = 37, /**< Format 37 2880 x 576p 50Hz 4:3 */
++ HDMITX_VFMT_38_2880x576p_50Hz = 38, /**< Format 38 2880 x 576p 50Hz 16:9 */
++
++ HDMITX_VFMT_INDEX_60_1280x720p_24Hz = 39,/**< Index of HDMITX_VFMT_60_1280x720p_24Hz */
++ HDMITX_VFMT_60_1280x720p_24Hz = 60, /**< Format 60 1280 x 720p 23.97/24Hz 16:9 */
++ HDMITX_VFMT_61_1280x720p_25Hz = 61, /**< Format 61 1280 x 720p 25Hz 16:9 */
++ HDMITX_VFMT_62_1280x720p_30Hz = 62, /**< Format 60 1280 x 720p 29.97/30Hz 16:9 */
++
++ HDMITX_VFMT_TV_MAX = 62, /**< Highest valid TV format value */
++ HDMITX_VFMT_TV_NUM = 42, /**< Number of TV formats + null, it is also the Index of PC_MIN */
++
++ HDMITX_VFMT_PC_MIN = 128, /**< Lowest valid PC format */
++ HDMITX_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */
++ HDMITX_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */
++ HDMITX_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */
++ HDMITX_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */
++ HDMITX_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */
++ HDMITX_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */
++ HDMITX_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */
++ HDMITX_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */
++ HDMITX_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */
++ HDMITX_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */
++ HDMITX_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */
++ HDMITX_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */
++ HDMITX_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */
++ HDMITX_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */
++ HDMITX_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */
++ HDMITX_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */
++ HDMITX_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */
++ HDMITX_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */
++ HDMITX_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */
++ HDMITX_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */
++ HDMITX_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */
++ HDMITX_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */
++ HDMITX_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */
++ HDMITX_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */
++ HDMITX_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */
++ HDMITX_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */
++ HDMITX_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */
++ HDMITX_VFMT_PC_MAX = 154, /**< Highest valid PC format */
++ HDMITX_VFMT_PC_NUM = (1+154-128) /**< Number of PC formats */
++} tmbslHdmiTxVidFmt_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984AudioInSetConfig() parameter types
++ */
++/** Audio input formats */
++typedef enum
++{
++ HDMITX_AFMT_SPDIF = 0, /**< SPDIF */
++ HDMITX_AFMT_I2S = 1, /**< I2S */
++ HDMITX_AFMT_OBA = 2, /**< One bit audio / DSD */
++ HDMITX_AFMT_DST = 3, /**< DST */
++ HDMITX_AFMT_HBR = 4, /**< HBR */
++ HDMITX_AFMT_NUM = 5, /**< Number of Audio input format */
++ HDMITX_AFMT_INVALID = 5 /**< Invalid format */
++} tmbslHdmiTxaFmt_t;
++
++/** I2s formats */
++typedef enum
++{
++ HDMITX_I2SFOR_PHILIPS_L = 0, /**< Philips like format */
++ HDMITX_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */
++ HDMITX_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */
++ HDMITX_I2SFOR_INVALID = 4 /**< Invalid format*/
++} tmbslHdmiTxI2sFor_t;
++
++/** DSD clock polarities */
++typedef enum
++{
++ HDMITX_CLKPOLDSD_ACLK = 0, /**< Same as ACLK */
++ HDMITX_CLKPOLDSD_NACLK = 1, /**< Not ACLK, i.e. inverted */
++ HDMITX_CLKPOLDSD_NO_CHANGE = 2, /**< No change */
++ HDMITX_CLKPOLDSD_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxClkPolDsd_t;
++
++/** DSD data swap values */
++typedef enum
++{
++ HDMITX_SWAPDSD_OFF = 0, /**< No swap */
++ HDMITX_SWAPDSD_ON = 1, /**< Swap */
++ HDMITX_SWAPDSD_NO_CHANGE = 2, /**< No change */
++ HDMITX_SWAPDSD_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxSwapDsd_t;
++
++/** DST data transfer rates */
++typedef enum
++{
++ HDMITX_DSTRATE_SINGLE = 0, /**< Single transfer rate */
++ HDMITX_DSTRATE_DOUBLE = 1, /**< Double data rate */
++ HDMITX_DSTRATE_NO_CHANGE = 2, /**< No change */
++ HDMITX_DSTRATE_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxDstRate_t;
++
++/** I2S, SPDIF and DSD channel allocation values */
++enum _tmbslHdmiTxChan
++{
++ HDMITX_CHAN_MIN = 0,
++ HDMITX_CHAN_MAX = 31,
++ HDMITX_CHAN_NO_CHANGE = 32,
++ HDMITX_CHAN_INVALID = 33
++};
++
++/** Audio layout values */
++enum _tmbslHdmiTxLayout
++{
++ HDMITX_LAYOUT_MIN = 0,
++ HDMITX_LAYOUT_MAX = 1,
++ HDMITX_LAYOUT_NO_CHANGE = 2,
++ HDMITX_LAYOUT_INVALID = 3
++};
++
++/** Audio FIFO read latency values */
++enum _tmbslHdmiTxlatency_rd
++{
++ HDMITX_LATENCY_MIN = 0x000,
++ HDMITX_LATENCY_CURRENT = 0x080,
++ HDMITX_LATENCY_MAX = 0x0FF,
++ HDMITX_LATENCY_NO_CHANGE = 0x100,
++ HDMITX_LATENCY_INVALID = 0x101
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984AudioInSetCts() parameter types
++ */
++/** Clock Time Stamp reference source */
++typedef enum
++{
++ HDMITX_CTSREF_ACLK = 0, /**< Clock input pin for I2S */
++ HDMITX_CTSREF_MCLK = 1, /**< Clock input pin for EXTREF */
++ HDMITX_CTSREF_FS64SPDIF = 2, /**< 64xsample rate, for SPDIF */
++ HDMITX_CTSREF_INVALID = 3 /**< Invalid value */
++} tmbslHdmiTxctsRef_t;
++
++/** Audio sample rate kHz indexes */
++typedef enum
++{
++ HDMITX_AFS_32k = 0, /**< 32kHz */
++ HDMITX_AFS_44_1k = 1, /**< 44.1kHz */
++ HDMITX_AFS_48K = 2, /**< 48kHz */
++ HDMITX_AFS_88_2K = 3, /**< 88.2kHz */
++ HDMITX_AFS_96K = 4, /**< 96kHz */
++ HDMITX_AFS_176_4K = 5, /**< 176.4kHz */
++ HDMITX_AFS_192K = 6, /**< 192kHz */
++ HDMITX_AFS_768K = 7, /**< 768kHz */
++ HDMITX_AFS_NOT_INDICATED = 8, /**< Not Indicated (Channel Status) */
++ HDMITX_AFS_INVALID = 8, /**< Invalid */
++ HDMITX_AFS_NUM = 8 /**< # rates */
++} tmbslHdmiTxafs_t;
++
++/** Vertical output frequencies */
++typedef enum
++{
++ HDMITX_VFREQ_24Hz = 0, /**< 24Hz */
++ HDMITX_VFREQ_25Hz = 1, /**< 25Hz */
++ HDMITX_VFREQ_30Hz = 2, /**< 30Hz */
++ HDMITX_VFREQ_50Hz = 3, /**< 50Hz */
++ HDMITX_VFREQ_59Hz = 4, /**< 59.94Hz */
++ HDMITX_VFREQ_60Hz = 5, /**< 60Hz */
++#ifndef FORMAT_PC
++ HDMITX_VFREQ_INVALID = 6, /**< Invalid */
++ HDMITX_VFREQ_NUM = 6 /**< No. of values */
++#else /* FORMAT_PC */
++ HDMITX_VFREQ_70Hz = 6, /**< 70Hz */
++ HDMITX_VFREQ_72Hz = 7, /**< 72Hz */
++ HDMITX_VFREQ_75Hz = 8, /**< 75Hz */
++ HDMITX_VFREQ_85Hz = 9, /**< 85Hz */
++ HDMITX_VFREQ_87Hz = 10, /**< 87Hz */
++ HDMITX_VFREQ_INVALID = 11, /**< Invalid */
++ HDMITX_VFREQ_NUM = 11 /**< No. of values */
++#endif /* FORMAT_PC */
++} tmbslHdmiTxVfreq_t;
++
++/** Clock Time Stamp predivider - scales N */
++typedef enum
++{
++ HDMITX_CTSK1 = 0, /**< k=1 */
++ HDMITX_CTSK2 = 1, /**< k=2 */
++ HDMITX_CTSK3 = 2, /**< k=3 */
++ HDMITX_CTSK4 = 3, /**< k=4 */
++ HDMITX_CTSK8 = 4, /**< k=8 */
++ HDMITX_CTSK_USE_CTSX = 5, /**< Calculate from ctsX factor */
++ HDMITX_CTSK_INVALID = 6 /**< Invalid */
++} tmbslHdmiTxctsK_t;
++
++/** Clock Time Stamp postdivider measured time stamp */
++typedef enum
++{
++ HDMITX_CTSMTS = 0, /**< =mts */
++ HDMITX_CTSMTS2 = 1, /**< =mts%2 */
++ HDMITX_CTSMTS4 = 2, /**< =mts%4 */
++ HDMITX_CTSMTS8 = 3, /**< =mts%8 */
++ HDMITX_CTSMTS_USE_CTSX = 4, /**< Calculate from ctsX factor */
++ HDMITX_CTSMTS_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxctsM_t;
++
++/** Cycle Time Stamp values */
++enum _tmbslHdmiTxCts
++{
++ HDMITX_CTS_AUTO = 0,
++ HDMITX_CTS_MIN = 0x000001
++};
++
++/** Cycle Time Stamp X factors */
++enum _tmbslHdmiTxCtsX
++{
++ HDMITX_CTSX_16 = 0,
++ HDMITX_CTSX_32 = 1,
++ HDMITX_CTSX_48 = 2,
++ HDMITX_CTSX_64 = 3,
++ HDMITX_CTSX_128 = 4,
++ HDMITX_CTSX_NUM = 5,
++ HDMITX_CTSX_UNUSED = 5, /**< CTX value unused when K and Mts used */
++ HDMITX_CTSX_INVALID = 6
++};
++
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984AudioOutSetChanStatus() parameter types
++ */
++
++typedef enum
++{
++ HDMITX_AUDIO_DATA_PCM = 0, /**< Main data field represents linear PCM samples. */
++ HDMITX_AUDIO_DATA_OTHER = 1, /**< Main data field used for purposes other purposes. */
++ HDMITX_AUDIO_DATA_INVALID = 2 /**< Invalid value */
++} tmbslHdmiTxAudioData_t;
++
++/** BYTE 0: Channel Status Format information */
++typedef enum
++{
++ HDMITX_CSFI_PCM_2CHAN_NO_PRE = 0, /**< PCM 2 channels without pre-emphasis */
++ HDMITX_CSFI_PCM_2CHAN_PRE = 1, /**< PCM 2 channels with 50us/15us pre-emphasis */
++ HDMITX_CSFI_PCM_2CHAN_PRE_RSVD1 = 2, /**< PCM Reserved for 2 channels with pre-emphasis */
++ HDMITX_CSFI_PCM_2CHAN_PRE_RSVD2 = 3, /**< PCM Reserved for 2 channels with pre-emphasis */
++ HDMITX_CSFI_NOTPCM_DEFAULT = 4, /**< Non-PCM Default state */
++ HDMITX_CSFI_INVALID = 5 /**< Invalid value */
++} tmbslHdmiTxCSformatInfo_t;
++
++/** BYTE 0: Channel Status Copyright assertion */
++typedef enum
++{
++ HDMITX_CSCOPYRIGHT_PROTECTED = 0, /**< Copyright protected */
++ HDMITX_CSCOPYRIGHT_UNPROTECTED = 1, /**< Not copyright protected */
++ HDMITX_CSCOPYRIGHT_INVALID = 2 /**< Invalid value */
++} tmbslHdmiTxCScopyright_t;
++
++/** BYTE 3: Channel Status Clock Accuracy */
++typedef enum
++{
++ HDMITX_CSCLK_LEVEL_II = 0, /**< Level II */
++ HDMITX_CSCLK_LEVEL_I = 1, /**< Level I */
++ HDMITX_CSCLK_LEVEL_III = 2, /**< Level III */
++ HDMITX_CSCLK_NOT_MATCHED = 3, /**< Not matched to sample freq. */
++ HDMITX_CSCLK_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxCSclkAcc_t;
++
++/** BYTE 4: Channel Status Maximum sample word length */
++typedef enum
++{
++ HDMITX_CSMAX_LENGTH_20 = 0, /**< Max word length is 20 bits */
++ HDMITX_CSMAX_LENGTH_24 = 1, /**< Max word length is 24 bits */
++ HDMITX_CSMAX_INVALID = 2 /**< Invalid value */
++} tmbslHdmiTxCSmaxWordLength_t;
++
++
++/** BYTE 4: Channel Status Sample word length */
++typedef enum
++{
++ HDMITX_CSWORD_DEFAULT = 0, /**< Word length is not indicated */
++ HDMITX_CSWORD_20_OF_24 = 1, /**< Sample length is 20 bits out of max 24 possible */
++ HDMITX_CSWORD_16_OF_20 = 1, /**< Sample length is 16 bits out of max 20 possible */
++ HDMITX_CSWORD_22_OF_24 = 2, /**< Sample length is 22 bits out of max 24 possible */
++ HDMITX_CSWORD_18_OF_20 = 2, /**< Sample length is 18 bits out of max 20 possible */
++ HDMITX_CSWORD_RESVD = 3, /**< Reserved - shall not be used */
++ HDMITX_CSWORD_23_OF_24 = 4, /**< Sample length is 23 bits out of max 24 possible */
++ HDMITX_CSWORD_19_OF_20 = 4, /**< Sample length is 19 bits out of max 20 possible */
++ HDMITX_CSWORD_24_OF_24 = 5, /**< Sample length is 24 bits out of max 24 possible */
++ HDMITX_CSWORD_20_OF_20 = 5, /**< Sample length is 20 bits out of max 20 possible */
++ HDMITX_CSWORD_21_OF_24 = 6, /**< Sample length is 21 bits out of max 24 possible */
++ HDMITX_CSWORD_17_OF_20 = 6, /**< Sample length is 17 bits out of max 20 possible */
++ HDMITX_CSWORD_INVALID = 7 /**< Invalid */
++} tmbslHdmiTxCSwordLength_t;
++
++/** BYTE 4: Channel Status Original sample frequency */
++typedef enum
++{
++ HDMITX_CSOFREQ_NOT_INDICATED = 0, /**< Not Indicated */
++ HDMITX_CSOFREQ_192k = 1, /**< 192kHz */
++ HDMITX_CSOFREQ_12k = 2, /**< 12kHz */
++ HDMITX_CSOFREQ_176_4k = 3, /**< 176.4kHz */
++ HDMITX_CSOFREQ_RSVD1 = 4, /**< Reserved */
++ HDMITX_CSOFREQ_96k = 5, /**< 96kHz */
++ HDMITX_CSOFREQ_8k = 6, /**< 8kHz */
++ HDMITX_CSOFREQ_88_2k = 7, /**< 88.2kHz */
++ HDMITX_CSOFREQ_16k = 8, /**< 16kHz */
++ HDMITX_CSOFREQ_24k = 9, /**< 24kHz */
++ HDMITX_CSOFREQ_11_025k = 10, /**< 11.025kHz */
++ HDMITX_CSOFREQ_22_05k = 11, /**< 22.05kHz */
++ HDMITX_CSOFREQ_32k = 12, /**< 32kHz */
++ HDMITX_CSOFREQ_48k = 13, /**< 48kHz */
++ HDMITX_CSOFREQ_RSVD2 = 14, /**< Reserved */
++ HDMITX_CSOFREQ_44_1k = 15, /**< 44.1kHz */
++ HDMITX_CSAFS_INVALID = 16 /**< Invalid value */
++} tmbslHdmiTxCSorigAfs_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984AudioOutSetChanStatusMapping() parameter types
++ */
++/** Channel Status source/channel number limits */
++enum _tmbslHdmiTxChanStatusChanLimits
++{
++ HDMITX_CS_CHANNELS_MAX = 0x0F,
++ HDMITX_CS_SOURCES_MAX = 0x0F
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984AudioOutSetMute() parameter type
++ */
++/** Audio mute state */
++typedef enum
++{
++ HDMITX_AMUTE_OFF = 0, /**< Mute off */
++ HDMITX_AMUTE_ON = 1, /**< Mute on */
++ HDMITX_AMUTE_INVALID = 2 /**< Invalid */
++} tmbslHdmiTxaMute_t;
++
++/** Number of 3 byte Short Audio Descriptors stored in pEdidAFmts */
++#define HDMI_TX_SAD_MAX_CNT 30
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984EdidGetBlockData() parameter types
++ */
++/** An enum to represent the current EDID status */
++enum _tmbslHdmiTxEdidSta_t
++{
++ HDMITX_EDID_READ = 0, /* All blocks read OK */
++ HDMITX_EDID_READ_INCOMPLETE = 1, /* All blocks read OK but buffer too
++ small to return all of them */
++ HDMITX_EDID_ERROR_CHK_BLOCK_0 = 2, /* Block 0 checksum error */
++
++ HDMITX_EDID_ERROR_CHK = 3, /* Block 0 OK, checksum error in one
++ or more other blocks */
++ HDMITX_EDID_NOT_READ = 4, /* EDID not read */
++
++ HDMITX_EDID_STATUS_INVALID = 5 /**< Invalid */
++
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984EdidGetSinkType() parameter types
++ */
++/** Sink device type */
++typedef enum
++{
++ HDMITX_SINK_DVI = 0, /**< DVI */
++ HDMITX_SINK_HDMI = 1, /**< HDMI */
++ HDMITX_SINK_EDID = 2, /**< As currently defined in EDID */
++ HDMITX_SINK_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxSinkType_t;
++
++/*============================================================================*/
++/**
++ * \brief The tmbslTDA9984EdidGetVideoPreferred() parameter type
++ * Detailed timining description structure
++ */
++typedef struct _tmbslHdmiTxEdidDtd_t
++{
++ UInt16 uPixelClock; /**< Pixel Clock/10,000 */
++ UInt16 uHActivePixels; /**< Horizontal Active Pixels */
++ UInt16 uHBlankPixels; /**< Horizontal Blanking Pixels */
++ UInt16 uVActiveLines; /**< Vertical Active Lines */
++ UInt16 uVBlankLines; /**< Vertical Blanking Lines */
++ UInt16 uHSyncOffset; /**< Horizontal Sync Offset */
++ UInt16 uHSyncWidth; /**< Horiz. Sync Pulse Width */
++ UInt16 uVSyncOffset; /**< Vertical Sync Offset */
++ UInt16 uVSyncWidth; /**< Vertical Sync Pulse Width */
++ UInt16 uHImageSize; /**< Horizontal Image Size */
++ UInt16 uVImageSize; /**< Vertical Image Size */
++ UInt16 uHBorderPixels; /**< Horizontal Border */
++ UInt16 uVBorderPixels; /**< Vertical Border */
++ UInt8 Flags; /**< Interlace/sync info */
++} tmbslHdmiTxEdidDtd_t;
++
++
++/*============================================================================*/
++/**
++ * First monitor descriptor structure
++ */
++typedef struct _tmbslHdmiTxEdidFirstMD_t
++{
++ Bool bDescRecord; /**< True when parameters of struct are available */
++ UInt8 uMonitorName[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Monitor Name */
++} tmbslHdmiTxEdidFirstMD_t;
++
++/*============================================================================*/
++/**
++ * Second monitor descriptor structure
++ */
++typedef struct _tmbslHdmiTxEdidSecondMD_t
++{
++ Bool bDescRecord; /**< True when parameters of struct are available */
++ UInt8 uMinVerticalRate; /**< Min vertical rate in Hz */
++ UInt8 uMaxVerticalRate; /**< Max vertical rate in Hz */
++ UInt8 uMinHorizontalRate; /**< Min horizontal rate in Hz */
++ UInt8 uMaxHorizontalRate; /**< Max horizontal rate in Hz */
++ UInt8 uMaxSupportedPixelClk; /**< Max suuported pixel clock rate in MHz */
++} tmbslHdmiTxEdidSecondMD_t;
++
++/*============================================================================*/
++/**
++ * Other monitor descriptor structure
++ */
++typedef struct _tmbslHdmiTxEdidOtherMD_t
++{
++ Bool bDescRecord; /**< True when parameters of struct are available */
++ UInt8 uOtherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Other monitor Descriptor */
++} tmbslHdmiTxEdidOtherMD_t;
++
++/*============================================================================*/
++/**
++ * basic display parameters structure
++ */
++typedef struct _tmbslHdmiTxEdidBDParam_t
++{
++ UInt8 uVideoInputDef; /**< Video Input Definition */
++ UInt8 uMaxHorizontalSize; /**< Max. Horizontal Image Size in cm */
++ UInt8 uMaxVerticalSize; /**< Max. Vertical Image Size in cm */
++ UInt8 uGamma; /**< Gamma */
++ UInt8 uFeatureSupport; /**< Feature support */
++} tmbslHdmiTxEdidBDParam_t;
++
++/*============================================================================*/
++/**
++ * \brief The tmbslTDA9984EdidGetAudioCapabilities() parameter type
++ */
++typedef struct _tmbslHdmiTxEdidSad_t
++{
++ UInt8 ModeChans; /* Bits[6:3]: EIA/CEA861 mode; Bits[2:0]: channels */
++ UInt8 Freqs; /* Bits for each supported frequency */
++ UInt8 Byte3; /* EIA/CEA861B p83: data depending on audio mode */
++}tmbslHdmiTxEdidSad_t;
++
++/*============================================================================*/
++/**
++ * \brief struc to store parameter provide by function tmbslTDA9984EdidRequestBlockData()
++ */
++typedef struct _tmbslHdmiTxEdidToApp_t
++{
++ UInt8 *pRawEdid; /* pointer on a tab to store edid requested by application */
++ Int numBlocks; /* number of edid block requested by application */
++}tmbslHdmiTxEdidToApp_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984EdidGetVideoCapabilities() parameter types
++ */
++/** Number of 1 byte Short Video Descriptors stored in pEdidVFmts */
++#define HDMI_TX_SVD_MAX_CNT 113
++
++/** number of detailed timing descriptor stored in BSL */
++#define NUMBER_DTD_STORED 10
++
++
++
++/** Flag set in Short Video Descriptor to indicate native format */
++#define HDMI_TX_SVD_NATIVE_MASK 0x80
++#define HDMI_TX_SVD_NATIVE_NOT 0x7F
++
++/** Video capability flags */
++enum _tmbslHdmiTxVidCap_t
++{
++ HDMITX_VIDCAP_UNDERSCAN = 0x80, /**< Underscan supported */
++ HDMITX_VIDCAP_YUV444 = 0x40, /**< YCbCr 4:4:4 supported */
++ HDMITX_VIDCAP_YUV422 = 0x20, /**< YCbCr 4:2:2 supported */
++ HDMITX_VIDCAP_UNUSED = 0x1F /**< Unused flags */
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HdcpCheck() parameter type
++ */
++/** HDCP check result */
++typedef enum
++{
++ HDMITX_HDCP_CHECK_NOT_STARTED = 0, /**< Check not started */
++ HDMITX_HDCP_CHECK_IN_PROGRESS = 1, /**< No failures, more to do */
++ HDMITX_HDCP_CHECK_PASS = 2, /**< Final check has passed */
++ HDMITX_HDCP_CHECK_FAIL_FIRST = 3, /**< First check failure code */
++ HDMITX_HDCP_CHECK_FAIL_DRIVER_STATE = 3, /**< Driver not AUTHENTICATED */
++ HDMITX_HDCP_CHECK_FAIL_DEVICE_T0 = 4, /**< A T0 interrupt occurred */
++ HDMITX_HDCP_CHECK_FAIL_DEVICE_RI = 5, /**< Device RI changed */
++ HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM = 6, /**< Device FSM not 10h */
++ HDMITX_HDCP_CHECK_NUM = 7 /**< Number of check results */
++}tmbslHdmiTxHdcpCheck_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HdcpConfigure() parameter type
++ */
++/** HDCP DDC slave addresses */
++enum _tmbslHdmiTxHdcpSlaveAddress
++{
++ HDMITX_HDCP_SLAVE_PRIMARY = 0x74,
++ HDMITX_HDCP_SLAVE_SECONDARY = 0x76
++};
++
++/** HDCP transmitter modes */
++typedef enum
++{
++ HDMITX_HDCP_TXMODE_NOT_SET = 0,
++ HDMITX_HDCP_TXMODE_REPEATER = 1,
++ HDMITX_HDCP_TXMODE_TOP_LEVEL = 2,
++ HDMITX_HDCP_TXMODE_MAX = 2
++}tmbslHdmiTxHdcpTxMode_t;
++
++/** HDCP option flags */
++typedef enum
++{
++ HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED = 0x01,/* Not set: obey PJ result */
++ HDMITX_HDCP_OPTION_FORCE_SLOW_DDC = 0x02,/* Not set: obey BCAPS setting */
++ HDMITX_HDCP_OPTION_FORCE_NO_1_1 = 0x04,/* Not set: obey BCAPS setting */
++ HDMITX_HDCP_OPTION_FORCE_REPEATER = 0x08,/* Not set: obey BCAPS setting */
++ HDMITX_HDCP_OPTION_FORCE_NO_REPEATER= 0x10,/* Not set: obey BCAPS setting */
++ HDMITX_HDCP_OPTION_FORCE_V_EQU_VBAR = 0x20,/* Not set: obey V=V' result */
++ HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC = 0x40,/* Set: 50kHz DDC */
++ HDMITX_HDCP_OPTION_DEFAULT = 0x00,/* All the above Not Set vals */
++ HDMITX_HDCP_OPTION_MASK = 0x7F,/* Only these bits are allowed */
++ HDMITX_HDCP_OPTION_MASK_BAD = 0x80 /* These bits are not allowed */
++}tmbslHdmiTxHdcpOptions_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HdcpDownloadKeys() parameter type
++ */
++/** HDCP decryption mode */
++typedef enum
++{
++ HDMITX_HDCP_DECRYPT_DISABLE = 0,
++ HDMITX_HDCP_DECRYPT_ENABLE = 1,
++ HDMITX_HDCP_DECRYPT_MAX = 1
++}tmbslHdmiTxDecrypt_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HdcpHandleBSTATUS() parameter type
++ */
++/** BSTATUS bit fields */
++enum _tmbslHdmiTxHdcpHandleBSTATUS
++{
++ HDMITX_HDCP_BSTATUS_HDMI_MODE = 0x1000,
++ HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED = 0x0800,
++ HDMITX_HDCP_BSTATUS_CASCADE_DEPTH = 0x0700,
++ HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED = 0x0080,
++ HDMITX_HDCP_BSTATUS_DEVICE_COUNT = 0x007F
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HdcpHandleSHA_1() parameter types
++ */
++/** KSV list sizes */
++enum _tmbslHdmiTxHdcpHandleSHA_1
++{
++ HDMITX_KSV_LIST_MAX_DEVICES = 128,
++ HDMITX_KSV_BYTES_PER_DEVICE = 5
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HotPlugGetStatus() parameter type
++ */
++/** Current hotplug status */
++typedef enum
++{
++ HDMITX_HOTPLUG_INACTIVE = 0, /**< Hotplug inactive */
++ HDMITX_HOTPLUG_ACTIVE = 1, /**< Hotplug active */
++ HDMITX_HOTPLUG_INVALID = 2 /**< Invalid Hotplug */
++} tmbslHdmiTxHotPlug_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984RxSenseGetStatus() parameter type
++ */
++/** Current RX Sense status */
++typedef enum
++{
++ HDMITX_RX_SENSE_INACTIVE = 0, /**< RxSense inactive */
++ HDMITX_RX_SENSE_ACTIVE = 1, /**< RxSense active */
++ HDMITX_RX_SENSE_INVALID = 2 /**< Invalid RxSense */
++} tmbslHdmiTxRxSense_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984HwGetCapabilities() parameter type
++ */
++/** List of HW features that may be supported by HW */
++typedef enum
++{
++ HDMITX_FEATURE_HW_HDCP = 0, /**< HDCP feature */
++ HDMITX_FEATURE_HW_SCALER = 1, /**< Scaler feature */
++ HDMITX_FEATURE_HW_AUDIO_OBA = 2, /**< One Bit Audio feature */
++ HDMITX_FEATURE_HW_AUDIO_DST = 3, /**< DST Audio feature */
++ HDMITX_FEATURE_HW_AUDIO_HBR = 4, /**< HBR Audio feature */
++ HDMITX_FEATURE_HW_HDMI_1_1 = 5, /**< HDMI 1.1 feature */
++ HDMITX_FEATURE_HW_HDMI_1_2A = 6, /**< HDMI 1.2a feature */
++ HDMITX_FEATURE_HW_HDMI_1_3A = 7, /**< HDMI 1.3a feature */
++ HDMITX_FEATURE_HW_DEEP_COLOR_30 = 8, /**< 30 bits deep color support */
++ HDMITX_FEATURE_HW_DEEP_COLOR_36 = 9, /**< 36 bits deep color support */
++ HDMITX_FEATURE_HW_DEEP_COLOR_48 = 11, /**< 48 bits deep color support */
++ HDMITX_FEATURE_HW_UPSAMPLER = 12, /**< Up sampler feature */
++ HDMITX_FEATURE_HW_DOWNSAMPLER = 13, /**< Down sampler feature */
++ HDMITX_FEATURE_HW_COLOR_CONVERSION = 14 /**< Color conversion matrix */
++} tmbslHdmiTxHwFeature_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984Init() parameter types
++ */
++/** Supported range of I2C slave addresses */
++enum _tmbslHdmiTxSlaveAddress
++{
++ HDMITX_SLAVE_ADDRESS_MIN = 1,
++ HDMITX_SLAVE_ADDRESS_MAX = 127
++};
++
++/**
++ * Indexes into the funcCallback[] array of interrupt callback function pointers
++ */
++typedef enum _tmbslHdmiTxCallbackInt
++{
++ HDMITX_CALLBACK_INT_SECURITY = 0, /**< HDCP encryption switched off */
++ HDMITX_CALLBACK_INT_ENCRYPT = 0, /**< HDCP encrypt as above (Obsolete) */
++ HDMITX_CALLBACK_INT_HPD = 1, /**< Transition on HPD input */
++ HDMITX_CALLBACK_INT_T0 = 2, /**< HDCP state machine in state T0 */
++ HDMITX_CALLBACK_INT_BCAPS = 3, /**< BCAPS available */
++ HDMITX_CALLBACK_INT_BSTATUS = 4, /**< BSTATUS available */
++ HDMITX_CALLBACK_INT_SHA_1 = 5, /**< sha-1(ksv,bstatus,m0)=V' */
++ HDMITX_CALLBACK_INT_PJ = 6, /**< pj=pj' check fails */
++ HDMITX_CALLBACK_INT_R0 = 7, /**< R0 interrupt */
++ HDMITX_CALLBACK_INT_SW_INT = 8, /**< SW DEBUG interrupt */
++ HDMITX_CALLBACK_INT_RX_SENSE = 9, /**< RX SENSE interrupt */
++ HDMITX_CALLBACK_INT_EDID_BLK_READ = 10, /**< EDID BLK READ interrupt */
++ HDMITX_CALLBACK_INT_PLL_LOCK = 11, /**< Pll Lock (Serial or Formatter) */
++ HDMITX_CALLBACK_INT_VS_RPT = 12, /**< VS Interrupt for Gamut packets */
++ HDMITX_CALLBACK_INT_NUM = 13 /**< Number of callbacks */
++}tmbslHdmiTxCallbackInt_t;
++
++/** Pixel rate */
++typedef enum
++{
++ HDMITX_PIXRATE_DOUBLE = 0, /**< Double pixel rate */
++ HDMITX_PIXRATE_SINGLE = 1, /**< Single pixel rate */
++ HDMITX_PIXRATE_SINGLE_REPEATED = 2, /**< Single pixel repeated */
++ HDMITX_PIXRATE_NO_CHANGE = 3, /**< No Change */
++ HDMITX_PIXRATE_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxPixRate_t;
++
++/**
++ * \brief The tmbslTDA9984Init() parameter structure
++ */
++typedef struct _tmbslHdmiTxCallbackList_t
++{
++ /** Interrupt callback function pointers (each ptr if null = not used) */
++ ptmbslHdmiTxCallback_t funcCallback[HDMITX_CALLBACK_INT_NUM];
++
++} tmbslHdmiTxCallbackList_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984MatrixSetCoeffs() parameter type
++ */
++/** Parameter structure array size */
++enum _tmbslHdmiTxMatCoeff
++{
++ HDMITX_MAT_COEFF_NUM = 9
++};
++
++
++/** \brief The tmbslTDA9984MatrixSetCoeffs() parameter structure */
++/** Array of coefficients (values -1024 to +1023) */
++typedef struct _tmbslHdmiTxMatCoeff_t
++{
++ /** Array of coefficients (values -1024 to +1023) */
++ Int16 Coeff[HDMITX_MAT_COEFF_NUM];
++} tmbslHdmiTxMatCoeff_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984MatrixSetConversion() parameter type
++ */
++/** Video input mode */
++typedef enum
++{
++ HDMITX_VINMODE_CCIR656 = 0, /**< ccir656 */
++ HDMITX_VINMODE_RGB444 = 1, /**< RGB444 */
++ HDMITX_VINMODE_YUV444 = 2, /**< YUV444 */
++ HDMITX_VINMODE_YUV422 = 3, /**< YUV422 */
++ HDMITX_VINMODE_NO_CHANGE = 4, /**< No change */
++ HDMITX_VINMODE_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxVinMode_t;
++
++/** Video output mode */
++typedef enum
++{
++ HDMITX_VOUTMODE_RGB444 = 0, /**< RGB444 */
++ HDMITX_VOUTMODE_YUV422 = 1, /**< YUV422 */
++ HDMITX_VOUTMODE_YUV444 = 2, /**< YUV444 */
++ HDMITX_VOUTMODE_NO_CHANGE = 3, /**< No change */
++ HDMITX_VOUTMODE_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxVoutMode_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984MatrixSetMode() parameter types
++ */
++/** Matrix control values */
++typedef enum
++{
++ HDMITX_MCNTRL_ON = 0, /**< Matrix on */
++ HDMITX_MCNTRL_OFF = 1, /**< Matrix off */
++ HDMITX_MCNTRL_NO_CHANGE = 2, /**< Matrix unchanged */
++ HDMITX_MCNTRL_MAX = 2, /**< Max value */
++ HDMITX_MCNTRL_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxmCntrl_t;
++
++/** Matrix scale values */
++typedef enum
++{
++ HDMITX_MSCALE_256 = 0, /**< Factor 1/256 */
++ HDMITX_MSCALE_512 = 1, /**< Factor 1/512 */
++ HDMITX_MSCALE_1024 = 2, /**< Factor 1/1024 */
++ HDMITX_MSCALE_NO_CHANGE = 3, /**< Factor unchanged */
++ HDMITX_MSCALE_MAX = 3, /**< Max value */
++ HDMITX_MSCALE_INVALID = 4 /**< Invalid value */
++} tmbslHdmiTxmScale_t;
++
++/*============================================================================*/
++/**
++ * Data Island Packet structure
++ */
++/** Parameter structure array sizes */
++enum _tmbslHdmiTxPkt
++{
++ HDMITX_PKT_DATA_BYTE_CNT = 28
++};
++
++/** \brief The parameter structure for tmbslTDA9984Pkt*() APIs */
++typedef struct _tmbslHdmiTxPkt_t
++{
++ UInt8 dataByte[HDMITX_PKT_DATA_BYTE_CNT]; /**< Packet Data */
++} tmbslHdmiTxPkt_t;
++
++/*============================================================================*/
++/**
++ * \brief The Audio Infoframe Parameter structure
++ */
++typedef struct _tmbslHdmiTxPktAif_t
++{
++ UInt8 CodingType; /**< Coding Type 0 to 0Fh */
++ UInt8 ChannelCount; /**< Channel Count 0 to 07h */
++ UInt8 SampleFreq; /**< Sample Frequency 0 to 07h */
++ UInt8 SampleSize; /**< Sample Size 0 to 03h */
++ UInt8 ChannelAlloc; /**< Channel Allocation 0 to FFh */
++ Bool DownMixInhibit; /**< Downmix inhibit flag 0/1 */
++ UInt8 LevelShift; /**< Level Shift 0 to 0Fh */
++} tmbslHdmiTxPktAif_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984PktSetMpegInfoframe() parameter types
++ */
++/** MPEG frame types */
++typedef enum
++{
++ HDMITX_MPEG_FRAME_UNKNOWN = 0, /**< Unknown */
++ HDMITX_MPEG_FRAME_I = 1, /**< i-frame */
++ HDMITX_MPEG_FRAME_B = 2, /**< b-frame */
++ HDMITX_MPEG_FRAME_P = 3, /**< p-frame */
++ HDMITX_MPEG_FRAME_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxMpegFrame_t;
++
++/** \brief The MPEG Infoframe Parameter structure */
++typedef struct _tmbslHdmiTxPktMpeg_t
++{
++ UInt32 bitRate; /**< MPEG bit rate in Hz */
++ tmbslHdmiTxMpegFrame_t frameType; /**< MPEG frame type */
++ Bool bFieldRepeat; /**< 0: new field, 1:repeated field */
++}tmbslHdmiTxPktMpeg_t;
++
++/*============================================================================*/
++/**
++ * Source Product Description Infoframe Parameter types
++ */
++/** SDI frame types */
++typedef enum
++{
++ HDMITX_SPD_INFO_UNKNOWN = 0,
++ HDMITX_SPD_INFO_DIGITAL_STB = 1,
++ HDMITX_SPD_INFO_DVD = 2,
++ HDMITX_SPD_INFO_DVHS = 3,
++ HDMITX_SPD_INFO_HDD_VIDEO = 4,
++ HDMITX_SPD_INFO_DVC = 5,
++ HDMITX_SPD_INFO_DSC = 6,
++ HDMITX_SPD_INFO_VIDEO_CD = 7,
++ HDMITX_SPD_INFO_GAME = 8,
++ HDMITX_SPD_INFO_PC = 9,
++ HDMITX_SPD_INFO_INVALID = 10
++} tmbslHdmiTxSourceDev_t;
++
++#define HDMI_TX_SPD_VENDOR_SIZE 8
++#define HDMI_TX_SPD_DESCR_SIZE 16
++#define HDMI_TX_SPD_LENGTH 25
++
++/** \brief The Source Product Description Infoframe Parameter structure */
++typedef struct _tmbslHdmiTxPktSpd_t
++{
++ UInt8 VendorName[HDMI_TX_SPD_VENDOR_SIZE]; /**< Vendor name */
++ UInt8 ProdDescr[HDMI_TX_SPD_DESCR_SIZE]; /**< Product Description */
++ tmbslHdmiTxSourceDev_t SourceDevInfo; /**< Source Device Info */
++} tmbslHdmiTxPktSpd_t;
++
++/*============================================================================*/
++/**
++ * \brief The Video Infoframe Parameter structure
++ */
++typedef struct _tmbslHdmiTxPktVif_t
++{
++ UInt8 Colour; /**< 0 to 03h */
++ Bool ActiveInfo; /**< 0/1 */
++ UInt8 BarInfo; /**< 0 to 03h */
++ UInt8 ScanInfo; /**< 0 to 03h */
++ UInt8 Colorimetry; /**< 0 to 03h */
++ UInt8 PictureAspectRatio; /**< 0 to 03h */
++ UInt8 ActiveFormatRatio; /**< 0 to 0Fh */
++ UInt8 Scaling; /**< 0 to 03h */
++ UInt8 VidFormat; /**< 0 to 7Fh */
++ UInt8 PixelRepeat; /**< 0 to 0Fh */
++ UInt16 EndTopBarLine;
++ UInt16 StartBottomBarLine;
++ UInt16 EndLeftBarPixel;
++ UInt16 StartRightBarPixel;
++} tmbslHdmiTxPktVif_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerGetMode() parameter types
++ */
++/** Scaler modes */
++typedef enum
++{
++ HDMITX_SCAMODE_OFF = 0, /**< Off */
++ HDMITX_SCAMODE_ON = 1, /**< On */
++ HDMITX_SCAMODE_AUTO = 2, /**< Auto */
++ HDMITX_SCAMODE_NO_CHANGE = 3, /**< No change */
++ HDMITX_SCAMODE_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxScaMode_t;
++
++/*============================================================================*/
++/**
++ * \brief The tmbslTDA9984ScalerGet() parameter type
++ */
++typedef struct _tmbslHdmiTxScalerDiag_t
++{
++ UInt16 maxBuffill_p; /**< Filling primary video buffer */
++ UInt16 maxBuffill_d; /**< Filling video deinterlaced buffer */
++ UInt8 maxFifofill_pi; /**< Filling primary video input FIFO */
++ UInt8 minFifofill_po1; /**< Filling primary video output FIFO #1 */
++ UInt8 minFifofill_po2; /**< Filling primary video output FIFO #2 */
++ UInt8 minFifofill_po3; /**< Filling primary video output FIFO #3 */
++ UInt8 minFifofill_po4; /**< Filling primary video output FIFO #4 */
++ UInt8 maxFifofill_di; /**< Filling deinterlaced video input FIFO */
++ UInt8 maxFifofill_do; /**< Filling deinterlaced video output FIFO */
++} tmbslHdmiTxScalerDiag_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerSetCoeffs() parameter types
++ */
++/** Scaler lookup table selection */
++typedef enum
++{
++ HDMITX_SCALUT_DEFAULT_TAB1 = 0, /**< Use default table 1 */
++ HDMITX_SCALUT_DEFAULT_TAB2 = 1, /**< Use default table 2 */
++ HDMITX_SCALUT_USE_VSLUT = 2, /**< Use vsLut parameter */
++ HDMITX_SCALUT_INVALID = 3 /**< Invalid value */
++} tmbslHdmiTxScaLut_t;
++
++/** Scaler control parameter structure array size */
++enum _tmbslHdmiTxvsLut
++{
++ HDMITX_VSLUT_COEFF_NUM = 45
++};
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerSetFieldOrder() parameter types
++ */
++/** IntExt values */
++typedef enum
++{
++ HDMITX_INTEXT_INTERNAL = 0, /**< Internal */
++ HDMITX_INTEXT_EXTERNAL = 1, /**< External */
++ HDMITX_INTEXT_NO_CHANGE = 2, /**< No change */
++ HDMITX_INTEXT_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxIntExt_t;
++
++/** TopSel values */
++typedef enum
++{
++ HDMITX_TOPSEL_INTERNAL = 0, /**< Internal */
++ HDMITX_TOPSEL_VRF = 1, /**< VRF */
++ HDMITX_TOPSEL_NO_CHANGE = 2, /**< No change */
++ HDMITX_TOPSEL_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxTopSel_t;
++
++/** TopTgl values */
++typedef enum
++{
++ HDMITX_TOPTGL_NO_ACTION = 0, /**< NO action */
++ HDMITX_TOPTGL_TOGGLE = 1, /**< Toggle */
++ HDMITX_TOPTGL_NO_CHANGE = 2, /**< No change */
++ HDMITX_TOPTGL_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxTopTgl_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerSetPhase() parameter types
++ */
++/** Phases_h values */
++typedef enum
++{
++ HDMITX_H_PHASES_16 = 0, /**< 15 horizontal phases */
++ HDMITX_H_PHASES_15 = 1, /**< 16 horizontal phases */
++ HDMITX_H_PHASES_INVALID = 2 /**< Invalid */
++} tmbslHdmiTxHPhases_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerSetFine() parameter types
++ */
++/** Reference pixel values */
++enum _tmbslHdmiTxScalerFinePixelLimits
++{
++ HDMITX_SCALER_FINE_PIXEL_MIN = 0x0000,
++ HDMITX_SCALER_FINE_PIXEL_MAX = 0x1FFF,
++ HDMITX_SCALER_FINE_PIXEL_NO_CHANGE = 0x2000,
++ HDMITX_SCALER_FINE_PIXEL_INVALID = 0x2001
++};
++
++/** Reference line values */
++enum _tmbslHdmiTxScalerFineLineLimits
++{
++ HDMITX_SCALER_FINE_LINE_MIN = 0x0000,
++ HDMITX_SCALER_FINE_LINE_MAX = 0x07FF,
++ HDMITX_SCALER_FINE_LINE_NO_CHANGE = 0x0800,
++ HDMITX_SCALER_FINE_LINE_INVALID = 0x0801
++};
++/*============================================================================*/
++/**
++ * tmbslTDA9984ScalerSetSync() parameter types
++ */
++/** Video sync method */
++typedef enum
++{
++ HDMITX_VSMETH_V_H = 0, /**< V and H */
++ HDMITX_VSMETH_V_XDE = 1, /**< V and X-DE */
++ HDMITX_VSMETH_NO_CHANGE = 2, /**< No change */
++ HDMITX_VSMETH_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxVsMeth_t;
++
++/** Line/pixel counters sync */
++typedef enum
++{
++ HDMITX_VSONCE_EACH_FRAME = 0, /**< Sync on each frame */
++ HDMITX_VSONCE_ONCE = 1, /**< Sync once only */
++ HDMITX_VSONCE_NO_CHANGE = 2, /**< No change */
++ HDMITX_VSONCE_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxVsOnce_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984TmdsSetOutputs() parameter types
++ */
++/** TMDS output mode */
++typedef enum
++{
++ HDMITX_TMDSOUT_NORMAL = 0, /**< Normal outputs */
++ HDMITX_TMDSOUT_NORMAL1 = 1, /**< Normal outputs, same as 0 */
++ HDMITX_TMDSOUT_FORCED0 = 2, /**< Forced 0 outputs */
++ HDMITX_TMDSOUT_FORCED1 = 3, /**< Forced 1 outputs */
++ HDMITX_TMDSOUT_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxTmdsOut_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984TmdsSetSerializer() parameter types
++ */
++/** Serializer phase limits */
++enum _tmbslHdmiTxTmdsPhase
++{
++ HDMITX_TMDSPHASE_MIN = 0,
++ HDMITX_TMDSPHASE_MAX = 15,
++ HDMITX_TMDSPHASE_INVALID = 16
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984TestSetPattern() parameter types
++ */
++/** Test pattern types */
++typedef enum
++{
++ HDMITX_PATTERN_OFF = 0, /**< Insert test pattern */
++ HDMITX_PATTERN_CBAR4 = 1, /**< Insert 4-bar colour bar */
++ HDMITX_PATTERN_CBAR8 = 2, /**< Insert 8-bar colour bar */
++ HDMITX_PATTERN_BLUE = 3, /**< Insert Blue screen */
++ HDMITX_PATTERN_BLACK = 4, /**< Insert Blue screen */
++ HDMITX_PATTERN_INVALID = 5 /**< Invalid pattern */
++} tmbslHdmiTxTestPattern_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984TestSetMode() parameter types
++ */
++/** Test modes */
++typedef enum
++{
++ HDMITX_TESTMODE_PAT = 0,/**< Insert test pattern */
++ HDMITX_TESTMODE_656 = 1,/**< Inject CCIR-656 video via audio port */
++ HDMITX_TESTMODE_SERPHOE = 2,/**< Activate srl_tst_ph2_o & srl_tst_ph3_o */
++ HDMITX_TESTMODE_NOSC = 3,/**< Input nosc predivider = PLL-ref input */
++ HDMITX_TESTMODE_HVP = 4,/**< Test high voltage protection cells */
++ HDMITX_TESTMODE_PWD = 5,/**< Test PLLs in sleep mode */
++ HDMITX_TESTMODE_DIVOE = 6,/**< Enable scaler PLL divider test output */
++ HDMITX_TESTMODE_INVALID = 7 /**< Invalid test */
++} tmbslHdmiTxTestMode_t;
++
++/** Test states */
++typedef enum
++{
++ HDMITX_TESTSTATE_OFF = 0, /**< Disable the selected test */
++ HDMITX_TESTSTATE_ON = 1, /**< Enable the selected test */
++ HDMITX_TESTSTATE_INVALID = 2 /**< Invalid value */
++} tmbslHdmiTxTestState_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetBlanking() parameter types
++ */
++/** Blankit Source */
++typedef enum
++{
++ HDMITX_BLNKSRC_NOT_DE = 0, /**< Source=Not DE */
++ HDMITX_BLNKSRC_VS_HS = 1, /**< Source=VS And HS */
++ HDMITX_BLNKSRC_VS_NOT_HS = 2, /**< Source=VS And Not HS */
++ HDMITX_BLNKSRC_VS_HEMB_VEMB = 3, /**< Source=Hemb And Vemb */
++ HDMITX_BLNKSRC_NO_CHANGE = 4, /**< No change */
++ HDMITX_BLNKSRC_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxBlnkSrc_t;
++
++/** Blanking Codes */
++typedef enum
++{
++ HDMITX_BLNKCODE_ALL_0 = 0, /**< Code=All Zero */
++ HDMITX_BLNKCODE_RGB444 = 1, /**< Code=RGB444 */
++ HDMITX_BLNKCODE_YUV444 = 2, /**< Code=YUV444 */
++ HDMITX_BLNKCODE_YUV422 = 3, /**< Code=YUV422 */
++ HDMITX_BLNKCODE_NO_CHANGE = 4, /**< No change */
++ HDMITX_BLNKCODE_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxBlnkCode_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetConfig() parameter types
++ */
++/** Sample edge */
++typedef enum
++{
++ HDMITX_PIXEDGE_CLK_POS = 0, /**< Pixel Clock Positive Edge */
++ HDMITX_PIXEDGE_CLK_NEG = 1, /**< Pixel Clock Negative Edge */
++ HDMITX_PIXEDGE_NO_CHANGE = 2, /**< No Change */
++ HDMITX_PIXEDGE_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxPixEdge_t;
++
++/** Upsample modes */
++typedef enum
++{
++ HDMITX_UPSAMPLE_BYPASS = 0, /**< Bypass */
++ HDMITX_UPSAMPLE_COPY = 1, /**< Copy */
++ HDMITX_UPSAMPLE_INTERPOLATE = 2, /**< Interpolate */
++ HDMITX_UPSAMPLE_AUTO = 3, /**< Auto: driver chooses best value */
++ HDMITX_UPSAMPLE_NO_CHANGE = 4, /**< No Change */
++ HDMITX_UPSAMPLE_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxUpsampleMode_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetFine() parameter types
++ */
++/** Subpacket count */
++typedef enum
++{
++ HDMITX_PIXSUBPKT_FIX_0 = 0, /**< Fix At 0 */
++ HDMITX_PIXSUBPKT_FIX_1 = 1, /**< Fix At 1 */
++ HDMITX_PIXSUBPKT_FIX_2 = 2, /**< Fix At 2 */
++ HDMITX_PIXSUBPKT_FIX_3 = 3, /**< Fix At 3 */
++ HDMITX_PIXSUBPKT_SYNC_FIRST = 4, /**< First Sync value */
++ HDMITX_PIXSUBPKT_SYNC_HEMB = 4, /**< Sync By Hemb */
++ HDMITX_PIXSUBPKT_SYNC_DE = 5, /**< Sync By Rising Edge DE */
++ HDMITX_PIXSUBPKT_SYNC_HS = 6, /**< Sync By Rising Edge HS */
++ HDMITX_PIXSUBPKT_NO_CHANGE = 7, /**< No Change */
++ HDMITX_PIXSUBPKT_INVALID = 8, /**< Invalid */
++ HDMITX_PIXSUBPKT_SYNC_FIXED = 3 /**< Not used as a parameter value,
++ * but used internally when
++ * Fix at 0/1/2/3 values are set */
++} tmbslHdmiTxPixSubpkt_t;
++
++/** Toggling */
++typedef enum
++{
++ HDMITX_PIXTOGL_NO_ACTION = 0, /**< No Action */
++ HDMITX_PIXTOGL_ENABLE = 1, /**< Toggle */
++ HDMITX_PIXTOGL_NO_CHANGE = 2, /**< No Change */
++ HDMITX_PIXTOGL_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxPixTogl_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetMapping() parameter types
++ */
++/** Video input port parameter structure array size and limits */
++enum _tmbslHdmiTxVinPortMap
++{
++ HDMITX_VIN_PORT_MAP_TABLE_LEN = 6,
++
++ HDMITX_VIN_PORT_SWAP_NO_CHANGE = 6,
++ HDMITX_VIN_PORT_SWAP_INVALID = 7,
++
++ HDMITX_VIN_PORT_MIRROR_NO_CHANGE = 2,
++ HDMITX_VIN_PORT_MIRROR_INVALID = 3
++};
++
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetSyncAuto() parameter types
++ */
++/** Sync source - was Embedded sync HDMITX_PIXEMBSYNC_ */
++typedef enum
++{
++ HDMITX_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */
++ HDMITX_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */
++ HDMITX_SYNCSRC_EXT_VS = 2, /**< External sync Vs, Hs */
++ HDMITX_SYNCSRC_NO_CHANGE = 3, /**< No Change */
++ HDMITX_SYNCSRC_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxSyncSource_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoInSetSyncManual() parameter types
++ */
++/** Video output frame pixel values */
++enum _tmbslHdmiTxVoutFinePixelLimits
++{
++ HDMITX_VOUT_FINE_PIXEL_MIN = 0x0000,
++ HDMITX_VOUT_FINE_PIXEL_MAX = 0x1FFF,
++ HDMITX_VOUT_FINE_PIXEL_NO_CHANGE = 0x2000,
++ HDMITX_VOUT_FINE_PIXEL_INVALID = 0x2001
++};
++
++/** Video output frame line values */
++enum _tmbslHdmiTxVoutFineLineLimits
++{
++ HDMITX_VOUT_FINE_LINE_MIN = 0x0000,
++ HDMITX_VOUT_FINE_LINE_MAX = 0x07FF,
++ HDMITX_VOUT_FINE_LINE_NO_CHANGE = 0x0800,
++ HDMITX_VOUT_FINE_LINE_INVALID = 0x0801
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoOutSetConfig() parameter types
++ */
++/** Prefilter */
++typedef enum
++{
++ HDMITX_VOUT_PREFIL_OFF = 0, /**< Off */
++ HDMITX_VOUT_PREFIL_121 = 1, /**< 121 */
++ HDMITX_VOUT_PREFIL_109 = 2, /**< 109 */
++ HDMITX_VOUT_PREFIL_CCIR601 = 3, /**< CCIR601 */
++ HDMITX_VOUT_PREFIL_NO_CHANGE = 4, /**< No Change */
++ HDMITX_VOUT_PREFIL_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxVoutPrefil_t;
++
++/** YUV blanking */
++typedef enum
++{
++ HDMITX_VOUT_YUV_BLNK_16 = 0, /**< 16 */
++ HDMITX_VOUT_YUV_BLNK_0 = 1, /**< 0 */
++ HDMITX_VOUT_YUV_BLNK_NO_CHANGE = 2, /**< No Change */
++ HDMITX_VOUT_YUV_BLNK_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxVoutYuvBlnk_t;
++
++/** Video quantization range */
++typedef enum
++{
++ HDMITX_VOUT_QRANGE_FS = 0, /**< Full Scale */
++ HDMITX_VOUT_QRANGE_RGB_YUV = 1, /**< RGB Or YUV */
++ HDMITX_VOUT_QRANGE_YUV = 2, /**< YUV */
++ HDMITX_VOUT_QRANGE_NO_CHANGE = 3, /**< No Change */
++ HDMITX_VOUT_QRANGE_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxVoutQrange_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoOutSetSync() parameter types
++ */
++/** Video sync source */
++typedef enum
++{
++ HDMITX_VSSRC_INTERNAL = 0, /**< Internal */
++ HDMITX_VSSRC_EXTERNAL = 1, /**< External */
++ HDMITX_VSSRC_NO_CHANGE = 2, /**< No change */
++ HDMITX_VSSRC_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxVsSrc_t;
++
++/** Video sync toggle */
++typedef enum
++{
++ HDMITX_VSTGL_TABLE = 0, /**< Vs/Hs polarity from table */
++ HDMITX_VSTGL_UNUSED_1 = 1, /**< Unused */
++ HDMITX_VSTGL_UNUSED_2 = 2, /**< Unused */
++ HDMITX_VSTGL_UNUSED_3 = 3, /**< Unused */
++ HDMITX_VSTGL_NO_ACTION = 4, /**< No toggle */
++ HDMITX_VSTGL_HS = 5, /**< Toggle Hs */
++ HDMITX_VSTGL_VS = 6, /**< Toggle Vs */
++ HDMITX_VSTGL_HS_VS = 7, /**< Toggle Hs & Vs */
++ HDMITX_VSTGL_NO_CHANGE = 8, /**< No change */
++ HDMITX_VSTGL_INVALID = 9 /**< Invalid */
++} tmbslHdmiTxVsTgl_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984VideoSetInOut() parameter types
++ */
++/** Pixel repetition values */
++enum _tmbslHdmiTxPixRepeat
++{
++ HDMITX_PIXREP_NONE = 0, /**< No repetition */
++ HDMITX_PIXREP_MIN = 0, /**< 1 repetition */
++
++ HDMITX_PIXREP_0 = 0,
++ HDMITX_PIXREP_1 = 1,
++ HDMITX_PIXREP_2 = 2,
++ HDMITX_PIXREP_3 = 3,
++ HDMITX_PIXREP_4 = 4,
++ HDMITX_PIXREP_5 = 5,
++ HDMITX_PIXREP_6 = 6,
++ HDMITX_PIXREP_7 = 7,
++ HDMITX_PIXREP_8 = 8,
++ HDMITX_PIXREP_9 = 9,
++
++ HDMITX_PIXREP_MAX = 9, /**< 10 repetitions */
++ HDMITX_PIXREP_DEFAULT = 10, /**< Default repetitions for output format */
++ HDMITX_PIXREP_NO_CHANGE = 11, /**< No change */
++ HDMITX_PIXREP_INVALID = 12 /**< Invalid */
++};
++
++/** Matrix modes */
++typedef enum
++{
++ HDMITX_MATMODE_OFF = 0, /**< Off */
++ HDMITX_MATMODE_AUTO = 1, /**< Auto */
++ HDMITX_MATMODE_NO_CHANGE = 2, /**< No change */
++ HDMITX_MATMODE_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxMatMode_t;
++
++/** Datapath bitwidth */
++typedef enum
++{
++ HDMITX_VOUT_DBITS_12 = 0, /**< 12 bits */
++ HDMITX_VOUT_DBITS_8 = 1, /**< 8 bits */
++ HDMITX_VOUT_DBITS_10 = 2, /**< 10 bits */
++ HDMITX_VOUT_DBITS_NO_CHANGE = 3, /**< No change */
++ HDMITX_VOUT_DBITS_INVALID = 4 /**< Invalid */
++} tmbslHdmiTxVoutDbits_t;
++
++/** Color depth */
++typedef enum
++{
++ HDMITX_COLORDEPTH_24 = 0, /**< 24 bits per pixel */
++ HDMITX_COLORDEPTH_30 = 1, /**< 30 bits per pixel */
++ HDMITX_COLORDEPTH_36 = 2, /**< 36 bits per pixel */
++ HDMITX_COLORDEPTH_48 = 3, /**< 48 bits per pixel */
++ HDMITX_COLORDEPTH_NO_CHANGE = 4, /**< No change */
++ HDMITX_COLORDEPTH_INVALID = 5 /**< Invalid */
++} tmbslHdmiTxColorDepth;
++
++/** the supported transmission formats of 3D video data */
++typedef enum
++{
++ HDMITX_3D_NONE = 0, /**< 3D video data not present */
++ HDMITX_3D_FRAME_PACKING = 1, /**< 3D video data Frame Packing structure */
++ HDMITX_3D_TOP_AND_BOTTOM = 2, /**< 3D video data Top and Bottom structure */
++ HDMITX_3D_SIDE_BY_SIDE_HALF = 3, /**< 3D video data Side by Side Half structure */
++ HDMITX_3D_INVALID = 4 /**< Invalid */
++} tmbslHdmiTx3DStructure_t;
++
++/*============================================================================*/
++/**
++ * tmbslTDA9984MatrixSetInputOffset() parameter type
++ */
++/** Parameter structure array size */
++enum _tmbslHdmiTxMatOffset
++{
++ HDMITX_MAT_OFFSET_NUM = 3
++};
++
++/** \brief The tmbslTDA9984MatrixSetInputOffset() parameter structure */
++typedef struct _tmbslHdmiTxMatOffset_t
++{
++ /** Offset array (values -1024 to +1023) */
++ Int16 Offset[HDMITX_MAT_OFFSET_NUM];
++} tmbslHdmiTxMatOffset_t;
++
++/** Matrix numeric limits */
++enum _tmbslHdmiTxMatLimits
++{
++ HDMITX_MAT_OFFSET_MIN = -1024,
++ HDMITX_MAT_OFFSET_MAX = 1023
++};
++
++/*============================================================================*/
++/**
++ * tmbslTDA9989PowerSetState() and tmbslTDA9989PowerGetState() parameter types
++ */
++typedef enum
++{
++ HDMITX_POWER_STATE_STAND_BY = 0, /**< Stand by mode */
++ HDMITX_POWER_STATE_SLEEP_MODE = 1, /**< Sleep mode */
++ HDMITX_POWER_STATE_ON = 2, /**< On mode */
++ HDMITX_POWER_STATE_INVALID = 3 /**< Invalid format */
++} tmbslHdmiTxPowerState_t;
++
++/**
++ * \brief Structure describing gamut metadata packet (P0 or P1 profiles)
++ */
++typedef struct
++{
++ UInt8 HB[3]; /**< Header bytes (HB0, HB1 & HB2) */
++ UInt8 PB[28]; /**< Payload bytes 0..27 */
++} tmbslHdmiTxPktGamut_t;
++
++
++/**
++ * \brief Structure describing RAW AVI infoframe
++ */
++typedef struct
++{
++ UInt8 HB[3]; /**< Header bytes (HB0, HB1 & HB2) */
++ UInt8 PB[28]; /**< Payload bytes 0..27 */
++} tmbslHdmiTxPktRawAvi_t;
++
++
++/** Sink category */
++typedef enum
++{
++ HDMITX_SINK_CAT_NOT_REPEATER = 0, /**< Not repeater */
++ HDMITX_SINK_CAT_REPEATER = 1, /**< repeater */
++ HDMITX_SINK_CAT_INVALID = 3 /**< Invalid */
++} tmbslHdmiTxSinkCategory_t;
++
++
++typedef struct
++{
++ Bool latency_available;
++ Bool Ilatency_available;
++ UInt8 Edidvideo_latency;
++ UInt8 Edidaudio_latency;
++ UInt8 EdidIvideo_latency;
++ UInt8 EdidIaudio_latency;
++
++} tmbslHdmiTxEdidLatency_t;
++
++/**
++ * \brief Structure defining additional VSDB data
++ */
++typedef struct
++{
++ UInt8 maxTmdsClock; /* maximum supported TMDS clock */
++ UInt8 cnc0; /* content type Graphics (text) */
++ UInt8 cnc1; /* content type Photo */
++ UInt8 cnc2; /* content type Cinema */
++ UInt8 cnc3; /* content type Game */
++ UInt8 hdmiVideoPresent; /* additional video format */
++ UInt8 h3DPresent; /* 3D support by the HDMI Sink */
++ UInt8 h3DMultiPresent; /* 3D multi strctures present */
++ UInt8 imageSize; /* additional info for the values in the image size area */
++ UInt8 hdmi3DLen; /* total length of 3D video formats */
++ UInt8 hdmiVicLen; /* total length of extended video formats */
++ UInt8 ext3DData[21]; /* max_len-10, ie: 31-10=21 */
++} tmbslHdmiTxEdidExtraVsdbData_t;
++
++/**
++ * \brief Enum defining possible quantization range
++ */
++typedef enum
++{
++ HDMITX_VQR_DEFAULT = 0, /* Follow HDMI spec. */
++ HDMITX_RGB_FULL = 1, /* Force RGB FULL , DVI only */
++ HDMITX_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */
++} tmbslHdmiTxVQR_t;
++
++
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLHDMITX_TYPES_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h
+new file mode 100755
+index 0000000..8fc3084
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslHdmiTx_funcMapping.h
+@@ -0,0 +1,141 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslHdmiTx_funcMapping.h
++ *
++ * \version $Revision: 2 $
++ *
++*/
++
++
++
++#ifndef TMDLHDMITXTDA9989_CFG_H
++#define TMDLHDMITXTDA9989_CFG_H
++
++#include "tmbslTDA9989_Functions.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define tmbslHdmiTxInit tmbslTDA9989Init
++#define tmbslHdmiTxEdidRequestBlockData tmbslTDA9989EdidRequestBlockData
++#define tmbslHdmiTxVideoOutSetConfig tmbslTDA9989VideoOutSetConfig
++#define tmbslHdmiTxAudioInResetCts tmbslTDA9989AudioInResetCts
++#define tmbslHdmiTxAudioInSetConfig tmbslTDA9989AudioInSetConfig
++#define tmbslHdmiTxAudioInSetCts tmbslTDA9989AudioInSetCts
++#define tmbslHdmiTxAudioOutSetChanStatus tmbslTDA9989AudioOutSetChanStatus
++#define tmbslHdmiTxAudioOutSetChanStatusMapping tmbslTDA9989AudioOutSetChanStatusMapping
++#define tmbslHdmiTxAudioOutSetMute tmbslTDA9989AudioOutSetMute
++#define tmbslHdmiTxDeinit tmbslTDA9989Deinit
++#define tmbslHdmiTxEdidGetAudioCapabilities tmbslTDA9989EdidGetAudioCapabilities
++#define tmbslHdmiTxEdidGetBlockCount tmbslTDA9989EdidGetBlockCount
++#define tmbslHdmiTxEdidGetStatus tmbslTDA9989EdidGetStatus
++#define tmbslHdmiTxEdidGetSinkType tmbslTDA9989EdidGetSinkType
++#define tmbslHdmiTxEdidGetSourceAddress tmbslTDA9989EdidGetSourceAddress
++#define tmbslHdmiTxEdidGetVideoCapabilities tmbslTDA9989EdidGetVideoCapabilities
++#define tmbslHdmiTxEdidGetVideoPreferred tmbslTDA9989EdidGetVideoPreferred
++#define tmbslHdmiTxHdcpCheck tmbslTDA9989HdcpCheck
++#define tmbslHdmiTxHdcpConfigure tmbslTDA9989HdcpConfigure
++#define tmbslHdmiTxHdcpDownloadKeys tmbslTDA9989HdcpDownloadKeys
++#define tmbslHdmiTxHdcpEncryptionOn tmbslTDA9989HdcpEncryptionOn
++#define tmbslHdmiTxHdcpGetOtp tmbslTDA9989HdcpGetOtp
++#define tmbslHdmiTxHdcpGetT0FailState tmbslTDA9989HdcpGetT0FailState
++#define tmbslHdmiTxHdcpHandleBCAPS tmbslTDA9989HdcpHandleBCAPS
++#define tmbslHdmiTxHdcpHandleBKSV tmbslTDA9989HdcpHandleBKSV
++#define tmbslHdmiTxHdcpHandleBKSVResult tmbslTDA9989HdcpHandleBKSVResult
++#define tmbslHdmiTxHdcpHandleBSTATUS tmbslTDA9989HdcpHandleBSTATUS
++#define tmbslHdmiTxHdcpHandleENCRYPT tmbslTDA9989HdcpHandleENCRYPT
++#define tmbslHdmiTxHdcpHandlePJ tmbslTDA9989HdcpHandlePJ
++#define tmbslHdmiTxHdcpHandleSHA_1 tmbslTDA9989HdcpHandleSHA_1
++#define tmbslHdmiTxHdcpHandleSHA_1Result tmbslTDA9989HdcpHandleSHA_1Result
++#define tmbslHdmiTxHdcpHandleT0 tmbslTDA9989HdcpHandleT0
++#define tmbslHdmiTxHdcpInit tmbslTDA9989HdcpInit
++#define tmbslHdmiTxHdcpRun tmbslTDA9989HdcpRun
++#define tmbslHdmiTxHdcpStop tmbslTDA9989HdcpStop
++#define tmbslHdmiTxHotPlugGetStatus tmbslTDA9989HotPlugGetStatus
++#define tmbslHdmiTxRxSenseGetStatus tmbslTDA9989RxSenseGetStatus
++#define tmbslHdmiTxHwGetRegisters tmbslTDA9989HwGetRegisters
++#define tmbslHdmiTxHwGetVersion tmbslTDA9989HwGetVersion
++#define tmbslHdmiTxHwGetCapabilities tmbslTDA9989HwGetCapabilities
++#define tmbslHdmiTxHwHandleInterrupt tmbslTDA9989HwHandleInterrupt
++#define tmbslHdmiTxHwSetRegisters tmbslTDA9989HwSetRegisters
++#define tmbslHdmiTxHwStartup tmbslTDA9989HwStartup
++#define tmbslHdmiTxMatrixSetCoeffs tmbslTDA9989MatrixSetCoeffs
++#define tmbslHdmiTxMatrixSetConversion tmbslTDA9989MatrixSetConversion
++#define tmbslHdmiTxMatrixSetInputOffset tmbslTDA9989MatrixSetInputOffset
++#define tmbslHdmiTxMatrixSetMode tmbslTDA9989MatrixSetMode
++#define tmbslHdmiTxMatrixSetOutputOffset tmbslTDA9989MatrixSetOutputOffset
++#define tmbslHdmiTxPktSetAclkRecovery tmbslTDA9989PktSetAclkRecovery
++#define tmbslHdmiTxPktSetAcp tmbslTDA9989PktSetAcp
++#define tmbslHdmiTxPktSetAudioInfoframe tmbslTDA9989PktSetAudioInfoframe
++#define tmbslHdmiTxPktSetGeneralCntrl tmbslTDA9989PktSetGeneralCntrl
++#define tmbslHdmiTxPktSetIsrc1 tmbslTDA9989PktSetIsrc1
++#define tmbslHdmiTxPktSetIsrc2 tmbslTDA9989PktSetIsrc2
++#define tmbslHdmiTxPktSetMpegInfoframe tmbslTDA9989PktSetMpegInfoframe
++#define tmbslHdmiTxPktSetNullInsert tmbslTDA9989PktSetNullInsert
++#define tmbslHdmiTxPktSetNullSingle tmbslTDA9989PktSetNullSingle
++#define tmbslHdmiTxPktSetSpdInfoframe tmbslTDA9989PktSetSpdInfoframe
++#define tmbslHdmiTxPktSetVideoInfoframe tmbslTDA9989PktSetVideoInfoframe
++#define tmbslHdmiTxPktSetVsInfoframe tmbslTDA9989PktSetVsInfoframe
++#define tmbslHdmiTxPktSetRawVideoInfoframe tmbslTDA9989PktSetRawVideoInfoframe
++#define tmbslHdmiTxPowerGetState tmbslTDA9989PowerGetState
++#define tmbslHdmiTxPowerSetState tmbslTDA9989PowerSetState
++#define tmbslHdmiTxReset tmbslTDA9989Reset
++#define tmbslHdmiTxScalerGet tmbslTDA9989ScalerGet
++#define tmbslHdmiTxScalerGetMode tmbslTDA9989ScalerGetMode
++#define tmbslHdmiTxScalerInDisable tmbslTDA9989ScalerInDisable
++#define tmbslHdmiTxScalerSetCoeffs tmbslTDA9989ScalerSetCoeffs
++#define tmbslHdmiTxScalerSetFieldOrder tmbslTDA9989ScalerSetFieldOrder
++#define tmbslHdmiTxScalerSetFine tmbslTDA9989ScalerSetFine
++#define tmbslHdmiTxScalerSetPhase tmbslTDA9989ScalerSetPhase
++#define tmbslHdmiTxScalerSetLatency tmbslTDA9989ScalerSetLatency
++#define tmbslHdmiTxScalerSetSync tmbslTDA9989ScalerSetSync
++#define tmbslHdmiTxSwGetVersion tmbslTDA9989SwGetVersion
++#define tmbslHdmiTxSysTimerWait tmbslTDA9989SysTimerWait
++#define tmbslHdmiTxTmdsSetOutputs tmbslTDA9989TmdsSetOutputs
++#define tmbslHdmiTxTmdsSetSerializer tmbslTDA9989TmdsSetSerializer
++#define tmbslHdmiTxTestSetPattern tmbslTDA9989TestSetPattern
++#define tmbslHdmiTxTestSetMode tmbslTDA9989TestSetMode
++#define tmbslHdmiTxVideoInSetBlanking tmbslTDA9989VideoInSetBlanking
++#define tmbslHdmiTxVideoInSetConfig tmbslTDA9989VideoInSetConfig
++#define tmbslHdmiTxVideoInSetFine tmbslTDA9989VideoInSetFine
++#define tmbslHdmiTxVideoInSetMapping tmbslTDA9989VideoInSetMapping
++#define tmbslHdmiTxSetVideoPortConfig tmbslTDA9989SetVideoPortConfig
++#define tmbslHdmiTxSetAudioPortConfig tmbslTDA9989SetAudioPortConfig
++#define tmbslHdmiTxSetAudioClockPortConfig tmbslTDA9989SetAudioClockPortConfig
++#define tmbslHdmiTxVideoInSetSyncAuto tmbslTDA9989VideoInSetSyncAuto
++#define tmbslHdmiTxVideoInSetSyncManual tmbslTDA9989VideoInSetSyncManual
++#define tmbslHdmiTxVideoOutDisable tmbslTDA9989VideoOutDisable
++#define tmbslHdmiTxVideoOutSetSync tmbslTDA9989VideoOutSetSync
++#define tmbslHdmiTxVideoSetInOut tmbslTDA9989VideoSetInOut
++#define tmbslHdmiTxFlagSwInt tmbslTDA9989FlagSwInt
++#define tmbslHdmiTxSet5vpower tmbslTDA9989Set5vpower
++#define tmbslHdmiTxEnableCallback tmbslTDA9989EnableCallback
++#define tmbslHdmiTxSetColorDepth tmbslTDA9989SetColorDepth
++#define tmbslHdmiTxSetDefaultPhase tmbslTDA9989SetDefaultPhase
++#define tmbslHdmiTxPktFillGamut tmbslTDA9989PktFillGamut
++#define tmbslHdmiTxPktSendGamut tmbslTDA9989PktSendGamut
++#define tmbslHdmiTxEdidGetMonitorDescriptors tmbslTDA9989EdidGetMonitorDescriptors
++#define tmbslHdmiTxEdidGetDetailedTimingDescriptors tmbslTDA9989EdidGetDetailedTimingDescriptors
++#define tmbslHdmiTxEdidGetBasicDisplayParam tmbslTDA9989EdidGetBasicDisplayParam
++#define tmbslHdmiTxHdcpGetSinkCategory tmbslTDA9989HdcpGetSinkCategory
++#define tmbslHdmiTxEdidGetLatencyInfo tmbslTDA9989EdidGetLatencyInfo
++#define tmbslHdmiTxEdidGetExtraVsdbData tmbslTDA9989EdidGetExtraVsdbData
++#ifdef TMFL_TDA19989
++#define tmbslHdmiTxHdcpPowerDown tmbslTDA9989HdcpPowerDown
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITXTDA9989_CFG_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h
+new file mode 100755
+index 0000000..0f9a3e3
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/inc/tmbslTDA9989_Functions.h
+@@ -0,0 +1,3060 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_functions.h
++ *
++ * \version $Revision: 2 $
++ *
++ *
++*/
++
++#ifndef TMBSLTDA9989_FUNCTIONS_H
++#define TMBSLTDA9989_FUNCTIONS_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxCompId.h"
++#include "tmbslHdmiTx_types.h"
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/*============================================================================*/
++/**
++ \brief Reset the Clock Time Stamp generator in HDMI mode only
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++ */
++tmErrorCode_t
++tmbslTDA9989AudioInResetCts
++(
++ tmUnitSelect_t txUnit
++);
++
++/**
++ \brief Set audio input configuration in HDMI mode only
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] aFmt Audio input format
++ \param[in] i2sFormat I2s format type
++ \param[in] chanI2s I2S channel allocation
++ \param[in] chanDsd DSD channel allocation
++ \param[in] clkPolDsd DSD clock polarity
++ \param[in] swapDsd DSD data swap
++ \param[in] layout Sample layout
++ \param[in] latency_rd Audio FIFO read latency
++ \param[in] dstRate Dst rate (not used)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++ */
++tmErrorCode_t
++tmbslTDA9989AudioInSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaFmt_t aFmt,
++ tmbslHdmiTxI2sFor_t i2sFormat,
++ UInt8 chanI2s,
++ UInt8 chanDsd,
++ tmbslHdmiTxClkPolDsd_t clkPolDsd,
++ tmbslHdmiTxSwapDsd_t swapDsd,
++ UInt8 layout,
++ UInt16 latency_rd,
++ tmbslHdmiTxDstRate_t dstRate
++);
++
++
++/**
++ \brief Set the Clock Time Stamp generator in HDMI mode only
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] ctsRef Clock Time Stamp reference source
++ \param[in] afs Audio input sample frequency
++ \param[in] voutFmt Video output format
++ \param[in] voutFreq Vertical output frequency
++ \param[in] uCts Manual Cycle Time Stamp
++ \param[in] uCtsX Clock Time Stamp factor x
++ \param[in] ctsK Clock Time Stamp predivider k
++ \param[in] ctsM Clock Time Stamp postdivider m
++ \param[in] dstRate Dst rate (not used)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++ */
++tmErrorCode_t
++tmbslTDA9989AudioInSetCts
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxctsRef_t ctsRef,
++ tmbslHdmiTxafs_t afs,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVfreq_t voutFreq,
++ UInt32 uCts,
++ UInt16 uCtsX,
++ tmbslHdmiTxctsK_t ctsK,
++ tmbslHdmiTxctsM_t ctsM,
++ tmbslHdmiTxDstRate_t dstRate
++);
++
++/**
++ \brief Set the Channel Status Bytes 0,1,3 & 4
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] copyright Byte 0 Copyright bit (bit2)
++ \param[in] formatInfo Byte 0 Audio sample format (bit1) and additional info (bit345)
++ \param[in] categoryCode Byte 1 Category code (bits8-15)
++ \param[in] sampleFreq Byte 3 Sample Frequency (bits24-27)
++ \param[in] clockAccuracy Byte 3 Clock Accuracy (bits38-31)
++ \param[in] maxWordLength Byte 4 Maximum word length (bit32)
++ \param[in] wordLength Byte 4 Word length (bits33-35)
++ \param[in] origSampleFreq Byte 4 Original Sample Frequency (bits36-39)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++
++ \note The consumer use bit (bit0) and Mode bits (bits6-7) are forced to zero.
++ Use tmbslTDA9989AudioOutSetChanStatusMapping to set CS Byte 2.
++
++ */
++tmErrorCode_t
++tmbslTDA9989AudioOutSetChanStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxAudioData_t pcmIdentification,
++ tmbslHdmiTxCSformatInfo_t formatInfo,
++ tmbslHdmiTxCScopyright_t copyright,
++ UInt8 categoryCode,
++ tmbslHdmiTxafs_t sampleFreq,
++ tmbslHdmiTxCSclkAcc_t clockAccuracy,
++ tmbslHdmiTxCSmaxWordLength_t maxWordLength,
++ tmbslHdmiTxCSwordLength_t wordLength,
++ tmbslHdmiTxCSorigAfs_t origSampleFreq
++);
++
++/**
++ \brief Set the Channel Status Byte2 for Audio Port 0
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] sourceLeft L Source Number: 0 don't take into account, 1-15
++ \param[in] channelLeft L Channel Number: 0 don't take into account, 1-15
++ \param[in] sourceRight R Source Number: 0 don't take into account, 1-15
++ \param[in] channelRight R Channel Number: 0 don't take into account, 1-15
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++
++ \note Use tmbslTDA9989AudioOutSetChanStatus to set all other CS bytes
++ This function only sets the mapping for Audio Port 0.
++
++ */
++tmErrorCode_t
++tmbslTDA9989AudioOutSetChanStatusMapping
++(
++ tmUnitSelect_t txUnit,
++ UInt8 sourceLeft[4],
++ UInt8 channelLeft[4],
++ UInt8 sourceRight[4],
++ UInt8 channelRight[4]
++);
++
++/**
++ \brief Mute or un-mute the audio output by controlling the audio FIFO,
++ in HDMI mode only
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] aMute Audio mute: On, Off
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: in DVI mode
++
++ \note tmbslTDA9989PktSetGeneralCntrl must be used to control the audio
++ mute in outgoing data island packets
++
++ */
++tmErrorCode_t
++tmbslTDA9989AudioOutSetMute
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaMute_t aMute
++);
++
++
++/*============================================================================*/
++/**
++ \brief Disable an HDMI Transmitter output and destroy its driver
++ instance
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989Deinit
++(
++ tmUnitSelect_t txUnit
++);
++
++
++/**
++ \brief Get supported audio format(s) from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidAFmts Pointer to the array of structures to receive the
++ supported Short Audio Descriptors
++ \param[in] aFmtLength Number of SADs supported in buffer pEdidAFmts,
++ up to HDMI_TX_SAD_MAX_CNT
++ \param[out] pAFmtsAvail Pointer to receive the number of SADs available
++ \param[out] pAudioFlags Pointer to the byte to receive the Audio Capability
++ Flags
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \note \verbatim
++ Supported Short Audio Descriptors array:
++ EdidAFmts[0].ModeChans SAD 1 - Mode byte
++ EdidAFmts[0].Freqs SAD 1 - Frequencies byte
++ EdidAFmts[0].Byte3 SAD 1 - Byte 3
++ ...
++ EdidAFmts[n-1].ModeChans SAD n - Mode byte
++ EdidAFmts[n-1].Freqs SAD n - Frequencies byte
++ EdidAFmts[n-1].Byte3 SAD n - Byte 3
++ (Where n is the smaller of aFmtLength and pAFmtAvail)
++ \endverbatim
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetAudioCapabilities
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidSad_t *pEdidAFmts,
++ UInt aFmtLength,
++ UInt *pAFmtsAvail,
++ UInt8 *pAudioFlags
++);
++
++/*============================================================================*/
++/**
++ \brief Get the EDID block count
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] puEdidBlockCount Pointer to data byte in which to return the
++ block count
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetBlockCount
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *puEdidBlockCount
++);
++
++/*============================================================================*/
++/**
++ \brief Get the EDID status
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] puEdidBlockCount Pointer to data byte in which to return the
++ edid status
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetStatus
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *puEdidStatus
++);
++
++/**
++ \brief Request read of EDID blocks from the sink device via DDC
++ function not synchronous edid will available on
++ EDID_BLK_READ callback
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pRawEdid Pointer to a buffer supplied by the caller to accept
++ the raw EDID data.
++ \param[in] numBlocks Number of blocks to read
++ \param[in] lenRawEdid Length in bytes of the supplied buffer
++ \param[out] pEdidStatus Pointer to status value E_EDID_READ or E_EDID_ERROR
++ valid only when the return value is TM_OK
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE: EDID not read
++
++ \note NA
++
++ */
++
++tmErrorCode_t
++tmbslTDA9989EdidRequestBlockData
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pRawEdid,
++ Int numBlocks, /* Only relevant if pRawEdid valid */
++ Int lenRawEdid /* Only relevant if pRawEdid valid */
++);
++
++
++/**
++ \brief Get Sink Type by analysis of EDID content
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pSinkType Pointer to returned Sink Type: DVI or HDMI
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : edid not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive
++
++ \sa tmbslTDA9989EdidGetBlockData
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetSinkType
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkType_t *pSinkType
++);
++
++/*============================================================================*/
++/**
++ \brief Get Source Physical Address by analysis of EDID content
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pSourceAddress Pointer to returned Source Physical Address (ABCDh)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \sa tmbslTDA9989EdidGetBlockData
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetSourceAddress
++(
++ tmUnitSelect_t txUnit,
++ UInt16 *pSourceAddress
++);
++
++/**
++ \brief Get supported video format(s) from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidVFmts Pointer to the array to receive the supported Short
++ Video Descriptors
++ \param[in] vFmtLength Number of SVDs supported in buffer pEdidVFmts,
++ up to HDMI_TX_SVD_MAX_CNT
++ \param[out] pVFmtsAvail Pointer to receive the number of SVDs available
++ \param[out] pVidFlags Ptr to the byte to receive Video Capability Flags
++ b7: underscan supported
++ b6: YCbCr 4:4:4 supported
++ b5: YCbCr 4:2:2 supported
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive
++
++ \note \verbatim
++ Supported Short Video Descriptors array:
++ (HDMI_TX_SVD_NATIVE_MASK bit set to indicate native format)
++ EdidVFmts[0] EIA/CEA Short Video Descriptor 1, or 0
++ ...
++ EdidVFmts[n-1] EIA/CEA Short Video Descriptor 32, or 0
++ (Where n is the smaller of vFmtLength and pVFmtAvail)
++ \endverbatim
++ \sa tmbslTDA9989EdidGetBlockData
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetVideoCapabilities
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEdidVFmts,
++ UInt vFmtLength,
++ UInt *pVFmtsAvail,
++ UInt8 *pVidFlags
++);
++/**
++ \brief Get detailed timing descriptor from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidDTD Pointer to the array to receive the Detailed timing descriptor
++
++ \param[in] nb_size Number of DTD supported in buffer pEdidDTD
++
++ \param[out] pDTDAvail Pointer to receive the number of DTD available
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++*/
++tmErrorCode_t
++tmbslTDA9989EdidGetDetailedTimingDescriptors
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidDtd_t *pEdidDTD,
++ UInt8 nb_size,
++ UInt8 *pDTDAvail
++);
++
++/**
++ \brief Get detailed Monitor descriptor from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidFirstMD Pointer to the First Monitor descriptor
++ \param[out] pEdidSecondMD Pointer to the Second Monitor descriptor
++ \param[out] pEdidOtherMD Pointer to the Other Monitor descriptor
++ \param[in] sizeOtherMD Not used
++ \param[out] pOtherMDAvail Not used
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++*/
++tmErrorCode_t
++tmbslTDA9989EdidGetMonitorDescriptors
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidFirstMD_t *pEdidFirstMD,
++ tmbslHdmiTxEdidSecondMD_t *pEdidSecondMD,
++ tmbslHdmiTxEdidOtherMD_t *pEdidOtherMD,
++ UInt8 sizeOtherMD,
++ UInt8 *pOtherMDAvail
++);
++
++/**
++ \brief Get basic display parameters from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidBDParam Pointer to the Basic Display Parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++*/
++tmErrorCode_t
++tmbslTDA9989EdidGetBasicDisplayParam
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidBDParam_t *pEdidBDParam
++);
++
++
++/**
++ \brief Get preferred video format from previously read EDID
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pEdidDTD Pointer to the structure to receive the Detailed
++ Timing Descriptor parameters of the preferred video
++ format
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NULL_CONNECTION: HPD pin is inactive
++
++ \note \verbatim
++ Detailed Timing Descriptor parameters output structure:
++ UInt16 uPixelClock Pixel Clock (MHz/10,000)
++ UInt16 uHActivePixels Horizontal Active Pixels
++ UInt16 uHBlankPixels Horizontal Blanking Pixels
++ UInt16 uVActiveLines Vertical Active Lines
++ UInt16 uVBlankLines Vertical Blanking Lines
++ UInt16 uHSyncOffset Horizontal Sync Offset (Pixels)
++ UInt16 uHSyncWidth Horizontal Sync Pulse Width (Pixels)
++ UInt16 uVSyncOffset Vertical Sync Offset (Lines)
++ UInt16 uVSyncWidth Vertical Sync Pulse Width (Lines)
++ UInt16 uHImageSize Horizontal Image Size (mm)
++ UInt16 uVImageSize Vertical Image Size (mm)
++ UInt16 uHBorderPixels Horizontal Border (Pixels)
++ UInt16 uVborderPixels Vertical Border (Pixels)
++ UInt8 Flags Interlace/sync info
++ \endverbatim
++ \sa tmbslTDA9989EdidGetBlockData
++ */
++tmErrorCode_t
++tmbslTDA9989EdidGetVideoPreferred
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidDtd_t *pEdidDTD
++);
++
++/**
++ \brief Check the result of an HDCP encryption attempt, called at
++ intervals (set by uTimeSinceLastCallMs) after tmbslTDA9989HdcpRun
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uTimeSinceLastCallMs Time in ms since this was last called
++ \param[out] pResult The outcome of the check
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++ */
++tmErrorCode_t
++tmbslTDA9989HdcpCheck
++(
++ tmUnitSelect_t txUnit,
++ UInt16 uTimeSinceLastCallMs,
++ tmbslHdmiTxHdcpCheck_t *pResult
++);
++
++/**
++ \brief Configure various HDCP parameters
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] slaveAddress DDC I2C slave address
++ \param[in] txMode Mode of our transmitter device
++ \param[in] options Options flags to control behaviour of HDCP
++ \param[in] uCheckIntervalMs HDCP check interval in milliseconds
++ \param[in] uChecksToDo Number of HDCP checks to do after HDCP starts
++ A value of 2 or more is valid for checking
++ May be set to 0 to disabling checking
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++ \note Must be called before all other HDCP APIs
++ */
++tmErrorCode_t
++tmbslTDA9989HdcpConfigure
++(
++ tmUnitSelect_t txUnit,
++ UInt8 slaveAddress,
++ tmbslHdmiTxHdcpTxMode_t txMode,
++ tmbslHdmiTxHdcpOptions_t options,
++ UInt16 uCheckIntervalMs,
++ UInt8 uChecksToDo
++);
++
++/**
++ \brief Download keys and AKSV data from OTP memory to the device
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] seed Seed value
++ \param[in] keyDecryption State of key decryption 0 to 1 (disabled, enabled)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++ */
++tmErrorCode_t
++tmbslTDA9989HdcpDownloadKeys
++(
++ tmUnitSelect_t txUnit,
++ UInt16 seed,
++ tmbslHdmiTxDecrypt_t keyDecryption
++);
++
++/*============================================================================*/
++/**
++ \brief Switch HDCP encryption on or off without disturbing Infoframes
++ (Not normally used)
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bOn Encryption state: 1=on, 0=off
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpEncryptionOn
++(
++ tmUnitSelect_t txUnit,
++ Bool bOn
++);
++
++/*============================================================================*/
++/**
++ \brief Get HDCP OTP registers
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] otpAddress OTP start address 0-FF
++ \param[out] pOtpData Ptr to a three-byte array to hold the data read:
++ [0] = OTP_DATA_MSB
++ [1] = OTP_DATA_ISB
++ [2] = OTP_DATA_LSB
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpGetOtp
++(
++ tmUnitSelect_t txUnit,
++ UInt8 otpAddress,
++ UInt8 *pOtpData
++);
++
++/*============================================================================*/
++/**
++ \brief Return the failure state that caused the last T0 interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pFailState Ptr to the unit's last T0 fail state
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpGetT0FailState
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pFailState
++);
++
++/*============================================================================*/
++/**
++ \brief Handle BCAPS interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note The user BCAPS interrupt handler (registered with
++ tmbslTDA9989Init) calls this API before calling
++ tmbslTDA9989HdcpHandleBKSV
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBCAPS
++(
++ tmUnitSelect_t txUnit
++);
++
++/*============================================================================*/
++/**
++ \brief Read BKSV registers
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pBksv Pointer to 5-byte BKSV array returned to caller
++ (1st byte is MSB)
++ \param[out] pbCheckRequired Pointer to a result variable to tell the caller
++ whether to check for BKSV in a revocation list:
++ 0 or 1 (check not required, check required)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note The user BCAPS interrupt handler (registered with
++ tmbslTDA9989Init) calls this API after calling
++ tmbslTDA9989HdcpHandleBCAPS
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBKSV
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pBksv,
++ Bool *pbCheckRequired
++);
++
++/*============================================================================*/
++/**
++ \brief Declare BKSV result to be secure or not secure
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bSecure Result of user's check of BKSV against a
++ revocation list:
++ 0 (not secure: BKSV found in revocation list)
++ 1 (secure: BKSV not found in revocation list)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note The user BCAPS interrupt handler (registered with
++ tmbslTDA9989Init) calls this API after calling
++ tmbslTDA9989HdcpHandleBKSV
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBKSVResult
++(
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++);
++
++/**
++ \brief Handle BSTATUS interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pBstatus Pointer to 16-bit BSTATUS value returned to caller
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note Called by user's BSTATUS interrupt handler registered with
++ tmbslTDA9989Init
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBSTATUS
++(
++ tmUnitSelect_t txUnit,
++ UInt16 *pBstatus
++);
++
++/*============================================================================*/
++/**
++ \brief Handle ENCRYPT interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note Called by user's ENCRYPT interrupt handler registered with
++ tmbslTDA9989Init
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleENCRYPT
++(
++ tmUnitSelect_t txUnit
++);
++
++/*============================================================================*/
++/**
++ \brief Handle PJ interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note Called by user's PJ interrupt handler registered with
++ tmbslTDA9989Init
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandlePJ
++(
++ tmUnitSelect_t txUnit
++);
++
++/**
++ \brief Handle SHA-1 interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] maxKsvDevices Maximum number of 5-byte devices that will fit
++ in *pKsvList: 0 to 128 devices
++ If 0, no KSV read is done and it is treated as
++ secure
++ \param[out] pKsvList Pointer to KSV list array supplied by caller:
++ Sets of 5-byte KSVs, 1 per device, 1st byte is
++ LSB of 1st device
++ May be null if maxKsvDevices is 0
++ \param[out] pnKsvDevices Pointer to number of KSV devices copied to
++ *pKsvList: 0 to 128
++ If 0, no KSV check is needed and it is treated
++ as secure
++ May be null if maxKsvDevices is 0
++ \param[out] pDepth Connection tree depth
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: two parameters disagree
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note Called by user's SHA-1 interrupt handler registered with
++ tmbslTDA9989Init
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleSHA_1
++(
++ tmUnitSelect_t txUnit,
++ UInt8 maxKsvDevices,
++ UInt8 *pKsvList,
++ UInt8 *pnKsvDevices,
++ UInt8 *pDepth
++);
++
++/*============================================================================*/
++/**
++ \brief Declare KSV list result to be secure or not secure
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bSecure Result of user's check of KSV list against a
++ revocation list:
++ 0 (not secure: one or more KSVs are in r.list)
++ 1 (secure: no KSV found in revocation list)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note The user SHA_1 interrupt handler (registered with
++ tmbslTDA9989Init) calls this API after calling
++ tmbslTDA9989HdcpHandleSHA_1
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleSHA_1Result
++(
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++);
++
++/*============================================================================*/
++/**
++ \brief Handle T0 interrupt
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++
++ \note Called by user's T0 interrupt handler registered with
++ tmbslTDA9989Init
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleT0
++(
++ tmUnitSelect_t txUnit
++);
++
++/*============================================================================*/
++/**
++ \brief Prepare for HDCP operation
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] voutFmt Video output format
++ \param[in] voutFreq Vertical output frequency
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++ \note Must be called before tmbslTDA9989HdcpRun
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpInit
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVfreq_t voutFreq
++);
++
++/*============================================================================*/
++/**
++ \brief Start HDCP operation
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++ \note Must be called after tmbslTDA9989HdcpInit
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpRun
++(
++ tmUnitSelect_t txUnit
++);
++
++/*============================================================================*/
++/**
++ \brief Stop HDCP operation, and cease encrypting the output
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++ \note This will trigger an Encrypt interrupt
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpStop
++(
++ tmUnitSelect_t txUnit
++);
++/**
++ \brief Get the hot plug input status last read by tmbslTDA9989Init
++ or tmbslTDA9989HwHandleInterrupt
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pHotPlugStatus Pointer to returned Hot Plug Detect status
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989HotPlugGetStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHotPlug_t *pHotPlugStatus,
++ Bool client /* Used to determine whether the request comes from the application */
++);
++
++/**
++ \brief Get the rx sense input status last read by tmbslTDA9989Init
++ or tmbslTDA9989HwHandleInterrupt
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pRxSenseStatus Pointer to returned Rx Sense Detect status
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989RxSenseGetStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxRxSense_t *pRxSenseStatus,
++ Bool client /* Used to determine whether the request comes from the application */
++);
++
++/*============================================================================*/
++/**
++ \brief Get one or more hardware I2C register values
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] regPage The device register's page: 00h, 01h, 02h, 11h, 12h
++ \param[in] regAddr The starting register address on the page: 0 to FFh
++ \param[out] pRegBuf Pointer to buffer to receive the register data
++ \param[in] nRegs Number of contiguous registers to read: 1 to 254
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989HwGetRegisters
++(
++ tmUnitSelect_t txUnit,
++ Int regPage,
++ Int regAddr,
++ UInt8 *pRegBuf,
++ Int nRegs
++);
++
++/*============================================================================*/
++/**
++ \brief Get the transmitter device version read at initialization
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] puDeviceVersion Pointer to returned hardware version
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989HwGetVersion
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *puDeviceVersion
++);
++
++
++/**
++ \brief Get the transmitter device feature read at initialization
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] deviceFeature Hardware feature to check
++ \param[out] pFeatureSupported Hardware feature supported or not
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989HwGetCapabilities
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHwFeature_t deviceCapability,
++ Bool *pFeatureSupported
++);
++
++
++/*============================================================================*/
++/**
++ \brief Handle all hardware interrupts from a transmitter unit
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ \note This function must be called at task level not interrupt level,
++ as I2C access is required
++ */
++tmErrorCode_t
++tmbslTDA9989HwHandleInterrupt
++(
++ tmUnitSelect_t txUnit
++);
++
++
++/*============================================================================*/
++/**
++ \brief Set one or more hardware I2C registers
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] regPage The device register's page: 00h, 01h, 02h, 11h, 12h
++ \param[in] regAddr The starting register address on the page: 0 to FFh
++ \param[in] pRegBuf Ptr to buffer from which to write the register data
++ \param[in] nRegs Number of contiguous registers to write: 0 to 254.
++ The page register (255) may not be written - it is
++ written to automatically here. If nRegs is 0, the
++ page register is the only register written.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989HwSetRegisters
++(
++ tmUnitSelect_t txUnit,
++ Int regPage,
++ Int regAddr,
++ UInt8 *pRegBuf,
++ Int nRegs
++);
++
++
++/*============================================================================*/
++/**
++ \brief Handle hardware startup by resetting Device Instance Data
++ */
++void
++tmbslTDA9989HwStartup
++(
++ void
++);
++
++/**
++ \brief Create an instance of an HDMI Transmitter: initialize the
++ driver, reset the transmitter device and get the current
++ Hot Plug state
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uHwAddress Device I2C slave address
++ \param[in] sysFuncWrite System function to write I2C
++ \param[in] sysFuncRead System function to read I2C
++ \param[in] sysFuncEdidRead System function to read EDID blocks via I2C
++ \param[in] sysFuncTimer System function to run a timer
++ \param[in] funcIntCallbacks Pointer to interrupt callback function list
++ The list pointer is null for no callbacks;
++ each pointer in the list may also be null.
++ \param[in] bEdidAltAddr Use alternative i2c address for EDID data
++ register between Driver and TDA9983/2:
++ 0 - use default address (A0)
++ 1 - use alternative address (A2)
++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change
++ \param[in] pixRate Single data (repeated or not) or double data rate
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the transmitter instance is already initialised
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already
++ initialised
++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable
++ with the internal device version code
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989Init
++(
++ tmUnitSelect_t txUnit,
++ UInt8 uHwAddress,
++ ptmbslHdmiTxSysFunc_t sysFuncWrite,
++ ptmbslHdmiTxSysFunc_t sysFuncRead,
++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead,
++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer,
++ tmbslHdmiTxCallbackList_t *funcIntCallbacks,
++ Bool bEdidAltAddr,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxPixRate_t pixRate
++);
++
++/**
++ \brief Set colour space converter matrix coefficients
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pMatCoeff Pointer to Matrix Coefficient structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note Matrix Coefficient parameter structure:
++ Int16 Coeff[9]: Array of coefficients (values -1024 to +1023)
++ */
++tmErrorCode_t
++tmbslTDA9989MatrixSetCoeffs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatCoeff_t *pMatCoeff
++);
++
++/**
++ \brief Set colour space conversion using preset values
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] vinFmt Input video format
++ \param[in] vinMode Input video mode
++ \param[in] voutFmt Output video format
++ \param[in] voutMode Output video mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989MatrixSetConversion
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVoutMode_t voutMode,
++ tmbslHdmiTxVQR_t dviVqr
++);
++
++/**
++ \brief Set colour space converter matrix offset at input
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pMatOffset Pointer to Matrix Offset structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \note Matrix Offset structure parameter structure:
++ Int16 Offset[3]: Offset array (values -1024 to +1023)
++ */
++tmErrorCode_t
++tmbslTDA9989MatrixSetInputOffset
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatOffset_t *pMatOffset
++);
++
++/**
++ \brief Set colour space converter matrix mode
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] mControl Matrix Control: On, Off, No change
++ \param[in] mScale Matrix Scale Factor: 1/256, 1/512, 1/1024, No change
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \note NA
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989MatrixSetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxmCntrl_t mControl,
++ tmbslHdmiTxmScale_t mScale
++);
++
++/*============================================================================*/
++/**
++ \brief Set colour space converter matrix offset at output
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pMatOffset Pointer to Matrix Offset structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \note Matrix Offset parameter structure:
++ nt16 Offset[3]: Offset array (values -1024 to +1023)
++ */
++tmErrorCode_t
++tmbslTDA9989MatrixSetOutputOffset
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatOffset_t *pMatOffset
++);
++
++/*============================================================================*/
++/**
++ \brief Enable audio clock recovery packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: when in DVI mode
++
++ \note tmbslTDA9989AudioInSetCts sets CTS and N values
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetAclkRecovery
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable
++);
++
++/**
++ \brief Set audio content protection packet & enable/disable packet
++ insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Data Island Packet structure
++ \param[in] byteCnt Packet buffer byte count
++ \param[in] uAcpType Content protection type
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Data Island Packet parameter structure:
++ UInt8 dataByte[28] Packet Data
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetAcp
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ UInt8 uAcpType,
++ Bool bEnable
++);
++
++/**
++ \brief Set audio info frame packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Audio Infoframe structure
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Audio Infoframe structure:
++ UInt8 CodingType
++ UInt8 ChannelCount
++ UInt8 SampleFreq
++ UInt8 SampleSize
++ UInt8 ChannelAlloc
++ Bool DownMixInhibit
++ UInt8 LevelShift
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetAudioInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktAif_t *pPkt,
++ Bool bEnable
++);
++
++
++/*============================================================================*/
++/**
++ \brief Set contents of general control packet & enable/disable
++ packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] paMute Pointer to Audio Mute; if Null, no change to packet
++ contents is made
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note tmbslTDA9989AudioOutSetMute must be used to mute the audio output
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetGeneralCntrl
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaMute_t *paMute,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Set ISRC1 packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Data Island Packet structure
++ \param[in] byteCnt Packet buffer byte count
++ \param[in] bIsrcCont ISRC continuation flag
++ \param[in] bIsrcValid ISRC valid flag
++ \param[in] uIsrcStatus ISRC Status
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Data Island Packet parameter structure:
++ UInt8 dataByte[28] Packet Data
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetIsrc1
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ Bool bIsrcCont,
++ Bool bIsrcValid,
++ UInt8 uIsrcStatus,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Set ISRC2 packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Data Island Packet structure
++ \param[in] byteCnt Packet buffer byte count
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Data Island Packet parameter structure:
++ UInt8 dataByte[28] Packet Data
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetIsrc2
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ Bool bEnable
++);
++
++/**
++ \brief Set MPEG infoframe packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to MPEG Infoframe structure
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note MPEG Infoframe structure:
++ UInt32 bitRate
++ tmbslHdmiTxMpegFrame_t frameType
++ Bool bFieldRepeat
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetMpegInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktMpeg_t *pPkt,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Enable NULL packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetNullInsert
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Set single Null packet insertion (flag auto-resets after
++ transmission)
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Operation resets after single transmission
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetNullSingle
++(
++ tmUnitSelect_t txUnit
++);
++
++/**
++ \brief Set audio info frame packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Audio Infoframe structure
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Audio Infoframe structure:
++ UInt8 VendorName[8]
++ UInt8 ProdDescr[16]
++ tmbslHdmiTxSourceDev_t SourceDevInfo
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetSpdInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktSpd_t *pPkt,
++ Bool bEnable
++);
++
++/**
++ \brief Set video infoframe packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Video Infoframe structure
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Video Infoframe structure:
++ UInt8 Colour
++ Bool ActiveInfo
++ UInt8 BarInfo
++ UInt8 ScanInfo
++ UInt8 Colorimetry
++ UInt8 PictureAspectRatio
++ UInt8 ActiveFormatRatio
++ UInt8 Scaling
++ UInt8 VidFormat
++ UInt8 PixelRepeat
++ UInt16 EndTopBarLine
++ UInt16 StartBottomBarLine
++ UInt16 EndLeftBarPixel
++ UInt16 StartRightBarPixel (incorrectly named in [HDMI1.2])
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetVideoInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktVif_t *pPkt,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Set Vendor Specific Infoframe packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to Data Island Packet structure
++ \param[in] byteCnt Packet buffer byte count
++ \param[in] uVersion Version number for packet header
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: pointer suppied with byte count of zero
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: not possible with this device
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Data Island Packet parameter structure:
++ UInt8 dataByte[28] Packet Data (only use 27 bytes max)
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989PktSetVsInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ UInt8 uVersion,
++ Bool bEnable
++);
++
++/*============================================================================*/
++/**
++ \brief Set raw video Infoframe packet & enable/disable packet insertion
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pPkt Pointer to raw Packet structure
++ \param[in] bEnable Enable or disable packet insertion
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++ \note Data Island Packet parameter structure:
++ UInt8 dataByte[28] Packet Data
++
++ \sa NA
++ */
++tmErrorCode_t tmbslTDA9989PktSetRawVideoInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktRawAvi_t *pPkt,
++ Bool bEnable
++);
++
++
++/*============================================================================*/
++/**
++ \brief Get the power state of the transmitter
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pePowerState Pointer to the power state of the device now
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++ \note Power states:
++ - tmPowerOn
++ - tmPowerStandby
++ */
++tmErrorCode_t
++tmbslTDA9989PowerGetState
++(
++ tmUnitSelect_t txUnit,
++ tmPowerState_t *pePowerState
++);
++
++/*============================================================================*/
++/**
++ \brief Set the power state of the transmitter
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] ePowerState Power state to set
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note Power states (Off and Suspend are treated the same as Standby):
++ - tmPowerOn
++ - tmPowerStandby
++ - tmPowerSuspend
++ - tmPowerOff
++ */
++tmErrorCode_t
++tmbslTDA9989PowerSetState
++(
++ tmUnitSelect_t txUnit,
++ tmPowerState_t ePowerState
++);
++
++
++/*============================================================================*/
++/**
++ \brief Reset the HDMI transmitter
++
++ \param[in] txUnit Transmitter unit number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note NA
++
++ \sa tmbslTDA9989Init
++ */
++tmErrorCode_t
++tmbslTDA9989Reset
++(
++ tmUnitSelect_t txUnit
++);
++
++/**
++ \brief Get diagnostic counters from the scaler
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pScalerDiag Pointer to structure to receive scaler diagnostic
++ registers
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++
++ \note scaler diagnostic registers structure:
++ UInt16 maxBuffill_p Filling primary video buffer
++ UInt16 maxBuffill_d Filling video deinterlaced buffer
++ UInt8 maxFifofill_pi Filling primary video input FIFO
++ UInt8 minFifofill_po1 Filling primary video output FIFO #1
++ UInt8 minFifofill_po2 Filling primary video output FIFO #2
++ UInt8 minFifofill_po3 Filling primary video output FIFO #3
++ UInt8 minFifofill_po4 Filling primary video output FIFO #4
++ UInt8 maxFifofill_di Filling deinterlaced video input FIFO
++ UInt8 maxFifofill_do Filling deinterlaced video output FIFO
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerGet
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScalerDiag_t *pScalerDiag
++);
++
++
++
++/**
++ \brief Get the current scaler mode
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[out] pScalerMode Pointer to variable to receive scaler mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++*/
++tmErrorCode_t
++tmbslTDA9989ScalerGetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScaMode_t *pScalerMode
++);
++
++
++/*============================================================================*/
++/**
++ \brief Enable or disable scaler input frame
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bDisable Enable or disable scaler input
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerInDisable
++(
++ tmUnitSelect_t txUnit,
++ Bool bDisable
++);
++
++/**
++ \brief Set the active coefficient lookup table for the vertical scaler
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] lutSel Coefficient lookup table selection
++ \param[in] pVsLut Table of HDMITX_VSLUT_COEFF_NUM coefficient values
++ (may be null if lutSel not HDMITX_SCALUT_USE_VSLUT)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: two parameters disagree
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerSetCoeffs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScaLut_t lutSel,
++ UInt8 *pVsLut
++);
++
++/**
++ \brief Set scaler field positions
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] topExt Internal, External, No Change
++ \param[in] deExt Internal, External, No Change
++ \param[in] topSel Internal, VRF, No Change
++ \param[in] topTgl No Action, Toggle, No Change
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerSetFieldOrder
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxIntExt_t topExt,
++ tmbslHdmiTxIntExt_t deExt,
++ tmbslHdmiTxTopSel_t topSel,
++ tmbslHdmiTxTopTgl_t topTgl
++);
++
++/**
++ \brief Set scaler fine adjustment options
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uRefPix Ref. pixel preset 0 to 1FFFh (2000h = No Change)
++ \param[in] uRefLine Ref. line preset 0 to 7FFh (800h = No Change)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerSetFine
++(
++ tmUnitSelect_t txUnit,
++ UInt16 uRefPix,
++ UInt16 uRefLine
++);
++
++/**
++ \brief Set scaler phase for scaling 1080p
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] tmbslHdmiTxHPhases_t Ref. 0 to 15_horizontal_phases 1 to 16_horizontal_phases
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++
++tmErrorCode_t
++tmbslTDA9989ScalerSetPhase
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHPhases_t horizontalPhases
++);
++
++/**
++ \brief configure scaler latency to set run in run out
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] UInt8 Ref. 0 to 255
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerSetLatency
++(
++ tmUnitSelect_t txUnit,
++ UInt8 scaler_latency
++);
++
++/**
++ \brief Set scaler synchronization options
++ On a TDA9989 this function is not supported and
++ return result TMBSL_ERR_HDMI_NOT_SUPPORTED
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] method Sync. combination method
++ \param[in] once Line/pixel counters sync once or each frame
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989ScalerSetSync
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVsMeth_t method,
++ tmbslHdmiTxVsOnce_t once
++);
++
++
++/*============================================================================*/
++/**
++ \brief Get the driver software version and compatibility numbers
++
++ \param[out] pSWVersion Pointer to the software version structure returned
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989SwGetVersion
++(
++ ptmSWVersion_t pSWVersion
++);
++
++
++/*============================================================================*/
++/**
++ \brief Get the driver software version and compatibility numbers
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] waitMs Period in milliseconds to wait
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989SysTimerWait
++(
++ tmUnitSelect_t txUnit,
++ UInt16 waitMs
++);
++
++/**
++ \brief Set the TMDS outputs to normal active operation or to a forced
++ state
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] tmdsOut TMDS output mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989TmdsSetOutputs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTmdsOut_t tmdsOut
++);
++
++/**
++ \brief Fine-tune the TMDS serializer
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uPhase2 Serializer phase 2
++ \param[in] uPhase3 Serializer phase 3
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ */
++tmErrorCode_t
++tmbslTDA9989TmdsSetSerializer
++(
++ tmUnitSelect_t txUnit,
++ UInt8 uPhase2,
++ UInt8 uPhase3
++);
++
++/**
++ \brief Set a colour bar test pattern
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pattern Test pattern
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989TestSetPattern
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTestPattern_t pattern
++);
++
++/**
++ \brief Set or clear one or more simultaneous test modes
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] testMode Mode: tst_pat, tst_656, tst_serphoe, tst_nosc,
++ tst_hvp, tst_pwd, tst_divoe
++ \param[in] testState State: 1=On, 0=Off
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989TestSetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTestMode_t testMode,
++ tmbslHdmiTxTestState_t testState
++);
++
++/**
++ \brief Enable blanking between active data
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] blankitSource Blankit Source: Not DE, VS And HS,
++ VS And Not HS, Hemb And Vemb, No Change
++ \param[in] blankingCodes Blanking Codes: All Zero, RGB444, YUV444,
++ YUV422, No Change
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note NA
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetBlanking
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxBlnkSrc_t blankitSource,
++ tmbslHdmiTxBlnkCode_t blankingCodes
++);
++
++/**
++ \brief Configure video input options and control the upsampler
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] vinMode Video input mode
++ \param[in] voutFmt EIA/CEA Video output format: 1 to 31, 0 = No Change
++ \param[in] sampleEdge Sample edge:
++ Pixel Clock Positive Edge,
++ Pixel Clock Negative Edge, No Change
++ \param[in] pixRate Single data or double data rate
++ \param[in] upsampleMode Upsample mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D,
++ tmbslHdmiTxPixEdge_t sampleEdge,
++ tmbslHdmiTxPixRate_t pixRate,
++ tmbslHdmiTxUpsampleMode_t upsampleMode
++);
++
++/**
++ \brief Set fine image position
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] subpacketCount Subpacket Count fixed values and sync options
++ \param[in] toggleClk1 Toggle clock 1 phase w.r.t. clock 2
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note NA
++
++ \sa NA
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetFine
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPixSubpkt_t subpacketCount,
++ tmbslHdmiTxPixTogl_t toggleClk1
++);
++
++/**
++ \brief Set video input port swapping and mirroring
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pSwapTable Pointer to 6-byte port swap table
++ \param[in] pMirrorTable Pointer to 6-byte port mirror table
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note UInt8 pSwapTable[6]
++
++ Each table position 0 to 5 represents a group of 4 port bits:
++ [0]=23:20, [1]=16:19, [2]=15:12, [3]=11:8, [4]=4:7, [5]=0:3
++ Table position values are 0 to 6, denoting the group of 4 port
++ bits to swap to: 0=23:20, 1=16:19, 2=15:12, 3=11:8, 4=4:7, 5=0:3.
++ For example, to swap port bits 15:12 to bits 4:7: pSwapTable[2]=4
++
++ UInt8 pMirrorTable[6]
++
++ Each table position 0 to 5 represents a group of 4 port bits:
++ [0]=23:20, [1]=16:19, [2]=15:12, [3]=11:8, [4]=4:7, [5]=0:3.
++ Cell values are 0 to 2 (Not Mirrored, Mirrored, No Change).
++ For example, to mirror port bits 11:8 to bits 8:11:
++ pMirrorTable[3]=1.
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetMapping
++#ifdef TMFL_RGB_DDR_12BITS
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pSwapTable,
++ UInt8 *pMirrorTable,
++ UInt8 *pMux
++);
++#else
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pSwapTable,
++ UInt8 *pMirrorTable
++);
++#endif
++/**
++ \brief Set video input port (enable, ground)
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pEnaVideoPortTable Pointer to 3-byte video port enable table
++ \param[in] pGndVideoPortTable Pointer to 3-byte video port ground table
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note UInt8 pEnaVideoPortTable[3]
++
++ Each table position 0 to 2 represents a group of 8 port bits:
++ [0]=7:0, [1]=15:8, [2]=23:16
++ bitn = '1' means enable port n
++ bitn = '0' means disable port n
++ For example, to enable port 0 to 7 only : pEnaVideoPortTable[0]= 0xFF
++ pEnaVideoPortTable[1]= 0x00, pEnaVideoPortTable[2]= 0x00
++
++ UInt8 pGndVideoPortTable[3]
++
++ Each table position 0 to 2 represents a group of 8 port bits:
++ [0]=7:0, [1]=15:8, [2]=23:16
++ bitn = '1' means pulldown port n
++ bitn = '0' means not pulldown port n
++ For example, to pulldown port 8 to 15 only : pEnaVideoPortTable[0]= 0x00
++ pEnaVideoPortTable[1]= 0xFF, pEnaVideoPortTable[2]= 0x00
++ */
++tmErrorCode_t
++tmbslTDA9989SetVideoPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaVideoPortTable,
++ UInt8 *pGndVideoPortTable
++);
++
++/*============================================================================*/
++/**
++ \brief Set audio input port (enable, ground)
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pEnaAudioPortTable Pointer to 1-byte audio port enable configuration
++ \param[in] pGndAudioPortTable Pointer to 1-byte audio port ground configuration
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note UInt8 pEnaAudioPortTable[1]
++ bitn = '1' means enable port n
++ bitn = '0' means disable port n
++ For example, to enable all audio port (0:7) : pEnaAudioPortTable[0]= 0xFF
++
++ UInt8 pGndAudioPortTable[1]
++ bitn = '1' means pulldown port n
++ bitn = '0' means not pulldown port n
++ For example, to pulldown audio port (0:7) : pEnaAudioPortTable[0]= 0xFF
++*/
++tmErrorCode_t
++tmbslTDA9989SetAudioPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaAudioPortTable,
++ UInt8 *pGndAudioPortTable
++);
++
++/*============================================================================*/
++/**
++ \brief Set audio input Clock port (enable, ground)
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pEnaAudioClockPortTable Pointer to 1-byte audio Clock port enable configuration
++ \param[in] pGndAudioClockPortTable Pointer to 1-byte audio Clock port ground configuration
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++ \note UInt8 pEnaAudioClockPortTable[1]
++ bitn = '1' means enable port n
++ bitn = '0' means disable port n
++ For example, to enable all audio Clock port (0) : pEnaAudioPortTable[0]= 0x01
++
++ UInt8 pGndAudioClockPortTable[1]
++ bitn = '1' means pulldown port n
++ bitn = '0' means not pulldown port n
++ For example, to pulldown audio Clock port (0:7) : pEnaAudioPortTable[0]= 0x01
++*/
++tmErrorCode_t
++tmbslTDA9989SetAudioClockPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaAudioClockPortTable,
++ UInt8 *pGndAudioClockPortTable
++);
++
++/**
++ \brief Configure video input sync automatically
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] syncSource Sync Source:
++ Embedded, External Vref, External Vs
++ No Change
++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change
++ \param[in] vinMode Input video mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetSyncAuto
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSyncSource_t syncSource,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTx3DStructure_t structure3D
++);
++
++/**
++ \brief Configure video input sync with manual parameters
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] syncSource Sync Source:
++ Embedded, External Vref, External Vs
++ No Change
++ \param[in] syncMethod Sync method: V And H, V And X-DE, No Change
++ \param[in] toggleV VS Toggle:
++ No Action, Toggle VS/Vref, No Change
++ \param[in] toggleH HS Toggle:
++ No Action, Toggle HS/Href, No Change
++ \param[in] toggleX DE/FREF Toggle:
++ No Action, Toggle DE/Fref, No Change
++ \param[in] uRefPix Ref. pixel preset 0 to 1FFFh (2000h = No Change)
++ \param[in] uRefLine Ref. line preset 0 to 7FFh (800h = No Change)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoInSetSyncManual
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSyncSource_t syncSource,
++ tmbslHdmiTxVsMeth_t syncMethod,
++ tmbslHdmiTxPixTogl_t toggleV,
++ tmbslHdmiTxPixTogl_t toggleH,
++ tmbslHdmiTxPixTogl_t toggleX,
++ UInt16 uRefPix,
++ UInt16 uRefLine
++);
++
++
++/*============================================================================*/
++/**
++ \brief Enable or disable output video frame
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bDisable Enable or disable scaler input
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoOutDisable
++(
++ tmUnitSelect_t txUnit,
++ Bool bDisable
++);
++
++/**
++ \brief Configure sink type, configure video output colour and
++ quantization, control the downsampler, and force RGB output
++ and mute audio in DVI mode
++
++ \param[in] txUnit Transmitter unit number:
++ \param[in] sinkType Sink device type: DVI or HDMI or copy from EDID
++ \param[in] voutMode Video output mode
++ \param[in] preFilter Prefilter: Off, 121, 109, CCIR601, No Change
++ \param[in] yuvBlank YUV blanking: 16, 0, No Change
++ \param[in] quantization Video quantization range:
++ Full Scale, RGB Or YUV, YUV, No Change
++
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoOutSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkType_t sinkType,
++ tmbslHdmiTxVoutMode_t voutMode,
++ tmbslHdmiTxVoutPrefil_t preFilter,
++ tmbslHdmiTxVoutYuvBlnk_t yuvBlank,
++ tmbslHdmiTxVoutQrange_t quantization
++);
++
++/**
++ \brief Set video synchronization
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] srcH Horizontal sync source: Internal, Exter'l, No Change
++ \param[in] srcV Vertical sync source: Internal, Exter'l, No Change
++ \param[in] srcX X sync source: Internal, Exter'l, No Change
++ \param[in] toggle Sync toggle: Hs, Vs, Off, No Change
++ \param[in] once Line/pixel counters sync once or each frame
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoOutSetSync
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVsSrc_t srcH,
++ tmbslHdmiTxVsSrc_t srcV,
++ tmbslHdmiTxVsSrc_t srcX,
++ tmbslHdmiTxVsTgl_t toggle,
++ tmbslHdmiTxVsOnce_t once
++);
++
++/**
++ \brief Set main video input and output parameters
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] vinFmt EIA/CEA Video input format: 1 to 31, 0 = No Change
++ \param[in] scaMode Scaler mode: Off, On, Auto, No Change
++ On TDA9989, only scaler mode off is possible
++ \param[in] voutFmt EIA/CEA Video output format: 1 to 31, 0 = No Change
++ \param[in] uPixelRepeat Pixel repetition factor: 0 to 9, 10 = default,
++ 11 = no change
++ \param[in] matMode Matrix mode: 0 = off, 1 = auto
++ \param[in] datapathBits Datapath bitwidth: 0 to 3 (8, 10, 12, No Change)
++ \param[in] Desired VQR in dvi mode
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989VideoSetInOut
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTx3DStructure_t structure3D,
++ tmbslHdmiTxScaMode_t scaMode,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTxMatMode_t matMode,
++ tmbslHdmiTxVoutDbits_t datapathBits,
++ tmbslHdmiTxVQR_t dviVqr
++);
++
++/**
++ \brief Use only for debug to flag the software debug interrupt
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uSwInt Interrupt to be generated (not relevant)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++tmErrorCode_t
++tmbslTDA9989FlagSwInt
++(
++ tmUnitSelect_t txUnit,
++ UInt32 uSwInt
++);
++
++
++/**
++ \brief Enable or disable 5v power
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] pwrEnable 5v Power enable(True)/disable(False)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: functionnality not supported by this device
++ */
++tmErrorCode_t
++tmbslTDA9989Set5vpower
++(
++ tmUnitSelect_t txUnit,
++ Bool pwrEnable
++);
++
++/**
++ \brief Enable or disable a callback source
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] callbackSource Callback source
++ \param[in] enable Callback source enable(True)/disable(False)
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: impossible to disable this interrupt
++ */
++tmErrorCode_t
++tmbslTDA9989EnableCallback
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxCallbackInt_t callbackSource,
++ Bool enable
++);
++
++/**
++ \brief Configure the deep color mode
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] colorDepth Number of bits per pixel to be processed
++ \param[in] termEnable Enable transmitter termination
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: mode not supported
++ */
++tmErrorCode_t
++tmbslTDA9989SetColorDepth
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxColorDepth colorDepth,
++ Bool termEnable
++);
++
++/**
++ \brief Configure the default phase for a specific deep color mode
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] bEnable Enable(true)/disable(False) default phase
++ \param[in] colorDepth Concerned deepcolor mode
++ \param[in] videoFormat Number of bits per pixel to be processed
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: functionnality not supported by this device
++ */
++tmErrorCode_t
++tmbslTDA9989SetDefaultPhase
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable,
++ tmbslHdmiTxColorDepth colorDepth,
++ UInt8 videoFormat
++);
++
++
++
++/**
++ \brief Control (Enable/Disable) VS interrupt
++
++ \param[in] txUnit Transmitter unit number
++ \param[in] uIntFlag Enable/Disable VS interrupt
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - Else a problem has been detected:
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ */
++
++tmErrorCode_t
++tmbslTDA9989CtlVsInterrupt
++(
++ tmUnitSelect_t txUnit,
++ Bool uIntFlag
++);
++
++/*============================================================================*/
++/**
++ \brief Fill Gamut metadata packet into one of the gamut HW buffer. this
++ function is not sending any gamut metadata into the HDMI stream,
++ it is only loading data into the HW.
++
++ \param txUnit Transmitter unit number
++ \param pPkt pointer to the gamut packet structure
++ \param bufSel number of the gamut buffer to fill
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C
++ bus
++
++ ******************************************************************************/
++tmErrorCode_t tmbslTDA9989PktFillGamut
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktGamut_t *pPkt,
++ UInt8 bufSel
++);
++
++/*============================================================================*/
++/**
++ \brief Enable transmission of gamut metadata packet. Calling this function
++ tells HW which gamut buffer to send into the HDMI stream. HW will
++ only take into account this command at the next VS, not during the
++ current one.
++
++ \param txUnit Transmitter unit number
++ \param bufSel Number of the gamut buffer to be sent
++ \param enable Enable/disable gamut packet transmission
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C
++ bus
++
++ ******************************************************************************/
++tmErrorCode_t tmbslTDA9989PktSendGamut
++(
++ tmUnitSelect_t txUnit,
++ UInt8 bufSel,
++ Bool bEnable
++);
++
++
++/**
++ \brief Return the category of equipement connected
++
++ \param txUnit Transmitter unit number
++ \param category return category type
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started
++
++*/
++tmErrorCode_t tmbslTDA9989HdcpGetSinkCategory
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkCategory_t *category
++);
++
++
++/**
++ \brief Return the sink latency information if any
++
++ \param txUnit Transmitter unit number
++ \param pEdidLatency latency data structure to return
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started
++
++*/
++tmErrorCode_t tmbslTDA9989EdidGetLatencyInfo
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidLatency_t * pEdidLatency
++);
++
++
++/**
++ \brief Return the sink additional VSDB data information if any
++
++ \param txUnit Transmitter unit number
++ \param p3Ddata 3D data structure to return
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE hdcp not started
++
++*/
++tmErrorCode_t tmbslTDA9989EdidGetExtraVsdbData
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidExtraVsdbData_t **pExtraVsdbData
++);
++
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++/**
++ \brief Optimized power by frozing useless clocks related to HDCP
++
++ \param txUnit Transmitter unit number
++ \param request power down request
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_HDMI_INCONSISTENT_PARAMS: params are inconsistent
++
++*/
++tmErrorCode_t
++tmbslTDA9989HdcpPowerDown
++(
++ tmUnitSelect_t txUnit,
++ Bool requested
++);
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_FUNCTIONS_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c
+new file mode 100755
+index 0000000..488b950
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid.c
+@@ -0,0 +1,1572 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_edid.c
++ *
++ * \version $Revision: 2 $
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++#include "tmbslTDA9989_State_l.h"
++#include "tmbslTDA9989_Edid_l.h"
++
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++#define EDID_NUMBER_MAX_DTD_BLK_1 6
++/** EDID block 0 parse start point */
++#define EDID_BLK0_BASE_DTD 0x36
++
++#define EDID_BLK1_OFFSET_BASE_DTD 2
++
++/** EDID block 0 extension block count */
++#define EDID_BLK0_EXT_CNT 0x7E
++
++/** EDID extension block parse start point */
++#define EDID_BLK_EXT_BASE 0x04
++
++/** CEA extension block type */
++#define EDID_CEA_EXTENSION 0x02
++
++/** CEA Block Map */
++#define EDID_BLOCK_MAP 0xF0
++
++/** NB Max of descriptor DTD or monitor in block 0 */
++#define EDID_NB_MAX_DESCRIP_BLK_IN_BLK_0 4
++
++#define EDID_MONITOR_NAME_DESC_DATA_TYPE 252
++
++#define EDID_MONITOR_RANGE_DESC_DATA_TYPE 253
++
++/*============================================================================*/
++/* DEFINES DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++static tmErrorCode_t requestEdidBlock(tmHdmiTxobject_t *pDis);
++
++static tmErrorCode_t parseEdidBlock (tmHdmiTxobject_t *pDis,
++ Int blockNumber);
++static Bool storeDtdBlock (tmHdmiTxobject_t *pDis,
++ UInt8 blockPtr);
++
++static Bool storeMonitorDescriptor (tmHdmiTxobject_t *pDis,
++ UInt8 blockPtr);
++
++
++
++/*============================================================================*/
++/* tmbslTDA9989HwGetCapabilities */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HwGetCapabilities
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHwFeature_t deviceCapability,
++ Bool *pFeatureSupported
++ )
++{
++ tmHdmiTxobject_t *pDis;
++ tmErrorCode_t err = TM_OK;
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ RETIF_BADPARAM(pFeatureSupported == Null)
++
++ *pFeatureSupported = False;
++
++
++ switch (deviceCapability)
++ {
++ case HDMITX_FEATURE_HW_HDCP:
++ if((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_h) == 0)
++ {
++ *pFeatureSupported = True;
++ }
++ break;
++ case HDMITX_FEATURE_HW_SCALER:
++ if((pDis->uDeviceFeatures & E_MASKREG_P00_VERSION_not_s) == 0)
++ {
++ *pFeatureSupported = True;
++ }
++ break;
++ case HDMITX_FEATURE_HW_AUDIO_OBA:
++ *pFeatureSupported = True;
++ break;
++ case HDMITX_FEATURE_HW_AUDIO_DST:
++ *pFeatureSupported = False;
++ break;
++ case HDMITX_FEATURE_HW_AUDIO_HBR:
++ *pFeatureSupported = False;
++ break;
++ case HDMITX_FEATURE_HW_HDMI_1_1:
++ *pFeatureSupported = True;
++ break;
++ case HDMITX_FEATURE_HW_HDMI_1_2A:
++ *pFeatureSupported = True;
++ break;
++ case HDMITX_FEATURE_HW_HDMI_1_3A:
++ *pFeatureSupported = False;
++ break;
++
++ case HDMITX_FEATURE_HW_DEEP_COLOR_30:
++ *pFeatureSupported = False;
++ break;
++
++ case HDMITX_FEATURE_HW_DEEP_COLOR_36:
++ *pFeatureSupported = False;
++ break;
++
++ case HDMITX_FEATURE_HW_DEEP_COLOR_48:
++ *pFeatureSupported = False;
++ break;
++
++ case HDMITX_FEATURE_HW_UPSAMPLER:
++ *pFeatureSupported = True;
++ break;
++
++ case HDMITX_FEATURE_HW_DOWNSAMPLER:
++ *pFeatureSupported = True;
++ break;
++
++ case HDMITX_FEATURE_HW_COLOR_CONVERSION:
++ *pFeatureSupported = True;
++ break;
++
++ default:
++ *pFeatureSupported = False;
++ break;
++ }
++
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetAudioCapabilities */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetAudioCapabilities
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidSad_t *pEdidAFmts,
++ UInt aFmtLength,
++ UInt *pAFmtsAvail,
++ UInt8 *pAudioFlags
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt i; /* Loop index */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidAFmts == Null)
++ RETIF_BADPARAM(aFmtLength < 1)
++ RETIF_BADPARAM(pAFmtsAvail == Null)
++ RETIF_BADPARAM(pAudioFlags == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ /* Copy the Device Instance Structure EdidAFmts descriptors to
++ * pEdidAFmts until we run out or no more space in structure.
++ */
++ if (pDis->EdidSadCnt > 0)
++ {
++ for (i = 0; (i < (UInt)pDis->EdidSadCnt) && (i < aFmtLength); i++)
++ {
++ pEdidAFmts[i].ModeChans = pDis->EdidAFmts[i].ModeChans;
++ pEdidAFmts[i].Freqs = pDis->EdidAFmts[i].Freqs;
++ pEdidAFmts[i].Byte3 = pDis->EdidAFmts[i].Byte3;
++ }
++ }
++ else
++ {
++ /* No pEdidAFmts to copy so set a zero format to be safe */
++ pEdidAFmts[0].ModeChans = 0;
++ pEdidAFmts[0].Freqs = 0;
++ pEdidAFmts[0].Byte3 = 0;
++ }
++
++ /* Fill Audio Flags parameter */
++ *pAudioFlags = ((pDis->EdidCeaFlags & 0x40) << 1); /* Basic audio */
++ if (pDis->EdidSinkAi == True)
++ {
++ *pAudioFlags += 0x40; /* Mask in AI support */
++ }
++
++ /* Fill number of SADs available parameter */
++ *pAFmtsAvail = pDis->EdidSadCnt;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetBlockCount */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetBlockCount
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *puEdidBlockCount
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(puEdidBlockCount == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++ *puEdidBlockCount = pDis->EdidBlockCnt;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetStatus */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetStatus
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *puEdidStatus
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(puEdidStatus == Null)
++
++ if (puEdidStatus)
++ {
++ *puEdidStatus = pDis->EdidStatus;
++ }
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidRequestBlockData */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidRequestBlockData
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pRawEdid,
++ Int numBlocks, /* Only relevant if pRawEdid valid */
++ Int lenRawEdid /* Only relevant if pRawEdid valid */
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regval; /* Byte value write to register */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++ if ( (pDis->vinFmt == HDMITX_VFMT_16_1920x1080p_60Hz) || (pDis->vinFmt == HDMITX_VFMT_31_1920x1080p_50Hz)) {
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_PLL_SERIAL_3_RW,
++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir,
++ 0x01);
++ RETIF_REG_FAIL(err)
++
++ }
++
++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /* RAM on */
++ setHwRegisterField(pDis, E_REG_P12_TX4_RW, E_MASKREG_P12_TX4_pd_ram, 0);
++#endif
++
++ /* enable edid read */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW,
++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd);
++
++ /* Check remaining parameter(s)
++ * We do allow a null pRawEdid pointer, in which case buffer length is
++ * irrelevant. If pRawEdid pointer is valid, there is no point in
++ * continuing if insufficient space for at least one block.
++ */
++ RETIF_BADPARAM((pRawEdid != Null) && (lenRawEdid < EDID_BLOCK_SIZE))
++ /* Sensible value of numBlocks? */
++ RETIF((pRawEdid != Null) && ((numBlocks < 1) || (numBlocks > 255)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ /* Enough space for the data requested? */
++ RETIF((pRawEdid != Null) && (lenRawEdid < (numBlocks * EDID_BLOCK_SIZE)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++
++ /* Read the HPD pin via the hpd_in flag in the first interrupt status
++ * register and return a TMBSL_ERR_HDMI_NULL_CONNECTION error if it is
++ * not set.
++ * We must use the flag in the Device Instance Structure to avoid
++ * clearing pending interrupt flags.
++ */
++ RETIF(pDis->hotPlugStatus != HDMITX_HOTPLUG_ACTIVE,
++ TMBSL_ERR_HDMI_NULL_CONNECTION)
++
++ if (pDis->EdidReadStarted == False)
++ {
++
++ /* Reset the EdidStatus in the Device Instance Structure */
++ pDis->EdidStatus = HDMITX_EDID_NOT_READ;
++
++ pDis->EdidReadStarted = True;
++
++ /* Reset stored parameters from EDID in the Device Instance Structure */
++ pDis->EdidSinkType = HDMITX_SINK_DVI;
++ pDis->EdidSinkAi = False;
++ pDis->EdidCeaFlags = 0;
++ pDis->EdidCeaXVYCCFlags = 0;
++ pDis->EdidSvdCnt = 0;
++ pDis->EdidSadCnt = 0;
++ pDis->EdidSourceAddress = 0; /* 0.0.0.0 */
++ pDis->NbDTDStored = 0;
++ pDis->EdidFirstMonitorDescriptor.bDescRecord = False;
++ pDis->EdidSecondMonitorDescriptor.bDescRecord = False;
++ pDis->EdidOtherMonitorDescriptor.bDescRecord = False;
++
++ pDis->EdidLatency.latency_available = False;
++ pDis->EdidLatency.Ilatency_available = False;
++
++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False;
++
++
++ pDis->EdidToApp.pRawEdid = pRawEdid;
++ pDis->EdidToApp.numBlocks = numBlocks;
++
++ /* Enable the T0 interrupt for detecting the Read_EDID failure */
++ regval = E_MASKREG_P00_INT_FLAGS_0_t0 ;
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_0_RW, regval);
++ RETIF(err != TM_OK, err);
++
++
++ /* Launch the read of first EDID block into Device Instance workspace */
++ pDis->EdidBlockRequested = 0;
++ err = requestEdidBlock(pDis);
++ }
++ else
++ {
++ /* Not allowed if read edid is on going */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return err;
++}
++
++
++/*============================================================================*/
++/* EdidBlockAvailable */
++/*============================================================================*/
++
++tmErrorCode_t
++EdidBlockAvailable (tmUnitSelect_t txUnit, Bool * pSendEDIDCallback)
++{
++
++ tmErrorCode_t err; /* Error code */
++ UInt8 chksum; /* Checksum value */
++ UInt8 LoopIndex; /* Loop index */
++ UInt8 extBlockCnt;
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++
++ err = TM_OK;
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pSendEDIDCallback == Null)
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ if (pDis->EdidReadStarted == True)
++ {
++
++ err = tmbslTDA9989HwGetRegisters(txUnit, kPageIndexToPage[E_PAGE_09],
++ SPA2ADDR(E_REG_P09_EDID_DATA_0_R), pDis->EdidBlock, EDID_BLOCK_SIZE);
++ RETIF(err != TM_OK, err)
++
++ if(pSendEDIDCallback)
++ {
++ *pSendEDIDCallback = False;
++ }
++
++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ)
++ {
++ err = getHwRegisters(pDis, E_REG_P09_EDID_DATA_0_R, pDis->EdidBlock,
++ EDID_BLOCK_SIZE);
++ RETIF_REG_FAIL(err)
++
++ /* Add up all the values of the EDID block bytes, including the
++ * checksum byte
++ */
++ chksum = 0;
++ for (LoopIndex = 0; LoopIndex < EDID_BLOCK_SIZE; LoopIndex++)
++ {
++ chksum = chksum + pDis->EdidBlock[LoopIndex];
++ }
++
++ /* IF the EDID block does not yield a checksum of zero
++ */
++ if(chksum != 0)
++ {
++ if (pDis->EdidBlockRequested == 0)
++ {
++ /* THEN return a HDMITX_EDID_ERROR error.*/
++ pDis->EdidStatus = HDMITX_EDID_ERROR_CHK_BLOCK_0;
++ }
++ else
++ {
++ /* THEN return a HDMITX_EDID_ERROR_CHK error.*/
++ pDis->EdidStatus = HDMITX_EDID_ERROR_CHK;
++ }
++ }
++ }
++
++ if (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK_BLOCK_0)
++ {
++ /* PR11 : On i2c error or bad checksum in block 0 */
++ /* allow driver to go in state CONNECTED */
++ /* On the other block, we also accept INVALID_CHECKSUM which means
++ * there was a checksum error */
++
++ if(pSendEDIDCallback)
++ {
++ *pSendEDIDCallback = True;
++ }
++
++ setState(pDis, EV_GETBLOCKDATA);
++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE)
++ {
++ setState(pDis, EV_SINKON);
++ }
++ pDis->EdidReadStarted = False;
++ return err;
++ }
++
++ /* Check if block 0 */
++ if (pDis->EdidBlockRequested == 0)
++ {
++ /* Could check block 0 header (0x00,6 x 0xFF,0x00) here but not
++ * certain to be future proof [CEA861C A.2.3]
++ */
++
++ /* Read block count from penultimate byte of block and store in DIS */
++ extBlockCnt = pDis->EdidBlock[EDID_BLK0_EXT_CNT];
++
++ pDis->EdidBlockCnt = extBlockCnt + 1; /* Total = Block 0 + extensions */
++
++ }
++
++ /* If pointer was supplied, copy block from DIS to buffer */
++ if (pDis->EdidToApp.pRawEdid != Null)
++ {
++ /* Check if we've copied as many as requested yet? */
++ if (pDis->EdidBlockRequested < pDis->EdidToApp.numBlocks)
++ {
++ lmemcpy(pDis->EdidToApp.pRawEdid + (pDis->EdidBlockRequested * EDID_BLOCK_SIZE),
++ pDis->EdidBlock,
++ EDID_BLOCK_SIZE);
++ }
++ }
++ parseEdidBlock(pDis, pDis->EdidBlockRequested);
++
++ /* If extension blocks are present, process them */
++ if ( (pDis->EdidBlockRequested + 1) < pDis->EdidBlockCnt)
++ {
++ pDis->EdidBlockRequested = pDis->EdidBlockRequested + 1;
++ /* Launch an edid block read */
++ err = requestEdidBlock(pDis);
++ }
++ else
++ {
++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ)
++ {
++ pDis->EdidStatus = HDMITX_EDID_READ;
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /* RAM off */
++ setHwRegisterField(pDis, E_REG_P12_TX4_RW, E_MASKREG_P12_TX4_pd_ram, 1);
++#endif
++ }
++
++ if(pSendEDIDCallback)
++ {
++ *pSendEDIDCallback = True;
++ }
++
++ setState(pDis, EV_GETBLOCKDATA);
++
++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE)
++ {
++ setState(pDis, EV_SINKON);
++ }
++ pDis->EdidReadStarted = False;
++ }
++ }
++ else
++ {
++ /* function called in an invalid state */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return err;
++
++}
++
++/*============================================================================*/
++/* ClearEdidRequest */
++/*============================================================================*/
++
++tmErrorCode_t
++ClearEdidRequest (tmUnitSelect_t txUnit)
++{
++
++ tmErrorCode_t err; /* Error code */
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++
++ err = TM_OK;
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++
++ /* Reset the EdidStatus in the Device Instance Structure */
++ pDis->EdidStatus = HDMITX_EDID_NOT_READ;
++
++ pDis->EdidReadStarted = False;
++
++ /* Reset stored parameters from EDID in the Device Instance Structure */
++ pDis->EdidSinkType = HDMITX_SINK_DVI;
++ pDis->EdidSinkAi = False;
++ pDis->EdidCeaFlags = 0;
++ pDis->EdidCeaXVYCCFlags = 0;
++ pDis->EdidSvdCnt = 0;
++ pDis->EdidSadCnt = 0;
++ pDis->EdidSourceAddress = 0; /* 0.0.0.0 */
++ pDis->NbDTDStored = 0;
++ pDis->EdidFirstMonitorDescriptor.bDescRecord = False;
++ pDis->EdidSecondMonitorDescriptor.bDescRecord = False;
++ pDis->EdidOtherMonitorDescriptor.bDescRecord = False;
++
++ pDis->EdidLatency.latency_available = False;
++ pDis->EdidLatency.Ilatency_available = False;
++
++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False;
++
++ /* Launch the read of first EDID block into Device Instance workspace */
++ pDis->EdidBlockRequested = 0;
++
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetSinkType */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetSinkType
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkType_t *pSinkType
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pSinkType == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ *pSinkType = pDis->EdidSinkType;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetSourceAddress */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989EdidGetSourceAddress
++(
++ tmUnitSelect_t txUnit,
++ UInt16 *pSourceAddress
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pSourceAddress == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ *pSourceAddress = pDis->EdidSourceAddress;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetDetailedTimingDescriptors */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetDetailedTimingDescriptors
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidDtd_t *pEdidDTD,
++ UInt8 nb_size,
++ UInt8 *pDTDAvail
++)
++{
++
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidDTD == Null)
++ RETIF_BADPARAM(pDTDAvail == Null)
++ RETIF_BADPARAM(nb_size == 0)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++ if (nb_size > pDis->NbDTDStored)
++ {
++ *pDTDAvail = pDis->NbDTDStored;
++ }
++ else
++ {
++ *pDTDAvail = nb_size;
++ }
++
++ lmemcpy(pEdidDTD, pDis->EdidDTD, sizeof(tmbslHdmiTxEdidDtd_t) * (*pDTDAvail));
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetMonitorDescriptors */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetMonitorDescriptors
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidFirstMD_t *pEdidFirstMD,
++ tmbslHdmiTxEdidSecondMD_t *pEdidSecondMD,
++ tmbslHdmiTxEdidOtherMD_t *pEdidOtherMD,
++ UInt8 sizeOtherMD,
++ UInt8 *pOtherMDAvail
++)
++{
++
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidFirstMD == Null)
++ RETIF_BADPARAM(pEdidSecondMD == Null)
++ RETIF_BADPARAM(pEdidOtherMD == Null)
++
++ DUMMY_ACCESS(pOtherMDAvail);
++ DUMMY_ACCESS(sizeOtherMD);
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ *pOtherMDAvail = 1;
++ lmemcpy(pEdidFirstMD, &(pDis->EdidFirstMonitorDescriptor), sizeof(tmbslHdmiTxEdidFirstMD_t));
++ lmemcpy(pEdidSecondMD, &(pDis->EdidSecondMonitorDescriptor), sizeof(tmbslHdmiTxEdidSecondMD_t));
++ lmemcpy(pEdidOtherMD, &(pDis->EdidOtherMonitorDescriptor), sizeof(tmbslHdmiTxEdidOtherMD_t));
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ *pOtherMDAvail = 0;
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return TM_OK;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetBasicDisplayParam */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetBasicDisplayParam
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidBDParam_t *pEdidBDParam
++)
++{
++
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidBDParam == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ lmemcpy(pEdidBDParam, &(pDis->EDIDBasicDisplayParam), sizeof(tmbslHdmiTxEdidBDParam_t));
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetVideoCapabilities */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetVideoCapabilities
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEdidVFmts,
++ UInt vFmtLength,
++ UInt *pVFmtsAvail,
++ UInt8 *pVidFlags
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt i; /* Loop index */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidVFmts == Null)
++ RETIF_BADPARAM(vFmtLength < 1)
++ RETIF_BADPARAM(pVFmtsAvail == Null)
++ RETIF_BADPARAM(pVidFlags == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ /* Copy the Device Instance Structure EdidVFmts descriptors to
++ * pEdidVFmts until we run out or no more space in structure.
++ */
++ if (pDis->EdidSvdCnt > 0)
++ {
++ for (i = 0; (i < (UInt)pDis->EdidSvdCnt) && (i < vFmtLength); i++)
++ {
++ pEdidVFmts[i] = pDis->EdidVFmts[i];
++ }
++ }
++ else
++ {
++ /* No pEdidVFmts to copy so set a zero format to be safe */
++ pEdidVFmts[0] = HDMITX_VFMT_NULL;
++ }
++
++ /* Fill Video Flags parameter */
++ *pVidFlags = ((pDis->EdidCeaFlags & 0x80) | /* Underscan */
++ ((pDis->EdidCeaFlags & 0x30) << 1) ); /* YUV444, YUV422 */
++
++
++ /* Add info regarding xvYCC support */
++ *pVidFlags = *pVidFlags | (pDis->EdidCeaXVYCCFlags & 0x03);
++
++ /* Fill number of SVDs available parameter */
++ *pVFmtsAvail = pDis->EdidSvdCnt;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetVideoPreferred */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989EdidGetVideoPreferred
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidDtd_t *pEdidDTD
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidDTD == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ /* Populate the Detailed Timing Descriptor structure pEdidDTD from
++ * EdidDtd in the Device Instance Structure.
++ */
++ lmemcpy(pEdidDTD, &pDis->EdidDTD, sizeof(tmbslHdmiTxEdidDtd_t));
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++
++}
++
++
++/*============================================================================*/
++/* STATIC FUNCTION */
++/*============================================================================*/
++
++/*============================================================================*/
++/* requestEdidBlock - reads an entire edid block */
++/*============================================================================*/
++static tmErrorCode_t
++requestEdidBlock
++(
++ tmHdmiTxobject_t *pDis /* Device instance strucure to use */
++ )
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 segptr; /* Segment ptr value */
++ UInt8 offset; /* Word offset value */
++
++ /* Check block number is valid [CEA861C A.2.1] */
++ RETIF_BADPARAM(pDis->EdidBlockRequested >= 255)
++
++ err = setHwRegister(pDis, E_REG_P09_DDC_ADDR_RW, DDC_EDID_ADDRESS);
++ RETIF_REG_FAIL(err)
++
++ /* For even blocks we need an offset of 0, odd blocks we need 128 */
++ offset = (((UInt8)pDis->EdidBlockRequested & 1) == 1) ? 128 : 0;
++
++ err = setHwRegister(pDis, E_REG_P09_DDC_OFFS_RW, offset);
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis, E_REG_P09_DDC_SEGM_ADDR_RW, DDC_SGMT_PTR_ADDRESS);
++ RETIF_REG_FAIL(err)
++
++ /* Calculate which segment of the EDID we need (2 blocks per segment) */
++ segptr = (UInt8)pDis->EdidBlockRequested / 2;
++
++ err = setHwRegister(pDis, E_REG_P09_DDC_SEGM_RW, segptr);
++ RETIF_REG_FAIL(err)
++
++ /* Enable reading EDID */
++ err = setHwRegister(pDis, E_REG_P09_EDID_CTRL_RW, 0x1);
++ RETIF_REG_FAIL(err)
++
++ /* The flag to start the EDID reading must cleared by software*/
++ err = setHwRegister(pDis, E_REG_P09_EDID_CTRL_RW, 0x0);
++ RETIF_REG_FAIL(err)
++
++ return err;
++}
++
++/*============================================================================*/
++/* parseEdidBlock */
++/*============================================================================*/
++static tmErrorCode_t
++parseEdidBlock
++(
++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */
++ Int blockNumber /* Block number */
++ )
++{
++ UInt8 i; /* Loop index */
++ UInt8 blockPtr, endPtr; /* Parsing pointers */
++ UInt8 blockType, blockLength;
++ Bool dtdFound;
++ UInt8 NbBlkRead, offset3D=0;
++
++ /* Check block number is valid [CEA861C A.2.1] */
++ RETIF_BADPARAM(blockNumber >= 255)
++
++ NbBlkRead = 0;
++ dtdFound = True;
++ blockPtr = 0;
++
++ if (blockNumber == 0)
++ {
++ pDis->EDIDBasicDisplayParam.uVideoInputDef = pDis->EdidBlock[0x14];
++ pDis->EDIDBasicDisplayParam.uMaxHorizontalSize = pDis->EdidBlock[0x15];
++ pDis->EDIDBasicDisplayParam.uMaxVerticalSize = pDis->EdidBlock[0x16];
++ pDis->EDIDBasicDisplayParam.uGamma = pDis->EdidBlock[0x17];
++ pDis->EDIDBasicDisplayParam.uFeatureSupport = pDis->EdidBlock[0x18];
++
++ /* Block 0 - contains DTDs but no video data block (SVDs) */
++ for (i = 0; (i < 2) && (dtdFound); i++) /* search 2 possible DTD blocks in block 0 */
++ {
++ blockPtr = (UInt8)(EDID_BLK0_BASE_DTD + (i * EDID_DTD_BLK_SIZE));
++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE)
++ {
++ dtdFound = storeDtdBlock(pDis, blockPtr);
++ if (dtdFound)
++ {
++ NbBlkRead++;
++ }
++ }
++ }
++
++ dtdFound = True;
++
++ /* Parse monitor descriptor */
++ for (i = NbBlkRead; (i < EDID_NB_MAX_DESCRIP_BLK_IN_BLK_0) && (dtdFound); i++)
++ {
++ blockPtr = (UInt8)(EDID_BLK0_BASE_DTD + (i * EDID_DTD_BLK_SIZE));
++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE)
++ {
++ dtdFound = storeMonitorDescriptor(pDis, blockPtr);
++ }
++ }
++ }
++ else if (blockNumber >= 1)
++ {
++ switch (pDis->EdidBlock[0])
++ {
++ /* CEA EXTENSION */
++ case EDID_CEA_EXTENSION:
++ /* Read CEA flag bits here - lockout when read once??? */
++ pDis->EdidCeaFlags = pDis->EdidBlock[3];
++
++ blockPtr = EDID_BLK_EXT_BASE; /* data block start always fixed */
++ endPtr = pDis->EdidBlock[2]; /* byte after end of data blocks */
++ if (endPtr >= (EDID_BLK_EXT_BASE + 2) && (endPtr <= EDID_BLOCK_SIZE))
++ /* Only try reading if data blocks take up 2 bytes or more, since
++ * a video data block must be at least 2 bytes
++ */
++ {
++ while (blockPtr < endPtr)
++ {
++ blockType = (UInt8)((pDis->EdidBlock[blockPtr] & 0xE0) >> 5);
++ blockLength = (pDis->EdidBlock[blockPtr] & 0x1F);
++
++ switch((Int)blockType)
++ {
++ case E_CEA_VIDEO_BLOCK: /* We have a video data block */
++ for (i = 1; i <= blockLength; i++)
++ {
++ if ((blockPtr + i) < (EDID_BLOCK_SIZE))
++ {
++ /* If space, store non-zero SVDs */
++ if ((pDis->EdidBlock[blockPtr + i] != 0) &&
++ (pDis->EdidSvdCnt < HDMI_TX_SVD_MAX_CNT))
++ {
++ pDis->EdidVFmts[pDis->EdidSvdCnt] =
++ pDis->EdidBlock[blockPtr + i];
++ pDis->EdidSvdCnt++;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ break;
++ case E_CEA_AUDIO_BLOCK: /* We have an audio data block */
++ for (i = 1; (i + 2) <= blockLength; i += 3)
++ { /* Must loop in steps of 3 (SAD size) */
++ /* If space, store non-zero SADs */
++ if ((blockPtr) < (EDID_BLOCK_SIZE -(i +2)))
++ {
++ if (((pDis->EdidBlock[blockPtr + i] & 0x78) != 0) &&
++ (pDis->EdidSadCnt < HDMI_TX_SAD_MAX_CNT))
++ {
++ pDis->EdidAFmts[pDis->EdidSadCnt].ModeChans =
++ pDis->EdidBlock[blockPtr + i];
++ pDis->EdidAFmts[pDis->EdidSadCnt].Freqs =
++ pDis->EdidBlock[blockPtr + i + 1];
++ pDis->EdidAFmts[pDis->EdidSadCnt].Byte3 =
++ pDis->EdidBlock[blockPtr + i + 2];
++ pDis->EdidSadCnt++;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ break;
++ case E_CEA_VSDB: /* We have a VSDB */
++ /* 5 bytes expected, but this is EDID land so double check*/
++ if (blockLength >= 5)
++ {
++ if ((blockPtr) < (EDID_BLOCK_SIZE - 5))
++ {
++ if ((pDis->EdidBlock[blockPtr + 1] == 0x03) &&
++ (pDis->EdidBlock[blockPtr + 2] == 0x0C) &&
++ (pDis->EdidBlock[blockPtr + 3] == 0x00))
++ {
++ pDis->EdidSinkType = HDMITX_SINK_HDMI;
++ if ((blockPtr) < (EDID_BLOCK_SIZE - 5))
++ {
++ pDis->EdidSourceAddress =
++ ((UInt16)pDis->EdidBlock[blockPtr + 4] << 8) +
++ pDis->EdidBlock[blockPtr + 5];
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ else
++ {
++ pDis->EdidSinkType = HDMITX_SINK_DVI;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++
++ if (blockLength >= 6) /* Space for byte with AI flag */
++ { /* Mask AI bit */
++ if ((blockPtr ) < (EDID_BLOCK_SIZE - 6))
++ {
++ if((pDis->EdidBlock[blockPtr + 6] & 0x80) == 0x80)
++ {
++ pDis->EdidSinkAi = True;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++
++ /* Read Max_TMDS_Clock */
++ if (blockLength >= 7)
++ pDis->EdidExtraVsdbData.maxTmdsClock = pDis->EdidBlock[blockPtr + 7];
++ else
++ pDis->EdidExtraVsdbData.maxTmdsClock = 0;
++
++
++ /* latency, HDMI Video present and content type fields */
++ if (blockLength >= 8) {
++ if ((blockPtr) < (EDID_BLOCK_SIZE - 10))
++ {
++ /* Read CNC0~3 */
++ pDis->EdidExtraVsdbData.cnc0 = pDis->EdidBlock[blockPtr + 8] & 0x01; /* 1=True, 0=False */
++ pDis->EdidExtraVsdbData.cnc1 = (pDis->EdidBlock[blockPtr + 8] & 0x02) >> 1;
++ pDis->EdidExtraVsdbData.cnc2 = (pDis->EdidBlock[blockPtr + 8] & 0x04) >> 2;
++ pDis->EdidExtraVsdbData.cnc3 = (pDis->EdidBlock[blockPtr + 8] & 0x08) >> 3;
++
++ if( (pDis->EdidBlock[blockPtr + 8] & 0xC0) == 0xC0 ) {
++ /* Read video_latency, audio_latency, I_video_latency, I_audio_latency */
++
++ if ((blockPtr) < (EDID_BLOCK_SIZE - 12))
++ {
++ pDis->EdidLatency.Edidvideo_latency = pDis->EdidBlock[blockPtr + 9];
++ pDis->EdidLatency.Edidaudio_latency = pDis->EdidBlock[blockPtr + 10];
++ pDis->EdidLatency.EdidIvideo_latency = pDis->EdidBlock[blockPtr + 11];
++ pDis->EdidLatency.EdidIaudio_latency = pDis->EdidBlock[blockPtr + 12];
++
++ pDis->EdidLatency.latency_available = True;
++ pDis->EdidLatency.Ilatency_available = True;
++
++ offset3D = 13; /* offset to the '3D_present' field */
++
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ else if ((pDis->EdidBlock[blockPtr + 8] & 0x80) == 0x80) {
++ /* Read video_latency, audio_latency */
++
++ pDis->EdidLatency.Edidvideo_latency = pDis->EdidBlock[blockPtr + 9];
++ pDis->EdidLatency.Edidaudio_latency = pDis->EdidBlock[blockPtr + 10];
++
++ pDis->EdidLatency.latency_available = True;
++
++ offset3D = 11;
++ }
++ else {
++ pDis->EdidLatency.latency_available = False;
++ pDis->EdidLatency.Ilatency_available = False;
++ offset3D = 9;
++ }
++
++ /* Read HDMI_Video_present */
++ pDis->EdidExtraVsdbData.hdmiVideoPresent = (pDis->EdidBlock[blockPtr + 8] & 0x20) >> 5;
++
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ else {
++ pDis->EdidLatency.latency_available = False;
++ pDis->EdidLatency.Ilatency_available = False;
++ pDis->EdidExtraVsdbData.hdmiVideoPresent = False;
++ pDis->EdidExtraVsdbData.cnc0 = False;
++ pDis->EdidExtraVsdbData.cnc1 = False;
++ pDis->EdidExtraVsdbData.cnc2 = False;
++ pDis->EdidExtraVsdbData.cnc3 = False;
++ }
++
++
++ /* 3D data fields according to HDMI 1.4a standard */
++ if (pDis->EdidExtraVsdbData.hdmiVideoPresent) {
++
++ /* read 3D_present */
++ pDis->EdidExtraVsdbData.h3DPresent = (pDis->EdidBlock[blockPtr + offset3D] & 0x80) >> 7;
++ /* read 3D_Multi_present */
++ pDis->EdidExtraVsdbData.h3DMultiPresent = (pDis->EdidBlock[blockPtr + offset3D] & 0x60) >> 5;
++ /* read image_Size */
++ pDis->EdidExtraVsdbData.imageSize = (pDis->EdidBlock[blockPtr + offset3D] & 0x18) >> 3;
++
++ /* read HDMI_3D_LEN and HDMI_XX_LEN */
++ offset3D += 1;
++ pDis->EdidExtraVsdbData.hdmi3DLen = pDis->EdidBlock[blockPtr + offset3D] & 0x1F;
++ pDis->EdidExtraVsdbData.hdmiVicLen = (pDis->EdidBlock[blockPtr + offset3D] & 0xE0) >> 5;
++
++ if((pDis->EdidExtraVsdbData.hdmi3DLen + pDis->EdidExtraVsdbData.hdmiVicLen) > 0)
++ {
++ /* copy the rest of the bytes*/
++ lmemcpy(pDis->EdidExtraVsdbData.ext3DData, &(pDis->EdidBlock[blockPtr + offset3D + 1]), blockLength-offset3D);
++ }
++ }
++ else {
++ pDis->EdidExtraVsdbData.h3DPresent = False;
++ pDis->EdidExtraVsdbData.h3DMultiPresent = 0;
++ pDis->EdidExtraVsdbData.imageSize = 0;
++ pDis->EdidExtraVsdbData.hdmi3DLen = 0;
++ pDis->EdidExtraVsdbData.hdmiVicLen = 0;
++ }
++
++
++ break;
++
++
++ case E_CEA_EXTENDED: /* Use extended Tag */
++
++ /* we need to read the extended tag code */
++
++ if ((blockPtr ) < (EDID_BLOCK_SIZE -2))
++ {
++ switch ( pDis->EdidBlock[blockPtr + 1])
++ {
++ case EXT_CEA_COLORIMETRY_DB:
++
++ /* look at xvYCC709 and xvYCC601 support */
++ pDis->EdidCeaXVYCCFlags = pDis->EdidBlock[blockPtr + 2];
++
++ break;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ break; /* E_CEA_EXTENDED */
++
++
++
++ default:
++ break;
++ }
++ blockPtr += (blockLength + 1); /* Point to next block */
++ }
++ }
++ dtdFound = True;
++
++ for (i = 0; (i < EDID_NUMBER_MAX_DTD_BLK_1) && (dtdFound); i++) /* search possible DTD blocks in block 1 */
++ {
++ blockPtr = ((UInt8)pDis->EdidBlock[EDID_BLK1_OFFSET_BASE_DTD]) + ((UInt8)(i * EDID_DTD_BLK_SIZE));
++ if ((blockPtr + EDID_DTD_BLK_SIZE - 1) < EDID_BLOCK_SIZE)
++ {
++ dtdFound = storeDtdBlock(pDis, blockPtr);
++ }
++ }
++
++ break;
++
++
++ case EDID_BLOCK_MAP:
++ /* BLOCK MAP */
++
++ if (pDis->EdidBlockCnt > 1) {
++ if ((pDis->EdidBlockCnt - 1) < EDID_BLOCK_SIZE)
++ {
++ if (pDis->EdidBlock[pDis->EdidBlockCnt - 1] == EDID_CEA_EXTENSION) {
++ /* Some devices have been incorrectly designed so that the block map is not counted in the */
++ /* extension count. Design of compliant devices should take compatibility with those non-compliant */
++ /* devices into consideration. */
++ pDis->EdidBlockCnt = pDis->EdidBlockCnt + 1;
++ }
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++
++
++ break;
++
++
++ }
++
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* storeDtdBlock */
++/*============================================================================*/
++static Bool
++storeDtdBlock
++(
++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */
++ UInt8 blockPtr
++)
++{
++
++ Bool dtdFound = False;
++
++ if (blockPtr >= (EDID_BLOCK_SIZE-17))
++ {
++ /* do nothing */
++ return dtdFound;
++ }
++
++ /* First, select blocks that are DTDs [CEA861C A.2.10] */
++ if (((pDis->EdidBlock[blockPtr+0] != 0) ||
++ (pDis->EdidBlock[blockPtr+1] != 0) ||
++ (pDis->EdidBlock[blockPtr+2] != 0) ||
++ (pDis->EdidBlock[blockPtr+4] != 0))
++ &&
++ (pDis->NbDTDStored < NUMBER_DTD_STORED))
++ { /* Store the first DTD we find, others will be skipped */
++ pDis->EdidDTD[pDis->NbDTDStored].uPixelClock =
++ ((UInt16)pDis->EdidBlock[blockPtr+1] << 8) |
++ (UInt16)pDis->EdidBlock[blockPtr+0];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHActivePixels =
++ (((UInt16)pDis->EdidBlock[blockPtr+4] & 0x00F0) << 4) |
++ (UInt16)pDis->EdidBlock[blockPtr+2];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHBlankPixels =
++ (((UInt16)pDis->EdidBlock[blockPtr+4] & 0x000F) << 8) |
++ (UInt16)pDis->EdidBlock[blockPtr+3];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVActiveLines =
++ (((UInt16)pDis->EdidBlock[blockPtr+7] & 0x00F0) << 4) |
++ (UInt16)pDis->EdidBlock[blockPtr+5];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVBlankLines =
++ (((UInt16)pDis->EdidBlock[blockPtr+7] & 0x000F) << 8) |
++ (UInt16)pDis->EdidBlock[blockPtr+6];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHSyncOffset =
++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x00C0) << 2) |
++ (UInt16)pDis->EdidBlock[blockPtr+8];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHSyncWidth =
++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x0030) << 4) |
++ (UInt16)pDis->EdidBlock[blockPtr+9];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVSyncOffset =
++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x000C) << 2) |
++ (((UInt16)pDis->EdidBlock[blockPtr+10] & 0x00F0) >> 4);
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVSyncWidth =
++ (((UInt16)pDis->EdidBlock[blockPtr+11] & 0x0003) << 4) |
++ ((UInt16)pDis->EdidBlock[blockPtr+10] & 0x000F);
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHImageSize =
++ (((UInt16)pDis->EdidBlock[blockPtr+14] & 0x00F0) << 4) |
++ (UInt16)pDis->EdidBlock[blockPtr+12];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVImageSize =
++ (((UInt16)pDis->EdidBlock[blockPtr+14] & 0x000F) << 8) |
++ (UInt16)pDis->EdidBlock[blockPtr+13];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uHBorderPixels =
++ (UInt16)pDis->EdidBlock[blockPtr+15];
++
++ pDis->EdidDTD[pDis->NbDTDStored].uVBorderPixels =
++ (UInt16)pDis->EdidBlock[blockPtr+16];
++
++ pDis->EdidDTD[pDis->NbDTDStored].Flags = pDis->EdidBlock[blockPtr+17];
++
++ pDis->NbDTDStored++;
++
++ dtdFound = True; /* Stop any more DTDs being parsed */
++ }
++
++ return (dtdFound);
++}
++
++
++/*============================================================================*/
++/* storeMonitorBlock */
++/*============================================================================*/
++static Bool
++storeMonitorDescriptor
++(
++ tmHdmiTxobject_t *pDis, /* Device instance strucure holding block */
++ UInt8 blockPtr
++)
++{
++
++ Bool dtdFound = False;
++
++ if (blockPtr >= (EDID_BLOCK_SIZE-5))
++ {
++ /* do nothing */
++ return dtdFound;
++ }
++
++ /* First, select blocks that are DTDs [CEA861C A.2.10] */
++ if ((pDis->EdidBlock[blockPtr+0] == 0) &&
++ (pDis->EdidBlock[blockPtr+1] == 0) &&
++ (pDis->EdidBlock[blockPtr+2] == 0)
++ )
++ {
++ if (pDis->EdidBlock[blockPtr+3] == EDID_MONITOR_NAME_DESC_DATA_TYPE)
++ {
++ if (pDis->EdidFirstMonitorDescriptor.bDescRecord == False)
++ {
++ pDis->EdidFirstMonitorDescriptor.bDescRecord = True;
++ lmemcpy(&(pDis->EdidFirstMonitorDescriptor.uMonitorName) ,
++ &(pDis->EdidBlock[blockPtr+5]), EDID_MONITOR_DESCRIPTOR_SIZE);
++ dtdFound = True;
++ }
++ else if ((pDis->EdidOtherMonitorDescriptor.bDescRecord == False))
++ {
++ pDis->EdidOtherMonitorDescriptor.bDescRecord = True;
++ lmemcpy(&(pDis->EdidOtherMonitorDescriptor.uOtherDescriptor) ,
++ &(pDis->EdidBlock[blockPtr+5]), EDID_MONITOR_DESCRIPTOR_SIZE);
++ dtdFound = True;
++ }
++ }
++ else if (pDis->EdidBlock[blockPtr+3] == EDID_MONITOR_RANGE_DESC_DATA_TYPE)
++ {
++ if (pDis->EdidSecondMonitorDescriptor.bDescRecord == False)
++ {
++ if (blockPtr < (EDID_BLOCK_SIZE-9))
++ {
++ pDis->EdidSecondMonitorDescriptor.bDescRecord = True;
++ pDis->EdidSecondMonitorDescriptor.uMinVerticalRate = pDis->EdidBlock[blockPtr+5];
++ pDis->EdidSecondMonitorDescriptor.uMaxVerticalRate = pDis->EdidBlock[blockPtr+6];
++ pDis->EdidSecondMonitorDescriptor.uMinHorizontalRate = pDis->EdidBlock[blockPtr+7];
++ pDis->EdidSecondMonitorDescriptor.uMaxHorizontalRate = pDis->EdidBlock[blockPtr+8];
++ pDis->EdidSecondMonitorDescriptor.uMaxSupportedPixelClk = pDis->EdidBlock[blockPtr+9];
++ dtdFound = True;
++ }
++ else
++ {
++ /* do nothing */
++ }
++ }
++ }
++ }
++
++ return (dtdFound);
++
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetLatencyInfo */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EdidGetLatencyInfo
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidLatency_t * pEdidLatency
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pEdidLatency == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++
++ *pEdidLatency = pDis->EdidLatency;
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989EdidGetExtraVsdbData */
++/*============================================================================*/
++tmErrorCode_t tmbslTDA9989EdidGetExtraVsdbData
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxEdidExtraVsdbData_t **pExtraVsdbData
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pExtraVsdbData == Null)
++
++ if ((pDis->EdidStatus == HDMITX_EDID_READ) ||
++ (pDis->EdidStatus == HDMITX_EDID_ERROR_CHK))
++ {
++ /* allow if edid are read or if there are a chk error on an other block than block 0 */
++ *pExtraVsdbData = &(pDis->EdidExtraVsdbData);
++ }
++ else
++ {
++ /* Not allowed if EdidStatus value is not valid */
++ err = TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE;
++ }
++ return err;
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h
+new file mode 100755
+index 0000000..25cad98
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Edid_l.h
+@@ -0,0 +1,62 @@
++/**
++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of Koninklijke Philips Electronics N.V. and is confidential in
++ * nature. Under no circumstances is this software to be exposed to or placed
++ * under an Open Source License of any type without the expressed written
++ * permission of Koninklijke Philips Electronics N.V.
++ *
++ * \file tmbslTDA9989_Edid_l.h
++ *
++ * \version $Revision: 2 $
++ *
++ * \date $Date: 04/07/07 17:00 $
++ *
++ *
++*/
++
++#ifndef TMBSLTDA9989_EDID_L_H
++#define TMBSLTDA9989_EDID_L_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++extern tmErrorCode_t
++EdidBlockAvailable (tmUnitSelect_t txUnit, Bool * pSendEDIDCallback);
++
++extern tmErrorCode_t
++ClearEdidRequest (tmUnitSelect_t txUnit);
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_EDID_L_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c
+new file mode 100755
+index 0000000..33ab4d1
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP.c
+@@ -0,0 +1,655 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_HDCP.c
++ *
++ * \version $Revision: 2 $
++ *
++ */
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++#include "tmbslTDA9989_State_l.h"
++#include "tmbslTDA9989_InOut_l.h"
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS EXPORTED */
++/*============================================================================*/
++
++/**
++ * Table of registers to switch HDMI HDCP mode off for DVI
++ */
++
++CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOff[] =
++ {
++ {E_REG_P00_TBG_CNTRL_1_W, E_MASKREG_P00_TBG_CNTRL_1_dwin_dis, 1},
++ {E_REG_P12_TX33_RW, E_MASKREG_P12_TX33_hdmi, 0},
++ {0,0,0}
++ };
++
++/**
++ * Table of registers to switch HDMI HDCP mode on for HDMI
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOn[] =
++ {
++ {E_REG_P00_TBG_CNTRL_1_W, E_MASKREG_P00_TBG_CNTRL_1_dwin_dis, 0},
++ {E_REG_P11_ENC_CNTRL_RW, E_MASKREG_P11_ENC_CNTRL_ctl_code, 1},
++ {E_REG_P12_TX33_RW, E_MASKREG_P12_TX33_hdmi, 1},
++ {0,0,0}
++ };
++
++#ifdef __LINUX_ARM_ARCH__
++
++#include <linux/kernel.h>
++
++typedef struct {
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpCheck)
++ (
++ tmUnitSelect_t txUnit,
++ UInt16 uTimeSinceLastCallMs,
++ tmbslHdmiTxHdcpCheck_t *pResult
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpConfigure)
++ (
++ tmUnitSelect_t txUnit,
++ UInt8 slaveAddress,
++ tmbslHdmiTxHdcpTxMode_t txMode,
++ tmbslHdmiTxHdcpOptions_t options,
++ UInt16 uCheckIntervalMs,
++ UInt8 uChecksToDo
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpDownloadKeys)
++ (
++ tmUnitSelect_t txUnit,
++ UInt16 seed,
++ tmbslHdmiTxDecrypt_t keyDecryption
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpEncryptionOn)
++ (
++ tmUnitSelect_t txUnit,
++ Bool bOn
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpGetOtp)
++ (
++ tmUnitSelect_t txUnit,
++ UInt8 otpAddress,
++ UInt8 *pOtpData
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpGetT0FailState)
++ (
++ tmUnitSelect_t txUnit,
++ UInt8 *pFailState
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleBCAPS)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleBKSV)
++ (
++ tmUnitSelect_t txUnit,
++ UInt8 *pBksv,
++ Bool *pbCheckRequired /* May be null, but only for testing */
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleBKSVResult)
++ (
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleBSTATUS)
++ (
++ tmUnitSelect_t txUnit,
++ UInt16 *pBstatus /* May be null */
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleENCRYPT)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandlePJ)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleSHA_1)
++ (
++ tmUnitSelect_t txUnit,
++ UInt8 maxKsvDevices,
++ UInt8 *pKsvList, /* May be null if maxKsvDevices is 0 */
++ UInt8 *pnKsvDevices, /* May be null if maxKsvDevices is 0 */
++ UInt8 *pDepth /* Connection tree depth returned with KSV list */
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleSHA_1Result)
++ (
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpHandleT0)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpInit)
++ (
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVfreq_t voutFreq
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpRun)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpStop)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989HdcpGetSinkCategory)
++ (
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkCategory_t *category
++ );
++ tmErrorCode_t
++ (*tmbslTDA9989handleBKSVResultSecure)
++ (
++ tmUnitSelect_t txUnit
++ );
++ tmErrorCode_t (*f1)(tmHdmiTxobject_t *pDis);
++ int (*f2)(tmHdmiTxobject_t *pDis);
++} hdcp_private_t;
++
++#include <linux/module.h> /* need for EXPORT_SYMBOL */
++
++hdcp_private_t *h;
++
++void register_hdcp_private(hdcp_private_t *hdcp)
++{
++ h = hdcp;
++}
++EXPORT_SYMBOL(register_hdcp_private);
++
++tmErrorCode_t rej_f1(tmHdmiTxobject_t *pDis) {
++ return (h?h->f1(pDis):0);
++}
++
++int rej_f2(tmHdmiTxobject_t *pDis) {
++ return (h?h->f2(pDis):0);
++}
++
++tmErrorCode_t rej_f3(tmUnitSelect_t txUnit) {
++ return (h?h->tmbslTDA9989handleBKSVResultSecure(txUnit):TM_OK);
++}
++
++#endif
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpCheck */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpCheck
++(
++ tmUnitSelect_t txUnit,
++ UInt16 uTimeSinceLastCallMs,
++ tmbslHdmiTxHdcpCheck_t *pResult
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpCheck
++ (
++ txUnit,
++ uTimeSinceLastCallMs,
++ pResult
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpConfigure */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpConfigure
++(
++ tmUnitSelect_t txUnit,
++ UInt8 slaveAddress,
++ tmbslHdmiTxHdcpTxMode_t txMode,
++ tmbslHdmiTxHdcpOptions_t options,
++ UInt16 uCheckIntervalMs,
++ UInt8 uChecksToDo
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpConfigure
++ (
++ txUnit,
++ slaveAddress,
++ txMode,
++ options,
++ uCheckIntervalMs,
++ uChecksToDo
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpDownloadKeys */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpDownloadKeys
++(
++ tmUnitSelect_t txUnit,
++ UInt16 seed,
++ tmbslHdmiTxDecrypt_t keyDecryption
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpDownloadKeys
++ (
++ txUnit,
++ seed,
++ keyDecryption
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpEncryptionOn */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpEncryptionOn
++(
++ tmUnitSelect_t txUnit,
++ Bool bOn
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpEncryptionOn
++ (
++ txUnit,
++ bOn
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpGetOtp */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpGetOtp
++(
++ tmUnitSelect_t txUnit,
++ UInt8 otpAddress,
++ UInt8 *pOtpData
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpGetOtp
++ (
++ txUnit,
++ otpAddress,
++ pOtpData
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpGetT0FailState */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpGetT0FailState
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pFailState
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpGetT0FailState
++ (
++ txUnit,
++ pFailState
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleBCAPS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBCAPS
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleBCAPS
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleBKSV */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBKSV
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pBksv,
++ Bool *pbCheckRequired /* May be null, but only for testing */
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleBKSV
++ (
++ txUnit,
++ pBksv,
++ pbCheckRequired /* May be null, but only for testing */
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleBKSVResult */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBKSVResult
++(
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleBKSVResult
++ (
++ txUnit,
++ bSecure
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleBSTATUS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleBSTATUS
++(
++ tmUnitSelect_t txUnit,
++ UInt16 *pBstatus /* May be null */
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleBSTATUS
++ (
++ txUnit,
++ pBstatus /* May be null */
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleENCRYPT */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleENCRYPT
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleENCRYPT
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandlePJ */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandlePJ
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandlePJ
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleSHA_1 */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleSHA_1
++(
++ tmUnitSelect_t txUnit,
++ UInt8 maxKsvDevices,
++ UInt8 *pKsvList, /* May be null if maxKsvDevices is 0 */
++ UInt8 *pnKsvDevices, /* May be null if maxKsvDevices is 0 */
++ UInt8 *pDepth /* Connection tree depth returned with KSV list */
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleSHA_1
++ (
++ txUnit,
++ maxKsvDevices,
++ pKsvList, /* May be null if maxKsvDevices is 0 */
++ pnKsvDevices, /* May be null if maxKsvDevices is 0 */
++ pDepth /* Connection tree depth returned with KSV list */
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleSHA_1Result */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleSHA_1Result
++(
++ tmUnitSelect_t txUnit,
++ Bool bSecure
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleSHA_1Result
++ (
++ txUnit,
++ bSecure
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpHandleT0 */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpHandleT0
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpHandleT0
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpInit */
++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpInit
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVfreq_t voutFreq
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpInit
++ (
++ txUnit,
++ voutFmt,
++ voutFreq
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpRun */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpRun
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpRun
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpStop */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpStop
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpStop
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HdcpGetSinkCategory */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpGetSinkCategory
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkCategory_t *category
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989HdcpGetSinkCategory
++ (
++ txUnit,
++ category
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++
++
++
++/*============================================================================*/
++/* tmbslTDA9989handleBKSVResultSecure */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989handleBKSVResultSecure
++(
++ tmUnitSelect_t txUnit
++ )
++{
++#ifdef __LINUX_ARM_ARCH__
++ if (h) return h->tmbslTDA9989handleBKSVResultSecure
++ (
++ txUnit
++ );
++/* else {printk("%s is empty\n",__func__);}*/
++#endif
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h
+new file mode 100755
+index 0000000..7e74ab6
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_HDCP_l.h
+@@ -0,0 +1,72 @@
++/**
++ * Copyright (C) 2008 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_HDCP_l.h
++ *
++ * \version %version: 2 %
++ *
++ * \date %date_modified: %
++ *
++ * \brief BSL driver component local definitions for the TDA998x
++ * HDMI Transmitter.
++ *
++ * \section info Change Information
++ *
++ *
++*/
++
++#ifndef TMBSLTDA9989_HDCP_L_H
++#define TMBSLTDA9989_HDCP_L_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifdef __LINUX_ARM_ARCH__
++
++#define HDCP_F1 { \
++ int rej_f2(tmHdmiTxobject_t *pDis); \
++ regVal = rej_f2(pDis); \
++ }
++
++#define HDCP_F2 { \
++ tmErrorCode_t rej_f1(tmHdmiTxobject_t *pDis); \
++ err = rej_f1(pDis); \
++ RETIF(err != TM_OK, err); \
++}
++
++#define HDCP_F3 { \
++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_R0)) \
++ { \
++ tmErrorCode_t rej_f3(tmUnitSelect_t txUnit); \
++ err = rej_f3(txUnit); \
++ RETIF(err != TM_OK, err); \
++ } \
++}
++
++#else
++
++#define HDCP_F1 {regVal = 0;}
++
++#define HDCP_F2 {}
++
++#define HDCP_F3 {}
++
++#endif /*TMFL_HDCP_SUPPORT*/
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_HDCP_L_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c
+new file mode 100755
+index 0000000..8ff0b65
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut.c
+@@ -0,0 +1,5101 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_InOut.c
++ *
++ * \version %version: 3 %
++ *
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#include <linux/module.h>
++#endif
++
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++#include "tmbslTDA9989_HDCP_l.h"
++#include "tmbslTDA9989_State_l.h"
++#include "tmbslTDA9989_Misc_l.h"
++#include "tmbslTDA9989_InOut_l.h"
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++#define SSD_UNUSED_VALUE 0xF0
++
++#ifdef FORMAT_PC
++#define DEPTH_COLOR_PC 1 /* PC_FORMAT only 8 bits available */
++#endif /* FORMAT_PC */
++
++#define REG_VAL_SEL_AIP_SPDIF 0
++#define REG_VAL_SEL_AIP_I2S 1
++#define REG_VAL_SEL_AIP_OBA 2
++#define REG_VAL_SEL_AIP_DST 3
++#define REG_VAL_SEL_AIP_HBR 5
++
++struct vic2reg {
++ unsigned char vic;
++ unsigned char reg;
++};
++
++struct sync_desc {
++ UInt16 Vs2;
++ UInt8 pix_rep;
++ UInt8 v_toggle;
++ UInt8 h_toggle;
++ UInt16 hfp; /* Output values for Vs/Hs input sync */
++ UInt16 vfp;
++ UInt16 href; /* Output values for all other input sync sources */
++ UInt16 vref;
++};
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS EXPORTED */
++/*============================================================================*/
++
++extern CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOff[];
++extern CONST_DAT tmHdmiTxRegMaskVal_t kVoutHdcpOn[];
++
++/**
++ * Lookup table of input port control registers and their swap and mirror masks
++ */
++CONST_DAT tmbslTDA9989RegVip
++ kRegVip[HDMITX_VIN_PORT_MAP_TABLE_LEN] =
++{
++ {E_REG_P00_VIP_CNTRL_0_W,
++ E_MASKREG_P00_VIP_CNTRL_0_swap_a,
++ E_MASKREG_P00_VIP_CNTRL_0_mirr_a
++ }, /* Port group 0 */
++ {E_REG_P00_VIP_CNTRL_0_W,
++ E_MASKREG_P00_VIP_CNTRL_0_swap_b,
++ E_MASKREG_P00_VIP_CNTRL_0_mirr_b
++ }, /* Port group 1 */
++ {E_REG_P00_VIP_CNTRL_1_W,
++ E_MASKREG_P00_VIP_CNTRL_1_swap_c,
++ E_MASKREG_P00_VIP_CNTRL_1_mirr_c
++ }, /* Port group 2 */
++ {E_REG_P00_VIP_CNTRL_1_W,
++ E_MASKREG_P00_VIP_CNTRL_1_swap_d,
++ E_MASKREG_P00_VIP_CNTRL_1_mirr_d
++ }, /* Port group 3 */
++ {E_REG_P00_VIP_CNTRL_2_W,
++ E_MASKREG_P00_VIP_CNTRL_2_swap_e,
++ E_MASKREG_P00_VIP_CNTRL_2_mirr_e
++ }, /* Port group 4 */
++ {E_REG_P00_VIP_CNTRL_2_W,
++ E_MASKREG_P00_VIP_CNTRL_2_swap_f,
++ E_MASKREG_P00_VIP_CNTRL_2_mirr_f
++ } /* Port group 5 */
++};
++
++/**
++ * Table of PLL settings registers to configure for all video input format (vinFmt)
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kCommonPllCfg[] =
++{
++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_PLL_SERIAL_2_RW, E_MASKREG_ALL, 0x01},
++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_SERIALIZER_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_AUDIO_DIV_RW, E_MASKREG_ALL, 0x03},
++ /*{E_REG_P02_TEST2_RW, E_MASKREG_ALL, 0x00},*/
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_ALL, 0x09},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure double mode pixel rate,
++ * vinFmt other than 480i or 576i
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kDoublePrateVfmtOtherPllCfg[] =
++{
++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x00},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure for single mode pixel rate,
++ * vinFmt 480i or 576i only
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmt480i576iPllCfg[] =
++{
++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x11},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure single mode pixel rate,
++ * vinFmt other than 480i or 576i
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmtOtherPllCfg[] =
++{
++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x10},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure for single repeated mode pixel rate,
++ * vinFmt 480i or 576i only
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kSrepeatedPrateVfmt480i576iPllCfg[] =
++{
++ {E_REG_P02_PLL_SCG2_RW, E_MASKREG_ALL, 0x01},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure for 480i and 576i vinFmt
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kVfmt480i576iPllCfg[] =
++{
++ {E_REG_P02_PLL_SCGN1_RW, E_MASKREG_ALL, 0x14},
++ {E_REG_P02_PLL_SCGN2_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_PLL_SCGR1_RW, E_MASKREG_ALL, 0x0A},
++ {E_REG_P02_PLL_SCGR2_RW, E_MASKREG_ALL, 0x00},
++ {0,0,0}
++};
++
++/**
++ * Table of PLL settings registers to configure for other vinFmt than 480i and 576i
++ */
++CONST_DAT tmHdmiTxRegMaskVal_t kVfmtOtherPllCfg[] =
++{
++ {E_REG_P02_PLL_SCGN1_RW, E_MASKREG_ALL, 0xFA},
++ {E_REG_P02_PLL_SCGN2_RW, E_MASKREG_ALL, 0x00},
++ {E_REG_P02_PLL_SCGR1_RW, E_MASKREG_ALL, 0x5B},
++ {E_REG_P02_PLL_SCGR2_RW, E_MASKREG_ALL, 0x00},
++ {0,0,0}
++};
++
++/**
++ * Lookup table to convert from EIA/CEA TV video formats used in the EDID and
++ * in API parameters to pixel clock frequencies, according to SCS Table
++ * "HDMI Pixel Clock Frequencies per EIA/CEA-861B Video Output Format".
++ * The other index is the veritical frame frequency.
++ */
++
++CONST_DAT UInt8 kVfmtToPixClk_TV[HDMITX_VFMT_TV_MAX][HDMITX_VFREQ_NUM] =
++{
++ /* HDMITX_VFREQ_24Hz HDMITX_VFREQ_25Hz HDMITX_VFREQ_30Hz HDMITX_VFREQ_50Hz HDMITX_VFREQ_59Hz HDMITX_VFREQ_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_25175, E_PIXCLK_25200}, /* HDMITX_VFMT_01_640x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_02_720x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_03_720x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74175, E_PIXCLK_74250}, /* HDMITX_VFMT_04_1280x720p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74175, E_PIXCLK_74250}, /* HDMITX_VFMT_05_1920x1080i_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_06_720x480i_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_07_720x480i_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_08_720x240p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_27027}, /* HDMITX_VFMT_09_720x240p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_10_720x480i_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_11_720x480i_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_12_720x240p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_13_720x240p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_14_1440x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_54054}, /* HDMITX_VFMT_15_1440x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_148350, E_PIXCLK_148500}, /* HDMITX_VFMT_16_1920x1080p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_17_720x576p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_18_720x576p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_19_1280x720p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_20_1920x1080i_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_21_720x576i_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_22_720x576i_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_23_720x288p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_27000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_24_720x288p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_25_720x576i_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_26_720x576i_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_27_720x288p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_28_720x288p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_29_1440x576p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_54000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_30_1440x576p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_148500, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_31_1920x1080p_50Hz */
++ {E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_32_1920x1080p_24Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_33_1920x1080p_25Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_34_1920x1080p_30Hz */
++
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_108108}, /* HDMITX_VFMT_35_2880x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_108108}, /* HDMITX_VFMT_36_2880x480p_60Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_37_2880x576p_50Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_108000, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_38_2880x576p_50Hz */
++
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_39_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_40_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_41_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_42_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_43_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_44_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_45_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_46_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_47_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_48_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_49_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_50_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_51_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_52_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_53_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_54_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_55_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_56_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_57_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_58_ */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_59_ */
++
++ {E_PIXCLK_59400, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_60_1280x720p_24Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID}, /* HDMITX_VFMT_61_1280x720p_25Hz */
++ {E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_74250, E_PIXCLK_INVALID, E_PIXCLK_INVALID, E_PIXCLK_INVALID} /* HDMITX_VFMT_62_1280x720p_30Hz */
++};
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++
++/**
++ * Lookup table to convert PC formats used in API parameters to pixel clock
++ * frequencies.
++ * The other index is the veritical frame frequency.
++ */
++#ifdef FORMAT_PC
++CONST_DAT UInt8 kVfmtToPixClk_PC[HDMITX_VFMT_PC_NUM] =
++{
++ /* HDMITX_VFREQ_60Hz HDMITX_VFREQ_70Hz HDMITX_VFREQ_72Hz HDMITX_VFREQ_75Hz HDMITX_VFREQ_85Hz HDMITX_VFREQ_87Hz*/
++ E_PIXCLK_25175 , /* HDMITX_VFMT_PC_640x480p_60Hz */
++ E_PIXCLK_40000 , /* HDMITX_VFMT_PC_800x600p_60Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1152x960p_60Hz */
++ E_PIXCLK_65000 , /* HDMITX_VFMT_PC_1024x768p_60Hz */
++ E_PIXCLK_79500 , /* HDMITX_VFMT_PC_1280x768p_60Hz */
++ E_PIXCLK_108000 , /* HDMITX_VFMT_PC_1280x1024p_60Hz */
++ E_PIXCLK_85500 , /* HDMITX_VFMT_PC_1360x768p_60Hz */
++ E_PIXCLK_121750 , /* HDMITX_VFMT_PC_1400x1050p_60Hz */
++ E_PIXCLK_162000 , /* HDMITX_VFMT_PC_1600x1200p_60Hz */
++ E_PIXCLK_75000 , /* HDMITX_VFMT_PC_1024x768p_70Hz */
++ E_PIXCLK_31500 , /* HDMITX_VFMT_PC_640x480p_72Hz */
++ E_PIXCLK_50000 , /* HDMITX_VFMT_PC_800x600p_72Hz */
++ E_PIXCLK_31500 , /* HDMITX_VFMT_PC_640x480p_75Hz */
++ E_PIXCLK_78750 , /* HDMITX_VFMT_PC_1024x768p_75Hz */
++ E_PIXCLK_49500 , /* HDMITX_VFMT_PC_800x600p_75Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1024x864p_75Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x1024p_75Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_640x350p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_640x400p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_720x400p_85Hz */
++ E_PIXCLK_36000 , /* HDMITX_VFMT_PC_640x480p_85Hz */
++ E_PIXCLK_56250 , /* HDMITX_VFMT_PC_800x600p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1024x768p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1152x864p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x960p_85Hz */
++ E_PIXCLK_INVALID, /* HDMITX_VFMT_PC_1280x1024p_85Hz */ /* PR1570 FIXED */
++ E_PIXCLK_INVALID /* HDMITX_VFMT_PC_1024x768i_87Hz */
++};
++#endif
++
++/**
++ * Lookup table to convert from EIA/CEA TV video formats used in the EDID and in
++ * API parameters to the format used in the E_REG_P00_VIDFORMAT_W register
++ */
++
++#ifdef TMFL_RGB_DDR_12BITS
++static CONST_DAT struct vic2reg vic2reg_TV[] = {
++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_640x480p_60Hz},
++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz},
++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz},
++ {HDMITX_VFMT_06_720x480i_60Hz, E_REGVFMT_720x480i_60Hz},
++ {HDMITX_VFMT_07_720x480i_60Hz, E_REGVFMT_720x480i_60Hz},
++ {HDMITX_VFMT_08_720x240p_60Hz, E_REGVFMT_720x240p_60Hz},
++ {HDMITX_VFMT_09_720x240p_60Hz, E_REGVFMT_720x240p_60Hz},
++ {HDMITX_VFMT_10_720x480i_60Hz, E_REGVFMT_2880x480i_60Hz_PR4},
++ {HDMITX_VFMT_11_720x480i_60Hz, E_REGVFMT_2880x480i_60Hz_PR4},
++ {HDMITX_VFMT_14_1440x480p_60Hz, E_REGVFMT_1440x480p_60Hz},
++ {HDMITX_VFMT_15_1440x480p_60Hz, E_REGVFMT_1440x480p_60Hz},
++ {HDMITX_VFMT_16_1920x1080p_60Hz,E_REGVFMT_1920x1080p_60Hz},
++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz},
++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz},
++ {HDMITX_VFMT_21_720x576i_50Hz, E_REGVFMT_720x576i_50Hz},
++ {HDMITX_VFMT_22_720x576i_50Hz, E_REGVFMT_720x576i_50Hz},
++ {HDMITX_VFMT_23_720x288p_50Hz, E_REGVFMT_720x288p_50Hz},
++ {HDMITX_VFMT_24_720x288p_50Hz, E_REGVFMT_720x288p_50Hz},
++ {HDMITX_VFMT_25_720x576i_50Hz, E_REGVFMT_2880x576i_50Hz}, /* FIXME PR 2 */
++ {HDMITX_VFMT_26_720x576i_50Hz, E_REGVFMT_2880x576i_50Hz}, /* FIXME PR 2 */
++ {HDMITX_VFMT_29_1440x576p_50Hz, E_REGVFMT_1440x576p_50Hz},
++ {HDMITX_VFMT_30_1440x576p_50Hz, E_REGVFMT_1440x576p_50Hz},
++ {HDMITX_VFMT_31_1920x1080p_50Hz,E_REGVFMT_1920x1080p_50Hz},
++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz},
++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz},
++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz},
++ {HDMITX_VFMT_35_2880x480p_60Hz, E_REGVFMT_2880x480p_60Hz},
++ {HDMITX_VFMT_36_2880x480p_60Hz, E_REGVFMT_2880x480p_60Hz},
++ {HDMITX_VFMT_37_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_38_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz},
++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz},
++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz}
++};
++static CONST_DAT struct vic2reg vic2reg_TV_FP[] = {
++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP},
++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP},
++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz_FP},
++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz_FP},
++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz_FP},
++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz_FP},
++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz_FP},
++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz_FP},
++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz_FP},
++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz_FP},
++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz_FP},
++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz_FP},
++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz_FP},
++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz_FP},
++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz_FP}
++};
++#else
++static CONST_DAT struct vic2reg vic2reg_TV[] = {
++ {HDMITX_VFMT_01_640x480p_60Hz, E_REGVFMT_640x480p_60Hz},
++ {HDMITX_VFMT_02_720x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_03_720x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz},
++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz},
++ {HDMITX_VFMT_06_720x480i_60Hz, E_REGVFMT_720x480i_60Hz},
++ {HDMITX_VFMT_07_720x480i_60Hz, E_REGVFMT_720x480i_60Hz},
++ {HDMITX_VFMT_08_720x240p_60Hz, E_REGVFMT_720x240p_60Hz},
++ {HDMITX_VFMT_09_720x240p_60Hz, E_REGVFMT_720x240p_60Hz},
++ {HDMITX_VFMT_16_1920x1080p_60Hz,E_REGVFMT_1920x1080p_60Hz},
++ {HDMITX_VFMT_17_720x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_18_720x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz},
++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz},
++ {HDMITX_VFMT_21_720x576i_50Hz, E_REGVFMT_720x576i_50Hz},
++ {HDMITX_VFMT_22_720x576i_50Hz, E_REGVFMT_720x576i_50Hz},
++ {HDMITX_VFMT_23_720x288p_50Hz, E_REGVFMT_720x288p_50Hz},
++ {HDMITX_VFMT_24_720x288p_50Hz, E_REGVFMT_720x288p_50Hz},
++ {HDMITX_VFMT_31_1920x1080p_50Hz,E_REGVFMT_1920x1080p_50Hz},
++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz},
++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz},
++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz},
++ {HDMITX_VFMT_35_2880x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_36_2880x480p_60Hz, E_REGVFMT_720x480p_60Hz},
++ {HDMITX_VFMT_37_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_38_2880x576p_50Hz, E_REGVFMT_720x576p_50Hz},
++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz},
++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz},
++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz}
++};
++static CONST_DAT struct vic2reg vic2reg_TV_FP[] = {
++ {HDMITX_VFMT_04_1280x720p_60Hz, E_REGVFMT_1280x720p_60Hz_FP},
++ {HDMITX_VFMT_05_1920x1080i_60Hz,E_REGVFMT_1920x1080i_60Hz_FP},
++ {HDMITX_VFMT_19_1280x720p_50Hz, E_REGVFMT_1280x720p_50Hz_FP},
++ {HDMITX_VFMT_20_1920x1080i_50Hz,E_REGVFMT_1920x1080i_50Hz_FP},
++ {HDMITX_VFMT_32_1920x1080p_24Hz,E_REGVFMT_1920x1080p_24Hz_FP},
++ {HDMITX_VFMT_33_1920x1080p_25Hz,E_REGVFMT_1920x1080p_25Hz_FP},
++ {HDMITX_VFMT_34_1920x1080p_30Hz,E_REGVFMT_1920x1080p_30Hz_FP},
++ {HDMITX_VFMT_60_1280x720p_24Hz, E_REGVFMT_1280x720p_24Hz_FP},
++ {HDMITX_VFMT_61_1280x720p_25Hz, E_REGVFMT_1280x720p_25Hz_FP},
++ {HDMITX_VFMT_62_1280x720p_30Hz, E_REGVFMT_1280x720p_30Hz_FP}
++};
++#endif
++
++#ifdef FORMAT_PC
++static CONST_DAT struct vic2reg vic2reg_PC[HDMITX_VFMT_PC_NUM] = {
++ {HDMITX_VFMT_PC_640x480p_60Hz, E_REGVFMT_640x480p_60Hz},
++ {HDMITX_VFMT_PC_800x600p_60Hz, E_REGVFMT_800x600p_60Hz},
++ {HDMITX_VFMT_PC_1024x768p_60Hz, E_REGVFMT_1024x768p_60Hz},
++ {HDMITX_VFMT_PC_1280x768p_60Hz, E_REGVFMT_1280x768p_60Hz},
++ {HDMITX_VFMT_PC_1280x1024p_60Hz,E_REGVFMT_1280x1024p_60Hz},
++ {HDMITX_VFMT_PC_1360x768p_60Hz, E_REGVFMT_1360x768p_60Hz},
++ {HDMITX_VFMT_PC_1400x1050p_60Hz,E_REGVFMT_1400x1050p_60Hz},
++ {HDMITX_VFMT_PC_1600x1200p_60Hz,E_REGVFMT_1600x1200p_60Hz},
++ {HDMITX_VFMT_PC_1024x768p_70Hz, E_REGVFMT_1024x768p_70Hz},
++ {HDMITX_VFMT_PC_640x480p_72Hz, E_REGVFMT_640x480p_72Hz},
++ {HDMITX_VFMT_PC_800x600p_72Hz, E_REGVFMT_800x600p_72Hz},
++ {HDMITX_VFMT_PC_640x480p_75Hz, E_REGVFMT_640x480p_75Hz},
++ {HDMITX_VFMT_PC_1024x768p_75Hz, E_REGVFMT_1024x768p_75Hz},
++ {HDMITX_VFMT_PC_800x600p_75Hz, E_REGVFMT_800x600p_75Hz},
++ {HDMITX_VFMT_PC_640x480p_85Hz, E_REGVFMT_640x480p_85Hz},
++ {HDMITX_VFMT_PC_800x600p_85Hz, E_REGVFMT_800x600p_85Hz},
++ {HDMITX_VFMT_PC_1280x1024p_85Hz,E_REGVFMT_1280x1024p_85Hz}
++};
++#endif /* FORMAT PC */
++
++
++/**
++ * Lookup table to convert from video format codes used in the
++ * E_REG_P00_VIDFORMAT_W register to corresponding VS_PIX_STRT_2
++ * register values, to correct the output window for interlaced
++ * output formats, with or without the scaler.
++ *
++ * The correction is VS_PIX_STRT_2=VS_PIX_STRT_2+VS_PIX_STRT_1.
++ * The same value is also applied to VS_PIX_END_2.
++ */
++
++/**
++ * Lookup table to convert from video format codes used in the
++ * E_REG_P00_VIDFORMAT_W register to corresponding
++ * pixel repetition values in the PLL_SERIAL_2 register.
++ * 0=no repetition (pixel sent once)
++ * 1=one repetition (pixel sent twice) etc
++ */
++
++/**
++ * Lookup table to convert from video format codes used in the
++ * E_REG_P00_VIDFORMAT_W register to corresponding
++ * trios of 2-bit values in the srl_nosc, scg_nosc and de_nosc
++ * PLL control registers
++ *
++ * Rational for dummies by André ;)
++ * -----------------------------
++ * the TMDS serializer multiply x10 the pixclk (this is a PLL;)
++ * <format> --> <pixclk> --> <PLL> --> <div by>
++ * 576i or 480i 13.5 Mhz (*2) 270 Mhz 4
++ * 576p 27 Mhz 270 Mhz 4
++ * 720p or 1080i 74.25 Mhz 742 Mhz 2
++ * 1080p 148.5 Mhz 1485 Mhz 1
++ *
++ */
++
++static CONST_DAT UInt8 pll[] = {
++ /* prefetch */
++ 2, /* E_REGVFMT_640x480p_60Hz */
++ 2, /* E_REGVFMT_720x480p_60Hz */
++ 1, /* E_REGVFMT_1280x720p_60Hz */
++ 1, /* E_REGVFMT_1920x1080i_60Hz */
++ 3, /* E_REGVFMT_720x480i_60Hz */
++ 0, /* E_REGVFMT_720x240p_60Hz */ /** \todo Need nosc PLL value */
++ 0, /* E_REGVFMT_1920x1080p_60Hz */
++ 2, /* E_REGVFMT_720x576p_50Hz */
++ 1, /* E_REGVFMT_1280x720p_50Hz */
++ 1, /* E_REGVFMT_1920x1080i_50Hz */
++ 3, /* E_REGVFMT_720x576i_50Hz */
++ 0, /* E_REGVFMT_720x288p_50Hz */ /** \todo Need nosc PLL value */
++ 0, /* E_REGVFMT_1920x1080p_50Hz */
++#ifdef TMFL_RGB_DDR_12BITS
++ 0, /* E_REGVFMT_1920x1080p_24Hz */
++ 1, /* E_REGVFMT_1440x576p_50Hz */
++ 1, /* E_REGVFMT_1440x480p_50Hz */
++ 0, /* E_REGVFMT_2880x480p_50Hz */
++ 0, /* E_REGVFMT_2880x576p_50Hz */
++ 1, /* E_REGVFMT_2880x480i_60Hz */
++ 2, /* E_REGVFMT_2880x480i_60Hz_PR2*/
++ 2, /* E_REGVFMT_2880x480i_60Hz_PR4*/
++ 1, /* E_REGVFMT_2880x576i_50Hz */
++ 2, /* E_REGVFMT_2880x576i_50Hz_PR2*/
++ 1, /* E_REGVFMT_720x480p_60Hz_FP */
++ 0, /* E_REGVFMT_1280x720p_60Hz_FP */
++ 1, /* E_REGVFMT_720x576p_50Hz_FP */
++ 0, /* E_REGVFMT_1280x720p_50Hz_FP */
++ 0, /* E_REGVFMT_1920x1080p_23Hz_FP*/
++ 0, /* E_REGVFMT_1920x1080p_25Hz_FP*/
++ 0, /* E_REGVFMT_1920x1080p_29Hz_FP*/
++ 0, /* E_REGVFMT_1920x1080i_60Hz_FP*/
++ 0, /* E_REGVFMT_1920x1080i_50Hz_FP*/
++#endif
++ /* extra list */
++#ifndef TMFL_RGB_DDR_12BITS
++ 1, /* E_REGVFMT_1920x1080p_24Hz */
++#endif
++ 1, /* E_REGVFMT_1920x1080p_25Hz */
++ 1, /* E_REGVFMT_1920x1080p_30Hz */
++ 1, /* E_REGVFMT_1280x720p_24Hz */
++ 1, /* E_REGVFMT_1280x720p_25Hz */
++ 1, /* E_REGVFMT_1280x720p_30Hz */
++#ifndef TMFL_RGB_DDR_12BITS
++ 0, /* E_REGVFMT_1280x720p_60Hz_FP */
++ 0, /* E_REGVFMT_1920x1080i_60Hz_FP */
++ 0, /* E_REGVFMT_1280x720p_50Hz_FP */
++ 0, /* E_REGVFMT_1920x1080i_50Hz_FP */
++ 0, /* E_REGVFMT_1920x1080p_24Hz_FP */
++ 0, /* E_REGVFMT_1920x1080p_25Hz_FP */
++ 0, /* E_REGVFMT_1920x1080p_30Hz_FP */
++#endif
++ 0, /* E_REGVFMT_1280x720p_24Hz_FP */
++ 0, /* E_REGVFMT_1280x720p_25Hz_FP */
++ 0, /* E_REGVFMT_1280x720p_30Hz_FP */
++#ifdef FORMAT_PC
++ 2, /* E_REGVFMT_640x480p_72Hz */
++ 2, /* E_REGVFMT_640x480p_75Hz */
++ 2, /* E_REGVFMT_640x480p_85Hz */
++ 1, /* E_REGVFMT_800x600p_60Hz */
++ 1, /* E_REGVFMT_800x600p_72Hz */
++ 1, /* E_REGVFMT_800x600p_75Hz */
++ 1, /* E_REGVFMT_800x600p_85Hz */
++ 1, /* E_REGVFMT_1024x768p_60Hz */
++ 1, /* E_REGVFMT_1024x768p_70Hz */
++ 1, /* E_REGVFMT_1024x768p_75Hz */
++ 0, /* E_REGVFMT_1280x768p_60Hz */
++ 0, /* E_REGVFMT_1280x1024p_60Hz */
++ 0, /* E_REGVFMT_1360x768p_60Hz */
++ 0, /* E_REGVFMT_1400x1050p_60Hz */
++ 0, /* E_REGVFMT_1600x1200p_60Hz */
++ 1 /* E_REGVFMT_1280x1024p_85Hz */
++#endif /* FORMAT_PC */
++};
++
++
++
++/**
++ * Lokup table to convert from video format codes used in the
++ * E_REG_P00_VIDFORMAT_W register to RefPix and RefLine values
++ * according to sync source
++ */
++/* prefetch list */
++static CONST_DAT struct sync_desc ref_sync[] =
++{
++ /*
++ designer world <==> CEA-861 reader world
++ ----------------------------------------
++ t_hs_s : hfp+1
++ t_vsl_s1 : vfp+1
++ t_de_s : href+1
++ t_vw_s1 : vref+1
++
++ For the story, designer have defined VsPixRef and VsLineRef concept
++ that are the position of VSync in pixel and line starting from the top
++ of the frame.
++ So we have in fact : VSync that is hfp + vfp*total_h_active away from top
++
++ */
++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */
++ {0, 0, 1, 1, 17, 2, 161, 36}, /* E_REGVFMT_640x480p_60Hz */
++ {0, 0, 1, 1, 17, 8, 139, 43}, /* E_REGVFMT_720x480p_60Hz */
++ {0, 0, 0, 0, 111, 2, 371, 26}, /* E_REGVFMT_1280x720p_60Hz */
++ {1100+88, 0, 0, 0, 89, 2, 281, 21}, /* E_REGVFMT_1920x1080i_60Hz */
++ {429+19, 1, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_720x480i_60Hz */
++ {0, 1, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_720x240p_60Hz */
++ {0, 0, 0, 0, 89, 2, 281, 42}, /* E_REGVFMT_1920x1080p_60Hz */
++ {0, 0, 1, 1, 13, 2, 145, 45}, /* E_REGVFMT_720x576p_50Hz */
++ {0, 0, 0, 0, 441, 2, 701, 26}, /* E_REGVFMT_1280x720p_50Hz */
++ {1320+528,0, 0, 0, 529, 2, 721, 21}, /* E_REGVFMT_1920x1080i_50Hz */
++ {432+12, 1, 1, 1, 13, 2, 145, 23}, /* E_REGVFMT_720x576i_50Hz */
++ {0, 1, 1, 1, 13, 2, 145, 23}, /* E_REGVFMT_720x288p_50Hz */
++ {0, 0, 0, 0, 529, 2, 721, 42}, /* E_REGVFMT_1920x1080p_50Hz */
++#ifdef TMFL_RGB_DDR_12BITS
++ {0, 0, 0, 0, 639, 2, 831, 42}, /* E_REGVFMT_1920x1080p_24Hz */
++ {0, 0, 1, 1, 25, 2, 289, 45}, /* E_REGVFMT_1440x576p_50Hz */
++ {0, 0, 1, 1, 33, 8, 277, 43}, /* E_REGVFMT_1440x480p_50Hz */
++ {0, 0, 1, 1, 65, 8, 553, 43}, /* E_REGVFMT_2880x480p_50Hz */
++ {0, 0, 1, 1, 49, 2, 577, 45}, /* E_REGVFMT_2880x576p_50Hz */
++ {1716+76, 0, 1, 1, 77, 5, 553, 22}, /* E_REGVFMT_2880x480i_60Hz */
++ {858+38, 1, 1, 1, 39, 5, 277, 22}, /* E_REGVFMT_2880x480i_60Hz_PR2*/
++ {429+19, 2, 1, 1, 20, 5, 139, 22}, /* E_REGVFMT_2880x480i_60Hz_PR4*/
++ {1728+48, 0, 1, 1, 49, 2, 577, 23}, /* E_REGVFMT_2880x576i_50Hz */
++ {864+24, 1, 1, 1, 25, 2, 289, 23} /* E_REGVFMT_2880x576i_50Hz_PR*/
++#endif
++};
++
++/* extra list */
++static CONST_DAT struct sync_desc ref_sync_extra[] =
++{
++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */
++#ifndef TMFL_RGB_DDR_12BITS
++ {0, 0, 0, 0, 639, 2, 831, 42}, /* E_REGVFMT_1920x1080p_24Hz */
++#endif
++ {0, 0, 0, 0, 529, 2, 721, 42}, /* E_REGVFMT_1920x1080p_25Hz */
++ {0, 0, 0, 0, 89, 2, 281, 42}, /* E_REGVFMT_1920x1080p_30Hz */
++ {0, 0, 0, 0, 1761, 2, 2021,26}, /* E_REGVFMT_1280x720p_24Hz */
++ {0, 0, 0, 0, 2421, 2, 2681,26}, /* E_REGVFMT_1280x720p_25Hz */
++ {0, 0, 0, 0, 1761, 2, 2021,26} /* E_REGVFMT_1280x720p_30Hz */
++};
++
++#ifdef FORMAT_PC
++ /* PC list */
++static CONST_DAT struct sync_desc ref_sync_PC[] =
++{
++ /* Vs2 PR Vtg Htg HFP VFP HREF VREF */
++ {0, 0, 1, 1, 25, 2, 195, 32}, /* E_REGVFMT_640x480p_72Hz */
++ {0, 0, 1, 1, 17, 2, 203, 20}, /* E_REGVFMT_640x480p_75Hz */
++ {0, 0, 1, 1, 57, 2, 195, 29}, /* E_REGVFMT_640x480p_85Hz */
++ {0, 0, 0, 0, 41, 2, 259, 28}, /* E_REGVFMT_800x600p_60Hz */
++ {0, 0, 0, 0, 57, 2, 243, 30}, /* E_REGVFMT_800x600p_72Hz */
++ {0, 0, 0, 0, 17, 2, 259, 25}, /* E_REGVFMT_800x600p_75Hz */
++ {0, 0, 0, 0, 33, 2, 251, 31}, /* E_REGVFMT_800x600p_85Hz */
++ {0, 0, 1, 1, 25, 2, 323, 36}, /* E_REGVFMT_1024x768p_60Hz */
++ {0, 0, 1, 1, 25, 2, 307, 36}, /* E_REGVFMT_1024x768p_70Hz */
++ {0, 0, 0, 0, 17, 2, 291, 32}, /* E_REGVFMT_1024x768p_75Hz */
++ {0, 0, 0, 1, 65, 2, 387, 28}, /* E_REGVFMT_1280x768p_60Hz */
++ {0, 0, 0, 0, 49, 2, 411, 42}, /* E_REGVFMT_1280x1024p_60Hz */
++ {0, 0, 0, 0, 65, 2, 435, 25}, /* E_REGVFMT_1360x768p_60Hz */
++ {0, 0, 0, 1, 89, 2, 467, 37}, /* E_REGVFMT_1400x1050p_60Hz */
++ {0, 0, 0, 0, 65, 2, 563, 50}, /* E_REGVFMT_1600x1200p_60Hz */
++ {0, 0, 0, 0, 65, 2, 451, 48} /* E_REGVFMT_1280x1024p_85Hz */
++};
++#endif/* FORMAT_PC */
++
++static CONST_DAT tmHdmiTxVidReg_t format_param_extra[] = {
++ /* NPIX NLINE VsLineStart VsPixStart VsLineEnd VsPixEnd HsStart HsEnd ActiveVideoStart ActiveVideoEnd DeStart DeEnd */
++ /* npix nline vsl_s1 vsp_s1 vsl_e1 vsp_e1 hs_e hs_e vw_s1 vw_e1 de_s de_e */
++#ifndef TMFL_RGB_DDR_12BITS
++ {2750, 1125, 1, 638, 6, 638, 638, 682, 41, 1121, 830, 2750, 0, 0},/* E_REGVFMT_1920x1080p_24Hz */
++#endif
++ {2640, 1125, 1, 528, 6, 528, 528, 572, 41, 1121, 720, 2640, 0, 0},/* E_REGVFMT_1920x1080p_25Hz */
++ {2200, 1125, 1, 88, 6, 88, 88, 132, 41, 1121, 280, 2200, 0, 0},/* E_REGVFMT_1920x1080p_30Hz */
++ {3300, 750, 1, 1760, 6, 1760, 1760, 1800, 25, 745, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_24Hz */
++ {3960, 750, 1, 2420, 6, 2420, 2420, 2460, 25, 745, 2680, 3960, 0, 0},/* E_REGVFMT_1280x720p_25Hz */
++ {3300, 750, 1, 1760, 6, 1760, 1760, 1800, 25, 745, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_30Hz */
++#ifndef TMFL_RGB_DDR_12BITS
++ {1650, 1500, 1, 110, 6, 110, 110, 150, 25, 1495, 370, 1650, 746, 776},/* E_REGVFMT_1280x720p_60Hz_FP */
++ {2200, 2250, 1, 88, 6, 88, 88, 132, 20, 2248, 280, 2200, 0, 0},/* E_REGVFMT_1920x1080i_60Hz_FP */
++ {1980, 1500, 1, 440, 6, 440, 440, 480, 25, 1495, 700, 1980, 746, 776},/* E_REGVFMT_1280x720p_50Hz_FP */
++ {2640, 2250, 1, 528, 6, 528, 528, 572, 20, 2248, 720, 2640, 0, 0},/* E_REGVFMT_1920x1080i_50Hz_FP */
++ {2750, 2250, 1, 638, 6, 638, 638, 682, 41, 2246, 830, 2750, 1122, 1167},/* E_REGVFMT_1920x1080p_24Hz_FP */
++ {2640, 2250, 1, 528, 6, 528, 528, 572, 41, 2246, 720, 2640, 1122, 1167},/* E_REGVFMT_1920x1080p_25Hz_FP */
++ {2200, 2250, 1, 88, 6, 88, 88, 132, 41, 2246, 280, 2200, 1122, 1167},/* E_REGVFMT_1920x1080p_30Hz_FP */
++#endif
++ {3300, 1500, 1, 1760, 6, 1760, 1760, 1800, 25, 1495, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_24Hz_FP */
++ {3960, 1500, 1, 2420, 6, 2420, 2420, 2460, 25, 1495, 2680, 3960, 0, 0},/* E_REGVFMT_1280x720p_25Hz_FP */
++ {3300, 1500, 1, 1760, 6, 1760, 1760, 1800, 25, 1495, 2020, 3300, 0, 0},/* E_REGVFMT_1280x720p_30Hz_FP */
++};
++
++#ifdef FORMAT_PC
++static CONST_DAT tmHdmiTxVidReg_t format_param_PC[HDMITX_VFMT_PC_NUM] =
++{
++ /* NPIX NLINE VsLineStart VsPixStart VsLineEnd VsPixEnd HsStart HsEnd ActiveVideoStart ActiveVideoEnd DeStart DeEnd */
++ /* npix nline vsl_s1 vsp_s1 vsl_e1 vsp_e1 hs_e hs_e vw_s1 vw_e1 de_s de_e */
++ {832, 520, 1, 24, 4, 24, 24, 64, 31, 511, 192, 832, 0, 0},/* E_REGVFMT_640x480p_72Hz */
++ {840, 500, 1, 16, 4, 16, 16, 80, 19, 499, 200, 840, 0, 0},/* E_REGVFMT_640x480p_75Hz */
++ {832, 509, 1, 56, 4, 56, 56, 112, 28, 508, 192, 832, 0, 0},/* E_REGVFMT_640x480p_85Hz */
++ {1056, 628, 1, 40, 5, 40, 40, 168, 27, 627, 256, 1056, 0, 0},/* E_REGVFMT_800x600p_60Hz */
++ {1040, 666, 1, 56, 7, 56, 56, 176, 29, 619, 240, 1040, 0, 0},/* E_REGVFMT_800x600p_72Hz */
++ {1056, 625, 1, 16, 4, 16, 16, 96, 24, 624, 256, 1056, 0, 0},/* E_REGVFMT_800x600p_75Hz */
++ {1048, 631, 1, 32, 4, 32, 32, 96, 30, 630, 248, 1048, 0, 0},/* E_REGVFMT_800x600p_85Hz */
++ {1344, 806, 1, 24, 7, 24, 24, 160, 35, 803, 320, 1344, 0, 0},/* E_REGVFMT_1024x768p_60Hz */
++ {1328, 806, 1, 24, 7, 24, 24, 160, 35, 803, 304, 1328, 0, 0},/* E_REGVFMT_1024x768p_70Hz */
++ {1312, 800, 1, 16, 4, 16, 16, 112, 31, 799, 288, 1312, 0, 0},/* E_REGVFMT_1024x768p_75Hz */
++ {1664, 798, 1, 64, 8, 64, 64, 192, 27, 795, 384, 1664, 0, 0},/* E_REGVFMT_1280x768p_60Hz */
++ {1688, 1066, 1, 48, 4, 48, 48, 160, 41, 1065, 408, 1688, 0, 0},/* E_REGVFMT_1280x1024p_60Hz */
++ {1792, 795, 1, 64, 7, 64, 64, 176, 24, 792, 432, 1792, 0, 0},/* E_REGVFMT_1360x768p_60Hz */
++ {1864, 1089, 1, 88, 5, 88, 88, 232, 36, 1086, 464, 1864, 0, 0},/* E_REGVFMT_1400x1050p_60Hz */
++ {2160, 1250, 1, 64, 4, 64, 64, 256, 49, 1249, 560, 2160, 0, 0},/* E_REGVFMT_1600x1200p_60Hz */
++ {1728, 1072, 1, 64, 4, 64, 64, 224, 47, 1071, 448, 1728, 0, 0} /* E_REGVFMT_1280x1024p_85Hz */
++};
++#endif/* FORMAT_PC */
++
++ /**
++ * Lookup table for each pixel clock frequency's CTS value in kHz
++ * according to SCS table "Audio Clock Recovery CTS Values"
++ */
++static CONST_DAT UInt32 kPixClkToAcrCts[E_PIXCLK_NUM][HDMITX_AFS_NUM] =
++{
++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */
++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */
++ { 28125, 31250, 28125, 31250, 28125, 31250, 28125}, /* E_PIXCLK_25175 */
++ { 25200, 28000, 25200, 28000, 25200, 28000, 25200}, /* E_PIXCLK_25200 */
++ { 27000, 30000, 27000, 30000, 27000, 30000, 27000}, /* E_PIXCLK_27000 */
++ { 27027, 30030, 27027, 30030, 27027, 30030, 27027}, /* E_PIXCLK_27027 */
++ { 54000, 60000, 54000, 60000, 54000, 60000, 54000}, /* E_PIXCLK_54000 */
++ { 54054, 60060, 54054, 60060, 54054, 60060, 54054}, /* E_PIXCLK_54054 */
++ { 59400, 65996, 59400, 65996, 59400, 65996, 59400}, /* E_PIXCLK_59400 */
++ {210937, 234375, 140625, 234375, 140625, 234375, 140625}, /* E_PIXCLK_74175 */
++ { 74250, 82500, 74250, 82500, 74250, 82500, 74250}, /* E_PIXCLK_74250 */
++ {421875, 234375, 140625, 234375, 140625, 234375, 140625}, /* E_PIXCLK_148350*/
++ {148500, 165000, 148500, 165000, 148500, 165000, 148500} /* E_PIXCLK_148500*/
++#ifdef FORMAT_PC
++ ,{ 31500, 35000, 31500, 35000, 31500, 35000, 31500}, /* E_PIXCLK_31500 */
++ { 36000, 40000, 36000, 40000, 36000, 40000, 36000}, /* E_PIXCLK_36000 */
++ { 40000, 44444, 40000, 44444, 40000, 44444, 40000}, /* E_PIXCLK_40000 */
++ { 49500, 55000, 49500, 55000, 49500, 55000, 49500}, /* E_PIXCLK_49500 */
++ { 50000, 55556, 50000, 55556, 50000, 55556, 50000}, /* E_PIXCLK_50000 */
++ { 56250, 62500, 56250, 62500, 56250, 62500, 56250}, /* E_PIXCLK_56250 */
++ { 65000, 72222, 65000, 72222, 65000, 72222, 65000}, /* E_PIXCLK_65000 */
++ { 75000, 83333, 75000, 83333, 75000, 83333, 75000}, /* E_PIXCLK_75000 */
++ { 78750, 87500, 78750, 87500, 78750, 87500, 78750}, /* E_PIXCLK_78750 */
++ {162000, 180000, 162000, 180000, 162000, 180000, 162000}, /* E_PIXCLK_162000*/
++ {157500, 175000, 157500, 175000, 157500, 175000, 157500} /* E_PIXCLK_157500 */
++#endif /* FORMAT_PC */
++};
++
++/**
++ * Lookup table for each pixel clock frequency's Audio Clock Regeneration N,
++ * according to SCS Table "Audio Clock Recovery N Values"
++ */
++static CONST_DAT UInt32 kPixClkToAcrN[E_PIXCLK_NUM][HDMITX_AFS_NUM] =
++{
++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */
++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */
++ { 4576, 7007, 6864, 14014, 13728, 28028, 27456}, /* E_PIXCLK_25175 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_25200 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_27000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_27027 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_54000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_54054 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_59400 */
++ {11648, 17836, 11648, 35672, 23296, 71344, 46592}, /* E_PIXCLK_74175 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_74250 */
++ {11648, 8918, 5824, 17836, 11648, 35672, 23296}, /* E_PIXCLK_148350*/
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576} /* E_PIXCLK_148500*/
++#ifdef FORMAT_PC
++ ,{ 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_31500 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_36000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_40000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_49500 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_50000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_56250 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_65000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_75000 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_78750 */
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576}, /* E_PIXCLK_162000*/
++ { 4096, 6272, 6144, 12544, 12288, 25088, 24576} /* E_PIXCLK_157500*/
++#endif /* FORMAT_PC */
++};
++
++/**
++ * Lookup table for each pixel clock frequency's Audio Divider, according to
++ * SCS Table "Audio Clock Recovery Divider Values"
++ */
++static CONST_DAT UInt8 kPixClkToAdiv[E_PIXCLK_NUM][HDMITX_AFS_NUM] =
++{
++ /* HDMITX_AFS_32k _AFS_48K _AFS_96K _AFS_192K */
++ /* _AFS_44_1k _AFS_88_2K _AFS_176_4K */
++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_25175 */
++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_25200 */
++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_27000 */
++ {2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_27027 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_54000 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_54054 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_59400 */
++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_74175 */
++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_74250 */
++ {5, 4, 4, 3, 3, 2, 2}, /* E_PIXCLK_148350 */
++ {5, 4, 4, 3, 3, 2, 2} /* E_PIXCLK_148500 */
++#ifdef FORMAT_PC
++ ,{2, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_31500 */
++ {3, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_36000 */
++ {3, 2, 2, 1, 1, 0, 0}, /* E_PIXCLK_40000 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_49500 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_50000 */
++ {3, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_56250 */
++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_65000 */
++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_75000 */
++ {4, 3, 3, 2, 2, 1, 1}, /* E_PIXCLK_78750 */
++ {5, 4, 4, 3, 3, 2, 2}, /* E_PIXCLK_162000 */
++ {5, 4, 4, 3, 3, 2, 2} /* E_PIXCLK_157500 */
++#endif /* FORMAT_PC */
++
++};
++
++/**
++ * Lookup table for converting a sampling frequency into the values
++ * required in channel status byte 3 according to IEC60958-3
++ */
++static CONST_DAT UInt8 kAfsToCSbyte3[HDMITX_AFS_NUM+1] =
++{
++ 3, /* HDMITX_AFS_32k */
++ 0, /* HDMITX_AFS_44_1k */
++ 2, /* HDMITX_AFS_48k */
++ 8, /* HDMITX_AFS_88_2k */
++ 10, /* HDMITX_AFS_96k */
++ 12, /* HDMITX_AFS_176_4k */
++ 14, /* HDMITX_AFS_192k */
++ 9, /* HDMITX_AFS_768k */
++ 1, /* HDMITX_AFS_NOT_INDICATED */
++};
++
++
++
++/**
++ * Lookup table for each CTS X factor's k and m register values
++ */
++static CONST_DAT UInt8 kCtsXToMK[HDMITX_CTSX_NUM][2] =
++{
++/* Register values Actual values */
++/* m k m, k */
++ {3, 0}, /* 8, 1 */
++ {3, 1}, /* 8, 2 */
++ {3, 2}, /* 8, 3 */
++ {3, 3}, /* 8, 4 */
++ {0, 0} /* 1, 1 */
++};
++
++/**
++ * Table of registers to reset and release the CTS generator
++ */
++static CONST_DAT tmHdmiTxRegMaskVal_t kResetCtsGenerator[] =
++{
++ {E_REG_P11_AIP_CNTRL_0_RW, E_MASKREG_P11_AIP_CNTRL_0_rst_cts, 1},
++ {E_REG_P11_AIP_CNTRL_0_RW, E_MASKREG_P11_AIP_CNTRL_0_rst_cts, 0},
++ {0,0,0}
++};
++
++/**
++ * Table of registers to bypass colour processing (up/down sampler & matrix)
++ */
++static CONST_DAT tmHdmiTxRegMaskVal_t kBypassColourProc[] =
++{
++ /* Bypass upsampler for RGB colourbars */
++ {E_REG_P00_HVF_CNTRL_0_W, E_MASKREG_P00_HVF_CNTRL_0_intpol, 0},
++ /* Bypass matrix for RGB colourbars */
++ {E_REG_P00_MAT_CONTRL_W, E_MASKREG_P00_MAT_CONTRL_mat_bp, 1},
++ /* Bypass downsampler for RGB colourbars */
++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_for, 0},
++ {0,0,0}
++};
++
++/**
++ * Table of registers to configure video input mode CCIR656*/
++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeCCIR656[] =
++{
++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 1},
++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1},
++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 1},*/
++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 1},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 1},
++ {0,0,0}
++};
++
++ /* Table of registers to configure video input mode for CCIR656 DDR with 1280*720p and 1920*1080i formats*/
++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeCCIR656_DDR_above720p[] =
++{
++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 1},
++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1},/*To be defined*/
++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},To be defined*/
++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0},
++ {0,0,0}
++};
++/**
++ * Table of registers to configure video input mode RGB444 or YUV444
++ */
++static CONST_DAT tmHdmiTxRegMaskVal_t kVinMode444[] =
++{
++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 0},
++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 0},
++ /* {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},*/
++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0},
++ {0,0,0}
++};
++
++/**
++ * Table of registers to configure video input mode YUV422
++ */
++static CONST_DAT tmHdmiTxRegMaskVal_t kVinModeYUV422[] =
++{
++ {E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_ccir656, 0},
++ {E_REG_P00_HVF_CNTRL_1_W, E_MASKREG_P00_HVF_CNTRL_1_semi_planar, 1},
++ /*{E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_clk1, 0},*/
++ {E_REG_P02_PLL_SERIAL_3_RW, E_MASKREG_P02_PLL_SERIAL_3_srl_ccir, 0},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_sel_vrf_clk, 0},
++ {0,0,0}
++};
++
++
++/**
++ * Lookup table for colour space conversion matrix register sets.
++ * Each array consists of 31 register values from MAT_CONTROL through
++ * to MAT_OO3_LSB
++ */
++static CONST_DAT UInt8 kMatrixPreset[MATRIX_PRESET_QTY][MATRIX_PRESET_SIZE] =
++{
++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x6F, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x3, 0x6F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
++ 0x6F, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40
++ }, /* RGB Full to RGB Limited */
++
++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x4, 0x1, 0x7, 0x0,
++ 0x64, 0x6, 0x88, 0x1, 0xC2, 0x7, 0xB7, 0x6, 0xD6, 0x7, 0x68, 0x1,
++ 0xC2, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ }, /* RGB Full to BT601 */
++
++ {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x75, 0x0, 0xBB, 0x0,
++ 0x3F, 0x6, 0x68, 0x1, 0xC2, 0x7, 0xD7, 0x6, 0xA6, 0x7, 0x99, 0x1,
++ 0xC2, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ }, /* RGB Full to BT709 */
++
++ {0x1, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0x54, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x2, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2,
++ 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
++ }, /* RGB Limited to RGB Full */
++
++ {0x2, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0x59, 0x1, 0x32, 0x0,
++ 0x75, 0x6, 0x4A, 0x2, 0x0C, 0x7, 0xAB, 0x6, 0xA5, 0x7, 0x4F, 0x2,
++ 0x0C, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ }, /* RGB Limited to BT601 */
++
++ {0x2, 0x7, 0xC0, 0x7, 0xC0, 0x7, 0xC0, 0x2, 0xDC, 0x0, 0xDA, 0x0,
++ 0x4A, 0x6, 0x24, 0x2, 0x0C, 0x7, 0xD0, 0x6, 0x6C, 0x7, 0x88, 0x2,
++ 0x0C, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ }, /* RGB Limited to BT709 */
++
++ {0x0, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x1, 0x2A, 0x7, 0x30, 0x7,
++ 0x9C, 0x1, 0x2A, 0x1, 0x99, 0x0, 0x0, 0x1, 0x2A, 0x0, 0x0, 0x2,
++ 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
++ }, /* BT601 to RGB Full */
++
++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x6, 0x9A, 0x7,
++ 0x54, 0x2, 0x0, 0x2, 0xBE, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3,
++ 0x77, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40
++ }, /* BT601 to RGB Limited */
++
++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x7, 0x96, 0x7,
++ 0xC5, 0x0, 0x0, 0x2, 0x0D, 0x0, 0x26, 0x0, 0x0, 0x0, 0x3B, 0x2,
++ 0x0A, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ }, /* BT601 to BT709 */
++
++ {0x0, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x1, 0x2A, 0x7, 0x77, 0x7,
++ 0xC9, 0x1, 0x2A, 0x1, 0xCB, 0x0, 0x0, 0x1, 0x2A, 0x0, 0x0, 0x2,
++ 0x1D, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
++ }, /* BT709 to RGB Full */
++
++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x7, 0x16, 0x7,
++ 0xA2, 0x2, 0x0, 0x3, 0x14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x3,
++ 0xA1, 0x0, 0x40, 0x0, 0x40, 0x0, 0x40
++ }, /* BT709 to RGB Limited */
++
++ {0x1, 0x7, 0xC0, 0x6, 0x0, 0x6, 0x0, 0x2, 0x0, 0x0, 0x62, 0x0,
++ 0x33, 0x0, 0x0, 0x1, 0xF7, 0x7, 0xDB, 0x0, 0x0, 0x7, 0xC7, 0x1,
++ 0xFB, 0x0, 0x40, 0x2, 0x0, 0x2, 0x0
++ } /* BT709 to BT601 */
++};
++
++/**
++ * This table gives us the index into the kMatrixPreset array, based
++ * on the input and output colourspaces.
++ * The co-ordinates into this array are tmbslTDA9989Colourspace_t enums.
++ * The value of -1 is returned for matching input/output colourspaces.
++ */
++static CONST_DAT Int kMatrixIndex[HDMITX_CS_NUM][HDMITX_CS_NUM] =
++{
++ {-1, E_MATRIX_RGBF_2_RGBL, E_MATRIX_RGBF_2_BT601, E_MATRIX_RGBF_2_BT709},
++ {E_MATRIX_RGBL_2_RGBF, -1, E_MATRIX_RGBL_2_BT601, E_MATRIX_RGBL_2_BT709},
++ {E_MATRIX_BT601_2_RGBF, E_MATRIX_BT601_2_RGBL, -1, E_MATRIX_BT601_2_BT709},
++ {E_MATRIX_BT709_2_RGBF, E_MATRIX_BT709_2_RGBL, E_MATRIX_BT709_2_BT601, -1}
++};
++
++/**
++ * Blue filter Lookup table for colour space conversion.
++ * Each array consists of 31 register values from MAT_CONTROL through
++ * to MAT_OO3_LSB
++ */
++static CONST_DAT UInt8 MatrixCoeffBlueScreen[][MATRIX_PRESET_SIZE] =
++{
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0
++ }, /* blue screen for RGB output color space */
++
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0
++ }, /* blue screen for YCbCr422 output color space */
++
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x1, 0x0, 0x3, 0x0
++ }, /* blue screen for YCbCr444 output color space */
++};
++
++/**
++ * Black filter Lookup table for colour space conversion.
++ * Each array consists of 31 register values from MAT_CONTROL through
++ * to MAT_OO3_LSB
++ */
++static CONST_DAT UInt8 MatrixCoeffBlackScreen[][MATRIX_PRESET_SIZE] =
++{
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
++ }, /* black screen for RGB output color space */
++
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0
++ }, /* black screen for YCbCr422 output color space */
++
++ {0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
++ 0x0, 0x0, 0x0, 0x2, 0x0, 0x2, 0x0
++ }, /* black screen for YCbCr444 output color space */
++};
++
++
++/*============================================================================*/
++/* DEFINES DECLARATIONS */
++/*============================================================================*/
++#define HDMITX_LAT_SCO_MAX_VAL 40
++#define HDMITX_LAT_SCO_MIN_VAL 34
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++/* Register values per device to restore colour processing after test pattern */
++static RAM_DAT UInt8 gMatContrl[HDMITX_UNITS_MAX];
++static RAM_DAT UInt8 gHvfCntrl0[HDMITX_UNITS_MAX];
++static RAM_DAT UInt8 gHvfCntrl1[HDMITX_UNITS_MAX];
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++static tmErrorCode_t setDeVs(tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D);
++static tmErrorCode_t setPixelRepeat(tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTx3DStructure_t structure3D);
++static tmErrorCode_t setSampling(tmHdmiTxobject_t *pDis);
++static UInt8 calculateChecksum(UInt8 *pData, Int numBytes);
++static UInt8 reg_vid_fmt(tmbslHdmiTxVidFmt_t fmt, \
++ tmbslHdmiTx3DStructure_t structure3D, \
++ UInt8 *idx, \
++ UInt8 *idx3d, \
++ struct sync_desc **sync);
++UInt8 pix_clk(tmbslHdmiTxVidFmt_t fmt, tmbslHdmiTxVfreq_t freq, UInt8 *pclk);
++static tmErrorCode_t InputConfig(tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxPixEdge_t sampleEdge,
++ tmbslHdmiTxPixRate_t pixRate,
++ tmbslHdmiTxUpsampleMode_t upsampleMode,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D);
++/*============================================================================*/
++/* tmbslTDA9989AudioInResetCts */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989AudioInResetCts
++(
++ tmUnitSelect_t txUnit
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Reset and release the CTS generator */
++ err = setHwRegisterFieldTable(pDis, &kResetCtsGenerator[0]);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989AudioInSetConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989AudioInSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaFmt_t aFmt,
++ tmbslHdmiTxI2sFor_t i2sFormat,
++ UInt8 chanI2s,
++ UInt8 chanDsd,
++ tmbslHdmiTxClkPolDsd_t clkPolDsd,
++ tmbslHdmiTxSwapDsd_t swapDsd,
++ UInt8 layout,
++ UInt16 uLatency_rd,
++ tmbslHdmiTxDstRate_t dstRate
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Value to write in register */
++
++ DUMMY_ACCESS(dstRate);
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameters */
++#ifdef TMFL_HBR_SUPPORT
++ RETIF_BADPARAM((aFmt != HDMITX_AFMT_SPDIF) &&
++ (aFmt != HDMITX_AFMT_I2S) &&
++ (aFmt != HDMITX_AFMT_OBA) &&
++ (aFmt != HDMITX_AFMT_HBR))
++
++#else /* TMFL_HBR_SUPPORT */
++ RETIF_BADPARAM((aFmt != HDMITX_AFMT_SPDIF) &&
++ (aFmt != HDMITX_AFMT_I2S) &&
++ (aFmt != HDMITX_AFMT_OBA))
++
++
++#endif /* TMFL_HBR_SUPPORT */
++
++ RETIF_BADPARAM(chanI2s >= HDMITX_CHAN_INVALID)
++ RETIF_BADPARAM(chanDsd >= HDMITX_CHAN_INVALID)
++ RETIF_BADPARAM(clkPolDsd >= HDMITX_CLKPOLDSD_INVALID)
++ RETIF_BADPARAM(swapDsd >= HDMITX_SWAPDSD_INVALID)
++ RETIF_BADPARAM(layout >= HDMITX_LAYOUT_INVALID)
++ RETIF_BADPARAM(uLatency_rd >= HDMITX_LATENCY_INVALID)
++
++ if ((aFmt == HDMITX_AFMT_I2S)
++#ifdef TMFL_HBR_SUPPORT
++ || (aFmt == HDMITX_AFMT_HBR)
++#endif /* TMFL_HBR_SUPPORT */
++ )
++ {
++ RETIF_BADPARAM((i2sFormat != HDMITX_I2SFOR_PHILIPS_L) &&
++ (i2sFormat != HDMITX_I2SFOR_OTH_L) &&
++ (i2sFormat != HDMITX_I2SFOR_OTH_R)
++ )
++ }
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ /*
++ power management :
++ freeze/wakeup SPDIF clock
++ */
++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \
++ E_MASKREG_FEAT_POWER_DOWN_spdif, \
++ (aFmt != HDMITX_AFMT_SPDIF));
++ RETIF_REG_FAIL(err);
++#endif
++
++ switch (aFmt)
++ {
++ case HDMITX_AFMT_SPDIF:
++ regVal = (UInt8)REG_VAL_SEL_AIP_SPDIF;
++ /* configure MUX_AP */
++ err = setHwRegister(pDis, E_REG_P00_MUX_AP_RW, TDA19989_MUX_AP_SELECT_SPDIF);
++ RETIF_REG_FAIL(err)
++ break;
++
++ case HDMITX_AFMT_I2S:
++ regVal = (UInt8)REG_VAL_SEL_AIP_I2S;
++ /* configure MUX_AP */
++ err = setHwRegister(pDis, E_REG_P00_MUX_AP_RW, TDA19989_MUX_AP_SELECT_I2S);
++ RETIF_REG_FAIL(err)
++ break;
++
++ case HDMITX_AFMT_OBA:
++ regVal = (UInt8)REG_VAL_SEL_AIP_OBA;
++ break;
++
++ case HDMITX_AFMT_HBR:
++ regVal = (UInt8)REG_VAL_SEL_AIP_HBR;
++ break;
++
++ default:
++ return TMBSL_ERR_HDMI_BAD_PARAMETER;
++ }
++
++
++ /* Set the audio input processor format to aFmt. */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_AIP_CLKSEL_W,
++ E_MASKREG_P00_AIP_CLKSEL_sel_aip,
++ regVal);
++ RETIF_REG_FAIL(err)
++
++ /* Channel status on 1 channel */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_CA_I2S_RW,
++ E_MASKREG_P11_CA_I2S_hbr_chstat_4,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ /* Select the audio format */
++ if ((aFmt == HDMITX_AFMT_I2S)
++#ifdef TMFL_HBR_SUPPORT
++ || (aFmt == HDMITX_AFMT_HBR)
++#endif /* TMFL_HBR_SUPPORT */
++ )
++ {
++ if (chanI2s != HDMITX_CHAN_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P11_CA_I2S_RW,
++ E_MASKREG_P11_CA_I2S_ca_i2s,
++ (UInt8)chanI2s);
++ }
++
++ /* Select the I2S format */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_I2S_FORMAT_RW,
++ E_MASKREG_P00_I2S_FORMAT_i2s_format,
++ (UInt8)i2sFormat);
++ RETIF_REG_FAIL(err)
++
++//#ifdef TMFL_HBR_SUPPORT
++ //if (aFmt == HDMITX_AFMT_HBR)
++ // {
++ /* Channel status on 1 channel */
++ // err = setHwRegisterField(pDis,
++ // E_REG_P11_CA_I2S_RW,
++ // E_MASKREG_P11_CA_I2S_hbr_chstat_4,
++ // 1);
++ // RETIF_REG_FAIL(err)
++ // }
++//#endif /* TMFL_HBR_SUPPORT */
++ }
++ else if (aFmt == HDMITX_AFMT_OBA)
++ {
++ if (chanDsd != HDMITX_CHAN_NO_CHANGE)
++ {
++ err = setHwRegister(pDis, E_REG_P11_CA_DSD_RW, chanDsd);
++ RETIF_REG_FAIL(err)
++ }
++ if (clkPolDsd != HDMITX_CLKPOLDSD_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_AIP_CLKSEL_W,
++ E_MASKREG_P00_AIP_CLKSEL_sel_pol_clk,
++ (UInt8)clkPolDsd);
++ RETIF_REG_FAIL(err)
++ }
++ if (swapDsd != HDMITX_SWAPDSD_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_swap,
++ (UInt8)swapDsd);
++ RETIF_REG_FAIL(err)
++ }
++ }
++
++ /* Set layout and latency */
++ if (layout != HDMITX_LAYOUT_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_layout,
++ layout);
++ RETIF_REG_FAIL(err)
++ }
++ if (uLatency_rd != HDMITX_LATENCY_NO_CHANGE)
++ {
++ err = setHwRegister(pDis, E_REG_P11_LATENCY_RD_RW, (UInt8)uLatency_rd);
++ RETIF_REG_FAIL(err)
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989AudioInSetCts */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989AudioInSetCts
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxctsRef_t ctsRef,
++ tmbslHdmiTxafs_t afs,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVfreq_t voutFreq,
++ UInt32 uCts,
++ UInt16 uCtsX,
++ tmbslHdmiTxctsK_t ctsK,
++ tmbslHdmiTxctsM_t ctsM,
++ tmbslHdmiTxDstRate_t dstRate
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Register value */
++ UInt8 pixClk; /* Pixel clock index */
++ UInt32 acrN; /* Audio clock recovery N */
++
++ DUMMY_ACCESS(dstRate);
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(ctsRef >= HDMITX_CTSREF_INVALID)
++ RETIF_BADPARAM(afs >= HDMITX_AFS_INVALID)
++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt))
++ RETIF_BADPARAM(voutFreq >= HDMITX_VFREQ_INVALID)
++ RETIF_BADPARAM(uCtsX >= HDMITX_CTSX_INVALID)
++ RETIF_BADPARAM(ctsK >= HDMITX_CTSK_INVALID)
++ RETIF_BADPARAM(ctsM >= HDMITX_CTSMTS_INVALID)
++
++
++ if (IS_TV(voutFmt))
++ {
++ if (voutFreq == HDMITX_VFREQ_50Hz)
++ {
++ RETIF(((voutFmt < HDMITX_VFMT_17_720x576p_50Hz) \
++ || (voutFmt > HDMITX_VFMT_31_1920x1080p_50Hz)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ else if (voutFreq == HDMITX_VFREQ_24Hz)
++ {
++ RETIF((voutFmt != HDMITX_VFMT_32_1920x1080p_24Hz) \
++ && (voutFmt != HDMITX_VFMT_60_1280x720p_24Hz),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ else if (voutFreq == HDMITX_VFREQ_25Hz)
++ {
++ RETIF((voutFmt != HDMITX_VFMT_33_1920x1080p_25Hz) \
++ && (voutFmt != HDMITX_VFMT_20_1920x1080i_50Hz) \
++ && (voutFmt != HDMITX_VFMT_61_1280x720p_25Hz),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ else if (voutFreq == HDMITX_VFREQ_30Hz)
++ {
++ RETIF((voutFmt != HDMITX_VFMT_34_1920x1080p_30Hz) \
++ && (voutFmt != HDMITX_VFMT_05_1920x1080i_60Hz) \
++ && (voutFmt != HDMITX_VFMT_62_1280x720p_30Hz),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ else
++ {
++ RETIF(voutFmt >= HDMITX_VFMT_17_720x576p_50Hz,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ }
++
++#ifdef FORMAT_PC
++ if (IS_PC(voutFmt))
++ {
++ if (voutFreq == HDMITX_VFREQ_60Hz)
++ {
++ RETIF(voutFmt > HDMITX_VFMT_PC_1600x1200p_60Hz,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ else if (voutFreq == HDMITX_VFREQ_70Hz)
++ {
++ RETIF(voutFmt != HDMITX_VFMT_PC_1024x768p_70Hz,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ else if (voutFreq == HDMITX_VFREQ_72Hz)
++ {
++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x480p_72Hz) ||
++ (voutFmt > HDMITX_VFMT_PC_800x600p_72Hz)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ else if (voutFreq == HDMITX_VFREQ_75Hz)
++ {
++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x480p_75Hz) ||
++ (voutFmt > HDMITX_VFMT_PC_1280x1024p_75Hz)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ else if (voutFreq == HDMITX_VFREQ_85Hz)
++ {
++ RETIF( ((voutFmt < HDMITX_VFMT_PC_640x350p_85Hz) ||
++ (voutFmt > HDMITX_VFMT_PC_1280x1024p_85Hz)),
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ else
++ {
++ RETIF(voutFmt != HDMITX_VFMT_PC_1024x768i_87Hz,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ }
++ }
++#endif /* FORMAT_PC */
++
++ /* Check for auto or manual CTS */
++ if (uCts == HDMITX_CTS_AUTO)
++ {
++ /* Auto */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_acr_man,
++ 0);
++ RETIF_REG_FAIL(err)
++ }
++ else
++ {
++ /* Manual */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_acr_man,
++ 1);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Derive M and K from X? */
++ if ((ctsM == HDMITX_CTSMTS_USE_CTSX) || (ctsK == HDMITX_CTSK_USE_CTSX))
++ {
++ RETIF_BADPARAM(uCtsX == HDMITX_CTSX_UNUSED)
++ ctsM = (tmbslHdmiTxctsM_t) kCtsXToMK[uCtsX][0];
++ ctsK = (tmbslHdmiTxctsK_t)kCtsXToMK[uCtsX][1];
++ }
++
++ /* Set the Post-divider measured timestamp factor */
++ regVal = (UInt8)ctsM;
++ err = setHwRegisterField(pDis,
++ E_REG_P11_CTS_N_RW,
++ E_MASKREG_P11_CTS_N_m_sel,
++ regVal);
++ RETIF_REG_FAIL(err)
++
++ /* Set the Pre-divider scale */
++ regVal = (UInt8)ctsK;
++ err = setHwRegisterField(pDis,
++ E_REG_P11_CTS_N_RW,
++ E_MASKREG_P11_CTS_N_k_sel,
++ regVal);
++ RETIF_REG_FAIL(err);
++
++ /* Use voutFmt and voutFreq to index into a lookup table to get
++ * the current pixel clock value. */
++ pix_clk(voutFmt, voutFreq, &pixClk);
++
++ if (pixClk != E_PIXCLK_INVALID)
++ {
++ /* Set the Audio Clock Recovery N multiplier based on the audio sample
++ * frequency afs and current pixel clock. */
++ acrN = kPixClkToAcrN[pixClk][afs];
++
++ /* Set ACR N multiplier [19 to 16] */
++ regVal = (UInt8)(acrN >> 16);
++ err = setHwRegister(pDis, E_REG_P11_ACR_N_2_RW, regVal);
++ RETIF_REG_FAIL(err)
++ /* Set ACR N multiplier [15 to 8] */
++ regVal = (UInt8)(acrN >> 8);
++ err = setHwRegister(pDis, E_REG_P11_ACR_N_1_RW, regVal);
++ RETIF_REG_FAIL(err)
++ /* Set ACR N multiplier [7 to 0] */
++ regVal = (UInt8)acrN;
++ err = setHwRegister(pDis, E_REG_P11_ACR_N_0_RW, regVal);
++ RETIF_REG_FAIL(err)
++
++ /* Set the CDC Audio Divider register based on the audio sample frequency
++ * afs and current pixel clock. */
++ regVal = kPixClkToAdiv[pixClk][afs];
++ err = setHwRegister(pDis, E_REG_P02_AUDIO_DIV_RW, regVal);
++ RETIF_REG_FAIL(err)
++
++ /* If auto CTS, get CTS value based on the audio sample
++ * frequency afs and current pixel clock. */
++ if (uCts == HDMITX_CTS_AUTO)
++ {
++ uCts = kPixClkToAcrCts[pixClk][afs];
++ }
++ }
++
++ /* Set manual or pixel clock CTS */
++ if (uCts != HDMITX_CTS_AUTO)
++ {
++ /* Set manual ACR CTS [19 to 16 */
++ regVal = (UInt8)(uCts >> 16);
++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_2_RW, regVal);
++ RETIF_REG_FAIL(err)
++ /* Set manual ACR CTS [15 to 8] */
++ regVal = (UInt8)(uCts >> 8);
++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_1_RW, regVal);
++ RETIF_REG_FAIL(err)
++ /* Set manual ACR CTS [7 to 0] */
++ regVal = (UInt8)uCts;
++ err = setHwRegister(pDis, E_REG_P11_ACR_CTS_0_RW, regVal);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Set the CTS clock reference register according to ctsRef */
++ regVal = (UInt8)ctsRef;
++ err = setHwRegisterField(pDis,
++ E_REG_P00_AIP_CLKSEL_W,
++ E_MASKREG_P00_AIP_CLKSEL_sel_fs,
++ regVal);
++ RETIF_REG_FAIL(err)
++
++ /* Reset and release the CTS generator */
++ err = setHwRegisterFieldTable(pDis, &kResetCtsGenerator[0]);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989AudioOutSetChanStatus */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989AudioOutSetChanStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxAudioData_t pcmIdentification,
++ tmbslHdmiTxCSformatInfo_t formatInfo,
++ tmbslHdmiTxCScopyright_t copyright,
++ UInt8 categoryCode,
++ tmbslHdmiTxafs_t sampleFreq,
++ tmbslHdmiTxCSclkAcc_t clockAccuracy,
++ tmbslHdmiTxCSmaxWordLength_t maxWordLength,
++ tmbslHdmiTxCSwordLength_t wordLength,
++ tmbslHdmiTxCSorigAfs_t origSampleFreq
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[4]; /* Buffer to hold channel status data */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(formatInfo >= HDMITX_CSFI_INVALID)
++ RETIF_BADPARAM(copyright >= HDMITX_CSCOPYRIGHT_INVALID)
++ RETIF_BADPARAM(sampleFreq > HDMITX_AFS_NOT_INDICATED)
++ RETIF_BADPARAM(clockAccuracy >= HDMITX_CSCLK_INVALID)
++ RETIF_BADPARAM(maxWordLength >= HDMITX_CSMAX_INVALID)
++ RETIF_BADPARAM(wordLength >= HDMITX_CSWORD_INVALID)
++ RETIF_BADPARAM(wordLength == HDMITX_CSWORD_RESVD)
++ RETIF_BADPARAM(origSampleFreq >= HDMITX_CSAFS_INVALID)
++ RETIF_BADPARAM(pcmIdentification >=HDMITX_AUDIO_DATA_INVALID)
++
++ /* Prepare Byte 0 */
++ buf[0] = ((UInt8)formatInfo << 3) | ((UInt8)copyright << 2) | ((UInt8)pcmIdentification<< 1);
++
++ /* Prepare Byte 1 */
++ buf[1] = categoryCode;
++
++ /* Prepare Byte 3 - note Byte 2 not in sequence in TDA9983 register map */
++ buf[2] = ((UInt8)clockAccuracy << 4) | kAfsToCSbyte3[sampleFreq];
++
++ /* Prepare Byte 4 */
++ buf[3] = ((UInt8)origSampleFreq << 4) | ((UInt8)wordLength << 1) |
++ (UInt8)maxWordLength;
++
++ /* Write 4 Channel Status bytes */
++ err = setHwRegisters(pDis, E_REG_P11_CH_STAT_B_0_RW, &buf[0], 4);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989AudioOutSetChanStatusMapping */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989AudioOutSetChanStatusMapping
++(
++ tmUnitSelect_t txUnit,
++ UInt8 sourceLeft[4],
++ UInt8 channelLeft[4],
++ UInt8 sourceRight[4],
++ UInt8 channelRight[4]
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[2]; /* Buffer to hold channel status data */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(sourceLeft[0] > HDMITX_CS_SOURCES_MAX)
++ RETIF_BADPARAM(channelLeft[0] > HDMITX_CS_CHANNELS_MAX)
++ RETIF_BADPARAM(sourceRight[0] > HDMITX_CS_SOURCES_MAX)
++ RETIF_BADPARAM(channelRight[0] > HDMITX_CS_CHANNELS_MAX)
++
++ /* Prepare Left byte */
++ buf[0] = ((UInt8)channelLeft[0] << 4) | (UInt8)sourceLeft[0];
++
++ /* Prepare Right byte */
++ buf[1] = ((UInt8)channelRight[0] << 4) | (UInt8)sourceRight[0];
++
++ /* Write 2 Channel Status bytes */
++ err = setHwRegisters(pDis, E_REG_P11_CH_STAT_B_2_ap0_l_RW, &buf[0], 2);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989AudioOutSetMute */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989AudioOutSetMute
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaMute_t aMute
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if sink is not an HDMI device */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(aMute >= HDMITX_AMUTE_INVALID)
++
++ /* audio mute workaround, un-map audio input before muting */
++ if (aMute == HDMITX_AMUTE_ON)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_SR_REG_W,
++ E_MASKREG_P00_SR_REG_sr_audio,
++ (UInt8)aMute);
++ RETIF(err != TM_OK, err)
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_SR_REG_W,
++ E_MASKREG_P00_SR_REG_sr_audio,
++ (UInt8) !aMute);
++ RETIF(err != TM_OK, err)
++
++ }
++
++ /* Reset the audio FIFO to mute audio */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo,
++ (UInt8)aMute);
++ RETIF(err != TM_OK, err)
++
++
++ return TM_OK;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerGet */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989ScalerGet
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScalerDiag_t *pScalerDiag
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(pScalerDiag); /* else not referenced */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerGetMode */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerGetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScaMode_t *pScalerMode
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(pScalerMode); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerInDisable */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerInDisable
++(
++ tmUnitSelect_t txUnit,
++ Bool bDisable
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(bDisable);
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetCoeffs */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989ScalerSetCoeffs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxScaLut_t lutSel,
++ UInt8 *pVsLut
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(lutSel); /* else is declared but not used */
++ DUMMY_ACCESS(pVsLut); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetFieldOrder */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerSetFieldOrder
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxIntExt_t topExt,
++ tmbslHdmiTxIntExt_t deExt,
++ tmbslHdmiTxTopSel_t topSel,
++ tmbslHdmiTxTopTgl_t topTgl
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(deExt); /* else is declared but not used */
++ DUMMY_ACCESS(topExt); /* else is declared but not used */
++ DUMMY_ACCESS(topSel); /* else is declared but not used */
++ DUMMY_ACCESS(topTgl); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetPhase */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerSetPhase
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHPhases_t horizontalPhases
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(horizontalPhases); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetLatency */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerSetLatency
++(
++ tmUnitSelect_t txUnit,
++ UInt8 scaler_latency
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(scaler_latency); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetFine */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerSetFine
++(
++ tmUnitSelect_t txUnit,
++ UInt16 uRefPix,
++ UInt16 uRefLine
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(uRefPix); /* else is declared but not used */
++ DUMMY_ACCESS(uRefLine); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989ScalerSetSync */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989ScalerSetSync
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVsMeth_t method,
++ tmbslHdmiTxVsOnce_t once
++)
++{
++ DUMMY_ACCESS(txUnit); /* else not referenced */
++ DUMMY_ACCESS(method); /* else is declared but not used */
++ DUMMY_ACCESS(once); /* else is declared but not used */
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++
++}
++
++/*============================================================================*/
++/* tmbslTDA9989TmdsSetOutputs */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989TmdsSetOutputs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTmdsOut_t tmdsOut
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(tmdsOut >= HDMITX_TMDSOUT_INVALID)
++
++ /* Set the TMDS output mode */
++ err = setHwRegisterField(pDis,
++ E_REG_P02_BUFFER_OUT_RW,
++ E_MASKREG_P02_BUFFER_OUT_srl_force,
++ (UInt8)tmdsOut);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989TmdsSetSerializer */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989TmdsSetSerializer
++(
++ tmUnitSelect_t txUnit,
++ UInt8 uPhase2,
++ UInt8 uPhase3
++)
++{
++
++ DUMMY_ACCESS(txUnit);
++ DUMMY_ACCESS(uPhase2);
++ DUMMY_ACCESS(uPhase3);
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989TestSetPattern */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989TestSetPattern
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTestPattern_t pattern
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 serviceMode; /* Register value */
++ UInt8 bars8; /* Register value */
++ UInt8 buf[MATRIX_PRESET_SIZE]; /* Temp buffer */
++ UInt8 i; /* Loop index */
++ UInt8 *MatrixCoeff=Null;
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check pattern parameters */
++ switch (pattern)
++ {
++ case HDMITX_PATTERN_CBAR4:
++ serviceMode = 1;
++ bars8 = 0;
++ break;
++ case HDMITX_PATTERN_BLUE:
++ MatrixCoeff = (UInt8*)&MatrixCoeffBlueScreen[pDis->voutMode][0]; //point to the blue matrix
++ serviceMode = 1;
++ bars8 = 1;
++ break;
++ case HDMITX_PATTERN_BLACK:
++ MatrixCoeff = (UInt8*)&MatrixCoeffBlackScreen[pDis->voutMode][0]; //point to the black matrix
++ case HDMITX_PATTERN_CBAR8:
++ serviceMode = 1;
++ bars8 = 1;
++ break;
++ case HDMITX_PATTERN_OFF:
++ serviceMode = 0;
++ bars8 = 0;
++ break;
++ default:
++ return TMBSL_ERR_HDMI_BAD_PARAMETER;
++ }
++
++ if (serviceMode)
++ {
++ if (!pDis->prevPattern) /* if a pattern is on, registers are already saved */
++ {
++ /* The kBypassColourProc registers are saved in tmbslTDA9989VideoSetInOut API */
++ /* Bypass up/down sampler and matrix for RGB colourbars */
++ setHwRegisterFieldTable(pDis, &kBypassColourProc[0]);
++ }
++ if (( pattern == HDMITX_PATTERN_BLUE )||( pattern == HDMITX_PATTERN_BLACK )) /* blue or black screen pattern */
++ {
++
++ /* To create blue or black screen, we use the internal color bar 8 on which we apply a matrix to change it to blue or black */
++ /* Set the first block byte separately, as it is shadowed and can't
++ * be set by setHwRegisters */
++
++ /* Set the first block byte separately, as it is shadowed and can't
++ * be set by setHwRegisters */
++ err = setHwRegister(pDis,
++ E_REG_P00_MAT_CONTRL_W,
++ MatrixCoeff[0]);
++ RETIF_REG_FAIL(err)
++
++ for (i = 0; i < MATRIX_PRESET_SIZE; i++)
++ {
++ buf[i] = MatrixCoeff[i];
++ }
++
++ /* Set the rest of the block */
++ err = setHwRegisters(pDis,
++ E_REG_P00_MAT_OI1_MSB_W,
++ &buf[1],
++ MATRIX_PRESET_SIZE - 1);
++ RETIF_REG_FAIL(err)
++ pDis->prevFilterPattern = True;
++ }
++ else /* colour bars patterns */
++ {
++ /* Set number of colour bars */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_0_W,
++ E_MASKREG_P00_HVF_CNTRL_0_rwb,
++ bars8);
++ RETIF_REG_FAIL(err)
++
++ /* Bypass up/down sampler and matrix for RGB colourbars */
++ setHwRegisterFieldTable(pDis, &kBypassColourProc[0]);
++ }
++ pDis->prevPattern = True;
++ }
++ else /* serviceMode == 0 */
++ {
++ if (pDis->prevFilterPattern)
++ {
++ /* Restore the previous Matrix when pattern goes off */
++ err = tmbslTDA9989MatrixSetConversion ( txUnit, pDis->vinFmt, pDis->vinMode, pDis->voutFmt, pDis->voutMode,pDis->dviVqr);
++ RETIF_REG_FAIL(err)
++
++ pDis->prevFilterPattern = False;
++ }
++ /* Restore kBypassColourProc registers when pattern goes off */
++ setHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, gMatContrl[txUnit]);
++ setHwRegister(pDis, E_REG_P00_HVF_CNTRL_0_W, gHvfCntrl0[txUnit]);
++ setHwRegister(pDis, E_REG_P00_HVF_CNTRL_1_W, gHvfCntrl1[txUnit]);
++ pDis->prevPattern = False;
++ }
++
++ /* Set Service Mode on or off */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_0_W,
++ E_MASKREG_P00_HVF_CNTRL_0_sm,
++ serviceMode);
++#ifdef TMFL_HDCP_SUPPORT
++ pDis->HDCPIgnoreEncrypt = True; /* Skip the next encrypt IT */
++#endif /* TMFL_HDCP_SUPPORT */
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetBlanking */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetBlanking
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxBlnkSrc_t blankitSource,
++ tmbslHdmiTxBlnkCode_t blankingCodes
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(blankitSource >= HDMITX_BLNKSRC_INVALID)
++ RETIF_BADPARAM(blankingCodes >= HDMITX_BLNKCODE_INVALID)
++
++ /* For each parameter that is not No Change, set its register */
++ if (blankitSource != HDMITX_BLNKSRC_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_blankit,
++ (UInt8)blankitSource);
++ RETIF_REG_FAIL(err)
++ }
++ if (blankingCodes != HDMITX_BLNKCODE_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_blc,
++ (UInt8)blankingCodes);
++ RETIF_REG_FAIL(err)
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D,
++ tmbslHdmiTxPixEdge_t sampleEdge,
++ tmbslHdmiTxPixRate_t pixRate,
++ tmbslHdmiTxUpsampleMode_t upsampleMode
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_INVALID)
++ RETIF_BADPARAM(sampleEdge >= HDMITX_PIXEDGE_INVALID)
++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID)
++ RETIF_BADPARAM(upsampleMode >= HDMITX_UPSAMPLE_INVALID)
++
++ err = InputConfig(pDis,
++ vinMode,
++ sampleEdge,
++ pixRate,
++ upsampleMode,
++ HDMITX_PIXREP_NO_CHANGE,
++ voutFmt,
++ structure3D);
++ RETIF_REG_FAIL(err)
++
++ return TM_OK;
++}
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetFine */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetFine
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPixSubpkt_t subpacketCount,
++ tmbslHdmiTxPixTogl_t toggleClk1
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(subpacketCount >= HDMITX_PIXSUBPKT_INVALID)
++ RETIF_BADPARAM(toggleClk1 >= HDMITX_PIXTOGL_INVALID)
++
++ /* IF subpacketCount is Fix at 0/1/2/3 THEN set subpacket count register
++ * to 0/1/2/3 and set subpacket sync register to 3
++ */
++ if (subpacketCount <= HDMITX_PIXSUBPKT_FIX_3)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_5_W,
++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt,
++ (UInt8)subpacketCount);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync,
++ HDMITX_PIXSUBPKT_SYNC_FIXED);
++ RETIF_REG_FAIL(err)
++ }
++ /* ELSE IF subpacketCount is Sync by Hemb/ Sync by Rising Edge DE/
++ * Sync by Rising Edge HS THEN set the unused subpacket count to zero and
++ * set subpacket sync register to 0/1/2
++ */
++ else if (subpacketCount != HDMITX_PIXSUBPKT_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_5_W,
++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt,
++ HDMITX_PIXSUBPKT_FIX_0);
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync,
++ (UInt8)(subpacketCount - HDMITX_PIXSUBPKT_SYNC_FIRST));
++ RETIF_REG_FAIL(err)
++ }
++
++ /* IF toggleClk1 is not No Change THEN set ckcase bitfield */
++ if (toggleClk1 != HDMITX_PIXTOGL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_5_W,
++ E_MASKREG_P00_VIP_CNTRL_5_ckcase,
++ (UInt8)toggleClk1);
++ RETIF_REG_FAIL(err)
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetMapping */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetMapping
++#ifdef TMFL_RGB_DDR_12BITS
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pSwapTable,
++ UInt8 *pMirrorTable,
++ UInt8 *pMux
++)
++#else
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pSwapTable,
++ UInt8 *pMirrorTable
++)
++#endif
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop counter */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(pSwapTable == Null)
++ RETIF_BADPARAM(pMirrorTable == Null)
++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++)
++ {
++ RETIF_BADPARAM(pSwapTable[i] >= HDMITX_VIN_PORT_SWAP_INVALID)
++ RETIF_BADPARAM(pMirrorTable[i] >= HDMITX_VIN_PORT_MIRROR_INVALID)
++ }
++
++ /* IF pswapTable[n] is not No Change THEN set the port swap registers from
++ * pswapTable[n]
++ */
++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++)
++ {
++ if (pSwapTable[0] < HDMITX_VIN_PORT_SWAP_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ kRegVip[i].Register,
++ kRegVip[i].MaskSwap,
++ pSwapTable[i]);
++ RETIF_REG_FAIL(err)
++ }
++ }
++
++ /* IF pMirrorTable[n] is not No Change THEN set the port mirror registers
++ * from pMirrorTable[n]
++ */
++ for (i = 0; i < HDMITX_VIN_PORT_MAP_TABLE_LEN; i++)
++ {
++ if (pMirrorTable[0] < HDMITX_VIN_PORT_MIRROR_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ kRegVip[i].Register,
++ kRegVip[i].MaskMirror,
++ pMirrorTable[i]);
++ RETIF_REG_FAIL(err)
++ }
++ }
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /*
++ mux for RGB_DDR_12bits
++ */
++ err = setHwRegister(pDis,E_REG_P00_MUX_VP_VIP_OUT_RW, *pMux);
++ RETIF_REG_FAIL(err);
++#endif
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SetVideoPortConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SetVideoPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaVideoPortTable,
++ UInt8 *pGndVideoPortTable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(pEnaVideoPortTable == Null)
++ RETIF_BADPARAM(pGndVideoPortTable == Null)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_0_RW,
++ pEnaVideoPortTable[0]);
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_1_RW,
++ pEnaVideoPortTable[1]);
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_2_RW,
++ pEnaVideoPortTable[2]);
++ RETIF_REG_FAIL(err)
++
++ /* err = setHwRegister(pDis,
++ E_REG_P00_GND_VP_0_RW,
++ pGndVideoPortTable[0]);
++ RETIF_REG_FAIL(err)*/
++
++ /* err = setHwRegister(pDis,
++ E_REG_P00_GND_VP_1_RW,
++ pGndVideoPortTable[1]);
++ RETIF_REG_FAIL(err)*/
++
++ /* err = setHwRegister(pDis,
++ E_REG_P00_GND_VP_2_RW,
++ pGndVideoPortTable[2]);
++ RETIF_REG_FAIL(err)*/
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SetAudioPortConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SetAudioPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaAudioPortTable,
++ UInt8 *pGndAudioPortTable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(pEnaAudioPortTable == Null)
++ RETIF_BADPARAM(pGndAudioPortTable == Null)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_AP_RW,
++ pEnaAudioPortTable[0]);
++ RETIF_REG_FAIL(err)
++
++ /* err = setHwRegister(pDis,
++ E_REG_P00_GND_AP_RW,
++ pGndAudioPortTable[0]);
++ RETIF_REG_FAIL(err)*/
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SetAudioClockPortConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SetAudioClockPortConfig
++(
++ tmUnitSelect_t txUnit,
++ UInt8 *pEnaAudioClockPortTable,
++ UInt8 *pGndAudioClockPortTable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(pEnaAudioClockPortTable == Null)
++ RETIF_BADPARAM(pGndAudioClockPortTable == Null)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_ACLK_RW,
++ pEnaAudioClockPortTable[0]);
++ RETIF_REG_FAIL(err)
++
++ /*err = setHwRegister(pDis,
++ E_REG_P00_GND_ACLK_RW,
++ pGndAudioClockPortTable[0]);
++ RETIF_REG_FAIL(err)*/
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* set_video replace E_REG_P00_VIDFORMAT_W register */
++/* use it for new video format */
++/*============================================================================*/
++tmErrorCode_t set_video(tmHdmiTxobject_t *pDis,tmbslHdmiTxVidFmt_t reg_idx,tmHdmiTxVidReg_t *format_param)
++{
++ tmErrorCode_t err;
++ UInt8 regVal;
++
++ regVal = 0x00;/* PR1570 FIXED */
++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].nPix;
++ err = setHwRegister(pDis, E_REG_P00_NPIX_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].nPix>>8);
++ err = setHwRegister(pDis, E_REG_P00_NPIX_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].nLine;
++ err = setHwRegister(pDis, E_REG_P00_NLINE_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].nLine>>8);
++ err = setHwRegister(pDis, E_REG_P00_NLINE_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].VsLineStart;
++ err = setHwRegister(pDis, E_REG_P00_VS_LINE_STRT_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].VsPixStart;
++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_STRT_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].VsPixStart>>8);
++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_STRT_1_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].VsLineEnd;
++ err = setHwRegister(pDis, E_REG_P00_VS_LINE_END_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].VsPixEnd;
++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_END_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].VsPixEnd>>8);
++ err = setHwRegister(pDis, E_REG_P00_VS_PIX_END_1_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].HsStart;
++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_START_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].HsStart>>8);
++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_START_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].HsEnd;
++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_STOP_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].HsEnd>>8);
++ err = setHwRegister(pDis, E_REG_P00_HS_PIX_STOP_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].ActiveVideoStart;
++ err = setHwRegister(pDis, E_REG_P00_VWIN_START_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++ err = setHwRegister(pDis, E_REG_P00_VWIN_START_1_MSB_W, 0);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].ActiveVideoEnd;
++ err = setHwRegister(pDis, E_REG_P00_VWIN_END_1_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].ActiveVideoEnd>>8);
++ err = setHwRegister(pDis, E_REG_P00_VWIN_END_1_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].DeStart;
++ err = setHwRegister(pDis, E_REG_P00_DE_START_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].DeStart>>8);
++ err = setHwRegister(pDis, E_REG_P00_DE_START_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].DeEnd;
++ err = setHwRegister(pDis, E_REG_P00_DE_STOP_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)(format_param[reg_idx].DeEnd>>8);
++ err = setHwRegister(pDis, E_REG_P00_DE_STOP_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++#ifdef TMFL_RGB_DDR_12BITS
++ if (format_param[reg_idx].ActiveSpaceStart) {
++ /* enable active space */
++ err = setHwRegisterField(pDis, E_REG_P00_ENABLE_SPACE_W, 0x01, 0x01);
++ RETIF_REG_FAIL(err);
++
++ /* set active space to black */
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_Y_DATA_W, 0x00);
++ RETIF_REG_FAIL(err);
++
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_U_DATA_W, 0x80);
++ RETIF_REG_FAIL(err);
++
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_V_DATA_W, 0x80);
++ RETIF_REG_FAIL(err);
++
++ /* active space definition */
++ regVal = (UInt8)format_param[reg_idx].ActiveSpaceStart;
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_START_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)((format_param[reg_idx].ActiveSpaceStart>>8) & 0x0F);
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_START_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)format_param[reg_idx].ActiveSpaceEnd;
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_END_LSB_W, regVal);
++ RETIF_REG_FAIL(err);
++
++ regVal = (UInt8)((format_param[reg_idx].ActiveSpaceEnd>>8) & 0x0F);
++ err = setHwRegister(pDis, E_REG_P00_VSPACE_END_MSB_W, regVal);
++ RETIF_REG_FAIL(err);
++ }
++ else {
++ /* let incoming pixels feel the active space (if any) */
++ err = setHwRegisterField(pDis, E_REG_P00_ENABLE_SPACE_W, 0x01, 0x00);
++ RETIF_REG_FAIL(err);
++ }
++#endif
++
++ return TM_OK;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetSyncAuto */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetSyncAuto
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSyncSource_t syncSource,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTx3DStructure_t structure3D
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 reg_idx,reg_idx3D; /* Video i/p fmt value used for comparison */
++ UInt8 embedded; /* Register value */
++ UInt8 syncMethod; /* Sync method */
++ UInt8 toggleV; /* V toggle */
++ UInt8 toggleH; /* H toggle */
++ UInt8 toggleX; /* X toggle */
++ UInt16 uRefPix; /* Output refpix */
++ UInt16 uRefLine; /* Output refline */
++#ifdef FORMAT_PC
++ UInt8 regVal;/* PR1570 FIXED */
++#endif /* FORMAT_PC */
++ struct sync_desc *sync;
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err);
++
++ /* Check parameters - syncSource must be specified */
++ RETIF_BADPARAM(syncSource >= HDMITX_SYNCSRC_NO_CHANGE);
++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt));
++
++ /* Look up the VIDFORMAT register format from the register format table */
++ /* Quit if the input format does not map to the register format */
++ RETIF_BADPARAM(reg_vid_fmt(vinFmt,structure3D,&reg_idx,&reg_idx3D,&sync));
++
++ /* Select values according to sync source */
++ embedded = 0;
++ switch (syncSource)
++ {
++ case HDMITX_SYNCSRC_EXT_VS:
++ syncMethod = 0;
++ toggleV = sync[BASE(reg_idx)].v_toggle;
++ toggleH = sync[BASE(reg_idx)].h_toggle;
++ toggleX = 0;
++ uRefPix = sync[BASE(reg_idx)].hfp;
++ uRefLine = sync[BASE(reg_idx)].vfp;
++ break;
++ case HDMITX_SYNCSRC_EMBEDDED:
++ embedded++;
++ /* fall thru */
++ case HDMITX_SYNCSRC_EXT_VREF:
++ default:
++ syncMethod = 1;
++ toggleV = 1;
++ toggleH = 1;
++ toggleX = 1;
++ uRefPix = sync[BASE(reg_idx)].href;
++ uRefLine = sync[BASE(reg_idx)].vref;
++ break;
++ }
++ /* Table has +1 added to refpix values which are not needed in
++ RGB444, YUV444 and YUV422 modes, but +2 is required in those cases */
++ if (vinMode != HDMITX_VINMODE_CCIR656)
++ {
++ uRefPix = uRefPix + 2;
++ }
++
++ /* ---------------------------------------------------------- */
++ /* Synchronicity software workaround issue number 106 */
++ /* ---------------------------------------------------------- */
++ if (vinMode == HDMITX_VINMODE_CCIR656) {
++ if (syncSource == HDMITX_SYNCSRC_EXT_VS) {
++ if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE) {
++
++ switch (reg_idx) {
++ case E_REGVFMT_720x480p_60Hz:
++ case E_REGVFMT_720x480i_60Hz:
++ case E_REGVFMT_720x576p_50Hz:
++ case E_REGVFMT_720x576i_50Hz:
++ uRefPix = uRefPix + 1;
++ break;
++ default:
++ /* do nothing... well I would say : FIXME */
++ break;
++ }
++
++ }
++ }
++ }
++
++
++ /* Set embedded sync */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_emb,
++ embedded);
++ RETIF_REG_FAIL(err)
++
++ /* Set sync method */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd,
++ syncMethod);
++ RETIF_REG_FAIL(err)
++
++/* printk("DBG auto toggle X:%d V:%d H:%d\n",toggleX,toggleV,toggleH); */
++ /* Set VH toggle */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl,
++ toggleV);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl,
++ toggleH);
++ RETIF_REG_FAIL(err)
++
++ /* Set X toggle */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl,
++ toggleX);
++ RETIF_REG_FAIL(err);
++
++#ifdef TMFL_RGB_DDR_12BITS
++ if (syncSource == HDMITX_SYNCSRC_EXT_VREF) {
++ if (structure3D == HDMITX_3D_FRAME_PACKING) {
++ /*
++ stereo sync signaling :
++ -----------------------
++
++ When there is a positive sync at the input pins, therefore a negative sync
++ at input of the TBG, then 3d_neg_vs signal has to be set at 1 (OR-function)
++ to create the correct VS to preset the line and pixel counters
++
++ case Vs > 0:
++ -----------
++ Vs : __/¨¨\__
++ Vs(TBG): ¨¨\__/¨¨ where Vs(TBG)=NOT(Vs)
++ 3D : ¨¨\_____
++ Stereo : ¨¨\__/¨¨ where Stereo = Vs(TBG) OR 3D because 3d_neg_vs = 1
++
++ case Vs < 0:
++ -----------
++ Vs : ¨¨\__/¨¨
++ Vs(TBG): __/¨¨\__ where Vs(TBG)=NOT(Vs)
++ 3D : ¨¨\_____
++ Stereo : __/¨¨\__ where Stereo = Vs(TBG) AND NOT(3D) because 3d_neg_vs = 0
++
++
++ It is possible to invert the incoming VS, HS and DE. In case of 3D format
++ the DE input will be the 3D signal. This signal will only be used to remove
++ 1 of the VS depending on the polarity of the 3D signal. When there is a need
++ to switch the Left or Right it is possible to invert the 3D signal with an
++ already existing register.
++
++ */
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIDFORMAT_W,
++ E_MASKREG_P00_VIDFORMAT_3d_neg_vs,
++ toggleV);
++ RETIF_REG_FAIL(err);
++ }
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIDFORMAT_W,
++ E_MASKREG_P00_VIDFORMAT_3d,
++ (structure3D == HDMITX_3D_FRAME_PACKING));
++ RETIF_REG_FAIL(err);
++ }
++#endif
++
++
++ if (EXTRA(reg_idx) && (structure3D != HDMITX_3D_FRAME_PACKING)) {
++ /* 2d extra video format */
++ RETIF_REG_FAIL(set_video(pDis,BASE(reg_idx),(tmHdmiTxVidReg_t *)format_param_extra));
++ }
++ else if (EXTRA(reg_idx3D) && (structure3D == HDMITX_3D_FRAME_PACKING)) {
++ /* 3d extra frame packing */
++ RETIF_REG_FAIL(set_video(pDis,BASE(reg_idx3D),(tmHdmiTxVidReg_t *)format_param_extra));
++ }
++ else {
++ /* see video set up using E_REG_P00_VIDFORMAT_W */
++ }
++
++
++#ifdef FORMAT_PC
++
++ if (IS_PC(vinFmt))
++ {
++ RETIF_REG_FAIL(set_video(pDis,reg_idx,(tmHdmiTxVidReg_t *)format_param_PC));
++
++ regVal = DEPTH_COLOR_PC;
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_pad,
++ regVal);
++ RETIF_REG_FAIL(err);
++ }
++#endif /* FORMAT_PC */
++
++ /* Set refpix, refline */
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFPIX_MSB_W, uRefPix);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFLINE_MSB_W, uRefLine);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoInSetSyncManual */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoInSetSyncManual
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSyncSource_t syncSource,
++ tmbslHdmiTxVsMeth_t syncMethod,
++ tmbslHdmiTxPixTogl_t toggleV,
++ tmbslHdmiTxPixTogl_t toggleH,
++ tmbslHdmiTxPixTogl_t toggleX,
++ UInt16 uRefPix,
++ UInt16 uRefLine
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 embedded; /* Register value */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(syncSource >= HDMITX_SYNCSRC_INVALID)
++ RETIF_BADPARAM(syncMethod >= HDMITX_VSMETH_INVALID)
++ RETIF_BADPARAM(toggleV >= HDMITX_PIXTOGL_INVALID)
++ RETIF_BADPARAM(toggleH >= HDMITX_PIXTOGL_INVALID)
++ RETIF_BADPARAM(toggleX >= HDMITX_PIXTOGL_INVALID)
++ RETIF_BADPARAM(uRefPix >= HDMITX_VOUT_FINE_PIXEL_INVALID)
++ RETIF_BADPARAM(uRefLine >= HDMITX_VOUT_FINE_LINE_INVALID)
++
++ if (syncSource != HDMITX_SYNCSRC_NO_CHANGE)
++ {
++ if (syncSource == HDMITX_SYNCSRC_EMBEDDED)
++ {
++ embedded = 1;
++ }
++ else
++ {
++ embedded = 0;
++ }
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_emb,
++ embedded);
++ RETIF_REG_FAIL(err)
++ }
++ if (syncMethod != HDMITX_VSMETH_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd,
++ (UInt8)syncMethod);
++ RETIF_REG_FAIL(err)
++ }
++/* printk("DBG manual toggle X:%d V:%d H:%d\n",toggleX,toggleV,toggleH); */
++ if (toggleV != HDMITX_PIXTOGL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl,
++ (UInt8)toggleV);
++ RETIF_REG_FAIL(err)
++ }
++ if (toggleH != HDMITX_PIXTOGL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl,
++ (UInt8)toggleH);
++ RETIF_REG_FAIL(err)
++ }
++ if (toggleX != HDMITX_PIXTOGL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl,
++ (UInt8)toggleX);
++ RETIF_REG_FAIL(err)
++ }
++ if (uRefPix < HDMITX_VOUT_FINE_PIXEL_NO_CHANGE)
++ {
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFPIX_MSB_W, uRefPix);
++ RETIF_REG_FAIL(err)
++ }
++ if (uRefLine < HDMITX_VOUT_FINE_LINE_NO_CHANGE)
++ {
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_REFLINE_MSB_W, uRefLine);
++ RETIF_REG_FAIL(err)
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoOutDisable */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989VideoOutDisable
++(
++ tmUnitSelect_t txUnit,
++ Bool bDisable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(bDisable > True)
++
++ /* Set or clear frame_dis in the scaler Timebase Control 0 register
++ * according to bDisable
++ */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_frame_dis,
++ (UInt8)bDisable);
++ if (bDisable)
++ {
++ setState(pDis, EV_OUTDISABLE);
++ }
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989VideoOutSetConfig */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoOutSetConfig
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxSinkType_t sinkType,
++ tmbslHdmiTxVoutMode_t voutMode,
++ tmbslHdmiTxVoutPrefil_t preFilter,
++ tmbslHdmiTxVoutYuvBlnk_t yuvBlank,
++ tmbslHdmiTxVoutQrange_t quantization
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Register value */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(sinkType >= HDMITX_SINK_INVALID)
++ RETIF_BADPARAM(voutMode >= HDMITX_VOUTMODE_INVALID)
++ RETIF_BADPARAM(preFilter >= HDMITX_VOUT_PREFIL_INVALID)
++ RETIF_BADPARAM(yuvBlank >= HDMITX_VOUT_YUV_BLNK_INVALID)
++ RETIF_BADPARAM(quantization >= HDMITX_VOUT_QRANGE_INVALID)
++
++ if (sinkType == HDMITX_SINK_EDID)
++ {
++ if (pDis->EdidStatus == HDMITX_EDID_NOT_READ)
++ {
++ /* EDID has not been read so assume simplest sink */
++ pDis->sinkType = HDMITX_SINK_DVI;
++ }
++ else
++ {
++ /* EDID has been read so set sink to the type that was read */
++ pDis->sinkType = pDis->EdidSinkType;
++ }
++ }
++ else
++ {
++ /* Set demanded sink type */
++ pDis->sinkType = sinkType;
++ }
++
++ /* Is DVI sink required? */
++ if (pDis->sinkType == HDMITX_SINK_DVI)
++ {
++ /* Mute the audio FIFO */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo,
++ 1);
++ RETIF_REG_FAIL(err)
++
++ /* Force RGB mode for DVI sink */
++ voutMode = HDMITX_VOUTMODE_RGB444;
++
++ /* Set HDMI HDCP mode off for DVI */
++ err = setHwRegisterFieldTable(pDis, &kVoutHdcpOff[0]);
++ RETIF_REG_FAIL(err);
++
++ HDCP_F1;
++
++ err = setHwRegisterField(pDis,
++ E_REG_P11_ENC_CNTRL_RW,
++ E_MASKREG_P11_ENC_CNTRL_ctl_code,
++ regVal);
++ RETIF_REG_FAIL(err)
++ }
++ else
++ {
++ /* Unmute the audio FIFO */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_AIP_CNTRL_0_RW,
++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ /* Set HDMI HDCP mode on for HDMI */
++ /* Also sets E_MASKREG_P11_ENC_CNTRL_ctl_code */
++ err = setHwRegisterFieldTable(pDis, &kVoutHdcpOn[0]);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* For each parameter that is not No Change, set its register */
++ if (voutMode != HDMITX_VOUTMODE_NO_CHANGE)
++ {
++ /* Save the output mode for later use by the matrix & downsampler */
++ pDis->voutMode = voutMode;
++ }
++ if (preFilter < HDMITX_VOUT_PREFIL_NO_CHANGE)
++ {
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ /*
++ power management :
++ freeze/wakeup SPDIF clock
++ */
++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \
++ E_MASKREG_FEAT_POWER_DOWN_prefilt, \
++ (preFilter == HDMITX_VOUT_PREFIL_OFF));
++ RETIF_REG_FAIL(err);
++#endif
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_0_W,
++ E_MASKREG_P00_HVF_CNTRL_0_prefil,
++ (UInt8)preFilter);
++ RETIF_REG_FAIL(err)
++ }
++ if (yuvBlank < HDMITX_VOUT_YUV_BLNK_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_yuvblk,
++ (UInt8)yuvBlank);
++ RETIF_REG_FAIL(err)
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoOutSetSync */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoOutSetSync
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVsSrc_t srcH,
++ tmbslHdmiTxVsSrc_t srcV,
++ tmbslHdmiTxVsSrc_t srcX,
++ tmbslHdmiTxVsTgl_t toggle,
++ tmbslHdmiTxVsOnce_t once
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 reg_idx;
++ struct sync_desc *sync;
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(srcH >= HDMITX_VSSRC_INVALID)
++ RETIF_BADPARAM(srcV >= HDMITX_VSSRC_INVALID)
++ RETIF_BADPARAM(srcX >= HDMITX_VSSRC_INVALID)
++ RETIF_BADPARAM(toggle >= HDMITX_VSTGL_INVALID)
++ RETIF_BADPARAM(once >= HDMITX_VSONCE_INVALID)
++
++ /* For each parameter that is not No Change, set its register */
++ if (srcH != HDMITX_VSSRC_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_1_W,
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_hs,
++ (UInt8)srcH);
++ RETIF_REG_FAIL(err)
++ }
++ if (srcV != HDMITX_VSSRC_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_1_W,
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_vs,
++ (UInt8)srcV);
++ RETIF_REG_FAIL(err)
++ }
++ if (srcX != HDMITX_VSSRC_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_1_W,
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_de,
++ (UInt8)srcX);
++ RETIF_REG_FAIL(err)
++ }
++ {
++ /* Hs Vs polarity fix */
++ /* set polarity back when VIDFORMAT_TABLE (E_REG_P00_VIDFORMAT_W) is not used */
++ RETIF_BADPARAM(reg_vid_fmt(pDis->vinFmt,0,&reg_idx,0,&sync));
++ if (EXTRA(reg_idx)) {
++ toggle= E_MASKREG_P00_TBG_CNTRL_1_vh_tgl & \
++ (0x04 | sync[BASE(reg_idx)].v_toggle | sync[BASE(reg_idx)].h_toggle);
++ }
++ }
++
++
++ if (toggle != HDMITX_VSTGL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_1_W,
++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl,
++ (UInt8)toggle);
++/* printk("DBG toogl CNTRL1:%d\n",toggle); */
++ RETIF_REG_FAIL(err)
++ }
++ if (once != HDMITX_VSONCE_NO_CHANGE)
++ {
++ /* Must be last register set */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_sync_once,
++ (UInt8)once);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Toggle TMDS serialiser force flags - stability fix */
++ err = setHwRegisterField(pDis,
++ E_REG_P02_BUFFER_OUT_RW,
++ E_MASKREG_P02_BUFFER_OUT_srl_force,
++ (UInt8)HDMITX_TMDSOUT_FORCED0);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterField(pDis,
++ E_REG_P02_BUFFER_OUT_RW,
++ E_MASKREG_P02_BUFFER_OUT_srl_force,
++ (UInt8)HDMITX_TMDSOUT_NORMAL);
++ RETIF_REG_FAIL(err)
++
++
++ if (once == HDMITX_VSONCE_ONCE)
++ {
++ /* Toggle output Sync Once flag for settings to take effect */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_sync_once,
++ (UInt8)HDMITX_VSONCE_EACH_FRAME);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterField(pDis,
++ E_REG_P00_TBG_CNTRL_0_W,
++ E_MASKREG_P00_TBG_CNTRL_0_sync_once,
++ (UInt8)HDMITX_VSONCE_ONCE);
++ RETIF_REG_FAIL(err)
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989VideoSetInOut */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989VideoSetInOut
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTx3DStructure_t structure3D,
++ tmbslHdmiTxScaMode_t scaModeRequest,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTxMatMode_t matMode,
++ tmbslHdmiTxVoutDbits_t datapathBits,
++ tmbslHdmiTxVQR_t dviVqr
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ tmbslHdmiTxScaMode_t scaMode; /* Scaler mode */
++ UInt8 reg_idx,reg_idx3D; /* Video o/p format value used for register */
++ UInt8 regVal;
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt))
++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt))
++
++ RETIF_BADPARAM(scaModeRequest >= HDMITX_SCAMODE_INVALID)
++ RETIF_BADPARAM(uPixelRepeat >= HDMITX_PIXREP_INVALID)
++ RETIF_BADPARAM(matMode >= HDMITX_MATMODE_INVALID)
++ RETIF_BADPARAM(datapathBits >= HDMITX_VOUT_DBITS_INVALID)
++
++ scaMode = HDMITX_SCAMODE_OFF;
++ pDis->scaMode = HDMITX_SCAMODE_OFF;
++
++ /* Get current input format if it must not change */
++ if (vinFmt == HDMITX_VFMT_NO_CHANGE)
++ {
++ RETIF(pDis->vinFmt == HDMITX_VFMT_NULL,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ vinFmt = pDis->vinFmt;
++ }
++ else
++ {
++ pDis->vinFmt = vinFmt;
++ pDis->h3dFpOn = (structure3D == HDMITX_3D_FRAME_PACKING);
++
++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++ if (IS_TV(pDis->vinFmt)) {
++
++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, 0);
++ RETIF(err != TM_OK, err);
++
++ err = setHwRegister(pDis, E_REG_P00_NDIV_IM_W, kndiv_im[vinFmt]);
++ RETIF(err != TM_OK, err);
++
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, kclk_div[vinFmt]);
++ RETIF(err != TM_OK, err);
++
++ }
++ else {
++
++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, E_MASKREG_P00_TIMER_H_im_clksel);
++ RETIF(err != TM_OK, err);
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, 17);
++ RETIF(err != TM_OK, err);
++ }
++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++
++ }
++
++ /* Get current output format if it must not change */
++ if (voutFmt == HDMITX_VFMT_NO_CHANGE)
++ {
++ RETIF(pDis->voutFmt == HDMITX_VFMT_NULL,
++ TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++ voutFmt = pDis->voutFmt;
++ }
++ else
++ {
++ pDis->voutFmt = voutFmt;
++ }
++ if (pDis->voutMode == HDMITX_VOUTMODE_RGB444)
++ {
++ if ((pDis->voutFmt >= HDMITX_VFMT_02_720x480p_60Hz) && (IS_TV(pDis->voutFmt)))
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_vqr,
++ (UInt8) HDMITX_VOUT_QRANGE_RGB_YUV);
++ RETIF_REG_FAIL(err)
++ }
++ else /*Format PC or VGA*/
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_vqr,
++ (UInt8) HDMITX_VOUT_QRANGE_FS);
++ RETIF_REG_FAIL(err)
++ }
++ }
++ else
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_vqr,
++ (UInt8) HDMITX_VOUT_QRANGE_YUV);
++ RETIF_REG_FAIL(err);
++ }
++
++ /* Set pixel repetition - sets pixelRepeatCount, used by setScalerFormat */
++ err = setPixelRepeat(pDis, voutFmt, uPixelRepeat, structure3D);
++ RETIF(err != TM_OK, err);
++
++ /* If scaler mode is auto then set mode based on input and output format */
++ if (scaMode != HDMITX_SCAMODE_NO_CHANGE)
++ {
++ /* Set scaler clock */
++ regVal = 0;
++ if ((pDis->pixelRepeatCount > HDMITX_PIXREP_MIN) &&
++ (pDis->pixelRepeatCount <= HDMITX_PIXREP_MAX))
++ {
++ regVal = 2;
++ }
++ else if (pDis->vinMode == HDMITX_VINMODE_CCIR656)
++ {
++ regVal = (UInt8)((pDis->scaMode == HDMITX_SCAMODE_ON) ? 0 : 1);
++
++ if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE)
++ {
++ regVal = 0;
++ }
++ }
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_SEL_CLK_RW,
++ E_MASKREG_P02_SEL_CLK_sel_vrf_clk,
++ regVal);
++ RETIF_REG_FAIL(err);
++
++ /* Look up the VIDFORMAT register format from the register format table */
++ RETIF_BADPARAM(reg_vid_fmt(vinFmt,structure3D,&reg_idx,&reg_idx3D,0));
++
++ /* Set format register for the selected output format voutFmt */
++ if (PREFETCH(reg_idx3D) && (structure3D == HDMITX_3D_FRAME_PACKING)) {
++ /* embedded 3D video format */
++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W,reg_idx3D);
++ }
++ else if (PREFETCH(reg_idx) && (structure3D != HDMITX_3D_FRAME_PACKING)) {
++ /* embedded 2D video format */
++/* printk("DBG %s E_REG_P00_VIDFORMAT_W used\n",__func__); */
++ err = setHwRegister(pDis, E_REG_P00_VIDFORMAT_W,reg_idx);
++ }
++ else {
++ /* see video set up using set_video() */
++ }
++ RETIF_REG_FAIL(err);
++
++ }
++
++ /* Set VS and optional DE */
++ err = setDeVs(pDis, voutFmt, structure3D);
++ RETIF(err != TM_OK, err);
++
++ /* If matrix mode is auto then set mode based on input and output format */
++ if (matMode != HDMITX_MATMODE_NO_CHANGE)
++ {
++ if (matMode == HDMITX_MATMODE_AUTO)
++ {
++ err = tmbslTDA9989MatrixSetConversion(txUnit, vinFmt,
++ pDis->vinMode, voutFmt, pDis->voutMode,pDis->dviVqr);
++ }
++ else
++ {
++ err = tmbslTDA9989MatrixSetMode(txUnit, HDMITX_MCNTRL_OFF,
++ HDMITX_MSCALE_NO_CHANGE);
++ }
++ RETIF(err != TM_OK, err)
++ }
++
++ /* Set upsampler and downsampler */
++ err = setSampling(pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Set colour component bit depth */
++ if (datapathBits != HDMITX_VOUT_DBITS_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_pad,
++ (UInt8)datapathBits);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Save kBypassColourProc registers before pattern goes on */
++ getHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, &gMatContrl[txUnit]);
++ getHwRegister(pDis, E_REG_P00_HVF_CNTRL_0_W, &gHvfCntrl0[txUnit]);
++ getHwRegister(pDis, E_REG_P00_HVF_CNTRL_1_W, &gHvfCntrl1[txUnit]);
++
++ setState(pDis, EV_SETINOUT);
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989MatrixSetCoeffs */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989MatrixSetCoeffs
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatCoeff_t *pMatCoeff
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ UInt8 buf[HDMITX_MAT_COEFF_NUM * 2]; /* Temp buffer */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pMatCoeff == (tmbslHdmiTxMatCoeff_t *)0)
++ for (i = 0; i < HDMITX_MAT_COEFF_NUM; i++)
++ {
++ RETIF_BADPARAM((pMatCoeff->Coeff[i] < HDMITX_MAT_OFFSET_MIN) ||
++ (pMatCoeff->Coeff[i] > HDMITX_MAT_OFFSET_MAX))
++ }
++
++ /* Convert signed 11 bit values from Coeff array to pairs of MSB-LSB
++ * register values, and write to register pairs
++ */
++ for (i = 0; i < HDMITX_MAT_COEFF_NUM; i++)
++ {
++ /* Mask & copy MSB */
++ buf[i*2] = (UInt8)(((UInt16)pMatCoeff->Coeff[i] & 0x0700) >> 8);
++ /* Copy LSB */
++ buf[(i*2)+1] = (UInt8)((UInt16)pMatCoeff->Coeff[i] & 0x00FF);
++ }
++ err = setHwRegisters(pDis,
++ E_REG_P00_MAT_P11_MSB_W,
++ &buf[0],
++ HDMITX_MAT_COEFF_NUM * 2);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989MatrixSetConversion */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989MatrixSetConversion
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTxVoutMode_t voutMode,
++ tmbslHdmiTxVQR_t dviVqr
++)
++{
++ tmHdmiTxobject_t *pDis; /* Ptr to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ tmbslTDA9989Colourspace_t cspace_in; /* Input colourspaces */
++ tmbslTDA9989Colourspace_t cspace_out; /* Output colourspaces */
++ Int matrixIndex;/* Index into matrix preset array */
++ UInt8 buf[MATRIX_PRESET_SIZE]; /* Temp buffer */
++ UInt8 i; /* Loop index */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt))
++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt))
++ /* NB: NO_CHANGE is not valid for this function, so limit to actual values*/
++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_NO_CHANGE)
++ /* NB: NO_CHANGE is not valid for this function, so limit to actual values*/
++ RETIF_BADPARAM(voutMode >= HDMITX_VOUTMODE_NO_CHANGE)
++
++ /* Since vinMode and voutMode are different types, we don't use a local
++ function to do this and use inline code twice */
++
++
++ /* Calculate input colour space */
++ switch (vinFmt)
++ { /* Catch the HD modes */
++ case HDMITX_VFMT_04_1280x720p_60Hz:
++ case HDMITX_VFMT_05_1920x1080i_60Hz:
++ case HDMITX_VFMT_16_1920x1080p_60Hz:
++ case HDMITX_VFMT_19_1280x720p_50Hz:
++ case HDMITX_VFMT_20_1920x1080i_50Hz:
++ case HDMITX_VFMT_31_1920x1080p_50Hz:
++ case HDMITX_VFMT_32_1920x1080p_24Hz:
++ case HDMITX_VFMT_33_1920x1080p_25Hz:
++ case HDMITX_VFMT_34_1920x1080p_30Hz:
++ case HDMITX_VFMT_60_1280x720p_24Hz:
++ case HDMITX_VFMT_61_1280x720p_25Hz:
++ case HDMITX_VFMT_62_1280x720p_30Hz:
++
++ if(vinMode == HDMITX_VINMODE_RGB444) /* RGB */
++ {
++ cspace_in = HDMITX_CS_RGB_LIMITED;
++ }
++ else /* CCIR656, YUV444, YU422 */
++ {
++ cspace_in = HDMITX_CS_YUV_ITU_BT709;
++ }
++ break;
++ default: /* Now all the SD modes */
++ if(vinMode == HDMITX_VINMODE_RGB444) /* we're RGB */
++ {
++ cspace_in = HDMITX_CS_RGB_LIMITED;
++ }
++ else /* CCIR656, YUV444, YU422 */
++ {
++ cspace_in = HDMITX_CS_YUV_ITU_BT601;
++ }
++ break;
++ }
++
++/* } */
++
++ /* Calculate output colour space */
++#ifdef FORMAT_PC
++ if(IS_PC(voutFmt))
++ {
++ /* Catch the PC formats */
++ cspace_in = HDMITX_CS_RGB_FULL; /* PR1570 FIXED */
++ cspace_out = HDMITX_CS_RGB_FULL;
++ }
++ else
++ {
++#endif
++ switch (voutFmt)
++ { /* Catch the HD modes */
++ case HDMITX_VFMT_04_1280x720p_60Hz:
++ case HDMITX_VFMT_05_1920x1080i_60Hz:
++ case HDMITX_VFMT_16_1920x1080p_60Hz:
++ case HDMITX_VFMT_19_1280x720p_50Hz:
++ case HDMITX_VFMT_20_1920x1080i_50Hz:
++ case HDMITX_VFMT_31_1920x1080p_50Hz:
++ case HDMITX_VFMT_32_1920x1080p_24Hz:
++ case HDMITX_VFMT_33_1920x1080p_25Hz:
++ case HDMITX_VFMT_34_1920x1080p_30Hz:
++ case HDMITX_VFMT_60_1280x720p_24Hz:
++ case HDMITX_VFMT_61_1280x720p_25Hz:
++ case HDMITX_VFMT_62_1280x720p_30Hz:
++
++ if(voutMode == HDMITX_VOUTMODE_RGB444) /* RGB */
++ {
++ cspace_out = HDMITX_CS_RGB_LIMITED;
++ }
++ else /* YUV444 or YUV422 */
++ {
++ cspace_out = HDMITX_CS_YUV_ITU_BT709;
++ }
++ break;
++ default: /* Now all the SD modes */
++ if(voutMode == HDMITX_VOUTMODE_RGB444) /* RGB */
++ {
++ cspace_out = HDMITX_CS_RGB_LIMITED;
++ }
++ else /* YUV444 or YUV422 */
++ {
++ cspace_out = HDMITX_CS_YUV_ITU_BT601;
++ }
++ break;
++ }
++#ifdef FORMAT_PC
++ }
++#endif
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ /*
++ power management :
++ freeze/wakeup color space conversion clock
++ */
++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \
++ E_MASKREG_FEAT_POWER_DOWN_csc, \
++ (cspace_in == cspace_out));
++ RETIF_REG_FAIL(err);
++#endif
++
++ if (cspace_in == cspace_out)
++ {
++ /* Switch off colour matrix by setting bypass flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_MAT_CONTRL_W,
++ E_MASKREG_P00_MAT_CONTRL_mat_bp,
++ 1);
++ }
++ else
++ {
++ /* Load appropriate values into matrix - we have preset blocks of
++ * 31 register vales in a table, just need to work out which set to use
++ */
++ matrixIndex = kMatrixIndex[cspace_in][cspace_out];
++
++ /* Set the first block byte separately, as it is shadowed and can't
++ * be set by setHwRegisters */
++ err = setHwRegister(pDis,
++ E_REG_P00_MAT_CONTRL_W,
++ kMatrixPreset[matrixIndex][0]);
++ RETIF_REG_FAIL(err)
++
++ for (i = 0; i < MATRIX_PRESET_SIZE; i++)
++ {
++ buf[i] = kMatrixPreset[matrixIndex][i];
++ }
++
++ /* Set the rest of the block */
++ err = setHwRegisters(pDis,
++ E_REG_P00_MAT_OI1_MSB_W,
++ &buf[1],
++ MATRIX_PRESET_SIZE - 1);
++ }
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989MatrixSetInputOffset */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989MatrixSetInputOffset
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatOffset_t *pMatOffset
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ UInt8 buf[HDMITX_MAT_OFFSET_NUM * 2]; /* Temp buffer */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pMatOffset == (tmbslHdmiTxMatOffset_t *)0)
++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++)
++ {
++ RETIF_BADPARAM((pMatOffset->Offset[i] < HDMITX_MAT_OFFSET_MIN) ||
++ (pMatOffset->Offset[i] > HDMITX_MAT_OFFSET_MAX))
++ }
++
++ /* Convert signed 11 bit values from Offset array to pairs of MSB-LSB
++ * register values, and write to register pairs
++ */
++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++)
++ {
++ /* Mask & copy MSB */
++ buf[i*2] = (UInt8)(((UInt16)pMatOffset->Offset[i] & 0x0700) >> 8);
++ /* Copy LSB */
++ buf[(i*2)+1] = (UInt8)((UInt16)pMatOffset->Offset[i] & 0x00FF);
++ }
++ err = setHwRegisters(pDis,
++ E_REG_P00_MAT_OI1_MSB_W,
++ &buf[0],
++ HDMITX_MAT_OFFSET_NUM * 2);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989MatrixSetMode */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989MatrixSetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxmCntrl_t mControl,
++ tmbslHdmiTxmScale_t mScale
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM((mControl > HDMITX_MCNTRL_MAX) ||
++ (mScale > HDMITX_MSCALE_MAX))
++
++ /* For each value that is not NoChange, update the appropriate register */
++ if (mControl != HDMITX_MCNTRL_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_MAT_CONTRL_W,
++ E_MASKREG_P00_MAT_CONTRL_mat_bp,
++ (UInt8)mControl);
++ RETIF_REG_FAIL(err)
++ }
++
++ if (mScale != HDMITX_MSCALE_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_MAT_CONTRL_W,
++ E_MASKREG_P00_MAT_CONTRL_mat_sc,
++ (UInt8)mScale);
++ RETIF_REG_FAIL(err)
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989MatrixSetOutputOffset */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989MatrixSetOutputOffset
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxMatOffset_t *pMatOffset
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ UInt8 buf[HDMITX_MAT_OFFSET_NUM * 2]; /* Temp buffer */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM(pMatOffset == (tmbslHdmiTxMatOffset_t *)0)
++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++)
++ {
++ RETIF_BADPARAM((pMatOffset->Offset[i] < HDMITX_MAT_OFFSET_MIN) ||
++ (pMatOffset->Offset[i] > HDMITX_MAT_OFFSET_MAX))
++ }
++
++ /* Convert signed 11 bit values from Offset array to pairs of MSB-LSB
++ * register values, and write to register pairs
++ */
++ for (i = 0; i < HDMITX_MAT_OFFSET_NUM; i++)
++ {
++ /* Mask & copy MSB */
++ buf[i*2] = (UInt8)(((UInt16)pMatOffset->Offset[i] & 0x0700) >> 8);
++ /* Copy LSB */
++ buf[(i*2)+1] = (UInt8)((UInt16)pMatOffset->Offset[i] & 0x00FF);
++ }
++ err = setHwRegisters(pDis,
++ E_REG_P00_MAT_OO1_MSB_W,
++ &buf[0],
++ HDMITX_MAT_OFFSET_NUM * 2);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetAclkRecovery */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989PktSetAclkRecovery
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ /* Write the ACR packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_acr,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetAcp */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetAcp
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ UInt8 uAcpType,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[3]; /* Temp buffer to hold header bytes */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT)
++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++
++ /* Data to change, start by clearing ACP packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_acp,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare ACP header */
++ buf[0] = 0x04; /* ACP packet */
++ buf[1] = uAcpType;
++ buf[2] = 0; /* Reserved [HDMI 1.2] */
++
++
++ /* Write 3 header bytes to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ACP_HB0_RW,
++ &buf[0],
++ 3);
++ RETIF_REG_FAIL(err)
++
++ /* Write "byteCnt" bytes of data to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ACP_PB0_RW,
++ &pPkt->dataByte[0],
++ (UInt16)byteCnt);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the ACP packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_acp,
++ (UInt8)bEnable);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetAudioInfoframe */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetAudioInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktAif_t *pPkt,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[9]; /* Temp buffer to hold header/packet bytes */
++ UInt16 bufReg; /* Base register used for writing InfoFrame*/
++ UInt16 flagReg;/* Flag register to be used */
++ UInt8 flagMask;/* Mask used for writing flag register */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM(pPkt->CodingType > 0x0F)
++ RETIF_BADPARAM(pPkt->ChannelCount > 0x07)
++ RETIF_BADPARAM(pPkt->SampleFreq > 0x07)
++ RETIF_BADPARAM(pPkt->SampleSize > 0x03)
++ /* No need to check ChannelAlloc - all values are allowed */
++ RETIF_BADPARAM((pPkt->DownMixInhibit != True) &&
++ (pPkt->DownMixInhibit != False))
++ RETIF_BADPARAM(pPkt->LevelShift > 0x0F)
++ }
++
++ /* Only supported for device N4 or later */
++
++ /* We're using n4 or later, use IF4 buffer for Audio InfoFrame */
++ bufReg = E_REG_P10_IF4_HB0_RW;
++ flagReg = E_REG_P11_DIP_IF_FLAGS_RW;
++ flagMask = E_MASKREG_P11_DIP_IF_FLAGS_if4;
++
++ if(pPkt != Null)
++ {
++ /* Data to change, start by clearing AIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ flagReg,
++ flagMask,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare AIF header */
++ buf[0] = 0x84; /* Audio InfoFrame */
++ buf[1] = 0x01; /* Version 1 [HDMI 1.2] */
++ buf[2] = 0x0A; /* Length [HDMI 1.2] */
++
++ /* Prepare AIF packet (byte numbers offset by 3) */
++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */
++ buf[1+3] = ((pPkt->CodingType & 0x0F) << 4) |
++ (pPkt->ChannelCount & 0x07); /* CT3-0, CC2-0 */
++ buf[2+3] = ((pPkt->SampleFreq & 0x07) << 2) |
++ (pPkt->SampleSize & 0x03); /* SF2-0, SS1-0 */
++ buf[3+3] = 0; /* [HDMI 1.2] */
++ buf[4+3] = pPkt->ChannelAlloc; /* CA7-0 */
++ buf[5+3] = ((pPkt->LevelShift & 0x0F) << 3); /* LS3-0 */
++ if(pPkt->DownMixInhibit == True)
++ {
++ buf[5+3] += 0x80; /* DMI bit */
++ }
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes. We exclude bytes PB6 to PB10 (which we
++ * are not writing) since they are zero.
++ */
++ buf[0+3] = calculateChecksum(&buf[0], 0x0A+1+3-5);
++
++ /* Write header and packet bytes in one operation */
++ err = setHwRegisters(pDis,
++ bufReg,
++ &buf[0],
++ 9);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write AIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ flagReg,
++ flagMask,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetGeneralCntrl */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989PktSetGeneralCntrl
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxaMute_t *paMute,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(paMute != Null)
++ {
++ RETIF_BADPARAM((*paMute != HDMITX_AMUTE_OFF) && (*paMute != HDMITX_AMUTE_ON))
++
++ if (*paMute == HDMITX_AMUTE_ON)
++ {
++ err = setHwRegister(pDis, E_REG_P11_GC_AVMUTE_RW, 0x02);
++ RETIF_REG_FAIL(err)
++ }
++ else
++ {
++ err = setHwRegister(pDis, E_REG_P11_GC_AVMUTE_RW, 0x01);
++ RETIF_REG_FAIL(err)
++ }
++ }
++
++ /* Set or clear GC packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_gc,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetIsrc1 */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetIsrc1
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ Bool bIsrcCont,
++ Bool bIsrcValid,
++ UInt8 uIsrcStatus,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[3]; /* Temp buffer to hold header bytes */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM((bIsrcCont != True) && (bIsrcCont != False))
++ RETIF_BADPARAM((bIsrcValid != True) && (bIsrcValid != False))
++ RETIF_BADPARAM(uIsrcStatus > 7) /* 3 bits */
++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT)
++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++
++ /* Data to change, start by clearing ISRC1 packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_isrc1,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare ISRC1 header */
++ buf[0] = 0x05; /* ISRC1 packet */
++ buf[1] = (uIsrcStatus & 0x07);
++ if(bIsrcValid == True)
++ {
++ buf[1] += 0x40;
++ }
++ if(bIsrcCont == True)
++ {
++ buf[1] += 0x80;
++ }
++ buf[2] = 0; /* Reserved [HDMI 1.2] */
++
++ /* Write 3 header bytes to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ISRC1_HB0_RW,
++ &buf[0],
++ 3);
++ RETIF_REG_FAIL(err)
++
++ /* Write "byteCnt" bytes of data to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ISRC1_PB0_RW,
++ &pPkt->dataByte[0],
++ (UInt16)byteCnt);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the ISRC1 packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_isrc1,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetIsrc2 */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetIsrc2
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[3]; /* Temp buffer to hold header bytes */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM(byteCnt > HDMITX_PKT_DATA_BYTE_CNT)
++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++
++ /* Data to change, start by clearing ISRC2 packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_isrc2,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare ISRC2 header */
++ buf[0] = 0x06; /* ISRC2 packet */
++ buf[1] = 0; /* Reserved [HDMI 1.2] */
++ buf[2] = 0; /* Reserved [HDMI 1.2] */
++
++ /* Write 3 header bytes to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ISRC2_HB0_RW,
++ &buf[0],
++ 3);
++ RETIF_REG_FAIL(err)
++
++ /* Write "byteCnt" bytes of data to registers */
++ err = setHwRegisters(pDis,
++ E_REG_P11_ISRC2_PB0_RW,
++ &pPkt->dataByte[0],
++ (UInt16)byteCnt);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the ISRC2 packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_isrc2,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetMpegInfoframe */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetMpegInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktMpeg_t *pPkt,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[9]; /* Temp buffer to hold packet */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM((pPkt->bFieldRepeat != True) && (pPkt->bFieldRepeat != False))
++ RETIF_BADPARAM(pPkt->frameType >= HDMITX_MPEG_FRAME_INVALID)
++
++ /* Data to change, start by clearing MPEG packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if5,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare MPEG header */
++ buf[0] = 0x85; /* MPEG Source InfoFrame */
++ buf[1] = 0x01; /* Version 1 [HDMI 1.2] */
++ buf[2] = 0x0A; /* Length [HDMI 1.2] */
++
++ /* Prepare MPEG packet (byte numbers offset by 3) */
++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */
++ buf[1+3] = (UInt8)(pPkt->bitRate & 0x000000FF);
++ buf[2+3] = (UInt8)((pPkt->bitRate & 0x0000FF00) >> 8);
++ buf[3+3] = (UInt8)((pPkt->bitRate & 0x00FF0000) >> 16);
++ buf[4+3] = (UInt8)((pPkt->bitRate & 0xFF000000) >> 24);
++ buf[5+3] = pPkt->frameType; /* MF1-0 */
++ if(pPkt->bFieldRepeat == True)
++ {
++ buf[5+3] += 0x10; /* FR0 bit */
++ }
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes. We exclude bytes PB6 to PB10 (which we
++ * are not writing) since they are zero.
++ */
++ buf[0+3] = calculateChecksum(&buf[0], 0x0A+1+3-5);
++
++ /* Write header and packet bytes in one operation */
++ err = setHwRegisters(pDis,
++ E_REG_P10_IF5_HB0_RW,
++ &buf[0],
++ 9);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the MPEG packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if5,
++ (UInt8)bEnable);
++ return err;
++}
++/*============================================================================*/
++/* tmbslTDA9989PktSetNullInsert */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetNullInsert
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ /* Set or clear FORCE_NULL packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_force_null,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetNullSingle */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetNullSingle
++(
++ tmUnitSelect_t txUnit
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Set NULL packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_FLAGS_RW,
++ E_MASKREG_P11_DIP_FLAGS_null,
++ 0x01);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetSpdInfoframe */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetSpdInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktSpd_t *pPkt,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[29];/* Temp buffer to hold packet */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM(pPkt->SourceDevInfo >= HDMITX_SPD_INFO_INVALID)
++
++ /* Data to change, start by clearing SPD packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if3,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare SPD header */
++ buf[0] = 0x83; /* Source. Product Descriptor InfoFrame */
++ buf[1] = 0x01; /* Version 1 [CEA 861B] */
++ buf[2] = 0x19; /* Length [HDMI 1.2] */
++
++ /* Prepare SPD packet (byte numbers offset by 3) */
++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */
++ lmemcpy(&buf[1+3], &pPkt->VendorName[0], HDMI_TX_SPD_VENDOR_SIZE);
++ lmemcpy(&buf[1+3+HDMI_TX_SPD_VENDOR_SIZE], &pPkt->ProdDescr[0],
++ HDMI_TX_SPD_DESCR_SIZE);
++
++
++ buf[HDMI_TX_SPD_LENGTH+3] = pPkt->SourceDevInfo;
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes.
++ */
++ buf[0+3] = calculateChecksum(&buf[0], HDMI_TX_SPD_LENGTH+1+3);
++
++ /* Write header and packet bytes in one operation */
++ err = setHwRegisters(pDis,
++ E_REG_P10_IF3_HB0_RW,
++ &buf[0],
++ 29);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the SPD packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if3,
++ (UInt8)bEnable);
++ return err;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetVideoInfoframe */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PktSetVideoInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktVif_t *pPkt,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[17];/* Temp buffer to hold header/packet bytes */
++ UInt16 bufReg; /* Base register used for writing InfoFrame*/
++ UInt16 flagReg;/* Flag register to be used */
++ UInt8 flagMask;/* Mask used for writing flag register */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ RETIF_BADPARAM(pPkt->Colour > 0x03)
++ RETIF_BADPARAM((pPkt->ActiveInfo != True) && (pPkt->ActiveInfo != False))
++ RETIF_BADPARAM(pPkt->BarInfo > 0x03)
++ RETIF_BADPARAM(pPkt->ScanInfo > 0x03)
++ RETIF_BADPARAM(pPkt->Colorimetry > 0x03)
++ RETIF_BADPARAM(pPkt->PictureAspectRatio > 0x03)
++ RETIF_BADPARAM(pPkt->ActiveFormatRatio > 0x0F)
++ RETIF_BADPARAM(pPkt->Scaling > 0x03)
++ RETIF_BADPARAM(pPkt->VidFormat > 0x7F)
++ RETIF_BADPARAM(pPkt->PixelRepeat > 0x0F)
++ }
++
++ /* Only supported for device N4 or later */
++
++ /* We're using n4 or later, use IF2 buffer for Video InfoFrame */
++ bufReg = E_REG_P10_IF2_HB0_RW;
++ flagReg = E_REG_P11_DIP_IF_FLAGS_RW;
++ flagMask = E_MASKREG_P11_DIP_IF_FLAGS_if2;
++
++ if(pPkt != Null)
++ {
++ /* Data to change, start by clearing VIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ flagReg,
++ flagMask,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare VIF header */
++ buf[0] = 0x82; /* Video InfoFrame */
++ buf[1] = 0x02; /* Version 2 [HDMI 1.2] */
++ buf[2] = 0x0D; /* Length [HDMI 1.2] */
++
++ /* Prepare VIF packet (byte numbers offset by 3) */
++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */
++ buf[1+3] = ((pPkt->Colour & 0x03) << 5) | /* Y1-0, B1-0,S1-0 */
++ ((pPkt->BarInfo & 0x03) << 2) |
++ (pPkt->ScanInfo & 0x03);
++ if(pPkt->ActiveInfo == True)
++ {
++ buf[1+3] += 0x10; /* AI bit */
++ }
++ buf[2+3] = ((pPkt->Colorimetry & 0x03) << 6) | /* C1-0, M1-0, R3-0 */
++ ((pPkt->PictureAspectRatio & 0x03) << 4) |
++ (pPkt->ActiveFormatRatio & 0x0F);
++ buf[3+3] = (pPkt->Scaling & 0x03); /* SC1-0 */ /* [HDMI 1.2] */
++ buf[4+3] = (pPkt->VidFormat & 0x7F); /* VIC6-0 */
++ buf[5+3] = (pPkt->PixelRepeat & 0x0F); /* PR3-0 */
++ buf[6+3] = (UInt8)(pPkt->EndTopBarLine & 0x00FF);
++ buf[7+3] = (UInt8)((pPkt->EndTopBarLine & 0xFF00) >> 8);
++ buf[8+3] = (UInt8)(pPkt->StartBottomBarLine & 0x00FF);
++ buf[9+3] = (UInt8)((pPkt->StartBottomBarLine & 0xFF00) >> 8);
++ buf[10+3] = (UInt8)(pPkt->EndLeftBarPixel & 0x00FF);
++ buf[11+3] = (UInt8)((pPkt->EndLeftBarPixel & 0xFF00) >> 8);
++ buf[12+3] = (UInt8)(pPkt->StartRightBarPixel & 0x00FF);
++ buf[13+3] = (UInt8)((pPkt->StartRightBarPixel & 0xFF00) >> 8);
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes.
++ */
++ buf[0+3] = calculateChecksum(&buf[0], 0x0D+1+3);
++
++ /* Write header and packet bytes in one operation */
++ err = setHwRegisters(pDis,
++ bufReg,
++ &buf[0],
++ 17);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write VIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ flagReg,
++ flagMask,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetRawVideoInfoframe */
++/*============================================================================*/
++tmErrorCode_t tmbslTDA9989PktSetRawVideoInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktRawAvi_t *pPkt,
++ Bool bEnable
++)
++{
++
++
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ /* use IF2 buffer */
++ if(pPkt != Null)
++ {
++ /* Data to change, start by clearing VIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if2,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++
++ /* Write VIF raw header bytes 0-2 */
++ err = setHwRegisters(pDis,
++ E_REG_P10_IF2_HB0_RW,
++ pPkt->HB,
++ 3);
++ RETIF_REG_FAIL(err)
++
++ /* Write VIF raw payload bytes 0-27 */
++ err = setHwRegisters(pDis,
++ E_REG_P10_IF2_PB0_RW,
++ pPkt->PB,
++ 28);
++
++ RETIF_REG_FAIL(err)
++
++ }
++
++ /* Write VIF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if2,
++ (UInt8)bEnable);
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PktSetVsInfoframe */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989PktSetVsInfoframe
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPkt_t *pPkt,
++ UInt byteCnt,
++ UInt8 uVersion,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 buf[31];/* Temp buffer to hold packet */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED error if the
++ * sinkType is not HDMI
++ */
++ RETIF(pDis->sinkType != HDMITX_SINK_HDMI,
++ TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++
++ /* Only supported for device N4 or later */
++
++ /* Check remaining parameter(s) - NULL pointer allowed */
++ RETIF_BADPARAM((bEnable != True) && (bEnable != False))
++
++ if(pPkt != Null)
++ {
++ /* Pointer to structure provided so check parameters */
++ /* InfoFrame needs a checksum, so 1 usable byte less than full pkt */
++ RETIF_BADPARAM(byteCnt > (HDMITX_PKT_DATA_BYTE_CNT-1))
++ RETIF(byteCnt == 0, TMBSL_ERR_HDMI_INCONSISTENT_PARAMS)
++
++ /* Data to change, start by clearing VS_IF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if1,
++ 0x00);
++ RETIF_REG_FAIL(err)
++
++ /* Prepare VS_IF header */
++ lmemset(&buf[0], 0, 31); /* Clear buffer as user may vary length used */
++ buf[0] = 0x81; /* Vendor Specific InfoFrame */
++ buf[1] = uVersion; /* Vendor defined version */
++ buf[2] = (UInt8)byteCnt; /* Length [HDMI 1.2] */
++
++ /* Prepare VS_IF packet (byte numbers offset by 3) */
++ buf[0+3] = 0; /* Preset checksum to zero so calculation works! */
++ lmemcpy(&buf[1+3], &pPkt->dataByte[0], byteCnt);
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes.
++ */
++ buf[0+3] = calculateChecksum(&buf[0], byteCnt+1+3);
++
++ /* Write header and packet bytes in one operation - write entire
++ * buffer even though we may not be using it all so that zeros
++ * are placed in the unused registers. */
++ err = setHwRegisters(pDis,
++ E_REG_P10_IF1_HB0_RW,
++ &buf[0],
++ 31);
++ RETIF_REG_FAIL(err)
++ }
++
++ /* Write the VS_IF packet insertion flag */
++ err = setHwRegisterField(pDis,
++ E_REG_P11_DIP_IF_FLAGS_RW,
++ E_MASKREG_P11_DIP_IF_FLAGS_if1,
++ (UInt8)bEnable);
++ return err;
++}
++
++/*============================================================================*/
++/* STATIC FUNCTIONS */
++/*============================================================================*/
++
++/*===============================================================================*/
++/* reg_vid_fmt(): get register index for normal and 3D, plus sync table */
++/*===============================================================================*/
++static UInt8 reg_vid_fmt(tmbslHdmiTxVidFmt_t fmt, \
++ tmbslHdmiTx3DStructure_t structure3D, \
++ UInt8 *idx, \
++ UInt8 *idx3d, \
++ struct sync_desc **sync)
++{
++ struct vic2reg *hash;
++ int i;
++
++ (*idx)=REGVFMT_INVALID;
++ if (idx3d) (*idx3d)=REGVFMT_INVALID;
++ if (IS_TV(fmt)) {
++ VIC2REG_LOOP(vic2reg_TV,idx);
++ if (idx3d) {
++ if (structure3D == HDMITX_3D_FRAME_PACKING) {
++ /* any 3D FP prefetch ? */
++ VIC2REG_LOOP(vic2reg_TV_FP,idx3d);
++ }
++ }
++ }
++#ifdef FORMAT_PC
++ else {
++ VIC2REG_LOOP(vic2reg_PC,idx);
++ }
++#endif
++ /* PR1570 FIXED */
++ if (sync) {
++ if PREFETCH(*idx) {
++ *sync = (struct sync_desc *)ref_sync;
++ }
++#ifdef FORMAT_PC
++ else if PCFORMAT(*idx) {
++ *sync = (struct sync_desc *)ref_sync_PC;
++ *idx = *idx - E_REGVFMT_MAX_EXTRA;
++ }
++#endif //FORMAT_PC
++ else {
++ *sync = (struct sync_desc *)ref_sync_extra;
++ }
++ }
++ return ((*idx)==REGVFMT_INVALID);
++}
++
++/*===============================================================================*/
++/* pix_clk(): get pixel clock */
++/*===============================================================================*/
++UInt8 pix_clk(tmbslHdmiTxVidFmt_t fmt, tmbslHdmiTxVfreq_t freq, UInt8 *pclk)
++{
++
++ (*pclk)=REGVFMT_INVALID;
++#ifdef FORMAT_PC
++ if (IS_PC(fmt)) {
++ (*pclk)=kVfmtToPixClk_PC[fmt - HDMITX_VFMT_PC_MIN];
++ }
++#endif
++ if (IS_TV(fmt)) {
++ (*pclk)=kVfmtToPixClk_TV[fmt - HDMITX_VFMT_TV_MIN][freq];
++ }
++ return ((*pclk)==REGVFMT_INVALID);
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(pix_clk);
++#endif
++
++/*===============================================================================*/
++/* calculateVidFmtIndex(): Calculate table index according to video format value */
++/*===============================================================================*/
++tmbslHdmiTxVidFmt_t calculateVidFmtIndex(tmbslHdmiTxVidFmt_t vidFmt)
++{
++ tmbslHdmiTxVidFmt_t vidFmtIndex = vidFmt;
++
++ /* Hanlde VIC or table index discontinuity */
++ if((vidFmt >= HDMITX_VFMT_60_1280x720p_24Hz) && (vidFmt <= HDMITX_VFMT_62_1280x720p_30Hz))
++ {
++ vidFmtIndex = (tmbslHdmiTxVidFmt_t)(HDMITX_VFMT_INDEX_60_1280x720p_24Hz + (vidFmt - HDMITX_VFMT_60_1280x720p_24Hz));
++ }
++#ifdef FORMAT_PC
++ else if (IS_PC(vidFmt))
++ {
++ vidFmtIndex = (tmbslHdmiTxVidFmt_t)(HDMITX_VFMT_TV_NUM + (vidFmt - HDMITX_VFMT_PC_MIN));
++ }
++#endif /* FORMAT_PC */
++ return(vidFmtIndex);
++}
++
++/*============================================================================*/
++/* setDeVs */
++/*============================================================================*/
++static tmErrorCode_t
++setDeVs
++(
++ tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt16 vsPixStrt2; /* VS pixel number for start pulse in field 2 */
++ UInt8 reg_idx; /* Video format value used for register */
++ struct sync_desc *sync;
++
++ /* IF voutFmt = No Change THEN return TM_OK */
++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK);
++
++ /* Quit if the output format does not map to the register format */
++ RETIF_BADPARAM(reg_vid_fmt(voutFmt,structure3D,&reg_idx,0,&sync));
++
++ /* DE_START & DE_STOP no longer set because N2 device no longer supported */
++
++ /* Adjust VS_PIX_STRT_2 and VS_PIX_END_2 for interlaced output formats */
++ vsPixStrt2 = sync[BASE(reg_idx)].Vs2;
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_VS_PIX_STRT_2_MSB_W, vsPixStrt2);
++ RETIF_REG_FAIL(err)
++ err = setHwRegisterMsbLsb(pDis, E_REG_P00_VS_PIX_END_2_MSB_W, vsPixStrt2);
++/* printk("DBG %s vs2:%d\n",__func__,vsPixStrt2); */
++
++ return err;
++}
++
++/*============================================================================*/
++/* setPixelRepeat */
++/*============================================================================*/
++static tmErrorCode_t
++setPixelRepeat
++(
++ tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTx3DStructure_t structure3D
++)
++{
++ tmErrorCode_t err = TM_OK; /* Error code */
++
++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK)
++
++ err = InputConfig(pDis,
++ HDMITX_VINMODE_NO_CHANGE,
++ HDMITX_PIXEDGE_NO_CHANGE,
++ HDMITX_PIXRATE_NO_CHANGE,
++ HDMITX_UPSAMPLE_NO_CHANGE,
++ uPixelRepeat,
++ voutFmt,
++ structure3D);
++
++ return err;
++}
++/*============================================================================*/
++/* setSampling */
++/*============================================================================*/
++static tmErrorCode_t
++setSampling
++(
++ tmHdmiTxobject_t *pDis
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 upSample; /* 1 if upsampler must be enabled */
++ UInt8 downSample; /* 1 if downsampler must be enabled */
++ UInt8 matrixBypass; /*>0 if matrix has been bypassed */
++
++ if ((pDis->vinMode == HDMITX_VINMODE_YUV422)
++ || (pDis->vinMode == HDMITX_VINMODE_CCIR656))
++ {
++ if (pDis->voutMode == HDMITX_VOUTMODE_YUV422)
++ {
++ /* Input 422/656, output 422 */
++ err = getHwRegister(pDis, E_REG_P00_MAT_CONTRL_W, &matrixBypass);
++ RETIF_REG_FAIL(err)
++ matrixBypass &= E_MASKREG_P00_MAT_CONTRL_mat_bp;
++ /* Has matrix been bypassed? */
++ if (matrixBypass > 0)
++ {
++ upSample = 0;
++ downSample = 0;
++ }
++ else
++ {
++ upSample = 1;
++ downSample = 1;
++ }
++ }
++ else
++ {
++ /* Input 422/656, output not 422 */
++ upSample = 1;
++ downSample = 0;
++ }
++ }
++ else
++ {
++ if (pDis->voutMode == HDMITX_VOUTMODE_YUV422)
++ {
++ /* Input not 422/656, output 422 */
++ upSample = 0;
++ downSample = 1;
++ }
++ else
++ {
++ /* Input not 422/656, output not 422 */
++ upSample = 0;
++ downSample = 0;
++ }
++ }
++
++ /* Check upsample mode saved by tmbslTDA9989VideoInSetConfig */
++ if (pDis->upsampleMode != HDMITX_UPSAMPLE_AUTO)
++ {
++ /* Saved upsample mode overrides local one */
++ upSample = pDis->upsampleMode;
++ }
++
++ /* Set upsampler */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_0_W,
++ E_MASKREG_P00_HVF_CNTRL_0_intpol,
++ upSample);
++ RETIF_REG_FAIL(err)
++
++ /* Set downsampler */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_HVF_CNTRL_1_W,
++ E_MASKREG_P00_HVF_CNTRL_1_for,
++ downSample);
++ return err;
++}
++
++
++/*============================================================================*/
++/* calculateChecksum - returns the byte needed to yield a checksum of zero */
++/*============================================================================*/
++static UInt8
++calculateChecksum
++(
++ UInt8 *pData, /* Pointer to checksum data */
++ Int numBytes /* Number of bytes over which to calculate */
++ )
++{
++ UInt8 checksum = 0; /* Working checksum calculation */
++ UInt8 result = 0; /* Value to be returned */
++ Int i;
++
++ if((pData != Null) && (numBytes > 0))
++ {
++ for (i = 0; i < numBytes; i++)
++ {
++ checksum = checksum + (*(pData + i));
++ }
++ result = (255 - checksum) + 1;
++ }
++ return result; /* returns 0 in the case of null ptr or 0 bytes */
++}
++
++/*============================================================================*/
++/* InputConfig */
++/*============================================================================*/
++static tmErrorCode_t
++InputConfig
++(
++ tmHdmiTxobject_t *pDis,
++ tmbslHdmiTxVinMode_t vinMode,
++ tmbslHdmiTxPixEdge_t sampleEdge,
++ tmbslHdmiTxPixRate_t pixRate,
++ tmbslHdmiTxUpsampleMode_t upsampleMode,
++ UInt8 uPixelRepeat,
++ tmbslHdmiTxVidFmt_t voutFmt,
++ tmbslHdmiTx3DStructure_t structure3D
++)
++{
++ tmErrorCode_t err = TM_OK; /* Error code */
++ UInt8 reg_idx,reg_idx3D; /* Video format value used for register */
++ UInt8 ssd=0; /* Packed srl, scg and de */
++ struct sync_desc *sync;
++
++ /****************Check Parameters********************/
++ /* Check parameters */
++ RETIF_BADPARAM(vinMode >= HDMITX_VINMODE_INVALID);
++ RETIF_BADPARAM(sampleEdge >= HDMITX_PIXEDGE_INVALID);
++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID);
++ RETIF_BADPARAM(upsampleMode >= HDMITX_UPSAMPLE_INVALID);
++
++ RETIF(voutFmt == HDMITX_VFMT_NO_CHANGE, TM_OK);
++ RETIF_BADPARAM(!IS_VALID_FMT(voutFmt));
++
++ /* Quit if the output format does not map to the register format */
++ RETIF_BADPARAM(reg_vid_fmt(voutFmt,structure3D,&reg_idx,&reg_idx3D,&sync));
++
++/****************Set the VinMode************************
++- P00_VIP_CNTRL_4_ccir656
++- P00_HVF_CNTRL_1_semi_planar
++- P02_PLL_SERIAL_3_srl_ccir
++- P02_SEL_CLK_sel_vrf_clk
++*/
++ if (vinMode != HDMITX_VINMODE_NO_CHANGE)
++ {
++ pDis->vinMode = vinMode;
++ }
++/****************Set the sampleEdge***********************
++-P00_VIP_CNTRL_3_edge*/
++
++ if (sampleEdge != HDMITX_PIXEDGE_NO_CHANGE)
++ {
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_3_W,
++ E_MASKREG_P00_VIP_CNTRL_3_edge,
++ (UInt8)sampleEdge);
++ RETIF_REG_FAIL(err)
++ }
++
++/****************Set the Pixel Rate***********************
++-P02_CCIR_DIV_refdiv2
++-P02_P02_PLL_SCG2_selpllclkin
++-P02_P02_PLL_DE_bypass_pllde
++-P00_VIP_CNTRL_4_656_alt */
++
++ if (pixRate != HDMITX_PIXRATE_NO_CHANGE)
++ {
++ pDis->pixRate = pixRate;
++ }
++
++ if ((pixRate != HDMITX_PIXRATE_NO_CHANGE)||(vinMode != HDMITX_VINMODE_NO_CHANGE))
++ {
++ switch (pDis->vinMode)
++ {
++ case HDMITX_VINMODE_RGB444:
++ case HDMITX_VINMODE_YUV444:
++
++ if (pDis->pixRate == HDMITX_PIXRATE_SINGLE)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else
++ {
++ /* Not supported*/
++ }
++ break;
++ case HDMITX_VINMODE_YUV422:
++ if (pDis->pixRate == HDMITX_PIXRATE_SINGLE)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinModeYUV422[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinModeYUV422[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else
++ {
++ /* Not supported*/
++ return TMBSL_ERR_HDMI_BAD_PARAMETER;
++ }
++ break;
++ case HDMITX_VINMODE_CCIR656:
++ if(pDis->pixRate == HDMITX_PIXRATE_SINGLE)
++ {
++
++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else if (pDis->pixRate == HDMITX_PIXRATE_SINGLE_REPEATED)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ }
++ else if (pDis->pixRate == HDMITX_PIXRATE_DOUBLE)
++ {
++ err = setHwRegisterFieldTable(pDis, &kVinModeCCIR656_DDR_above720p[0]);
++
++ RETIF_REG_FAIL(err)
++
++
++
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_VIP_CNTRL_4_W,
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt,
++ 1);
++ RETIF_REG_FAIL(err)
++
++ }
++ break;
++ default:
++ err = setHwRegisterFieldTable(pDis, &kVinMode444[0]);
++
++ RETIF_REG_FAIL(err)
++ break;
++ }
++
++ }
++ /****************Update the Sample Mode***********************/
++
++ if (upsampleMode != HDMITX_UPSAMPLE_NO_CHANGE) {
++ pDis->upsampleMode = upsampleMode;
++ }
++
++/****************Set the Pixel repeat PLL Value ***********************
++- P02_PLL_SERIAL_2_srl_nosc
++- P02_PLL_DE_pllde_nosc */
++
++ if ((structure3D == HDMITX_3D_FRAME_PACKING) && \
++ (reg_idx3D != REGVFMT_INVALID)) {
++ /* embedded 3D video format */
++ ssd = pll[reg_idx3D];
++ }
++ else {
++ /* embedded 2D video format */
++ ssd = pll[reg_idx];
++ }
++
++ if ( ssd < SSD_UNUSED_VALUE) {
++ err = setHwRegisterField(pDis, E_REG_P02_PLL_SERIAL_2_RW,
++ E_MASKREG_P02_PLL_SERIAL_2_srl_nosc,
++ ssd);
++/* printk("DBG nosc:%d\n",ssd); */
++ }
++
++/*****************Set the Pixel Repetition***********************
++- P02_PLL_SERIAL_2_srl_pr*/
++
++ /* Set pixel repetition */
++ if (uPixelRepeat != HDMITX_PIXREP_NO_CHANGE)
++ {
++ if (uPixelRepeat == HDMITX_PIXREP_DEFAULT)
++ {
++ /* Look up default pixel repeat value for this output format */
++ uPixelRepeat = sync[BASE(reg_idx)].pix_rep;
++ }
++
++ /* Update current pixel repetition count */
++ pDis->pixelRepeatCount = uPixelRepeat;
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_PLL_SERIAL_2_RW,
++ E_MASKREG_P02_PLL_SERIAL_2_srl_pr,
++ uPixelRepeat);
++ RETIF_REG_FAIL(err)
++ /* Set pixel repetition count for Repetitor module */
++ err = setHwRegister(pDis, E_REG_P00_RPT_CNTRL_W, uPixelRepeat);
++ }
++
++/*******************Fixe other settings*********************
++- P02_PLL_SERIAL_1_srl_man_iz = 0
++- P02_PLL_SERIAL_3_srl_de = 0
++- Pol Clk Sel = P02_SERIALIZER_RW = 0
++- P02_BUFFER_OUT_srl_force = 0
++- P02_BUFFER_OUT_srl_clk = 0
++- P02_PLL_DE_pllde_iz = 0
++*/
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_PLL_SERIAL_1_RW,
++ E_MASKREG_P02_PLL_SERIAL_1_srl_man_iz,
++ 0);
++
++
++RETIF_REG_FAIL(err)
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_PLL_SERIAL_3_RW,
++ E_MASKREG_P02_PLL_SERIAL_3_srl_de,
++ 0);
++RETIF_REG_FAIL(err)
++
++err = setHwRegister(pDis, E_REG_P02_SERIALIZER_RW, 0);
++RETIF_REG_FAIL(err)
++
++return err;
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h
+new file mode 100755
+index 0000000..343e41b
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_InOut_l.h
+@@ -0,0 +1,112 @@
++/**
++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of Koninklijke Philips Electronics N.V. and is confidential in
++ * nature. Under no circumstances is this software to be exposed to or placed
++ * under an Open Source License of any type without the expressed written
++ * permission of Koninklijke Philips Electronics N.V.
++ *
++ * \file tmbslTDA9989_InOut_l.h
++ *
++ * \version $Revision: 2 $
++ *
++ *
++*/
++
++#ifndef TMBSLTDA9989_INOUT_L_H
++#define TMBSLTDA9989_INOUT_L_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++#define IS_TV(fmt) (fmt >= HDMITX_VFMT_TV_MIN && fmt <= HDMITX_VFMT_TV_MAX)
++#define IS_VALID_FMT(fmt) IS_TV(fmt)
++#ifdef FORMAT_PC
++#define IS_PC(fmt) (fmt >= HDMITX_VFMT_PC_MIN && fmt <= HDMITX_VFMT_PC_MAX)
++#define IS_VALID_FMT(fmt) (IS_TV(fmt)||IS_PC(fmt))
++#endif
++#define VIC2REG_LOOP(array,idx) do { \
++ hash=(struct vic2reg *)(array); \
++ for (i=0;i<(sizeof(array)/sizeof(struct vic2reg));i++) { \
++ if (hash[i].vic==fmt) { \
++ (*idx)=hash[i].reg; \
++ break; \
++ } \
++ } \
++} while (0);
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++typedef struct
++{
++ UInt16 Register;
++ UInt8 MaskSwap;
++ UInt8 MaskMirror;
++} tmbslTDA9989RegVip;
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++extern CONST_DAT tmHdmiTxRegMaskVal_t kCommonPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure for 480i and 576i vinFmt
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kVfmt480i576iPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure for single mode pixel rate,
++ * vinFmt 480i or 576i only
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmt480i576iPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure for single repeated mode pixel rate,
++ * vinFmt 480i or 576i only
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kSrepeatedPrateVfmt480i576iPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure for other vinFmt than 480i and 576i
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kVfmtOtherPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure single mode pixel rate,
++ * vinFmt other than 480i or 576i
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kSinglePrateVfmtOtherPllCfg[];
++
++/**
++ * Table of PLL settings registers to configure double mode pixel rate,
++ * vinFmt other than 480i or 576i
++ */
++extern CONST_DAT tmHdmiTxRegMaskVal_t kDoublePrateVfmtOtherPllCfg[];
++
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++extern tmbslHdmiTxVidFmt_t calculateVidFmtIndex(tmbslHdmiTxVidFmt_t vidFmt);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_INOUT_L_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c
+new file mode 100755
+index 0000000..d45cc25
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc.c
+@@ -0,0 +1,2512 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_misc.c
++ *
++ * \version %version: 3 %
++ *
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#endif
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++#include "tmbslTDA9989_HDCP_l.h"
++#include "tmbslTDA9989_State_l.h"
++#include "tmbslTDA9989_InOut_l.h"
++#include "tmbslTDA9989_Edid_l.h"
++#include "tmbslTDA9989_Misc_l.h"
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS EXPORTED */
++/*============================================================================*/
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++/** Preset default values for an object instance */
++static CONST_DAT tmHdmiTxobject_t kHdmiTxInstanceDefault
++=
++{
++ ST_UNINITIALIZED, /* state */
++ 0, /* nIgnoredEvents */
++ tmUnit0, /* txUnit */
++ 0, /* uHwAddress */
++ (ptmbslHdmiTxSysFunc_t)0, /* sysFuncWrite */
++ (ptmbslHdmiTxSysFunc_t)0, /* sysFuncRead */
++ (ptmbslHdmiTxSysFuncEdid_t)0, /* sysFuncEdidRead */
++ (ptmbslHdmiTxSysFuncTimer_t)0, /* sysFuncTimer */
++ { /* funcIntCallbacks[] */
++ (ptmbslHdmiTxCallback_t)0
++ },
++ 0, /* InterruptsEnable */
++ { /* uSupportedVersions[] */
++ E_DEV_VERSION_N2,
++ E_DEV_VERSION_TDA19989,
++ E_DEV_VERSION_TDA19989_N2,
++ E_DEV_VERSION_TDA19988,
++ E_DEV_VERSION_LIST_END
++ },
++ E_DEV_VERSION_LIST_END, /* uDeviceVersion */
++ E_DEV_VERSION_LIST_END, /* uDeviceFeatures */
++ (tmbslHdmiTxPowerState_t)tmPowerOff, /* ePowerState */
++ False, /* EdidAlternateAddr */
++ HDMITX_SINK_DVI, /* sinkType */
++ HDMITX_SINK_DVI, /* EdidSinkType */
++ False, /* EdidSinkAi */
++ 0, /* EdidCeaFlags */
++
++ 0, /* EdidCeaXVYCCFlags */
++ {
++ False, /* latency_available */
++ False, /* Ilatency_available */
++ 0, /* Edidvideo_latency */
++ 0, /* Edidaudio_latency */
++ 0, /* EdidIvideo_latency */
++ 0}, /* EdidIaudio_latency */
++
++ {
++ 0, /* maximum supported TMDS clock */
++ 0, /* content type Graphics (text) */
++ 0, /* content type Photo */
++ 0, /* content type Cinema */
++ 0, /* content type Game */
++ 0, /* additional video format */
++ 0, /* 3D support by the HDMI Sink */
++ 0, /* 3D multi strctures present */
++ 0, /* additional info for the values in the image size area */
++ 0, /* total length of 3D video formats */
++ 0, /* total length of extended video formats */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} /* max_len-10, ie: 31-10=21 */
++ },
++
++ HDMITX_EDID_NOT_READ, /* EdidStatus */
++ 0, /* NbDTDStored */
++ { /* EdidDTD: */ /* * NUMBER_DTD_STORED */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*1 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*2 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*3 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*4 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*5 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*6 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*7 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*8 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, /*9 */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0,0} /*10*/
++ },
++ { /* EdidMonitorDescriptor */
++ False, /* bDescRecord */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0} /* uMonitorName[EDID_MONITOR_DESCRIPTOR_SIZE] */
++ },
++ {
++ False, /* bDescRecord */
++ 0, /* uMinVerticalRate */
++ 0, /* uMaxVerticalRate */
++ 0, /* uMinHorizontalRate */
++ 0, /* uMaxHorizontalRate */
++ 0 /* uMaxSupportedPixelClk */
++ },
++ {
++ False, /* bDescRecord */
++ {0,0,0,0,0,0,0,0,0,0,0,0,0} /* uOtherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE] */
++ },
++ { /* EdidVFmts[] */
++ HDMITX_VFMT_NULL
++ },
++ 0, /* EdidSvdCnt */
++ { /* EdidAFmts[]. */
++ {0,0,0} /* {ModeChans, Freqs, Byte3} */
++ },
++ 0, /* EdidSadCnt */
++ {
++ 0 /* EdidBlock[ ] */
++ },
++ 0, /* EdidBlockCnt */
++ 0, /* EdidSourceAddress */
++ 0, /* EdidBlockRequested */
++ False, /* EdidReadStarted */
++ { /* EdidToApp */
++ 0, /* pRawEdid */
++ 0 /* numBlocks */
++ },
++ { /* EDIDBasicDisplayParam */
++ 0, /* uVideoInputDef */
++ 0, /* uMaxHorizontalSize */
++ 0, /* uMaxVerticalSize */
++ 0, /* uGamma */
++ 0, /* uFeatureSupport */
++ },
++#ifdef TMFL_HDCP_SUPPORT
++ False, /* HDCPIgnoreEncrypt */
++ 0, /* HdcpPortAddress */
++ HDMITX_HDCP_TXMODE_NOT_SET, /* HdcpTxMode */
++ HDMITX_HDCP_OPTION_DEFAULT, /* HdcpOptions */
++ 0, /* HdcpBcaps */
++ 0, /* HdcpBstatus */
++ 0, /* HdcpRi */
++ 0, /* HdcpFsmState */
++ 0, /* HdcpT0FailState */
++ 0, /* HdcpSeed */
++ {0, 0, 0, 0, 0}, /* HdcpAksv */
++ (ptmHdmiTxFunc_t)0, /* HdcpFuncScheduled */
++ 0, /* HdcpFuncRemainingMs */
++ 0, /* HdcpCheckIntervalMs */
++ 0, /* HdcpCheckRemainingMs */
++ 0, /* HdcpCheckNum */
++ 0, /* HdcpChecksToDo */
++#endif /* TMFL_HDCP_SUPPORT */
++ HDMITX_VFMT_NULL, /* vinFmt */
++ HDMITX_VFMT_NULL, /* voutFmt */
++ HDMITX_PIXRATE_DOUBLE, /* pixRate */
++ HDMITX_VINMODE_RGB444, /* vinMode */
++ HDMITX_VOUTMODE_RGB444, /* voutMode */
++ HDMITX_VFREQ_INVALID, /* voutFreq */
++ HDMITX_SCAMODE_OFF, /* scaMode */
++ HDMITX_UPSAMPLE_AUTO, /* upsampleMode */
++ HDMITX_PIXREP_MIN, /* pixelRepeatCount */
++ HDMITX_HOTPLUG_INVALID, /* hotPlugStatus */
++ HDMITX_RX_SENSE_INVALID, /* rxSenseStatus */
++ E_PAGE_INVALID, /* curRegPage */
++ {
++ /* These match power-up defaults. shadowReg[]: */
++ 0x00, /* E_SP00_INT_FLAGS_0 */
++ 0x00, /* E_SP00_INT_FLAGS_1 */
++ 0x00, /* E_SP00_INT_FLAGS_2 */
++ 0x01, /* E_SP00_VIP_CNTRL_0 */
++ 0x24, /* E_SP00_VIP_CNTRL_1 */
++ 0x56, /* E_SP00_VIP_CNTRL_2 */
++ 0x17, /* E_SP00_VIP_CNTRL_3 */
++ 0x01, /* E_SP00_VIP_CNTRL_4 */
++ 0x00, /* E_SP00_VIP_CNTRL_5 */
++ 0x05, /* E_SP00_MAT_CONTRL */
++ 0x00, /* E_SP00_TBG_CNTRL_0 */
++ 0x00, /* E_SP00_TBG_CNTRL_1 */
++ 0x00, /* E_SP00_HVF_CNTRL_0 */
++ 0x00, /* E_SP00_HVF_CNTRL_1 */
++ 0x00, /* E_SP00_TIMER_H */
++ 0x00, /* E_SP00_DEBUG_PROBE */
++ 0x00 /* E_SP00_AIP_CLKSEL */
++ ,0x00 /* E_SP01_SC_VIDFORMAT*/
++ ,0x00 /* E_SP01_SC_CNTRL */
++ ,0x00 /* E_SP01_TBG_CNTRL_0 */
++#ifdef TMFL_HDCP_SUPPORT
++ ,0x00 /* E_SP12_CTRL */
++ ,0x00 /* E_SP12_BCAPS */
++#endif /* TMFL_HDCP_SUPPORT */
++ },
++ False, /* Init prevFilterPattern to false */
++ False, /* Init prevPattern to false */
++ False, /* bInitialized */
++ HDMITX_VQR_DEFAULT
++};
++
++
++/**
++ * Table of shadow registers, as packed Shad/Page/Addr codes.
++ * This allows shadow index values to be searched for using register page
++ * and address values.
++ */
++static CONST_DAT UInt16 kShadowReg[E_SNUM] =
++{/* Shadow Index Packed Shad/Page/Addr */
++ E_REG_P00_INT_FLAGS_0_RW, /* E_SP00_INT_FLAGS_0 */
++ E_REG_P00_INT_FLAGS_1_RW, /* E_SP00_INT_FLAGS_1 */
++ E_REG_P00_INT_FLAGS_2_RW, /* E_SP00_INT_FLAGS_2 */
++ E_REG_P00_VIP_CNTRL_0_W , /* E_SP00_VIP_CNTRL_0 */
++ E_REG_P00_VIP_CNTRL_1_W , /* E_SP00_VIP_CNTRL_1 */
++ E_REG_P00_VIP_CNTRL_2_W , /* E_SP00_VIP_CNTRL_2 */
++ E_REG_P00_VIP_CNTRL_3_W , /* E_SP00_VIP_CNTRL_3 */
++ E_REG_P00_VIP_CNTRL_4_W , /* E_SP00_VIP_CNTRL_4 */
++ E_REG_P00_VIP_CNTRL_5_W , /* E_SP00_VIP_CNTRL_5 */
++ E_REG_P00_MAT_CONTRL_W , /* E_SP00_MAT_CONTRL */
++ E_REG_P00_TBG_CNTRL_0_W , /* E_SP00_TBG_CNTRL_0 */
++ E_REG_P00_TBG_CNTRL_1_W , /* E_SP00_TBG_CNTRL_1 */
++ E_REG_P00_HVF_CNTRL_0_W , /* E_SP00_HVF_CNTRL_0 */
++ E_REG_P00_HVF_CNTRL_1_W , /* E_SP00_HVF_CNTRL_1 */
++ E_REG_P00_TIMER_H_W , /* E_SP00_TIMER_H */
++ E_REG_P00_DEBUG_PROBE_W , /* E_SP00_DEBUG_PROBE */
++ E_REG_P00_AIP_CLKSEL_W, /* E_SP00_AIP_CLKSEL */
++ E_REG_P01_SC_VIDFORMAT_W, /* E_SP01_SC_VIDFORMAT */
++ E_REG_P01_SC_CNTRL_W, /* E_SP01_SC_CNTRL */
++ E_REG_P01_TBG_CNTRL_0_W /* E_SP01_TBG_CNTRL_0 */
++#ifdef TMFL_HDCP_SUPPORT
++ ,E_REG_P12_CTRL_W /* E_SP12_CTRL */
++ ,E_REG_P12_BCAPS_W /* E_SP12_BCAPS */
++#endif /* TMFL_HDCP_SUPPORT */
++};
++
++
++/**
++ * Table of registers to switch to low power (standby)
++
++static CONST_DAT tmHdmiTxRegMaskVal_t kPowerOff[] =
++{
++ {E_REG_P02_TEST2_RW, E_MASKREG_P02_TEST2_pwd1v8, 1},
++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_P02_PLL_SCG1_scg_fdn, 1},
++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_P02_PLL_SERIAL_1_srl_fdn, 1},
++ {E_REG_P02_PLL_DE_RW, E_MASKREG_P02_PLL_DE_pllde_fdn, 1},
++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_P02_BUFFER_OUT_srl_force, 2},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_ena_sc_clk, 0},
++ {E_REG_P00_CCLK_ON_RW, E_MASKREG_P00_CCLK_ON_cclk_on, 0},
++ {0,0,0}
++};
++*/
++/**
++ * Table of registers to switch to normal power (resume)
++
++static CONST_DAT tmHdmiTxRegMaskVal_t kPowerOn[] =
++{
++ {E_REG_P02_TEST2_RW, E_MASKREG_P02_TEST2_pwd1v8, 0},
++ {E_REG_P02_PLL_SERIAL_1_RW, E_MASKREG_P02_PLL_SERIAL_1_srl_fdn, 0},
++ {E_REG_P02_PLL_DE_RW, E_MASKREG_P02_PLL_DE_pllde_fdn, 0},
++ {E_REG_P02_PLL_SCG1_RW, E_MASKREG_P02_PLL_SCG1_scg_fdn, 0},
++ {E_REG_P02_SEL_CLK_RW, E_MASKREG_P02_SEL_CLK_ena_sc_clk, 1},
++ {E_REG_P02_BUFFER_OUT_RW, E_MASKREG_P02_BUFFER_OUT_srl_force, 0},
++ {E_REG_P00_TBG_CNTRL_0_W, E_MASKREG_P00_TBG_CNTRL_0_sync_once,0},
++ {E_REG_P00_CCLK_ON_RW, E_MASKREG_P00_CCLK_ON_cclk_on, 1},
++ {0,0,0}
++};
++*/
++
++static CONST_DAT tmbslHdmiTxCallbackInt_t kITCallbackPriority[HDMITX_CALLBACK_INT_NUM] =
++{
++ HDMITX_CALLBACK_INT_R0, /**< R0 interrupt */
++ HDMITX_CALLBACK_INT_ENCRYPT, /**< HDCP encryption switched off */
++ HDMITX_CALLBACK_INT_HPD, /**< Transition on HPD input */
++ HDMITX_CALLBACK_INT_T0, /**< HDCP state machine in state T0 */
++ HDMITX_CALLBACK_INT_BCAPS, /**< BCAPS available */
++ HDMITX_CALLBACK_INT_BSTATUS, /**< BSTATUS available */
++ HDMITX_CALLBACK_INT_SHA_1, /**< sha-1(ksv,bstatus,m0)=V' */
++ HDMITX_CALLBACK_INT_PJ, /**< pj=pj' check fails */
++ HDMITX_CALLBACK_INT_SW_INT, /**< SW DEBUG interrupt */
++ HDMITX_CALLBACK_INT_RX_SENSE, /**< RX SENSE interrupt */
++ HDMITX_CALLBACK_INT_EDID_BLK_READ, /**< EDID BLK READ interrupt */
++ HDMITX_CALLBACK_INT_VS_RPT, /**< VS interrupt */
++ HDMITX_CALLBACK_INT_PLL_LOCK /** PLL LOCK not present on TDA9984 */
++};
++
++
++
++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++ CONST_DAT UInt8 kndiv_im[] =
++{
++ 0, /* HDMITX_VFMT_NO_CHANGE */
++ 4, /* HDMITX_VFMT_01_640x480p_60Hz */
++ 4, /* HDMITX_VFMT_02_720x480p_60Hz */
++ 4, /* HDMITX_VFMT_03_720x480p_60Hz */
++ 12, /* HDMITX_VFMT_04_1280x720p_60Hz */
++ 12, /* HDMITX_VFMT_05_1920x1080i_60Hz */
++ 4, /* HDMITX_VFMT_06_720x480i_60Hz */
++ 4, /* HDMITX_VFMT_07_720x480i_60Hz */
++ 4, /* HDMITX_VFMT_08_720x240p_60Hz */
++ 4, /* HDMITX_VFMT_09_720x240p_60Hz */
++ 4, /* HDMITX_VFMT_10_720x480i_60Hz */
++ 4, /* HDMITX_VFMT_11_720x480i_60Hz */
++ 4, /* HDMITX_VFMT_12_720x240p_60Hz */
++ 4, /* HDMITX_VFMT_13_720x240p_60Hz */
++ 4, /* HDMITX_VFMT_14_1440x480p_60Hz */
++ 4, /* HDMITX_VFMT_15_1440x480p_60Hz */
++ 12,/* HDMITX_VFMT_16_1920x1080p_60Hz */
++ 4, /* HDMITX_VFMT_17_720x576p_50Hz */
++ 4, /* HDMITX_VFMT_18_720x576p_50Hz */
++ 12, /* HDMITX_VFMT_19_1280x720p_50Hz */
++ 12, /* HDMITX_VFMT_20_1920x1080i_50Hz */
++ 4, /* HDMITX_VFMT_21_720x576i_50Hz */
++ 4, /* HDMITX_VFMT_22_720x576i_50Hz */
++ 4, /* HDMITX_VFMT_23_720x288p_50Hz */
++ 4, /* HDMITX_VFMT_24_720x288p_50Hz */
++ 4, /* HDMITX_VFMT_25_720x576i_50Hz */
++ 4, /* HDMITX_VFMT_26_720x576i_50Hz */
++ 4, /* HDMITX_VFMT_27_720x288p_50Hz */
++ 4, /* HDMITX_VFMT_28_720x288p_50Hz */
++ 4, /* HDMITX_VFMT_29_1440x576p_50Hz */
++ 4, /* HDMITX_VFMT_30_1440x576p_50Hz */
++ 12,/* HDMITX_VFMT_31_1920x1080p_50Hz */
++ 12, /* HDMITX_VFMT_32_1920x1080p_24Hz */
++ 12, /* HDMITX_VFMT_33_1920x1080p_25Hz */
++ 12, /* HDMITX_VFMT_34_1920x1080p_30Hz */
++
++};
++
++ CONST_DAT UInt8 kclk_div[] =
++ {
++ 0, /* HDMITX_VFMT_NO_CHANGE */
++ 44, /* HDMITX_VFMT_01_640x480p_60Hz */
++ 44, /* HDMITX_VFMT_02_720x480p_60Hz */
++ 44, /* HDMITX_VFMT_03_720x480p_60Hz */
++ 44, /* HDMITX_VFMT_04_1280x720p_60Hz */
++ 44, /* HDMITX_VFMT_05_1920x1080i_60Hz */
++ 44, /* HDMITX_VFMT_06_720x480i_60Hz */
++ 44, /* HDMITX_VFMT_07_720x480i_60Hz */
++ 44, /* HDMITX_VFMT_08_720x240p_60Hz */
++ 44, /* HDMITX_VFMT_09_720x240p_60Hz */
++ 44, /* HDMITX_VFMT_10_720x480i_60Hz */
++ 44, /* HDMITX_VFMT_11_720x480i_60Hz */
++ 44, /* HDMITX_VFMT_12_720x240p_60Hz */
++ 44, /* HDMITX_VFMT_13_720x240p_60Hz */
++ 44, /* HDMITX_VFMT_14_1440x480p_60Hz */
++ 44, /* HDMITX_VFMT_15_1440x480p_60Hz */
++ 44,/* HDMITX_VFMT_16_1920x1080p_60Hz */
++ 44, /* HDMITX_VFMT_17_720x576p_50Hz */
++ 44, /* HDMITX_VFMT_18_720x576p_50Hz */
++ 44, /* HDMITX_VFMT_19_1280x720p_50Hz */
++ 44, /* HDMITX_VFMT_20_1920x1080i_50Hz */
++ 44, /* HDMITX_VFMT_21_720x576i_50Hz */
++ 44, /* HDMITX_VFMT_22_720x576i_50Hz */
++ 44, /* HDMITX_VFMT_23_720x288p_50Hz */
++ 44, /* HDMITX_VFMT_24_720x288p_50Hz */
++ 44, /* HDMITX_VFMT_25_720x576i_50Hz */
++ 44, /* HDMITX_VFMT_26_720x576i_50Hz */
++ 44, /* HDMITX_VFMT_27_720x288p_50Hz */
++ 44, /* HDMITX_VFMT_28_720x288p_50Hz */
++ 44, /* HDMITX_VFMT_29_1440x576p_50Hz */
++ 44, /* HDMITX_VFMT_30_1440x576p_50Hz */
++ 44,/* HDMITX_VFMT_31_1920x1080p_50Hz */
++ 44, /* HDMITX_VFMT_32_1920x1080p_24Hz */
++ 44, /* HDMITX_VFMT_33_1920x1080p_25Hz */
++ 44, /* HDMITX_VFMT_34_1920x1080p_30Hz */
++ };
++
++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++
++/*============================================================================*/
++/* FUNCTIONS DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++#ifdef TMFL_HDCP_SUPPORT
++static UInt32 sgBcapsCounter = 0;
++#endif /* TMFL_HDCP_SUPPORT */
++
++#define TDA19989_DDC_SPEED_FACTOR 39
++
++static Bool gMiscInterruptHpdRxEnable = False; /* Enable HPD and RX sense IT after */
++ /* first call done by init function */
++static UInt8 int_level=0xFF;
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/*============================================================================*/
++/* tmbslTDA9989Deinit */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989Deinit
++(
++ tmUnitSelect_t txUnit
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 EnableModeMask = 0; /* Local Variable */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* patch to get successfull soft reset even if powerstate has been set to standby mode */
++ /*Write data in ENAMODS CEC Register */
++ EnableModeMask = 0x40;
++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /*Enable HDMI Mode*/
++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask);
++ RETIF_REG_FAIL(err)
++
++ /* Hold the device in reset to disable it */
++ err = setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW,
++ E_MASKREG_P00_MAIN_CNTRL0_sr, 1);
++ RETIF_REG_FAIL(err)
++
++ /* patch to get successfull soft reset even if powerstate has been set to standby mode */
++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Disable HDMI Mode*/
++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_ena_rxs; /* Reset RxSense Mode*/
++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_dis_fro; /* Disable FRO */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask);
++ RETIF_REG_FAIL(err)
++
++ /* Clear the Initialized flag to destroy the device instance */
++ pDis->bInitialized = False;
++
++ setState(pDis, EV_DEINIT);
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HotPlugGetStatus */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HotPlugGetStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxHotPlug_t *pHotPlugStatus,
++ Bool client /* Used to determine whether the request comes from the application */
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Register value */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(pHotPlugStatus == (tmbslHdmiTxHotPlug_t *)0)
++
++ /* Read HPD RXS level */
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&regVal);
++ RETIF(err != TM_OK, err)
++
++ /* Read Hot Plug input status to know the actual level that caused the interrupt */
++ if (client)
++ {
++ *pHotPlugStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ?
++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE;
++ }
++ else {
++
++ *pHotPlugStatus = pDis->hotPlugStatus;
++
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989RxSenseGetStatus */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989RxSenseGetStatus
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxRxSense_t *pRxSenseStatus,
++ Bool client /* Used to determine whether the request comes from the application */
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Register value */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(pRxSenseStatus == (tmbslHdmiTxRxSense_t *)0)
++
++
++ /* Read HPD RXS level */
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&regVal);
++ RETIF(err != TM_OK, err)
++
++
++ /*Read RXS_FIL status to know the actual level that caused the interrupt */
++ if (client)
++ {
++ *pRxSenseStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ?
++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE;
++ }
++ else {
++ *pRxSenseStatus = pDis->rxSenseStatus;
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HwGetRegisters */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HwGetRegisters
++(
++ tmUnitSelect_t txUnit,
++ Int regPage,
++ Int regAddr,
++ UInt8 *pRegBuf,
++ Int nRegs
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ UInt8 newRegPage; /* The register's new page number */
++ UInt8 regShad; /* Index to the register's shadow copy */
++ UInt16 regShadPageAddr;/* Packed shadowindex/page/address */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM((regPage < kPageIndexToPage[E_PAGE_00])
++ || ((regPage > kPageIndexToPage[E_PAGE_02])
++ && (regPage < kPageIndexToPage[E_PAGE_09]))
++ || ((regPage > kPageIndexToPage[E_PAGE_09])
++ && (regPage < kPageIndexToPage[E_PAGE_11]))
++ || (regPage > kPageIndexToPage[E_PAGE_12]))
++ RETIF_BADPARAM((regAddr < E_REG_MIN_ADR) || (regAddr >= E_REG_CURPAGE_ADR_W))
++ RETIF_BADPARAM(pRegBuf == (pUInt8)0)
++ RETIF_BADPARAM((nRegs < 1) || ((nRegs + regAddr) > E_REG_CURPAGE_ADR_W))
++
++ /* Set page register if required */
++ newRegPage = (UInt8)regPage;
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* Read each register in the range. nRegs must start at 1 or more */
++ for ( ; nRegs > 0; pRegBuf++, regAddr++, nRegs--)
++ {
++ /* Find shadow register index.
++ * This loop is not very efficient, but it is assumed that this API
++ * will not be used often. The alternative is to use a huge sparse
++ * array indexed by page and address and containing the shadow index.
++ */
++ regShad = E_SNONE;
++ for (i = 0; i < E_SNUM; i++)
++ {
++ /* Check lookup table for match with page and address */
++ regShadPageAddr = kShadowReg[i];
++ if ((SPA2PAGE(regShadPageAddr) == newRegPage)
++ && (SPA2ADDR(regShadPageAddr) == regAddr))
++ {
++ /* Found page and address - look up the shadow index */
++ regShad = SPA2SHAD(regShadPageAddr);
++ break;
++ }
++ }
++ /* Read the shadow register if available, as device registers that
++ * are shadowed cannot be read directly */
++ if (regShad != E_SNONE)
++ {
++ *pRegBuf = pDis->shadowReg[regShad];
++ }
++ else
++ {
++ /* Read the device register - all non-OK results are errors.
++ * Note that some non-shadowed registers are also write-only and
++ * cannot be read. */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = (UInt8)regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = pRegBuf;
++ err = pDis->sysFuncRead(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_READ)
++ }
++ }
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HwGetVersion */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989HwGetVersion
++(
++ tmUnitSelect_t txUnit,
++ pUInt8 pHwVersion
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal;
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(pHwVersion == (pUInt8)0)
++
++ /* Get MSB version Value*/
++ err = getHwRegister(pDis, E_REG_P00_VERSION_MSB_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++ switch (regVal)
++ {
++ case 0x01:
++ *pHwVersion = (UInt8)(BSLHDMITX_TDA9989);
++ break;
++ case 0x02:
++ *pHwVersion = (UInt8)(BSLHDMITX_TDA19989);
++ break;
++ case 0x03:
++ *pHwVersion = (UInt8)(BSLHDMITX_TDA19988);
++ break;
++ default:
++ *pHwVersion = (UInt8)(BSLHDMITX_UNKNOWN);
++ break;
++ }
++
++ return TM_OK;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989HwHandleInterrupt */
++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HwHandleInterrupt
++(
++ tmUnitSelect_t txUnit
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal; /* Register value */
++ UInt8 regVal1; /* Register value */
++ UInt16 fInterruptStatus; /* Interrupt flags */
++ UInt16 fInterruptMask; /* Mask to test each interrupt bit */
++ tmbslHdmiTxRxSense_t newRxs_fil; /* Latest copy of rx_sense */
++ Int i; /* Loop counter */
++ tmbslHdmiTxHotPlug_t newHpdIn; /* Latest copy of hpd input */
++ Bool sendEdidCallback;
++ Bool hpdOrRxsLevelHasChanged = False;
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ fInterruptStatus = 0;
++ sendEdidCallback = False;
++
++
++
++ /* Read HPD RXS int status */
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINT_R,&regVal);
++ RETIF(err != TM_OK, err);
++
++ /* Read HPD RXS level */
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&regVal1);
++ RETIF(err != TM_OK, err);
++
++ if (int_level!=0xFF) { /* init should be done */
++ /* check multi-transition */
++ if ((regVal==0) && (int_level!=regVal1)) {
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++ printk("HDMI Int multi-transition\n");
++#endif
++ err = setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, 0x00);
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, \
++ E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int | \
++ E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&regVal1);
++ RETIF(err != TM_OK, err)
++ }
++ }
++ int_level=regVal1;
++
++ /* Read Hot Plug input status to know the actual level that caused the interrupt */
++ newHpdIn = (regVal1 & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ?
++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE;
++
++ /*Read RXS_FIL status to know the actual level that caused the interrupt */
++ newRxs_fil = (regVal1 & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ?
++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE;
++
++ /*Fill fInterruptStatus with HPD Interrupt flag*/
++
++ if (newHpdIn != pDis->hotPlugStatus)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_HPD);
++ /* Yes: save new HPD level */
++ pDis->hotPlugStatus = newHpdIn;
++ hpdOrRxsLevelHasChanged = True;
++ }
++
++ /*Fill fInterruptStatus with RX Sense Interrupt flag*/
++ if (newRxs_fil != pDis->rxSenseStatus)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_RX_SENSE);
++ /* Yes: save new rxSense level */
++ pDis->rxSenseStatus = newRxs_fil;
++ hpdOrRxsLevelHasChanged = True;
++ }
++
++
++
++ /* is it HDMI interrupt ? */
++ err = getCECHwRegister(pDis, E_REG_CEC_INTERRUPTSTATUS_R,&regVal);
++ RETIF(err != TM_OK, err)
++
++ /* there is no HDMI int to handle, give up */
++ if ((regVal & E_MASKREG_CEC_INTERRUPTSTATUS_hdmi_int) == 0x00) {
++
++ if (hpdOrRxsLevelHasChanged == True) {
++ }
++ else {
++ return TM_OK;
++ }
++ }
++
++
++
++ /************************************************************************************************/
++ /***********************************End of Temporary code****************************************/
++ /************************************************************************************************/
++
++ /* Do only if HDMI is On*/
++ if(pDis->ePowerState == tmPowerOn)
++ {
++ /* Read the main interrupt flags register to determine the source(s)
++ * of the interrupt. (The device resets these register flags after they
++ * have been read.)
++ */
++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_0_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++#ifdef TMFL_HDCP_SUPPORT
++ /* encrypt */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_encrypt) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_ENCRYPT);
++ }
++#endif /* TMFL_HDCP_SUPPORT */
++
++ /* get TO interrupt Flag*/
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_t0) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_T0);
++ }
++
++#ifdef TMFL_HDCP_SUPPORT
++ /* bcaps */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_bcaps) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_BCAPS);
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ /* WA: HDCP ATC Test 1B_03 */
++
++ sgBcapsCounter++;
++
++ if (sgBcapsCounter == 49) {
++ sgBcapsCounter = 0;
++ /* force a T0 interrupt */
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_T0);
++ }
++
++ } /* TDA19989 N1 only */
++
++ }
++
++ /* bstatus */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_bstatus) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_BSTATUS);
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ /* WA: HDCP ATC Test 1B_03 */
++ sgBcapsCounter = 0;
++
++ } /* TDA19989 N1 only */
++
++ }
++
++ /* sha_1 */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_sha_1) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_SHA_1);
++ }
++
++ /* pj */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_pj) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_PJ);
++ }
++
++ /* r0 */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_0_r0) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_R0);
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ /* WA: HDCP ATC Test 1B_03 */
++ sgBcapsCounter = 0;
++
++ } /* TDA19989 N1 only */
++
++ }
++#endif /* TMFL_HDCP_SUPPORT */
++
++
++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++
++ /* Read the software interrupt flag */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_1_sw_int) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_SW_INT);
++ }
++
++ /* Read the VS_rpt interrupt flag */
++ if (((pDis->InterruptsEnable & E_MASKREG_P00_INT_FLAGS_1_vs_rpt) != 0) &&
++ ((regVal & E_MASKREG_P00_INT_FLAGS_1_vs_rpt) != 0)
++ )
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_VS_RPT);
++ }
++
++ /* Read INT_FLAGS_2 interrupt flag register.
++ *(The device resets these register flags after they
++ * have been read.) */
++ err = getHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++ /* Has the EDID_blk_rd interrupt occurs */
++ if ((regVal & E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd) != 0)
++ {
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ);
++ }
++ }
++
++
++ /* Handle the HPD Interrupt */
++ if ((fInterruptStatus & (1 << HDMITX_CALLBACK_INT_HPD))!=0 )
++ {
++ /* Callback disable on first tmbslTDA9989HwHandleInterrupt call */
++ if(gMiscInterruptHpdRxEnable)
++ {
++ /* Reset EDID status */
++ err = ClearEdidRequest(txUnit);
++
++ /* Reset all simultaneous HDCP interrupts on hot plug,
++ * preserving only the high-priority hpd interrupt rx_sense and sw interrupt for debug*/
++ fInterruptStatus &= (1 << HDMITX_CALLBACK_INT_HPD) |
++ (1 << HDMITX_CALLBACK_INT_RX_SENSE) |
++ (1 << HDMITX_CALLBACK_INT_SW_INT);
++
++ if(pDis->ePowerState == tmPowerOn)
++ {
++ if ((pDis->hotPlugStatus == HDMITX_HOTPLUG_ACTIVE))
++ {
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ err = tmbslTDA9989Reset(txUnit);
++ RETIF(err != TM_OK, err)
++
++ err = hotPlugRestore(txUnit);
++ RETIF(err != TM_OK, err)
++
++ } /* TDA19989 N1 only */
++
++ else { /* TDA19989 N2 */
++
++ HDCP_F2;
++ }
++
++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++ err = tmbslTDA9989Reset(txUnit);
++ RETIF(err != TM_OK, err)
++
++ err = hotPlugRestore(txUnit);
++ RETIF(err != TM_OK, err)
++
++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++
++
++ setState(pDis, EV_PLUGGEDIN);
++ }
++ else
++ {
++ setState(pDis, EV_UNPLUGGED);
++ }
++ }
++ }
++ }
++ else
++ {
++ /* Clear HPD status if level has not changed */
++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_HPD);
++
++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ))
++ {
++ err = EdidBlockAvailable(txUnit,&sendEdidCallback);
++ RETIF(err != TM_OK, err)
++ if (sendEdidCallback == False)
++ {
++ /* Read EDID not finished clear callback */
++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_EDID_BLK_READ);
++ }
++ else {
++ #ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++ if ( (pDis->vinFmt == HDMITX_VFMT_16_1920x1080p_60Hz) || (pDis->vinFmt == HDMITX_VFMT_31_1920x1080p_50Hz)) {
++
++ err = setHwRegisterField(pDis,
++ E_REG_P02_PLL_SERIAL_3_RW,
++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir,
++ 0x00);
++ RETIF_REG_FAIL(err)
++ }
++
++ #endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++ }
++
++
++ }
++ }
++
++ /*Handle RxSense Interrupt*/
++ if ((fInterruptStatus &( 1 << HDMITX_CALLBACK_INT_RX_SENSE))!= 0)
++ {
++ /* Callback disable on first tmbslTDA9989HwHandleInterrupt call */
++ if(gMiscInterruptHpdRxEnable)
++ {
++
++
++ fInterruptStatus &= (1 << HDMITX_CALLBACK_INT_HPD) |
++ (1 << HDMITX_CALLBACK_INT_RX_SENSE) |
++ (1 << HDMITX_CALLBACK_INT_SW_INT);
++
++ if (pDis->rxSenseStatus == HDMITX_RX_SENSE_ACTIVE)
++ {
++ setState(pDis, EV_SINKON);
++ }
++ else
++ {
++ setState(pDis, EV_SINKOFF);
++ }
++ }
++ }
++ else
++ {
++ /* Clear RX_sense IT if level has not changed */
++ fInterruptStatus &= ~(1 << HDMITX_CALLBACK_INT_RX_SENSE);
++ }
++
++ /* Ignore other simultaneous HDCP interrupts if T0 interrupt,
++ * preserving any hpd interrupt */
++
++ if (fInterruptStatus & (1 << HDMITX_CALLBACK_INT_T0))
++ {
++ if (pDis->EdidReadStarted)
++ {
++
++#ifdef TMFL_HDCP_SUPPORT
++ err = getHwRegister(pDis, E_REG_P12_TX0_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++ /* EDID read failure */
++ if ((regVal & E_MASKREG_P12_TX0_sr_hdcp) != 0) {
++
++#endif /* TMFL_HDCP_SUPPORT */
++
++
++ /* Reset EDID status */
++ err = ClearEdidRequest(txUnit);
++ RETIF(err != TM_OK, err)
++
++ /* enable EDID callback */
++ fInterruptStatus = (UInt16) (fInterruptStatus & (~(1 << HDMITX_CALLBACK_INT_T0)));
++ fInterruptStatus = fInterruptStatus | (1 << HDMITX_CALLBACK_INT_EDID_BLK_READ);
++
++#ifdef TMFL_HDCP_SUPPORT
++ }
++#endif /* TMFL_HDCP_SUPPORT */
++
++ }
++ else
++ {
++ fInterruptStatus &=
++ (
++ (1 << HDMITX_CALLBACK_INT_HPD)
++ |(1 << HDMITX_CALLBACK_INT_T0)
++ |(1 << HDMITX_CALLBACK_INT_RX_SENSE)
++ |(1 << HDMITX_CALLBACK_INT_SW_INT)
++ );
++ }
++ }
++
++ HDCP_F3;
++
++ /* For each interrupt flag that is set, check the corresponding registered
++ * callback function pointer in the Device Instance Structure
++ * funcIntCallbacks array.
++ */
++ fInterruptMask = 1;
++ for (i = 0; i < HDMITX_CALLBACK_INT_NUM; i++)
++ {
++ if ( i != HDMITX_CALLBACK_INT_PLL_LOCK) /* PLL LOCK not present on TDA9989 */
++ {
++
++ fInterruptMask = 1;
++ fInterruptMask = fInterruptMask << ((UInt16)kITCallbackPriority[i]);
++
++ if (fInterruptStatus & fInterruptMask)
++ {
++ /* IF a registered callback pointer is non-null THEN call it. */
++ if (pDis->funcIntCallbacks[kITCallbackPriority[i]] != (ptmbslHdmiTxCallback_t)0)
++ {
++ pDis->funcIntCallbacks[kITCallbackPriority[i]](txUnit);
++ }
++ }
++
++ }
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989FlagSwInt */
++/* Use only for debug to flag the software debug interrupt */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989FlagSwInt
++(
++ tmUnitSelect_t txUnit,
++ UInt32 uSwInt
++ )
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ DUMMY_ACCESS(uSwInt);
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ err = setHwRegister(pDis, E_REG_P00_SW_INT_W,
++ E_MASKREG_P00_SW_INT_sw_int);
++
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989HwSetRegisters */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989HwSetRegisters
++(
++ tmUnitSelect_t txUnit,
++ Int regPage,
++ Int regAddr,
++ UInt8 *pRegBuf,
++ Int nRegs
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ UInt8 newRegPage; /* The register's new page number */
++ UInt8 regShad; /* Index to the register's shadow copy */
++ UInt16 regShadPageAddr;/* Packed shadowindex/page/address */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM((regPage < kPageIndexToPage[E_PAGE_00])
++ || ((regPage > kPageIndexToPage[E_PAGE_02])
++ && (regPage < kPageIndexToPage[E_PAGE_11]))
++ || (regPage > kPageIndexToPage[E_PAGE_12]))
++ RETIF_BADPARAM((regAddr < E_REG_MIN_ADR) || (regAddr >= E_REG_CURPAGE_ADR_W))
++ RETIF_BADPARAM(pRegBuf == (pUInt8)0)
++ RETIF_BADPARAM((nRegs < 0) || ((nRegs + regAddr) > E_REG_CURPAGE_ADR_W))
++
++ /* Set page register if required */
++ newRegPage = (UInt8)regPage;
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* Write each register in the range. nRegs = 0 is ok, to allow only
++ * the page register to be written if required (above)
++ */
++ for ( ; nRegs > 0; pRegBuf++, regAddr++, nRegs--)
++ {
++ /* Find shadow register index.
++ * This loop is not very efficient, but it is assumed that this API
++ * will not be used often. The alternative is to use a huge sparse
++ * array indexed by page and address and containing the shadow index.
++ */
++ for (i = 0; i < E_SNUM; i++)
++ {
++ /* Check lookup table for match with page and address */
++ regShadPageAddr = kShadowReg[i];
++ if ((SPA2PAGE(regShadPageAddr) == newRegPage)
++ && (SPA2ADDR(regShadPageAddr) == regAddr))
++ {
++ /* Found index - write the shadow register */
++ regShad = SPA2SHAD(regShadPageAddr);
++ pDis->shadowReg[regShad] = *pRegBuf;
++ break;
++ }
++ }
++ /* Write the device register - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = (UInt8)regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = pRegBuf;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ }
++
++ return TM_OK;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989HwStartup */
++/*============================================================================*/
++void
++tmbslTDA9989HwStartup
++(
++ void
++)
++{
++ /* Reset device instance data for when compiler doesn't do it */
++ lmemset(&gHdmiTxInstance, 0, sizeof(gHdmiTxInstance));
++}
++
++/*============================================================================*/
++/* tmbslTDA9989Init */
++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989Init
++(
++ tmUnitSelect_t txUnit,
++ UInt8 uHwAddress,
++ ptmbslHdmiTxSysFunc_t sysFuncWrite,
++ ptmbslHdmiTxSysFunc_t sysFuncRead,
++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead,
++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer,
++ tmbslHdmiTxCallbackList_t *funcIntCallbacks,
++ Bool bEdidAltAddr,
++ tmbslHdmiTxVidFmt_t vinFmt,
++ tmbslHdmiTxPixRate_t pixRate
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Loop index */
++ Bool bFound; /* T=found, F=not found */
++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/
++ UInt8 EnableModeMask; /* Mask used to Set HDMI and RxSense modes*/
++ UInt16 val16Bits; /* Value on 16 bit */
++ UInt8 regVal; /* Register value */
++
++ /* Check unit parameter and point to its object */
++ RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
++ RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
++ pDis = &gHdmiTxInstance[txUnit];
++
++ /* IF the bInitialized flag is set THEN return (only Init does this) */
++ RETIF(pDis->bInitialized, TMBSL_ERR_HDMI_INIT_FAILED)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(uHwAddress < HDMITX_SLAVE_ADDRESS_MIN)
++ RETIF_BADPARAM(uHwAddress > HDMITX_SLAVE_ADDRESS_MAX)
++ RETIF_BADPARAM(sysFuncWrite == (ptmbslHdmiTxSysFunc_t)0)
++ RETIF_BADPARAM(sysFuncRead == (ptmbslHdmiTxSysFunc_t)0)
++ /*RETIF_BADPARAM(sysFuncEdidRead == (ptmbslHdmiTxSysFuncEdid_t)0)*/ /*Previously on TDA9983*/
++ /*RETIF_BADPARAM(sysFuncTimer == (ptmbslHdmiTxSysFuncTimer_t)0)*/
++ RETIF_BADPARAM((bEdidAltAddr != True) && (bEdidAltAddr != False))
++ RETIF_BADPARAM(!IS_VALID_FMT(vinFmt))
++ RETIF_BADPARAM(pixRate >= HDMITX_PIXRATE_INVALID)
++
++ /* Set all Device Instance Structure members to default values */
++ lmemcpy(pDis, &kHdmiTxInstanceDefault, sizeof(*pDis));
++
++ /* Copy txUnit, uHwAddress, sysFuncWrite and sysFuncRead values to
++ * the defaulted Device Instance Structure BEFORE FIRST DEVICE ACCESS.
++ */
++ pDis->txUnit = txUnit;
++#ifdef UNIT_TEST
++ /* Unit test build can't support 127 device sets of dummy registers, so use
++ * smaller range instead, indexed by unit number not I2C address */
++ pDis->uHwAddress = (UInt8)txUnit;
++#else
++ /* Store actual I2C address */
++ pDis->uHwAddress = uHwAddress;
++#endif
++ pDis->sysFuncWrite = sysFuncWrite;
++ pDis->sysFuncRead = sysFuncRead;
++ pDis->sysFuncEdidRead = sysFuncEdidRead;
++ pDis->sysFuncTimer = sysFuncTimer;
++
++ /* IF the funcIntCallbacks array pointer is defined
++ * THEN for each funcIntCallbacks pointer that is not null:
++ * - Copy the pointer to the Device Instance Structure
++ * funcIntCallbacks array.
++ */
++
++ for (i = 0; i < HDMITX_CALLBACK_INT_NUM; i++)
++ {
++ if ((funcIntCallbacks != (tmbslHdmiTxCallbackList_t *)0)
++ && (funcIntCallbacks->funcCallback[i] != (ptmbslHdmiTxCallback_t)0))
++ {
++ pDis->funcIntCallbacks[i] = funcIntCallbacks->funcCallback[i];
++ }
++ else
++ {
++ pDis->funcIntCallbacks[i] = (ptmbslHdmiTxCallback_t)0;
++ }
++ }
++
++ /* Set the EDID alternate address flag if needed*/
++ pDis->bEdidAlternateAddr = bEdidAltAddr;
++
++//*****************************************************************************************//
++//*****************************************************************************************//
++//**********************Enable HDMI and RxSense************************///
++
++ /* reset ENAMODS */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, 0x40);
++ RETIF_REG_FAIL(err)
++
++
++
++
++
++ /*Read data out of ENAMODS CEC Register */
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &EnableModeMask);
++
++ /*Enable required modes*/
++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /*Enable HDMI Mode*/
++ EnableModeMask |= E_MASKREG_CEC_ENAMODS_ena_rxs; /*Enable RxSense Mode*/
++ EnableModeMask &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */
++
++ /*Write data in ENAMODS CEC Register */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, EnableModeMask);
++
++ pDis->ePowerState = (tmbslHdmiTxPowerState_t) tmPowerOn;
++
++ /* Set the bInitialized flag to enable other APIs */
++ pDis->bInitialized = True;
++
++ /* Reset the device */
++ err = tmbslTDA9989Reset(txUnit);
++ RETIF(err != TM_OK, err)
++
++//***************************************************************************************//
++//****************Get Device Version and Capabilities************************************//
++ /* Read the device version register to uDeviceVersion in the
++ * Device Instance Structure
++ */
++ err = getHwRegister(pDis, E_REG_P00_VERSION_R, &regVal);
++ RETIF(err != TM_OK, err)
++
++ /* Copy N4 features bits to DIS */
++ pDis->uDeviceFeatures = regVal &
++ (E_MASKREG_P00_VERSION_not_h | E_MASKREG_P00_VERSION_not_s);
++
++ pDis->uDeviceVersion = regVal;
++
++ /* Get MSB version Value*/
++ err = getHwRegister(pDis, E_REG_P00_VERSION_MSB_RW, &regVal);
++ RETIF(err != TM_OK, err)
++
++ /* Build Device Version Info */
++ val16Bits = regVal;
++ pDis->uDeviceVersion = pDis->uDeviceVersion | (val16Bits << 8);
++ val16Bits = pDis->uDeviceFeatures;
++ pDis->uDeviceVersion &= ~val16Bits;
++
++ if (pDis->uDeviceVersion != E_DEV_VERSION_LIST_END)
++ {
++ /* Search for the device version in the Supported Version
++ * List in the Device Instance Structure.
++ */
++ for (i = 0, bFound = False; i < E_DEV_VERSION_LIST_NUM; i++)
++ {
++ if (pDis->uDeviceVersion == pDis->uSupportedVersions[i])
++ {
++ bFound = True;
++ }
++ }
++ if (bFound == False)
++ {
++ /* IF the device version is not found in the Supported Version List THEN
++ * this driver component is not compatible with the device.*/
++ err = tmbslTDA9989Deinit(txUnit);
++ RETIF(err != TM_OK, err)
++ return TMBSL_ERR_HDMI_COMPATIBILITY;
++ }
++ }
++ else
++ {
++ /* Quit if version reads zero */
++ err = tmbslTDA9989Deinit(txUnit);
++ RETIF(err != TM_OK, err)
++ return TMBSL_ERR_HDMI_COMPATIBILITY;
++ }
++
++/***************************************************************************************/
++/************Set the BIAS_tmds Value (general control for Analogu module)***************/
++ regVal = HDMI_TX_VSWING_VALUE;
++
++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal);
++ RETIF(err != TM_OK, err)
++
++/*****************************************************************************************/
++/*****************************************************************************************/
++
++ /* Set the PLL before resetting the device */
++ /* PLL registers common configuration */
++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/
++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0);
++
++ switch (vinFmt)
++ {
++ /* 480i or 576i video input format */
++ case HDMITX_VFMT_06_720x480i_60Hz:
++ case HDMITX_VFMT_07_720x480i_60Hz:
++ case HDMITX_VFMT_21_720x576i_50Hz:
++ case HDMITX_VFMT_22_720x576i_50Hz:
++ err = setHwRegisterFieldTable(pDis, &kVfmt480i576iPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ switch (pixRate)
++ {
++ case HDMITX_PIXRATE_SINGLE:
++ /* Single edge mode, vinFmt 480i or 576i */
++ err = setHwRegisterFieldTable(pDis, &kSinglePrateVfmt480i576iPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ break;
++ case HDMITX_PIXRATE_SINGLE_REPEATED:
++ /* Single repeated edge mode, vinFmt 480i or 576i */
++ err = setHwRegisterFieldTable(pDis, &kSrepeatedPrateVfmt480i576iPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ break;
++ default:
++ /* Double edge mode doesn't exist for vinFmt 480i or 576i */
++ return(TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++
++ break;
++
++
++ /* Others video input format */
++ default:
++ err = setHwRegisterFieldTable(pDis, &kVfmtOtherPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ switch (pixRate)
++ {
++ case HDMITX_PIXRATE_SINGLE:
++ /* Single edge mode, vinFmt other than 480i or 576i */
++ err = setHwRegisterFieldTable(pDis, &kSinglePrateVfmtOtherPllCfg[0]);
++ RETIF_REG_FAIL(err)
++ break;
++ case HDMITX_PIXRATE_DOUBLE:
++ /* Double edge mode, vinFmt other than 480i or 576i */
++ err = setHwRegisterFieldTable(pDis, &kDoublePrateVfmtOtherPllCfg[0]);
++ RETIF_REG_FAIL(err)
++ break;
++ default:
++ /* Single repeated edge mode doesn't exist for other vinFmt */
++ return(TMBSL_ERR_HDMI_INCONSISTENT_PARAMS);
++ }
++ break;
++
++ }
++
++ /* DDC interface is disable for TDA9989 after reset, enable it */
++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00);
++ RETIF(err != TM_OK, err)
++
++ /* Set clock speed of the DDC channel */
++
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR);
++ RETIF(err != TM_OK, err)
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_I2C_MASTER_RW,
++ E_MASKREG_P00_I2C_MASTER_dis_mm,
++ 0); /* 0: enable multi master mode */
++ RETIF_REG_FAIL(err)
++
++ } /* TDA19989 N1 only */
++
++
++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel);
++ RETIF_REG_FAIL(err)
++
++ /* The DIS hotplug status is HDMITX_HOTPLUG_INVALID, so call the main
++ * interrupt handler to read the current Hot Plug status and run any
++ * registered HPD callback before interrupts are enabled below */
++ //err = tmbslTDA9989HwHandleInterrupt(txUnit);
++ RETIF(err != TM_OK, err)
++
++ /* enable sw _interrupt and VS_interrupt for debug */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW,
++ E_MASKREG_P00_INT_FLAGS_1_sw_int);
++
++ /* enable edid read */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW,
++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd);
++
++
++ /* Read HPD RXS level */
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&regVal);
++ RETIF(err != TM_OK, err)
++
++ /* Read Hot Plug input status to know the actual level that caused the interrupt */
++ pDis->hotPlugStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_hpd_level) ?
++ HDMITX_HOTPLUG_ACTIVE : HDMITX_HOTPLUG_INACTIVE;
++
++ /*Read RXS_FIL status to know the actual level that caused the interrupt */
++ pDis->rxSenseStatus = (regVal & E_MASKREG_CEC_RXSHPDLEV_rxs_level) ?
++ HDMITX_RX_SENSE_ACTIVE : HDMITX_RX_SENSE_INACTIVE;
++
++ /*Disable required Interrupts*/
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask);
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/
++
++ /* Switch BSL State machine into UNINITIALIZED State */
++ setState(pDis, EV_INIT);
++
++ /*Write data in RXSHPD Register*/
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++
++ /* Enable HPD and RX sense IT after first call done by init function */
++ gMiscInterruptHpdRxEnable = True;
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989PowerGetState */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989PowerGetState
++(
++ tmUnitSelect_t txUnit,
++ tmPowerState_t *pePowerState
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM(pePowerState == (tmPowerState_t)0)
++
++ /*return parameter*/
++ *pePowerState = (tmPowerState_t) pDis->ePowerState;
++
++ return TM_OK;
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989PowerSetState */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989PowerSetState
++(
++ tmUnitSelect_t txUnit,
++ tmPowerState_t ePowerState
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 RegVal = 0; /* Local Variable */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ if (ePowerState == tmPowerOff) {
++ ePowerState = tmPowerStandby;
++ }
++
++
++ /* Check remaining parameters */
++ RETIF_BADPARAM((ePowerState != tmPowerStandby)
++ &&(ePowerState != tmPowerSuspend)
++ &&(ePowerState != tmPowerOn)
++ )
++
++ if ((ePowerState == tmPowerStandby)&&(pDis->ePowerState != tmPowerStandby))
++ {
++ /*Disable HPD and RxSense Interrupts*/
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int;
++ RegVal &= ~E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int;
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++ RETIF_REG_FAIL(err)
++
++ /* Disable if coming from ACTIVE */
++ if (pDis->ePowerState == tmPowerOn)
++ {
++
++ /* Disable audio and video ports */
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_AP_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_0_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_1_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_2_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++ /* Disable DDC */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_DDC_DISABLE_RW,
++ E_MASKREG_P00_DDC_DISABLE_ddc_dis,
++ 1); /* 1: disable */
++ RETIF_REG_FAIL(err);
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ /* power down clocks */
++ tmbslTDA9989HdcpPowerDown(txUnit,True);
++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \
++ E_MASKREG_FEAT_POWER_DOWN_all, \
++ 0x0F);
++#endif
++ }
++
++ /*Disable HDMI and RxSense Modes AND FRO if required*/
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/
++
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RETIF_REG_FAIL(err)
++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Set HDMI Mode*/
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/
++
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_rxs; /* Reset RxSense Mode*/
++
++
++ /* disable FRO */
++ RegVal |= E_MASKREG_CEC_ENAMODS_dis_fro;
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++
++ /*Send STANDBY event to the BSL State Machine */
++ setState(pDis, EV_STANDBY);
++ }
++ else if ((ePowerState == tmPowerSuspend)&&(pDis->ePowerState != tmPowerSuspend))
++ {
++
++ /* Disable if coming from ACTIVE */
++ if (pDis->ePowerState == tmPowerOn)
++ {
++ /* Disable audio and video ports */
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_AP_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_0_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_1_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_2_RW,
++ 0x00); /* 0: disable */
++ RETIF_REG_FAIL(err);
++
++ /* Disable DDC */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_DDC_DISABLE_RW,
++ E_MASKREG_P00_DDC_DISABLE_ddc_dis,
++ 1); /* 1: disable */
++ RETIF_REG_FAIL(err);
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ /* power down clocks */
++ tmbslTDA9989HdcpPowerDown(txUnit,True);
++ err = setHwRegisterField(pDis, E_REG_FEAT_POWER_DOWN, \
++ E_MASKREG_FEAT_POWER_DOWN_all, \
++ 0x0F);
++#endif
++ }
++
++ /*Enable RxSense Mode and Disable HDMI Mode*/
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Reset HDMI Mode*/
++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_rxs; /* Set RxSense Mode*/
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++ /*Enable HPD and RxS Interupt in case of the current Device Power States is STANDBY*/
++ /*In other cases, those interrupts have already been enabled*/
++ if(pDis->ePowerState == tmPowerStandby)
++ {
++ /* Enable FRO if coming from STANDBY */
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++ /*Enable HPD and RxS Interupt*/
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal);
++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/
++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++ RETIF_REG_FAIL(err)
++
++ /* force interrupt HPD and RXS level reading */
++ err = tmbslTDA9989HwHandleInterrupt(txUnit);
++ RETIF(err != TM_OK, err)
++
++
++ }
++
++ /*Send the SLEEP event to the BSL State Machine */
++ setState(pDis, EV_SLEEP);
++
++ }
++
++ else if ((ePowerState == tmPowerOn)&&(pDis->ePowerState != tmPowerOn))
++ {
++
++ /* Enable RxSense HDMI Modes */
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_hdmi; /* Set HDMI Mode*/
++ RegVal |= E_MASKREG_CEC_ENAMODS_ena_rxs; /* Set RxSense Mode*/
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++ /*Enable HPD and RxS Interupt in case of the current Device Power States is STANDBY*/
++ /*In other cases, those interrupts have already been enabled*/
++ if(pDis->ePowerState == tmPowerStandby)
++ {
++ /* Enable FRO if coming from STANDBY */
++ err = getCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, &RegVal);
++ RegVal &= ~E_MASKREG_CEC_ENAMODS_dis_fro; /* Enable FRO */
++ err = setCECHwRegister(pDis, E_REG_CEC_ENAMODS_RW, RegVal);
++ RETIF_REG_FAIL(err)
++
++
++ /*Apply the required mode, Reset RxS and HDMI bits*/
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &RegVal);
++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/
++ RegVal |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, RegVal);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++ RETIF_REG_FAIL(err)
++ }
++
++
++ /* Restore BIAS TMDS */
++ RegVal = HDMI_TX_VSWING_VALUE;
++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, RegVal);
++ RETIF(err != TM_OK, err)
++
++
++ err = tmbslTDA9989Reset(txUnit);
++ RETIF(err != TM_OK, err)
++
++
++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0);
++
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR);
++ RETIF(err != TM_OK, err)
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_I2C_MASTER_RW,
++ E_MASKREG_P00_I2C_MASTER_dis_mm,
++ 0);
++ RETIF_REG_FAIL(err)
++
++ } /* TDA19989 N1 only */
++
++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel);
++ RETIF_REG_FAIL(err)
++
++#ifdef TMFL_HDCP_SUPPORT
++ if (pDis->HdcpSeed) {
++ err = tmbslTDA9989HdcpDownloadKeys(txUnit, pDis->HdcpSeed, HDMITX_HDCP_DECRYPT_ENABLE);
++ }
++#endif /* TMFL_HDCP_SUPPORT */
++
++
++ /* Enable DDC */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_DDC_DISABLE_RW,
++ E_MASKREG_P00_DDC_DISABLE_ddc_dis,
++ 0); /* 0: enable */
++ RETIF_REG_FAIL(err)
++
++ /* Enable audio and video ports */
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_AP_RW,
++ 0xFF); /* 1: enable */
++ RETIF_REG_FAIL(err)
++
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_0_RW,
++ 0xFF); /* 1: enable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_1_RW,
++ 0xFF); /* 1: enable */
++ RETIF_REG_FAIL(err)
++
++ err = setHwRegister(pDis,
++ E_REG_P00_ENA_VP_2_RW,
++ 0xFF); /* 1: enable */
++ RETIF_REG_FAIL(err)
++
++
++ /*Send the Hot Plug detection status event to the BSL State Machine */
++ if (pDis->hotPlugStatus == HDMITX_HOTPLUG_ACTIVE)
++ {
++ setState(pDis, EV_PLUGGEDIN);
++ }
++ else
++ {
++ setState(pDis, EV_UNPLUGGED);
++ }
++
++ }
++
++ /* Set the current Device Power status to the required Power Status */
++ pDis->ePowerState = (tmbslHdmiTxPowerState_t) ePowerState;
++
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989Reset */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989Reset
++(
++ tmUnitSelect_t txUnit
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to its object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Reset I2C master and Audio*/
++ (void)setHwRegisterField(pDis, E_REG_P00_SR_REG_W,
++ E_MASKREG_P00_SR_REG_sr_i2c_ms |
++ E_MASKREG_P00_SR_REG_sr_audio, 1);
++
++ pDis->sysFuncTimer(50); /* ms */
++
++ (void)setHwRegisterField(pDis, E_REG_P00_SR_REG_W,
++ E_MASKREG_P00_SR_REG_sr_i2c_ms |
++ E_MASKREG_P00_SR_REG_sr_audio, 0);
++
++ pDis->sysFuncTimer(50); /* ms */
++
++ /* Write to the transmitter to do a soft reset. Don't abort after any
++ * error here, to ensure full reset.
++ */
++ (void)setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW,
++ E_MASKREG_P00_MAIN_CNTRL0_sr, 1);
++ /* pDis->sysFuncTimer(50); */ /* ms */
++ (void)setHwRegisterField(pDis, E_REG_P00_MAIN_CNTRL0_RW,
++ E_MASKREG_P00_MAIN_CNTRL0_sr, 0);
++ /* pDis->sysFuncTimer(50); */ /* ms */
++ /* Clear any colourbars */
++ (void)setHwRegisterField(pDis, E_REG_P00_HVF_CNTRL_0_W,
++ E_MASKREG_P00_HVF_CNTRL_0_sm, 0);
++
++#ifdef TMFL_HDCP_SUPPORT
++ /* Disable any scheduled function and HDCP check timer */
++ pDis->HdcpFuncRemainingMs = 0;
++ pDis->HdcpCheckNum = 0;
++#endif /* TMFL_HDCP_SUPPORT */
++
++ /* Switch BSL State machine into UNINITIALIZED State */
++ setState(pDis, EV_DEINIT);
++ /* Switch Power State into STAND_BY State */
++ //pDis->ePowerState = tmPowerStandby;
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SwGetVersion */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SwGetVersion
++(
++ ptmSWVersion_t pSWVersion
++)
++{
++ /* Check parameters */
++ RETIF_BADPARAM(pSWVersion == (ptmSWVersion_t)0)
++
++ /* Get the version details of the component. */
++ pSWVersion->compatibilityNr = HDMITX_BSL_COMP_NUM;
++ pSWVersion->majorVersionNr = HDMITX_BSL_MAJOR_VER;
++ pSWVersion->minorVersionNr = HDMITX_BSL_MINOR_VER;
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SysTimerWait */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SysTimerWait
++(
++ tmUnitSelect_t txUnit,
++ UInt16 waitMs
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Return if this device timer is not set up */
++ RETIF(!pDis->sysFuncTimer, TMBSL_ERR_HDMI_NOT_INITIALIZED)
++
++ /* Wait for the requested time */
++ pDis->sysFuncTimer(waitMs);
++
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989TestSetMode */
++/*============================================================================*/
++
++tmErrorCode_t
++tmbslTDA9989TestSetMode
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxTestMode_t testMode,
++ tmbslHdmiTxTestState_t testState
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ /* Register used to activate a test */
++ UInt16 testReg = E_REG_P00_VIP_CNTRL_4_W;
++ /* Register bitfield mask used */
++ UInt8 testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_pat;
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM(testMode >= HDMITX_TESTMODE_INVALID)
++ RETIF_BADPARAM(testState >= HDMITX_TESTSTATE_INVALID)
++
++ /* Set the mode selected by testMode to the state indicated by testState */
++ switch (testMode)
++ {
++ case HDMITX_TESTMODE_PAT:
++ testReg = E_REG_P00_VIP_CNTRL_4_W;
++ testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_pat;
++ break;
++ case HDMITX_TESTMODE_656:
++ testReg = E_REG_P00_VIP_CNTRL_4_W;
++ testMask = E_MASKREG_P00_VIP_CNTRL_4_tst_656;
++ break;
++ case HDMITX_TESTMODE_SERPHOE:
++ /*testReg = E_REG_P02_TEST1_RW;
++ testMask = E_MASKREG_P02_TEST1_tstserphoe;*/
++ break;
++ case HDMITX_TESTMODE_NOSC:
++ testReg = E_REG_P02_TEST1_RW;
++ testMask = E_MASKREG_P02_TEST1_tst_nosc;
++ break;
++ case HDMITX_TESTMODE_HVP:
++ /*testReg = E_REG_P02_TEST1_RW;
++ testMask = E_MASKREG_P02_TEST1_tst_hvp;*/
++ break;
++ case HDMITX_TESTMODE_PWD:
++ /*testReg = E_REG_P02_TEST2_RW;
++ testMask = E_MASKREG_P02_TEST2_pwd1v8;*/
++ break;
++ case HDMITX_TESTMODE_DIVOE:
++ /*testReg = E_REG_P02_TEST2_RW;
++ testMask = E_MASKREG_P02_TEST2_divtestoe;*/
++ break;
++ case HDMITX_TESTMODE_INVALID:
++ break;
++ }
++ err = setHwRegisterField(pDis, testReg, testMask, (UInt8)testState);
++ return err;
++}
++
++/*============================================================================*/
++/**
++ \brief Fill Gamut metadata packet into one of the gamut HW buffer. this
++ function is not sending any gamut metadata into the HDMI stream,
++ it is only loading data into the HW.
++
++ \param txUnit Transmitter unit number
++ \param pPkt pointer to the gamut packet structure
++ \param bufSel number of the gamut buffer to fill
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_BSLHDMIRX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_BSLHDMIRX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_BSLHDMIRX_I2C_WRITE: failed when writing to the I2C
++ bus
++
++ ******************************************************************************/
++tmErrorCode_t tmbslTDA9989PktFillGamut
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxPktGamut_t *pPkt,
++ UInt8 bufSel
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM((bufSel != 0) && (bufSel != 1))
++
++ /* Fill Gamut registers*/
++ /*Fill buffer 0*/
++ if(bufSel == 0)
++ {
++ /*Write Header*/
++ err = setHwRegisters(pDis, E_REG_P13_GMD_0_HB0_RW, &pPkt->HB[0], 3);
++ RETIF(err != TM_OK, err)
++ /*Write Payload*/
++ err = setHwRegisters(pDis, E_REG_P13_GMD_0_PB0_RW, &pPkt->PB[0], 28);
++ RETIF(err != TM_OK, err)
++ }
++
++ /*Fill buffer 1*/
++ else
++ {
++ /*Write Header*/
++ err = setHwRegisters(pDis, E_REG_P13_GMD_1_HB0_RW, &pPkt->HB[0], 3);
++ RETIF(err != TM_OK, err)
++ /*Write Payload*/
++ err = setHwRegisters(pDis, E_REG_P13_GMD_1_PB0_RW, &pPkt->PB[0], 28);
++ RETIF(err != TM_OK, err)
++ }
++
++return err;
++}
++
++/*============================================================================*/
++/**
++ \brief Enable transmission of gamut metadata packet. Calling this function
++ tells HW which gamut buffer to send into the HDMI stream. HW will
++ only take into account this command at the next VS, not during the
++ current one.
++
++ \param txUnit Transmitter unit number
++ \param bufSel Number of the gamut buffer to be sent
++ \param enable Enable/disable gamut packet transmission
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMBSL_ERR_BSLHDMIRX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMBSL_ERR_BSLHDMIRX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_BSLHDMIRX_I2C_WRITE: failed when writing to the I2C
++ bus
++
++ ******************************************************************************/
++tmErrorCode_t tmbslTDA9989PktSendGamut
++(
++ tmUnitSelect_t txUnit,
++ UInt8 bufSel,
++ Bool bEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 GMD_Ctrl_Val; /*GMD control Value*/
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM((bufSel != 0) && (bufSel != 1))
++
++ /*Init Value*/
++ GMD_Ctrl_Val = 0x00;
++
++ /*Enable Send of Gamut MetaData*/
++ if(bEnable)
++ {
++ /*Send Buffer 0*/
++ if(bufSel == 0)
++ {
++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_enable;
++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_buf_sel;
++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val);
++ RETIF(err != TM_OK, err)
++ }
++ /*Send Buffer 1*/
++ else
++ {
++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_enable;
++ GMD_Ctrl_Val |= E_MASKREG_P13_GMD_CONTROL_buf_sel;
++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val);
++ RETIF(err != TM_OK, err)
++ }
++ }
++ /*Disable Send of Gamut MetaData*/
++ else
++ {
++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_enable;
++ GMD_Ctrl_Val &= ~E_MASKREG_P13_GMD_CONTROL_buf_sel;
++ err = setHwRegister(pDis, E_REG_P13_GMD_CONTROL_RW, GMD_Ctrl_Val);
++ RETIF(err != TM_OK, err)
++ }
++
++ return err;
++}
++
++
++
++
++/*============================================================================*/
++/* tmbslTDA9989EnableCallback */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989EnableCallback
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxCallbackInt_t callbackSource,
++ Bool enable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err = TM_OK; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM( callbackSource >= HDMITX_CALLBACK_INT_NUM )
++
++ switch (callbackSource)
++ {
++ case HDMITX_CALLBACK_INT_VS_RPT:
++ /* Enable or disable VS Interrupt */
++ err = setHwRegisterField(pDis,
++ E_REG_P00_INT_FLAGS_1_RW,
++ E_MASKREG_P00_INT_FLAGS_1_vs_rpt,
++ (UInt8)enable);
++ if (enable)
++ {
++ pDis->InterruptsEnable |= (1 << callbackSource);
++ }
++ else
++ {
++ pDis->InterruptsEnable &= ~(1 << callbackSource);
++ }
++ break;
++ default:
++ err = TMBSL_ERR_HDMI_NOT_SUPPORTED;
++ break;
++ }
++
++ return err;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SetColorDepth */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SetColorDepth
++(
++ tmUnitSelect_t txUnit,
++ tmbslHdmiTxColorDepth colorDepth,
++ Bool termEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err = TM_OK; /* Error code */
++
++ DUMMY_ACCESS(termEnable);
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Check parameters */
++ RETIF_BADPARAM( colorDepth >= HDMITX_COLORDEPTH_INVALID )
++
++ switch (colorDepth)
++ {
++ case HDMITX_COLORDEPTH_NO_CHANGE:
++ break;
++
++ case HDMITX_COLORDEPTH_24:
++
++ break;
++
++ default:
++ err = TMBSL_ERR_HDMI_NOT_SUPPORTED;
++ break;
++ }
++
++ return err;
++
++}
++
++
++/*============================================================================*/
++/* tmbslTDA9989Set5vpower */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989Set5vpower
++(
++ tmUnitSelect_t txUnit,
++ Bool pwrEnable
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ DUMMY_ACCESS(pwrEnable);
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++/*============================================================================*/
++/* tmbslTDA9989SetDefaultPhase */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989SetDefaultPhase
++(
++ tmUnitSelect_t txUnit,
++ Bool bEnable,
++ tmbslHdmiTxColorDepth colorDepth,
++ UInt8 videoFormat
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ DUMMY_ACCESS(bEnable);
++ DUMMY_ACCESS(colorDepth);
++ DUMMY_ACCESS(videoFormat);
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ return TMBSL_ERR_HDMI_NOT_SUPPORTED;
++}
++
++
++
++/*============================================================================*/
++/* tmbslDebugWriteFakeRegPage */
++/*============================================================================*/
++tmErrorCode_t tmbslDebugWriteFakeRegPage( tmUnitSelect_t txUnit )
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ err = checkUnitSetDis(txUnit, &pDis);
++
++ pDis->curRegPage = 0x20;
++
++ return err;
++}
++
++
++/*============================================================================*/
++/* hotPlugRestore */
++/*============================================================================*/
++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit )
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal;
++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Set the BIAS_tmds Value */
++ regVal = HDMI_TX_VSWING_VALUE;
++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal);
++ RETIF(err != TM_OK, err)
++
++ /* PLL registers common configuration */
++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/
++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0);
++
++ /* DDC interface is disable for TDA9989 after reset, enable it */
++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00);
++ RETIF(err != TM_OK, err)
++
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, TDA19989_DDC_SPEED_FACTOR);
++ RETIF(err != TM_OK, err)
++
++ /* TDA19989 N1 only */
++ if (pDis->uDeviceVersion == E_DEV_VERSION_TDA19989) {
++
++ err = setHwRegisterField(pDis,
++ E_REG_P00_I2C_MASTER_RW,
++ E_MASKREG_P00_I2C_MASTER_dis_mm,
++ 0); /* 0: enable multi master mode */
++ RETIF_REG_FAIL(err)
++
++ } /* TDA19989 N1 only */
++
++
++ err = setCECHwRegister(pDis, E_REG_CEC_FRO_IM_CLK_CTRL_RW, E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis | E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel);
++ RETIF_REG_FAIL(err)
++
++
++
++
++ /* enable sw_interrupt for debug */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW,
++ E_MASKREG_P00_INT_FLAGS_1_sw_int);
++
++ /* enable edid read */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW,
++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd);
++
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask);
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++
++#ifdef TMFL_HDCP_SUPPORT
++
++ if (pDis->HdcpSeed)
++ {
++ err = tmbslTDA9989HdcpDownloadKeys(txUnit, pDis->HdcpSeed, HDMITX_HDCP_DECRYPT_ENABLE);
++ }
++
++#endif /* TMFL_HDCP_SUPPORT */
++
++ setState(pDis, EV_INIT);
++
++ return err;
++}
++
++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++
++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit )
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++ UInt8 regVal;
++ UInt8 EnableIntMask = 0; /* Mask used to enable HPD and RX Sense interrupt*/
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err)
++
++ /* Set the BIAS_tmds Value */
++ regVal = HDMI_TX_VSWING_VALUE;
++ err = setHwRegister(pDis, E_REG_P02_ANA_GENERAL_RW, regVal);
++ RETIF(err != TM_OK, err)
++
++ /* PLL registers common configuration */
++ err = setHwRegisterFieldTable(pDis, &kCommonPllCfg[0]);
++ RETIF_REG_FAIL(err)
++
++ /*Reset 656_Alt bit in VIP_CONTROL_4 Register*/
++ err = setHwRegisterField( pDis, E_REG_P00_VIP_CNTRL_4_W, E_MASKREG_P00_VIP_CNTRL_4_656_alt, 0);
++
++ /* DDC interface is disable for TDA9989 after reset, enable it */
++ err = setHwRegister(pDis, E_REG_P00_DDC_DISABLE_RW, 0x00);
++ RETIF(err != TM_OK, err)
++
++
++
++ if ( (pDis->vinFmt != HDMITX_VFMT_NO_CHANGE) && (pDis->vinFmt <= HDMITX_VFMT_TV_MAX ) ) {
++
++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, 0);
++ RETIF(err != TM_OK, err)
++
++ err = setHwRegister(pDis, E_REG_P00_NDIV_IM_W, kndiv_im[pDis->vinFmt]);
++ RETIF(err != TM_OK, err)
++
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, kclk_div[pDis->vinFmt]);
++ RETIF(err != TM_OK, err)
++
++ }
++ else if (pDis->vinFmt > HDMITX_VFMT_TV_MAX) {
++
++ err = setHwRegister(pDis, E_REG_P00_TIMER_H_W, E_MASKREG_P00_TIMER_H_im_clksel);
++ RETIF(err != TM_OK, err)
++ err = setHwRegister(pDis, E_REG_P12_TX3_RW, 17);
++ RETIF(err != TM_OK, err)
++ }
++
++
++
++
++
++ /* enable sw_interrupt for debug */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_1_RW,
++ E_MASKREG_P00_INT_FLAGS_1_sw_int);
++
++ /* enable edid read */
++ err = setHwRegister(pDis, E_REG_P00_INT_FLAGS_2_RW,
++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd);
++
++ err = getCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, &EnableIntMask);
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int; /* Enable RxSense Interrupt*/
++ EnableIntMask |= E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int; /* Enable HPD Interrupt*/
++ err += setCECHwRegister(pDis, E_REG_CEC_RXSHPDINTENA_RW, EnableIntMask);
++ err += getCECHwRegister(pDis, E_REG_CEC_RXSHPDLEV_R,&int_level);
++
++ return err;
++}
++
++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++/*============================================================================*/
++/* tmbslTDA9989HdcpPowerDown */
++/* RETIF_REG_FAIL NOT USED HERE AS ALL ERRORS SHOULD BE TRAPPED IN ALL BUILDS */
++/*============================================================================*/
++tmErrorCode_t
++tmbslTDA9989HdcpPowerDown
++(
++ tmUnitSelect_t txUnit,
++ Bool requested
++)
++{
++ tmHdmiTxobject_t *pDis; /* Pointer to Device Instance Structure */
++ tmErrorCode_t err; /* Error code */
++
++ /* Check unit parameter and point to TX unit object */
++ err = checkUnitSetDis(txUnit, &pDis);
++ RETIF(err != TM_OK, err);
++
++ err = setHwRegisterField(pDis, E_REG_P12_TX4_RW, \
++ E_MASKREG_P12_TX4_pd_all, \
++ (requested?0x07:0x00));
++ return err;
++
++}
++#endif
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h
+new file mode 100755
+index 0000000..990ee5c
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_Misc_l.h
+@@ -0,0 +1,62 @@
++/**
++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of Koninklijke Philips Electronics N.V. and is confidential in
++ * nature. Under no circumstances is this software to be exposed to or placed
++ * under an Open Source License of any type without the expressed written
++ * permission of Koninklijke Philips Electronics N.V.
++ *
++ * \file tmbslTDA9989_Misc_l.h
++ *
++ * \version $Revision: 2 $
++ *
++*/
++
++#ifndef TMBSLTDA9989_MISC_L_H
++#define TMBSLTDA9989_MISC_L_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++extern CONST_DAT UInt8 kndiv_im[];
++extern CONST_DAT UInt8 kclk_div[];
++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit );
++
++#ifdef TMFL_TDA9989_PIXEL_CLOCK_ON_DDC
++tmErrorCode_t hotPlugRestore ( tmUnitSelect_t txUnit );
++#endif /* TMFL_TDA9989_PIXEL_CLOCK_ON_DDC */
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_MISC_L_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c
+new file mode 100755
+index 0000000..887f8e1
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State.c
+@@ -0,0 +1,240 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_state.c
++ *
++ * \version $Revision: 2 $
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#include <linux/module.h>
++#endif
++
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++#include "tmbslTDA9989_State_l.h"
++
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* DEFINES DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/*============================================================================*/
++/* setState */
++/*============================================================================*/
++tmErrorCode_t
++setState
++(
++ tmHdmiTxobject_t *pDis,
++ tmbslTDA9989Event_t event
++)
++{
++ tmbslTDA9989State_t state = pDis->state;
++ UInt8 nIgnoredEvents = pDis->nIgnoredEvents;
++
++ switch (state)
++ {
++ case ST_UNINITIALIZED:
++ switch (event)
++ {
++ case EV_INIT: state = ST_STANDBY; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++
++ case ST_STANDBY:
++ switch (event)
++ {
++ case EV_UNPLUGGED: state = ST_DISCONNECTED; break; /*Only when PowerSetState(ON)*/
++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; /*Only when PowerSetState(ON)*/
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_SETINOUT: state = ST_VIDEO_NO_HDCP; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_SLEEP:
++ switch (event)
++ {
++ case EV_UNPLUGGED: state = ST_DISCONNECTED; break; /*Only when PowerSetState(ON)*/
++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break; /*Only when PowerSetState(ON)*/
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++
++ case ST_DISCONNECTED:
++ switch (event)
++ {
++ case EV_PLUGGEDIN: state = ST_AWAIT_EDID; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_AWAIT_EDID:
++ switch (event)
++ {
++ case EV_GETBLOCKDATA: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++
++ case ST_AWAIT_RX_SENSE:
++ switch (event)
++ {
++ case EV_SINKON: state = ST_SINK_CONNECTED; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++
++ case ST_SINK_CONNECTED:
++ switch (event)
++ {
++ case EV_SETINOUT: state = ST_VIDEO_NO_HDCP; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_VIDEO_NO_HDCP:
++ switch (event)
++ {
++ case EV_OUTDISABLE: state = ST_SINK_CONNECTED; break;
++ case EV_HDCP_RUN: state = ST_HDCP_WAIT_RX; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_HDCP_WAIT_RX:
++ switch (event)
++ {
++ case EV_HDCP_BKSV_NREPEAT: state = ST_HDCP_AUTHENTICATED;break;
++ case EV_HDCP_BKSV_REPEAT: state = ST_HDCP_WAIT_BSTATUS; break;
++ case EV_HDCP_BKSV_NSECURE: state = ST_HDCP_WAIT_RX; break;
++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break;
++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_HDCP_WAIT_BSTATUS:
++ switch (event)
++ {
++ case EV_HDCP_BSTATUS_GOOD: state = ST_HDCP_WAIT_SHA_1; break;
++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break;
++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_HDCP_WAIT_SHA_1:
++ switch (event)
++ {
++ case EV_HDCP_KSV_SECURE: state = ST_HDCP_AUTHENTICATED;break;
++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break;
++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++ case ST_HDCP_AUTHENTICATED:
++ switch (event)
++ {
++ case EV_HDCP_T0: state = ST_HDCP_WAIT_RX; break;
++ case EV_HDCP_STOP: state = ST_VIDEO_NO_HDCP; break;
++ case EV_SINKOFF: state = ST_AWAIT_RX_SENSE; break;
++ case EV_DEINIT: state = ST_UNINITIALIZED; break;
++ case EV_STANDBY: state = ST_STANDBY; break;
++ case EV_SLEEP: state = ST_SLEEP; break;
++ case EV_UNPLUGGED: state = ST_SLEEP; break;
++ default: nIgnoredEvents++; break;
++ }
++ break;
++
++ case ST_INVALID:
++ nIgnoredEvents++;
++ break;
++
++ default:
++ break;
++ }
++
++ pDis->state = state;
++ pDis->nIgnoredEvents = nIgnoredEvents;
++
++ if (nIgnoredEvents)
++ {
++ /* int cbeDebug = 1; */
++ }
++
++ return TM_OK;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setState);
++#endif
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h
+new file mode 100755
+index 0000000..c0e7857
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_State_l.h
+@@ -0,0 +1,56 @@
++/**
++ * Copyright (C) 2009 Koninklijke Philips Electronics N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of Koninklijke Philips Electronics N.V. and is confidential in
++ * nature. Under no circumstances is this software to be exposed to or placed
++ * under an Open Source License of any type without the expressed written
++ * permission of Koninklijke Philips Electronics N.V.
++ *
++ * \file tmbslTDA9989_State.h
++ *
++ * \version $Revision: 2 $
++ *
++ *
++*/
++
++#ifndef TMBSLTDA9989_STATE_L_H
++#define TMBSLTDA9989_STATE_L_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++tmErrorCode_t setState (tmHdmiTxobject_t *pDis, tmbslTDA9989Event_t event);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_STATE_L_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c
+new file mode 100755
+index 0000000..9030ebc
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.c
+@@ -0,0 +1,670 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_local.c
++ *
++ * \version $Revision: 2 $
++ *
++ *
++*/
++
++/*============================================================================*/
++/* FILE CONFIGURATION */
++/*============================================================================*/
++
++/* Defining this symbol on the compiler command line excludes some API checks */
++/* #define NO_RETIF_BADPARAM */
++
++/*============================================================================*/
++/* STANDARD INCLUDE FILES */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* PROJECT INCLUDE FILES */
++/*============================================================================*/
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_Functions.h"
++#include "tmbslTDA9989_local.h"
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* TYPE DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* PUBLIC VARIABLE DEFINITIONS */
++/*============================================================================*/
++
++/** The array of object instances for all concurrently supported HDMI
++ * Transmitter units
++ */
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#ifdef USE_SHARED_HDMI_INSTANCE
++extern tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX];
++#else
++#include <linux/kernel.h>
++#include <linux/module.h>
++RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX];
++EXPORT_SYMBOL(gHdmiTxInstance);
++#endif
++#else
++RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX];
++#endif
++
++/**
++ * Lookup table to map register page index to actual page number
++ */
++CONST_DAT UInt8 kPageIndexToPage[E_PAGE_NUM] =
++{
++ 0x00, /* E_PAGE_00 */
++ 0x01, /* E_PAGE_01 */
++ 0x02, /* E_PAGE_02 */
++ 0x09, /* E_PAGE_09 */
++ 0x10, /* E_PAGE_10 */
++ 0x11, /* E_PAGE_11 */
++ 0x12, /* E_PAGE_12 */
++ 0x13 /* E_PAGE_13 */
++};
++
++
++/*============================================================================*/
++/* STATIC VARIABLE DECLARATIONS */
++/*============================================================================*/
++
++/**
++ * Lookup table to map an 8-bit mask to a number of left shifts
++ * needed to shift a value starting at bit 0 onto the mask.
++ * Indexed by mask 0-255. For example, mask 0x00 and 0x01 need
++ * no shift, mask 0x02 needs one shift, mask 0x03 needs no shift,
++ * mask 0x04 needs 2 shifts, etc.
++ * Rows were formatted by "HDMI Driver - Register List.xls" and pasted here
++ */
++static CONST_DAT UInt8 kMaskToShift[256] =
++{/* Mask index: */
++ /*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
++ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 1x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 2x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 3x */
++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 4x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 5x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 6x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 7x */
++ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 8x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 9x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ax */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Bx */
++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Cx */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Dx */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ex */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* Fx */
++};
++
++/*============================================================================*/
++/* STATIC FUNCTION DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* PUBLIC FUNCTION DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* checkUnitSetDis */
++/*============================================================================*/
++tmErrorCode_t
++checkUnitSetDis
++(
++ tmUnitSelect_t txUnit,
++ tmHdmiTxobject_t **ppDis
++)
++{
++ /* Return error if unit numbr is out of range */
++ RETIF(txUnit < tmUnit0, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
++ RETIF(txUnit >= HDMITX_UNITS_MAX, TMBSL_ERR_HDMI_BAD_UNIT_NUMBER)
++
++ /* Point to unit's Device Instance Structure */
++ *ppDis = &gHdmiTxInstance[txUnit];
++
++ /* Return if this device instance is not initialised */
++ if(!(*ppDis)->bInitialized)
++ {
++ return TMBSL_ERR_HDMI_NOT_INITIALIZED;
++ }
++
++ return TM_OK;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(checkUnitSetDis);
++#endif
++
++/*============================================================================*/
++/* getHwRegisters */
++/*============================================================================*/
++tmErrorCode_t
++getHwRegisters
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pData,
++ UInt16 lenData
++ )
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regShad; /* The index to the register's shadow copy */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack 1st register's shadow index, page index and address */
++ regShad = SPA2SHAD(regShadPageAddr);
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Check length does not overflow page */
++ RETIF_BADPARAM((regAddr+lenData) > E_REG_CURPAGE_ADR_W)
++
++ /* Check 1st reg does not have a shadow - whole range assumed likewise */
++ RETIF_BADPARAM(regShad != E_SNONE)
++
++ /* Set page register if required */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* Get I2C register range - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = (UInt8)lenData;
++ sysArgs.pData = pData;
++ err = pDis->sysFuncRead(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(getHwRegisters);
++#endif
++
++/*============================================================================*/
++/* getHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++getHwRegister
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pRegValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regShad; /* The index to the register's shadow copy */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack register shadow index, page index and address */
++ regShad = SPA2SHAD(regShadPageAddr);
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Set page register if required */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ if ((regShad != E_SNONE)
++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_0_RW)
++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_1_RW)
++ && (regShadPageAddr != E_REG_P00_INT_FLAGS_2_RW))
++ {
++ /* Get shadow copy - shadowed registers can't be read */
++ /* Don't read shadow copy of interrupt status flags! */
++ *pRegValue = pDis->shadowReg[regShad];
++ return TM_OK;
++ }
++ else
++ {
++ /* Get I2C register - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = pRegValue;
++ err = pDis->sysFuncRead(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ;
++ }
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(getHwRegister);
++#endif
++
++/*============================================================================*/
++/* setHwRegisters */
++/*============================================================================*/
++tmErrorCode_t
++setHwRegisters
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pData,
++ UInt16 lenData
++ )
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regShad; /* The index to the register's shadow copy */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack 1st register's shadow index, page index and address */
++ regShad = SPA2SHAD(regShadPageAddr);
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Check length does not overflow page */
++ RETIF_BADPARAM((regAddr+lenData) > E_REG_CURPAGE_ADR_W)
++
++ /* Check 1st reg does not have a shadow - whole range assumed likewise */
++ RETIF_BADPARAM(regShad != E_SNONE)
++
++ /* Set page register if required - whole range is on same page */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* Write to I2C register range - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = (UInt8)lenData;
++ sysArgs.pData = pData;
++ err = pDis->sysFuncWrite(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setHwRegisters);
++#endif
++
++
++/*============================================================================*/
++/* setHwRegisterMsbLsb */
++/*============================================================================*/
++tmErrorCode_t
++setHwRegisterMsbLsb
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt16 regWord
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ UInt8 msbLsb[2]; /* The bytes from regWord */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack register shadow index, page index and address */
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Unpack regWord bytes, MSB first */
++ msbLsb[0] = (UInt8)(regWord >> 8);
++ msbLsb[1] = (UInt8)(regWord & 0xFF);
++
++ /* Set page register if required */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* No word registers are shadowed */
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 2;
++ sysArgs.pData = &msbLsb[0];
++ err = pDis->sysFuncWrite(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setHwRegisterMsbLsb);
++#endif
++
++/*============================================================================*/
++/* setHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++setHwRegister_main
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 regValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regShad; /* The index to the register's shadow copy */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack register shadow index, page index and address */
++ regShad = SPA2SHAD(regShadPageAddr);
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Set page register if required */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ /* Set shadow copy */
++ if (regShad != E_SNONE)
++ {
++ pDis->shadowReg[regShad] = regValue;
++ }
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->sysFuncWrite(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setHwRegister_main);
++#endif
++
++/*============================================================================*/
++/* setHwRegisterField */
++/*============================================================================*/
++tmErrorCode_t
++setHwRegisterField
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 fieldMask,
++ UInt8 fieldValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regShad; /* The index to the register's shadow copy */
++ UInt8 regPage; /* The index to the register's page */
++ UInt8 regAddr; /* The register's address on the page */
++ UInt8 newRegPage; /* The register's new page number */
++ UInt8 regValue; /* The register's current value */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack register shadow index, page index and address */
++ regShad = SPA2SHAD(regShadPageAddr);
++ regPage = SPA2PAGE(regShadPageAddr);
++ regAddr = SPA2ADDR(regShadPageAddr);
++ newRegPage = kPageIndexToPage[regPage];
++
++ /* Set page register if required */
++ if (pDis->curRegPage != newRegPage)
++ {
++ /* All non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = E_REG_CURPAGE_ADR_W;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &newRegPage;
++ err = pDis->sysFuncWrite(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_WRITE)
++ pDis->curRegPage = newRegPage;
++ }
++
++ if (regShad != E_SNONE)
++ {
++ /* Get shadow copy */
++ regValue = pDis->shadowReg[regShad];
++ }
++ else
++ {
++ /* Read I2C register value.
++ * All bitfield registers are either shadowed or can be read.
++ */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->sysFuncRead(&sysArgs);
++ RETIF(err != TM_OK, TMBSL_ERR_HDMI_I2C_READ)
++ }
++
++ /* Reset register bits that are set in the mask */
++ regValue = regValue & (UInt8)(~fieldMask);
++
++ /* Shift the field value left to align its bits with the mask */
++ fieldValue <<= kMaskToShift[fieldMask];
++
++ /* Reset shifted field bits that are not set in the mask */
++ fieldValue &= fieldMask;
++
++ /* Set the shifted bitfield */
++ regValue |= fieldValue;
++
++ /* Set shadow copy */
++ if (regShad != E_SNONE)
++ {
++ pDis->shadowReg[regShad] = regValue;
++ }
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->uHwAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->sysFuncWrite(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setHwRegisterField);
++#endif
++
++/*============================================================================*/
++/* getCECHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++getCECHwRegister
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regAddr,
++ UInt8 *pRegValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++ UInt8 CECAddress; /* CEC Address deduced from uHwAddress */
++
++ /*Convert HwAddress into CEC Address*/
++ CECAddress = pDis->uHwAddress;
++ CECAddress = CECAddress ^ 0x44; /*Convert address to obtain the correspondance in CEC*/
++ /*CECAddress = ((~CECAddress & 0x44)||(CECAddress & 0xBB)); */
++ /*Prepare Write operation*/
++ sysArgs.slaveAddr = CECAddress;
++ sysArgs.firstRegister = (UInt8)regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = pRegValue;
++
++ /*Read data in Chip*/
++ err = pDis->sysFuncRead(&sysArgs); /* Call IC Read function*/
++
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_READ;
++
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(getCECHwRegister);
++#endif
++
++/*============================================================================*/
++/* setCECHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++setCECHwRegister
++(
++ tmHdmiTxobject_t *pDis,
++ UInt16 regAddr,
++ UInt8 regValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ tmbslHdmiTxSysArgs_t sysArgs; /* Arguments passed to system function */
++ UInt8 CECAddress; /* CEC Address deduced from uHwAddress */
++
++ /*Convert HwAddress into CEC Address*/
++ CECAddress = pDis->uHwAddress;
++ CECAddress = CECAddress ^ 0x44; /*Convert address to obtain the correspondance in CEC*/
++
++ /*Prepare Write operation*/
++ sysArgs.slaveAddr = CECAddress;
++ sysArgs.firstRegister = (UInt8)regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++
++ /*Write data in Chip*/
++ err = pDis->sysFuncWrite(&sysArgs); /* Call IC Write function*/
++
++ return (err == TM_OK) ? TM_OK : TMBSL_ERR_HDMI_I2C_WRITE;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setCECHwRegister);
++#endif
++
++/*============================================================================*/
++/* setHwRegisterFieldTable */
++/*============================================================================*/
++tmErrorCode_t
++setHwRegisterFieldTable
++(
++ tmHdmiTxobject_t *pDis,
++ const tmHdmiTxRegMaskVal_t *pTable
++)
++{
++ tmErrorCode_t err; /* Error code */
++ Int i; /* Table index */
++
++ /* Set register, mask and value from table until terminator is reached */
++ for (i = 0; pTable[i].Reg > 0; i++)
++ {
++ err = setHwRegisterField(pDis, pTable[i].Reg, pTable[i].Mask, pTable[i].Val);
++ RETIF(err != TM_OK, err)
++ }
++ return TM_OK;
++}
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++EXPORT_SYMBOL(setHwRegisterFieldTable);
++#endif
++
++
++/*============================================================================*/
++/* lmemcpy */
++/*============================================================================*/
++tmErrorCode_t
++lmemcpy
++(
++ void *pTable1,
++ const void * pTable2,
++ UInt Size
++)
++{
++ char *ptrSource = (char*) pTable1;
++ char *endSource = (char*)pTable1 + Size;
++ char *ptrDest = (char *)pTable2;
++
++ RETIF_BADPARAM(pTable1 == Null)
++ RETIF_BADPARAM(pTable2 == Null)
++
++ while (endSource > ptrSource)
++ {
++ *(ptrSource++) = *(ptrDest++);
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* lmemset */
++/*============================================================================*/
++tmErrorCode_t
++lmemset
++(
++ void *pTable1,
++ const UInt8 value,
++ UInt Size
++)
++{
++ char *ptrSource = (char*) pTable1;
++ char *endSource = (char*)pTable1 + Size;
++
++ RETIF_BADPARAM(pTable1 == Null)
++
++ while (endSource > ptrSource)
++ {
++ *(ptrSource++) = value;
++ }
++ return TM_OK;
++}
++
++/*============================================================================*/
++/* STATIC FUNCTION DEFINTIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h
+new file mode 100755
+index 0000000..02843e2
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local.h
+@@ -0,0 +1,2056 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_local.h
++ *
++ * \version %version: 3 %
++ *
++*/
++
++#ifndef TMBSLTDA9989_LOCAL_H
++#define TMBSLTDA9989_LOCAL_H
++#define setHwRegister(pDis, regShadPageAddr, regValue) setHwRegister_main(pDis, regShadPageAddr, regValue); printk("Setting " # regShadPageAddr "\n");
++
++/*
++
++ INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++#ifndef DUMMY_ACCESS
++#ifdef _WINDOWS
++#define DUMMY_ACCESS(x) x
++#else
++#define DUMMY_ACCESS(x)
++#endif
++#endif /* DUMMY_ACCESS */
++
++/** \name Versions
++ * A group of macros to set the software component number and version
++ */
++/*@{*/
++/** Compatibility number */
++#define HDMITX_BSL_COMP_NUM 1
++
++/** Major software version 1 to 255 */
++#define HDMITX_BSL_MAJOR_VER 5
++
++/** Minor software version 0 to 9 */
++#define HDMITX_BSL_MINOR_VER 4
++/*@}*/
++
++/** \name ErrorChecks
++ * A group of checks ensuring that public error codes match DVP standard errors
++ */
++/*@{*/
++/** SW interface compatibility error */
++#if TMBSL_ERR_HDMI_COMPATIBILITY != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_COMPATIBILITY)
++#error
++#endif
++
++/** SW major version error */
++#if TMBSL_ERR_HDMI_MAJOR_VERSION != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_MAJOR_VERSION)
++#error
++#endif
++
++/** SW component version error */
++#if TMBSL_ERR_HDMI_COMP_VERSION != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_COMP_VERSION)
++#error
++#endif
++
++/** Invalid device unit number */
++#if TMBSL_ERR_HDMI_BAD_UNIT_NUMBER != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_BAD_UNIT_NUMBER)
++#error
++#endif
++
++/** Invalid input parameter other than unit number */
++#if TMBSL_ERR_HDMI_BAD_PARAMETER != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_BAD_PARAMETER)
++#error
++#endif
++
++/** Inconsistent input parameters */
++#if TMBSL_ERR_HDMI_INCONSISTENT_PARAMS != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_INCONSISTENT_PARAMS)
++#error
++#endif
++
++/** Component is not initialized */
++#if TMBSL_ERR_HDMI_NOT_INITIALIZED != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_NOT_INITIALIZED)
++#error
++#endif
++
++/** Command not supported for current device */
++#if TMBSL_ERR_HDMI_NOT_SUPPORTED != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_NOT_SUPPORTED)
++#error
++#endif
++
++/** Initialization failed */
++#if TMBSL_ERR_HDMI_INIT_FAILED != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_INIT_FAILED)
++#error
++#endif
++
++/** Component is busy and cannot do a new operation */
++#if TMBSL_ERR_HDMI_BUSY != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_BUSY)
++#error
++#endif
++
++/** I2C read error */
++#if TMBSL_ERR_HDMI_I2C_READ != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_READ)
++#error
++#endif
++
++/** I2C write error */
++#if TMBSL_ERR_HDMI_I2C_WRITE != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_WRITE)
++#error
++#endif
++
++/** Assertion failure */
++#if TMBSL_ERR_HDMI_ASSERTION != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_ASSERTION)
++#error
++#endif
++
++/** Bad EDID block checksum */
++#if TMBSL_ERR_HDMI_INVALID_CHECKSUM != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_INVALID_STATE)
++#error
++#endif
++
++/** No connection to HPD pin */
++#if TMBSL_ERR_HDMI_NULL_CONNECTION != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_NULL_CONNECTION)
++#error
++#endif
++
++/** Not allowed in DVI mode */
++#if TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_OPERATION_NOT_PERMITTED)
++#error
++#endif
++
++/** Ressource not available*/
++#if TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE != \
++(TMBSL_ERR_HDMI_BASE + TM_ERR_NO_RESOURCES)
++#error
++#endif
++
++
++/*@}*/
++
++/**
++ * A macro to check a condition and if true return a result
++ */
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#define RETIF(cond, rslt) if ((cond)){printk(KERN_INFO "%s %d\n",__func__,__LINE__);return (rslt);}
++#else
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++#endif
++
++/**
++ * A macro to check a condition and if true return
++ * TMBSL_ERR_HDMI_BAD_PARAMETER.
++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on
++ * the compiler command line.
++ */
++#ifdef NO_RETIF_BADPARAM
++#define RETIF_BADPARAM(cond)
++#else
++#define RETIF_BADPARAM(cond) if ((cond)){return TMBSL_ERR_HDMI_BAD_PARAMETER;}
++#endif
++
++/**
++ * A macro to check the result of a register API and if not TM_OK to return it.
++ * To save code space, it can be compiled out by defining NO_RETIF_REG_FAIL on
++ * the compiler command line.
++ */
++#ifdef NO_RETIF_REG_FAIL
++#define RETIF_REG_FAIL(result)
++#else
++#define RETIF_REG_FAIL(result) if ((result) != TM_OK){return (result);}
++#endif
++
++/**
++ * Check the consistancy of BSL structure
++ */
++/* #define BSL_CONSISTANCY(_x_,_y_) do { \ */
++/* #if ((_x_) != (_y_) * (_x_)[0]) \ */
++/* #error "BSL HAS WRONG ARRAY SIZE" \ */
++/* #endif \ */
++/* } while (0) */
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++/**
++ * Driver events and states used for diagnosis
++ */
++typedef enum _tmbslTDA9989Event
++{
++ EV_DEINIT = 0,
++ EV_INIT = 1,
++ EV_STANDBY = 2,
++ EV_SLEEP = 3,
++ EV_ON = 4,
++ EV_UNPLUGGED = 5,
++ EV_PLUGGEDIN = 6,
++ EV_RESUME_UNPLUGGED = 7,
++ EV_RESUME_PLUGGEDIN = 8,
++ EV_GETBLOCKDATA = 9,
++ EV_SETINOUT = 10,
++ EV_OUTDISABLE = 11,
++ EV_HDCP_RUN = 12,
++ EV_HDCP_BKSV_NREPEAT = 13,
++ EV_HDCP_BKSV_NSECURE = 14,
++ EV_HDCP_BKSV_REPEAT = 15,
++ EV_HDCP_BSTATUS_GOOD = 16,
++ EV_HDCP_KSV_SECURE = 17,
++ EV_HDCP_T0 = 18,
++ EV_HDCP_STOP = 19,
++ EV_SINKON = 20,
++ EV_SINKOFF = 21,
++ EV_INVALID = 22
++} tmbslTDA9989Event_t;
++
++typedef enum _tmbslTDA9989State
++{
++ ST_UNINITIALIZED = 0,
++ ST_STANDBY = 1,
++ ST_SLEEP = 2,
++ ST_DISCONNECTED = 3,
++ ST_AWAIT_EDID = 4,
++ ST_SINK_CONNECTED = 5,
++ ST_VIDEO_NO_HDCP = 6,
++ ST_HDCP_WAIT_RX = 7,
++ ST_HDCP_WAIT_BSTATUS = 8,
++ ST_HDCP_WAIT_SHA_1 = 9,
++ ST_HDCP_AUTHENTICATED = 10,
++ ST_AWAIT_RX_SENSE = 11,
++ ST_INVALID = 12,
++ ST_NUM = 13
++} tmbslTDA9989State_t;
++
++/**
++ * An enum to index into the Device Instance Data shadowReg array
++ */
++enum _eShad
++{
++ E_SP00_INT_FLAGS_0 = 0,
++ E_SP00_INT_FLAGS_1 = 1,
++ E_SP00_INT_FLAGS_2 = 2,
++ E_SP00_VIP_CNTRL_0 = 3,
++ E_SP00_VIP_CNTRL_1 = 4,
++ E_SP00_VIP_CNTRL_2 = 5,
++ E_SP00_VIP_CNTRL_3 = 6,
++ E_SP00_VIP_CNTRL_4 = 7,
++ E_SP00_VIP_CNTRL_5 = 8,
++ E_SP00_MAT_CONTRL = 9,
++ E_SP00_TBG_CNTRL_0 = 10,
++ E_SP00_TBG_CNTRL_1 = 11,
++ E_SP00_HVF_CNTRL_0 = 12,
++ E_SP00_HVF_CNTRL_1 = 13,
++ E_SP00_TIMER_H = 14,
++ E_SP00_DEBUG_PROBE = 15,
++ E_SP00_AIP_CLKSEL = 16,
++ E_SP01_SC_VIDFORMAT = 17,
++ E_SP01_SC_CNTRL = 18,
++ E_SP01_TBG_CNTRL_0 = 19,
++#ifdef TMFL_HDCP_SUPPORT
++ E_SP12_CTRL = 20,
++ E_SP12_BCAPS = 21,
++ E_SNUM = 22, /* Number of shadow registers */
++ E_SNONE = 22 /* Index value indicating no shadow register */
++#else /* TMFL_HDCP_SUPPORT */
++ E_SNUM = 20, /* Number of shadow registers */
++ E_SNONE = 20 /* Index value indicating no shadow register */
++#endif /* TMFL_HDCP_SUPPORT */
++};
++
++/**
++ * Page list
++ * These are indexes to the allowed register page numbers
++ */
++enum _ePage
++{
++ E_PAGE_00 = 0,
++ E_PAGE_01 = 1,
++ E_PAGE_02 = 2,
++ E_PAGE_09 = 3,
++ E_PAGE_10 = 4,
++ E_PAGE_11 = 5,
++ E_PAGE_12 = 6,
++ E_PAGE_13 = 7,
++ E_PAGE_NUM = 8, /* Number of pages */
++ E_PAGE_INVALID = 8 /* Index value indicating invalid page */
++};
++
++/**
++ * Macros to initialize and access the following register list enum _eReg
++ */
++/* Pack shadow index s, page index p and register address a into UInt16 */
++#define SPA(s,p,a) (UInt16)(((s)<<11)|((p)<<8)|(a))
++/* Unpacks shadow index s from UInt16 */
++#define SPA2SHAD(spa) (UInt8)((spa)>>11)
++/* Unpacks page index p from UInt16 */
++#define SPA2PAGE(spa) (UInt8)(((spa)>>8)&0x0007)
++/* Unpacks register address a from UInt16 */
++#define SPA2ADDR(spa) (UInt8)((spa)&0x00FF)
++
++/**
++ * Register list
++ *
++ * Each register symbol has these fields: E_REG_page_register_access
++ *
++ * The symbols have a 16-bit value as follows, including an index to
++ * the Device Instance Data shadowReg[] array:
++ *
++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
++ * |15 |14 |13 |12 |11 |10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
++ * | Shadow Index |Page Index | Register Address |
++ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
++ *
++ */
++enum _eReg
++{
++ /*************************************************************************/
++ /** Rows formatted in "HDMI Driver - Register List.xls" and pasted here **/
++ /*************************************************************************/
++ E_REG_MIN_ADR = 0x00, /* First register on all pages */
++ E_REG_CURPAGE_ADR_W = 0xFF, /* Address register on all pages */
++ /*CEC Registers*/
++
++ E_REG_CEC_INTERRUPTSTATUS_R = 0xEE,
++ E_REG_CEC_RXSHPDINTENA_RW = 0xFC,
++ E_REG_CEC_RXSHPDINT_R = 0xFD,
++ E_REG_CEC_RXSHPDLEV_R = 0xFE,
++ E_REG_CEC_ENAMODS_RW = 0xFF,
++ E_REG_CEC_FRO_IM_CLK_CTRL_RW = 0xFB,
++
++ E_REG_P00_VERSION_R = SPA(E_SNONE , E_PAGE_00, 0x00),
++ E_REG_P00_MAIN_CNTRL0_RW = SPA(E_SNONE , E_PAGE_00, 0x01),
++ E_REG_P00_VERSION_MSB_RW = SPA(E_SNONE , E_PAGE_00, 0x02),
++ E_REG_P00_PACKAGE_TYPE_R = SPA(E_SNONE , E_PAGE_00, 0x03),
++ E_REG_P00_SR_REG_W = SPA(E_SNONE , E_PAGE_00, 0x0A),
++ E_REG_P00_DDC_DISABLE_RW = SPA(E_SNONE , E_PAGE_00, 0x0B),
++ E_REG_P00_CCLK_ON_RW = SPA(E_SNONE , E_PAGE_00, 0x0C),
++ E_REG_P00_I2C_MASTER_RW = SPA(E_SNONE , E_PAGE_00, 0x0D),
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ E_REG_FEAT_POWER_DOWN = SPA(E_SNONE , E_PAGE_00, 0x0E),
++#endif
++
++ E_REG_P00_INT_FLAGS_0_RW = SPA(E_SP00_INT_FLAGS_0 , E_PAGE_00, 0x0F),
++ E_REG_P00_INT_FLAGS_1_RW = SPA(E_SP00_INT_FLAGS_1 , E_PAGE_00, 0x10),
++ E_REG_P00_INT_FLAGS_2_RW = SPA(E_SP00_INT_FLAGS_2 , E_PAGE_00, 0x11),
++ /*E_REG_P00_INT_FLAGS_3_R = SPA(E_SNONE , E_PAGE_00, 0x12),*/
++ E_REG_P00_SW_INT_W = SPA(E_SNONE , E_PAGE_00, 0x15),
++ E_REG_P00_ENA_ACLK_RW = SPA(E_SNONE , E_PAGE_00, 0x16),
++ E_REG_P00_ENA_VP_0_RW = SPA(E_SNONE , E_PAGE_00, 0x18),
++ E_REG_P00_ENA_VP_1_RW = SPA(E_SNONE , E_PAGE_00, 0x19),
++ E_REG_P00_ENA_VP_2_RW = SPA(E_SNONE , E_PAGE_00, 0x1A),
++ E_REG_P00_ENA_AP_RW = SPA(E_SNONE , E_PAGE_00, 0x1E),
++ E_REG_P00_VIP_CNTRL_0_W = SPA(E_SP00_VIP_CNTRL_0 , E_PAGE_00, 0x20),
++ E_REG_P00_VIP_CNTRL_1_W = SPA(E_SP00_VIP_CNTRL_1 , E_PAGE_00, 0x21),
++ E_REG_P00_VIP_CNTRL_2_W = SPA(E_SP00_VIP_CNTRL_2 , E_PAGE_00, 0x22),
++ E_REG_P00_VIP_CNTRL_3_W = SPA(E_SP00_VIP_CNTRL_3 , E_PAGE_00, 0x23),
++ E_REG_P00_VIP_CNTRL_4_W = SPA(E_SP00_VIP_CNTRL_4 , E_PAGE_00, 0x24),
++ E_REG_P00_VIP_CNTRL_5_W = SPA(E_SP00_VIP_CNTRL_5 , E_PAGE_00, 0x25),
++ E_REG_P00_MUX_AP_RW = SPA(E_SNONE , E_PAGE_00, 0x26),
++ E_REG_P00_MUX_VP_VIP_OUT_RW = SPA(E_SNONE , E_PAGE_00, 0x27),
++ E_REG_P00_MAT_CONTRL_W = SPA(E_SP00_MAT_CONTRL , E_PAGE_00, 0x80),
++ E_REG_P00_MAT_OI1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x81),
++ E_REG_P00_MAT_OI1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x82),
++ E_REG_P00_MAT_OI2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x83),
++ E_REG_P00_MAT_OI2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x84),
++ E_REG_P00_MAT_OI3_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x85),
++ E_REG_P00_MAT_OI3_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x86),
++ E_REG_P00_MAT_P11_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x87),
++ E_REG_P00_MAT_P11_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x88),
++ E_REG_P00_MAT_P12_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x89),
++ E_REG_P00_MAT_P12_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8A),
++ E_REG_P00_MAT_P13_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8B),
++ E_REG_P00_MAT_P13_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8C),
++ E_REG_P00_MAT_P21_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8D),
++ E_REG_P00_MAT_P21_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x8E),
++ E_REG_P00_MAT_P22_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x8F),
++ E_REG_P00_MAT_P22_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x90),
++ E_REG_P00_MAT_P23_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x91),
++ E_REG_P00_MAT_P23_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x92),
++ E_REG_P00_MAT_P31_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x93),
++ E_REG_P00_MAT_P31_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x94),
++ E_REG_P00_MAT_P32_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x95),
++ E_REG_P00_MAT_P32_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x96),
++ E_REG_P00_MAT_P33_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x97),
++ E_REG_P00_MAT_P33_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x98),
++ E_REG_P00_MAT_OO1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x99),
++ E_REG_P00_MAT_OO1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9A),
++ E_REG_P00_MAT_OO2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x9B),
++ E_REG_P00_MAT_OO2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9C),
++ E_REG_P00_MAT_OO3_MSB_W = SPA(E_SNONE , E_PAGE_00, 0x9D),
++ E_REG_P00_MAT_OO3_LSB_W = SPA(E_SNONE , E_PAGE_00, 0x9E),
++ E_REG_P00_VIDFORMAT_W = SPA(E_SNONE , E_PAGE_00, 0xA0),
++ E_REG_P00_REFPIX_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA1),
++ E_REG_P00_REFPIX_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA2),
++ E_REG_P00_REFLINE_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA3),
++ E_REG_P00_REFLINE_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA4),
++ E_REG_P00_NPIX_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA5),
++ E_REG_P00_NPIX_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA6),
++ E_REG_P00_NLINE_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA7),
++ E_REG_P00_NLINE_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xA8),
++ E_REG_P00_VS_LINE_STRT_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xA9),
++ E_REG_P00_VS_LINE_STRT_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAA),
++ E_REG_P00_VS_PIX_STRT_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAB),
++ E_REG_P00_VS_PIX_STRT_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAC),
++ E_REG_P00_VS_LINE_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAD),
++ E_REG_P00_VS_LINE_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xAE),
++ E_REG_P00_VS_PIX_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xAF),
++ E_REG_P00_VS_PIX_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB0),
++ E_REG_P00_VS_LINE_STRT_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB1),
++ E_REG_P00_VS_LINE_STRT_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB2),
++ E_REG_P00_VS_PIX_STRT_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB3),
++ E_REG_P00_VS_PIX_STRT_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB4),
++ E_REG_P00_VS_LINE_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB5),
++ E_REG_P00_VS_LINE_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB6),
++ E_REG_P00_VS_PIX_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB7),
++ E_REG_P00_VS_PIX_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xB8),
++ E_REG_P00_HS_PIX_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xB9),
++ E_REG_P00_HS_PIX_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBA),
++ E_REG_P00_HS_PIX_STOP_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBB),
++ E_REG_P00_HS_PIX_STOP_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBC),
++ E_REG_P00_VWIN_START_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBD),
++ E_REG_P00_VWIN_START_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xBE),
++ E_REG_P00_VWIN_END_1_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xBF),
++ E_REG_P00_VWIN_END_1_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC0),
++ E_REG_P00_VWIN_START_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC1),
++ E_REG_P00_VWIN_START_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC2),
++ E_REG_P00_VWIN_END_2_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC3),
++ E_REG_P00_VWIN_END_2_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC4),
++ E_REG_P00_DE_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC5),
++ E_REG_P00_DE_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC6),
++ E_REG_P00_DE_STOP_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xC7),
++ E_REG_P00_DE_STOP_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xC8),
++ E_REG_P00_COLBAR_WIDTH_W = SPA(E_SNONE , E_PAGE_00, 0xC9),
++ E_REG_P00_TBG_CNTRL_0_W = SPA(E_SP00_TBG_CNTRL_0 , E_PAGE_00, 0xCA),
++ E_REG_P00_TBG_CNTRL_1_W = SPA(E_SP00_TBG_CNTRL_1 , E_PAGE_00, 0xCB),
++ E_REG_P00_VBL_OFFSET_START_W = SPA(E_SNONE , E_PAGE_00, 0xCC),
++ E_REG_P00_VBL_OFFSET_END_W = SPA(E_SNONE , E_PAGE_00, 0xCD),
++ E_REG_P00_HBL_OFFSET_START_W = SPA(E_SNONE , E_PAGE_00, 0xCE),
++ E_REG_P00_HBL_OFFSET_END_W = SPA(E_SNONE , E_PAGE_00, 0xCF),
++ E_REG_P00_DWIN_RE_DE_W = SPA(E_SNONE , E_PAGE_00, 0xD0),
++ E_REG_P00_DWIN_FE_DE_W = SPA(E_SNONE , E_PAGE_00, 0xD1),
++#ifdef TMFL_RGB_DDR_12BITS
++ E_REG_P00_VSPACE_START_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xD2),
++ E_REG_P00_VSPACE_START_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xD3),
++ E_REG_P00_VSPACE_END_MSB_W = SPA(E_SNONE , E_PAGE_00, 0xD4),
++ E_REG_P00_VSPACE_END_LSB_W = SPA(E_SNONE , E_PAGE_00, 0xD5),
++ E_REG_P00_ENABLE_SPACE_W = SPA(E_SNONE , E_PAGE_00, 0xD6),
++ E_REG_P00_VSPACE_Y_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD7),
++ E_REG_P00_VSPACE_U_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD8),
++ E_REG_P00_VSPACE_V_DATA_W = SPA(E_SNONE , E_PAGE_00, 0xD9),
++#endif
++
++ E_REG_P00_TIMER_RI_PJ_RW = SPA(E_SNONE , E_PAGE_00, 0xE1),
++ E_REG_P00_BCAPS_POLL_RW = SPA(E_SNONE , E_PAGE_00, 0xE2),
++ E_REG_P00_100us_RW = SPA(E_SNONE , E_PAGE_00, 0xE3),
++
++ E_REG_P00_HVF_CNTRL_0_W = SPA(E_SP00_HVF_CNTRL_0 , E_PAGE_00, 0xE4),
++ E_REG_P00_HVF_CNTRL_1_W = SPA(E_SP00_HVF_CNTRL_1 , E_PAGE_00, 0xE5),
++
++ E_REG_P00_TIMER_H_W = SPA(E_SP00_TIMER_H , E_PAGE_00, 0xE8),
++ E_REG_P00_TIMER_M_W = SPA(E_SNONE , E_PAGE_00, 0xE9),
++ E_REG_P00_TIMER_L_W = SPA(E_SNONE , E_PAGE_00, 0xEA),
++ E_REG_P00_TIMER_2SEC_W = SPA(E_SNONE , E_PAGE_00, 0xEB),
++ E_REG_P00_TIMER_5SEC_W = SPA(E_SNONE , E_PAGE_00, 0xEC),
++ E_REG_P00_NDIV_IM_W = SPA(E_SNONE , E_PAGE_00, 0xEE),
++ E_REG_P00_NDIV_PF_W = SPA(E_SNONE , E_PAGE_00, 0xEF),
++ E_REG_P00_RPT_CNTRL_W = SPA(E_SNONE , E_PAGE_00, 0xF0),
++ E_REG_P00_LEAD_OFF_W = SPA(E_SNONE , E_PAGE_00, 0xF1),
++ E_REG_P00_TRAIL_OFF_W = SPA(E_SNONE , E_PAGE_00, 0xF2),
++ E_REG_P00_MISR_EXP_0_RW = SPA(E_SNONE , E_PAGE_00, 0xF3),
++ E_REG_P00_MISR_EXP_1_RW = SPA(E_SNONE , E_PAGE_00, 0xF4),
++ E_REG_P00_MISR_EXP_2_RW = SPA(E_SNONE , E_PAGE_00, 0xF5),
++ E_REG_P00_MISR_0_R = SPA(E_SNONE , E_PAGE_00, 0xF6),
++ E_REG_P00_MISR_1_R = SPA(E_SNONE , E_PAGE_00, 0xF7),
++ E_REG_P00_DEBUG_PROBE_W = SPA(E_SP00_DEBUG_PROBE , E_PAGE_00, 0xF8),
++ E_REG_P00_GHOST_XADDR_W = SPA(E_SNONE , E_PAGE_00, 0xF9),
++ E_REG_P00_MISR_2_R = SPA(E_SNONE , E_PAGE_00, 0xFA),
++ E_REG_P00_I2S_FORMAT_RW = SPA(E_SNONE , E_PAGE_00, 0xFC),
++ E_REG_P00_AIP_CLKSEL_W = SPA(E_SP00_AIP_CLKSEL , E_PAGE_00, 0xFD),
++ E_REG_P00_GHOST_ADDR_W = SPA(E_SNONE , E_PAGE_00, 0xFE),
++ E_REG_P01_SC_VIDFORMAT_W = SPA(E_SP01_SC_VIDFORMAT, E_PAGE_01, 0x00),
++
++ E_REG_P01_SC_CNTRL_W = SPA(E_SP01_SC_CNTRL , E_PAGE_01, 0x01),
++ E_REG_P01_SC_DELTA_PHASE_V_W = SPA(E_SNONE , E_PAGE_01, 0x02),
++ E_REG_P01_SC_DELTA_PHASE_H_W = SPA(E_SNONE , E_PAGE_01, 0x03),
++ E_REG_P01_SC_START_PHASE_H_W = SPA(E_SNONE , E_PAGE_01, 0x04),
++ E_REG_P01_SC_NPIX_IN_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x05),
++ E_REG_P01_SC_NPIX_IN_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x06),
++ E_REG_P01_SC_NPIX_OUT_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x07),
++ E_REG_P01_SC_NPIX_OUT_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x08),
++ E_REG_P01_SC_NLINE_IN_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x09),
++ E_REG_P01_SC_NLINE_IN_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x0A),
++ E_REG_P01_SC_NLINE_OUT_LSB_W = SPA(E_SNONE , E_PAGE_01, 0x0B),
++ E_REG_P01_SC_NLINE_OUT_MSB_W = SPA(E_SNONE , E_PAGE_01, 0x0C),
++ E_REG_P01_SC_NLINE_SKIP_W = SPA(E_SNONE , E_PAGE_01, 0x0D),
++ E_REG_P01_SC_SAMPLE_BUFFILL_R = SPA(E_SNONE , E_PAGE_01, 0x0E),
++ E_REG_P01_SC_MAX_BUFFILL_P_0_R = SPA(E_SNONE , E_PAGE_01, 0x0F),
++ E_REG_P01_SC_MAX_BUFFILL_P_1_R = SPA(E_SNONE , E_PAGE_01, 0x10),
++ E_REG_P01_SC_MAX_BUFFILL_D_0_R = SPA(E_SNONE , E_PAGE_01, 0x11),
++ E_REG_P01_SC_MAX_BUFFILL_D_1_R = SPA(E_SNONE , E_PAGE_01, 0x12),
++ E_REG_P01_SC_SAMPLE_FIFOFILL_R = SPA(E_SNONE , E_PAGE_01, 0x13),
++ E_REG_P01_SC_MAX_FIFOFILL_PI_R = SPA(E_SNONE , E_PAGE_01, 0x14),
++ E_REG_P01_SC_MIN_FIFOFILL_PO1_R = SPA(E_SNONE , E_PAGE_01, 0x15),
++ E_REG_P01_SC_MIN_FIFOFILL_PO2_R = SPA(E_SNONE , E_PAGE_01, 0x16),
++ E_REG_P01_SC_MIN_FIFOFILL_PO3_R = SPA(E_SNONE , E_PAGE_01, 0x17),
++ E_REG_P01_SC_MIN_FIFOFILL_PO4_R = SPA(E_SNONE , E_PAGE_01, 0x18),
++ E_REG_P01_SC_MAX_FIFOFILL_DI_R = SPA(E_SNONE , E_PAGE_01, 0x19),
++ E_REG_P01_SC_MAX_FIFOFILL_DO_R = SPA(E_SNONE , E_PAGE_01, 0x1A),
++ E_REG_P01_SC_VS_LUT_0_W = SPA(E_SNONE , E_PAGE_01, 0x1B),
++ E_REG_P01_SC_VS_LUT_1_W = SPA(E_SNONE , E_PAGE_01, 0x1C),
++ E_REG_P01_SC_VS_LUT_2_W = SPA(E_SNONE , E_PAGE_01, 0x1D),
++ E_REG_P01_SC_VS_LUT_3_W = SPA(E_SNONE , E_PAGE_01, 0x1E),
++ E_REG_P01_SC_VS_LUT_4_W = SPA(E_SNONE , E_PAGE_01, 0x1F),
++ E_REG_P01_SC_VS_LUT_5_W = SPA(E_SNONE , E_PAGE_01, 0x20),
++ E_REG_P01_SC_VS_LUT_6_W = SPA(E_SNONE , E_PAGE_01, 0x21),
++ E_REG_P01_SC_VS_LUT_7_W = SPA(E_SNONE , E_PAGE_01, 0x22),
++ E_REG_P01_SC_VS_LUT_8_W = SPA(E_SNONE , E_PAGE_01, 0x23),
++ E_REG_P01_SC_VS_LUT_9_W = SPA(E_SNONE , E_PAGE_01, 0x24),
++ E_REG_P01_SC_VS_LUT_10_W = SPA(E_SNONE , E_PAGE_01, 0x25),
++ E_REG_P01_SC_VS_LUT_11_W = SPA(E_SNONE , E_PAGE_01, 0x26),
++ E_REG_P01_SC_VS_LUT_12_W = SPA(E_SNONE , E_PAGE_01, 0x27),
++ E_REG_P01_SC_VS_LUT_13_W = SPA(E_SNONE , E_PAGE_01, 0x28),
++ E_REG_P01_SC_VS_LUT_14_W = SPA(E_SNONE , E_PAGE_01, 0x29),
++ E_REG_P01_SC_VS_LUT_15_W = SPA(E_SNONE , E_PAGE_01, 0x2A),
++ E_REG_P01_SC_VS_LUT_16_W = SPA(E_SNONE , E_PAGE_01, 0x2B),
++ E_REG_P01_SC_VS_LUT_17_W = SPA(E_SNONE , E_PAGE_01, 0x2C),
++ E_REG_P01_SC_VS_LUT_18_W = SPA(E_SNONE , E_PAGE_01, 0x2D),
++ E_REG_P01_SC_VS_LUT_19_W = SPA(E_SNONE , E_PAGE_01, 0x2E),
++ E_REG_P01_SC_VS_LUT_20_W = SPA(E_SNONE , E_PAGE_01, 0x2F),
++ E_REG_P01_SC_VS_LUT_21_W = SPA(E_SNONE , E_PAGE_01, 0x30),
++ E_REG_P01_SC_VS_LUT_22_W = SPA(E_SNONE , E_PAGE_01, 0x31),
++ E_REG_P01_SC_VS_LUT_23_W = SPA(E_SNONE , E_PAGE_01, 0x32),
++ E_REG_P01_SC_VS_LUT_24_W = SPA(E_SNONE , E_PAGE_01, 0x33),
++ E_REG_P01_SC_VS_LUT_25_W = SPA(E_SNONE , E_PAGE_01, 0x34),
++ E_REG_P01_SC_VS_LUT_26_W = SPA(E_SNONE , E_PAGE_01, 0x35),
++ E_REG_P01_SC_VS_LUT_27_W = SPA(E_SNONE , E_PAGE_01, 0x36),
++ E_REG_P01_SC_VS_LUT_28_W = SPA(E_SNONE , E_PAGE_01, 0x37),
++ E_REG_P01_SC_VS_LUT_29_W = SPA(E_SNONE , E_PAGE_01, 0x38),
++ E_REG_P01_SC_VS_LUT_30_W = SPA(E_SNONE , E_PAGE_01, 0x39),
++ E_REG_P01_SC_VS_LUT_31_W = SPA(E_SNONE , E_PAGE_01, 0x3A),
++ E_REG_P01_SC_VS_LUT_32_W = SPA(E_SNONE , E_PAGE_01, 0x3B),
++ E_REG_P01_SC_VS_LUT_33_W = SPA(E_SNONE , E_PAGE_01, 0x3C),
++ E_REG_P01_SC_VS_LUT_34_W = SPA(E_SNONE , E_PAGE_01, 0x3D),
++ E_REG_P01_SC_VS_LUT_35_W = SPA(E_SNONE , E_PAGE_01, 0x3E),
++ E_REG_P01_SC_VS_LUT_36_W = SPA(E_SNONE , E_PAGE_01, 0x3F),
++ E_REG_P01_SC_VS_LUT_37_W = SPA(E_SNONE , E_PAGE_01, 0x40),
++ E_REG_P01_SC_VS_LUT_38_W = SPA(E_SNONE , E_PAGE_01, 0x41),
++ E_REG_P01_SC_VS_LUT_39_W = SPA(E_SNONE , E_PAGE_01, 0x42),
++ E_REG_P01_SC_VS_LUT_40_W = SPA(E_SNONE , E_PAGE_01, 0x43),
++ E_REG_P01_SC_VS_LUT_41_W = SPA(E_SNONE , E_PAGE_01, 0x44),
++ E_REG_P01_SC_VS_LUT_42_W = SPA(E_SNONE , E_PAGE_01, 0x45),
++ E_REG_P01_SC_VS_LUT_43_W = SPA(E_SNONE , E_PAGE_01, 0x46),
++ E_REG_P01_SC_VS_LUT_44_W = SPA(E_SNONE , E_PAGE_01, 0x47),
++ E_REG_P01_SC_LAT_SCO_RW = SPA(E_SNONE , E_PAGE_01, 0x48),
++ E_REG_P01_VIDFORMAT_W = SPA(E_SNONE , E_PAGE_01, 0xA0),
++ E_REG_P01_REFPIX_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA1),
++ E_REG_P01_REFPIX_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA2),
++ E_REG_P01_REFLINE_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA3),
++ E_REG_P01_REFLINE_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA4),
++ E_REG_P01_NPIX_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA5),
++ E_REG_P01_NPIX_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA6),
++ E_REG_P01_NLINE_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xA7),
++ E_REG_P01_NLINE_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xA8),
++ E_REG_P01_VWIN_START_1_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xBD),
++ E_REG_P01_VWIN_START_1_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xBE),
++ E_REG_P01_VWIN_END_1_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xBF),
++ E_REG_P01_VWIN_END_1_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC0),
++ E_REG_P01_VWIN_START_2_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC1),
++ E_REG_P01_VWIN_START_2_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC2),
++ E_REG_P01_VWIN_END_2_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC3),
++ E_REG_P01_VWIN_END_2_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC4),
++ E_REG_P01_DE_START_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC5),
++ E_REG_P01_DE_START_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC6),
++ E_REG_P01_DE_STOP_MSB_W = SPA(E_SNONE , E_PAGE_01, 0xC7),
++ E_REG_P01_DE_STOP_LSB_W = SPA(E_SNONE , E_PAGE_01, 0xC8),
++ E_REG_P01_TBG_CNTRL_0_W = SPA(E_SP01_TBG_CNTRL_0 , E_PAGE_01, 0xCA),
++ E_REG_P02_PLL_SERIAL_1_RW = SPA(E_SNONE , E_PAGE_02, 0x00),
++ E_REG_P02_PLL_SERIAL_2_RW = SPA(E_SNONE , E_PAGE_02, 0x01),
++ E_REG_P02_PLL_SERIAL_3_RW = SPA(E_SNONE , E_PAGE_02, 0x02),
++ E_REG_P02_SERIALIZER_RW = SPA(E_SNONE , E_PAGE_02, 0x03),
++ E_REG_P02_BUFFER_OUT_RW = SPA(E_SNONE , E_PAGE_02, 0x04),
++ E_REG_P02_PLL_SCG1_RW = SPA(E_SNONE , E_PAGE_02, 0x05),
++ E_REG_P02_PLL_SCG2_RW = SPA(E_SNONE , E_PAGE_02, 0x06),
++ E_REG_P02_PLL_SCGN1_RW = SPA(E_SNONE , E_PAGE_02, 0x07),
++ E_REG_P02_PLL_SCGN2_RW = SPA(E_SNONE , E_PAGE_02, 0x08),
++ E_REG_P02_PLL_SCGR1_RW = SPA(E_SNONE , E_PAGE_02, 0x09),
++ E_REG_P02_PLL_SCGR2_RW = SPA(E_SNONE , E_PAGE_02, 0x0A),
++ E_REG_P02_VAI_PLL_R = SPA(E_SNONE , E_PAGE_02, 0x0D),
++ E_REG_P02_AUDIO_DIV_RW = SPA(E_SNONE , E_PAGE_02, 0x0E),
++ E_REG_P02_TEST1_RW = SPA(E_SNONE , E_PAGE_02, 0x0F),
++ /*E_REG_P02_TEST2_RW = SPA(E_SNONE , E_PAGE_02, 0x10),*/
++ E_REG_P02_SEL_CLK_RW = SPA(E_SNONE , E_PAGE_02, 0x11),
++ E_REG_P02_ANA_GENERAL_RW = SPA(E_SNONE , E_PAGE_02, 0x12),
++ E_REG_P02_BUFFER_OUT2_RW = SPA(E_SNONE , E_PAGE_02, 0x13),
++ E_REG_P02_SRL_TSTPAT0_RW = SPA(E_SNONE , E_PAGE_02, 0x14),
++ E_REG_P02_SRL_TSTPAT1_RW = SPA(E_SNONE , E_PAGE_02, 0x15),
++ E_REG_P02_SRL_TSTPAT2_RW = SPA(E_SNONE , E_PAGE_02, 0x16),
++ E_REG_P02_SRL_TSTPAT3_RW = SPA(E_SNONE , E_PAGE_02, 0x17),
++
++ E_REG_P09_EDID_DATA_0_R = SPA(E_SNONE , E_PAGE_09, 0x00),
++ E_REG_P09_EDID_DATA_1_R = SPA(E_SNONE , E_PAGE_09, 0x01),
++ E_REG_P09_EDID_DATA_2_R = SPA(E_SNONE , E_PAGE_09, 0x02),
++ E_REG_P09_EDID_DATA_3_R = SPA(E_SNONE , E_PAGE_09, 0x03),
++ E_REG_P09_EDID_DATA_4_R = SPA(E_SNONE , E_PAGE_09, 0x04),
++ E_REG_P09_EDID_DATA_5_R = SPA(E_SNONE , E_PAGE_09, 0x05),
++ E_REG_P09_EDID_DATA_6_R = SPA(E_SNONE , E_PAGE_09, 0x06),
++ E_REG_P09_EDID_DATA_7_R = SPA(E_SNONE , E_PAGE_09, 0x07),
++ E_REG_P09_EDID_DATA_8_R = SPA(E_SNONE , E_PAGE_09, 0x08),
++ E_REG_P09_EDID_DATA_9_R = SPA(E_SNONE , E_PAGE_09, 0x09),
++ E_REG_P09_EDID_DATA_10_R = SPA(E_SNONE , E_PAGE_09, 0x0A),
++ E_REG_P09_EDID_DATA_11_R = SPA(E_SNONE , E_PAGE_09, 0x0B),
++ E_REG_P09_EDID_DATA_12_R = SPA(E_SNONE , E_PAGE_09, 0x0C),
++ E_REG_P09_EDID_DATA_13_R = SPA(E_SNONE , E_PAGE_09, 0x0D),
++ E_REG_P09_EDID_DATA_14_R = SPA(E_SNONE , E_PAGE_09, 0x0E),
++ E_REG_P09_EDID_DATA_15_R = SPA(E_SNONE , E_PAGE_09, 0x0F),
++ E_REG_P09_EDID_DATA_16_R = SPA(E_SNONE , E_PAGE_09, 0x10),
++ E_REG_P09_EDID_DATA_17_R = SPA(E_SNONE , E_PAGE_09, 0x11),
++ E_REG_P09_EDID_DATA_18_R = SPA(E_SNONE , E_PAGE_09, 0x12),
++ E_REG_P09_EDID_DATA_19_R = SPA(E_SNONE , E_PAGE_09, 0x13),
++ E_REG_P09_EDID_DATA_20_R = SPA(E_SNONE , E_PAGE_09, 0x14),
++ E_REG_P09_EDID_DATA_21_R = SPA(E_SNONE , E_PAGE_09, 0x15),
++ E_REG_P09_EDID_DATA_22_R = SPA(E_SNONE , E_PAGE_09, 0x16),
++ E_REG_P09_EDID_DATA_23_R = SPA(E_SNONE , E_PAGE_09, 0x17),
++ E_REG_P09_EDID_DATA_24_R = SPA(E_SNONE , E_PAGE_09, 0x18),
++ E_REG_P09_EDID_DATA_25_R = SPA(E_SNONE , E_PAGE_09, 0x19),
++ E_REG_P09_EDID_DATA_26_R = SPA(E_SNONE , E_PAGE_09, 0x1A),
++ E_REG_P09_EDID_DATA_27_R = SPA(E_SNONE , E_PAGE_09, 0x1B),
++ E_REG_P09_EDID_DATA_28_R = SPA(E_SNONE , E_PAGE_09, 0x1C),
++ E_REG_P09_EDID_DATA_29_R = SPA(E_SNONE , E_PAGE_09, 0x1D),
++ E_REG_P09_EDID_DATA_30_R = SPA(E_SNONE , E_PAGE_09, 0x1E),
++ E_REG_P09_EDID_DATA_31_R = SPA(E_SNONE , E_PAGE_09, 0x1F),
++ E_REG_P09_EDID_DATA_32_R = SPA(E_SNONE , E_PAGE_09, 0x20),
++ E_REG_P09_EDID_DATA_33_R = SPA(E_SNONE , E_PAGE_09, 0x21),
++ E_REG_P09_EDID_DATA_34_R = SPA(E_SNONE , E_PAGE_09, 0x22),
++ E_REG_P09_EDID_DATA_35_R = SPA(E_SNONE , E_PAGE_09, 0x23),
++ E_REG_P09_EDID_DATA_36_R = SPA(E_SNONE , E_PAGE_09, 0x24),
++ E_REG_P09_EDID_DATA_37_R = SPA(E_SNONE , E_PAGE_09, 0x25),
++ E_REG_P09_EDID_DATA_38_R = SPA(E_SNONE , E_PAGE_09, 0x26),
++ E_REG_P09_EDID_DATA_39_R = SPA(E_SNONE , E_PAGE_09, 0x27),
++ E_REG_P09_EDID_DATA_40_R = SPA(E_SNONE , E_PAGE_09, 0x28),
++ E_REG_P09_EDID_DATA_41_R = SPA(E_SNONE , E_PAGE_09, 0x29),
++ E_REG_P09_EDID_DATA_42_R = SPA(E_SNONE , E_PAGE_09, 0x2A),
++ E_REG_P09_EDID_DATA_43_R = SPA(E_SNONE , E_PAGE_09, 0x2B),
++ E_REG_P09_EDID_DATA_44_R = SPA(E_SNONE , E_PAGE_09, 0x2C),
++ E_REG_P09_EDID_DATA_45_R = SPA(E_SNONE , E_PAGE_09, 0x2D),
++ E_REG_P09_EDID_DATA_46_R = SPA(E_SNONE , E_PAGE_09, 0x2E),
++ E_REG_P09_EDID_DATA_47_R = SPA(E_SNONE , E_PAGE_09, 0x2F),
++ E_REG_P09_EDID_DATA_48_R = SPA(E_SNONE , E_PAGE_09, 0x30),
++ E_REG_P09_EDID_DATA_49_R = SPA(E_SNONE , E_PAGE_09, 0x31),
++ E_REG_P09_EDID_DATA_50_R = SPA(E_SNONE , E_PAGE_09, 0x32),
++ E_REG_P09_EDID_DATA_51_R = SPA(E_SNONE , E_PAGE_09, 0x33),
++ E_REG_P09_EDID_DATA_52_R = SPA(E_SNONE , E_PAGE_09, 0x34),
++ E_REG_P09_EDID_DATA_53_R = SPA(E_SNONE , E_PAGE_09, 0x35),
++ E_REG_P09_EDID_DATA_54_R = SPA(E_SNONE , E_PAGE_09, 0x36),
++ E_REG_P09_EDID_DATA_55_R = SPA(E_SNONE , E_PAGE_09, 0x37),
++ E_REG_P09_EDID_DATA_56_R = SPA(E_SNONE , E_PAGE_09, 0x38),
++ E_REG_P09_EDID_DATA_57_R = SPA(E_SNONE , E_PAGE_09, 0x39),
++ E_REG_P09_EDID_DATA_58_R = SPA(E_SNONE , E_PAGE_09, 0x3A),
++ E_REG_P09_EDID_DATA_59_R = SPA(E_SNONE , E_PAGE_09, 0x3B),
++ E_REG_P09_EDID_DATA_60_R = SPA(E_SNONE , E_PAGE_09, 0x3C),
++ E_REG_P09_EDID_DATA_61_R = SPA(E_SNONE , E_PAGE_09, 0x3D),
++ E_REG_P09_EDID_DATA_62_R = SPA(E_SNONE , E_PAGE_09, 0x3E),
++ E_REG_P09_EDID_DATA_63_R = SPA(E_SNONE , E_PAGE_09, 0x3F),
++ E_REG_P09_EDID_DATA_64_R = SPA(E_SNONE , E_PAGE_09, 0x40),
++ E_REG_P09_EDID_DATA_65_R = SPA(E_SNONE , E_PAGE_09, 0x41),
++ E_REG_P09_EDID_DATA_66_R = SPA(E_SNONE , E_PAGE_09, 0x42),
++ E_REG_P09_EDID_DATA_67_R = SPA(E_SNONE , E_PAGE_09, 0x43),
++ E_REG_P09_EDID_DATA_68_R = SPA(E_SNONE , E_PAGE_09, 0x44),
++ E_REG_P09_EDID_DATA_69_R = SPA(E_SNONE , E_PAGE_09, 0x45),
++ E_REG_P09_EDID_DATA_70_R = SPA(E_SNONE , E_PAGE_09, 0x46),
++ E_REG_P09_EDID_DATA_71_R = SPA(E_SNONE , E_PAGE_09, 0x47),
++ E_REG_P09_EDID_DATA_72_R = SPA(E_SNONE , E_PAGE_09, 0x48),
++ E_REG_P09_EDID_DATA_73_R = SPA(E_SNONE , E_PAGE_09, 0x49),
++ E_REG_P09_EDID_DATA_74_R = SPA(E_SNONE , E_PAGE_09, 0x4A),
++ E_REG_P09_EDID_DATA_75_R = SPA(E_SNONE , E_PAGE_09, 0x4B),
++ E_REG_P09_EDID_DATA_76_R = SPA(E_SNONE , E_PAGE_09, 0x4C),
++ E_REG_P09_EDID_DATA_77_R = SPA(E_SNONE , E_PAGE_09, 0x4D),
++ E_REG_P09_EDID_DATA_78_R = SPA(E_SNONE , E_PAGE_09, 0x4E),
++ E_REG_P09_EDID_DATA_79_R = SPA(E_SNONE , E_PAGE_09, 0x4F),
++ E_REG_P09_EDID_DATA_80_R = SPA(E_SNONE , E_PAGE_09, 0x50),
++ E_REG_P09_EDID_DATA_81_R = SPA(E_SNONE , E_PAGE_09, 0x51),
++ E_REG_P09_EDID_DATA_82_R = SPA(E_SNONE , E_PAGE_09, 0x52),
++ E_REG_P09_EDID_DATA_83_R = SPA(E_SNONE , E_PAGE_09, 0x53),
++ E_REG_P09_EDID_DATA_84_R = SPA(E_SNONE , E_PAGE_09, 0x54),
++ E_REG_P09_EDID_DATA_85_R = SPA(E_SNONE , E_PAGE_09, 0x55),
++ E_REG_P09_EDID_DATA_86_R = SPA(E_SNONE , E_PAGE_09, 0x56),
++ E_REG_P09_EDID_DATA_87_R = SPA(E_SNONE , E_PAGE_09, 0x57),
++ E_REG_P09_EDID_DATA_88_R = SPA(E_SNONE , E_PAGE_09, 0x58),
++ E_REG_P09_EDID_DATA_89_R = SPA(E_SNONE , E_PAGE_09, 0x59),
++ E_REG_P09_EDID_DATA_90_R = SPA(E_SNONE , E_PAGE_09, 0x5A),
++ E_REG_P09_EDID_DATA_91_R = SPA(E_SNONE , E_PAGE_09, 0x5B),
++ E_REG_P09_EDID_DATA_92_R = SPA(E_SNONE , E_PAGE_09, 0x5C),
++ E_REG_P09_EDID_DATA_93_R = SPA(E_SNONE , E_PAGE_09, 0x5D),
++ E_REG_P09_EDID_DATA_94_R = SPA(E_SNONE , E_PAGE_09, 0x5E),
++ E_REG_P09_EDID_DATA_95_R = SPA(E_SNONE , E_PAGE_09, 0x5F),
++ E_REG_P09_EDID_DATA_96_R = SPA(E_SNONE , E_PAGE_09, 0x60),
++ E_REG_P09_EDID_DATA_97_R = SPA(E_SNONE , E_PAGE_09, 0x61),
++ E_REG_P09_EDID_DATA_98_R = SPA(E_SNONE , E_PAGE_09, 0x62),
++ E_REG_P09_EDID_DATA_99_R = SPA(E_SNONE , E_PAGE_09, 0x63),
++ E_REG_P09_EDID_DATA_100_R = SPA(E_SNONE , E_PAGE_09, 0x64),
++ E_REG_P09_EDID_DATA_101_R = SPA(E_SNONE , E_PAGE_09, 0x65),
++ E_REG_P09_EDID_DATA_102_R = SPA(E_SNONE , E_PAGE_09, 0x66),
++ E_REG_P09_EDID_DATA_103_R = SPA(E_SNONE , E_PAGE_09, 0x67),
++ E_REG_P09_EDID_DATA_104_R = SPA(E_SNONE , E_PAGE_09, 0x68),
++ E_REG_P09_EDID_DATA_105_R = SPA(E_SNONE , E_PAGE_09, 0x69),
++ E_REG_P09_EDID_DATA_106_R = SPA(E_SNONE , E_PAGE_09, 0x6A),
++ E_REG_P09_EDID_DATA_107_R = SPA(E_SNONE , E_PAGE_09, 0x6B),
++ E_REG_P09_EDID_DATA_108_R = SPA(E_SNONE , E_PAGE_09, 0x6C),
++ E_REG_P09_EDID_DATA_109_R = SPA(E_SNONE , E_PAGE_09, 0x6D),
++ E_REG_P09_EDID_DATA_110_R = SPA(E_SNONE , E_PAGE_09, 0x6E),
++ E_REG_P09_EDID_DATA_111_R = SPA(E_SNONE , E_PAGE_09, 0x6F),
++ E_REG_P09_EDID_DATA_112_R = SPA(E_SNONE , E_PAGE_09, 0x70),
++ E_REG_P09_EDID_DATA_113_R = SPA(E_SNONE , E_PAGE_09, 0x71),
++ E_REG_P09_EDID_DATA_114_R = SPA(E_SNONE , E_PAGE_09, 0x72),
++ E_REG_P09_EDID_DATA_115_R = SPA(E_SNONE , E_PAGE_09, 0x73),
++ E_REG_P09_EDID_DATA_116_R = SPA(E_SNONE , E_PAGE_09, 0x74),
++ E_REG_P09_EDID_DATA_117_R = SPA(E_SNONE , E_PAGE_09, 0x75),
++ E_REG_P09_EDID_DATA_118_R = SPA(E_SNONE , E_PAGE_09, 0x76),
++ E_REG_P09_EDID_DATA_119_R = SPA(E_SNONE , E_PAGE_09, 0x77),
++ E_REG_P09_EDID_DATA_120_R = SPA(E_SNONE , E_PAGE_09, 0x78),
++ E_REG_P09_EDID_DATA_121_R = SPA(E_SNONE , E_PAGE_09, 0x79),
++ E_REG_P09_EDID_DATA_122_R = SPA(E_SNONE , E_PAGE_09, 0x7A),
++ E_REG_P09_EDID_DATA_123_R = SPA(E_SNONE , E_PAGE_09, 0x7B),
++ E_REG_P09_EDID_DATA_124_R = SPA(E_SNONE , E_PAGE_09, 0x7C),
++ E_REG_P09_EDID_DATA_125_R = SPA(E_SNONE , E_PAGE_09, 0x7D),
++ E_REG_P09_EDID_DATA_126_R = SPA(E_SNONE , E_PAGE_09, 0x7E),
++ E_REG_P09_EDID_DATA_127_R = SPA(E_SNONE , E_PAGE_09, 0x7F),
++ E_REG_P09_EDID_CTRL_RW = SPA(E_SNONE , E_PAGE_09, 0xFA),
++ E_REG_P09_DDC_ADDR_RW = SPA(E_SNONE , E_PAGE_09, 0xFB),
++ E_REG_P09_DDC_OFFS_RW = SPA(E_SNONE , E_PAGE_09, 0xFC),
++ E_REG_P09_DDC_SEGM_ADDR_RW = SPA(E_SNONE , E_PAGE_09, 0xFD),
++ E_REG_P09_DDC_SEGM_RW = SPA(E_SNONE , E_PAGE_09, 0xFE),
++
++ E_REG_P10_IF1_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x20),
++ E_REG_P10_IF1_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x21),
++ E_REG_P10_IF1_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x22),
++ E_REG_P10_IF1_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x23),
++ E_REG_P10_IF1_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x24),
++ E_REG_P10_IF1_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x25),
++ E_REG_P10_IF1_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x26),
++ E_REG_P10_IF1_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x27),
++ E_REG_P10_IF1_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x28),
++ E_REG_P10_IF1_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x29),
++ E_REG_P10_IF1_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x2A),
++ E_REG_P10_IF1_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x2B),
++ E_REG_P10_IF1_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x2C),
++ E_REG_P10_IF1_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x2D),
++ E_REG_P10_IF1_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x2E),
++ E_REG_P10_IF1_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x2F),
++ E_REG_P10_IF1_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x30),
++ E_REG_P10_IF1_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x31),
++ E_REG_P10_IF1_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x32),
++ E_REG_P10_IF1_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x33),
++ E_REG_P10_IF1_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x34),
++ E_REG_P10_IF1_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x35),
++ E_REG_P10_IF1_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x36),
++ E_REG_P10_IF1_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x37),
++ E_REG_P10_IF1_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x38),
++ E_REG_P10_IF1_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x39),
++ E_REG_P10_IF1_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x3A),
++ E_REG_P10_IF1_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x3B),
++ E_REG_P10_IF1_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x3C),
++ E_REG_P10_IF1_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x3D),
++ E_REG_P10_IF1_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x3E),
++ E_REG_P10_IF2_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x40),
++ E_REG_P10_IF2_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x41),
++ E_REG_P10_IF2_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x42),
++ E_REG_P10_IF2_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x43),
++ E_REG_P10_IF2_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x44),
++ E_REG_P10_IF2_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x45),
++ E_REG_P10_IF2_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x46),
++ E_REG_P10_IF2_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x47),
++ E_REG_P10_IF2_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x48),
++ E_REG_P10_IF2_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x49),
++ E_REG_P10_IF2_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x4A),
++ E_REG_P10_IF2_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x4B),
++ E_REG_P10_IF2_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x4C),
++ E_REG_P10_IF2_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x4D),
++ E_REG_P10_IF2_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x4E),
++ E_REG_P10_IF2_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x4F),
++ E_REG_P10_IF2_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x50),
++ E_REG_P10_IF2_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x51),
++ E_REG_P10_IF2_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x52),
++ E_REG_P10_IF2_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x53),
++ E_REG_P10_IF2_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x54),
++ E_REG_P10_IF2_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x55),
++ E_REG_P10_IF2_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x56),
++ E_REG_P10_IF2_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x57),
++ E_REG_P10_IF2_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x58),
++ E_REG_P10_IF2_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x59),
++ E_REG_P10_IF2_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x5A),
++ E_REG_P10_IF2_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x5B),
++ E_REG_P10_IF2_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x5C),
++ E_REG_P10_IF2_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x5D),
++ E_REG_P10_IF2_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x5E),
++ E_REG_P10_IF3_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x60),
++ E_REG_P10_IF3_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x61),
++ E_REG_P10_IF3_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x62),
++ E_REG_P10_IF3_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x63),
++ E_REG_P10_IF3_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x64),
++ E_REG_P10_IF3_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x65),
++ E_REG_P10_IF3_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x66),
++ E_REG_P10_IF3_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x67),
++ E_REG_P10_IF3_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x68),
++ E_REG_P10_IF3_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x69),
++ E_REG_P10_IF3_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x6A),
++ E_REG_P10_IF3_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x6B),
++ E_REG_P10_IF3_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x6C),
++ E_REG_P10_IF3_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x6D),
++ E_REG_P10_IF3_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x6E),
++ E_REG_P10_IF3_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x6F),
++ E_REG_P10_IF3_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x70),
++ E_REG_P10_IF3_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x71),
++ E_REG_P10_IF3_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x72),
++ E_REG_P10_IF3_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x73),
++ E_REG_P10_IF3_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x74),
++ E_REG_P10_IF3_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x75),
++ E_REG_P10_IF3_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x76),
++ E_REG_P10_IF3_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x77),
++ E_REG_P10_IF3_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x78),
++ E_REG_P10_IF3_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x79),
++ E_REG_P10_IF3_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x7A),
++ E_REG_P10_IF3_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x7B),
++ E_REG_P10_IF3_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x7C),
++ E_REG_P10_IF3_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x7D),
++ E_REG_P10_IF3_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x7E),
++ E_REG_P10_IF4_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0x80),
++ E_REG_P10_IF4_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0x81),
++ E_REG_P10_IF4_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0x82),
++ E_REG_P10_IF4_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0x83),
++ E_REG_P10_IF4_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0x84),
++ E_REG_P10_IF4_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0x85),
++ E_REG_P10_IF4_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0x86),
++ E_REG_P10_IF4_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0x87),
++ E_REG_P10_IF4_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0x88),
++ E_REG_P10_IF4_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0x89),
++ E_REG_P10_IF4_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0x8A),
++ E_REG_P10_IF4_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0x8B),
++ E_REG_P10_IF4_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0x8C),
++ E_REG_P10_IF4_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0x8D),
++ E_REG_P10_IF4_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0x8E),
++ E_REG_P10_IF4_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0x8F),
++ E_REG_P10_IF4_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0x90),
++ E_REG_P10_IF4_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0x91),
++ E_REG_P10_IF4_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0x92),
++ E_REG_P10_IF4_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0x93),
++ E_REG_P10_IF4_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0x94),
++ E_REG_P10_IF4_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0x95),
++ E_REG_P10_IF4_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0x96),
++ E_REG_P10_IF4_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0x97),
++ E_REG_P10_IF4_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0x98),
++ E_REG_P10_IF4_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0x99),
++ E_REG_P10_IF4_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0x9A),
++ E_REG_P10_IF4_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0x9B),
++ E_REG_P10_IF4_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0x9C),
++ E_REG_P10_IF4_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0x9D),
++ E_REG_P10_IF4_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0x9E),
++ E_REG_P10_IF5_HB0_RW = SPA(E_SNONE , E_PAGE_10, 0xA0),
++ E_REG_P10_IF5_HB1_RW = SPA(E_SNONE , E_PAGE_10, 0xA1),
++ E_REG_P10_IF5_HB2_RW = SPA(E_SNONE , E_PAGE_10, 0xA2),
++ E_REG_P10_IF5_PB0_RW = SPA(E_SNONE , E_PAGE_10, 0xA3),
++ E_REG_P10_IF5_PB1_RW = SPA(E_SNONE , E_PAGE_10, 0xA4),
++ E_REG_P10_IF5_PB2_RW = SPA(E_SNONE , E_PAGE_10, 0xA5),
++ E_REG_P10_IF5_PB3_RW = SPA(E_SNONE , E_PAGE_10, 0xA6),
++ E_REG_P10_IF5_PB4_RW = SPA(E_SNONE , E_PAGE_10, 0xA7),
++ E_REG_P10_IF5_PB5_RW = SPA(E_SNONE , E_PAGE_10, 0xA8),
++ E_REG_P10_IF5_PB6_RW = SPA(E_SNONE , E_PAGE_10, 0xA9),
++ E_REG_P10_IF5_PB7_RW = SPA(E_SNONE , E_PAGE_10, 0xAA),
++ E_REG_P10_IF5_PB8_RW = SPA(E_SNONE , E_PAGE_10, 0xAB),
++ E_REG_P10_IF5_PB9_RW = SPA(E_SNONE , E_PAGE_10, 0xAC),
++ E_REG_P10_IF5_PB10_RW = SPA(E_SNONE , E_PAGE_10, 0xAD),
++ E_REG_P10_IF5_PB11_RW = SPA(E_SNONE , E_PAGE_10, 0xAE),
++ E_REG_P10_IF5_PB12_RW = SPA(E_SNONE , E_PAGE_10, 0xAF),
++ E_REG_P10_IF5_PB13_RW = SPA(E_SNONE , E_PAGE_10, 0xB0),
++ E_REG_P10_IF5_PB14_RW = SPA(E_SNONE , E_PAGE_10, 0xB1),
++ E_REG_P10_IF5_PB15_RW = SPA(E_SNONE , E_PAGE_10, 0xB2),
++ E_REG_P10_IF5_PB16_RW = SPA(E_SNONE , E_PAGE_10, 0xB3),
++ E_REG_P10_IF5_PB17_RW = SPA(E_SNONE , E_PAGE_10, 0xB4),
++ E_REG_P10_IF5_PB18_RW = SPA(E_SNONE , E_PAGE_10, 0xB5),
++ E_REG_P10_IF5_PB19_RW = SPA(E_SNONE , E_PAGE_10, 0xB6),
++ E_REG_P10_IF5_PB20_RW = SPA(E_SNONE , E_PAGE_10, 0xB7),
++ E_REG_P10_IF5_PB21_RW = SPA(E_SNONE , E_PAGE_10, 0xB8),
++ E_REG_P10_IF5_PB22_RW = SPA(E_SNONE , E_PAGE_10, 0xB9),
++ E_REG_P10_IF5_PB23_RW = SPA(E_SNONE , E_PAGE_10, 0xBA),
++ E_REG_P10_IF5_PB24_RW = SPA(E_SNONE , E_PAGE_10, 0xBB),
++ E_REG_P10_IF5_PB25_RW = SPA(E_SNONE , E_PAGE_10, 0xBC),
++ E_REG_P10_IF5_PB26_RW = SPA(E_SNONE , E_PAGE_10, 0xBD),
++ E_REG_P10_IF5_PB27_RW = SPA(E_SNONE , E_PAGE_10, 0xBE),
++ E_REG_P11_AIP_CNTRL_0_RW = SPA(E_SNONE , E_PAGE_11, 0x00),
++ E_REG_P11_CA_I2S_RW = SPA(E_SNONE , E_PAGE_11, 0x01),
++ E_REG_P11_CA_DSD_RW = SPA(E_SNONE , E_PAGE_11, 0x02),
++ E_REG_P11_OBA_PH_RW = SPA(E_SNONE , E_PAGE_11, 0x03),
++ E_REG_P11_LATENCY_RD_RW = SPA(E_SNONE , E_PAGE_11, 0x04),
++ E_REG_P11_ACR_CTS_0_RW = SPA(E_SNONE , E_PAGE_11, 0x05),
++ E_REG_P11_ACR_CTS_1_RW = SPA(E_SNONE , E_PAGE_11, 0x06),
++ E_REG_P11_ACR_CTS_2_RW = SPA(E_SNONE , E_PAGE_11, 0x07),
++ E_REG_P11_ACR_N_0_RW = SPA(E_SNONE , E_PAGE_11, 0x08),
++ E_REG_P11_ACR_N_1_RW = SPA(E_SNONE , E_PAGE_11, 0x09),
++ E_REG_P11_ACR_N_2_RW = SPA(E_SNONE , E_PAGE_11, 0x0A),
++ E_REG_P11_GC_AVMUTE_RW = SPA(E_SNONE , E_PAGE_11, 0x0B),
++ E_REG_P11_CTS_N_RW = SPA(E_SNONE , E_PAGE_11, 0x0C),
++ E_REG_P11_ENC_CNTRL_RW = SPA(E_SNONE , E_PAGE_11, 0x0D),
++ E_REG_P11_DIP_FLAGS_RW = SPA(E_SNONE , E_PAGE_11, 0x0E),
++ E_REG_P11_DIP_IF_FLAGS_RW = SPA(E_SNONE , E_PAGE_11, 0x0F),
++ E_REG_P11_CH_STAT_B_0_RW = SPA(E_SNONE , E_PAGE_11, 0x14),
++ E_REG_P11_CH_STAT_B_1_RW = SPA(E_SNONE , E_PAGE_11, 0x15),
++ E_REG_P11_CH_STAT_B_3_RW = SPA(E_SNONE , E_PAGE_11, 0x16),
++ E_REG_P11_CH_STAT_B_4_RW = SPA(E_SNONE , E_PAGE_11, 0x17),
++ E_REG_P11_CH_STAT_B_2_ap0_l_RW = SPA(E_SNONE , E_PAGE_11, 0x18),
++ E_REG_P11_CH_STAT_B_2_ap0_r_RW = SPA(E_SNONE , E_PAGE_11, 0x19),
++ E_REG_P11_CH_STAT_B_2_ap1_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1A),
++ E_REG_P11_CH_STAT_B_2_ap1_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1B),
++ E_REG_P11_CH_STAT_B_2_ap2_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1C),
++ E_REG_P11_CH_STAT_B_2_ap2_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1D),
++ E_REG_P11_CH_STAT_B_2_ap3_l_RW = SPA(E_SNONE , E_PAGE_11, 0x1E),
++ E_REG_P11_CH_STAT_B_2_ap3_r_RW = SPA(E_SNONE , E_PAGE_11, 0x1F),
++ E_REG_P11_ISRC1_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x20),
++ E_REG_P11_ISRC1_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x21),
++ E_REG_P11_ISRC1_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x22),
++ E_REG_P11_ISRC1_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x23),
++ E_REG_P11_ISRC1_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x24),
++ E_REG_P11_ISRC1_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x25),
++ E_REG_P11_ISRC1_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x26),
++ E_REG_P11_ISRC1_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x27),
++ E_REG_P11_ISRC1_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x28),
++ E_REG_P11_ISRC1_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x29),
++ E_REG_P11_ISRC1_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x2A),
++ E_REG_P11_ISRC1_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x2B),
++ E_REG_P11_ISRC1_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x2C),
++ E_REG_P11_ISRC1_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x2D),
++ E_REG_P11_ISRC1_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x2E),
++ E_REG_P11_ISRC1_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x2F),
++ E_REG_P11_ISRC1_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x30),
++ E_REG_P11_ISRC1_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x31),
++ E_REG_P11_ISRC1_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x32),
++ E_REG_P11_ISRC1_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x33),
++ E_REG_P11_ISRC1_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x34),
++ E_REG_P11_ISRC1_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x35),
++ E_REG_P11_ISRC1_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x36),
++ E_REG_P11_ISRC1_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x37),
++ E_REG_P11_ISRC1_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x38),
++ E_REG_P11_ISRC1_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x39),
++ E_REG_P11_ISRC1_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x3A) ,
++ E_REG_P11_ISRC1_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x3B) ,
++ E_REG_P11_ISRC1_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x3C),
++ E_REG_P11_ISRC1_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x3D),
++ E_REG_P11_ISRC1_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x3E),
++ E_REG_P11_ISRC2_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x40),
++ E_REG_P11_ISRC2_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x41),
++ E_REG_P11_ISRC2_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x42),
++ E_REG_P11_ISRC2_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x43),
++ E_REG_P11_ISRC2_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x44),
++ E_REG_P11_ISRC2_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x45),
++ E_REG_P11_ISRC2_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x46),
++ E_REG_P11_ISRC2_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x47),
++ E_REG_P11_ISRC2_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x48),
++ E_REG_P11_ISRC2_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x49),
++ E_REG_P11_ISRC2_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x4A),
++ E_REG_P11_ISRC2_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x4B),
++ E_REG_P11_ISRC2_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x4C),
++ E_REG_P11_ISRC2_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x4D),
++ E_REG_P11_ISRC2_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x4E),
++ E_REG_P11_ISRC2_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x4F),
++ E_REG_P11_ISRC2_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x50),
++ E_REG_P11_ISRC2_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x51),
++ E_REG_P11_ISRC2_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x52),
++ E_REG_P11_ISRC2_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x53),
++ E_REG_P11_ISRC2_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x54),
++ E_REG_P11_ISRC2_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x55),
++ E_REG_P11_ISRC2_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x56),
++ E_REG_P11_ISRC2_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x57),
++ E_REG_P11_ISRC2_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x58),
++ E_REG_P11_ISRC2_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x59),
++ E_REG_P11_ISRC2_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x5A),
++ E_REG_P11_ISRC2_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x5B),
++ E_REG_P11_ISRC2_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x5C),
++ E_REG_P11_ISRC2_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x5D),
++ E_REG_P11_ISRC2_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x5E),
++ E_REG_P11_ACP_HB0_RW = SPA(E_SNONE , E_PAGE_11, 0x60),
++ E_REG_P11_ACP_HB1_RW = SPA(E_SNONE , E_PAGE_11, 0x61),
++ E_REG_P11_ACP_HB2_RW = SPA(E_SNONE , E_PAGE_11, 0x62),
++ E_REG_P11_ACP_PB0_RW = SPA(E_SNONE , E_PAGE_11, 0x63),
++ E_REG_P11_ACP_PB1_RW = SPA(E_SNONE , E_PAGE_11, 0x64),
++ E_REG_P11_ACP_PB2_RW = SPA(E_SNONE , E_PAGE_11, 0x65),
++ E_REG_P11_ACP_PB3_RW = SPA(E_SNONE , E_PAGE_11, 0x66),
++ E_REG_P11_ACP_PB4_RW = SPA(E_SNONE , E_PAGE_11, 0x67),
++ E_REG_P11_ACP_PB5_RW = SPA(E_SNONE , E_PAGE_11, 0x68),
++ E_REG_P11_ACP_PB6_RW = SPA(E_SNONE , E_PAGE_11, 0x69),
++ E_REG_P11_ACP_PB7_RW = SPA(E_SNONE , E_PAGE_11, 0x6A),
++ E_REG_P11_ACP_PB8_RW = SPA(E_SNONE , E_PAGE_11, 0x6B),
++ E_REG_P11_ACP_PB9_RW = SPA(E_SNONE , E_PAGE_11, 0x6C),
++ E_REG_P11_ACP_PB10_RW = SPA(E_SNONE , E_PAGE_11, 0x6D),
++ E_REG_P11_ACP_PB11_RW = SPA(E_SNONE , E_PAGE_11, 0x6E),
++ E_REG_P11_ACP_PB12_RW = SPA(E_SNONE , E_PAGE_11, 0x6F),
++ E_REG_P11_ACP_PB13_RW = SPA(E_SNONE , E_PAGE_11, 0x70),
++ E_REG_P11_ACP_PB14_RW = SPA(E_SNONE , E_PAGE_11, 0x71),
++ E_REG_P11_ACP_PB15_RW = SPA(E_SNONE , E_PAGE_11, 0x72),
++ E_REG_P11_ACP_PB16_RW = SPA(E_SNONE , E_PAGE_11, 0x73),
++ E_REG_P11_ACP_PB17_RW = SPA(E_SNONE , E_PAGE_11, 0x74),
++ E_REG_P11_ACP_PB18_RW = SPA(E_SNONE , E_PAGE_11, 0x75),
++ E_REG_P11_ACP_PB19_RW = SPA(E_SNONE , E_PAGE_11, 0x76),
++ E_REG_P11_ACP_PB20_RW = SPA(E_SNONE , E_PAGE_11, 0x77),
++ E_REG_P11_ACP_PB21_RW = SPA(E_SNONE , E_PAGE_11, 0x78),
++ E_REG_P11_ACP_PB22_RW = SPA(E_SNONE , E_PAGE_11, 0x79),
++ E_REG_P11_ACP_PB23_RW = SPA(E_SNONE , E_PAGE_11, 0x7A),
++ E_REG_P11_ACP_PB24_RW = SPA(E_SNONE , E_PAGE_11, 0x7B),
++ E_REG_P11_ACP_PB25_RW = SPA(E_SNONE , E_PAGE_11, 0x7C),
++ E_REG_P11_ACP_PB26_RW = SPA(E_SNONE , E_PAGE_11, 0x7D),
++ E_REG_P11_ACP_PB27_RW = SPA(E_SNONE , E_PAGE_11, 0x7E),
++ E_REG_P13_GMD_0_HB0_RW = SPA(E_SNONE , E_PAGE_13, 0x00),
++ E_REG_P13_GMD_0_HB1_RW = SPA(E_SNONE , E_PAGE_13, 0x01),
++ E_REG_P13_GMD_0_HB2_RW = SPA(E_SNONE , E_PAGE_13, 0x02),
++ E_REG_P13_GMD_0_PB0_RW = SPA(E_SNONE , E_PAGE_13, 0x03),
++ E_REG_P13_GMD_0_PB1_RW = SPA(E_SNONE , E_PAGE_13, 0x04),
++ E_REG_P13_GMD_0_PB2_RW = SPA(E_SNONE , E_PAGE_13, 0x05),
++ E_REG_P13_GMD_0_PB3_RW = SPA(E_SNONE , E_PAGE_13, 0x06),
++ E_REG_P13_GMD_0_PB4_RW = SPA(E_SNONE , E_PAGE_13, 0x07),
++ E_REG_P13_GMD_0_PB5_RW = SPA(E_SNONE , E_PAGE_13, 0x08),
++ E_REG_P13_GMD_0_PB6_RW = SPA(E_SNONE , E_PAGE_13, 0x09),
++ E_REG_P13_GMD_0_PB7_RW = SPA(E_SNONE , E_PAGE_13, 0x0A),
++ E_REG_P13_GMD_0_PB8_RW = SPA(E_SNONE , E_PAGE_13, 0x0B),
++ E_REG_P13_GMD_0_PB9_RW = SPA(E_SNONE , E_PAGE_13, 0x0C),
++ E_REG_P13_GMD_0_PB10_RW = SPA(E_SNONE , E_PAGE_13, 0x0D),
++ E_REG_P13_GMD_0_PB11_RW = SPA(E_SNONE , E_PAGE_13, 0x0E),
++ E_REG_P13_GMD_0_PB12_RW = SPA(E_SNONE , E_PAGE_13, 0x0F),
++ E_REG_P13_GMD_0_PB13_RW = SPA(E_SNONE , E_PAGE_13, 0x10),
++ E_REG_P13_GMD_0_PB14_RW = SPA(E_SNONE , E_PAGE_13, 0x11),
++ E_REG_P13_GMD_0_PB15_RW = SPA(E_SNONE , E_PAGE_13, 0x12),
++ E_REG_P13_GMD_0_PB16_RW = SPA(E_SNONE , E_PAGE_13, 0x13),
++ E_REG_P13_GMD_0_PB17_RW = SPA(E_SNONE , E_PAGE_13, 0x14),
++ E_REG_P13_GMD_0_PB18_RW = SPA(E_SNONE , E_PAGE_13, 0x15),
++ E_REG_P13_GMD_0_PB19_RW = SPA(E_SNONE , E_PAGE_13, 0x16),
++ E_REG_P13_GMD_0_PB20_RW = SPA(E_SNONE , E_PAGE_13, 0x17),
++ E_REG_P13_GMD_0_PB21_RW = SPA(E_SNONE , E_PAGE_13, 0x18),
++ E_REG_P13_GMD_0_PB22_RW = SPA(E_SNONE , E_PAGE_13, 0x19),
++ E_REG_P13_GMD_0_PB23_RW = SPA(E_SNONE , E_PAGE_13, 0x1A),
++ E_REG_P13_GMD_0_PB24_RW = SPA(E_SNONE , E_PAGE_13, 0x1B),
++ E_REG_P13_GMD_0_PB25_RW = SPA(E_SNONE , E_PAGE_13, 0x1C),
++ E_REG_P13_GMD_0_PB26_RW = SPA(E_SNONE , E_PAGE_13, 0x1D),
++ E_REG_P13_GMD_0_PB27_RW = SPA(E_SNONE , E_PAGE_13, 0x1E),
++ E_REG_P13_GMD_CONTROL_RW = SPA(E_SNONE , E_PAGE_13, 0x1F),
++ E_REG_P13_GMD_1_HB0_RW = SPA(E_SNONE , E_PAGE_13, 0x20),
++ E_REG_P13_GMD_1_HB1_RW = SPA(E_SNONE , E_PAGE_13, 0x21),
++ E_REG_P13_GMD_1_HB2_RW = SPA(E_SNONE , E_PAGE_13, 0x22),
++ E_REG_P13_GMD_1_PB0_RW = SPA(E_SNONE , E_PAGE_13, 0x23),
++ E_REG_P13_GMD_1_PB1_RW = SPA(E_SNONE , E_PAGE_13, 0x24),
++ E_REG_P13_GMD_1_PB2_RW = SPA(E_SNONE , E_PAGE_13, 0x25),
++ E_REG_P13_GMD_1_PB3_RW = SPA(E_SNONE , E_PAGE_13, 0x26),
++ E_REG_P13_GMD_1_PB4_RW = SPA(E_SNONE , E_PAGE_13, 0x27),
++ E_REG_P13_GMD_1_PB5_RW = SPA(E_SNONE , E_PAGE_13, 0x28),
++ E_REG_P13_GMD_1_PB6_RW = SPA(E_SNONE , E_PAGE_13, 0x29),
++ E_REG_P13_GMD_1_PB7_RW = SPA(E_SNONE , E_PAGE_13, 0x2A),
++ E_REG_P13_GMD_1_PB8_RW = SPA(E_SNONE , E_PAGE_13, 0x2B),
++ E_REG_P13_GMD_1_PB9_RW = SPA(E_SNONE , E_PAGE_13, 0x2C),
++ E_REG_P13_GMD_1_PB10_RW = SPA(E_SNONE , E_PAGE_13, 0x2D),
++ E_REG_P13_GMD_1_PB11_RW = SPA(E_SNONE , E_PAGE_13, 0x2E),
++ E_REG_P13_GMD_1_PB12_RW = SPA(E_SNONE , E_PAGE_13, 0x2F),
++ E_REG_P13_GMD_1_PB13_RW = SPA(E_SNONE , E_PAGE_13, 0x30),
++ E_REG_P13_GMD_1_PB14_RW = SPA(E_SNONE , E_PAGE_13, 0x31),
++ E_REG_P13_GMD_1_PB15_RW = SPA(E_SNONE , E_PAGE_13, 0x32),
++ E_REG_P13_GMD_1_PB16_RW = SPA(E_SNONE , E_PAGE_13, 0x33),
++ E_REG_P13_GMD_1_PB17_RW = SPA(E_SNONE , E_PAGE_13, 0x34),
++ E_REG_P13_GMD_1_PB18_RW = SPA(E_SNONE , E_PAGE_13, 0x35),
++ E_REG_P13_GMD_1_PB19_RW = SPA(E_SNONE , E_PAGE_13, 0x36),
++ E_REG_P13_GMD_1_PB20_RW = SPA(E_SNONE , E_PAGE_13, 0x37),
++ E_REG_P13_GMD_1_PB21_RW = SPA(E_SNONE , E_PAGE_13, 0x38),
++ E_REG_P13_GMD_1_PB22_RW = SPA(E_SNONE , E_PAGE_13, 0x39),
++ E_REG_P13_GMD_1_PB23_RW = SPA(E_SNONE , E_PAGE_13, 0x3A),
++ E_REG_P13_GMD_1_PB24_RW = SPA(E_SNONE , E_PAGE_13, 0x3B),
++ E_REG_P13_GMD_1_PB25_RW = SPA(E_SNONE , E_PAGE_13, 0x3C),
++ E_REG_P13_GMD_1_PB26_RW = SPA(E_SNONE , E_PAGE_13, 0x3D),
++ E_REG_P13_GMD_1_PB27_RW = SPA(E_SNONE , E_PAGE_13, 0x3E)
++};
++#undef SPR
++
++/**
++ * Register bitfield masks, with a macro to allow binary initializers.
++ * Enum names are derived directly from TDA998x register and bitfield names.
++ */
++#define BINARY(d7,d6,d5,d4,d3,d2,d1,d0) \
++ (((d7)<<7)|((d6)<<6)|((d5)<<5)|((d4)<<4)|((d3)<<3)|((d2)<<2)|((d1)<<1)|(d0))
++
++enum _eMaskReg
++{
++ E_MASKREG_NONE = BINARY(0,0,0,0, 0,0,0,0),
++ E_MASKREG_ALL = BINARY(1,1,1,1, 1,1,1,1),
++
++ /* N4 features flags read from version register:
++ * not_h = no HDCP support
++ * not_s = no scaler support
++ *
++ * N5 = a flag that is not a register bit, but is derived by the
++ * driver from the new N5 registers DWIN_RE_DE and DWIN_FE_DE,
++ * because the N5 device still uses the N4 version register value.
++ * This bit position would clash with version register, so is not
++ * present in the driver's copy (uDeviceVersion) of the version
++ * register, but only in the driver's features byte (uDeviceFeatures).
++ */
++
++ /* CEC Masks*/
++
++ E_MASKREG_CEC_INTERRUPTSTATUS_hdmi_int = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_INTERRUPTSTATUS_cec_int = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_CEC_RXSHPDINTENA_ena_hpd_int = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_RXSHPDINTENA_ena_rxs_int = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_CEC_RXSHPDINT_hpd_int = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_RXSHPDINT_rxs_int = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_CEC_RXSHPDLEV_hpd_level = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_RXSHPDLEV_rxs_level = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_CEC_ENAMODS_dis_fro = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_CEC_ENAMODS_dis_cclk = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_CEC_ENAMODS_ena_rxs = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_CEC_ENAMODS_ena_hdmi = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_ENAMODS_ena_cec = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_ghost_dis = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_ena_otp = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_imclk_sel = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_CEC_FRO_IM_CLK_CTRL_fro_div = BINARY(0,0,0,0, 0,0,0,1),
++
++ /* HDMI Masks*/
++ E_MASKREG_P00_VERSION_not_h = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_VERSION_not_s = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_FEATURE_N5 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_MAIN_CNTRL0_scaler = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_MAIN_CNTRL0_cehs = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_MAIN_CNTRL0_cecs = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_MAIN_CNTRL0_dehs = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_MAIN_CNTRL0_decs = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_MAIN_CNTRL0_sr = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_SR_REG_sr_i2c_ms = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_SR_REG_sr_audio = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_DDC_DISABLE_ddc_dis = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_CCLK_ON_cclk_ddc_on = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_I2C_MASTER_app_strt_lat = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_I2C_MASTER_dis_filt = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_I2C_MASTER_dis_mm = BINARY(0,0,0,0, 0,0,0,1),
++
++#ifdef TMFL_TDA19989
++ E_MASKREG_FEAT_POWER_DOWN_spdif = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_FEAT_POWER_DOWN_otp = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_FEAT_POWER_DOWN_csc = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_FEAT_POWER_DOWN_prefilt = BINARY(0,0,0,0, 0,0,0,1),
++ E_MASKREG_FEAT_POWER_DOWN_all = BINARY(0,0,0,0, 1,1,1,1),
++#endif
++
++ E_MASKREG_P00_INT_FLAGS_0_r0 = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_0_pj = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_0_sha_1 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_0_bstatus = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_0_bcaps = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_0_t0 = BINARY(0,0,0,0, 0,1,0,0),
++ /*E_MASKREG_P00_INT_FLAGS_0_hpd = BINARY(0,0,0,0, 0,0,1,0),*/
++ E_MASKREG_P00_INT_FLAGS_0_encrypt = BINARY(0,0,0,0, 0,0,0,1),
++
++ /*E_MASKREG_P00_INT_FLAGS_1_hpd_in = BINARY(1,0,0,0, 0,0,0,0),*/
++ E_MASKREG_P00_INT_FLAGS_1_sw_int = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_1_sc_deil = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_1_sc_vid = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_1_sc_out = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_INT_FLAGS_1_sc_in = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_INT_FLAGS_1_otp = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_INT_FLAGS_1_vs_rpt = BINARY(0,0,0,0, 0,0,0,1),
++ /*E_MASKREG_P00_INT_FLAGS_2_rx_sense = BINARY(0,0,0,0, 0,0,0,1),*/
++ E_MASKREG_P00_INT_FLAGS_2_edid_blk_rd = BINARY(0,0,0,0, 0,0,1,0),
++
++ /*E_MASKREG_P00_INT_FLAGS_3_rxs_fil = BINARY(0,0,0,0, 0,0,0,1),*/
++
++ E_MASKREG_P00_SW_INT_sw_int = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_ENA_ACLK_ena_aclk = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_GND_ACLK_gnd_aclk = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_ENA_VP_0_ena_vp7 = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp6 = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp5 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp4 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp3 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp2 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp1 = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_ENA_VP_0_ena_vp0 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_ENA_VP_1_ena_vp15 = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp14 = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp13 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp12 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp11 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp10 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp9 = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_ENA_VP_1_ena_vp8 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_ENA_VP_2_ena_vp23 = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp22 = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp21 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp20 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp19 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp18 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp17 = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_ENA_VP_2_ena_vp16 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_ENA_AP_ena_ap7 = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap6 = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap5 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap4 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap3 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap2 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_ENA_AP_ena_ap1 = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_ENA_AP_ena_ap0 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_VIP_CNTRL_0_mirr_a = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_0_swap_a = BINARY(0,1,1,1, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_0_mirr_b = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_0_swap_b = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P00_VIP_CNTRL_1_mirr_c = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_1_swap_c = BINARY(0,1,1,1, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_1_mirr_d = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_1_swap_d = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P00_VIP_CNTRL_2_mirr_e = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_2_swap_e = BINARY(0,1,1,1, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_2_mirr_f = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_2_swap_f = BINARY(0,0,0,0, 0,1,1,1),
++
++#ifdef TMFL_TDA19989
++ E_MASKREG_P00_MUX_VP_VIP_OUT_red = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P00_MUX_VP_VIP_OUT_green = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P00_MUX_VP_VIP_OUT_blue = BINARY(0,0,0,0, 0,0,1,1),
++#endif
++
++ E_MASKREG_P00_VIP_CNTRL_3_edge = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_3_de_int = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_3_sp_sync = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_3_emb = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_3_v_tgl = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_VIP_CNTRL_3_h_tgl = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_VIP_CNTRL_3_x_tgl = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_VIP_CNTRL_4_tst_pat = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_4_tst_656 = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_4_656_alt = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_4_ccir656 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_VIP_CNTRL_4_blankit = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P00_VIP_CNTRL_4_blc = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P00_VIP_CNTRL_5_sp_cnt = BINARY(0,0,0,0, 0,1,1,0),
++ E_MASKREG_P00_VIP_CNTRL_5_ckcase = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_MAT_CONTRL_mat_bp = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_MAT_CONTRL_mat_sc = BINARY(0,0,0,0, 0,0,1,1),
++
++#ifdef TMFL_TDA19989
++ E_MASKREG_P00_VIDFORMAT_3d = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_VIDFORMAT_3d_neg_vs = BINARY(0,1,0,0, 0,0,0,0),
++#endif
++ E_MASKREG_P00_VIDFORMAT_vidformat = BINARY(0,0,0,1, 1,1,1,1),
++
++ E_MASKREG_P00_TBG_CNTRL_0_sync_once = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_0_sync_mthd = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_0_frame_dis = BINARY(0,0,1,0, 0,0,0,0),
++
++ E_MASKREG_P00_TBG_CNTRL_1_dwin_dis = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext = BINARY(0,0,1,1, 1,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_vs = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_hs = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vhx_ext_de = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl = BINARY(0,0,0,0, 0,1,1,1),
++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_2 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_1 = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_TBG_CNTRL_1_vh_tgl_0 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_I2C_TIMER_RI = BINARY(0,0,0,0, 1,1,1,1),
++ E_MASKREG_P00_I2C_TIMER_PJ = BINARY(1,1,1,1, 0,0,0,0),
++
++ E_MASKREG_P00_HVF_CNTRL_0_sm = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P00_HVF_CNTRL_0_rwb = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_HVF_CNTRL_0_prefil = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P00_HVF_CNTRL_0_intpol = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P00_HVF_CNTRL_1_semi_planar = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_HVF_CNTRL_1_pad = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P00_HVF_CNTRL_1_vqr = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P00_HVF_CNTRL_1_yuvblk = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_HVF_CNTRL_1_for = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_TIMER_H_wd_clksel = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_TIMER_H_tim_h = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P00_DEBUG_PROBE_sel = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P00_DEBUG_PROBE_bypass = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P00_DEBUG_PROBE_vid_de = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_DEBUG_PROBE_di_de = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P00_DEBUG_PROBE_woo_en = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P00_I2S_FORMAT_i2s_format = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P00_I2S_FORMAT_i2s_data_size = BINARY(0,0,0,0, 1,1,0,0),
++
++ E_MASKREG_P00_AIP_CLKSEL_dst_rate = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P00_AIP_CLKSEL_sel_aip_SHIFT = 3,
++ E_MASKREG_P00_AIP_CLKSEL_sel_aip = BINARY(0,0,1,1, 1,0,0,0),
++ E_MASKREG_P00_AIP_CLKSEL_sel_pol_clk = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P00_AIP_CLKSEL_sel_fs = BINARY(0,0,0,0, 0,0,1,1),
++ E_MASKREG_P01_SC_VIDFORMAT_lut_sel = BINARY(1,1,0,0, 0,0,0,0),
++ E_MASKREG_P01_SC_VIDFORMAT_vid_format_o = BINARY(0,0,1,1, 1,0,0,0),
++ E_MASKREG_P01_SC_VIDFORMAT_vid_format_i = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P01_SC_CNTRL_phases_h = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P01_SC_CNTRL_il_out_on = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P01_SC_CNTRL_phases_v = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P01_SC_CNTRL_vs_on = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P01_SC_CNTRL_deil_on = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P01_VIDFORMAT_vidformat = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P01_TBG_CNTRL_0_sync_once = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P01_TBG_CNTRL_0_sync_mthd = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P01_TBG_CNTRL_0_frame_dis = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P01_TBG_CNTRL_0_top_ext = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P01_TBG_CNTRL_0_de_ext = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P01_TBG_CNTRL_0_top_sel = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P01_TBG_CNTRL_0_top_tgl = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_PLL_SERIAL_1_srl_man_iz = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P02_PLL_SERIAL_1_srl_iz = BINARY(0,0,0,0, 0,1,1,0),
++ E_MASKREG_P02_PLL_SERIAL_1_srl_fdn = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_PLL_SERIAL_2_srl_pr = BINARY(1,1,1,1, 0,0,0,0),
++ E_MASKREG_P02_PLL_SERIAL_2_srl_nosc = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P02_PLL_SERIAL_3_srl_pxin_sel = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P02_PLL_SERIAL_3_srl_de = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P02_PLL_SERIAL_3_srl_ccir = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_SERIALIZER_srl_phase3 = BINARY(1,1,1,1, 0,0,0,0),
++ E_MASKREG_P02_SERIALIZER_srl_phase2 = BINARY(0,0,0,0, 1,1,1,1),
++
++ E_MASKREG_P02_BUFFER_OUT_srl_force = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P02_BUFFER_OUT_srl_clk = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P02_PLL_SCG1_scg_fdn = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_PLL_SCG2_bypass_scg = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P02_PLL_SCG2_selpllclkin = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P02_PLL_SCG2_scg_nosc = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P02_VAI_PLL_pllde_hvp = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P02_VAI_PLL_pllscg_hvp = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P02_VAI_PLL_pllsrl_hvp = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P02_VAI_PLL_pllscg_lock = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P02_VAI_PLL_pllsrl_lock = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_AUDIO_DIV_audio_div = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P02_TEST1_srldat = BINARY(1,1,0,0, 0,0,0,0),
++ E_MASKREG_P02_TEST1_tst_nosc = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P02_TEST1_tst_enahvp = BINARY(0,0,0,0, 0,0,0,1),
++
++ //E_MASKREG_P02_TEST2_pwd1v8 = BINARY(0,0,0,0, 0,0,1,0),
++ //E_MASKREG_P02_TEST2_divtestoe = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_SEL_CLK_ena_sc_clk = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P02_SEL_CLK_sel_vrf_clk = BINARY(0,0,0,0, 0,1,1,0),
++ E_MASKREG_P02_SEL_CLK_sel_clk1 = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P02_BUFF_OUT2_force_dat2 = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P02_BUFF_OUT2_force_dat1 = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P02_BUFF_OUT2_force_dat0 = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P09_EDID_CTRL_edid_rd = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P11_AIP_CNTRL_0_rst_cts = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P11_AIP_CNTRL_0_acr_man = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P11_AIP_CNTRL_0_layout = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P11_AIP_CNTRL_0_swap = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P11_AIP_CNTRL_0_rst_fifo = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P11_CA_I2S_hbr_chstat_4 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P11_CA_I2S_ca_i2s = BINARY(0,0,0,1, 1,1,1,1),
++
++ E_MASKREG_P11_GC_AVMUTE_set_mute = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P11_GC_AVMUTE_clr_mute = BINARY(0,0,0,0, 0,0,0,1),
++ E_MASKREG_P11_GC_AVMUTE_setclr_mute = BINARY(0,0,0,0, 0,0,1,1),
++
++ E_MASKREG_P11_CTS_N_m_sel = BINARY(0,0,1,1, 0,0,0,0),
++ E_MASKREG_P11_CTS_N_k_sel = BINARY(0,0,0,0, 0,1,1,1),
++
++ E_MASKREG_P11_ENC_CNTRL_ctl_code = BINARY(0,0,0,0, 1,1,0,0),
++ E_MASKREG_P11_ENC_CNTRL_rst_sel = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P11_ENC_CNTRL_rst_enc = BINARY(0,0,0,0, 0,0,0,1),
++ E_MASKREG_P11_DIP_FLAGS_force_null = BINARY(1,0,0,0, 0,0,0,0),
++ E_MASKREG_P11_DIP_FLAGS_null = BINARY(0,1,0,0, 0,0,0,0),
++ E_MASKREG_P11_DIP_FLAGS_acp = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P11_DIP_FLAGS_isrc2 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P11_DIP_FLAGS_isrc1 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P11_DIP_FLAGS_gc = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P11_DIP_FLAGS_acr = BINARY(0,0,0,0, 0,0,0,1),
++
++ E_MASKREG_P11_DIP_IF_FLAGS_if5 = BINARY(0,0,1,0, 0,0,0,0),
++ E_MASKREG_P11_DIP_IF_FLAGS_if4 = BINARY(0,0,0,1, 0,0,0,0),
++ E_MASKREG_P11_DIP_IF_FLAGS_if3 = BINARY(0,0,0,0, 1,0,0,0),
++ E_MASKREG_P11_DIP_IF_FLAGS_if2 = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P11_DIP_IF_FLAGS_if1 = BINARY(0,0,0,0, 0,0,1,0),
++
++ E_MASKREG_P13_GMD_CONTROL_buf_sel = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P13_GMD_CONTROL_enable = BINARY(0,0,0,0, 0,0,0,1)
++};
++#undef BINARY
++
++/**
++ * 3 enum for the video formats :
++ * - 1 used in the E_REG_P00_VIDFORMAT_W register
++ * - 1 for new format that are not prefetch
++ * - 1 for PC
++ */
++#define REGVFMT_INVALID 0xFF
++
++enum _eRegVfmt {
++ E_REGVFMT_640x480p_60Hz = 0, /* 1 */
++ E_REGVFMT_720x480p_60Hz , /* 2/3 */
++ E_REGVFMT_1280x720p_60Hz , /* 4 */
++ E_REGVFMT_1920x1080i_60Hz , /* 5 */
++ E_REGVFMT_720x480i_60Hz , /* 6/4 */
++ E_REGVFMT_720x240p_60Hz , /*NT 8/9 */
++ E_REGVFMT_1920x1080p_60Hz , /* 16 */
++ E_REGVFMT_720x576p_50Hz , /* 17/18 */
++ E_REGVFMT_1280x720p_50Hz , /* 19 */
++ E_REGVFMT_1920x1080i_50Hz , /* 20 */
++ E_REGVFMT_720x576i_50Hz , /* 21/22 */
++ E_REGVFMT_720x288p_50Hz , /* 23/24 */
++ E_REGVFMT_1920x1080p_50Hz , /* 31 */
++#ifdef TMFL_RGB_DDR_12BITS
++ E_REGVFMT_1920x1080p_24Hz , /* 32 */
++ E_REGVFMT_1440x576p_50Hz , /* 29/30 */
++ E_REGVFMT_1440x480p_60Hz , /* 14/15 */
++ E_REGVFMT_2880x480p_60Hz , /* 35/36 */
++ E_REGVFMT_2880x576p_50Hz , /* 37/38 */
++ E_REGVFMT_2880x480i_60Hz , /* 10/11*/
++ E_REGVFMT_2880x480i_60Hz_PR2, /* 10/11*/
++ E_REGVFMT_2880x480i_60Hz_PR4, /* 10/11*/
++ E_REGVFMT_2880x576i_50Hz , /* 25/26 */
++ E_REGVFMT_2880x576i_50Hz_PR2, /* 25/26 */
++ E_REGVFMT_720x480p_60Hz_FP , /* 2/3 FP */
++ E_REGVFMT_1280x720p_60Hz_FP , /* 4 FP */
++ E_REGVFMT_720x576p_50Hz_FP , /* 17/18 FP */
++ E_REGVFMT_1280x720p_50Hz_FP , /* 19 FP */
++ E_REGVFMT_1920x1080p_24Hz_FP, /* 32 FP */
++ E_REGVFMT_1920x1080p_25Hz_FP, /* 33 FP */
++ E_REGVFMT_1920x1080p_30Hz_FP, /* 34 FP */
++ E_REGVFMT_1920x1080i_60Hz_FP, /* 5 FP */
++ E_REGVFMT_1920x1080i_50Hz_FP, /* 20 FP */
++#endif
++ E_REGVFMT_MAX_PREFETCH ,
++ E_REGVFMT_NUM_PREFETCH = E_REGVFMT_MAX_PREFETCH
++};
++
++enum _eRegVfmtExtra {
++#ifndef TMFL_RGB_DDR_12BITS
++ E_REGVFMT_1920x1080p_24Hz = E_REGVFMT_MAX_PREFETCH, /* 32 */
++ E_REGVFMT_1920x1080p_25Hz , /* 33 */
++#else
++ E_REGVFMT_1920x1080p_25Hz = E_REGVFMT_MAX_PREFETCH,
++#endif
++ E_REGVFMT_1920x1080p_30Hz, /* 34 */
++ E_REGVFMT_1280x720p_24Hz, /* 60 */
++ E_REGVFMT_1280x720p_25Hz, /* 61 */
++ E_REGVFMT_1280x720p_30Hz , /* 62 */
++#ifndef TMFL_RGB_DDR_12BITS
++ E_REGVFMT_1280x720p_60Hz_FP,
++ E_REGVFMT_1920x1080i_60Hz_FP,
++ E_REGVFMT_1280x720p_50Hz_FP,
++ E_REGVFMT_1920x1080i_50Hz_FP,
++ E_REGVFMT_1920x1080p_24Hz_FP,
++ E_REGVFMT_1920x1080p_25Hz_FP,
++ E_REGVFMT_1920x1080p_30Hz_FP,
++#endif
++ E_REGVFMT_1280x720p_24Hz_FP,
++ E_REGVFMT_1280x720p_25Hz_FP,
++ E_REGVFMT_1280x720p_30Hz_FP,
++ E_REGVFMT_MAX_EXTRA ,
++ E_REGVFMT_NUM_EXTRA = E_REGVFMT_MAX_EXTRA - E_REGVFMT_MAX_PREFETCH
++};
++
++#ifdef FORMAT_PC
++enum _eRegVfmtPC {
++ E_REGVFMT_640x480p_72Hz = E_REGVFMT_MAX_EXTRA,
++ E_REGVFMT_640x480p_75Hz ,
++ E_REGVFMT_640x480p_85Hz ,
++ E_REGVFMT_800x600p_60Hz ,
++ E_REGVFMT_800x600p_72Hz ,
++ E_REGVFMT_800x600p_75Hz ,
++ E_REGVFMT_800x600p_85Hz ,
++ E_REGVFMT_1024x768p_60Hz ,
++ E_REGVFMT_1024x768p_70Hz ,
++ E_REGVFMT_1024x768p_75Hz ,
++ E_REGVFMT_1280x768p_60Hz ,
++ E_REGVFMT_1280x1024p_60Hz ,
++ E_REGVFMT_1360x768p_60Hz ,
++ E_REGVFMT_1400x1050p_60Hz ,
++ E_REGVFMT_1600x1200p_60Hz ,
++ E_REGVFMT_1280x1024p_85Hz ,
++ E_REGVFMT_MAX_PC ,
++ E_REGVFMT_NUM_PC = E_REGVFMT_MAX_PC - E_REGVFMT_MAX_EXTRA
++};
++#define E_REGVFMT_MAX E_REGVFMT_MAX_PC
++#else
++#define E_REGVFMT_MAX E_REGVFMT_MAX_EXTRA
++#endif /*FORMAT_PC*/
++
++#define PREFETCH(fmt) ((fmt) < E_REGVFMT_MAX_PREFETCH)
++#define EXTRA(fmt) (!PREFETCH(fmt))
++#define PCFORMAT(fmt) ((fmt) >= E_REGVFMT_MAX_EXTRA)/* PR1570 FIXED */
++#define BASE(fmt) (PREFETCH(fmt)?(fmt):(fmt)-E_REGVFMT_MAX_PREFETCH)
++
++
++/**
++ * An enum for the video input formats used in the E_REG_P01_SC_VIDFORMAT_W
++ * register
++ */
++enum _eRegVfmtScIn
++{
++ E_REGVFMT_SCIN_480i_60Hz = 0,
++ E_REGVFMT_SCIN_576i_50Hz = 1,
++ E_REGVFMT_SCIN_480p_60Hz = 2,
++ E_REGVFMT_SCIN_576p_50Hz = 3,
++ E_REGVFMT_SCIN_720p_50Hz_60Hz = 4,
++ E_REGVFMT_SCIN_1080i_50Hz_60Hz = 5,
++ E_REGVFMT_SCIN_MAX = 5,
++ E_REGVFMT_SCIN_NUM = 6,
++ E_REGVFMT_SCIN_INVALID = 6
++};
++
++/**
++ * An enum to list all supported pixel clock frequencies in kHz
++ */
++enum _ePixClk
++{
++ E_PIXCLK_25175 = 0,
++ E_PIXCLK_25200 = 1,
++ E_PIXCLK_27000 = 2,
++ E_PIXCLK_27027 = 3,
++ E_PIXCLK_54000 = 4,
++ E_PIXCLK_54054 = 5,
++ E_PIXCLK_59400 = 6,
++ E_PIXCLK_74175 = 7,
++ E_PIXCLK_74250 = 8,
++ E_PIXCLK_148350 = 9,
++ E_PIXCLK_148500 = 10,
++ E_PIXCLK_108000 = 11,
++ E_PIXCLK_108108 = 12,
++#ifndef FORMAT_PC
++ E_PIXCLK_MAX = 12,
++ E_PIXCLK_INVALID = 13,
++ E_PIXCLK_NUM = 13
++#else /* FORMAT_PC */
++ E_PIXCLK_31500 = 13,
++ E_PIXCLK_36000 = 14,
++ E_PIXCLK_40000 = 15,
++ E_PIXCLK_49500 = 16,
++ E_PIXCLK_50000 = 17,
++ E_PIXCLK_56250 = 18,
++ E_PIXCLK_65000 = 19,
++ E_PIXCLK_75000 = 20,
++ E_PIXCLK_78750 = 21,
++ E_PIXCLK_79500 = 22,
++ E_PIXCLK_85500 = 23,
++ E_PIXCLK_PC_108000 = 24,
++ E_PIXCLK_121750 = 25,
++ E_PIXCLK_162000 = 26,
++ E_PIXCLK_MAX = 26,
++ E_PIXCLK_INVALID = 27,
++ E_PIXCLK_NUM = 27
++#endif /* FORMAT_PC */
++};
++
++/**
++ * An enum to list all device version codes supported by this driver.
++ * The values form a list, with non-zero version codes first in any order.
++ * The E_DEV_VERSION_END_LIST must be the last value in the list.
++ */
++enum _eDevVersion
++{
++ E_DEV_VERSION_N2 = 0x101, /**< TDA9989 n2 */
++ E_DEV_VERSION_TDA19989 = 0x201, /**< TDA19989 */
++ E_DEV_VERSION_TDA19989_N2 = 0x202, /**< TDA19989 N2 */
++ E_DEV_VERSION_TDA19988 = 0x301, /**< TDA19988 */
++ E_DEV_VERSION_LIST_END = 0x00,
++ E_DEV_VERSION_LIST_NUM = 5 /**< Number of items in list */
++};
++
++/**
++ * An enum to list all CEA Data Block Tag Codes we may find in EDID.
++ */
++enum _eCeaBlockTags
++{
++ E_CEA_RESERVED_0 = 0x00,
++ E_CEA_AUDIO_BLOCK = 0x01,
++ E_CEA_VIDEO_BLOCK = 0x02,
++ E_CEA_VSDB = 0x03,
++ E_CEA_SPEAKER_ALLOC = 0x04,
++ E_CEA_VESA_DTC = 0x05,
++ E_CEA_RESERVED_6 = 0x06,
++ E_CEA_EXTENDED = 0x07
++};
++
++/**
++ * An enum to list all CEA Data Block Extended Tag Codes we may find in EDID.
++ */
++enum _eCeaExtendedBlockTags
++{
++ EXT_CEA_MISC_VIDEO_FIELDS = 0x00,
++ EXT_CEA_VS_VIDEO_DB = 0x01,
++ EXT_CEA_COLORIMETRY_DB = 0x05,
++ EXT_CEA_MISC_AUDIO_FIELDS = 0x10,
++ EXT_CEA_VS_AUDIO_DB = 0x11
++};
++
++/** A typedef for colourspace values */
++typedef enum
++{
++ HDMITX_CS_RGB_FULL = 0, /**< RGB Full (PC) */
++ HDMITX_CS_RGB_LIMITED = 1, /**< RGB Limited (TV) */
++ HDMITX_CS_YUV_ITU_BT601 = 2, /**< YUV ITUBT601 (SDTV) */
++ HDMITX_CS_YUV_ITU_BT709 = 3, /**< YUV ITUBT709 (HDTV) */
++ HDMITX_CS_NUM = 4 /**< Number Cspaces we support */
++} tmbslTDA9989Colourspace_t;
++
++/** Matrix register block size */
++#define MATRIX_PRESET_SIZE 31
++
++/** Matrix register block size */
++#define MATRIX_PRESET_QTY 12
++
++/** The enum that vectors us into the MatrixPreset table */
++enum _eMatrixPresetIndex
++{
++ E_MATRIX_RGBF_2_RGBL = 0,
++ E_MATRIX_RGBF_2_BT601 = 1,
++ E_MATRIX_RGBF_2_BT709 = 2,
++ E_MATRIX_RGBL_2_RGBF = 3,
++ E_MATRIX_RGBL_2_BT601 = 4,
++ E_MATRIX_RGBL_2_BT709 = 5,
++ E_MATRIX_BT601_2_RGBF = 6,
++ E_MATRIX_BT601_2_RGBL = 7,
++ E_MATRIX_BT601_2_BT709 = 8,
++ E_MATRIX_BT709_2_RGBF = 9,
++ E_MATRIX_BT709_2_RGBL = 10,
++ E_MATRIX_BT709_2_BT601 = 11
++};
++
++/** EDID i2c address */
++#define DDC_EDID_ADDRESS 0xA0
++
++/** EDID alternate i2c address */
++#define DDC_EDID_ADDRESS_ALT 0xA2
++
++/** EDID Segment Pointer address */
++#define DDC_SGMT_PTR_ADDRESS 0x60
++
++/** EDID DTD block descriptor size */
++#define EDID_DTD_BLK_SIZE 0x12
++
++/** number of detailed timing descriptor stored in pDis */
++#define NUMBER_DTD_STORED 10
++
++/** MUX_AP audio selection values */
++#define MUX_AP_SELECT_I2S 0xE4
++#define MUX_AP_SELECT_SPDIF 0x27
++
++#define TDA19989_MUX_AP_SELECT_I2S 0x64
++#define TDA19989_MUX_AP_SELECT_SPDIF 0x24
++
++/** VSWING default value */
++#define HDMI_TX_VSWING_VALUE 0x09
++
++
++/**
++ * \brief A structure type to form arrays that hold a series of registers and
++ * values
++ */
++typedef struct _tmHdmiTxRegVal_t
++{
++ UInt16 Reg;
++ UInt8 Val;
++} tmHdmiTxRegVal_t;
++
++/**
++ * \brief A structure type to form arrays that hold a series of registers,
++ * bitfield masks and bitfield values
++ */
++typedef struct _tmHdmiTxRegMaskVal_t
++{
++ UInt16 Reg;
++ UInt8 Mask;
++ UInt8 Val;
++} tmHdmiTxRegMaskVal_t;
++
++/**
++ * \brief A function pointer type to call a function and return a result
++ */
++typedef tmErrorCode_t (FUNC_PTR * ptmHdmiTxFunc_t) (tmUnitSelect_t txUnit);
++
++/**
++ * \brief The structure of a TM998x object, one per device unit
++ ****************************************************************************
++ ** Copy changes to kTestDisNames tab in "HDMI Driver - Register List.xls" **
++ ****************************************************************************
++ */
++
++typedef struct _tmHdmiTxobject_t
++{
++ /** Component State */
++ tmbslTDA9989State_t state;
++
++ /** Count of events ignored by setState() */
++ UInt8 nIgnoredEvents;
++
++ /** Device unit number */
++ tmUnitSelect_t txUnit;
++
++ /** Device I2C slave address */
++ UInt8 uHwAddress;
++
++ /** System function to write to the I2C driver */
++ ptmbslHdmiTxSysFunc_t sysFuncWrite;
++
++ /** System function to read from the I2C driver */
++ ptmbslHdmiTxSysFunc_t sysFuncRead;
++
++ /** System function to read EDID blocks via the I2C driver */
++ ptmbslHdmiTxSysFuncEdid_t sysFuncEdidRead;
++
++ /** System function to run a timer */
++ ptmbslHdmiTxSysFuncTimer_t sysFuncTimer;
++
++ /** Array of registered interrupt handler callback functions */
++ ptmbslHdmiTxCallback_t funcIntCallbacks[HDMITX_CALLBACK_INT_NUM];
++
++ /** Flags to store disable or enable of interrupts */
++ UInt16 InterruptsEnable; /* At moment used only for VS Interrupt */
++
++ /** Device version(s) supported by this component */
++ UInt16 uSupportedVersions[E_DEV_VERSION_LIST_NUM];
++
++ /** Device version read from register, with features flags masked out */
++ UInt16 uDeviceVersion;
++
++ /** Device features flags read from version register */
++ UInt8 uDeviceFeatures;
++
++ /** The device's power state */
++ tmbslHdmiTxPowerState_t ePowerState;
++
++ /*=== E D I D ===*/
++
++ /** EDID Use alternative i2c address flag */
++ Bool bEdidAlternateAddr;
++
++ /** The sink type set by the user (may or may not match EdidSinkType) */
++ tmbslHdmiTxSinkType_t sinkType;
++
++ /** EDID Sink Type for receiver */
++ tmbslHdmiTxSinkType_t EdidSinkType;
++
++ /** EDID AI_Support from HDMI VSDB */
++ Bool EdidSinkAi;
++
++ /** EDID CEA flags from extension block */
++ UInt8 EdidCeaFlags;
++
++ /** EDID CEA flags from colorimetry block */
++ UInt8 EdidCeaXVYCCFlags;
++
++ /** EDID latency information */
++ tmbslHdmiTxEdidLatency_t EdidLatency;
++
++ /** EDID 3D data structure */
++ tmbslHdmiTxEdidExtraVsdbData_t EdidExtraVsdbData;
++
++ /** EDID Read Status */
++ UInt8 EdidStatus;
++
++ /** NB DTD stored in EdidDTD */
++ UInt8 NbDTDStored;
++
++ /** EDID Detailed Timing Descriptor */
++ tmbslHdmiTxEdidDtd_t EdidDTD[NUMBER_DTD_STORED];
++
++ /** EDID First Moniteur descriptor */
++ tmbslHdmiTxEdidFirstMD_t EdidFirstMonitorDescriptor;
++
++ /** EDID Second Moniteur descriptor */
++ tmbslHdmiTxEdidSecondMD_t EdidSecondMonitorDescriptor;
++
++ /** EDID Other Moniteur descriptor */
++ tmbslHdmiTxEdidOtherMD_t EdidOtherMonitorDescriptor;
++
++ /** EDID supported Short Video Descriptors */
++ UInt8 EdidVFmts[HDMI_TX_SVD_MAX_CNT];
++
++ /** Counter for supported short video descriptors */
++ UInt8 EdidSvdCnt;
++
++ /** EDID supported Short Audio Descriptors */
++ tmbslHdmiTxEdidSad_t EdidAFmts[HDMI_TX_SAD_MAX_CNT];
++
++ /** Counter for supported short audio descriptors */
++ UInt8 EdidSadCnt;
++
++ /** EDID block workspace */
++ UInt8 EdidBlock[EDID_BLOCK_SIZE];
++
++ /** EDID Block Count */
++ UInt8 EdidBlockCnt;
++
++ /** CEC Source Address read from EDID as "A.B.C.D" nibbles */
++ UInt16 EdidSourceAddress;
++
++ /** EDID block number which is reading */
++ UInt8 EdidBlockRequested;
++
++ /** EDID read on going*/
++ Bool EdidReadStarted;
++
++ /** Parameter for return edid block requested by application */
++ tmbslHdmiTxEdidToApp_t EdidToApp;
++
++ /** EDID Basic Display Parameters */
++ tmbslHdmiTxEdidBDParam_t EDIDBasicDisplayParam;
++
++#ifdef TMFL_HDCP_SUPPORT
++ /*=== H D C P === */
++
++ Bool HDCPIgnoreEncrypt;
++
++ /** Configured DDC I2C slave address */
++ UInt8 HdcpSlaveAddress;
++
++ /** Configured mode of our transmitter device */
++ tmbslHdmiTxHdcpTxMode_t HdcpTxMode;
++
++ /** Configured HDCP options */
++ tmbslHdmiTxHdcpOptions_t HdcpOptions;
++
++ /** BCAPS read from sink */
++ UInt8 HdcpBcaps;
++
++ /** BSTATUS read from sink */
++ UInt16 HdcpBstatus;
++
++ /** Device value generated for Ri=Ri' comparison */
++ UInt16 HdcpRi;
++
++ /** Device HDCP FSM state */
++ UInt8 HdcpFsmState;
++
++ /** Device failure state that caused T0 interrupt */
++ UInt8 HdcpT0FailState;
++
++ /** Otp Seed key from user*/
++ UInt16 HdcpSeed;
++
++ /* Key Selection Vector for transmitter */
++ UInt8 HdcpAksv[HDMITX_KSV_BYTES_PER_DEVICE];
++
++ /** Local callback scheduled to be called after HdcpFuncRemainingMs */
++ ptmHdmiTxFunc_t HdcpFuncScheduled;
++
++ /** Period in ms after which to call HdcpFuncScheduled; 0=disabled */
++ UInt16 HdcpFuncRemainingMs;
++
++ /** Configured period in ms after which to do HDCP check */
++ UInt16 HdcpCheckIntervalMs;
++
++ /** Period in ms until next HDCP check */
++ UInt16 HdcpCheckRemainingMs;
++
++ /** Number of the HDCP check since HDCP was started; 0=disabled */
++ UInt8 HdcpCheckNum;
++
++ /** Configured number of HDCP checks to do after HDCP is started */
++ UInt8 HdcpChecksToDo;
++#endif /* TMFL_HDCP_SUPPORT */
++
++ /*=== V I D E O ===*/
++
++ /** Current EIA/CEA video input format */
++ tmbslHdmiTxVidFmt_t vinFmt;
++
++ /** Current EIA/CEA video output format */
++ tmbslHdmiTxVidFmt_t voutFmt;
++
++ /** Current pix Rate*/
++ tmbslHdmiTxPixRate_t pixRate;
++
++ /** Video input mode */
++ tmbslHdmiTxVinMode_t vinMode;
++
++ /** Video output mode */
++ tmbslHdmiTxVoutMode_t voutMode;
++
++ /** Vertical output frequency */
++ tmbslHdmiTxVfreq_t voutFreq;
++
++ /** Current scaler mode */
++ tmbslHdmiTxScaMode_t scaMode;
++
++ /** Current upsampler mode */
++ tmbslHdmiTxUpsampleMode_t upsampleMode;
++
++ /** Current pixel repetition count */
++ UInt8 pixelRepeatCount;
++
++ /** Status of hot plug detect pin last read at interrupt */
++ tmbslHdmiTxHotPlug_t hotPlugStatus;
++
++ /** Status of rx sense detect pin last read at interrupt */
++ tmbslHdmiTxRxSense_t rxSenseStatus;
++
++ /** Current register page */
++ UInt8 curRegPage;
++
++ /** Shadow copies of write-only registers with bitfields */
++ UInt8 shadowReg[E_SNUM];
++
++ /** TRUE: Blue screen is the previous test pattern ; FALSE: is not */
++ Bool prevFilterPattern;
++
++ /** TRUE: last screen is test pattern ; FALSE: is not */
++ Bool prevPattern;
++
++ /** TRUE: Unit has been initialized; FALSE: not initialized */
++ Bool bInitialized;
++
++ tmbslHdmiTxVQR_t dviVqr;
++
++ /** TRUE: 3D Frame Packing video is ongoing */
++ Bool h3dFpOn;
++
++} tmHdmiTxobject_t;
++
++/**
++ * \The structure of registers for video format ,
++ * used by PC_formats and chip_unknown formats
++ */
++
++typedef struct _tmHdmiTxVidReg_t
++{
++ UInt16 nPix;
++ UInt16 nLine;
++ UInt8 VsLineStart;
++ UInt16 VsPixStart;
++ UInt8 VsLineEnd;
++ UInt16 VsPixEnd;
++ UInt16 HsStart;
++ UInt16 HsEnd;
++ UInt8 ActiveVideoStart;
++ UInt16 ActiveVideoEnd;
++ UInt16 DeStart;
++ UInt16 DeEnd;
++ UInt16 ActiveSpaceStart;
++ UInt16 ActiveSpaceEnd;
++} tmHdmiTxVidReg_t;
++
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++#include "tmbslTDA9989_local_otp.h"
++
++extern RAM_DAT tmHdmiTxobject_t gHdmiTxInstance[HDMITX_UNITS_MAX];
++extern CONST_DAT UInt8 kPageIndexToPage[E_PAGE_NUM];
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++tmErrorCode_t checkUnitSetDis (tmUnitSelect_t txUnit,
++ tmHdmiTxobject_t **ppDis);
++tmErrorCode_t getHwRegisters (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pData, UInt16 lenData);
++tmErrorCode_t getHwRegister (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pRegValue);
++tmErrorCode_t setHwRegisters (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 *pData, UInt16 lenData);
++tmErrorCode_t setHwRegisterMsbLsb (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt16 regWord);
++
++tmErrorCode_t setHwRegister_main (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 regValue);
++tmErrorCode_t setHwRegisterField (tmHdmiTxobject_t *pDis,
++ UInt16 regShadPageAddr,
++ UInt8 fieldMask, UInt8 fieldValue);
++tmErrorCode_t setHwRegisterFieldTable(tmHdmiTxobject_t *pDis,
++ const tmHdmiTxRegMaskVal_t *pTable);
++tmErrorCode_t getCECHwRegister(tmHdmiTxobject_t *pDis,
++ UInt16 regAddr,
++ UInt8 *pRegValue);
++tmErrorCode_t setCECHwRegister(tmHdmiTxobject_t *pDis,
++ UInt16 regAddr,
++ UInt8 regValue);
++
++tmErrorCode_t lmemcpy (void *pTable1,
++ const void *pTable2,
++ UInt Size);
++tmErrorCode_t lmemset (void *pTable1,
++ const UInt8 value,
++ UInt Size);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMBSLTDA9989_LOCAL_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h
+new file mode 100755
+index 0000000..43cb78d
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmbslTDA9989/src/tmbslTDA9989_local_otp.h
+@@ -0,0 +1,54 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmbslTDA9989_local_otp.h
++ *
++ * \version %version: 1 %
++ *
++*/
++
++#ifndef TMBSLTDA9989_LOCAL_OTP_H
++#define TMBSLTDA9989_LOCAL_OTP_H
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++#define BINARY(d7,d6,d5,d4,d3,d2,d1,d0) \
++ (((d7)<<7)|((d6)<<6)|((d5)<<5)|((d4)<<4)|((d3)<<3)|((d2)<<2)|((d1)<<1)|(d0))
++
++enum _eRegOtp {
++#ifdef TMFL_HDCP_SUPPORT
++ E_REG_P12_CTRL_W = SPA(E_SP12_CTRL , E_PAGE_12, 0x40),
++#ifdef BCAPS_REPEATER
++ E_REG_P12_BCAPS_W = SPA(E_SP12_BCAPS , E_PAGE_12, 0x49),
++#else
++ E_REG_P12_BCAPS_W = SPA(E_SNONE , E_PAGE_12, 0x49),
++#endif /* BCAPS_REPEATER */
++#endif
++ E_REG_P12_TX0_RW = SPA(E_SNONE , E_PAGE_12, 0x97),
++ E_REG_P12_TX3_RW = SPA(E_SNONE , E_PAGE_12, 0x9A),
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ E_REG_P12_TX4_RW = SPA(E_SNONE , E_PAGE_12, 0x9B),
++#endif
++ E_REG_P12_TX33_RW = SPA(E_SNONE , E_PAGE_12, 0xB8),
++};
++
++enum _eMaskRegOtp
++{
++ E_MASKREG_P12_TX33_hdmi = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P12_TX0_sr_hdcp = BINARY(0,0,0,0, 0,0,0,1),
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ E_MASKREG_P12_TX4_pd_rg = BINARY(0,0,0,0, 0,1,0,0),
++ E_MASKREG_P12_TX4_pd_ram = BINARY(0,0,0,0, 0,0,1,0),
++ E_MASKREG_P12_TX4_pd_hdcp = BINARY(0,0,0,0, 0,0,0,1),
++ E_MASKREG_P12_TX4_pd_all = BINARY(0,0,0,0, 0,1,1,1),
++#endif
++};
++
++#endif /* TMBSLTDA9989_LOCAL_OTP_H */
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h
+new file mode 100755
+index 0000000..fac6b7d
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_IW.h
+@@ -0,0 +1,305 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiCEC_IW.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: $
++ *
++ * \brief devlib driver component API for the CEC messages
++ *
++ * \section refs Reference Documents
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiCEC_IW.h $
++ *
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMICEC_IW_H
++#define TMDLHDMICEC_IW_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#else
++#ifdef TMFL_OS_WINDOWS
++#define _WIN32_WINNT 0x0500
++#include "windows.h"
++#else
++#include "RTL.h"
++#endif
++#endif
++
++#include "tmNxTypes.h"
++#include "tmdlHdmiCEC_Types.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++/*============================================================================*/
++/* TYPE DEFINITIONS */
++/*============================================================================*/
++typedef void (*tmdlHdmiTxIWFuncPtr_t) (void);
++typedef UInt8 tmdlHdmiTxIWTaskHandle_t;
++typedef UInt8 tmdlHdmiTxIWQueueHandle_t;
++#ifdef TMFL_OS_WINDOWS
++typedef HANDLE tmdlHdmiTxIWSemHandle_t;
++#else
++typedef UInt8 tmdlHdmiTxIWSemHandle_t;
++#endif
++
++/**
++ * \brief Enum listing all available devices for enable/disable interrupts
++ */
++typedef enum
++{
++ TMDL_HDMI_IW_RX_1,
++ TMDL_HDMI_IW_RX_2,
++ TMDL_HDMI_IW_TX_1,
++ TMDL_HDMI_IW_TX_2,
++ TMDL_HDMI_IW_CEC_1,
++ TMDL_HDMI_IW_CEC_2
++} tmdlHdmiIWDeviceInterrupt_t;
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/**
++ \brief This function creates a task and allocates all the necessary
++ resources. Note that creating a task do not start it automatically,
++ an explicit call to IWTaskStart must be made.
++
++ \param pFunc Pointer to the function that will be executed in the task context.
++ \param Priority Priority of the task. The minimum priority is 0, the maximum is 255.
++ \param StackSize Size of the stack to allocate for this task.
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskCreate(tmdlHdmiTxIWFuncPtr_t pFunc,UInt8 priority, UInt16 stackSize, tmdlHdmiTxIWTaskHandle_t *pHandle);
++
++/*============================================================================*/
++
++/**
++ \brief This function destroys an existing task and frees resources used by it.
++
++ \param Handle Handle of the task to be destroyed, as returned by IWTaskCreate.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskDestroy(tmdlHdmiTxIWTaskHandle_t handle);
++
++/*============================================================================*/
++
++/**
++ \brief This function start an existing task.
++
++ \param Handle Handle of the task to be started.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_ALREADY_STARTED: the function is already started
++ - TMDL_ERR_DLHDMIRX_NOT_STARTED: the function is not started
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskStart(tmdlHdmiTxIWTaskHandle_t handle);
++
++/*============================================================================*/
++
++/**
++ \brief This function blocks the current task for the specified amount time. This is a passive wait.
++
++ \param Duration Duration of the task blocking in milliseconds.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWWait(UInt16 duration);
++
++/*============================================================================*/
++
++/**
++ \brief This function creates a message queue.
++
++ \param QueueSize Maximum number of messages in the message queue.
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueCreate(UInt8 queueSize, tmdlHdmiTxIWQueueHandle_t *pHandle);
++
++/*============================================================================*/
++
++/**
++ \brief This function destroys an existing message queue.
++
++ \param Handle Handle of the queue to be destroyed.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueDestroy(tmdlHdmiTxIWQueueHandle_t handle);
++
++/*============================================================================*/
++
++/**
++ \brief This function sends a message into the specified message queue.
++
++ \param Handle Handle of the queue that will receive the message.
++ \param Message Message to be sent.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMIRX_FULL: the queue is full
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueSend(tmdlHdmiTxIWQueueHandle_t handle, UInt8 message);
++
++/*============================================================================*/
++
++/**
++ \brief This function reads a message from the specified message queue.
++
++ \param Handle Handle of the queue from which to read the message.
++ \param pMessage Pointer to the message buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMIRX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueReceive(tmdlHdmiTxIWQueueHandle_t handle, UInt8 *pMessage);
++
++/*============================================================================*/
++
++/**
++ \brief This function creates a semaphore.
++
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMIRX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate(tmdlHdmiTxIWSemHandle_t *pHandle);
++
++/*============================================================================*/
++
++/**
++ \brief This function destroys an existing semaphore.
++
++ \param Handle Handle of the semaphore to be destroyed.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy(tmdlHdmiTxIWSemHandle_t handle);
++
++/*============================================================================*/
++
++/**
++ \brief This function acquires the specified semaphore.
++
++ \param Handle Handle of the semaphore to be acquired.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreP(tmdlHdmiTxIWSemHandle_t handle);
++
++/*============================================================================*/
++
++/**
++ \brief This function releases the specified semaphore.
++
++ \param Handle Handle of the semaphore to be released.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMIRX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreV(tmdlHdmiTxIWSemHandle_t handle);
++
++/******************************************************************************
++ \brief This function disables the interrupts for a specific device.
++
++ \param
++
++ \return The call result:
++ - TM_OK: the call was successful
++
++******************************************************************************/
++void tmdlHdmiTxIWDisableInterrupts(tmdlHdmiIWDeviceInterrupt_t device);
++
++/******************************************************************************
++ \brief This function enables the interrupts for a specific device.
++
++ \param
++
++ \return The call result:
++ - TM_OK: the call was successful
++
++******************************************************************************/
++void tmdlHdmiTxIWEnableInterrupts(tmdlHdmiIWDeviceInterrupt_t device);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMICEC_IW_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c
+new file mode 100755
+index 0000000..a775288
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_Linux.c
+@@ -0,0 +1,436 @@
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++
++#include "tmdlHdmiCEC_IW.h"
++#include "tmNxTypes.h"
++#include "tmdlHdmiCEC.h"
++#include "tmdlHdmiCEC_cfg.h"
++
++struct i2c_client *GetThisI2cClient(void);
++unsigned char my_i2c_data[255];
++
++/*============================================================================*/
++/* MACROS */
++/*============================================================================*/
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++#define I2C_M_WR 0
++
++/*============================================================================*/
++/* FUNCTIONS DECLARATIONS */
++/*============================================================================*/
++
++
++tmErrorCode_t I2cReadFunction(tmdlHdmiCecSysArgs_t *pSysArgs);
++tmErrorCode_t I2cWriteFunction(tmdlHdmiCecSysArgs_t *pSysArgs);
++
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++
++#define COMMAND_TASK_PRIORITY_0 250
++#define COMMAND_TASK_STACKSIZE_0 128
++#define COMMAND_TASK_QUEUESIZE_0 8
++
++/* I2C adress of the unit */
++#ifdef TMFL_TDA9996
++ #define UNIT_I2C_ADDRESS_0 0x60 /* I2C Address of TDA9950 */
++#else
++ #define UNIT_I2C_ADDRESS_0 0x34 /* I2C Address of TDA9950 */
++#endif
++
++
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++
++tmdlHdmiCecCapabilities_t CeccapabilitiesList = {TMDL_HDMICEC_DEVICE_UNKNOWN, CEC_VERSION_1_3a};
++
++tmdlHdmiCecDriverConfigTable_t CecdriverConfigTable[MAX_UNITS] = {
++ {
++ COMMAND_TASK_PRIORITY_0,
++ COMMAND_TASK_STACKSIZE_0,
++ COMMAND_TASK_QUEUESIZE_0,
++ UNIT_I2C_ADDRESS_0,
++ I2cReadFunction,
++ I2cWriteFunction,
++ &CeccapabilitiesList
++ }
++};
++
++
++int blockwrite_reg(struct i2c_client *client,
++ u8 reg, u16 alength, u8 *val, u16 *out_len)
++{
++ int err = 0,i,initiator,receiver;
++ struct i2c_msg msg[1];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = alength+1;
++ msg->buf = my_i2c_data;
++
++ msg->buf[0] = reg;
++ for (i=0; i<alength; i++) {
++ msg->buf[i+1] = val[i];
++/* printk(KERN_INFO "buf[%d]=%d val[%d]=%d\n",i+1,msg->buf[i+1],i,val[i]); */
++ }
++
++ err = i2c_transfer(client->adapter, msg, 1);
++ udelay(50);
++
++ if (reg==7) {
++ /* CEC message */
++ extern char *cec_opcode(int op);
++ initiator = (msg->buf[3] >> 4) & 0x0f;
++ receiver = msg->buf[3] & 0x0f;
++/* printk(KERN_INFO "reg:%d alength:%d \n",reg, alength); */
++ if (alength==3) {
++ printk(KERN_INFO "hdmicec:polling:[%x--->%x] \n", initiator,receiver);
++ }
++ else {
++ printk(KERN_INFO "hdmicec:Tx:[%x--->%x] %s %02x%02x%02x%02x\n", \
++ initiator,receiver,cec_opcode(msg->buf[4]),msg->buf[4],msg->buf[5],msg->buf[6],msg->buf[7]);
++ }
++ }
++/* dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " */
++/* "*val=%d flags=%d byte[%d] err=%d\n", */
++/* __func__, data[0], data[1], msg->flags, i, err); */
++ return (err < 0?err:0);
++
++#if 0
++ int err = 0, i;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 2;
++ msg->buf = data;
++
++ /* high byte goes out first */
++ data[0] = reg >> 8;
++
++ for (i = 0; i < alength - 1; i++) {
++ data[1] = val[i];
++ err = i2c_transfer(client->adapter, msg, 1);
++ udelay(50);
++ dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, "
++ "*val=%d flags=%d byte[%d] err=%d\n",
++ __func__, data[0], data[1], msg->flags, i, err);
++ if (err < 0)
++ break;
++ }
++ /* set the number of bytes written*/
++ *out_len = i;
++
++ if (err < 0) {
++ dev_err(&client->dev, "<%s> ERROR: i2c Block Write at 0x%x, "
++ "*val=%d flags=%d bytes written=%d "
++ "err=%d\n",
++ __func__, data[0], data[1], msg->flags, i, err);
++ return err;
++ }
++ return 0;
++#endif
++}
++
++int blockread_reg(struct i2c_client *client, u16 data_length,
++ u8 reg, u16 alength, u8 *val, u16 *out_len)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 1;
++ msg->buf = data;
++ data[0] = reg; /* High byte goes out first */
++ err = i2c_transfer(client->adapter, msg, 1);
++ if (err<0) goto BLOCK_READ_OUPS;
++
++ msg->flags = I2C_M_RD;
++ msg->len = alength;
++ msg->buf = val;
++ err = i2c_transfer(client->adapter, msg, 1);
++ if (err<0) goto BLOCK_READ_OUPS;
++
++/* printk(KERN_INFO "DBG blockread_reg addr:%x len:%d buf:%02x%02x%02x%02x\n",msg->addr,msg->len,\ */
++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3]); */
++
++ return 0;
++
++ BLOCK_READ_OUPS:
++/* printk(KERN_INFO "DBG blockread_reg addr:%x len:%d ERROR\n",msg->addr,msg->len); */
++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
++ "*val=%d flags=%d bytes err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++ return err;
++
++#if 0
++ int err = 0, i;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 1;
++ msg->buf = data;
++
++ /* High byte goes out first */
++ data[0] = reg;
++
++ for (i = 0; i < alength; i++) {
++ err = i2c_transfer(client->adapter, msg, 1);
++ dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, "
++ "*val=%d flags=%d err=%d\n",
++ __func__, data[0], data[1], msg->flags, err);
++ if (err >= 0) {
++ mdelay(3);
++ msg->flags = I2C_M_RD;
++ msg->len = data_length;
++ err = i2c_transfer(client->adapter, msg, 1);
++ } else
++ break;
++ if (err >= 0) {
++ val[i] = 0;
++ /* High byte comes first */
++ if (data_length == 1)
++ val[i] = data[0];
++ else if (data_length == 2)
++ val[i] = data[1] + (data[0] << 8);
++ dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, "
++ "*val=%d flags=%d byte=%d "
++ "err=%d\n",
++ __func__, reg, val[i], msg->flags, i, err);
++ } else
++ break;
++ }
++ *out_len = i;
++ dev_info(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n",
++ __func__, reg, *out_len);
++
++ if (err < 0) {
++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
++ "*val=%d flags=%d bytes read=%d err=%d\n",
++ __func__, reg, *val, msg->flags, i, err);
++ return err;
++ }
++ return 0;
++#endif
++}
++
++
++int write_reg(struct i2c_client *client, u8 reg, u8 val)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++ int retries = 0;
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ retry:
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 2;
++ msg->buf = data;
++
++ data[0] = reg;
++ data[1] = val;
++
++ err = i2c_transfer(client->adapter, msg, 1);
++ dev_dbg(&client->dev, "<%s> i2c write at=%x "
++ "val=%x flags=%d err=%d\n",
++ __func__, data[0], data[1], msg->flags, err);
++ udelay(50);
++
++/* printk(KERN_INFO "DBG write_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */
++ if (err >= 0)
++ return 0;
++
++ dev_err(&client->dev, "<%s> ERROR: i2c write at=%x "
++ "val=%x flags=%d err=%d\n",
++ __func__, data[0], data[1], msg->flags, err);
++ if (retries <= 5) {
++ dev_info(&client->dev, "Retrying I2C... %d\n", retries);
++ retries++;
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(msecs_to_jiffies(20));
++ goto retry;
++ }
++
++ return err;
++}
++
++int read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 1;
++ msg->buf = data;
++
++ data[0] = reg;
++ err = i2c_transfer(client->adapter, msg, 1);
++ dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d "
++ "flags=%d err=%d\n",
++ __func__, reg, data[1], msg->flags, err);
++
++ if (err >= 0) {
++ mdelay(3);
++ msg->flags = I2C_M_RD;
++ msg->len = data_length;
++ err = i2c_transfer(client->adapter, msg, 1);
++ }
++
++ if (err >= 0) {
++ *val = 0;
++ if (data_length == 1)
++ *val = data[0];
++ else if (data_length == 2)
++ *val = data[1] + (data[0] << 8);
++ dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d "
++ "flags=%d err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++ return 0;
++ }
++
++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
++ "*val=%d flags=%d err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++ return err;
++}
++
++
++tmErrorCode_t I2cReadFunction (tmdlHdmiCecSysArgs_t *pSysArgs)
++{
++ tmErrorCode_t errCode = TM_OK;
++ u16 outLenght=0;
++ struct i2c_client *client=GetThisI2cClient();
++ u32 client_main_addr=client->addr;
++
++ /* DevLib needs address control, so let it be */
++ client->addr=pSysArgs->slaveAddr;
++
++ if (pSysArgs->lenData == 1) {
++ /* single byte */
++ errCode = read_reg(GetThisI2cClient(),1,pSysArgs->firstRegister,pSysArgs->pData);
++ }
++ else {
++ /* block */
++ errCode = blockread_reg(GetThisI2cClient(),1, \
++ pSysArgs->firstRegister, \
++ pSysArgs->lenData, \
++ pSysArgs->pData, &outLenght);
++ }
++
++ /* restore default client address */
++ client->addr=client_main_addr;
++
++ return errCode;
++}
++
++
++tmErrorCode_t I2cWriteFunction(tmdlHdmiCecSysArgs_t *pSysArgs)
++{
++
++ tmErrorCode_t errCode = TM_OK;
++ u16 outLenght=0;
++ struct i2c_client *client=GetThisI2cClient();
++ u32 client_main_addr=client->addr;
++
++ /* DevLib needs address control, so let it be */
++ client->addr=pSysArgs->slaveAddr;
++
++ if (pSysArgs->lenData == 1) {
++ /* single byte */
++ errCode = write_reg(GetThisI2cClient(),pSysArgs->firstRegister,*pSysArgs->pData);
++ }
++ else {
++ /* block */
++ errCode = blockwrite_reg(GetThisI2cClient(), \
++ pSysArgs->firstRegister, \
++ pSysArgs->lenData, \
++ pSysArgs->pData,&outLenght);
++ }
++
++ /* restore default client address */
++ client->addr=client_main_addr;
++
++ return errCode;
++
++}
++
++tmErrorCode_t tmdlHdmiTxIWWait
++(
++ UInt16 duration
++)
++{
++
++ mdelay((unsigned long)duration);
++
++ return(TM_OK);
++}
++
++tmErrorCode_t tmdlHdmiCecCfgGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiCecDriverConfigTable_t *pConfig
++)
++{
++ /* check if unit number is in range */
++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER)
++
++ /* check if pointer is Null */
++ RETIF(pConfig == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ *pConfig = CecdriverConfigTable[unit];
++
++ return(TM_OK);
++};
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h
+new file mode 100755
+index 0000000..ecf98d7
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/cfg/tmdlHdmiCEC_cfg.h
+@@ -0,0 +1,107 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiCEC_cfg.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: $
++ *
++ * \brief devlib driver component API for the CEC messages
++ *
++ * \section refs Reference Documents
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++ *
++ $History: tmdlHdmiCEC_cfg.h
++ *
++ *
++ \endverbatim
++ *
++*/
++/******************************************************************************
++******************************************************************************
++* THIS FILE MUST NOT BE MODIFIED BY CUSTOMER *
++******************************************************************************
++*****************************************************************************/
++
++#ifndef TMDLHDMICEC_CFG_H
++#define TMDLHDMICEC_CFG_H
++
++#include "tmNxTypes.h"
++#include "tmdlHdmiCEC_Types.h"
++#include "tmdlHdmiCEC_Functions.h"
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Number of HW units supported by SW driver */
++#define MAX_UNITS 1
++
++
++#ifndef TMFL_CEC_AVAILABLE
++typedef struct _tmbslHdmiTxSysArgs_t
++{
++ UInt8 slaveAddr;
++ UInt8 firstRegister;
++ UInt8 lenData;
++ UInt8 *pData;
++} tmbslHdmiTxSysArgs_t;
++#endif
++
++
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++typedef struct
++{
++ UInt8 commandTaskPriority;
++ UInt8 commandTaskStackSize;
++ UInt8 commandTaskQueueSize;
++ UInt8 i2cAddress;
++ ptmdlHdmiCecSysFunc_t i2cReadFunction;
++ ptmdlHdmiCecSysFunc_t i2cWriteFunction;
++ tmdlHdmiCecCapabilities_t *pCapabilitiesList;
++} tmdlHdmiCecDriverConfigTable_t;
++
++/*============================================================================*/
++/* FUNCTIONS DECLARATIONS */
++/*============================================================================*/
++
++/**
++ \brief This function allows to the main driver to retrieve its
++ configuration parameters.
++
++ \param pConfig Pointer to the config structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiCecCfgGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiCecDriverConfigTable_t *pConfig
++);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMICEC_CFG_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip b/drivers/video/nxp/comps/tmdlHdmiCEC/docs/02_sw_req_an/tmdlHdmiCEC_API.zip
+new file mode 100755
+index 0000000000000000000000000000000000000000..0e96788c87aec8afb3a0753fe2ce8f6a6673791e
+GIT binary patch
+literal 148480
+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
+z7kW%K@%5|0Qtov)c!y#iwd@2W%Ps49Pb#Tl%0D#Zy&C<x^T5Zp)em10p~DBzYJ%X9
+zEKPG^C=Pkyp~F*Hl_1ga2!`R10rAEvv5$yKc4X)IHZsVeRm%i$Ay~+v7tI844QiZd
+z5-PI)cOL|B)|Omo^DQ=HD#&(Z|8)L1%^R)zz~LI9-tR6;{Y9%U{)>k4<V?yRfPrP*
+z@C8O(RQb2*C611s!U7NRfIT*hw+P9cTm^qzOu`zERK_5W!<!E+qEA;(Prsztpg|0&
+zv&tg!!UvhWxlt4@DFj(8l9n5eyk=A6>-$o(Lqt<18EG}I$HMsW6nO}XNSE1YM#{d!
+zV0&=*uwnIbueRNz`@-dC&tAO~sS|F`)4)~=hXLAw$J^@7z&%)BPt$)^WzUyatJ91&
+zwJ0?|8JT%JwST>F3Gdf6;P#Y(ubu2YKpX$yenQ8G-B+7klm0ZkT9IKz@)0M9DrkG8
+zmBaQ_vkh_~e}tJ1qbH`trKeJ1*4Py3QlSfSDJq9N5i^B25lcf(MNFenK`E7{xo^c8
+z;J5I(VeZhDPen~dETj3I+^<)P-Uc<<x^}SdAe^goL9BRx_-rEj2zJYfibhlFjkJc^
+z#+C3hxc4o4qQ##$;Z~{zI$XVBUgrwg0#?I8a%L{()3V3rS?zVqR(Q@Go&7hRyt_ny
+zRK5@Ygw8pm<%HN7tpLu?zJ3Wa$)rgGRY0^hR#a&;g=%N93_uf0RzfmKLKACh7+aEE
+zT@rl}KJfkMUrtZ^Ui(kR&;9|iNwc6`6KYC1ES3=4Ap2~k7MYYnTWez+I4pgoQ2uu5
+z_U$={kNpgusZu|IbY25O+8rG%RLP_>0m1dGAR4pb$jNe63c~!!a_6EtoSzsu$BF>0
+zsT>(UiK!eo2r4HExWwLzbu&}oS{%;)V|C=H{j6mW3MK<z?eS;sW*>E8Nc6@i<)hI_
+zc>aJA%z~M^a)xU~L#w#4_Dex=65gi;Z-6`hHp?2iOzXn+cfmlGtW6&7RhO-x$4x$b
+zpwGZH0@T}Fy@-mn=Hcqx*v;J6>ety!&H}3ES;4&U-an!fOicNj(<U8SBgZ6plk8C!
+ziqJG~KI6*J%9<WgBo_GDI}Bx{1;uYl56c!fJE;sjsS1um_-aMOo6Nn>DgyjRGTBt`
+zM1Zsf2>^alP-Yo#zMon#Qtz9IWuo~U2srI#J5KAa?W<q5<v@<)Iu+DYnwI2btT7{F
+zV9}J*r_q~Y*JwFg?;1rBpT5|ptWfZGnZ_EVBeyKHG9K+UP{=6Oj8S*=A$7snwT5V%
+zZKat}5Nes_WSkl8)1iiGQXtB-G*f28?9eTbSMMX9(&TH{q~^BAv}@PR5mnN*(>APo
+zqgwmKAjKRQWevz89%O-iWBkQ9aZ;RWghDy@-(k!7@V8-f$m3Y68mxbnOnVgg>uF<U
+z8)V#|h10)TO5fS;Mrm*R?Qsh5Ax=O@ql~qbzQM9LV$K=dAVo_)Bm3hlMT-$%PyddA
+ze?aHk!~LI(0#3FzPR}YBIKEM_I#fS~vJhR^ZtC++jsCTod{q@k<>Vhb`F~x?G|YQH
+z8Lfpp$7v@0F)=w(=T%n9#L>=WyUOFqp^6P@0JR=@Xv$kpwa5zGsFgpXY})wA1tDMq
+zu_1dZkeiI_VEC`EejkV?Q*&vO!D)gdR7{T+8eA=c7Tr^lcVbK3HKVoBGG&?AJv=?!
+z1O80WLvx7wO#6i78>m7g29DwpZOcPS2gF~P)#dVc(|8FT`^6jG{G}ul`h>_wIqNiu
+zZ_3LW-F%%OrYaR&Ok3iwlG-##JME>7b&`mI85+UFCfZqmff;)(wv@mX>tbjU>}=m^
+zmb`x6O6dsb*a4eH8Em-=oVhxpTAz>)P?(TM;Wt{wbMEcU!^U(?Pes(S{Vx?<)Up+=
+z_n$tWM)`$%&Au6MCHVD%N2;^s+)8i4Vdf6V1tz|?ygDV{);?bjjn=JQE%8JazWll>
+z;hIB}6*ZyK3frB!uQ3}Q;?AkmXDS>v%0?Xg<z{D-vI~QT$7)x*@9-#VlqQE+dHTn<
+z%2|Uvs)fSdg;mSQ^>13!?rjJ-Nz4nxuV}M||CG@Y5WlggexbdpW4&s~sjjQjNq(7s
+zFv13H)i;!+S5uJo%W;gl+$LU=6GUZvet%wemsc2p9v6~o4uJ+cX!2{Co(ntWn~_-h
+zY1n(-I=V@+s~%`5d331H*8W0dMo#r3+6y%*fjTdb$;mN?=hwjZ@=3l;Eh)E9q*gu*
+zw}qN<xB?Gs0v23srBobv3O9@b&B?qiBw=+NdS+$2@v?cdv0CO=a=A)SRatzXoDw%3
+zm=ULo7R}TYHOyf2IQ^EaOLLUy!)X1KF5NSYwP>{`F~AypHXlo^&#or7O-&#On#n|F
+zOG%VLNQUL_Sh8#@(B_Nl@GHO>>qXv1q-j4C2CE`Sk|*{b?Gmyz$S8D2J7&V*?y@4%
+zb(@mNxLxI!G^L!wC@gkLf_!09&UyRl>~*9gJ_<v(WftjDTwRo7TXvk4#Ec{UE>q7}
+zAwg4IH*eSUs->fa00zTmd?97>O?$S9;ih9n-Rh(V?$Jf>BH`e*y>w#>5Ai*11KR!r
+zLZKrb6_|HfR=DC4x`#1X81h9`V^KafHx_h!MB(7Han2DrtzyWyxJtC|sJMy>D+w}D
+zth7J$Q5Rh_)_Ub;eN<lw|8xDEhy2yxY^-bnyXA7lb)>?3Y7j`^3hyuDrNZjVF<#$c
+zW;IOA4EnW7`PNG}af&d5WbP9owp3b2_CO58lVHpEu_gEZ+_`Z}woh`s`QKITdP>x4
+zlfcQT-<RByfd&ln)C)|}Po_#jmC^ZjBwAyZt$lHHCEu)2W>7+K;v3&S3s`6)(&TJ@
+zb7GOt<j8=L;_QFETu+{B*_ck&MvS@hYJ+zlVfU&Frhc4Wc%(Pj<I>(HM}jAYagU7Q
+zcxSpqYrG3)!sFhz)NSYrZ}pqhFg-f8OplD?J&jketEFpj4L;~`S^~;#Yy_q_3~{V6
+z2{M$kW{FanMUaB6J&;5pI;edRL?M}|9}q<1-?3*%-rV^dt@~c{Xnb(J&xN?439b7)
+zWaIes4LuX32BbT(FC}Bfd*636+4B`#`S;v@9gGd?`Q&=;pKE=MI=Jp+kZai6wI~+)
+zElT{Egv;rb=RburW42I!US;Nt6S%6k!n+zSa!viGSLh4;iL^QmP&KWRD;{2^1T|_Z
+z7})7*uU%@jHL7o=?3Nc~ui>P}F_M};m~qEG?U4!W&A`yx=mU(?)8?}uZaaEt8(<br
+ziWj+ifP6T-ba0YgujCnC1`L|1)W%`W-2ia0>NP$+9#IO!BAe)>f&VnZU(VJnd7q+7
+z@gQZM<@Ki<_gl-5B9!!}oeMzbaWFGu%#e*Gg!jCWu{H!{=9Bl_nWs&zkAoR&zvd@k
+zrJkR0#^W#&s8%q;?$10Ee_@b5G;axj0Uvcay-ojfa;Qt?=O$XBo9|HANC&}NF6;iC
+zxiB*nT`6y85Wqx{(nrmHVRx*xSV5Cx0wIXG<(K3o_!E7fh8cqQC;FkP;Ut+<eU=`L
+zcFK}lk9Pd*SbD~#2$SxoL0#=?brT%~in)-Y>1+#K>=Q?ryUAY_`3?S(KaS8>Zk^x+
+zL+wP4HaG-#bQh4XsW4n@?9)D(c=(n5c!&nZvEJ1zpf~NA4LX|0Z{^K+D`{gMIHPXy
+zN!^PZ^Ul=~5e}o;=$b8cif#(4(GB#)<wp1`PtzN0s|@CiK9)#o4GQ!jIelB>@Pyf5
+z?Hs489^)eI9AJ3$J(crM%?7G+sP~GyNTo!izhN~h4|E3{J*Rkb!HnpjTQ4%UvwseB
+z)p--ajzN=@kaP|n0az~|cyEHb1;@!H2}rDkBnbMsvKL_tNmdFAXUtDw-PRw}9fl1_
+zT*G>Z#$XSarD+9kT`YhSuB9NkNpKbOL99le!l_Wcn}4^pi$qgCo2O|vEV(lCw%(s%
+zz1V2hZlJBYv~QH5pC(ocXokMub4`~WxEC%wW6&cG$!f2G_AOV8x;*P8m~O4(<_jdM
+zy)3Dsu_gIW4tD?es0(4dvc_zo+zLujy^LCi9~DjnZlanntwgKf$Yq(=XuV1NNZVU2
+zA1fq`AX*a5OjrZwp@+r#*<mt=KZGVqI1O|Tb`Q!u6y%l#36)?z8rWDs*M!$0&kLTi
+zmrW<=+(75NXSH-c-T`k<2PwM^b-P;bszxq;udNCxSY?43wm$;~##i@W{fz0+H8Kr2
+zJx-AVY|10un2)~`1lT-V68u$W4y&zN+kPhjC(QC6{1F1;<E+^xrdu+PC?6P4@s4$8
+z*#=u))$ak&zv=1wW!+L^KG;b8@(Lt7+<SpvIR@%!w#-ek|BXCcY?fz;g30}L3GlSE
+zh$wgZU=-B2^1A0&cU1K;!T4}c1Ebn?W7VmLxh$pCpL$wekY5Vm6!67^2bJe48#w^M
+zbgfkTCmDhCI$dfXPSj}1)1X!BM0jJfqyTZoSQDA~X9f+gQ}v?Z7N}I%x!U9>fX%7c
+zqcg);bP$Zt2lv<r7DEZ}T@CT47@GSy3Yt=L0E}Dy8&}~YV=H)`wLj9iAfo<DO3Dv+
+zVef+3s)0OX<33-s$B#{g1`nh*dl5=&BX~jYxo*02Oc@0l8dGzAzI)7-sa-}O*Z8V^
+z>Aci*RQ#XgP?GX6GW!UeVf-Cy@c+lyJH|&6F73myZQI^(f=#mV#I|kQww;YO*x0ts
+zjcwc3n{&?d<^A^m)>U;?&HVbVzNfmo<|@O*p4s_@pY!C2)B4KDGv`(x<zyy(V%#bQ
+z1zAK2%QVG*Y81NWwx6qK3LmC)u)UfkCiM!sR|vs{i#Jd1+{TT1F3r1DvXyojmy?wI
+zWj1`SIozOo(NaU^sKNP!1<JY2d@B#LLR<|FE8^hU%nZOKxX;i9$8hyk*y34#L#m3g
+z$&Hz>A}u>`sl<R!m=}0-Fq?-t%_lq<St1|a_7MUn-wPUlYiBL3npHJUzo$1$6BPMu
+z;yN@VgYsiWoi3QX6Kt<}-!O35l`}=@I~dAM>y5pvr-T9gy&Ny$L1zI_`+i*>%5g*+
+zfPO!hww261jfRtyJ&pCNZ>E=H<S>)hK*PoClc;u}L=p4x%%!y6`XmTF*!E-65KYNi
+z+@GV-i?GIwu2s?BOYn4Kd*a^3UhbXdf#mJ(`75!fk&gqYUkN#Y-Kf**y&EvBpa6H!
+z;v3oWSsp82IxIuQ>bsZSf+}+>Hq#mWz!Cz?;e@lLo-E}onTEwHSE?-+8-P-y=U`M5
+zEeHgle-B%6!3^$d^=ILm+sM?v+M#LcFV%F7@I_@MR#_F!aQ-S}5^x0nd!tp@hw%n<
+ztlt*Y9msRCdo|L$qCV-azt8nhE#M4RX_3Yol;rU6eQ#Z38s`~!DSw+3-^UX?E?%yu
+z_ic9B7G5cNNzq46T)!mKL&X_=gv5qV??DV4IlxtvZkEi-P>B5)B_1BL@=K{vSu-AJ
+zvZ5b^B(wu|is<<!c}5_Oe)@!#3efr$=MCTgJyP^$YRt1LGg~)BPQN04yyS6z10@&s
+z1tpgf0vAht1dT?3M%+e$sJ8_r*p&tQ6&M{V8aNR*1vO}!nj+PRJHJ_SL$Zg5Ji>YO
+zOFWW#gM;%DC=}Bx7_!<>_B22O0mNiS@fP_f$cn;_GK-2AdhkwSO)^i+iE@aG592>N
+zyG+a}KM#q2pS-s24`w{PftCKTEm*5(4@0;>Nt4LGEoh-{4-)EPgGVRP+z)o<$`|6C
+zw=4sFD|-b6O_;85ZH;*1_|L$MM9t1wzcDA=;wS2yCz-3XCmGZn`pvU^{6E8r+nYqB
+z_0whp1uxMEfx<{*mK>xmF)L`p*mqJ$IX-eoXqtEcKZ9D>=Xn4E(zP>DiE&v_^%GBJ
+zGwoiZ&2P{nQrR~HXfxm1AZS-tS%vlf6^(U5PF8J{a~xcz%ixl9c>>kJ;N1yyR|<S2
+zENuEiV-Scz&5dBgwoqbD=RfH#B1oaDt#M};me>6o{gJ7z;F73{cr?NBpFBj>#y@bv
+z)#}Vcks;B@?_5FAf?4eZ15s|^DPS%TjWKP~{YZYnkWu7QRK$m)=?NLO0VS+2oEry|
+zjL)#t(v<4Y&?=g=5(#HqrC`k4DI4Z?bc;Q65Fk(aFq87ppuJkh7b`4ixSt6=v!-P(
+z$T4l7K3db4ea;m3Sshg^?oAH4GS`Xj(@H)Sk;3-+U{RzM@UFJ3PJUHgcs(vpjgYq!
+zl9aEVoa=Or6iliP<#pV*5X1~jyLRJ95R)j!Mn&NExcu<&RCSzE*^O`Vq7WSWppZ&_
+zO<_>L)2<unq>zdZTm_)YdM*P{p<vShHTDrcuxTv^F08nks?w00>L(y5o8+p7ro7oD
+zahsp7bk)^x79xHVhskR7%OI*n2mMW`hgLVQKAMOo<_n{12gbVmGQU^Ncr}r7?#e6{
+z9DM6sb^TZA^(Ln|xd<K#1CwOM3p{FBrc*sVO^i1b%+KO~qjH0neJM^Yn>uSMkFb9H
+z-SSw&VoNfiDozBKDNkzlV-gn*=tD*hT5;!2`>KFkMap%s<3Ri>*SyUZDQw}Z<FOTQ
+zvp!en5P5rxag}5g$fl!eh*arpefD<oa{9U^b>tKP&RZv3Ku2&92{4^hdLOZ`-n4dj
+zU~hEAZR+XhiN(iBvAqfK6|2X0zf<Vux%c<qW`^z`(fv;QqTS5;gHHMZTSPLXDDmU_
+z4N0zYPzaA-Yg+!*f&I-p)ZmStGyO)L=0~0%PMg3nTRp6yIqI9qCmG0b<$C-~bABRI
+z+su)lz&0D{*(c5i-GMx27p<Qz){MX{kfLhf{fOd?dn#X~jp37~GfZz{2-|Rf+?q#0
+zEcvdTzE+Y0vbOgDMl<N6^ylhiKeJv=z6Xc9(=EFPj$Ce$ncRWI)cWq^=tfxiS$X@L
+zDN(s%xD@qF!S-L#heHZ})Rx!IF|&4<sO|}d$gj~1KYHDjJ?Ce-Zpu5)x8g6*|36><
+zoN57jmN*EA=`|<_=l>I5zp{tD$^Ro)|C`euXX2;N7hHu>TIA6XXD=6*k=hIzM?nmc
+zu4EINmfGKZ%CW;(X-lBx(A44QQ-4r0FcLXlp0#*vAW;T{81KV{%OC1~ht_vf`vcM+
+zS+1(S&+gyaaunC4%6rGEx8_f;pXJTz-L@OY@30erIxWt<J!>u72!E(^lBj!F-8Z4S
+z&W1tKxrDEG0#$|R*WEv{uQA%r#*?V;-(OfGWd)CIndI`HUG~J}s_=9DaX1`3(At@A
+zAbqz_nTeTbN|2FzPcc89&sK1sk6&$%2QK0GIs$#KZ(omJL2{yw<RQ(>j`Jw{wnL9&
+zz*F(5BbnqrFJ9=M4k$nc`Lp(HbG2g#r=hu~3f^}5TEPTfk!K#w<W>INe2@$=Qir_B
+zp8IPMT&CVIIg_W-ElSubC}xe=?~DFW>do$s?(B)Hvq9!_t2eZKazN(;WHwxjztXB*
+z8!|T)U!V4)GvNEM6I{b_{5qT97tB>Zma~8d4WIFoV^W74-(V|S?LGcgBi4OS=6_%x
+zyY^Lc+f@|5ly?_S{Im77262NPw3Fny1}R>WQjUbM09jjGo9OOg2dvrg0eihreTCu}
+za&76Kmv>~ZT&EHVTp$!x_on~o%f^eBzAb0ZkYBX_g_!L#<_WM#x3q1O8w)6s(TJeR
+zWdDx&`XmWButA#%(LV^?RJ%VZj}paillWail6uRD(3E#HB>Vi^Mybkn?r!PVa|dxs
+z1972+@(Jtp(k9%`b8h^5hHJu#y`ya`3l*4m5Qa_^L~9J*Pqgw+txQRoOjN=T8uj6=
+ztbc<%x7%RbUDiP`sCYgio$Iz)l&>}9jNJU`wy3@6?QFO4zr~n@vTPJ9ZPBDqGcm6x
+zqjCdvqzgk<g}nzEec?L+VheT~*DF!^fh=`4=6+>Vsm&>a1!_AUPfO=UVuMD@bYIA(
+zq`pd$4?cwQATjnN6;?;(_-HeIPNZ65#wBWH<!&L-KYYnYumfEKUeX!q*p#d1RlfXj
+z8pZ5jexmkwkqL=}BaBE_B}9sa$IY<bH_?XGV0(*shO7gV7YIvONoG#tMVNkkju=&u
+z`%jGHB@o{rwF+2j*Fyw*%E-Jeb=cvBe$pS4M+KU@HZ29bz`wGbO-?23Of71bON=ll
+z2BiN1Az5>(m2?q&%;VX3Vb7W@el)vowg#>JwL%oH;WdR-GDr4Lt|7c@sCP`ui@oi5
+zh3k<*q>t6Cdpj4PDYyuh*>S#Xrj>Z6$ur*N%k1&xHM&)%yP|qF59mj_-*E$hIwH1E
+z^MfAD?fgecM9LL<>UN^YNUZIr!a1Sx`|FbIE%}C8{Z`s55o9DTFqIrRSQ@U5OaUcF
+z`(wK@p<OHJrA6R%o)|fT^3&UB5-Yb(CBnrexiwaZz6AEW`%5zcN0Ss;H5B_Q_5{tT
+zfLi7INbto9a1vwthJ}M5zKFomb!$_$m6waRfY+&O^?qO)wkwJeC8vuv?UPtJNYXeW
+z6m)5@pv927Hp$fY#mX^KQ#t12pw|t#bGi>Fv$xK|5&NQ<54e9HjtL{O|7X2Zm=*~2
+zMH;hs`hpz(q09N1q=BjWi3CUAth!vgQeXVX4ly)o#~YA6p-EryPKcpe1V?{%A9iy@
+zE+5>KxY-?EgIg)wCG$-9I*P(YpHe^RcICT1AOKE}Fr!?Ky&e8o>B`>xlx_BOYaDbI
+z?~pRJu=X1)Co_kA>eJ6YIEh{{hk=FVwIIY~EsCqz*=DN3@#QJh=YE~cqlTb$7L&Vh
+zB!z1K!rLa#uJh!1C=0ndtYGKesme}31-RR-@N@sEwXV3euTg2(dEM+uKV4RT<Q6P4
+zkBHAWLeHrz8@qT_C5sHRcq|Xb=<d4)bue3DGltWGqgQLntQnf>Mv=QrgsqTLS84$F
+zFtE@Gp;R!iAn5B`RiL96o1{y_tgqQj_3y@lP^Dz(EUz)9W5^yKxW{fD8Dyer-m@CF
+zrK}KInQQ99d)3R1X%?y<sU{-Zoq96dzRDq9=P|(53Hd8;fSc8aCu{2DG+V!FsoG?X
+zJ=x}}+H=?3j`NYr1OTJx%+?YYRyn3)NP&^U1cW?{X5EWJGeyg&H=JA4+DjSy<o>kW
+zQypOPFzBu7n=Pp!DXy`VUL(-DBY@QiX=GmO?I~t21Y6@FMFXCPKJ=lr!$}qQp>YRu
+zWH4D<adtL(4VpJ<sIS!Nn47ncVufIX3WNvTE!=QUfveQg831)cOymuK1bvcT?dh9x
+z6~4R%2je-8u;VMiRrQ{OYc%a6m8hym{`j-uS}Ad)m7~r%Y3lG67vniiiK^2p)+iUM
+z0a7aT&!J0g=&-85a<6!~0&kU__(l6!VYa&+Yg?Jad5FpMzbcB44cQBtP`=+gd29n~
+z5q%lC;SmneEQzj4>%^k>FIBdQnd@9`y1MjA?UltmRXgHjD%Wx0-qf&(PrJ)9Ma}FW
+zcZmXbmA&M}^T$I|%jrAQC<V>8Izql(l2JB^5X_6FHIji9ERMDX?#M9qXf+oms(co2
+zeI#*6joKd$dXEiKH5}3^5tjwk3BrYmWl5?>EJWXr5e_2v?96h<msD`_8I>O!I_$lu
+z_|NmzLjNhB5ey6Cjacyoyvq;x&YZg?U@;AoGvW^-v_e8-S-2qWlg8|GjL=qkc>$Vv
+zB%+deFPJLd{zYxjIj8{3ohXnkXsU05Z-drmO6buYG>A4{ho?3Y{yBH9S*!nD;7$%>
+zPhFzW%>{5F^O4od6`JsBynyH8@Ro{Kq^cgN>lW5_455!_l3V-mr%6<3Xol1k^UX?{
+z@q0!5CprW3th(-A#KGjsMBNdzRFU<p<amy&Q9iDyZ3{AyYu<R@z~$M^_a`V<xt}44
+z?)p>^LrP7f*_n(vRxF7C5V0!~D&_7BtqK>oQ?V@=s&58v=kUilYkg7ZgZZPwoW@2>
+zEmV?!nxrhU!hBBv4ACx!DOR-&8u0?fsw!@YDV@>Ly5K!uJ*{-JsT{q)k+$(?Q%i3i
+zy|eKR)6vQ{SW-<(PvmiF<>#_|%91)^C;s={z>uV{&Ae;PfiN0J@sKco{6cRRp)P(G
+zBdkbh@CUr64pBRi1VO?`fS>H5pbWcp<$Ee4L?waC!_<5VCEmvw<@yG7$##eS!1^pg
+zN;3o2{EIcV^Y8q8`~h<p&_jLefh+9-jn`e*+i_!0fnU~FGH+M`Qo3n^-~U`i3f^w^
+zJ!T3L&t))y&`RXVQQ{Ha7A!SU*yW&KYx?GvYVk+o%*%@Bz_yG@{oy`DlfW%0tpv)l
+z4^m+UDpv&GM)eZP0m{G$s+$-@WHH1HP!Amdh$3Z)>DJ6sq8SOCT+Qf$mBN~xA_i6B
+z?>2mZiInn+Xp9IoRQ6s>oMJ;nkdDcq*tm5@t?!bI6O8ER@E$&lXigMI@o$3SAyYfI
+zFb9C)wF);e#gjeWq)xLvZh0ibJ?s6OxmDKEJ32K}<QA4}$@}2}E^K#%=xv71ce#GX
+zVy`Mi9r@!kOOGY`(zh3A35{&=uzx?Obs>+U`2s@IbII>tVetnq_6+<F2^uj-$P~gH
+zfkvUHw~gGS?{wBAknA!)?15XDeIG(MSWMs_d0EziF3kwRa-pI%8%BMcSieVPoW51V
+zCtD#te%47wSh0OilGG0A=h~vRE%Ky-Avg+OE$GJjAgLq4u9B>Wzoq!2mB*u6ZOkgD
+zx<>^Ke8@=&a)rRD@I_BP#43sNSEtj5$>BCm1>dcbC0KrC`~70|00;@MWNiFTUS|F5
+zMTBr<clW{K)<-O|%@^Br8}ueN1o?AYoRM3?vb-S{V*oM_=M0HWn5$O)5X9IYdP-+;
+zRkUir5AnIUr~sP}qkya(eB@wLa#k^NHBQ5ooiQf}I==V?w2{MVuMzNj%iEnjILh*X
+zXmgoxXxwn<m2l`aG-gdt-7T+sR$1)GN}Mn?;&qs-LJV%~ikV<*d{19#?>;y#@Kib3
+zV}?C~je%5WbnauZMLz{ZKa!1Tunkt$B0hBVoQMq%Q-C86_3ww!eo?<?2f*}=w4tHK
+z2hIVes<Qj`DWyFdK@tL1Xk%dJt(5V0+Q<-dEqpiY!C!$;O_Rbz%|yvlS-K2s^gno?
+z0L2}uczxph4t?6(!eBW?Gyc&)a(oTQ3m;aS`mo)WpT*&+kvbA8dAW&w0jj8U|EQA5
+z%sI-zi_88MStsHwQ`FW1Eys&C#^9m$%Rsy}DU_1DrF9cbL2SYZq<X(6X=(VR*r0O~
+z+lr|?G2BV3?P%my$mh%HKL!`=0O>#Wk8R`sRxvacR57>|Gp*DMal8l2hd}zN6NpM0
+zY7|kVw$Fj_NVZWptr5#&2bKQhJc92?%|QM|$`*y}LOKkmaR5rM8aN3MGw6}trK-^s
+zGSILqvY#w%WeCB{+lWLKGcT}kcTIt&i#JLMyXSU(7xxYwiR;%-s%)i9!a$-*_>fla
+zPf&AD4#t*TGJ(@@#-J^?XyR_hn(N)xN9AbFSv@|vW+7uFClh~do}$mpckD?)-rht;
+zWwds>o$14GO6szB8YO-_6PSz=_`!NB+XD97M|I5w0=d(D{KjV+1Kz9{=H;Ij#+r`%
+zUB<cZu=Yl0AVI1}Y8~}dE{=JzcM1$_w2-r`K}<Dcv=}5CaspVapwp>~Y|u*%H2Z2q
+zdrHX5dIGenhkZ&Y(*(H_V@u+}n`cO_z!_U1=(gujd)~=9(c2l54EuEs@)Q3ms93tD
+zmrd-msQm5hC%A$`Qd03CJaohk1%MRg<|u$uBv5*7fhjk-PStx|HZmmLW2vWlPag28
+z1o6mKvKdi|W7ho^=$hn_gW>`PvGN6n$tngB)NGShjArs$2aGZMpN^5A#EX|6Qt{1F
+z^eI=q@Gz9nN;}V5W}qa%qar`ElmE^!N-p}b-X%)Ycn1_Rh*k37R3Mv)&mt<D<Sc9^
+zPf^Xxm*Z_wSH8DLrFJ7pjC5~JkzkvA+68MUAwuUNoQE7(&!TW1VU8fqIZ;eO+6v4l
+zDCgN0J1)eWLd%q{`J9-t(5xauL_OX8K><`la=wvCY!((+l$!1F$Ryouf#+;Lst{Zr
+z_!adRY*dR!r>w!b!c)6==&F~uYpmI&5k07EeBh62(X<I~IV-NRjumFEHgxZhi{q%b
+z{8GCpH4=_>*08mx7_XKE%mz4$<174v{XWQmKRd`tRw3nh?C%P6#EF>+!&qLZDJr^w
+zuk5)RmT+TO1KX{pbm!@Q9n_%pA8qkY#^c92LXg6w%K9Uwfz~V1H71;M{MCk!c!QTt
+zv1mGX>2+LtJjf^6wd4Be!6amp9n{?sf!W<)Qq&?GA>Z7%0Du;;sZuzjQjSP$GIa(4
+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
+
+literal 0
+HcmV?d00001
+
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/docs/14_user_doc/HDMI_CEC_User_Manual.pdf b/drivers/video/nxp/comps/tmdlHdmiCEC/docs/14_user_doc/HDMI_CEC_User_Manual.pdf
+new file mode 100755
+index 0000000000000000000000000000000000000000..e714a63b881b4387bf99245a466fe8ec2ad51cca
+GIT binary patch
+literal 171295
+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
+
+literal 0
+HcmV?d00001
+
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h
+new file mode 100755
+index 0000000..f89d8d3
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC.h
+@@ -0,0 +1,46 @@
++//=============================================================================
++// Copyright (C) 2007 NXP N.V., All Rights Reserved.
++// This source code and any compilation or derivative thereof is the proprietary
++// information of NXP N.V. and is confidential in nature. Under no circumstances
++// is this software to be exposed to or placed under an Open Source License of
++// any type without the expressed written permission of NXP N.V.
++//=============================================================================
++/*!
++ \file tmdlHdmiCEC.h
++
++ \version 1.0
++
++ \date 04/07/2007
++
++ \brief This provides interfaces description of CEC messages.
++
++ \section refs Reference Documents
++ TDA998X Driver - tmdlHdmiTx - SCS.doc
++ \note None.
++
++ HISTORY :
++ \verbatim
++ Date Modified by CRPRNr TASKNr Maintenance description
++ -------------|-----------|-------|-------|-----------------------------------
++ 04/07/2007 | F.G | | | Creation.
++ -------------|-----------|-------|-------|-----------------------------------
++ \endverbatim
++*/
++//==========================================================================
++
++#ifndef TMDLHDMICEC_H
++#define TMDLHDMICEC_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#include "tmNxCompId.h"
++#include "tmdlHdmiCEC_Types.h"
++#include "tmdlHdmiCEC_Functions.h"
++
++#endif /* TMDLHDMICEC_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h
+new file mode 100755
+index 0000000..fa33118
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Functions.h
+@@ -0,0 +1,3166 @@
++//=============================================================================
++// Copyright (C) 2007 NXP N.V., All Rights Reserved.
++// This source code and any compilation or derivative thereof is the proprietary
++// information of NXP N.V. and is confidential in nature. Under no circumstances
++// is this software to be exposed to or placed under an Open Source License of
++// any type without the expressed written permission of NXP N.V.
++//=============================================================================
++/*!
++ \file tmdlHdmiCEC_Functions.h
++
++ \version 1.0
++
++ \date 04/07/2007
++
++ \brief This provides interfaces description of CEC messages.
++
++ \section refs Reference Documents
++ TDA998X Driver - tmdlHdmiCec - SCS.doc
++ \note None.
++
++ HISTORY :
++ \verbatim
++ Date Modified by CRPRNr TASKNr Maintenance description
++ -------------|-----------|-------|-------|-----------------------------------
++ 04/07/2007 | F.G | | | Creation.
++ -------------|-----------|-------|-------|-----------------------------------
++ \endverbatim
++*/
++//==========================================================================
++
++#ifndef TMDLHDMICEC_FUNCTIONS_H
++#define TMDLHDMICEC_FUNCTIONS_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxTypes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++/*============================================================================*/
++/* PUBLIC FUNCTION DECLARATION */
++/*============================================================================*/
++
++//==========================================================================
++/*!
++ \brief This message is reserved for testing purposes
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress\n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecAbortMessage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a new source to indicate that it has started
++ to transmit a stream OR used in reponse to a <Request Active Source>
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecActiveSource
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate the supported CEC version in response
++ to a <Get CEC Version>
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress\n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECVersion_t CECVersion \n
++ Supported CEC Version.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVersion
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECVersion_t CECVersion
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to clear an Analogue timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearAnalogueTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++);
++
++
++//==========================================================================
++/*!
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearDigitalTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to conrol a device's media functions
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDecControlMode_t DeckControlMode \n
++ Used in message <Deck Control>\n
++
++ \note The "Skip Forward / Wind" and "Skip Reverse / Rewind" values are
++ used for example in a DVD as next xhapter and previous chapter and
++ in a VCR as wind and rewind. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeckControl
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDecControlMode_t DeckControlMode
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to provide a deck's status to the initiator
++ of the <Give Deck Status> message
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDecInfo_t DeckInfo \n
++ Information on the device's current status \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeckStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDecInfo_t DeckInfo
++);
++
++//==========================================================================
++/*!
++ \brief This message report the vendor ID of this device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt32 VendorID \n
++ Indentifier for a specific Vendor \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeviceVendorID
++(
++ tmInstance_t Instance,
++ UInt32 VendorID
++);
++
++//==========================================================================
++/*!
++ \brief This message is used as a reponse to indicate that the device does
++ not support the requested message type, or that it cannot execute it
++ at the present time.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECFeatureOpcode_t FeatureOpcode \n
++ Opcode of the aborted message. \n
++
++ \param tmdlHdmiCECAbortReason_t AbortReason \n
++ The reason why message cannot respond. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecFeatureAbort
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode,
++ tmdlHdmiCECAbortReason_t AbortReason
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a device to enquire which version of CEC
++ the target supports
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetCecVersion
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is sent by a device capable of character generation
++ (for OSD and Menus) to a TV in order to discover the currently selected
++ Menu Language. Also used by a TV during installation to dicover the
++ currently set menu language of other devices.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetMenuLanguage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is requests an amplifier to send its volume and mute status
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveAudioStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to request the status of a device regardless
++ of whether or not it is the current active source.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n
++ Allows the initiator to request the status once or on all future state
++ change. Or to cancel a previous <Give Deck Status > ["On"] request. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDeckStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECStatusRequest_t StatusRequest
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to determine the current power status of a
++ target device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is request the vendor ID from a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to request preferred OSD name of a device
++ for use in menus associated with that device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveOsdName
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is a request to a device to return its physical Address
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGivePhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message request the status of the system audio mode
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to request the status of a tuner device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n
++ Allows the initiator to request the status once or on all future state
++ change. Or to cancel a previous <Give Tuner Device Status > ["On"] request. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECStatusRequest_t StatusRequest
++);
++
++//==========================================================================
++/*!
++ \brief This message sent by a source device to the TV whenever it enters
++ the active state
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receivers. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecImageViewOn
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by the currently active source to inform the
++ TV that it has no video to be presented to the user, or is going
++ into standby as the result of a lcoal user command on the device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress, \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Physical Address of the device. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInactiveSource
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message request from the TV for a device to show/remove a
++ menu or to query if a device is currently showing a menu
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECMenuRequestType_t MenuRequestType \n
++ Indicates if the menu request is to activate or deactivate the
++ devices menu or simply query the devices menu status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecMenuRequest
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECMenuRequestType_t MenuRequestType
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate to the TV that the device is
++ showing/has removed a menu and requets the remote control keys to
++ be passed though
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECMenuState_t MenuState \n
++ Indicates if the device is in the 'Device Menu Active' state or
++ 'Device Menu Inactive' state. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecMenuStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECMenuState_t MenuState
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to control the playback behaviour of a source
++ device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPlayMode_t PlayMode \n
++ In which mode to play media. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecPlay
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPlayMode_t PlayMode
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by any device for device discovery - similar to
++ ping in other protocols
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecPollingMessage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message request a device to stop a recording
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOff
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message attempt to record analogue source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++);
++
++//==========================================================================
++/*!
++ \brief This message attempt to record digital source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnDigitalService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++);
++
++//==========================================================================
++/*!
++ \brief This message attempt to record an external physical address source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message attempt to record an external plug source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++);
++
++//==========================================================================
++/*!
++ \brief This message attempt to record an external plug source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnOwnSource
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a recording device to inform the initiator
++ of the message <Record On> about its status.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo \n
++ The recording status of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo
++);
++
++//==========================================================================
++/*!
++ \brief This message request by the recording device to record the presently
++ displayed source.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordTvScreen
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message report an amplifier's volume and mute.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECAudioStatus_t AudioStatus \n
++ Volume and mute status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportAudioStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ ptmdlHdmiCECAudioStatus_t pAudioStatus
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor( )
++ \brief This message Report Audio Capability.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt32 ShortAudioDecriptor \n
++ Audio Descriptor. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt32 ShortAudioDecriptor
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor( )
++ \brief This message Request Audio Capability.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 AudioFormatID \n
++
++ \param UInt8 AudioFormatCode \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 AudioFormatID,
++ UInt8 AudioFormatCode
++
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecIniateARC( )
++ \brief This message Used by an ARC RX device to activate the
++ ARC functionality in an ARC TX device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecIniateARC
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportArcInitiated( )
++ \brief This message Used by an ARC TX device to indicate that
++ its ARC functionality has been activated
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportArcInitiated
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportArcTerminated( )
++ \brief This message Used by an ARC TX device to indicate that its ARC functionality
++ has been deactivated.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportArcTerminated
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestArcInitiation( )
++ \brief This message Used by an ARC TX device to request an ARC RX device to
++ activate the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestArcInitiation
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestArcTerminiation( )
++ \brief Used by an ARC TX device to request an ARC RX device to deactivate
++ the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestArcTerminiation
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTerminateARC( )
++ \brief Used by an ARC TX device to request an ARC RX device to deactivate
++ the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTerminateARC
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to inform all other devices of the mapping
++ between physical and logical address of the initiator.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Device physical address within the cluster. \n
++
++ \param tmdlHdmiCECDeviceType_t DeviceType \n
++ Type of the device (TV, Playback, tuner,...). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress,
++ tmdlHdmiCECDeviceType_t DeviceType
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to inform a requesting device of the current
++ power status.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPowerStatus_t PowerStatus \n
++ Current power status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportPowerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPowerStatus_t PowerStatus
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a new device to discover the status of
++ the system.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestActiveSource
++(
++ tmInstance_t Instance
++);
++
++//==========================================================================
++/*!
++ \brief This message is sent by a CEC switch when it is manually switched to
++ inform all other devices on the network that the active route below
++ the switch has changed.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 OriginalAddress \n
++ Previous address that the switch was switched to. \n
++
++ \param UInt16 NewAddress \n
++ The new address it has been moved to. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRoutingChange
++(
++ tmInstance_t Instance,
++ UInt16 OriginalAddress,
++ UInt16 NewAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is sent by a CEC switch to indicate the active route
++ below the switch.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ The current active route to the sink in the CEC switch. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRoutingInformation
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message select directly an analogue TV Service.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSelectAnalogueService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++);
++
++//==========================================================================
++/*!
++ \brief This message select directly a digital TV, Radio or Data Broadcast
++ Service.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSelectDigitalService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set asingle timer block on an analogue
++ recording device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetAnalogueTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to control audio rate from Source device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECAudioRate_t AudioRate \n
++ The audio rate requested. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetAudioRate
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAudioRate_t AudioRate
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set a digital timer block on a digital
++ recording device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetDigitalTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set a single timer block to record from an
++ external device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set a single timer block to record from an
++ external device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a TV or another device to indicate the menu
++ Language.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param const char *pLanguage \n
++ Pointer on the user's menu language choice. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetMenuLanguage
++(
++ tmInstance_t Instance,
++ const char *pLanguage
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set the preferred OSD name of a device
++ for use in manus associated with that device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param const char *pOsdName \n
++ Pointer on the preferred name of the device. \n
++
++ \param UInt8 OsdNameLength \n
++ Length of Osd Name String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetOsdName
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ const char *pOsdName,
++ UInt8 OsdNameLength
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to send a test message to output on a TV.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDisplayControl_t DisplayControl \n
++ Display timing. \n
++
++ \param const char *pOsdString \n
++ Pointer on the Text to display. \n
++
++ \param UInt8 OsdStringLength \n
++ Length of Osd String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetOsdString
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDisplayControl_t DisplayControl,
++ const char *pOsdString,
++ UInt8 OsdStringLength
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a TV to request a streaming path from
++ the specified physical address.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetStreamPath
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message turn the system audio Mode ON or OFF.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n
++ Specifies if the system audio mode is ON or OFF.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetSystemAudioMode
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to set the name of a program associated
++ with a timer block.Sent directly after sending a
++ <Set analogue Timer> or <Set Digital Timer> message. The name
++ is then associated with that timer block.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param const char *pProgramTitleString \n
++ Pointer on the program title. \n
++
++ \param UInt8 ProgramTitleLength \n
++ Length of Program Title String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ const char *pProgramTitleString,
++ UInt8 ProgramTitleLength
++);
++
++//==========================================================================
++/*!
++ \brief This message switches one or all devices into standby mode.Can be
++ be used as a broadcast message o be addressed to a specific device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecStandby
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief A device implementing System Audio Control and which has volume
++ control RC button(eg TV or STB) request to use System Audio Mode
++ to the amplifier.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt16 PhysicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief Reports the current status of the System Audio Mode.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n
++ Current system audio mode.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus
++);
++
++//==========================================================================
++/*!
++ \brief This message as <Image View On>, but should also remove any text,
++ menus and PIP windows from the TV's display
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTextViewOn
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to give the status of a <Cleared Analogue Timer>,
++ <Clear Digital Timer> or <Clear External Timer> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData \n
++ Indicates if the timer was cleared successfully. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTimerClearedStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to send timer status to the initiator of a
++ <Set Timer> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECTimerStatusData_t *pTimerStatusData \n
++ Pointer on the Timer status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTimerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECTimerStatusData_t *pTimerStatusData
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a tuner device to provide its status to the
++ initiator of the <Give Tuner Device Status> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n
++ Indicates if the tuner is being used as a source of a recording. \n
++
++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n
++ Indicates if the the device is currently deplaying its tuner or not. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordingFlag_t RecordingFlag,
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++);
++
++//==========================================================================
++/*!
++ \brief This message is used by a tuner device to provide its status to the
++ initiator of the <Give Tuner Device Status> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n
++ Indicates if the tuner is being used as a source of a recording. \n
++
++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n
++ Indicates if the the device is currently deplaying its tuner or not. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordingFlag_t RecordingFlag,
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo,
++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to tune to next lowest service in a tuner's
++ service list.Can be used for PIP.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerStepDecrement
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to tune to next highest service in a tuner's
++ service list.Can be used for PIP.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerStepIncrement
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECUserRemoteControlCommand_t UICommand \n
++ Relevant UI command issued by user. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressed
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECUserRemoteControlCommand_t UICommand
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPlayMode_t PlayMode \n
++ In which mode to play media. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedPlay
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPlayMode_t PlayMode
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectAudioInput \n
++ Number of the Audio Input (Audio input number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectAudioInput
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectAVInput \n
++ Number of the A/V Input (A/V input number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectAVInput
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectMedia \n
++ Number of Media (Media number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectMedia
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier \n
++ Pointer to the structure of Major and Minor Channel number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedTune
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier
++);
++
++//==========================================================================
++/*!
++ \brief This message is used to indicate that the user released a remote button
++ The last one indicated by the <User Control Pressed> Message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlReleased
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief This message is allows vendor specific commands to be sent between
++ two devices.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 *pVendorSpecificData \n
++ Pointer to the Vendor Specific datas
++
++ \param UInt8 VendorSpecificDataLength \n
++ Length of VendorSpecificData. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorCommand
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 *pVendorSpecificData,
++ UInt8 VendorSpecificDataLength
++);
++
++//==========================================================================
++/*!
++ \brief This message is allows vendor specific commands to be sent between
++ two devices or broadcast.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt32 VendorID \n
++ Indentifier for a specific Vendor \n
++
++ \param UInt8 *pVendorSpecificData \n
++ Pointer to the Vendor Specific datas
++
++ \param UInt8 VendorSpecificDataLength \n
++ Length of VendorSpecificData. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorCommandWithID
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt32 VendorID,
++ UInt8 *pVendorSpecificData,
++ UInt8 VendorSpecificDataLength
++);
++
++//==========================================================================
++/*!
++ \brief This message indicates that a remote control button has been depressed.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 *pVendorSpecificRcCode \n
++ Pointer to the Vendor Specific remote control code.
++ its recommended t keep this to a minimum size.
++ The maximum length shall not exceed 14 data blocks to avoid saturating bus
++
++ \param UInt8 VendorSpecificRcCodeLength \n
++ Length of VendorSpecificRcCode. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 *pVendorSpecificRcCode,
++ UInt8 VendorSpecificRcCodeLength
++);
++
++//==========================================================================
++/*!
++ \brief This message indicates that a remote control button (the last button
++ pressed indicated by the <Vendor remote button down > message) has
++ been released.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++);
++
++//==========================================================================
++/*!
++ \brief Get the software version of the driver.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param pSWVersion Pointer to the version structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetSWVersion
++(
++ tmSWVersion_t *pSWVersion
++);
++
++//==========================================================================
++/*!
++ \brief Get the number of available CEC devices in the system.
++ A unit directly represents a physical device.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param pUnitCount Pointer to the number of available units.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetNumberOfUnits
++(
++ UInt32 *pUnitCount
++);
++
++//==========================================================================
++/*!
++ \brief Get the capabilities of unit 0. Capabilities are stored into a
++ dedicated structure.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetCapabilities
++(
++ tmdlHdmiCecCapabilities_t *pCapabilities
++);
++
++//==========================================================================
++/*!
++ \brief Get the capabilities of a specific unit. Capabilities are stored
++ into a dedicated structure
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param unit Unit to be probed.
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetCapabilitiesM
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiCecCapabilities_t *pCapabilities
++);
++
++//==========================================================================
++/*!
++ \brief Open unit 0 of CEC driver and provides the instance number to
++ the caller. Note that one unit of CEC represents one physical
++ CEC device and that only one instance per unit can be opened.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param pInstance Pointer to the variable that will receive the instance
++ identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecOpen
++(
++ tmInstance_t *pInstance
++);
++
++//==========================================================================
++/*!
++ \brief Open a specific unit of CEC driver and provides the instance
++ number to the caller. Note that one unit of CEC represents one
++ physical CEC device and that only one instance per unit can be
++ opened.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param pInstance Pointer to the structure that will receive the instance
++ identifier.
++ \param unit Unit number to be opened.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecOpenM
++(
++ tmInstance_t *pInstance,
++ tmUnitSelect_t unit
++);
++
++//==========================================================================
++/*!
++ \brief Close an instance of CEC driver.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClose
++(
++ tmInstance_t instance
++);
++
++//==========================================================================
++/*!
++ \brief Set the power state of an instance of the CEC device. ON
++ state corresponds to a fully supplied, up and running device. Other
++ modes correspond to the powerdown state of the device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \param instance Instance identifier.
++ \param powerState Power state to set.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t powerState
++);
++
++//==========================================================================
++/*!
++ \brief Get the power state of an instance of the CEC device. ON
++ state corresponds to a fully supplied, up and running device. Other
++ modes correspond to the powerdown state of the device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pPowerState Pointer to the power state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t *pPowerState
++);
++
++//==========================================================================
++/*!
++ \brief Set the configuration of instance attributes. This function is
++ required by DVP architecture rules but actually does nothing in this
++ driver
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInstanceConfig
++(
++ tmInstance_t instance
++);
++
++//==========================================================================
++/*!
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration like Logical Address or device
++ state.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInstanceSetup
++(
++ tmInstance_t instance,
++ ptmdlHdmiCecInstanceSetup_t pSetupInfo
++);
++
++//==========================================================================
++/*!
++ \brief Get instance setup parameters.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure that will receive setup
++ parameters
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetInstanceSetup
++(
++ tmInstance_t instance,
++ ptmdlHdmiCecInstanceSetup_t pSetupInfo
++);
++
++//==========================================================================
++/*!
++ \brief Make device library handle an incoming interrupt. This function is
++ used by application to tell the device library that the hardware
++ sent an interrupt. It can also be used to poll the interrupt status
++ of the device if the interrupt line is not physically connected to
++ the CPU.
++ This function is synchronous.
++ This function is ISR friendly.
++
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_FULL: the queue is full
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecHandleInterrupt
++(
++ tmInstance_t instance
++);
++
++//==========================================================================
++/*!
++ \brief Register event callbacks. Only one callback is registered through
++ this API. This callback will received the type of event that
++ occured throug a dedicated parameter and will be called as many
++ times as there is pending events.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pCallback Pointer to the callback function that will handle events
++ from the devlib.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for
++ the function
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRegisterCallbacks
++(
++ tmInstance_t instance,
++ ptmdlHdmiCecCallbackFunc_t pkCallback
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetLogicalAddress( )
++ \brief Set Device Logical Address
++
++ \param instance Instance identifier.
++ \param LogicalAddress Logical Address value.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetLogicalAddress
++(
++ tmInstance_t instance,
++ tmdlHdmiCECLogicalAddress_t LogicalAddress
++);
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetRetry( )
++ \brief Change the number of retransmission
++
++ \param instance Instance identifier.
++ \param NbRetry Number of retry.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetRetry
++(
++ tmInstance_t instance,
++ UInt8 NbRetry
++);
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t getCecLastMessage( )
++ \brief Return the Addresses and the Opcode of the last CEC
++ transmitted message
++
++ \param pSaveMessage Pointer to the CEC Save Message
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t getCecLastMessage
++(
++ tmdlHdmiCecSaveMessage_t *pSaveMessage
++);
++
++
++//==========================================================================
++/*!
++ \brief This function allows enabling a specific event of devlib.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param event Event to enable
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecEnableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiCecEvent_t event
++);
++
++//==========================================================================
++/*!
++ \brief This function allows disabling a specific event of devlib.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param event Event to disable
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDisableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiCecEvent_t event
++);
++
++
++//==========================================================================
++/*!
++ \brief This function enables calibration depending on CEC clock source
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param cecClockSource CEC clock source
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecEnableCalibration
++(
++ tmInstance_t instance,
++ tmdlHdmiCecClockSource_t cecClockSource
++);
++
++
++//==========================================================================
++/*!
++ \brief This function disable calibration depending on CEC clock source
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDisableCalibration(
++ tmInstance_t instance
++);
++
++//==========================================================================
++/*!
++ \brief This function allow to send a generic CEC message
++ This function has to be used when CEC messages are construct in
++ the middleware
++
++ \param instance Instance identifier.
++
++ \param *pData Pointer to the CEC data buffer
++
++ \param lenData Lenght of I2C data buffer
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSendMessage(
++
++ tmInstance_t instance,
++ UInt8 *pData,
++ UInt16 lenData
++);
++
++unsigned char tmdlHdmiCecGetRegister(tmInstance_t instance, UInt32 offset);
++tmErrorCode_t tmdlHdmiCecSetRegister(tmInstance_t instance,UInt32 offset,UInt32 value);
++
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMICEC_FUNCTIONS_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h
+new file mode 100755
+index 0000000..d0bd632
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/inc/tmdlHdmiCEC_Types.h
+@@ -0,0 +1,1083 @@
++//=============================================================================
++// Copyright (C) 2007 NXP N.V., All Rights Reserved.
++// This source code and any compilation or derivative thereof is the proprietary
++// information of NXP N.V. and is confidential in nature. Under no circumstances
++// is this software to be exposed to or placed under an Open Source License of
++// any type without the expressed written permission of NXP N.V.
++//=============================================================================
++/*!
++ \file tmdlHdmiCEC_Types.h
++
++ \version 1.0
++
++ \date 04/07/2007
++
++ \brief This provides interfaces description of CEC messages.
++
++ \section refs Reference Documents
++ TDA998X Driver - tmdlHdmiTx - SCS.doc
++ \note None.
++
++ HISTORY :
++ \verbatim
++ Date Modified by CRPRNr TASKNr Maintenance description
++ -------------|-----------|-------|-------|-----------------------------------
++ 04/07/2007 | F.G | | | Creation.
++ -------------|-----------|-------|-------|-----------------------------------
++ \endverbatim
++*/
++//==========================================================================
++
++#ifndef TMDLHDMICEC_TYPES_H
++#define TMDLHDMICEC_TYPES_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxTypes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* DEFINES */
++/*============================================================================*/
++
++/**< Error Codes */
++#define TMDL_ERR_DLHDMICEC_BASE CID_DL_HDMICEC
++#define TMDL_ERR_DLHDMICEC_COMPATIBILITY (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_COMPATIBILITY) /**< SW Interface compatibility */
++#define TMDL_ERR_DLHDMICEC_MAJOR_VERSION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_MAJOR_VERSION) /**< SW Major Version error */
++#define TMDL_ERR_DLHDMICEC_COMP_VERSION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_COMP_VERSION) /**< SW component version error */
++#define TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_UNIT_NUMBER) /**< Invalid device unit number */
++#define TMDL_ERR_DLHDMICEC_BAD_INSTANCE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_INSTANCE) /**< Bad input instance value */
++#define TMDL_ERR_DLHDMICEC_BAD_HANDLE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_HANDLE) /**< Bad input handle */
++#define TMDL_ERR_DLHDMICEC_BAD_PARAMETER (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BAD_PARAMETER) /**< Invalid input parameter */
++#define TMDL_ERR_DLHDMICEC_NO_RESOURCES (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NO_RESOURCES) /**< Resource is not available */
++#define TMDL_ERR_DLHDMICEC_RESOURCE_OWNED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_RESOURCE_OWNED) /**< Resource is already in use */
++#define TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_RESOURCE_NOT_OWNED) /**< Caller does not own resource */
++#define TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INCONSISTENT_PARAMS) /**< Inconsistent input params */
++#define TMDL_ERR_DLHDMICEC_NOT_INITIALIZED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_INITIALIZED) /**< Component is not initialized */
++#define TMDL_ERR_DLHDMICEC_NOT_SUPPORTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_SUPPORTED) /**< Function is not supported */
++#define TMDL_ERR_DLHDMICEC_INIT_FAILED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INIT_FAILED) /**< Initialization failed */
++#define TMDL_ERR_DLHDMICEC_BUSY (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_BUSY) /**< Component is busy */
++#define TMDL_ERR_DLHDMICEC_I2C_READ (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_READ) /**< Read error */
++#define TMDL_ERR_DLHDMICEC_I2C_WRITE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_WRITE) /**< Write error */
++#define TMDL_ERR_DLHDMICEC_FULL (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_FULL) /**< Queue is full */
++#define TMDL_ERR_DLHDMICEC_NOT_STARTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_NOT_STARTED) /**< Function is not started */
++#define TMDL_ERR_DLHDMICEC_ALREADY_STARTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_ALREADY_STARTED) /**< Function is already started */
++#define TMDL_ERR_DLHDMICEC_ASSERTION (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_ASSERTION) /**< Assertion failure */
++#define TMDL_ERR_DLHDMICEC_INVALID_STATE (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_INVALID_STATE) /**< Invalid state for function */
++#define TMDL_ERR_DLHDMICEC_OPERATION_NOT_PERMITTED (TMDL_ERR_DLHDMICEC_BASE + TM_ERR_OPERATION_NOT_PERMITTED) /**< corresponds to posix EPERM */
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++/*!
++ \enum tmdlHdmiCECAbortReason_t
++ \brief This enum indicates the reason for a <Feature Abort> response
++*/
++typedef enum
++{
++ CEC_ABORT_UNKNOWN_OPCODE = 0, /*!< Unrecognized opcode */
++ CEC_ABORT_INCORRECT_MODE = 1, /*!< Not in correct mode to respond */
++ CEC_ABORT_NO_SOURCE = 2, /*!< cannot provide source */
++ CEC_ABORT_INVALID_OPERAND = 3, /*!< Invalid operand */
++ CEC_ABORT_REFUSED = 4, /*!< Refused */
++ CEC_ABORT_UNABLE_TO_DETERMINE = 5 /*!< Unable to Determine */
++} tmdlHdmiCECAbortReason_t;
++
++/*!
++ \enum tmdlHdmiCECAnalogueBroadcastType_t
++ \brief This enum indicates the analogue broadcast type
++*/
++typedef enum
++{
++ CEC_BROADCAST_TYPE_CABLE = 0x00, /*!< Cable */
++ CEC_BROADCAST_TYPE_SATELLITE = 0x01, /*!< Satellite*/
++ CEC_BROADCAST_TYPE_TERRESTRIAL = 0x02 /*!< Terrestrial */
++} tmdlHdmiCECAnalogueBroadcastType_t;
++
++/*!
++ \enum _tmdlHdmiCECAnalogueFrequency
++ \brief This enum specify the min and max frequency used by an analogue tuner
++*/
++enum _tmdlHdmiCECAnalogueFrequency
++{
++ CEC_ANALOG_FREQ_MIN = 0x0000, /*!< Min frequency used by analogue tuner */
++ CEC_ANALOG_FREQ_MAX = 0xFFFF /*!< Max frequency used by analogue tuner */
++};
++
++/*!
++ \enum _tmdlHdmiCECAsciiDigit
++ \brief This enum represent the min and max of a printable digit character
++*/
++enum _tmdlHdmiCECAsciiDigit
++{
++ CEC_ASCII_DIGIT_MIN = 0x30, /*!< Min of a printable digit character */
++ CEC_ASCII_DIGIT_MAX = 0x39 /*!< Max of a printable digit character */
++};
++
++/*!
++ \enum _tmdlHdmiCECAscii
++ \brief This enum represent the min and max of a printable character
++*/
++enum _tmbsHdmiCECAscii
++{
++ CEC_ASCII_CHARACTER_MIN = 0x20, /*!< Min of a printable character */
++ CEC_ASCII_CHARACTER_MAX = 0x7E /*!< Max of a printable character */
++};
++
++/*!
++ \enum _tmdlHdmiCECAudioFormatCode
++ \brief This enum represent the min and max of a Audio Format Code is defined
++ in CEA-861-D for CEA Short Audio Descriptor
++*/
++enum _tmdlHdmiCECAudioFormatCode
++{
++ CEC_AUDIO_FORMAT_CODE_MIN = 0x01, /*!< Min of a Audio Format Code */
++ CEC_AUDIO_FORMAT_CODE_MAX = 0x0F /*!< Max of a Audio Format Code */
++};
++
++/*!
++ \enum tmdlHdmiCECAudioRate_t
++ \brief This enum indicates the audio range control
++*/
++typedef enum
++{
++ CEC_AUDIO_RATE_OFF = 0, /*!< Rate Control off */
++ CEC_AUDIO_RATE_WIDE_RANGE_STANDARD_RATE = 1, /*!< Standard rate : 100% rate */
++ CEC_AUDIO_RATE_WIDE_RANGE_FAST_RATE = 2, /*!< Fast rate : Max 101% rate */
++ CEC_AUDIO_RATE_WIDE_RANGE_SLOW_RATE = 3, /*!< Sloaw rate : 99% rate */
++ CEC_AUDIO_RATE_NARROW_RANGE_STANDARD_RATE = 4, /*!< Standard rate : 100% rate */
++ CEC_AUDIO_RATE_NARROW_RANGE_FAST_RATE = 5, /*!< Fast rate : Max 101% rate */
++ CEC_AUDIO_RATE_NARROW_RANGE_SLOW_RATE = 6 /*!< Sloaw rate : 99% rate */
++} tmdlHdmiCECAudioRate_t;
++
++/*!
++ \enum tmdlHdmiCECAudioMute_t
++ \brief This enum indicates the audio current audio mute status
++*/
++typedef enum
++{
++ CEC_AUDIO_MUTE_OFF = 0, /*!< Audio Mute off */
++ CEC_AUDIO_MUTE_ON = 1 /*!< Audio Mute on */
++} tmdlHdmiCECAudioMute_t;
++
++
++/*!
++ \struct tmdlHdmiCECAudioStatus_t
++ \brief This union indicates the current audio status of a device
++*/
++typedef struct _tmdlHdmiCECAudioStatus_t
++{
++ tmdlHdmiCECAudioMute_t audioMuteStatus ; /*!< Audio Mute Status */
++ UInt8 audioVolumeStatus ; /*!< Audio Volume Status */
++} tmdlHdmiCECAudioStatus_t, *ptmdlHdmiCECAudioStatus_t;
++
++
++/*!
++ \enum tmdlHdmiCECBoolean_t
++ \brief This enum indicates a Flag
++*/
++typedef enum
++{
++ CEC_FALSE = 0, /*!< False */
++ CEC_TRUE = 1, /*!< True */
++} tmdlHdmiCECBoolean_t;
++
++
++/*!
++ \enum tmdlHdmiCECBroadcastSystem_t
++ \brief This enum indicates information about the color system, the sound carrier and IF-frequency
++*/
++typedef enum
++{ /*!< Sound / Sound Modulation / Video Modulation / Vertical Frequency / Color sub-carier */
++ CEC_BROADCAST_SYSTEM_PAL_BG = 0, /*!< 5.5MHZ / FM NEG 50HZ 4.43 MHZ */
++ CEC_BROADCAST_SYSTEM_PAL_SECAM_L = 1, /*!< 6.5MHZ / AM POS 50HZ Fob 4.25MHz,For 4.406Mhz */
++ CEC_BROADCAST_SYSTEM_PAL_M = 2, /*!< 4.5MHZ / FM NEG 60HZ 3.5756 MHZ */
++ CEC_BROADCAST_SYSTEM_NTSC_M = 3, /*!< 4.5MHZ / FM NEG 60HZ 3.5795 MHZ */
++ CEC_BROADCAST_SYSTEM_PAL_I = 4, /*!< 6.0MHZ / FM NEG 50HZ 4.43 MHZ */
++ CEC_BROADCAST_SYSTEM_SECAM_DK = 5, /*!< 6.5MHZ / FM NEG 50HZ Fob 4.25MHz,For 4.406Mhz */
++ CEC_BROADCAST_SYSTEM_SECAM_BG = 6, /*!< 5.5MHZ / FM NEG 50HZ Fob 4.25MHz,For 4.406Mhz */
++ CEC_BROADCAST_SYSTEM_SECAM_L = 7, /*!< 6.5MHZ / AM POS 50HZ Fob 4.25MHz,For 4.406Mhz */
++ CEC_BROADCAST_SYSTEM_PAL_DK = 8, /*!< 5.5MHZ / FM NEG 50HZ 4.43MHZ */
++ CEC_BROADCAST_SYSTEM_FUTURE_USE = 9, /*!< Future Use */
++ CEC_BROADCAST_SYSTEM_OTHER_SYSTEM = 31 /*!< Other System */
++} tmdlHdmiCECBroadcastSystem_t;
++
++/*!
++ \enum tmdlHdmiCECVersion_t
++ \brief This enum indicates the supported CEC version
++*/
++typedef enum
++{
++ CEC_VERSION_Reserved = 0x00, /*!< CEC Reserved */
++ CEC_VERSION_Reserved1 = 0x01, /*!< CEC Reserved */
++ CEC_VERSION_Reserved2 = 0x02, /*!< CEC Reserved */
++ CEC_VERSION_Reserved3 = 0x03, /*!< CEC Reserved */
++ CEC_VERSION_1_3a = 0x04, /*!< CEC Version 1.3a */
++ CEC_VERSION_1_4 = 0x05 /*!< CEC Version 1.4 */
++} tmdlHdmiCECVersion_t;
++
++/*!
++ \enum tmdlHdmiCECChanNumFormat_t
++ \brief This enum indicates the Channel Format
++*/
++typedef enum
++{
++ CEC_FIRST_CHAN_NUMBER = 0x01, /*!< 1-part channel number */
++ CEC_SECOND_CHAN_NUMBER = 0x02 /*!< 2-part channel number */
++} tmdlHdmiCECChanNumFormat_t;
++
++/*!
++ \struct tmdlHdmiCECChannelIdentifier_t
++ \brief This struct indicates a 1-part Logical or Virtual Channel Number or
++ a 2-part Major and Minor channel combination
++*/
++typedef struct
++{
++ tmdlHdmiCECChanNumFormat_t ChanNumFormat ; /*!< Channel Format */
++ UInt16 MajorChanNumber ; /*!< Major Channel Number (if channel is 2-part) */
++ UInt16 MinorChanNumber ; /*!< 1-part Channel Number ,or a Minor Channel Number (if channel is 2-part) */
++} tmdlHdmiCECChannelIdentifier_t ;
++
++/*!
++ \enum tmdlHdmiCECDayOfMonth_t
++ \brief This enum indicates the day of the month
++*/
++typedef enum
++{
++ CEC_FIRST_DAY_OF_MONTH = 1, /*!< First day of the month */
++ CEC_LAST_DAY_OF_MONTH = 31 /*!< Last day of the month */
++} tmdlHdmiCECDayOfMonth_t;
++
++/*!
++ \enum tmdlHdmiCECDecControlMode_t
++ \brief This enum indicates command used for opcode <Deck Control>
++*/
++typedef enum
++{
++ CEC_DECK_CONTROL_WIND = 1, /*!< Skip Forward / Wind */
++ CEC_DECK_CONTROL_REWIND = 2, /*!< Skip Reverse / Rewind */
++ CEC_DECK_CONTROL_STOP = 3, /*!< Stop */
++ CEC_DECK_CONTROL_EJECT = 4 /*!< Eject */
++} tmdlHdmiCECDecControlMode_t;
++
++/*!
++ \enum tmdlHdmiCECDecInfo_t
++ \brief This enum indicates the current status of a tape or disk deck
++*/
++typedef enum
++{
++ CEC_DECK_INFO_PLAY = 0x11, /*!< Play */
++ CEC_DECK_INFO_RECORD = 0x12, /*!< Record */
++ CEC_DECK_INFO_PLAY_REVERSE = 0x13, /*!< Play Reverse */
++ CEC_DECK_INFO_STILL = 0x14, /*!< Still */
++ CEC_DECK_INFO_SLOW = 0x15, /*!< Slow */
++ CEC_DECK_INFO_SLOW_REVERSE = 0x16, /*!< Slow Reverse */
++ CEC_DECK_INFO_FAST_FORWARD = 0x17, /*!< Fast Forward */
++ CEC_DECK_INFO_FAST_REVERSE = 0x18, /*!< Fast Reverse */
++ CEC_DECK_INFO_NO_MEDIA = 0x19, /*!< No Media */
++ CEC_DECK_INFO_STOP = 0x1A, /*!< Stop */
++ CEC_DECK_INFO_WIND = 0x1B, /*!< Skip Forward / Wind */
++ CEC_DECK_INFO_REWIND = 0x1C, /*!< Skip Reverse / Rewind */
++ CEC_DECK_INFO_ID_SEARCH_FORWARD = 0x1D, /*!< Index Search Forward */
++ CEC_DECK_INFO_ID_SEARCH_REVERSE = 0x1E, /*!< Index Search Forward */
++ CEC_DECK_INFO_OTHER_STATUS = 0x1F /*!< Other Status */
++} tmdlHdmiCECDecInfo_t;
++
++
++/*!
++ \enum tmdlHdmiCECDeviceType_t
++ \brief This enum indicates the device type
++*/
++typedef enum
++{
++ CEC_DEVICE_TYPE_TV = 0, /*!< TV */
++ CEC_DEVICE_TYPE_REC_DEVICE = 1, /*!< Recording Device */
++ CEC_DEVICE_TYPE_RESERVED = 2, /*!< Reserved */
++ CEC_DEVICE_TYPE_TUNER = 3, /*!< Tuner */
++ CEC_DEVICE_TYPE_PLAYBACK_DEVICE = 4, /*!< PlayBack Device */
++ CEC_DEVICE_TYPE_AUDIO_DEVICE = 5, /*!< Audio System */
++ CEC_DEVICE_TYPE_PURE_CEC_SWITCTH = 6, /*!< Pure CEC Switch */
++ CEC_DEVICE_TYPE_VIDEO_PROCESSOR = 7 /*!< Video Processor */
++} tmdlHdmiCECDeviceType_t;
++
++/*!
++ \enum tmdlHdmiCECServiceIdentMethod_t
++ \brief This enum indicates a Service Indentification Method
++*/
++typedef enum
++{
++ CEC_SERVICE_DIGITAL = 0, /*!< Service identified by digital IDs */
++ CEC_SERVICE_CHANNEL = 1 /*!< Service identified by channel */
++} tmdlHdmiCECServiceIdentMethod_t;
++
++/*!
++ \enum tmdlHdmiCECDigitalBroadcastSystem_t
++ \brief This enum indicates the Digital Broadcast System of required service
++*/
++typedef enum
++{
++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC = 0x01, /*!< ARIB generic */
++ CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC = 0x02, /*!< ATSC generic */
++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC = 0x03, /*!< DVB generic */
++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_BS = 0x08, /*!< ARIB-BS */
++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_CS = 0x09, /*!< ARIB-CS */
++ CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_T = 0x0A, /*!< ARIB-T */
++ CEC_DIGITAL_BROADCAST_SYSTEM_CABLE = 0x10, /*!< Cable */
++ CEC_DIGITAL_BROADCAST_SYSTEM_SATELLITE = 0x11, /*!< Satellite */
++ CEC_DIGITAL_BROADCAST_SYSTEM_TERRESTRIAL = 0x12, /*!< Terrestrial */
++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_C = 0x18, /*!< DVB-C */
++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_S = 0x19, /*!< DVB-S */
++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_S2 = 0x1A, /*!< DVB-S2 */
++ CEC_DIGITAL_BROADCAST_SYSTEM_DVB_T = 0x1B /*!< DVB-T */
++} tmdlHdmiCECDigitalBroadcastSystem_t;
++
++/*!
++ \struct tmdlHdmiCECAribData_t
++ \brief This struct indicates the ARIB Data
++*/
++typedef struct
++{
++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */
++ UInt16 ServiceID ; /*!< Service_ID of the required service */
++ UInt16 OriginalNetworkID ; /*!< Original_network_ID of the network carrying the transport stream for the required service */
++} tmdlHdmiCECAribData_t ;
++
++/*!
++ \struct tmdlHdmiCECAtscData_t
++ \brief This struct indicates the ATSC Data
++*/
++typedef struct
++{
++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */
++ UInt16 ProgramNumber ; /*!< Program Number of the required service */
++ UInt16 Reserved ; /*!< Reserved */
++} tmdlHdmiCECAtscData_t ;
++
++/*!
++ \struct tmdlHdmiCECDvbData_t
++ \brief This struct indicates the DVB Data
++*/
++typedef struct
++{
++ UInt16 TransportStreamID ; /*!< Tansport_stream_id of the transport stream carrying the required service */
++ UInt16 ServiceID ; /*!< Service_ID of the required service */
++ UInt16 OriginalNetworkID ; /*!< Original_network_ID of the network carrying the transport stream for the required service */
++} tmdlHdmiCECDvbData_t ;
++
++/*!
++ \struct tmdlHdmiCECChannelData_t
++ \brief This struct indicates the Channel Data
++*/
++typedef struct
++{
++ tmdlHdmiCECChannelIdentifier_t ChannelIdentifier ; /*!< Logical or virtual channel number of a service */
++ UInt16 Reserved ; /*!< Reserved */
++} tmdlHdmiCECChannelData_t ;
++
++/*!
++ \struct tmdlHdmiCECDigitalServiceIdentification_t
++ \brief This struct indicates the Digital Broadcast System
++ and the parameters to identify a specific service
++*/
++typedef struct _tmdlHdmiCECDigitalServiceIdentification_t
++{
++ tmdlHdmiCECServiceIdentMethod_t ServiceIdentificationMethod ; /*!< See tmdlHdmiCECServiceIdentMethod_t */
++ tmdlHdmiCECDigitalBroadcastSystem_t DigitalBroadcastSystem ; /*!< See tmdlHdmiCECDigitalBroadcastSystem_t */
++ void *pServiceIdentification ; /*!< tmdlHdmiCECAribData_t or tmdlHdmiCECAtscData_t or tmdlHdmiCECDvbData_t or tmdlHdmiCECChannelData_t */
++}tmdlHdmiCECDigitalServiceIdentification_t, *ptmdlHdmiCECDigitalServiceIdentification_t;
++
++/*!
++ \enum tmdlHdmiCECDisplayControl_t
++ \brief This enum indicates the display mode for an on screen display message
++*/
++typedef enum
++{
++ CEC_DISPLAY_CONTROL_DEFAULT_TIME = 0 , /*!< Display for default time */
++ CEC_DISPLAY_CONTROL_UNTIL_CLEARED = 64 , /*!< Display until cleared */
++ CEC_DISPLAY_CONTROL_CLEAR_PREVIOUS_MESSAGE = 128, /*!< Clear previous message */
++ CEC_DISPLAY_CONTROL_RESERVED = 192 /*!< Clear previous message */
++} tmdlHdmiCECDisplayControl_t;
++
++/*!
++ \struct tmdlHdmiCECDuration_t
++ \brief This struct indicates a duration in BCD format
++*/
++typedef struct
++{
++ UInt8 Hours ; /*!< Duration hours in bcd format between 0 and 99 */
++ UInt8 Minute ; /*!< Duration minute in bcd format between 0 and 59 */
++} tmdlHdmiCECDuration_t ;
++
++/*!
++ \brief This typedef indicates physical adress of device that is to be used as the source of a recording
++*/
++typedef UInt16 tmdlHdmiCECExternalPhysicalAddress_t ;
++
++/*!
++ \brief This typedef indicates external plug number (1 to 255 )on the recording device
++*/
++typedef UInt8 tmdlHdmiCECExternalPlug_t;
++
++/*!
++ \enum tmdlHdmiCECExternalSourceSpecifier_t
++ \brief This enum indicates External source specifier
++*/
++typedef enum
++{
++ CEC_EXTERNAL_PLUG = 4 , /*!< Display for default time */
++ CEC_EXTERNAL_PHYSICAL_ADDRESS = 5 /*!< Display until cleared */
++} tmdlHdmiCECExternalSourceSpecifier_t;
++
++/*!
++ \brief This typedef indicates External Source is specified bey exeternal plug number on the recording device
++ or by the External physical Adress of the required source
++*/
++typedef UInt8 ExternalSourceSpecifier;
++
++
++/*!
++ \enum tmdlHdmiCECFeatureOpcode_t
++ \brief This enum defines command to be performed
++*/
++typedef enum
++{
++ CEC_OPCODE_FEATURE_ABORT = 0x00, /*!< */
++ CEC_OPCODE_IMAGE_VIEW_ON = 0x04, /*!< */
++ CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05, /*!< */
++ CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06, /*!< */
++ CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07, /*!< */
++ CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08, /*!< */
++ CEC_OPCODE_RECORD_ON = 0x09, /*!< */
++ CEC_OPCODE_RECORD_STATUS = 0x0A, /*!< */
++ CEC_OPCODE_RECORD_OFF = 0x0B, /*!< */
++ CEC_OPCODE_TEXT_VIEW_ON = 0x0D, /*!< */
++ CEC_OPCODE_RECORD_TV_SCREEN = 0x0F, /*!< */
++ CEC_OPCODE_GIVE_DECK_STATUS = 0x1A, /*!< */
++ CEC_OPCODE_DECK_STATUS = 0x1B, /*!< */
++ CEC_OPCODE_SET_MENU_LANGUAGE = 0x32, /*!< */
++ CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33, /*!< */
++ CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34, /*!< */
++ CEC_OPCODE_TIMER_STATUS = 0x35, /*!< */
++ CEC_OPCODE_STANDBY = 0x36, /*!< */
++ CEC_OPCODE_PLAY = 0x41, /*!< */
++ CEC_OPCODE_DESCK_CONTROL = 0x42, /*!< */
++ CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43, /*!< */
++ CEC_OPCODE_USER_CONTROL_PRESSED = 0x44, /*!< */
++ CEC_OPCODE_USER_CONTROL_RELEASED = 0x45, /*!< */
++ CEC_OPCODE_GIVE_OSD_NAME = 0x46, /*!< */
++ CEC_OPCODE_SET_OSD_NAME = 0x47, /*!< */
++ CEC_OPCODE_SET_OSD_STRING = 0x64, /*!< */
++ CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67, /*!< */
++ CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, /*!< */
++ CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71, /*!< */
++ CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72, /*!< */
++ CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A, /*!< */
++ CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, /*!< */
++ CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, /*!< */
++ CEC_OPCODE_ROUTING_CHANGE = 0x80, /*!< */
++ CEC_OPCODE_ROUTING_INFORMATION = 0x81, /*!< */
++ CEC_OPCODE_ACTIVE_SOURCE = 0x82, /*!< */
++ CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83, /*!< */
++ CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84, /*!< */
++ CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85, /*!< */
++ CEC_OPCODE_SET_STREAM_PATH = 0x86, /*!< */
++ CEC_OPCODE_DEVICE_VENDOR_ID = 0x87, /*!< */
++ CEC_OPCODE_VENDOR_COMMAND = 0x89, /*!< */
++ CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, /*!< */
++ CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B, /*!< */
++ CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C, /*!< */
++ CEC_OPCODE_MENU_REQUEST = 0x8D, /*!< */
++ CEC_OPCODE_MENU_STATUS = 0x8E, /*!< */
++ CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F, /*!< */
++ CEC_OPCODE_REPORT_POWER_STATUS = 0x90, /*!< */
++ CEC_OPCODE_GET_MENU_LANGUAGE = 0x91, /*!< */
++ CEC_OPCODE_SET_ANALOGUE_SERVICE = 0x92, /*!< */
++ CEC_OPCODE_SET_DIGITAL_SERVICE = 0x93, /*!< */
++ CEC_OPCODE_SET_DIGITAL_TIMER = 0x97, /*!< */
++ CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99, /*!< */
++ CEC_OPCODE_SET_AUDIO_RATE = 0x9A, /*!< */
++ CEC_OPCODE_INACTIVE_SOURCE = 0x9D, /*!< */
++ CEC_OPCODE_CEC_VERSION = 0x9E, /*!< */
++ CEC_OPCODE_GET_CEC_VERSION = 0x9F, /*!< */
++ CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0, /*!< */
++ CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1, /*!< */
++ CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2, /*!< */
++ CEC_OPCODE_REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3, /*!< */
++ CEC_OPCODE_REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4, /*!< */
++ CEC_OPCODE_INITATE_ARC = 0xC0, /*!< */
++ CEC_OPCODE_REPORT_ARC_INITIATED = 0xC1, /*!< */
++ CEC_OPCODE_REPORT_ARC_TERMINATED = 0xC2, /*!< */
++ CEC_OPCODE_REPORT_ARC_INITIATION = 0xC3, /*!< */
++ CEC_OPCODE_REPORT_ARC_TERMINATION = 0xC4, /*!< */
++ CEC_OPCODE_TERMINATE_ARC = 0xC5, /*!< */
++ CEC_OPCODE_ABORT_MESSAGE = 0xFF /*!< This message is reserved for testing*/
++} tmdlHdmiCECFeatureOpcode_t;
++
++
++/*!
++ \enum tmdlHdmiCECMenuRequestType_t
++ \brief This enum specifies wether to activate or desactivate a devices menu or
++ simply query its current menu status
++*/
++typedef enum
++{
++ CEC_MENU_TYPE_ACTIVATE = 0 , /*!< Activate */
++ CEC_MENU_TYPE_DEACTIVATE = 1 , /*!< Deactivate */
++ CEC_MENU_TYPE_QUERY = 2 /*!< Query */
++} tmdlHdmiCECMenuRequestType_t;
++
++/*!
++ \enum tmdlHdmiCECMenuState_t
++ \brief This enum pecifies state of the device menu
++*/
++typedef enum
++{
++ CEC_MENU_STATE_ACTIVATE = 0 , /*!< Activate */
++ CEC_MENU_STATE_DEACTIVATE = 1 /*!< Deactivate */
++} tmdlHdmiCECMenuState_t;
++
++/*!
++ \enum tmdlHdmiCECPlayMode_t
++ \brief This enum indicates in which mode to play media
++*/
++typedef enum
++{
++ CEC_MODE_PLAY_FORWARD = 0x24 ,
++ CEC_MODE_PLAY_REVERSE = 0x20 ,
++ CEC_MODE_FAST_FORWARD_MIN_SPEED = 0x05 ,
++ CEC_MODE_FAST_FORWARD_MEDIUM_SPEED = 0x06 ,
++ CEC_MODE_FAST_FORWARD_MAX_SPEED = 0x07 ,
++ CEC_MODE_FAST_REVERSE_MIN_SPEED = 0x09 ,
++ CEC_MODE_FAST_REVERSE_MEDIUM_SPEED = 0x0A ,
++ CEC_MODE_FAST_REVERSE_MAX_SPEED = 0x0B ,
++ CEC_MODE_SLOW_FORWARD_MIN_SPEED = 0x15 ,
++ CEC_MODE_SLOW_FORWARD_MEDIUM_SPEED = 0x16 ,
++ CEC_MODE_SLOW_FORWARD_MAX_SPEED = 0x17 ,
++ CEC_MODE_SLOW_REVERSE_MIN_SPEED = 0x19 ,
++ CEC_MODE_SLOW_REVERSE_MEDIUM_SPEED = 0x1A ,
++ CEC_MODE_SLOW_REVERSE_MAX_SPEED = 0x1B
++} tmdlHdmiCECPlayMode_t;
++
++/*!
++ \enum tmdlHdmiCECPowerStatus_t
++ \brief This enum indicates the current power status of a device
++*/
++typedef enum
++{
++ CEC_POWER_STATUS_ON = 0x00 , /*!< On */
++ CEC_POWER_STATUS_STANDBY = 0x01 , /*!< Standby */
++ CEC_POWER_STATUS_TRANSITION_STANDBY_TO_ON = 0x02 , /*!< In Transition Standby to On */
++ CEC_POWER_STATUS_TRANSITION_ON_TO_STANDBY = 0x03 /*!< In Transition On to StandBy */
++} tmdlHdmiCECPowerStatus_t;
++
++/*!
++ \enum tmdlHdmiCECRecordSourceType_t
++ \brief This enum allows the record source to be specified for a recording
++*/
++typedef enum
++{
++ CEC_RECORD_SOURCE_OWN_SOURCE = 1 , /*!< Own Source */
++ CEC_RECORD_SOURCE_DIGITAL_SERVICE = 2 , /*!< Digital Service */
++ CEC_RECORD_SOURCE_ANALOGUE_SERVICE = 3 , /*!< Analogue Service */
++ CEC_RECORD_SOURCE_EXTERNAL_PLUG = 4 , /*!< External Plug */
++ CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS = 5 /*!< External Physical Address */
++} tmdlHdmiCECRecordSourceType_t;
++
++/*!
++ \enum tmdlHdmiCECRecordStatusInfo_t
++ \brief This enum indicates the status of a recording
++*/
++typedef enum
++{
++ CEC_RECORD_STATUS_INFO_RECORDING_CURRENTLY_SELECTED_SOURCE = 1 , /*!< */
++ CEC_RECORD_STATUS_INFO_RECORDING_DIGITAL_SERVICE = 2 , /*!< */
++ CEC_RECORD_STATUS_INFO_RECORDING_ANALOGUE_SERVCICE = 3 , /*!< */
++ CEC_RECORD_STATUS_INFO_RECORDING_EXTERNAL_INPUT = 4 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_RECORD_DIGITAL_SERVICE = 5 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_RECORD_ANALOGUE_SERVICE = 6 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_UNABLE_TO_SELECT_REQUIRED_SERVICE = 7 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_INVALID_EXTERNAL_PLUG_NUMBER = 9 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 10 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_CA_SYSTEM_NOT_SUPPORTED = 11 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 12 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NOT_ALLOWED_TO_COPY_SOURCE = 13 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NO_FURTHER_COPY_ALLOWED = 14 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NO_MEDIA = 16 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_PLAYING = 17 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_ALREADY_RECORDING = 18 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_MEDIA_PROTECTED = 19 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NO_SOURCE_SIGNAL = 20 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_MEDIA_PROBLEM = 21 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_NOT_ENOUGH_SPACE_AVAILABLE = 22 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_REC_PARENTAL_LOCK_ON = 23 , /*!< */
++ CEC_RECORD_STATUS_INFO_RECORDING_TERMINATED_NORMALLY = 26 , /*!< */
++ CEC_RECORD_STATUS_INFO_RECORDING_HAS_ALREADY_TERMINATED = 27 , /*!< */
++ CEC_RECORD_STATUS_INFO_NO_RECORDING_OTHER_REASON = 31 /*!< */
++} tmdlHdmiCECRecordStatusInfo_t;
++
++
++/*!
++ \enum tmdlHdmiCECRecordingSequence_t
++ \brief This enum indicates the status of a recording
++*/
++typedef enum
++{
++ CEC_RECORDING_SEQUENCE_ONCE_ONLY = 0 , /*!< */
++ CEC_RECORDING_SEQUENCE_SYNDAY = 1 , /*!< */
++ CEC_RECORDING_SEQUENCE_MONDAY = 2 , /*!< */
++ CEC_RECORDING_SEQUENCE_TUESDAY = 4 , /*!< */
++ CEC_RECORDING_SEQUENCE_WEDNESDAY = 8 , /*!< */
++ CEC_RECORDING_SEQUENCE_THURSDAY = 16, /*!< */
++ CEC_RECORDING_SEQUENCE_FRIDAY = 32, /*!< */
++ CEC_RECORDING_SEQUENCE_SATURDAY = 64 /*!< */
++} tmdlHdmiCECRecordingSequence_t;
++
++/*!
++ \enum tmdlHdmiCECStatusRequest_t
++ \brief This enum contains the status request mode which can be report once or
++ on all future state changes or reporting off.
++*/
++typedef enum
++{
++ CEC_STATUS_REQUEST_ON = 1 , /*!< Status Request ON */
++ CEC_STATUS_REQUEST_OFF = 2 , /*!< Status Request OFF */
++ CEC_STATUS_REQUEST_ONCE = 3 /*!< Status Request ONCE */
++} tmdlHdmiCECStatusRequest_t;
++
++/*!
++ \enum tmdlHdmiCECSystemAudioStatus_t
++ \brief This enum indicates if the system audio Mode is On or Off
++*/
++typedef enum
++{
++ CEC_SYSTEM_AUDIO_STATUS_OFF = 0 , /*!< Status Request OFF */
++ CEC_SYSTEM_AUDIO_STATUS_ON = 1 /*!< Status Request ON */
++} tmdlHdmiCECSystemAudioStatus_t;
++
++/*!
++ \enum tmdlHdmiCECTimerClearedStatusData_t
++ \brief This enum indicates status in <Timer Cleared Status> message
++*/
++typedef enum
++{
++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0, /*!< */
++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 1, /*!< */
++ CEC_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 2, /*!< */
++ CEC_TIMER_STATUS_TIMER_NOT_TIMER_CLEARED = 128 /*!< */
++} tmdlHdmiCECTimerClearedStatusData_t;
++
++
++/*!
++ \enum tmdlHdmiCECTimerOverlapWarning_t
++ \brief This enum indicates if there is another timer block already set which
++ overlaps with this new recording request
++*/
++typedef enum
++{
++ CEC_TIMER_OVERLAP_WARNING_NO_OVERLAP = 0, /*!< No Overlap */
++ CEC_TIMER_OVERLAP_WARNING_TIMER_BLOCKS_OVERLAP = 1 /*!< Timer blocks overlap */
++} tmdlHdmiCECTimerOverlapWarning_t;
++
++/*!
++ \enum tmdlHdmiCECMediaInfo_t
++ \brief This enum indicates if removable media is present and its write protect state
++*/
++typedef enum
++{
++ CEC_MEDIA_INFO_MEDIA_PRESENT_AND_NOT_PROTECTED = 0, /*!< Media present and not protected */
++ CEC_MEDIA_INFO_MEDIA_PRESENT_BUT_PROTECTED = 1, /*!< Media present but protected */
++ CEC_MEDIA_INFO_MEDIA_NOT_PRESENT = 2, /*!< Media not present */
++ CEC_MEDIA_INFO_FUTURE_USE = 3 /*!< Future use */
++} tmdlHdmiCECMediaInfo_t;
++
++
++/*!
++ \enum tmdlHdmiCECProgrammedIndicator_t
++ \brief This enum indicates a selector for [Timer Programmed Info]
++*/
++typedef enum
++{
++ CEC_PROGRAM_INDICATOR_NOT_PROGRAMMED = 0, /*!< */
++ CEC_PROGRAM_INDICATOR_PROGRAMMED = 1 /*!< */
++} tmdlHdmiCECProgrammedIndicator_t;
++
++/*!
++ \enum tmdlHdmiCECProgrammedInfo_t
++ \brief This enum indicates any non-fatal issues with the programming request
++*/
++typedef enum
++{
++ CEC_PROGRAM_INFO_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING = 8, /*!< */
++ CEC_PROGRAM_INFO_NOT_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING = 9, /*!< */
++ CEC_PROGRAM_INFO_NO_MEDIA_INFO_AVAILABLE = 10,/*!< */
++ CEC_PROGRAM_INFO_MAY_NOT_BE_ENOUGH_SPACE_AVAILABLE = 11 /*!< */
++} tmdlHdmiCECProgrammedInfo_t;
++
++
++/*!
++ \enum tmdlHdmiCECNotProgrammedErrorInfo_t
++ \brief This enum indicates reason for programming failure
++*/
++typedef enum
++{
++ CEC_PROGRAM_ERROR_INFO_FUTURE_USE = 0, /*!< */
++ CEC_PROGRAM_ERROR_INFO_NO_FREE_TIMER_AVAILABLE = 1, /*!< */
++ CEC_PROGRAM_ERROR_INFO_DATE_OUT_OF_RANGE = 2, /*!< */
++ CEC_PROGRAM_ERROR_INFO_RECORDING_SEQUENCE_ERROR = 3, /*!< */
++ CEC_PROGRAM_ERROR_INFO_INVALID_EXTERNAL_PLUG_NUMBER = 4, /*!< */
++ CEC_PROGRAM_ERROR_INFO_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 5, /*!< */
++ CEC_PROGRAM_ERROR_INFO_CA_SYSTEM_NOT_SUPPORTED = 6, /*!< */
++ CEC_PROGRAM_ERROR_INFO_NO_OR_INSUFFICIENT_CA_ENTITLMENTS = 7, /*!< */
++ CEC_PROGRAM_ERROR_INFO_DOES_NOT_SUPPORT_RESOLUTION = 8, /*!< Tuner or recorder does not support HD */
++ CEC_PROGRAM_ERROR_INFO_PARENTAL_LOCK_ON = 9, /*!< */
++ CEC_PROGRAM_ERROR_INFO_CLOCK_FAILURE = 10, /*!< */
++ CEC_PROGRAM_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED = 14 /*!< A timer block with identical details has already been programmed*/
++} tmdlHdmiCECNotProgrammedErrorInfo_t;
++
++/*!
++ \struct tmdlHdmiCECTimerProgrammedInfo_t
++ \brief This struct
++*/
++typedef struct
++{
++ tmdlHdmiCECProgrammedIndicator_t SelectProgramInfo ; /*!< tmdlHdmiCECProgrammedIndicator_t */
++ UInt8 ProgramInfo; /*!< tmdlHdmiCECProgrammedInfo_t or tmdlHdmiCECNotProgrammedErrorInfo_t*/
++ UInt16 DurationAvailable ; /*!< Optional paramter : If [Programmed Info] is "Not enough space available" */
++} tmdlHdmiCECTimerProgrammedInfo_t ; /*!< If [Not Programmed Info] is "Duplicate : already programmed" */
++
++/*!
++ \struct tmdlHdmiCECTimerStatusData_t
++ \brief This struct is used by recording device to respond to the initiator
++ of a <Set Timer> message
++*/
++typedef struct
++{
++ tmdlHdmiCECTimerOverlapWarning_t TimerOverlapWarning ; /*!< Indicates if there is another timer block already set which overlaps with this bew recording request*/
++ tmdlHdmiCECMediaInfo_t MediaInfo ; /*!< Indicate if removable media is present and its write protect state */
++ tmdlHdmiCECTimerProgrammedInfo_t TimerProgrammedInfo ; /*!< Give information about how and if the programming request has been done */
++} tmdlHdmiCECTimerStatusData_t ;
++
++
++/*!
++ \enum tmdlHdmiCECRecordingFlag_t
++ \brief This enum indicates if the tuner is being used as a source of a recording
++*/
++typedef enum
++{
++ CEC_RECORDING_FLAG_NOT_BEING_USED_FOR_RECORDING = 0, /*!< Not Being used for recording */
++ CEC_RECORDING_FLAG_BEING_USED_FOR_RECORDING = 1 /*!< Being used for recording */
++} tmdlHdmiCECRecordingFlag_t;
++
++/*!
++ \enum tmdlHdmiCECTunerDisplayInfo_t
++ \brief This enum indicates if the device is currently displaying its tuner or not.
++ (it may for example be displaying an external source or media)
++*/
++typedef enum
++{
++ CEC_TUNER_DISPLAY_MEDIA_DISPLAYING_DIGITAL_TUNER = 0, /*!< Displaying Digital Tuner */
++ CEC_TUNER_DISPLAY_MEDIA_NOT_DISPLAYING_TUNER = 1, /*!< Not Displaying Tuner */
++ CEC_TUNER_DISPLAY_MEDIA_DISPLAYING_ANALOGUE_TUNER = 2 /*!< Not Displaying Tuner */
++} tmdlHdmiCECTunerDisplayInfo_t;
++
++/*!
++ \enum tmdlHdmiCECUiBroadcastType_t
++ \brief This enum indicates type of broadcast
++*/
++typedef enum
++{
++ CEC_UI_BROADCAST_TYPE_ALL_AVAILABLE = 0x00 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_ANALOGUE_TOGGLE = 0x01 , /*!< */
++ CEC_UI_BROADCAST_TYPE_ANALOGUE = 0x10 , /*!< */
++ CEC_UI_BROADCAST_TYPE_ANALOGUE_TERRESTRIAL = 0x20 , /*!< */
++ CEC_UI_BROADCAST_TYPE_ANALOGUE_CABLE = 0x30 , /*!< */
++ CEC_UI_BROADCAST_TYPE_ANALOGUE_SATELLITE = 0x40 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL = 0x50 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_TERRESTRIAL = 0x60 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_CABLE = 0x70 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_SATELLITE = 0x80 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_COM_SATELLITE = 0x90 , /*!< */
++ CEC_UI_BROADCAST_TYPE_DIGITAL_COM_SATELLITE_2 = 0x91 , /*!< */
++ CEC_UI_BROADCAST_TYPE_IP = 0xA0 /*!< */
++} tmdlHdmiCECUiBroadcastType_t;
++
++/*!
++ \enum tmdlHdmiCECUiSoundPresentationControl_t
++ \brief This enum indicates the selected command
++*/
++typedef enum
++{
++ CEC_UI_PRESENTATION_CONTROL_SOUND_MIX_DUAL_MONO = 0x20 , /*!< "Sound Mixing Mode (Dual Mono)" */
++ CEC_UI_PRESENTATION_CONTROL_SOUND_MIX_KARAOKE = 0x30 , /*!< "Sound Mixing Mode (Karaoke)" */
++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_DOWNMIX = 0x80 , /*!< "Select Audio Downmix Mode" */
++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_REVERBERATION = 0x90 , /*!< "Select Audio Reverberation Processing Mode" */
++ CEC_UI_PRESENTATION_CONTROL_SELECT_AUDIO_EQUALIZER = 0xA0 , /*!< "Select Audio Equalizer Mode" */
++ CEC_UI_PRESENTATION_CONTROL_BASS_STEP_PLUS = 0xB1 , /*!< "bass step + " */
++ CEC_UI_PRESENTATION_CONTROL_BASS_NEUTRAL_POSITION = 0xB2 , /*!< "bass neutral position" */
++ CEC_UI_PRESENTATION_CONTROL_BASS_STEP_MINUS = 0xB3 , /*!< "bass step - " */
++ CEC_UI_PRESENTATION_CONTROL_TREBLE_STEP_PLUS = 0xC1 , /*!< "Treble step + " */
++ CEC_UI_PRESENTATION_CONTROL_TREBLE_NEUTRAL_POSITION = 0xC2 , /*!< "Treble neutral position" */
++ CEC_UI_PRESENTATION_CONTROL_TREBLE_STEP_MINUS = 0xC3 /*!< "Treble step - " */
++
++} tmdlHdmiCECUiSoundPresentationControl_t;
++
++/*!
++ \enum tmdlHdmiCECUserRemoteControlCommand_t
++ \brief This enum indicates the remote control button pressed
++*/
++typedef enum
++{
++ CEC_REMOTE_BUTTON_SELECT = 0,
++ CEC_REMOTE_BUTTON_UP = 1,
++ CEC_REMOTE_BUTTON_DOWN = 2,
++ CEC_REMOTE_BUTTON_LEFT = 3,
++ CEC_REMOTE_BUTTON_RIGHT = 4,
++ CEC_REMOTE_BUTTON_RIGHT_UP = 5,
++ CEC_REMOTE_BUTTON_RIGHT_DOWN = 6,
++ CEC_REMOTE_BUTTON_LEFT_UP = 7,
++ CEC_REMOTE_BUTTON_LEFT_DOWN = 8,
++ CEC_REMOTE_BUTTON_ROOT_MENU = 9,
++ CEC_REMOTE_BUTTON_SETUP_MENU = 10,
++ CEC_REMOTE_BUTTON_CONTENTS_MENU = 11,
++ CEC_REMOTE_BUTTON_FAVORITE_MENU = 12,
++ CEC_REMOTE_BUTTON_EXIT = 13,
++ CEC_REMOTE_BUTTON_MEDIA_TOP_MENU = 16,
++ CEC_REMOTE_BUTTON_MEDIA_CONTEXT = 17,
++ CEC_REMOTE_BUTTON_NUMBER_ENTRY_MODE = 29,
++ CEC_REMOTE_BUTTON_NUMBER_11 = 30,
++ CEC_REMOTE_BUTTON_NUMBER_12 = 31,
++ CEC_REMOTE_BUTTON_NUMBER_0_OR_NUMBER_10 = 32,
++ CEC_REMOTE_BUTTON_NUMBER_1 = 33,
++ CEC_REMOTE_BUTTON_NUMBER_2 = 34,
++ CEC_REMOTE_BUTTON_NUMBER_3 = 35,
++ CEC_REMOTE_BUTTON_NUMBER_4 = 36,
++ CEC_REMOTE_BUTTON_NUMBER_5 = 37,
++ CEC_REMOTE_BUTTON_NUMBER_6 = 38,
++ CEC_REMOTE_BUTTON_NUMBER_7 = 39,
++ CEC_REMOTE_BUTTON_NUMBER_8 = 40,
++ CEC_REMOTE_BUTTON_NUMBER_9 = 41,
++ CEC_REMOTE_BUTTON_DOT = 42,
++ CEC_REMOTE_BUTTON_ENTER = 43,
++ CEC_REMOTE_BUTTON_CLEAR = 44,
++ CEC_REMOTE_BUTTON_NEXT_FAVORITE = 47,
++ CEC_REMOTE_BUTTON_CHANNEL_UP = 48,
++ CEC_REMOTE_BUTTON_CHANNEL_DOWN = 49,
++ CEC_REMOTE_BUTTON_PREVIOUS_CHANNEL = 50,
++ CEC_REMOTE_BUTTON_SOUND_SELECT = 51,
++ CEC_REMOTE_BUTTON_INPUT_SELECT = 52,
++ CEC_REMOTE_BUTTON_DISPLAY_INFORMATION = 53,
++ CEC_REMOTE_BUTTON_HELP = 54,
++ CEC_REMOTE_BUTTON_PAGE_UP = 55,
++ CEC_REMOTE_BUTTON_PAGE_DOWN = 56,
++ CEC_REMOTE_BUTTON_POWER = 64,
++ CEC_REMOTE_BUTTON_VOLUME_UP = 65,
++ CEC_REMOTE_BUTTON_VOLUME_DOWN = 66,
++ CEC_REMOTE_BUTTON_MUTE = 67,
++ CEC_REMOTE_BUTTON_PLAY = 68,
++ CEC_REMOTE_BUTTON_STOP = 69,
++ CEC_REMOTE_BUTTON_PAUSE = 70,
++ CEC_REMOTE_BUTTON_RECORD = 71,
++ CEC_REMOTE_BUTTON_REWIND = 72,
++ CEC_REMOTE_BUTTON_FAST_FORWARD = 73,
++ CEC_REMOTE_BUTTON_EJECT = 74,
++ CEC_REMOTE_BUTTON_FORWARD = 75,
++ CEC_REMOTE_BUTTON_BACKWARD = 76,
++ CEC_REMOTE_BUTTON_STOP_RECORD = 77,
++ CEC_REMOTE_BUTTON_PAUSE_RECORD = 78,
++ CEC_REMOTE_BUTTON_ANGLE = 80,
++ CEC_REMOTE_BUTTON_SUB_PICTURE = 81,
++ CEC_REMOTE_BUTTON_VIDEO_ON_DEMAND = 82,
++ CEC_REMOTE_BUTTON_ELECTRONIC_PROGRAM_GUIDE = 83,
++ CEC_REMOTE_BUTTON_TIMER_PROGRAMMING = 84,
++ CEC_REMOTE_BUTTON_INITIAL_CONFIGURATION = 85,
++ CEC_REMOTE_BUTTON_SELECT_BROADCAST_TYPE = 86,
++ CEC_REMOTE_BUTTON_SELECT_SOUND_PRESENTATION = 87,
++ CEC_REMOTE_BUTTON_PLAY_FUNCTION = 96,
++ CEC_REMOTE_BUTTON_PAUSE_PLAY_FUNCTION = 97,
++ CEC_REMOTE_BUTTON_RECORD_FUNCTION = 98,
++ CEC_REMOTE_BUTTON_PAUSE_RECORD_FUNCTION = 99,
++ CEC_REMOTE_BUTTON_STOP_FUNCTION = 100,
++ CEC_REMOTE_BUTTON_MUTE_FUNCTION = 101,
++ CEC_REMOTE_BUTTON_RESTORE_VOLUME_FUNCTION = 102,
++ CEC_REMOTE_BUTTON_TUNE_FUNCTION = 103,
++ CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION = 104,
++ CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION = 105,
++ CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION = 106,
++ CEC_REMOTE_BUTTON_POWER_TOGGLE_FUNCTION = 107,
++ CEC_REMOTE_BUTTON_POWER_OFF_FUNCTION = 108,
++ CEC_REMOTE_BUTTON_POWER_ON_FUNCTION = 109,
++ CEC_REMOTE_BUTTON_F1_BLUE = 113,
++ CEC_REMOTE_BUTTON_F2_RED = 114,
++ CEC_REMOTE_BUTTON_F3_GREEN = 115,
++ CEC_REMOTE_BUTTON_F4_YELLOW = 116,
++ CEC_REMOTE_BUTTON_F5 = 117,
++ CEC_REMOTE_BUTTON_DATA = 118
++} tmdlHdmiCECUserRemoteControlCommand_t;
++
++/*!
++ \enum tmdlHdmiCECLogicalAddress_t
++ \brief This enum indicates the logical address of the a device
++*/
++typedef enum
++{
++ CEC_LOGICAL_ADDRESS_TV = 0, /*!< TV */
++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1 = 1, /*!< Recording Device 1 */
++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2 = 2, /*!< Recording Device 1 */
++ CEC_LOGICAL_ADDRESS_TUNER_1 = 3, /*!< Tuner 1 */
++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1 = 4, /*!< Playback Device 1 */
++ CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM = 5, /*!< Audio System */
++ CEC_LOGICAL_ADDRESS_TUNER_2 = 6, /*!< Tuner 2 */
++ CEC_LOGICAL_ADDRESS_TUNER_3 = 7, /*!< Tuner 3 */
++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2 = 8, /*!< Playback Device 2 */
++ CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3 = 9, /*!< Recording Device 3 */
++ CEC_LOGICAL_ADDRESS_TUNER_4 = 10, /*!< Tuner 4 */
++ CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3 = 11, /*!< Playback Device 3 */
++ CEC_LOGICAL_ADDRESS_RESERVED1 = 12, /*!< Reserved */
++ CEC_LOGICAL_ADDRESS_RESERVED2 = 13, /*!< Reserved */
++ CEC_LOGICAL_ADDRESS_SPECIFIC_USE = 14, /*!< Specific Use */
++ CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST = 15 /*!< Unregistred/Broadcast */
++} tmdlHdmiCECLogicalAddress_t;
++
++
++/*!
++ \enum tmdlHdmiCecEvent_t
++ \brief Enum listing all events that can be signalled to application
++ */
++typedef enum
++{
++ TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE = 0, /**< A message is available on CEC line */
++ TMDL_HDMICEC_CALLBACK_STATUS = 1, /**< Status of CEC line */
++} tmdlHdmiCecEvent_t;
++
++/*!
++ \enum tmdlHdmiCecEventStatus_t
++ \brief Enum listing all available event status
++ */
++typedef enum
++{
++ TMDL_HDMICEC_EVENT_ENABLED, /*!< Event is enabled */
++ TMDL_HDMICEC_EVENT_DISABLED /*!< Event is disabled */
++} tmdlHdmiCecEventStatus_t;
++
++/**
++ * \brief System function pointer type, to call user I2C read/write functions
++ * \param slaveAddr The I2C slave address
++ * \param firstRegister The first device register address to read or write
++ * \param lenData Length of data to read or write (i.e. no. of registers)
++ * \param pData Pointer to data to write, or to buffer to receive data
++ * \return The call result:
++ * - TM_OK: the call was successful
++ * - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing
++ * - TMBSL_ERR_HDMI_I2C_READ: failed when reading
++ */
++typedef struct
++{
++ UInt8 slaveAddr;
++ UInt8 firstRegister;
++ UInt8 lenData;
++ UInt8 *pData;
++} tmdlHdmiCecSysArgs_t;
++typedef tmErrorCode_t (*ptmdlHdmiCecSysFunc_t) (tmdlHdmiCecSysArgs_t *pSysArgs);
++
++
++/*!
++ \brief Timer function pointer type, to call an application timer
++ \param Parameter ms: Delay in milliseconds required
++ */
++typedef Void (*ptmbslHdmiCecSysFuncTimer_t) (UInt16 ms);
++
++/*!
++ \brief Callback function pointer type, used to allow driver to callback
++ application when activity status is changing at input.
++ \param Event Identifier of the source event.
++ */
++typedef void (*ptmdlHdmiCecCallbackFunc_t) (tmdlHdmiCecEvent_t event,
++ UInt8 *pdata,
++ UInt8 size);
++
++/*!
++ \brief Enum listing all supported device versions
++ */
++ typedef enum
++ {
++ TMDL_HDMICEC_DEVICE_UNKNOWN, /*!< HW device is unknown */
++ TMDL_HDMICEC_DEVICE_TDA9950, /*!< HW device is a TDA9950 */
++ TMDL_HDMICEC_DEVICE_TDA9989, /*!< HW device is a TDA9989 */
++ } tmdlHdmiCecDeviceVersion_t;
++
++
++/*!
++ \brief Enum listing possible CEC clock source
++ */
++ typedef enum
++ {
++ TMDL_HDMICEC_CLOCK_XTAL,
++ TMDL_HDMICEC_CLOCK_FRO,
++ TMDL_HDMICEC_CLOCK_PCLK
++ } tmdlHdmiCecClockSource_t;
++
++
++/**
++ * \brief Structure describing unit capabilities
++ */
++typedef struct
++{
++ tmdlHdmiCecDeviceVersion_t DeviceVersion; /*!< HW device version */
++ tmdlHdmiCECVersion_t HdmiCecVersion; /*!< Supported HDMI CEC standard version */
++} tmdlHdmiCecCapabilities_t;
++
++
++/*!
++ \struct tmdlHdmiCECInstanceSetup_t
++ \brief This struct is used to setup CEC driver by application
++ Application setup the device and state of the device.
++*/
++
++typedef struct _tmdlHdmiCecInstanceSetup_t
++{
++ tmdlHdmiCECLogicalAddress_t DeviceLogicalAddress;
++ tmdlHdmiCecClockSource_t cecClockSource;
++// tmdlHdmiCECDeviceState_t DeviceState;
++} tmdlHdmiCecInstanceSetup_t, *ptmdlHdmiCecInstanceSetup_t;
++
++
++/**
++ * \brief The structure of a CEC Data Register Protocol
++*/
++typedef struct
++{
++ UInt8 AddressByte;
++ Bool MessageTypePolling; /* Indicate if it's a poolling message "1" or a normal CEC message "0" */
++ UInt8 Opcode;
++}tmdlHdmiCecSaveMessage_t;
++
++typedef struct
++{
++ UInt8 FrameByteCount;
++ UInt8 AddressByte;
++ UInt8 DataBytes[15];
++}tmdlHdmiCecFrameFormat_t;
++
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMICEC_TYPES_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c
+new file mode 100755
+index 0000000..26df9b3
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC.c
+@@ -0,0 +1,7575 @@
++//=============================================================================
++// Copyright (C) 2007 NXP N.V., All Rights Reserved.
++// This source code and any compilation or derivative thereof is the proprietary
++// information of NXP N.V. and is confidential in nature. Under no circumstances
++// is this software to be exposed to or placed under an Open Source License of
++// any type without the expressed written permission of NXP N.V.
++//=============================================================================
++/*!
++ \file tmdlHdmiCEC.c
++
++ \version 1.0
++
++ \date 24/07/2007
++
++ \brief devlib driver component API for the CEC features.
++
++ \section refs Reference Documents
++ TDA998X Driver - tmdlHdmiTx - SCS.doc
++ \note None.
++
++ HISTORY :
++ \verbatim
++ Date Modified by CRPRNr TASKNr Maintenance description
++ -------------|-----------|-------|-------|-----------------------------------
++ 24/07/2007 | F.G | | | Creation.
++ -------------|-----------|-------|-------|-----------------------------------
++ \endverbatim
++*/
++//==========================================================================
++
++/*============================================================================*/
++/* FILE CONFIGURATION */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* STANDARD INCLUDE FILES */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* PROJECT INCLUDE FILES */
++/*============================================================================*/
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#else
++#include <string.h>
++#include <stdio.h>
++#endif
++#include "tmdlHdmiCEC_IW.h"
++#include "tmdlHdmiCEC_cfg.h"
++#include "tmdlHdmiCEC.h"
++#include "tmdlHdmiCEC_local.h"
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#define DV_DBG_PRINT printk
++#else
++#define DV_DBG_PRINT printf
++#endif
++
++/*============================================================================*/
++/* TYPE DEFINITIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* PUBLIC VARIABLE DEFINITIONS */
++/*============================================================================*/
++tmdlHdmiCecUnitConfig_t UnitTable[MAX_UNITS] = {
++ {0,CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST,False, TMDL_HDMICEC_DEVICE_TDA9950, CEC_STATE_NOT_INITIALIZED, 0}
++};
++
++tmdlHdmiCecDriverConfigTable_t gtmdlHdmiCecDriverConfigTable[MAX_UNITS];
++
++tmdlHdmiCecSaveMessage_t gtmdlHdmiCecDriverSaveMessage;
++
++
++/*============================================================================*/
++/* STATIC CONSTANT DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* STATIC VARIABLE DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* STATIC FUNCTION DECLARATIONS */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* FUNCTIONS */
++/*============================================================================*/
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetSWVersion( )
++ \brief Get the software version of the driver.
++
++ \param pSWVersion Pointer to the version structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetSWVersion
++(
++ tmSWVersion_t *pSWVersion
++)
++{
++ /* check that input pointer is not NULL */
++ RETIF(pSWVersion == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ /* copy SW version */
++ pSWVersion->compatibilityNr = VERSION_COMPATIBILITY;
++ pSWVersion->majorVersionNr = VERSION_MAJOR;
++ pSWVersion->minorVersionNr = VERSION_MINOR;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetNumberOfUnits( )
++ \brief Get the number of available CEC devices in the system.
++ A unit directly represents a physical device.
++
++ \param pUnitCount Pointer to the number of available units.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetNumberOfUnits
++(
++ UInt32 *pUnitCount
++)
++{
++ /* check that input pointer is not NULL */
++ RETIF(pUnitCount == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ /* copy the maximum number of units */
++ *pUnitCount = MAX_UNITS;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetInstanceSetup( )
++ \brief Get instance setup parameters.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure that will receive setup
++ parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetInstanceSetup
++(
++ tmInstance_t instance,
++ ptmdlHdmiCecInstanceSetup_t pSetupInfo
++)
++{
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check that input pointer is not NULL */
++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pSetupInfo->DeviceLogicalAddress = UnitTable[instance].DeviceLogicalAddress;
++
++
++ return(TM_OK);
++}
++
++//========================= =================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecHandleInterrupt( )
++ \brief Make device library handle an incoming interrupt. This function is
++ used by application to tell the device library that the hardware
++ sent an interrupt. It can also be used to poll the interrupt status
++ of the device if the interrupt line is not physically connected to
++ the CPU.
++ This function is synchronous.
++ This function is ISR friendly.
++
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_FULL: the queue is full
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecHandleInterrupt
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_ReadBuffer[19] ; /* I2C Read data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCecUnitConfig_t *pCecObject; /* Pointer to Cec Object */
++ tmdlHdmiCecFrameFormat_t ReadFrame;
++ tmdlHdmiCecSaveMessage_t LastSendMessage;
++ int i;
++
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++ pCecObject = &UnitTable[instance];
++
++#ifdef TMFL_TDA9989
++ //Check if pending CEC interruption
++ errCode = getCecHwRegisters(pDis, E_REG_CEC_INT, I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ if ((I2c_ReadBuffer[0] & CEC_INT_MASK) == 0x00)
++ {
++ //No CEC interruption pending.
++ return TM_OK;
++ }
++#endif
++
++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,19);
++ RETIF(errCode != TM_OK, errCode)
++
++ /*Fill Frame structure with read data*/
++
++ /* Case of Receiving CECData.cnf*/
++ /*Inform Success or reason of failure of CEC message sending*/
++ if (I2c_ReadBuffer[1]== 0x01)
++ {
++ /* Get Infos of last message send */
++ getCecLastMessage(&LastSendMessage);
++
++ if (LastSendMessage.MessageTypePolling)
++ {
++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0];
++ ReadFrame.AddressByte = LastSendMessage.AddressByte;
++ ReadFrame.DataBytes[0]= I2c_ReadBuffer[2];
++ }
++ else
++ {
++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0]+1;
++ ReadFrame.AddressByte = LastSendMessage.AddressByte;
++ ReadFrame.DataBytes[0]= I2c_ReadBuffer[2];
++ ReadFrame.DataBytes[1]= LastSendMessage.Opcode;
++ }
++
++ pCecObject->MessageCallback(TMDL_HDMICEC_CALLBACK_STATUS
++ , (Void *) &ReadFrame, ReadFrame.FrameByteCount);
++ }
++
++ /* Case of Receiving CECData.ind*/
++ /*Give receive data from CEC bus*/
++ if (I2c_ReadBuffer[1]== 0x81)
++ {
++ ReadFrame.FrameByteCount = I2c_ReadBuffer[0];
++ ReadFrame.AddressByte = I2c_ReadBuffer[2];
++ for (i=0; i<15; i++)
++ {
++ ReadFrame.DataBytes[i] = I2c_ReadBuffer[i+3];
++ }
++
++ pCecObject->MessageCallback(TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE
++ , (Void *) &ReadFrame, ReadFrame.FrameByteCount);
++ }
++
++ return(TM_OK);
++
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecOpen( )
++ \brief Open unit 0 of CEC and provides the instance number to
++ the caller. Note that one unit of CEC represents one physical
++ CEC device and that only one instance per unit can be opened.
++
++ \param pInstance Pointer to the variable that will receive the instance
++ identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for
++ the function
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecOpen
++(
++ tmInstance_t *pInstance
++)
++{
++ /* directly call OpenM function for unit 0 and return the result */
++ return(tmdlHdmiCecOpenM(pInstance, (tmUnitSelect_t)0));
++}
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecOpenM( )
++ \brief Open a specific unit of CEC driver and provides the instance
++ number to the caller. Note that one unit of CEC represents one
++ physical CEC device and that only one instance per unit can be
++ opened. This function switches driver's state machine to
++ "initialized" state.
++
++ \param pInstance Pointer to the structure that will receive the instance
++ identifier.
++ \param unit Unit number to be opened.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMICEC_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for
++ the function
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecOpenM
++(
++ tmInstance_t *pInstance,
++ tmUnitSelect_t unit
++)
++{
++
++ /* check if unit number is in range */
++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER)
++
++ /* check if Instance pointer is Null */
++ RETIF(pInstance == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ /* check if unit is already instanciated */
++ RETIF(UnitTable[unit].opened == True, TMDL_ERR_DLHDMICEC_RESOURCE_OWNED)
++
++ /* Ckeck the state */
++ RETIF(UnitTable[unit].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ /* instanciate unit and return corresponding instance number */
++ /* Since HW unit are only instanciable once, instance = unit */
++ UnitTable[unit].opened = True;
++ UnitTable[unit].MessageCallback = Null;
++ /* Give a logical Address to Device */
++ UnitTable[unit].DeviceLogicalAddress = CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++
++ /* Recover the configuration of the device library */
++ RETIF(tmdlHdmiCecCfgGetConfig(unit, &gtmdlHdmiCecDriverConfigTable[unit])!= TM_OK, TMDL_ERR_DLHDMICEC_INIT_FAILED)
++
++ *pInstance = (tmInstance_t)unit;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecClose( )
++ \brief Close an instance of CEC driver.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClose
++(
++ tmInstance_t instance
++)
++{
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* close instance */
++ UnitTable[instance].opened = False;
++ UnitTable[instance].state = CEC_STATE_NOT_INITIALIZED;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecInstanceConfig( )
++ \brief Set the configuration of instance attributes. This function is
++ required by DVP architecture rules but actually does nothing in this
++ driver
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInstanceConfig
++(
++ tmInstance_t instance
++)
++{
++ if (instance);
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecInstanceSetup( )
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration for CEC Stack Processor.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInstanceSetup
++(
++ tmInstance_t instance,
++ tmdlHdmiCecInstanceSetup_t *pSetupInfo
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++#ifdef TMFL_TDA9989
++ unsigned char I2c_ReadBuffer[1];
++#endif
++
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check that input pointer is not NULL */
++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* Ckeck the state */
++ RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* Wait for 250 ms */
++ RETIF( (errCode = tmdlHdmiTxIWWait(500) ) != TM_OK, errCode)
++
++#ifdef TMFL_TDA9989
++ /* Enable CEC Stack Processor */
++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ I2c_ReadBuffer[0] |= DEFAULT_ENAMODS;
++
++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]);
++ if (errCode != TM_OK)
++ {
++ //TODO WA still needed?
++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++ }
++
++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode)
++
++ /* Select CEC clock source and divider value */
++
++ if (pSetupInfo->cecClockSource == TMDL_HDMICEC_CLOCK_XTAL)
++ {
++ errCode = getCecHwRegisters(pDis, E_REG_CEC_CLK,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ I2c_ReadBuffer[0] &= CEC_CLK_SEL;
++ errCode = setCecHwRegister(pDis, E_REG_CEC_CLK, I2c_ReadBuffer[0]);
++ }
++
++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode)
++
++ //TODO WA to avoid spurious interrupts
++ errCode = getCecHwRegisters(pDis, E_REG_CDR0,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++#endif
++
++
++ /* Reset CEC Stack Processor */
++ errCode = setCecHwRegister(pDis, E_REG_CCR, 0x80);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ /* Wait for 250 ms */
++ RETIF( (errCode = tmdlHdmiTxIWWait(TDA9950_RESET_DELAY_MS) ) != TM_OK, errCode)
++
++ /* Configure Stack Processor (Retry = 5)*/
++ errCode = setCecHwRegister(pDis, E_REG_CCONR, 0x05);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ UnitTable[instance].DeviceLogicalAddress = pSetupInfo->DeviceLogicalAddress;
++
++
++ /* CEC Control register */
++ errCode = setCecHwRegisterMsbLsb(pDis, E_REG_ACKH, 0x1 << (UnitTable[instance].DeviceLogicalAddress));
++ RETIF(errCode != TM_OK, errCode)
++
++
++ /* CEC Stack Processor enable*/
++ errCode = setCecHwRegister(pDis, E_REG_CCR, 0x40);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ /* switch instance to its new state */
++ UnitTable[instance].state = CEC_STATE_CONFIGURED;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRegisterCallback( )
++ \brief Register event callbacks. Three types of callbacks can be
++ registered : input activity related callback, data related
++ callback (infoframes, packets, etc.) and general information
++ callback. A null pointer means that no callback are registered.
++
++ \param instance Instance identifier.
++ \param MessageCallback Pointer to the callback function that will
++ handle message related events.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_INVALID_STATE: the state is invalid for
++ the function
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRegisterCallbacks
++(
++ tmInstance_t instance,
++ ptmdlHdmiCecCallbackFunc_t MessageCallback
++)
++{
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ /* store callback pointers */
++ UnitTable[instance].MessageCallback = MessageCallback;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetLogicalAddress( )
++ \brief Set Device Logical Address
++
++ \param instance Instance identifier.
++ \param LogicalAddress Logical address value.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetLogicalAddress
++(
++ tmInstance_t instance,
++ tmdlHdmiCECLogicalAddress_t LogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* Ckeck the state */
++ RETIF(UnitTable[instance].state != CEC_STATE_CONFIGURED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ UnitTable[instance].DeviceLogicalAddress = LogicalAddress;
++
++ errCode = setCecHwRegisterMsbLsb(pDis, E_REG_ACKH, 0x1 << (UnitTable[instance].DeviceLogicalAddress));
++ RETIF(errCode != TM_OK, errCode)
++
++ return(TM_OK);
++}
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetRetry( )
++ \brief Change the number of retransmission
++
++ \param instance Instance identifier.
++ \param NbRetry Number of retry.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetRetry
++(
++ tmInstance_t instance,
++ UInt8 NbRetry
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* Ckeck the state */
++ RETIF(UnitTable[instance].state != CEC_STATE_CONFIGURED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* Configure Retry register */
++ errCode = setCecHwRegister(pDis, E_REG_CCONR, NbRetry);
++ RETIF(errCode != TM_OK, errCode)
++
++ return(TM_OK);
++}
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t getCecLastMessage( )
++ \brief Return the Addresses and the Opcode of the last CEC
++ transmitted message
++
++ \param pSaveMessage Pointer to the CEC Save Message
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t getCecLastMessage
++(
++ tmdlHdmiCecSaveMessage_t *pSaveMessage
++)
++{
++ /* copy Last CEC message datas */
++ pSaveMessage->AddressByte = gtmdlHdmiCecDriverSaveMessage.AddressByte;
++ pSaveMessage->MessageTypePolling = gtmdlHdmiCecDriverSaveMessage.MessageTypePolling;
++ pSaveMessage->Opcode = gtmdlHdmiCecDriverSaveMessage.Opcode;
++
++ return(TM_OK);
++}
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecImageViewOn( )
++ \brief This message sent by a source device to the TV whenever it enters
++ the active state
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receivers. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecImageViewOn
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C Write data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ //RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Image View On command */
++
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_IMAGE_VIEW_ON ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecInactiveSource( )
++ \brief This message is used by the currently active source to inform the
++ TV that it has no video to be presented to the user, or is going
++ into standby as the result of a lcoal user command on the device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress, \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Physical Address of the device. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecInactiveSource
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++ //======To do : make a prepare message function with parameter
++ /* Inactive source command */
++ I2c_Buffer[0] = 0x06;
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_INACTIVE_SOURCE ; /* Inactive Source*/
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecActiveSource()
++ \brief This message is used by a new source to indicate that it has started
++ to transmit a stream OR used in reponse to a <Request Active Source>
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecActiveSource
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Active Source command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_ACTIVE_SOURCE ; /* Active source */
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecVersion()
++ \brief This message is used to indicate the supported CEC version in response
++ to a <Get CEC Version>
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress\n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECVersion_t CECVersion \n
++ Supported CEC Version.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVersion
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECVersion_t CECVersion
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* CEC Version command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_CEC_VERSION ; /* CECVersion*/
++ I2c_Buffer[4] = CECVersion;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecClearAnalogueTimer( )
++ \brief This message is used to clear an Analogue timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearAnalogueTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[15] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Clear Analogue Timer command */
++ I2c_Buffer[0] = 0x0f; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_ANALOGUE_TIMER ;
++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/
++ I2c_Buffer[7] = (UInt8)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /*Duration minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++ I2c_Buffer[11] = AnalogueBroadcastType; /*Analogue Broadcast Type*/
++ I2c_Buffer[12] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/
++ I2c_Buffer[13] = (unsigned char)AnalogueFrequency;
++ I2c_Buffer[14] = BroadcastSystem; /*BroadcastSystem*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,15); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecClearDigitalTimer( )
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearDigitalTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[18] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECAribData_t *pARIB_Pointer;
++ tmdlHdmiCECAtscData_t *pATSC_Pointer;
++ tmdlHdmiCECDvbData_t *pDVB_Pointer;
++
++ unsigned char Regval; /* Local variable*/
++
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++
++ //======To do : make a prepare message function with parameter
++ /* Clear Digital Timer command */
++ I2c_Buffer[0] = 0x12; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_DIGITAL_TIMER ;
++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/
++ I2c_Buffer[7] = (UInt8)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /*Durantion Minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++
++ /* Digital service Identification*/
++ /*Merge Service Method and Digital Broadcast System in the same Byte*/
++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/
++ Regval = Regval << 7;
++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/
++ I2c_Buffer[11] = Regval;
++
++
++ /*Case of a ARIB Generic*/
++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC)
++ {
++ pARIB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pARIB_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pARIB_Pointer->ServiceID >> 8);
++ I2c_Buffer[15] = (unsigned char)pARIB_Pointer->ServiceID;
++ I2c_Buffer[16] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[17] = (unsigned char)pARIB_Pointer->OriginalNetworkID;
++
++ }
++ /*Case of a ATSC Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC)
++ {
++ pATSC_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pATSC_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8);
++ I2c_Buffer[15] = (unsigned char)pATSC_Pointer->ProgramNumber;
++ I2c_Buffer[16] = (unsigned char)(pATSC_Pointer->Reserved >> 8);
++ I2c_Buffer[17] = (unsigned char)pATSC_Pointer->Reserved;
++ }
++ /*Case of a DVB Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC)
++ {
++ pDVB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pDVB_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pDVB_Pointer->ServiceID >> 8);
++ I2c_Buffer[15] = (unsigned char)pDVB_Pointer->ServiceID;
++ I2c_Buffer[16] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[17] = (unsigned char)pDVB_Pointer->OriginalNetworkID;
++ }
++ /*other cases, Buffer are empty*/
++ else
++ {
++ I2c_Buffer[12] = 0xFF;
++ I2c_Buffer[13] = 0xFF;
++ I2c_Buffer[14] = 0xFF;
++ I2c_Buffer[15] = 0xFF;
++ I2c_Buffer[16] = 0xFF;
++ I2c_Buffer[17] = 0xFF;
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,18); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug( )
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[13] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ // RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Clear External Timer with External Plug Command*/
++ I2c_Buffer[0] = 0x0D; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_EXTERNAL_TIMER ;
++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /*Duration minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++ I2c_Buffer[11] = CEC_EXTERNAL_PLUG; /*External Source Specifier = External Plug */
++ I2c_Buffer[12] = ExternalPlug; /*External Plug*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,13); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress( )
++ \brief This message is used to clear a digital timer block of a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecClearExternalTimerWithPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[14] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Clear External Timer with Physical Address Command */
++ I2c_Buffer[0] = 0x0E; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_CLEAR_EXTERNAL_TIMER ; /*Clear External Timer*/
++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /*Duration Minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++ I2c_Buffer[11] = CEC_EXTERNAL_PHYSICAL_ADDRESS; /*External Source Specifier = External Address*/
++ I2c_Buffer[12] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Address*/
++ I2c_Buffer[13] = (unsigned char)ExternalPhysicalAddress;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,14); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTextViewOn( )
++ \brief This message as <Image View On>, but should also remove any text,
++ menus and PIP windows from the TV's display
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTextViewOn
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to Instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if Instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Text View On command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TEXT_VIEW_ON ; /* Text View On */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTimerClearedStatus( )
++ \brief This message is used to give the status of a <Cleared Analogue Timer>,
++ <Clear Digital Timer> or <Clear External Timer> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData \n
++ Indicates if the timer was cleared successfully. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTimerClearedStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECTimerClearedStatusData_t TimerClearedStatusData
++)
++{
++
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Timer Clear Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TIMER_CLEARED_STATUS; /* System Audio Status*/
++ I2c_Buffer[4] = TimerClearedStatusData; /* Timer Cleared Status*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTimerStatus( )
++ \brief This message is used to send timer status to the initiator of a
++ <Set Timer> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECTimerStatusData_t *pTimerStatusData \n
++ Pointer on the Timer status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTimerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECTimerStatusData_t *pTimerStatusData
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECTimerProgrammedInfo_t *pTimerProgInfo;
++ unsigned char Regval;
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Timer Status command */
++ I2c_Buffer[0] = 0x07; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TIMER_CLEARED_STATUS; /* System Audio Status*/
++ /* First Byte Building */
++ Regval = ((unsigned char)(pTimerStatusData->TimerOverlapWarning)& 0x01) << 7 ; // bit 7 for Timer Overlap Warning
++ Regval |= ((unsigned char)(pTimerStatusData->MediaInfo)& 0x03) << 5; // bit 6 to 5 for Media Info
++
++ pTimerProgInfo = &(pTimerStatusData->TimerProgrammedInfo);
++ Regval |= ((unsigned char)(pTimerProgInfo->SelectProgramInfo)& 0x01)<< 4; // bit 4 for Timer Programed Indicator
++ Regval |= (unsigned char)(pTimerProgInfo->ProgramInfo)& 0x0F; // bit 3 to 0 for Program Information
++ I2c_Buffer[4] = Regval;
++
++ /* 2 Duration Available Bytes Building */
++ /* Duration Available is only filled in the the both following conditions*/
++ if((pTimerProgInfo->SelectProgramInfo == CEC_PROGRAM_INDICATOR_NOT_PROGRAMMED)&&(pTimerProgInfo->ProgramInfo == CEC_PROGRAM_ERROR_INFO_DUPLICATE_ALREADY_PROGRAMMED))
++ {
++ I2c_Buffer[5] = (unsigned char)(pTimerProgInfo->DurationAvailable >> 8);
++ I2c_Buffer[6] = (unsigned char)pTimerProgInfo->DurationAvailable;
++ }
++ else if((pTimerProgInfo->SelectProgramInfo == CEC_PROGRAM_INDICATOR_PROGRAMMED)&&(pTimerProgInfo->ProgramInfo == CEC_PROGRAM_INFO_NOT_ENOUGHT_SPACE_AVAILABLE_FOR_RECORDING))
++ {
++ I2c_Buffer[5] = (unsigned char)(pTimerProgInfo->DurationAvailable >> 8);
++ I2c_Buffer[6] = (unsigned char)pTimerProgInfo->DurationAvailable;
++ }
++ /*Else, 2 bytes of Duration Available are filled with 0xFF*/
++ else
++ {
++ I2c_Buffer[5] = 0xFF;
++ I2c_Buffer[6] = 0xFF;
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue( )
++ \brief This message is used by a tuner device to provide its status to the
++ initiator of the <Give Tuner Device Status> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n
++ Indicates if the tuner is being used as a source of a recording. \n
++
++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n
++ Indicates if the the device is currently deplaying its tuner or not. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusAnalogue
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordingFlag_t RecordingFlag,
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++ )
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[9] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ unsigned char Regval; /*Local Variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Select Aanalogue Service command */
++ I2c_Buffer[0] = 0x09; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TUNER_DEVICE_STATUS ; /* Tuner Device Status*/
++ /* Build First Byte*/
++ Regval = ((unsigned char)RecordingFlag & 0X01)<< 7; /*bit 7 is Recording Flag */
++ Regval |= (unsigned char)TunerDisplayInfo & 0X7F; /*bit 6 to 0 are Tuner display Info*/
++ I2c_Buffer[4] = Regval;
++
++ I2c_Buffer[5] = AnalogueBroadcastType; /*Analogue Broadcast System type*/
++ I2c_Buffer[6] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/
++ I2c_Buffer[7] = (unsigned char)AnalogueFrequency;
++ I2c_Buffer[8] = BroadcastSystem; /*Broadcast System*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital( )
++ \brief This message is used by a tuner device to provide its status to the
++ initiator of the <Give Tuner Device Status> message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECRecordingFlag_t RecordingFlag \n
++ Indicates if the tuner is being used as a source of a recording. \n
++
++ \param tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo \n
++ Indicates if the the device is currently deplaying its tuner or not. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerDeviceStatusDigital
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordingFlag_t RecordingFlag,
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo,
++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[12] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECAribData_t *pARIB_Pointer;
++ tmdlHdmiCECAtscData_t *pATSC_Pointer;
++ tmdlHdmiCECDvbData_t *pDVB_Pointer;
++
++ unsigned char Regval; /* Local variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record On Digital Service command */
++ I2c_Buffer[0] = 0x0C; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TUNER_DEVICE_STATUS ; /* Tuner Device Status*/
++
++ /* Merge Recording Flag With Tuner Display Info*/
++ Regval = ((unsigned char)RecordingFlag & 0X01)<< 7; /* bit 7 is Recording Flag*/
++ Regval |= (unsigned char)TunerDisplayInfo & 0X7F; /* bit 6 to 0 are Tuner display Info*/
++ I2c_Buffer[4] = Regval;
++
++ /* Digital service Identification*/
++ /*Merge Service Method and Digital Broadcast System in the same Byte*/
++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01) << 7; /* bit 7 is Service Method*/
++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /* bits 6 to 0 are Digital Broadcast*/
++ I2c_Buffer[5] = Regval;
++
++ /*Case of a ARIB Generic*/
++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC)
++ {
++ pARIB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pARIB_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pARIB_Pointer->ServiceID >> 8);
++ I2c_Buffer[9] = (unsigned char)pARIB_Pointer->ServiceID;
++ I2c_Buffer[10] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[11] = (unsigned char)pARIB_Pointer->OriginalNetworkID;
++ }
++ /*Case of a ATSC Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC)
++ {
++ pATSC_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pATSC_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8);
++ I2c_Buffer[9] = (unsigned char)pATSC_Pointer->ProgramNumber;
++ I2c_Buffer[10] = (unsigned char)(pATSC_Pointer->Reserved >> 8);
++ I2c_Buffer[11] = (unsigned char)pATSC_Pointer->Reserved;
++ }
++ /*Case of a DVB Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC)
++ {
++ pDVB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pDVB_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pDVB_Pointer->ServiceID >> 8);
++ I2c_Buffer[9] = (unsigned char)pDVB_Pointer->ServiceID;
++ I2c_Buffer[10] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[11] = (unsigned char)pDVB_Pointer->OriginalNetworkID;
++ }
++ /*other cases, Buffer are empty*/
++ else
++ {
++ I2c_Buffer[6] = 0xFF;
++ I2c_Buffer[7] = 0xFF;
++ I2c_Buffer[8] = 0xFF;
++ I2c_Buffer[9] = 0xFF;
++ I2c_Buffer[10] = 0xFF;
++ I2c_Buffer[11] = 0xFF;
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,12); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestActiveSource( )
++ \brief This message is used by a new device to discover the status of
++ the system.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_Instance: the Instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestActiveSource
++(
++ tmInstance_t Instance
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* IRequest Active Source command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REQUEST_ACTIVE_SOURCE ; /* Request Active Source */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRoutingChange( )
++ \brief This message is sent by a CEC switch when it is manually switched to
++ inform all other devices on the network that the active route below
++ the switch has changed.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 OriginalAddress \n
++ Previous address that the switch was switched to. \n
++
++ \param UInt16 NewAddress \n
++ The new address it has been moved to. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRoutingChange
++(
++ tmInstance_t Instance,
++ UInt16 OriginalAddress,
++ UInt16 NewAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[8] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Routing Change command */
++ I2c_Buffer[0] = 0x08; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_ROUTING_CHANGE ; /* Routing Change */
++ I2c_Buffer[4] = (unsigned char)(OriginalAddress >> 8); /* MsByte of Original Address*/
++ I2c_Buffer[5] = (unsigned char)OriginalAddress; /* LsByte of Original Address */
++ I2c_Buffer[6] = (unsigned char)(NewAddress >> 8); /* MsByte of New Address */
++ I2c_Buffer[7] = (unsigned char)NewAddress; /* LsByte of New Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,8); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRoutingInformation( )
++ \brief This message is sent by a CEC switch to indicate the active route
++ below the switch.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ The current active route to the sink in the CEC switch. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRoutingInformation
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Routing Information command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_ROUTING_INFORMATION ; /* Routing Information */
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSelectAnalogueService( )
++ \brief This message select directly an analogue TV Service.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSelectAnalogueService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[8] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Select Aanalogue Service command */
++ I2c_Buffer[0] = 0x08; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_ANALOGUE_SERVICE ; /* Select Analogue Service*/
++ I2c_Buffer[4] = AnalogueBroadcastType;
++ I2c_Buffer[5] = (unsigned char)(AnalogueFrequency >> 8);
++ I2c_Buffer[6] = (unsigned char)AnalogueFrequency;
++ I2c_Buffer[7] = BroadcastSystem;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,8); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetStreamPath( )
++ \brief This message is used by a TV to request a streaming path from
++ the specified physical address.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetStreamPath
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set Stream Path command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_STREAM_PATH ; /* Set Stream Path */
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++ //==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetSystemAudioMode( )
++ \brief This message turn the system audio Mode ON or OFF.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n
++ Specifies if the system audio mode is ON or OFF.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetSystemAudioMode
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set System Audio Mode Command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_SYSTEM_AUDIO_MODE ; /* Set System Audio Mode*/
++ I2c_Buffer[4] = SystemAudioStatus; /*System Audio Status*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle( )
++ \brief This message is used to set the name of a program associated
++ with a timer block.Sent directly after sending a
++ <Set analogue Timer> or <Set Digital Timer> message. The name
++ is then associated with that timer block.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param const char *pProgramTitleString \n
++ Pointer on the program title. \n
++
++ \param UInt8 ProgramTitleLength \n
++ Length of Program Title String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetTimerProgramTitle
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ const char *pProgramTitleString,
++ UInt8 ProgramTitleLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Set Timer Program Title */
++ MessLength = ProgramTitleLength+4; /* Calculate Message length*/
++
++ I2c_Buffer[0] = (unsigned char)MessLength;
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_TIMER_PROGRAM_TITLE ; /* Set Timer Program Title*/
++
++ for(loci = 0; loci <= ProgramTitleLength ; loci++)
++ {
++ I2c_Buffer[(loci+4)] = pProgramTitleString[loci]; /* Fill Table with Program Title characters*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecStandby( )
++ \brief This message switches one or all devices into standby mode.Can be
++ be used as a broadcast message o be addressed to a specific device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecStandby
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Standby command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_STANDBY ; /* Standby */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest( )
++ \brief A device implementing System Audio Control and which has volume
++ control RC button(eg TV or STB) request to use System Audio Mode
++ to the amplifier.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Physical address of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSystemAudioModeRequest
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt16 PhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* System Audio Mode Request command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST ; /* System Audio Mode Request*/
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address */
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus( )
++ \brief Reports the current status of the System Audio Mode.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus \n
++ Current system audio mode.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSystemAudioModeStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECSystemAudioStatus_t SystemAudioStatus
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* System Audio Mode Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS ; /* System Audio Mode Status*/
++ I2c_Buffer[4] = SystemAudioStatus; /* System Audio Status*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus( )
++ \brief This message is used to request the status of a tuner device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n
++ Allows the initiator to request the status once or on all future state
++ change. Or to cancel a previous <Give Tuner Device Status > ["On"] request. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveTunerDeviceStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECStatusRequest_t StatusRequest
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* System Audio Mode Request command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS ; /* Give Tuner Device Status*/
++ I2c_Buffer[4] = (unsigned char)StatusRequest; /* Status Request */
++
++ errCode = setCecHwRegisters(pDis,E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordTvScreen( )
++ \brief This message request by the recording device to record the presently
++ displayed source.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordTvScreen
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record TV Sreen command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_TV_SCREEN ; /* Record TV screen */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportAudioStatus( )
++ \brief This message report an amplifier's volume and mute.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECAudioStatus_t AudioStatus \n
++ Volume and mute status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportAudioStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ ptmdlHdmiCECAudioStatus_t pAudioStatus
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char Regval; /*Local Variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Report Audio Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_AUDIO_STATUS ; /* Report Audio Statust*/
++ Regval = (((unsigned char)pAudioStatus -> audioMuteStatus) & 0x01 )<< 7; /* bit 7 Mute Status*/
++ Regval |= ((unsigned char)pAudioStatus -> audioVolumeStatus) & 0x7F; /* bit 6 to 0 Volum Status*/
++ I2c_Buffer[4] = Regval;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor( )
++ \brief This message Report Audio Capability.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt32 ShortAudioDecriptor \n
++ Audio Descriptor. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportShortAudioDescriptor
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt32 ShortAudioDecriptor
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x07; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_SHORT_AUDIO_DESCRIPTOR ; /* Report Audio Capability*/
++ I2c_Buffer[4] = (unsigned char)(ShortAudioDecriptor >> 16); /* MSByte of ShortAudioDecriptor*/
++ I2c_Buffer[5] = (unsigned char)(ShortAudioDecriptor >> 8);
++ I2c_Buffer[6] = (unsigned char)ShortAudioDecriptor; /* LSByte of ShortAudioDecriptor*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor( )
++ \brief This message Request Audio Capability.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 AudioFormatID \n
++
++ \param UInt8 AudioFormatCode \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestShortAudioDescriptor
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 AudioFormatID,
++ UInt8 AudioFormatCode
++
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char Regval; /*Local Variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REQUEST_SHORT_AUDIO_DESCRIPTOR ; /* Request Audio Capability*/
++ Regval = (((unsigned char)AudioFormatCode) & 0x3F )<< 2; /* bit 3 to 7 AudioFormatCode*/
++ Regval |= ((unsigned char)AudioFormatID) & 0x03; /* bit 1 to 0 AudioFormatID*/
++ I2c_Buffer[4] = Regval;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecIniateARC( )
++ \brief This message Used by an ARC RX device to activate the
++ ARC functionality in an ARC TX device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecIniateARC
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_INITATE_ARC ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportArcInitiated( )
++ \brief This message Used by an ARC TX device to indicate that
++ its ARC functionality has been activated
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportArcInitiated
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_INITIATED ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportArcTerminated( )
++ \brief This message Used by an ARC TX device to indicate that its ARC functionality
++ has been deactivated.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportArcTerminated
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_TERMINATED ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestArcInitiation( )
++ \brief This message Used by an ARC TX device to request an ARC RX device to
++ activate the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestArcInitiation
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_INITIATION ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRequestArcTerminiation( )
++ \brief Used by an ARC TX device to request an ARC RX device to deactivate
++ the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRequestArcTerminiation
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_ARC_TERMINATION ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTerminateARC( )
++ \brief Used by an ARC TX device to request an ARC RX device to deactivate
++ the ARC functionality in the ARC TX device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTerminateARC
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Report Short Audio Decriptor */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TERMINATE_ARC ;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGivePhysicalAddress( )
++ \brief This message is a request to a device to return its physical Address
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGivePhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give physical Address command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_PHYSICAL_ADDRESS ; /* Give Physical Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus( )
++ \brief This message request the status of the system audio mode
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveSystemAudioModeStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give System Audio Mode Status command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS ; /* Give System Audio Mode Status*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetMenuLanguage( )
++ \brief This message is sent by a device capable of character generation
++ (for OSD and Menus) to a TV in order to discover the currently selected
++ Menu Language. Also used by a TV during installation to dicover the
++ currently set menu language of other devices.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetMenuLanguage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Get Menu Language command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GET_MENU_LANGUAGE ; /* Get Menu Address */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveAudioStatus( )
++ \brief This message is requests an amplifier to send its volume and mute status
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveAudioStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give Audio Mode Status command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_AUDIO_STATUS ; /* Message Abort*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecPollingMessage( )
++ \brief This message is used by any device for device discovery - similar to
++ ping in other protocols
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecPollingMessage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[3] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Polling Message command */
++ I2c_Buffer[0] = 0x03; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,3); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 1;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = 0;
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordStatus( )
++ \brief This message is used by a recording device to inform the initiator
++ of the message <Record On> about its status.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo \n
++ The recording status of the device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECRecordStatusInfo_t RecordStatusInfo
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_STATUS ; /* Record Status */
++ I2c_Buffer[4] = RecordStatusInfo; /* Record Status */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOff( )
++ \brief This message request a device to stop a recording
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOff
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record Off command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_OFF ; /* Record Off */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService( )
++ \brief This message attempt to record analogue source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnAnalogueService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[9] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Record On Analogue Device command */
++ I2c_Buffer[0] = 0x09; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /*Record On*/
++
++ I2c_Buffer[4] = CEC_RECORD_SOURCE_ANALOGUE_SERVICE; /*RecordSourceType = CEC_RECORD_SOURCE_ANALOGUE_SERVICE*/
++ I2c_Buffer[5] = AnalogueBroadcastType; /*Analogue Brodcast Type*/
++ I2c_Buffer[6] = (unsigned char)(AnalogueFrequency >> 8); /*Analogue Frequency*/
++ I2c_Buffer[7] = (unsigned char)AnalogueFrequency;
++ I2c_Buffer[8] = BroadcastSystem; /*Brodcast System*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOnDigitalService( )
++ \brief This message attempt to record digital source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnDigitalService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[12] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECAribData_t *pARIB_Pointer;
++ tmdlHdmiCECAtscData_t *pATSC_Pointer;
++ tmdlHdmiCECDvbData_t *pDVB_Pointer;
++
++ unsigned char Regval; /* Local variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record On Digital Service command */
++ I2c_Buffer[0] = 0x0C; /* Param number = 10*/
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On Digital Service*/
++
++ I2c_Buffer[4] = CEC_RECORD_SOURCE_DIGITAL_SERVICE; /* RecordSourceType = CEC_RECORD_SOURCE_DIGITAL_SERVICE */
++
++ /* Digital Service Identification*/
++ /*Merge Service Method and Digital Broadcast System in the same Byte*/
++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/
++ Regval = Regval << 7;
++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/
++ I2c_Buffer[5] = Regval;
++
++ /*Case of a ARIB Generic*/
++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC)
++ {
++ pARIB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pARIB_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pARIB_Pointer->ServiceID >> 8);
++ I2c_Buffer[9] = (unsigned char)pARIB_Pointer->ServiceID;
++ I2c_Buffer[10] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[11] = (unsigned char)pARIB_Pointer->OriginalNetworkID;
++ }
++ /*Case of a ATSC Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC)
++ {
++ pATSC_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pATSC_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8);
++ I2c_Buffer[9] = (unsigned char)pATSC_Pointer->ProgramNumber;
++ I2c_Buffer[10] = (unsigned char)(pATSC_Pointer->Reserved >> 8);
++ I2c_Buffer[11] = (unsigned char)pATSC_Pointer->Reserved;
++ }
++ /*Case of a DVB Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC)
++ {
++ pDVB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[6] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[7] = (unsigned char)pDVB_Pointer->TransportStreamID;
++ I2c_Buffer[8] = (unsigned char)(pDVB_Pointer->ServiceID >> 8);
++ I2c_Buffer[9] = (unsigned char)pDVB_Pointer->ServiceID;
++ I2c_Buffer[10] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[11] = (unsigned char)pDVB_Pointer->OriginalNetworkID;
++ }
++ /*other cases, Buffer are empty*/
++ else
++ {
++ I2c_Buffer[6] = 0xFF;
++ I2c_Buffer[7] = 0xFF;
++ I2c_Buffer[8] = 0xFF;
++ I2c_Buffer[9] = 0xFF;
++ I2c_Buffer[10] = 0xFF;
++ I2c_Buffer[11] = 0xFF;
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,12); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress( )
++ \brief This message attempt to record an external physical address source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnExternalPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record On External Physial Address command */
++ I2c_Buffer[0] = 0x07; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /*Record On*/
++ I2c_Buffer[4] = CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS; /*RecordSourceType = CEC_RECORD_SOURCE_EXTERNAL_PHYSICAL_ADDRESS*/
++ I2c_Buffer[5] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Physical Address*/
++ I2c_Buffer[6] = (unsigned char)ExternalPhysicalAddress;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug( )
++ \brief This message attempt to record an external plug source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record On External Plug command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On*/
++
++ I2c_Buffer[4] = CEC_RECORD_SOURCE_EXTERNAL_PLUG; /* RecordSourceType = CEC_RECORD_SOURCE_EXTERNAL_PLUG*/
++ I2c_Buffer[5] = ExternalPlug; /*External Plug*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecRecordOnOwnSource( )
++ \brief This message attempt to record an external plug source
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecRecordOnOwnSource
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Record On Own Source command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_RECORD_ON ; /* Record On*/
++
++ I2c_Buffer[4] = CEC_RECORD_SOURCE_OWN_SOURCE; /* RecordSourceType = CEC_RECORD_SOURCE_OWN_SOURCE*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportPhysicalAddress( )
++ \brief This message is used to inform all other devices of the mapping
++ between physical and logical address of the initiator.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt16 PhysicalAddress \n
++ Device physical address within the cluster. \n
++
++ \param tmdlHdmiCECDeviceType_t DeviceType \n
++ Type of the device (TV, Playback, tuner,...). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt16 PhysicalAddress,
++ tmdlHdmiCECDeviceType_t DeviceType
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Report Physical Address command */
++ I2c_Buffer[0] = 0x07; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_PHYSICAL_ADDRESS ; /* Report Physical Address */
++ I2c_Buffer[4] = (unsigned char)(PhysicalAddress >> 8); /* MsByte of Physical Address*/
++ I2c_Buffer[5] = (unsigned char)PhysicalAddress; /* LsByte of Physical Address */
++
++ I2c_Buffer[6] = DeviceType ; /* Device Type*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetMenuLanguage( )
++ \brief This message is used by a TV or another device to indicate the menu
++ Language.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param const char *pLanguage \n
++ Pointer on the user's menu language choice. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetMenuLanguage
++(
++ tmInstance_t Instance,
++ const char *pLanguage
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ // RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set Menu Language command */
++ I2c_Buffer[0] = 0x07; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_MENU_LANGUAGE ; /* Set Menu Language*/
++ I2c_Buffer[4] = pLanguage[0]; /* First Tocken*/
++ I2c_Buffer[5] = pLanguage[1];
++ I2c_Buffer[6] = pLanguage[2]; /* Last Tocken*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecDeckControl()
++ \brief This message is used to conrol a device's media functions
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDecControlMode_t DeckControlMode \n
++ Used in message <Deck Control>\n
++
++ \note The "Skip Forward / Wind" and "Skip Reverse / Rewind" values are
++ used for example in a DVD as next xhapter and previous chapter and
++ in a VCR as wind and rewind. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeckControl
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDecControlMode_t DeckControlMode
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if Instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to Instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if Instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Deck Control command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_DESCK_CONTROL; /* Deck Control Mode*/
++ I2c_Buffer[4] = DeckControlMode; /* Deck Control Value*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecDeckStatus()
++ \brief This message is used to provide a deck's status to the initiator
++ of the <Give Deck Status> message
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDecInfo_t DeckInfo \n
++ Information on the device's current status \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeckStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDecInfo_t DeckInfo
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Deck Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_DECK_STATUS; /* Deck Status*/
++ I2c_Buffer[4] = DeckInfo; /* Deck Status Mode Information*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveDeckStatus( )
++ \brief This message is used to request the status of a device regardless
++ of whether or not it is the current active source.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECStatusRequest_t StatusRequest \n
++ Allows the initiator to request the status once or on all future state
++ change. Or to cancel a previous <Give Deck Status > ["On"] request. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDeckStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECStatusRequest_t StatusRequest
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if Instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give Deck Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DECK_STATUS; /* Give Deck Status*/
++ I2c_Buffer[4] = StatusRequest; /* Deck Status Request Information*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecPlay( )
++ \brief This message is used to control the playback behaviour of a source
++ device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPlayMode_t PlayMode \n
++ In which mode to play media. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecPlay
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPlayMode_t PlayMode
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Play command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_PLAY; /* Play*/
++ I2c_Buffer[4] = (unsigned char)PlayMode; /* Play Mode Information Information*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSelectDigitalService( )
++ \brief This message select directly a digital TV, Radio or Data Broadcast
++ Service.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSelectDigitalService
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ ptmdlHdmiCECDigitalServiceIdentification_t pServiceIdentification
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[11] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECAribData_t *pARIB_Pointer;
++ tmdlHdmiCECAtscData_t *pATSC_Pointer;
++ tmdlHdmiCECDvbData_t *pDVB_Pointer;
++
++ unsigned char Regval; /*Local Variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Select Digital Service command */
++ I2c_Buffer[0] = 0x0B; /* Param number = 10*/
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_DIGITAL_SERVICE ; /* Select Digital Service*/
++
++ /*Merge Service Method and Digital Broadcast System in the same Byte*/
++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /* Load the 1 bit of Service Method*/
++ Regval = Regval << 7;
++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*Merge with the 7 bits of Digital Broadcast*/
++ I2c_Buffer[4] = Regval;
++
++ /*Case of a ARIB Generic*/
++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC)
++ {
++ pARIB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[5] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8); /* Service Identification */
++ I2c_Buffer[6] = (unsigned char)pARIB_Pointer->TransportStreamID;
++ I2c_Buffer[7] = (unsigned char)(pARIB_Pointer->ServiceID >> 8);
++ I2c_Buffer[8] = (unsigned char)pARIB_Pointer->ServiceID;
++ I2c_Buffer[9] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[10] = (unsigned char)pARIB_Pointer->OriginalNetworkID;
++ }
++ /*Case of a ATSC Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC)
++ {
++ pATSC_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[5] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8); /* Service Identification */
++ I2c_Buffer[6] = (unsigned char)pATSC_Pointer->TransportStreamID;
++ I2c_Buffer[7] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8);
++ I2c_Buffer[8] = (unsigned char)pATSC_Pointer->ProgramNumber;
++ I2c_Buffer[9] = (unsigned char)(pATSC_Pointer->Reserved >> 8);
++ I2c_Buffer[10] = (unsigned char)pATSC_Pointer->Reserved;
++ }
++ /*Case of a DVB Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC)
++ {
++ pDVB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[5] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8); /* Service Identification */
++ I2c_Buffer[6] = (unsigned char)pDVB_Pointer->TransportStreamID;
++ I2c_Buffer[7] = (unsigned char)(pDVB_Pointer->ServiceID >> 8);
++ I2c_Buffer[8] = (unsigned char)pDVB_Pointer->ServiceID;
++ I2c_Buffer[9] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[10] = (unsigned char)pDVB_Pointer->OriginalNetworkID;
++ }
++ /*other cases, Buffer are empty*/
++ else
++ {
++ I2c_Buffer[5] = 0xFF; /* Service Identification */
++ I2c_Buffer[6] = 0xFF;
++ I2c_Buffer[7] = 0xFF;
++ I2c_Buffer[8] = 0xFF;
++ I2c_Buffer[9] = 0xFF;
++ I2c_Buffer[10] = 0xFF;
++ }
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,11); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetAnalogueTimer( )
++ \brief This message is used to set asingle timer block on an analogue
++ recording device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType \n
++ "Cable,Sattellite,Terrestrial".\n
++
++ \param UInt16 AnalogueFrequency \n
++ Specify frequency used by analogue tuner (0x0000<=N<=0xFFFF).\n
++
++ \param tmdlHdmiCECBroadcastSystem_t BroadcastSystem \n
++ Specify information about the colour system, the sound carrier and
++ the IF-frequency.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetAnalogueTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType,
++ UInt16 AnalogueFrequency,
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[15] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set Analogue Timer command */
++ I2c_Buffer[0] = 0x0F; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_ANALOGUE_TIMER ; /* Message Abort*/
++ I2c_Buffer[4] = DayOfMonth;
++ I2c_Buffer[5] = MonthOfYear;
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8);
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours;
++ I2c_Buffer[9] = pDuration -> Minute;
++ I2c_Buffer[10] = RecordingSequence;
++ I2c_Buffer[11] = AnalogueBroadcastType;
++ I2c_Buffer[12] = (unsigned char)(AnalogueFrequency >> 8);
++ I2c_Buffer[13] = (unsigned char)AnalogueFrequency;
++ I2c_Buffer[14] = BroadcastSystem;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,15); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetAudioRate( )
++ \brief This message is used to control audio rate from Source device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECAudioRate_t AudioRate \n
++ The audio rate requested. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetAudioRate
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECAudioRate_t AudioRate
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set Audio Rate command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_AUDIO_RATE ; /* Set Audio Rate */
++ I2c_Buffer[4] = AudioRate;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetDigitalTimer( )
++ \brief This message is used to set a digital timer block on a digital
++ recording device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress \n
++ Address of message receiver. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification \n
++ Pointer to the structure Digital Service Identification
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetDigitalTimer
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECDigitalServiceIdentification_t *pServiceIdentification
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[18] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ tmdlHdmiCECAribData_t *pARIB_Pointer;
++ tmdlHdmiCECAtscData_t *pATSC_Pointer;
++ tmdlHdmiCECDvbData_t *pDVB_Pointer;
++
++ unsigned char Regval; /* Local variable*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set Digital Timer command */
++ I2c_Buffer[0] = 0x12; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_DIGITAL_TIMER ; /* Set Digital Timer*/
++ I2c_Buffer[4] = DayOfMonth; /* Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /* Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /* Start Time*/
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /* Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /* Duration Minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++
++ /* Digital service Identification*/
++ /*Merge Service Method and Digital Broadcast System in the same Byte*/
++ Regval = (unsigned char)(pServiceIdentification->ServiceIdentificationMethod & 0x01); /*bit 7 is Service Method*/
++ Regval = Regval << 7;
++ Regval |= (unsigned char)(pServiceIdentification->DigitalBroadcastSystem & 0x7F); /*bits 6 to 0 are Digital Broadcast*/
++ I2c_Buffer[11] = Regval;
++
++ /*Case of a ARIB Generic*/
++ if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ARIB_GENERIC)
++ {
++ pARIB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pARIB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pARIB_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pARIB_Pointer->ServiceID >> 8);
++ I2c_Buffer[15] = (unsigned char)pARIB_Pointer->ServiceID;
++ I2c_Buffer[16] = (unsigned char)(pARIB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[17] = (unsigned char)pARIB_Pointer->OriginalNetworkID;
++ }
++ /*Case of a ATSC Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_ATSC_GENERIC)
++ {
++ pATSC_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pATSC_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pATSC_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pATSC_Pointer->ProgramNumber >> 8);
++ I2c_Buffer[15] = (unsigned char)pATSC_Pointer->ProgramNumber;
++ I2c_Buffer[16] = (unsigned char)(pATSC_Pointer->Reserved >> 8);
++ I2c_Buffer[17] = (unsigned char)pATSC_Pointer->Reserved;
++ }
++ /*Case of a DVB Generic*/
++ else if(pServiceIdentification->DigitalBroadcastSystem == CEC_DIGITAL_BROADCAST_SYSTEM_DVB_GENERIC)
++ {
++ pDVB_Pointer = pServiceIdentification->pServiceIdentification;
++
++ I2c_Buffer[12] = (unsigned char)(pDVB_Pointer->TransportStreamID >> 8);
++ I2c_Buffer[13] = (unsigned char)pDVB_Pointer->TransportStreamID;
++ I2c_Buffer[14] = (unsigned char)(pDVB_Pointer->ServiceID >> 8);
++ I2c_Buffer[15] = (unsigned char)pDVB_Pointer->ServiceID;
++ I2c_Buffer[16] = (unsigned char)(pDVB_Pointer->OriginalNetworkID >> 8);
++ I2c_Buffer[17] = (unsigned char)pDVB_Pointer->OriginalNetworkID;
++ }
++ /*other cases, Buffer are empty*/
++ else
++ {
++ I2c_Buffer[12] = 0xFF;
++ I2c_Buffer[13] = 0xFF;
++ I2c_Buffer[14] = 0xFF;
++ I2c_Buffer[15] = 0xFF;
++ I2c_Buffer[16] = 0xFF;
++ I2c_Buffer[17] = 0xFF;
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,18); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug( )
++ \brief This message is used to set a single timer block to record from an
++ external device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPlug_t ExternalPlug \n
++ indicates external plug number (1 to 255 )on the recording device.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithExternalPlug
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPlug_t ExternalPlug
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[13] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set External Timer With External Plug command */
++ I2c_Buffer[0] = 0x0D; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_EXTERNAL_TIMER ; /*SetDigital Timer*/
++
++ I2c_Buffer[4] = DayOfMonth; /*Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /*Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /*Start Time*/
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /*Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /*Duration Minute*/
++ I2c_Buffer[10] = RecordingSequence; /*Recording Sequence*/
++ I2c_Buffer[11] = CEC_EXTERNAL_PLUG; /*External Source Specifier = External Plug */
++ I2c_Buffer[12] = ExternalPlug; /*External Plug*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,13); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress( )
++ \brief This message is used to set a single timer block to record from an
++ external device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 DayOfMonth \n
++ Day of the month.\n
++
++ \param UInt8 MonthOfYear \n
++ Month of the year.\n
++
++ \param UInt16 StartTime \n
++ Start time for a timer based recording.\n
++
++ \param UInt16 Duration \n
++ Pointer to the structure tmdlHdmiCECDuration_t in BCD format.\n
++
++ \param UInt8 Recording Sequence \n
++ Indicates if recording is repeated and, if so, on which day
++ For repeated recording the recording sequence value is the
++ bitwise OR of the days when recordings are required
++ Shall be set to 0x00 when recording is not repeated.\n
++
++ \param tmdlHdmiCECExternalPhysicalAddress_t PhysicalAddress \n
++ Defines the path between the TV an a device-thus giving it a physical
++ address within the cluster.\n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetExternalTimerWithPhysicalAddress
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 DayOfMonth,
++ UInt8 MonthOfYear,
++ UInt16 StartTime,
++ tmdlHdmiCECDuration_t *pDuration,
++ UInt8 RecordingSequence,
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[14] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set external Timer With External Physical Address command */
++ I2c_Buffer[0] = 0x0E; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_EXTERNAL_TIMER ; /* SetDigital Timer*/
++
++ I2c_Buffer[4] = DayOfMonth; /* Day of Month*/
++ I2c_Buffer[5] = MonthOfYear; /* Month of Year*/
++ I2c_Buffer[6] = (unsigned char)(StartTime >> 8); /* Start Time*/
++ I2c_Buffer[7] = (unsigned char)StartTime;
++ I2c_Buffer[8] = pDuration -> Hours; /* Duration Hours*/
++ I2c_Buffer[9] = pDuration -> Minute; /* Duration Minute*/
++ I2c_Buffer[10] = RecordingSequence; /* Recording Sequence*/
++ I2c_Buffer[11] = CEC_EXTERNAL_PHYSICAL_ADDRESS; /*External Source Specifier = External Address*/
++ I2c_Buffer[12] = (unsigned char)(ExternalPhysicalAddress >> 8); /*External Address*/
++ I2c_Buffer[13] = (unsigned char) ExternalPhysicalAddress;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,14); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTunerStepDecrement( )
++ \brief This message is used to tune to next lowest service in a tuner's
++ service list.Can be used for PIP.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerStepDecrement
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Tuner Step Decrement command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TUNER_STEP_DECREMENT ; /* Tuner Step Decrement*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecTunerStepIncrement( )
++ \brief This message is used to tune to next highest service in a tuner's
++ service list.Can be used for PIP.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecTunerStepIncrement
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Tuner Step Increment command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_TUNER_STEP_INCREMENT ; /* Tuner Step Increment*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecDeviceVendorID()
++ \brief This message report the vendor ID of this device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt32 VendorID \n
++ Indentifier for a specific Vendor \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDeviceVendorID
++(
++ tmInstance_t Instance,
++ UInt32 VendorID
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[7] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Device Vendor ID command */
++ I2c_Buffer[0] = 0x07; /* Param number in case of Vendor ID is 32 Bytes*/
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= 0x0F; /* Broadcast*/
++
++ I2c_Buffer[3] = CEC_OPCODE_DEVICE_VENDOR_ID ; /* Device Vendor ID opcode = 0x87*/
++ I2c_Buffer[4] = (unsigned char)(VendorID >> 16); /* MSByte of Vendor ID*/
++ I2c_Buffer[5] = (unsigned char)(VendorID >> 8);
++ I2c_Buffer[6] = (unsigned char)VendorID; /* LSByte of Vendor ID*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,7); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID( )
++ \brief This message is request the vendor ID from a device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDeviceVendorID
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give Device Vendor ID command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DEVICE_VENDOR_ID ; /* Give Device Vendor*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecVendorCommand( )
++ \brief This message is allows vendor specific commands to be sent between
++ two devices.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 *pVendorSpecificData \n
++ Pointer to the Vendor Specific datas
++
++ \param UInt8 VendorSpecificDataLength \n
++ Length of VendorSpecificData. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorCommand
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 *pVendorSpecificData,
++ UInt8 VendorSpecificDataLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Vendor Command command */
++ MessLength = VendorSpecificDataLength + 4; /* Calculate Message length*/
++
++ I2c_Buffer[0] = MessLength; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_COMMAND ; /* Vendor Command*/
++
++ for(loci = 0; loci <= VendorSpecificDataLength ; loci++)
++ {
++ I2c_Buffer[(loci+7)] = pVendorSpecificData[loci]; /* Fill Table with vendorSpecific Data characters*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecVendorCommandWithID( )
++ \brief This message is allows vendor specific commands to be sent between
++ two devices or broadcast.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt32 VendorID \n
++ Indentifier for a specific Vendor \n
++
++ \param UInt8 *pVendorSpecificData \n
++ Pointer to the Vendor Specific datas
++
++ \param UInt8 VendorSpecificDataLength \n
++ Length of VendorSpecificData. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorCommandWithID
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt32 VendorID,
++ UInt8 *pVendorSpecificData,
++ UInt8 VendorSpecificDataLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Vendor Command With ID command */
++ MessLength = VendorSpecificDataLength + 7; /* Calculate Message length*/
++
++ I2c_Buffer[0] = MessLength; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_COMMAND_WITH_ID ; /* Vendor Command*/
++ I2c_Buffer[4] = (unsigned char)(VendorID >> 16); /* MSByte of Vendor ID*/
++ I2c_Buffer[5] = (unsigned char)(VendorID >> 8);
++ I2c_Buffer[6] = (unsigned char)VendorID; /* LSByte of Vendor ID*/
++
++ for(loci = 0; loci <= VendorSpecificDataLength ; loci++)
++ {
++ I2c_Buffer[(loci+7)] = pVendorSpecificData[loci]; /* Fill Table with vendorSpecific Data characters*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown( )
++ \brief This message indicates that a remote control button has been depressed.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 *pVendorSpecificRcCode \n
++ Pointer to the Vendor Specific remote control code.
++ its recommended t keep this to a minimum size.
++ The maximum length shall not exceed 14 data blocks to avoid saturating bus
++
++ \param UInt8 VendorSpecificRcCodeLength \n
++ Length of VendorSpecificRcCode. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonDown
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 *pVendorSpecificRcCode,
++ UInt8 VendorSpecificRcCodeLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ /* Vendor Remote Button Down command */
++ MessLength = VendorSpecificRcCodeLength + 4; /* Calculate Message length*/
++
++ I2c_Buffer[0] = MessLength; /* Message Length */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN ; /* Vendor Remote Button Down Opcode*/
++ /*Vendor Specific RC code Parameter*/
++ for(loci = 0; loci <= VendorSpecificRcCodeLength ; loci++)
++ {
++ I2c_Buffer[(loci+4)] = pVendorSpecificRcCode[loci]; /* Fill Table with Vendor Specific RC Code data*/
++ }
++ /*Send message Via I2C*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength);
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp( )
++ \brief This message indicates that a remote control button (the last button
++ pressed indicated by the <Vendor remote button down > message) has
++ been released.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecVendorRemoteButtonUp
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Vendor Remote Button Up command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP ; /* Vendor Remote Button Up*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetOsdString( )
++ \brief This message is used to send a test message to output on a TV.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECDisplayControl_t DisplayControl \n
++ Display timing. \n
++
++ \param const char *pOsdString \n
++ Pointer on the Text to display. \n
++
++ \param UInt8 OsdStringLength \n
++ Length of Osd String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetOsdString
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECDisplayControl_t DisplayControl,
++ const char *pOsdString,
++ UInt8 OsdStringLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set OSD String command */
++
++ MessLength = OsdStringLength+5; /* Calculate Message length*/
++
++ I2c_Buffer[0] = (unsigned char)MessLength;
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_OSD_STRING ; /* Set Osd String*/
++ I2c_Buffer[4] = DisplayControl; /*Display Control*/
++ for(loci = 0; loci <= OsdStringLength ; loci++)
++ {
++ I2c_Buffer[(loci+5)] = pOsdString[loci]; /* Fill Table with OSD Name characters*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveOsdName( )
++ \brief This message is used to request preferred OSD name of a device
++ for use in menus associated with that device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveOsdName
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give OSD Name command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_OSD_NAME ; /* Give OSD Name*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetOsdName( )
++ \brief This message is used to set the preferred OSD name of a device
++ for use in manus associated with that device.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param const char *pOsdName \n
++ Pointer on the preferred name of the device. \n
++
++ \param UInt8 OsdNameLength \n
++ Length of Osd Name String. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetOsdName
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ const char *pOsdName,
++ UInt8 OsdNameLength
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Set OSD Name command */
++
++ MessLength = OsdNameLength+4; /* Calculate Message length*/
++
++ I2c_Buffer[0] = (unsigned char)MessLength;
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_SET_OSD_NAME ; /* Set Osd Name*/
++ for(loci = 0; loci <= OsdNameLength ; loci++)
++ {
++ I2c_Buffer[(loci+4)] = pOsdName[loci]; /* Fill Table with OSD Name characters*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,(MessLength)); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecMenuRequest( )
++ \brief This message request from the TV for a device to show/remove a
++ menu or to query if a device is currently showing a menu
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECMenuRequestType_t MenuRequestType \n
++ Indicates if the menu request is to activate or deactivate the
++ devices menu or simply query the devices menu status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecMenuRequest
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECMenuRequestType_t MenuRequestType
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Menu Request command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_MENU_REQUEST ; /* Menu Request*/
++ I2c_Buffer[4] = MenuRequestType; /*Menu Request Type */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecMenuStatus( )
++ \brief This message is used to indicate to the TV that the device is
++ showing/has removed a menu and requets the remote control keys to
++ be passed though
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECMenuState_t MenuState \n
++ Indicates if the device is in the 'Device Menu Active' state or
++ 'Device Menu Inactive' state. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecMenuStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECMenuState_t MenuState
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Menu Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_MENU_STATUS; /* Menu Status*/
++ I2c_Buffer[4] = MenuState; /* Menu State*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressed( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECUserRemoteControlCommand_t UICommand \n
++ Relevant UI command issued by user. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressed
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECUserRemoteControlCommand_t UICommand
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Pressed command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control pressed*/
++ I2c_Buffer[4] = UICommand; /* UI Command*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedPlay( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPlayMode_t PlayMode \n
++ In which mode to play media. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedPlay
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPlayMode_t PlayMode
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Presses Play command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/
++
++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_PLAY_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_PLAY_FUNCTION */
++ I2c_Buffer[5] = PlayMode; /* Play Mode*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectAudioInput \n
++ Number of the Audio Input (Audio input number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAudioInput
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectAudioInput
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Pressed Select Audio Input command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/
++
++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION*/
++ I2c_Buffer[5] = SelectAudioInput; /* UI Function Select Audio mode*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectAVInput \n
++ Number of the A/V Input (A/V input number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectAVInput
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectAVInput
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Pressed Select AV Input command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/
++
++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION */
++ I2c_Buffer[5] = SelectAVInput; /* UI Function Select A/V Input*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 SelectMedia \n
++ Number of Media (Media number between 1 and 255). \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedSelectMedia
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ UInt8 SelectMedia
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Pressed Select Media command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed*/
++
++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION*/
++ I2c_Buffer[5] = SelectMedia; /* UI Function Media*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlPressedTune( )
++ \brief This message is used to indicate that the user pressed a remote button
++ or switched from one remote control button to another.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier \n
++ Pointer to the structure of Major and Minor Channel number
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlPressedTune
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECChannelIdentifier_t *pChannelIdentifier
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[10] ; /* I2C data buffer */
++ UInt16 Regval16 ; /* Local variable used for conversion*/
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Pressed Tune command */
++ I2c_Buffer[0] = 0x0A; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_PRESSED; /* User Control Pressed Opcode*/
++
++ I2c_Buffer[4] = CEC_REMOTE_BUTTON_TUNE_FUNCTION; /* UI Command = CEC_REMOTE_BUTTON_TUNE_FUNCTION*/
++
++ /* Merge 6 bits of ChanNum with 10 bits of Major channel*/
++ Regval16 = (UInt16)(pChannelIdentifier->ChanNumFormat & 0x003F); // Save the 6 lsbits
++ Regval16 = Regval16 << 10;
++ Regval16 |= (UInt16)(pChannelIdentifier->MajorChanNumber & 0x03FF);
++
++ /* Load the 4 information bytes of Channel ID*/
++ I2c_Buffer[5] = (unsigned char)(Regval16 >> 8);
++ I2c_Buffer[6] = (unsigned char)Regval16;
++ I2c_Buffer[7] = (unsigned char)(pChannelIdentifier->MinorChanNumber >> 8);
++ I2c_Buffer[8] = (unsigned char)pChannelIdentifier->MinorChanNumber;
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,9); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecUserControlReleased( )
++ \brief This message is used to indicate that the user released a remote button
++ The last one indicated by the <User Control Pressed> Message.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecUserControlReleased
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* User Control Released command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_USER_CONTROL_RELEASED ; /* User Control Released */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus( )
++ \brief This message is used to determine the current power status of a
++ target device
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGiveDevicePowerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Give Device power Status Power Status command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GIVE_DEVICE_POWER_STATUS ; /* Give Device Power Status */
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecReportPowerStatus( )
++ \brief This message is used to inform a requesting device of the current
++ power status.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECPowerStatus_t PowerStatus \n
++ Current power status. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecReportPowerStatus
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECPowerStatus_t PowerStatus
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[5] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Report Power Status command */
++ I2c_Buffer[0] = 0x05; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_REPORT_POWER_STATUS ; /* Report Power Status*/
++ I2c_Buffer[4] = PowerStatus; /* Power Status*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,5); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecFeatureAbort()
++ \brief This message is used as a reponse to indicate that the device does
++ not support the requested message type, or that it cannot execute it
++ at the present time.
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param tmdlHdmiCECFeatureOpcode_t FeatureOpcode \n
++ Opcode of the aborted message. \n
++
++ \param tmdlHdmiCECAbortReason_t AbortReason \n
++ The reason why message cannot respond. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecFeatureAbort
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress,
++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode,
++ tmdlHdmiCECAbortReason_t AbortReason
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[6] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Feature Abort command */
++ I2c_Buffer[0] = 0x06; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_FEATURE_ABORT ; /* Feature Abort*/
++ I2c_Buffer[4] = FeatureOpcode; /* Feature Opcode*/
++ I2c_Buffer[5] = AbortReason; /* Abort Reason*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,6); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetCecVersion( )
++ \brief This message is used by a device to enquire which version of CEC
++ the target supports
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetCecVersion
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* Get CEC Version command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_GET_CEC_VERSION ; /* Get CEC Version*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecAbortMessage( )
++ \brief This message is reserved for testing purposes
++
++ \param tmInstance_t Instance \n
++ Instance identifier. \n
++
++ \param UInt8 ReceiverLogicalAddress\n
++ Address of message receiver. \n
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecAbortMessage
++(
++ tmInstance_t Instance,
++ UInt8 ReceiverLogicalAddress
++)
++{
++ tmErrorCode_t errCode;
++ unsigned char I2c_Buffer[4] ; /* I2C data buffer */
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((Instance < 0) || (Instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[Instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if instance state is correct */
++ //RETIF(UnitTable[Instance].state != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[Instance];
++
++ //======To do : make a prepare message function with parameter
++ /* CEC Abort Message command */
++ I2c_Buffer[0] = 0x04; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[Instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= ReceiverLogicalAddress & 0x0F; /* Receiver logical Address*/
++
++ I2c_Buffer[3] = CEC_OPCODE_ABORT_MESSAGE ; /* Message Abort*/
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,4); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = I2c_Buffer[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = I2c_Buffer[3];
++
++ return(TM_OK);
++}
++
++//Non Functional function used to provide easy way to access register
++
++//==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecGetRegister( )
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration for CEC Stack Processor.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++unsigned char tmdlHdmiCecGetRegister
++(
++ tmInstance_t instance,
++ UInt32 offset
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++ unsigned char I2c_ReadBuffer[1];
++
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), 0xFF)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, 0xFF)
++
++ /* Ckeck the state */
++ //RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ errCode = getCecHwRegisters(pDis, (UInt8) offset,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, 0xff)
++
++ return(I2c_ReadBuffer[0]);
++}
++
++//QB 10 Jan ==========================================================================
++/*!
++ \fn tmErrorCode_t tmdlHdmiCecSetRegister( )
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration for CEC Stack Processor.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetRegister
++(
++ tmInstance_t instance,
++ UInt32 offset,
++ UInt32 value
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* Ckeck the state */
++ //RETIF(UnitTable[instance].state != CEC_STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMICEC_INVALID_STATE)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ errCode = setCecHwRegister(pDis, (UInt8) offset,(UInt8)value);
++ RETIF(errCode != TM_OK, errCode)
++
++ return(TM_OK);
++}
++
++
++
++//==========================================================================
++/*!
++ \brief Set the power state of an instance of the CEC device. ON
++ state corresponds to a fully supplied, up and running device. Other
++ modes correspond to the powerdown state of the device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \param instance Instance identifier.
++ \param powerState Power state to set.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t powerState
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++#ifdef TMFL_TDA9989
++ unsigned char I2c_ReadBuffer[1];
++
++ tmdlHdmiCecDriverConfigTable_t *pDis;
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ if (powerState == tmPowerOn) {
++
++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ I2c_ReadBuffer[0] |= DEFAULT_ENAMODS;
++
++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ }
++ else if (powerState == tmPowerStandby) {
++
++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ I2c_ReadBuffer[0] &= ~(DEFAULT_ENAMODS);
++
++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++ UnitTable[instance].state = CEC_STATE_NOT_INITIALIZED;
++
++ }
++ else {
++ return TMDL_ERR_DLHDMICEC_BAD_PARAMETER;
++ }
++
++#endif /* TMFL_TDA9989 */
++
++ return errCode;
++}
++
++
++//==========================================================================
++/*!
++ \brief Get the power state of an instance of the CEC device. ON
++ state corresponds to a fully supplied, up and running device. Other
++ modes correspond to the powerdown state of the device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pPowerState Pointer to the power state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecGetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t *pPowerState
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++#ifdef TMFL_TDA9989
++
++ unsigned char I2c_ReadBuffer[1];
++
++ tmdlHdmiCecDriverConfigTable_t *pDis;
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ if (pPowerState == NULL) return TMDL_ERR_DLHDMICEC_BAD_PARAMETER;
++
++
++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++
++ if ((I2c_ReadBuffer[0] & DEFAULT_ENAMODS) == DEFAULT_ENAMODS) {
++ *pPowerState = tmPowerOn;
++ }
++ else {
++ *pPowerState = tmPowerStandby;
++ }
++
++
++#endif /* TMFL_TDA9989 */
++
++ return errCode;
++
++}
++
++//==========================================================================
++/*!
++ \brief This function allow to send a generic CEC message
++ This function has to be used when CEC messages are construct in
++ the middleware
++
++ \param instance Instance identifier.
++
++ \param *pData Pointer to the CEC data buffer
++
++ \param lenData Lenght of I2C data buffer
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++*/
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecSendMessage(
++
++ tmInstance_t instance,
++ UInt8 *pData,
++ UInt16 lenData
++)
++{
++
++ tmErrorCode_t errCode = TM_OK;
++
++#ifdef TMFL_TDA9989
++
++ unsigned char I2c_Buffer[19] ; /* I2C data buffer */
++ unsigned char Loci; /* Local increment variable*/
++ unsigned char MessLength; /* Local Message length*/
++
++ tmdlHdmiCecDriverConfigTable_t *pDis; /* Pointer to Device Instance Structure */
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* check if unit corresponding to instance is opened */
++ RETIF(UnitTable[instance].opened == False, TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED)
++
++ /* check if CEC message is not too long */
++ RETIF((lenData > 16), TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS)
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* Calculate Internal Message length*/
++ MessLength = (lenData-1)+3; /* real data is less ReceiverLogical address */
++
++ I2c_Buffer[0] = MessLength; /* Param number */
++
++ I2c_Buffer[1] = 0x00; /* Request CEC data */
++
++ /*Build Initiator and Reciever Logical Address Byte*/
++ I2c_Buffer[2] = (unsigned char)(UnitTable[instance].DeviceLogicalAddress) & 0x0F; /*Initiator logical Address*/
++ I2c_Buffer[2] = I2c_Buffer[2] << 4;
++ I2c_Buffer[2] |= pData[0] & 0x0F;
++
++ for(Loci = 0; Loci <= lenData ; Loci++)
++ {
++ I2c_Buffer[(Loci+3)] = pData[(Loci+1)]; /* Fill Table with Data from middleware, Data begin at position 1*/
++ }
++
++ errCode = setCecHwRegisters(pDis, E_REG_CDR0, I2c_Buffer,MessLength); /* CEC Data register */
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Save Datas of the CEC message send */
++ gtmdlHdmiCecDriverSaveMessage.AddressByte = pData[2];
++ gtmdlHdmiCecDriverSaveMessage.MessageTypePolling = 0;
++ gtmdlHdmiCecDriverSaveMessage.Opcode = pData[3];
++
++#endif /* TMFL_TDA9989 */
++
++ return errCode;
++
++}
++
++
++
++//==========================================================================
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecEnableCalibration(tmInstance_t instance,tmdlHdmiCecClockSource_t cecClockSource)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++#ifdef TMFL_TDA9989
++
++ unsigned char I2c_ReadBuffer[1];
++ tmdlHdmiCecDriverConfigTable_t *pDis;
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* CLOCK SOURCE is FRO */
++ if (cecClockSource == TMDL_HDMICEC_CLOCK_FRO) {
++
++
++
++ /* cf PR1795 set desired frequency to 12 Mhz*/
++
++ tmdlHdmiCecSetRegister(instance, 0xF3, 0xC0);
++
++ RETIF(errCode != TM_OK, errCode)
++
++ tmdlHdmiCecSetRegister(instance, 0xF4, 0xD4);
++
++ RETIF(errCode != TM_OK, errCode)
++
++ /* set calibration in automatic mode */
++ errCode = getCecHwRegisters(pDis, E_REG_CEC_DES_FREQ2,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++ I2c_ReadBuffer[0] &= CEC_AUTOMATIC_CALIBRATION_MSK;
++ errCode = setCecHwRegister(pDis, E_REG_CEC_DES_FREQ2, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ /* select FRO clock mode, osc_freq shall be also set to one */
++ I2c_ReadBuffer[0] = CEC_SELECT_FRO_CLOCK_SOURCE;
++ errCode = setCecHwRegister(pDis, E_REG_CEC_CLK, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++
++ /* Enable cec_clk AND FRO */
++ errCode = getCecHwRegisters(pDis, E_REG_ENAMODS,I2c_ReadBuffer,1);
++ RETIF(errCode != TM_OK, errCode)
++ I2c_ReadBuffer[0] |= CEC_ENABLE_CEC_CLK_MSK;
++ I2c_ReadBuffer[0] &= CEC_ENABLE_FRO_MSK;
++ errCode = setCecHwRegister(pDis, E_REG_ENAMODS, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++ /* Enable calibration */
++ I2c_ReadBuffer[0] = CEC_ENABLE_CALIBRATION;
++ errCode = setCecHwRegister(pDis, E_REG_CEC_CAL_XOSC_CTRL1, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++ } /* CLOCK SOURCE is FRO */
++
++#endif /* TMFL_TDA9989 */
++
++ return errCode;
++}
++
++
++//==========================================================================
++//==========================================================================
++tmErrorCode_t tmdlHdmiCecDisableCalibration(tmInstance_t instance)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++#ifdef TMFL_TDA9989
++
++ unsigned char I2c_ReadBuffer[1];
++ tmdlHdmiCecDriverConfigTable_t *pDis;
++
++ pDis = &gtmdlHdmiCecDriverConfigTable[instance];
++
++ /* check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMICEC_BAD_INSTANCE)
++
++ /* Disable calibration */
++ I2c_ReadBuffer[0] = CEC_DISABLE_CALIBRATION;
++ errCode = setCecHwRegister(pDis, E_REG_CEC_CAL_XOSC_CTRL1, I2c_ReadBuffer[0]);
++ RETIF(errCode != TM_OK, errCode)
++
++#endif /* TMFL_TDA9989 */
++
++ return errCode;
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c
+new file mode 100755
+index 0000000..ed422d7
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.c
+@@ -0,0 +1,280 @@
++/**
++ * Copyright (C) 2006 Koninklijke Philips Electronics N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of Koninklijke Philips Electronics N.V. and is confidential in
++ * nature. Under no circumstances is this software to be exposed to or placed
++ * under an Open Source License of any type without the expressed written
++ * permission of Koninklijke Philips Electronics N.V.
++ *
++ * \file tmdlHdmiCEC_local.c
++ *
++ * \version $Revision: $
++ *
++ * \date $Date: $
++ *
++ * \brief dev lib driver component for the CEC messages
++ *
++ * \section refs Reference Documents
++ * \section info Change Information
++ *
++ * \verbatim
++ $History: tmdlHdmiCEC_local.c $
++ *
++ \endverbatim
++ *
++*/
++
++/*============================================================================*/
++/* FILE CONFIGURATION */
++/*============================================================================*/
++
++/* Defining this symbol on the compiler command line excludes some API checks */
++/* #define NO_RETIF_BADPARAM */
++
++/*============================================================================*/
++/* STANDARD INCLUDE FILES */
++/*============================================================================*/
++
++
++/*============================================================================*/
++/* PROJECT INCLUDE FILES */
++/*============================================================================*/
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#else
++#include <string.h>
++#endif
++#include "tmdlHdmiCEC.h"
++#include "tmdlHdmiCEC_local.h"
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* TYPE DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* PUBLIC VARIABLE DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* STATIC VARIABLE DECLARATIONS */
++/*============================================================================*/
++
++/**
++ * Lookup table to map an 8-bit mask to a number of left shifts
++ * needed to shift a value starting at bit 0 onto the mask.
++ * Indexed by mask 0-255. For example, mask 0x00 and 0x01 need
++ * no shift, mask 0x02 needs one shift, mask 0x03 needs no shift,
++ * mask 0x04 needs 2 shifts, etc.
++ * Rows were formatted by "HDMI Driver - Register List.xls" and pasted here
++ */
++static CONST_DAT UInt8 kMaskToShift[256] =
++{/* Mask index: */
++ /*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
++ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 1x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 2x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 3x */
++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 4x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 5x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 6x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 7x */
++ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 8x */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 9x */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ax */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Bx */
++ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Cx */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Dx */
++ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* Ex */
++ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* Fx */
++};
++
++/*============================================================================*/
++/* STATIC FUNCTION DECLARATIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* PUBLIC FUNCTION DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* getCecHwRegisters */
++/*============================================================================*/
++tmErrorCode_t
++getCecHwRegisters
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pData,
++ UInt16 lenData
++ )
++{
++ tmErrorCode_t err; /* Error code */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Get I2C register range - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = (UInt8)lenData;
++ sysArgs.pData = pData;
++ err = pDis->i2cReadFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_READ;
++}
++
++/*============================================================================*/
++/* getCecHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++getCecHwRegister
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pRegValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Get I2C register - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = pRegValue;
++ err = pDis->i2cReadFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_READ;
++
++}
++
++/*============================================================================*/
++/* setCecHwRegisters */
++/*============================================================================*/
++tmErrorCode_t
++setCecHwRegisters
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pData,
++ UInt16 lenData
++ )
++{
++ tmErrorCode_t err; /* Error code */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Write to I2C register range - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = (UInt8)lenData;
++ sysArgs.pData = pData;
++ err = pDis->i2cWriteFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE;
++}
++
++/*============================================================================*/
++/* setCecHwRegisterMsbLsb */
++/*============================================================================*/
++tmErrorCode_t
++setCecHwRegisterMsbLsb
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt16 regWord
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 msbLsb[2]; /* The bytes from regWord */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Unpack regWord bytes, MSB first */
++ msbLsb[0] = (UInt8)(regWord >> 8);
++ msbLsb[1] = (UInt8)(regWord & 0xFF);
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 2;
++ sysArgs.pData = &msbLsb[0];
++ err = pDis->i2cWriteFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE;
++}
++
++/*============================================================================*/
++/* setCecHwRegister */
++/*============================================================================*/
++tmErrorCode_t
++setCecHwRegister
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 regValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->i2cWriteFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE;
++}
++
++/*============================================================================*/
++/* setCecHwRegisterField */
++/*============================================================================*/
++tmErrorCode_t
++setCecHwRegisterField
++(
++ tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 fieldMask,
++ UInt8 fieldValue
++)
++{
++ tmErrorCode_t err; /* Error code */
++ UInt8 regValue; /* The register's current value */
++ tmdlHdmiCecSysArgs_t sysArgs; /* Arguments passed to system function */
++
++ /* Read I2C register value.
++ * All bitfield registers are either shadowed or can be read.
++ */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->i2cReadFunction(&sysArgs);
++ RETIF(err != TM_OK, TMDL_ERR_DLHDMICEC_I2C_READ)
++
++ /* Reset register bits that are set in the mask */
++ regValue = regValue & (UInt8)(~fieldMask);
++
++ /* Shift the field value left to align its bits with the mask */
++ fieldValue <<= kMaskToShift[fieldMask];
++
++ /* Reset shifted field bits that are not set in the mask */
++ fieldValue &= fieldMask;
++
++ /* Set the shifted bitfield */
++ regValue |= fieldValue;
++
++ /* Write to I2C - all non-OK results are errors */
++ sysArgs.slaveAddr = pDis->i2cAddress;
++ sysArgs.firstRegister = regAddr;
++ sysArgs.lenData = 1;
++ sysArgs.pData = &regValue;
++ err = pDis->i2cWriteFunction(&sysArgs);
++ return (err == TM_OK) ? TM_OK : TMDL_ERR_DLHDMICEC_I2C_WRITE;
++}
++
++
++/*============================================================================*/
++/* STATIC FUNCTION DEFINTIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h
+new file mode 100755
+index 0000000..c0baa18
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiCEC/src/tmdlHdmiCEC_local.h
+@@ -0,0 +1,221 @@
++//=============================================================================
++// Copyright (C) 2007 NXP N.V., All Rights Reserved.
++// This source code and any compilation or derivative thereof is the proprietary
++// information of NXP N.V. and is confidential in nature. Under no circumstances
++// is this software to be exposed to or placed under an Open Source License of
++// any type without the expressed written permission of NXP N.V.
++//=============================================================================
++/*!
++ \file tmdlHdmiCEC_local.h
++
++ \version 1.0
++
++ \date 24/07/2007
++
++ \brief devlib driver component API for the CEC messages.
++
++ \section refs Reference Documents
++ TDA998X Driver - tmdlHdmiTx - SCS.doc
++ \note None.
++
++ HISTORY :
++ \verbatim
++ Date Modified by CRPRNr TASKNr Maintenance description
++ -------------|-----------|-------|-------|-----------------------------------
++ 24/07/2007 | F.G | | | Creation.
++ -------------|-----------|-------|-------|-----------------------------------
++ \endverbatim
++*/
++//==========================================================================
++
++#ifndef TMDLHDMICEC_LOCAL_H
++#define TMDLHDMICEC_LOCAL_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++//#include "tmdlHdmiCEC_IW.h"
++#include "tmdlHdmiCEC_cfg.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++/* Version of the SW driver */
++#define VERSION_COMPATIBILITY 0
++#define VERSION_MAJOR 1
++#define VERSION_MINOR 4
++
++/**
++ * A macro to check a condition and if true return a result
++ */
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++
++/**
++ * A macro to check a condition and if true return
++ * TMBSL_ERR_HDMI_BAD_PARAMETER.
++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on
++ * the compiler command line.
++ */
++#ifdef NO_RETIF_BADPARAM
++#define RETIF_BADPARAM(cond)
++#else
++#define RETIF_BADPARAM(cond) if ((cond)){return TMBSL_ERR_HDMI_BAD_PARAMETER;}
++#endif
++
++/**
++ * A macro to check the result of a register API and if not TM_OK to return it.
++ * To save code space, it can be compiled out by defining NO_RETIF_REG_FAIL on
++ * the compiler command line.
++ */
++#ifdef NO_RETIF_REG_FAIL
++#define RETIF_REG_FAIL(result)
++#else
++#define RETIF_REG_FAIL(result) if ((result) != TM_OK){return (result);}
++#endif
++
++#define TDA9950_RESET_DELAY_MS 250
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++#ifdef TMFL_TDA9989
++
++#define E_REG_ENAMODS 0xFF
++#define E_REG_CEC_CLK 0xF6
++#define E_REG_CEC_INT 0xEE
++#define E_REG_COMBI_INT 0xEC
++#define DEFAULT_ENAMODS 0x81
++#define CEC_CLK_SEL 0xE6
++#define CEC_INT_MASK 0x01
++
++#define E_REG_CEC_CAL_XOSC_CTRL1 0xF2
++#define E_REG_CEC_DES_FREQ2 0xF5
++
++
++#define CEC_AUTOMATIC_CALIBRATION_MSK 0x7F
++#define CEC_SELECT_FRO_CLOCK_SOURCE 0x11
++#define CEC_ENABLE_CEC_CLK_MSK 0x80
++#define CEC_ENABLE_FRO_MSK 0xBF
++#define CEC_ENABLE_CALIBRATION 0x01
++#define CEC_DISABLE_CALIBRATION 0x00
++
++
++#endif /* TMFL_TDA9989 */
++
++/*!
++ \enum CEC Stack Processor Regsiters
++ \brief The CSP is controlled via a series of registers
++*/
++
++enum _eReg
++{
++ E_REG_APR = 0x00, /*!< Address Pointer Regsiter (Write) */
++ E_REG_CSR = 0x00, /*!< CSP Status Register (Read) */
++ E_REG_CER = 0x01, /*!< CSP Error Register (Read) */
++ E_REG_CVR = 0x02, /*!< CSP Version Register(Read) */
++ E_REG_CCR = 0x03, /*!< CSP Control Register (Read/Write) */
++ E_REG_ACKH = 0x04, /*!< CEC Address ACK High Register (Read/Write) */
++ E_REG_ACKL = 0x05, /*!< CEC Address ACK Low Register (Read/Write) */
++ E_REG_CCONR = 0x06, /*!< CEC Config Register (Read/Write) */
++ E_REG_CDR0 = 0x07, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR1 = 0x08, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR2 = 0x09, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR3 = 0x0A, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR4 = 0x0B, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR5 = 0x0C, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR6 = 0x0D, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR7 = 0x0E, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR8 = 0x0F, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR9 = 0x10, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR10 = 0x11, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR11 = 0x12, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR12 = 0x13, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR13 = 0x14, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR14 = 0x15, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR15 = 0x16, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR16 = 0x17, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR17 = 0x18, /*!< CEC Data Register (Read/Write) */
++ E_REG_CDR18 = 0x19 /*!< CEC Data Register (Read/Write) */
++};
++
++
++/* possible states of the state driver */
++typedef enum
++{
++ CEC_STATE_NOT_INITIALIZED, /**< Driver is not initialized */
++ CEC_STATE_UNLOCKED , /**< Driver is not locked */
++ CEC_STATE_LOCKED, /**< Driver is locked */
++ CEC_STATE_CONFIGURED /**< Driver is configured */
++} tmdlHdmiCecDriverState_t;
++
++/**
++ * \brief The structure of a CEC object, one per device unit
++*/
++typedef struct
++{
++ tmInstance_t instance;
++ tmdlHdmiCECLogicalAddress_t DeviceLogicalAddress;
++ Bool opened; /**< is unit instanciated ? */
++ tmdlHdmiCecDeviceVersion_t deviceVersion; /**< Version of the HW device */
++ tmdlHdmiCecDriverState_t state; /**< Current state of the driver */
++ ptmdlHdmiCecCallbackFunc_t MessageCallback; /**< Message callback */
++}tmdlHdmiCecUnitConfig_t;
++
++
++/**
++ * \brief States of CEC Status
++*/
++#define CEC_MSG_SUCCESS 0x00 /*Message transmisson Succeed*/
++#define CEC_CSP_OFF_STATE 0x80 /*CSP in Off State*/
++#define CEC_BAD_REQ_SERVICE 0x81 /*Bad .req service*/
++#define CEC_MSG_FAIL_UNABLE_TO_ACCESS 0x82 /*Message transmisson failed: Unable to access CEC line*/
++#define CEC_MSG_FAIL_ARBITRATION_ERROR 0x83 /*Message transmisson failed: Arbitration error*/
++#define CEC_MSG_FAIL_BIT_TIMMING_ERROR 0x84 /*Message transmisson failed: Bit timming error*/
++#define CEC_MSG_FAIL_DEST_NOT_ACK 0x85 /*Message transmisson failed: Destination Address not aknowledged*/
++#define CEC_MSG_FAIL_DATA_NOT_ACK 0x86 /*Message transmisson failed: Databyte not acknowledged*/
++
++
++/*============================================================================*/
++/* EXTERN DATA DEFINITION */
++/*============================================================================*/
++
++extern tmdlHdmiCecDriverConfigTable_t gtmdlHdmiCecDriverConfigTable[MAX_UNITS];
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++tmErrorCode_t getCecHwRegisters (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pData, UInt16 lenData);
++tmErrorCode_t getCecHwRegister (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pRegValue);
++tmErrorCode_t setCecHwRegisters (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 *pData, UInt16 lenData);
++tmErrorCode_t setCecHwRegisterMsbLsb (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt16 regWord);
++tmErrorCode_t setCecHwRegister (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 regValue);
++tmErrorCode_t setCecHwRegisterField (tmdlHdmiCecDriverConfigTable_t *pDis,
++ UInt8 regAddr,
++ UInt8 fieldMask, UInt8 fieldValue);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMI_CEC_LOCAL_H */
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c
+new file mode 100755
+index 0000000..aae2c10
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c
+@@ -0,0 +1,570 @@
++/**
++ * Copyright (C) 2009 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_LinuxCfg.c
++ *
++ * \version Revision: 1
++ *
++ * \date Date: 25/03/11 11:00
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ History: tmdlHdmiTx_LinuxCfg.c
++ *
++ * ***************** Version 2 *****************
++ * User: V. Vrignaud Date: March 25th, 2011
++ *
++ * ***************** Version 1 *****************
++ * User: A. Lepine Date: October 1st, 2009
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++/*============================================================================*/
++/* MACRO */
++/*============================================================================*/
++/* macro for quick error handling */
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++#define I2C_M_WR 0
++
++/*============================================================================*/
++/* STATIC FUNCTION DECLARATIONS */
++/*============================================================================*/
++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs);
++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs);
++
++/******************************************************************************
++ ******************************************************************************
++ * THIS PART CAN BE MODIFIED BY CUSTOMER *
++ ******************************************************************************
++ *****************************************************************************/
++struct i2c_client *GetThisI2cClient(void);
++unsigned char my_i2c_data[255];
++
++/* The following includes are used by I2C access function. If */
++/* you need to rewrite these functions for your own SW infrastructure, then */
++/* it can be removed */
++# include <linux/kernel.h>
++# include <linux/errno.h>
++# include <linux/string.h>
++# include <linux/types.h>
++# include <linux/i2c.h>
++# include <linux/delay.h>
++
++#include <linux/gfp.h>
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/vt_kern.h>
++#include <asm/types.h>
++
++/* I2C adress of the unit */
++/* Put there the I2C slave adress of the Tx transmitter IC */
++#define UNIT_I2C_ADDRESS_0 0x70
++
++/* Intel CE 4100 I2C bus number */
++/* Put there the number of I2C bus handling the Rx transmitter IC */
++#define I2C_BUS_NUMBER_0 0 // initial:0
++
++/* I2C Number of bytes in the data buffer. */
++#define SUB_ADDR_BYTE_COUNT_0 1
++
++/* Priority of the command task */
++/* Command task is an internal task that handles incoming event from the IC */
++/* put there a value that will ensure a response time of ~20ms in your system */
++#define COMMAND_TASK_PRIORITY_0 250
++#define COMMAND_TASK_PRIORITY_1 250
++
++/* Priority of the hdcp check tasks */
++/* HDCP task is an internal task that handles periodical HDCP processing */
++/* put there a value that will ensure a response time of ~20ms in your system */
++#define HDCP_CHECK_TASK_PRIORITY_0 250
++
++/* Stack size of the command tasks */
++/* This value depends of the type of CPU used, and also from the length of */
++/* the customer callbacks. Increase this value if you are making a lot of */
++/* processing (function calls & local variables) and that you experience */
++/* stack overflows */
++#define COMMAND_TASK_STACKSIZE_0 128
++#define COMMAND_TASK_STACKSIZE_1 128
++
++/* stack size of the hdcp check tasks */
++/* This value depends of the type of CPU used, default value should be enough */
++/* for all configuration */
++#define HDCP_CHECK_TASK_STACKSIZE_0 128
++
++/* Size of the message queues for command tasks */
++/* This value defines the size of the message queue used to link the */
++/* the tmdlHdmiTxHandleInterrupt function and the command task. The default */
++/* value below should fit any configuration */
++#define COMMAND_TASK_QUEUESIZE_0 128
++#define COMMAND_TASK_QUEUESIZE_1 128
++
++/* HDCP key seed */
++/* HDCP key are stored encrypted into the IC, this value allows the IC to */
++/* decrypt them. This value is provided to the customer by NXP customer */
++/* support team. */
++#define KEY_SEED 0x1234
++
++/* Video port configuration for YUV444 input */
++/* You can specify in this table how are connected video ports in case of */
++/* YUV444 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */
++ }
++};
++
++/* Video port configuration for RGB444 input */
++/* You can specify in this table how are connected video ports in case of */
++/* RGB444 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPC[4..7] */
++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPB[4..7] */
++ }
++};
++
++/* Video port configuration for YUV422 input */
++/* You can specify in this table how are connected video ports in case of */
++/* YUV422 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID422_Y_4_TO_7, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID422_Y_8_TO_11, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID422_UV_4_TO_7, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID422_UV_8_TO_11, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID422_NOT_CONNECTED /* Signals connected to VPC[4..7] */
++ }
++};
++
++/* Video port configuration for CCIR656 input */
++/* You can specify in this table how are connected video ports in case of */
++/* CCIR656 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VIDCCIR_4_TO_7, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VIDCCIR_8_TO_11, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED /* Signals connected to VPC[4..7] */
++ }
++};
++
++/*
++ *
++ * Linux wrapping starts here...............................
++ *
++ */
++/*
++ * Write a bloc to a register in Tx device.
++ */
++int blockwrite_reg(struct i2c_client *client, u8 reg, u16 alength, u8 *val)
++{
++ int err = 0;
++ int i;
++ struct i2c_msg msg[1];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = alength+1;
++ msg->buf = my_i2c_data;
++
++ msg->buf[0] = reg;
++ for (i=1; i<=alength; i++) msg->buf[i] = (*val++);
++
++ err = i2c_transfer(client->adapter, msg, 1);
++ udelay(50);
++
++
++/* printk(KERN_INFO "DBG blockwrite_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */
++
++/* dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, " */
++/* "*val=%d flags=%d byte[%d] err=%d\n", */
++/* __func__, data[0], data[1], msg->flags, i, err); */
++
++ return (err < 0?err:0);
++}
++
++/*
++ * Read a bloc to a register in Tx device.
++ */
++int blockread_reg(struct i2c_client *client, u8 reg, u16 alength, u8 *val)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 1;
++ msg->buf = data;
++ data[0] = reg; /* High byte goes out first */
++ err = i2c_transfer(client->adapter, msg, 1);
++/* printk(KERN_INFO "DBG blockread_reg #1 addr:%x len:%d buf:%02x%02x%02x%02x %s\n",msg->addr,msg->len,\ */
++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3],(err<0?"ERROR":"")); */
++ if (err<0) goto BLOCK_READ_OUPS;
++
++ msg->flags = I2C_M_RD;
++ msg->len = alength;
++ msg->buf = val;
++ err = i2c_transfer(client->adapter, msg, 1);
++/* printk(KERN_INFO "DBG blockread_reg #2 addr:%x len:%d buf:%02x%02x%02x%02x %s\n",msg->addr,msg->len,\ */
++/* msg->buf[0],msg->buf[1],msg->buf[2],msg->buf[3],(err<0?"ERROR":"")); */
++
++ if (err<0) goto BLOCK_READ_OUPS;
++
++ return 0;
++
++ BLOCK_READ_OUPS:
++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
++ "*val=%d flags=%d bytes err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++
++ return err;
++}
++
++/*
++ * Write a byte to a register in Tx device.
++ */
++int write_reg(struct i2c_client *client, u8 reg, u8 val)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++ int retries = 0;
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ retry:
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 2;
++ msg->buf = data;
++
++ data[0] = reg;
++ data[1] = val;
++
++ err = i2c_transfer(client->adapter, msg, 1);
++ dev_dbg(&client->dev, "<%s> i2c write at=%x "
++ "val=%x flags=%d err=%d\n",
++ __func__, data[0], data[1], msg->flags, err);
++ udelay(50);
++
++/* printk(KERN_INFO "DBG write_reg addr:%x reg:%d data:%x %s\n",msg->addr,reg,val,(err<0?"ERROR":"")); */
++
++ if (err >= 0)
++ return 0;
++
++ dev_err(&client->dev, "<%s> ERROR: i2c write at=%x "
++ "val=%x flags=%d err=%d\n",
++ __func__, data[0], data[1], msg->flags, err);
++ if (retries <= 5) {
++ dev_info(&client->dev, "Retrying I2C... %d\n", retries);
++ retries++;
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_timeout(msecs_to_jiffies(20));
++ goto retry;
++ }
++
++ return err;
++}
++
++/*
++ * Read a byte from a register in Tx device.
++ */
++int read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val)
++{
++ int err = 0;
++ struct i2c_msg msg[1];
++ u8 data[2];
++
++ if (!client->adapter) {
++ dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
++ return -ENODEV;
++ }
++
++ msg->addr = client->addr;
++ msg->flags = I2C_M_WR;
++ msg->len = 1;
++ msg->buf = data;
++
++ data[0] = reg;
++ err = i2c_transfer(client->adapter, msg, 1);
++ dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d "
++ "flags=%d err=%d\n",
++ __func__, reg, data[1], msg->flags, err);
++
++ if (err >= 0) {
++ mdelay(3);
++ msg->flags = I2C_M_RD;
++ msg->len = data_length;
++ err = i2c_transfer(client->adapter, msg, 1);
++ }
++
++ if (err >= 0) {
++ *val = 0;
++ if (data_length == 1)
++ *val = data[0];
++ else if (data_length == 2)
++ *val = data[1] + (data[0] << 8);
++ dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d "
++ "flags=%d err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++ return 0;
++ }
++
++ dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
++ "*val=%d flags=%d err=%d\n",
++ __func__, reg, *val, msg->flags, err);
++
++ return err;
++}
++/*
++ *
++ * Linux wrapping end...............................
++ *
++ */
++
++/* The following function must be rewritten by the customer to fit its own */
++/* SW infrastructure. This function allows reading through I2C bus. */
++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */
++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs)
++{
++ tmErrorCode_t errCode = TM_OK;
++ struct i2c_client *client=GetThisI2cClient();
++ u32 client_main_addr=client->addr;
++
++ /* DevLib needs address control, so let it be */
++ client->addr=pSysArgs->slaveAddr;
++
++ if (pSysArgs->lenData == 1) {
++ /* single byte */
++ errCode = read_reg(GetThisI2cClient(),1,pSysArgs->firstRegister,pSysArgs->pData);
++ }
++ else {
++ /* block */
++ errCode = blockread_reg(GetThisI2cClient(), \
++ pSysArgs->firstRegister, \
++ pSysArgs->lenData, \
++ pSysArgs->pData);
++ }
++
++ /* restore default client address */
++ client->addr=client_main_addr;
++
++ return errCode;
++}
++
++/* The following function must be rewritten by the customer to fit its own */
++/* SW infrastructure. This function allows writing through I2C bus. */
++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */
++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs)
++{
++ tmErrorCode_t errCode = TM_OK;
++ struct i2c_client *client=GetThisI2cClient();
++ u32 client_main_addr=client->addr;
++
++ /* DevLib needs address control, so let it be */
++ client->addr=pSysArgs->slaveAddr;
++
++ if (pSysArgs->lenData == 1) {
++ /* single byte */
++ errCode = write_reg(GetThisI2cClient(),pSysArgs->firstRegister,*pSysArgs->pData);
++ }
++ else {
++ /* block */
++ errCode = blockwrite_reg(GetThisI2cClient(), \
++ pSysArgs->firstRegister, \
++ pSysArgs->lenData, \
++ pSysArgs->pData);
++ }
++
++ /* restore default client address */
++ client->addr=client_main_addr;
++
++ return errCode;
++}
++
++
++/******************************************************************************
++ \brief This function blocks the current task for the specified amount time.
++ This is a passive wait.
++
++ \param Duration Duration of the task blocking in milliseconds.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWWait
++(
++ UInt16 duration
++)
++{
++ mdelay((unsigned long)duration);
++
++ return(TM_OK);
++}
++
++/******************************************************************************
++ \brief This function creates a semaphore.
++
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate
++(
++ tmdlHdmiTxIWSemHandle_t *pHandle
++)
++{
++ struct semaphore * mutex;
++
++ /* check that input pointer is not NULL */
++ RETIF(pHandle == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ mutex = (struct semaphore *)kmalloc(sizeof(struct semaphore),GFP_KERNEL);
++ if (!mutex) {
++ printk(KERN_ERR "malloc failed in %s\n",__func__);
++ return TMDL_ERR_DLHDMITX_NO_RESOURCES;
++ }
++
++ sema_init(mutex, 1);
++ *pHandle = (tmdlHdmiTxIWSemHandle_t)mutex;
++
++ RETIF(pHandle == NULL, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++
++ return(TM_OK);
++}
++
++/******************************************************************************
++ \brief This function destroys an existing semaphore.
++
++ \param Handle Handle of the semaphore to be destroyed.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy
++(
++ tmdlHdmiTxIWSemHandle_t handle
++)
++{
++ RETIF(handle == False, TMDL_ERR_DLHDMITX_BAD_HANDLE);
++
++ if (atomic_read((atomic_t*)&((struct semaphore *)handle)->count) < 1) {
++ printk(KERN_ERR "release catched semaphore");
++ }
++
++ kfree((void*)handle);
++
++ return(TM_OK);
++}
++
++/******************************************************************************
++ \brief This function acquires the specified semaphore.
++
++ \param Handle Handle of the semaphore to be acquired.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreP
++(
++ tmdlHdmiTxIWSemHandle_t handle
++)
++{
++ down((struct semaphore *)handle);
++
++ return(TM_OK);
++}
++
++/******************************************************************************
++ \brief This function releases the specified semaphore.
++
++ \param Handle Handle of the semaphore to be released.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreV
++(
++ tmdlHdmiTxIWSemHandle_t handle
++)
++{
++ up((struct semaphore *)handle);
++
++ return(TM_OK);
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c
+new file mode 100755
+index 0000000..23c5437
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_cfg.c
+@@ -0,0 +1,624 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_cfg.c
++ *
++ * \version Revision: 1
++ *
++ * \date Date: 25/03/11 11:00
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ History: tmdlHdmiTx_cfg.c
++ *
++ * ***************** Version 2 *****************
++ * User: V. Vrignaud Date: March 25th, 2011
++ *
++ * ***************** Version 1 *****************
++ * User: J. Lamotte Date: 08/08/07 Time: 11:00
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmdlHdmiTx_IW.h"
++#include "tmdlHdmiTx.h"
++#include "tmdlHdmiTx_cfg.h"
++
++#ifdef TMFL_CEC_AVAILABLE
++#include "tmdlHdmiCEC_functions.h"
++#define CEC_UNIT_I2C_ADDRESS_0 0x34
++#define CEC_UNIT_I2C_ADDRESS_1 0x34
++#endif
++
++//#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#ifdef TMFL_CFG_ZOOMII // OMAP Zoom II
++# include "tmdlHdmiTx_Linux_cfg.c"
++#elif TMFL_CFG_INTELCE4100 // Intel CE 4100
++# include "tmdlHdmiTx_IntelCE4100_cfg.c"
++#elif TMFL_OS_WINDOWS // Windows demo application
++# include "tmdlHdmiTx_Win_cfg.c"
++#else // Section to be modified by customer - Default configuration for NXP evalkit
++
++/*============================================================================*/
++/* MACRO */
++/*============================================================================*/
++
++/*============================================================================*/
++/* STATIC FUNCTION DECLARATIONS */
++/*============================================================================*/
++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs);
++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs);
++
++/******************************************************************************
++ ******************************************************************************
++ * THIS PART CAN BE MODIFIED BY CUSTOMER *
++ ******************************************************************************
++ *****************************************************************************/
++/* The following includes are used by I2C access function for ARM7. If */
++/* you need to rewrite these functions for your own SW infrastructure, then */
++/* it can be removed */
++#include "I2C.h"
++#include <LPC21xx.H>
++
++/* I2C adress of the unit */
++/* Put there the I2C slave adress of the Tx transmitter IC */
++#define UNIT_I2C_ADDRESS_0 0x70
++
++/* Priority of the command task */
++/* Command task is an internal task that handles incoming event from the IC */
++/* put there a value that will ensure a response time of ~20ms in your system */
++#define COMMAND_TASK_PRIORITY_0 250
++#define COMMAND_TASK_PRIORITY_1 250
++
++/* Priority of the hdcp check tasks */
++/* HDCP task is an internal task that handles periodical HDCP processing */
++/* put there a value that will ensure a response time of ~20ms in your system */
++#define HDCP_CHECK_TASK_PRIORITY_0 250
++
++/* Stack size of the command tasks */
++/* This value depends of the type of CPU used, and also from the length of */
++/* the customer callbacks. Increase this value if you are making a lot of */
++/* processing (function calls & local variables) and that you experience */
++/* stack overflows */
++#define COMMAND_TASK_STACKSIZE_0 128
++#define COMMAND_TASK_STACKSIZE_1 128
++
++/* stack size of the hdcp check tasks */
++/* This value depends of the type of CPU used, default value should be enough */
++/* for all configuration */
++#define HDCP_CHECK_TASK_STACKSIZE_0 128
++
++/* Size of the message queues for command tasks */
++/* This value defines the size of the message queue used to link the */
++/* the tmdlHdmiTxHandleInterrupt function and the command task. The default */
++/* value below should fit any configuration */
++#define COMMAND_TASK_QUEUESIZE_0 128
++#define COMMAND_TASK_QUEUESIZE_1 128
++
++/* HDCP key seed */
++/* HDCP key are stored encrypted into the IC, this value allows the IC to */
++/* decrypt them. This value is provided to the customer by NXP customer */
++/* support team. */
++#define KEY_SEED 0x1234
++
++/* Video port configuration for YUV444 input */
++/* You can specify in this table how are connected video ports in case of */
++/* YUV444 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */
++ }
++};
++
++/* Video port configuration for RGB444 input */
++/* You can specify in this table how are connected video ports in case of */
++/* RGB444 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID444_GY_0_TO_3, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID444_GY_4_TO_7, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID444_BU_0_TO_3, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID444_BU_4_TO_7, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID444_VR_0_TO_3, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID444_VR_4_TO_7 /* Signals connected to VPC[4..7] */
++ }
++};
++
++/* Video port configuration for YUV422 input */
++/* You can specify in this table how are connected video ports in case of */
++/* YUV422 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID422_NOT_CONNECTED, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID422_UV_4_TO_7, /* Signals connected to VPC[4..7] */
++ TMDL_HDMITX_VID422_UV_8_TO_11, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID422_Y_4_TO_7, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID422_Y_8_TO_11 /* Signals connected to VPA[4..7] */
++ }
++};
++
++/* Video port configuration for CCIR656 input */
++/* You can specify in this table how are connected video ports in case of */
++/* CCIR656 input signal. Each line of the array corresponds to a quartet of */
++/* pins of one video port (see comment on the left to identify them). Just */
++/* change the enum to specify which signal you connected to it. See file */
++/* tmdlHdmiTx_cfg.h to get the list of possible values */
++const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED, /* Signals connected to VPC[4..7] */
++ TMDL_HDMITX_VIDCCIR_4_TO_7, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VIDCCIR_8_TO_11 /* Signals connected to VPA[0..3] */
++ }
++};
++
++/* The following function must be rewritten by the customer to fit its own */
++/* SW infrastructure. This function allows reading through I2C bus. */
++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */
++tmErrorCode_t TxI2cReadFunction(tmbslHdmiTxSysArgs_t *pSysArgs)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++ if (pSysArgs->slaveAddr == 0x70)
++ {
++ errCode = i2cRead(reg_TDA998X, (tmbslHdmiSysArgs_t *) pSysArgs);
++ }
++ else if (pSysArgs->slaveAddr == 0x34)
++ {
++ errCode = i2cRead(reg_TDA9989_CEC, (tmbslHdmiSysArgs_t *) pSysArgs);
++ }
++ else
++ {
++ errCode = ~TM_OK;
++ }
++
++ return errCode;
++}
++
++/* The following function must be rewritten by the customer to fit its own */
++/* SW infrastructure. This function allows writing through I2C bus. */
++/* tmbslHdmiTxSysArgs_t definition is located into tmbslHdmiTx_type.h file. */
++tmErrorCode_t TxI2cWriteFunction(tmbslHdmiTxSysArgs_t *pSysArgs)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++ if (pSysArgs->slaveAddr == 0x70)
++ {
++ errCode = i2cWrite(reg_TDA998X, (tmbslHdmiSysArgs_t *) pSysArgs);
++
++ }
++ else if (pSysArgs->slaveAddr == 0x34)
++ {
++ errCode = i2cWrite(reg_TDA9989_CEC, (tmbslHdmiSysArgs_t *) pSysArgs);
++ }
++ else
++ {
++ errCode = ~TM_OK;
++ }
++
++ return errCode;
++}
++
++#endif
++
++#ifdef TMFL_RGB_DDR_12BITS
++
++/* Video port configuration for RGB 24 bits input received with only 12 bits */
++/* using the double data rate */
++/*
++ The main difference between RGB12 bits and CCIR 656 formats is that for the new format
++ RGB888 the“Green� data is separated on rising and on falling edge. This is in principle
++ no problem only the result is that the colors RGB will be swabbed.
++ After the Video Input Processing (VIP) module there will be a multiplexer structure
++ implemented which can swab all colors and combinations.
++
++ Extra information on request
++
++ P:\Partages\BCT_TV_FE\Product_Development\Project folders\TDA19988 \
++ 14_Design\Video_pipe_Schematic_RGB888.pdf
++
++ but ok, let's give it a try...
++
++ In DDR, VIP input latches on failing and raising clock edge,
++ so VIP internal input is doubled from 24 to 48 bits
++
++ VIP input ------>[ T ]---[ T ]--------------------> VIP internal input
++ /24 | | ° /24 | /48
++ | | | |
++ | pclk----------- |
++ | | |
++ | ° |
++ ------>[ T ]------------------
++ /24
++
++ But in the 24 VIP input, only 12 bits are used :
++
++ -------------------------------------------------------------------
++ | | | | | | |
++ | Vpc[7:4] | Vpc[3:0] | Vpb[7:4] | Vpb[3:0] | Vpa[7:4] | Vpa[3:0] |
++ | | | ........ | | ........ | ........ |
++ -------------------------------------------------------------------
++ ^ ^ ^
++ | | |
++ | | |
++ location of valid data -------------------------------------
++
++ So we get first RGB 12 bits on bits 24 to 47 of VIP internal input
++ and second RGB 12 bits on bits 0 to 23 of VIP internal input
++
++ 1)first edge (failing) R[7:4] R[3:0] G[7:4]
++ | | |
++ | | |
++ V V V
++ --------------------------------------------------------------------..
++ | | | | | | |
++ | 47...44 | 43...40 | 39...36 | 35...32 | 31...28 | 27...24 |
++ | | | | | | |
++ --------------------------------------------------------------------..
++
++ 2)2nd edge (raising) G[3:0] B[7:3] B[3:0]
++ | | |
++ | | |
++ V V V
++..-------------------------------------------------------------------
++ | | | | | | |
++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 |
++ | | | | | | |
++..-------------------------------------------------------------------
++
++
++
++
++
++
++ After port swaping, internal video bus goes back from 48 to 24 bits
++
++ VIP internal ------------>[ swap ]-------[ T ]---------->
++ /48 | | /24
++ | |
++ i2c_swap_a/f ------ pclk ---
++
++ -------------------------------------------------------------------
++ | | | | | | |
++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 |
++ | | | | | | |
++ -------------------------------------------------------------------
++ R[7:4] R[3:0] G[7:4] G[3:0] B[7:3] B[3:0]
++
++ Here is the swapping code :
++
++IF i2c_swap_a = "000" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(23 downto 20); vp_alt_d2(23 downto 20) <= vp_alt_i_r(47 downto 44);
++ELSIF i2c_swap_a = "001" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(19 downto 16); vp_alt_d2(23 downto 20) <= vp_alt_i_r(43 downto 40);
++ELSIF i2c_swap_a = "010" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(15 downto 12); vp_alt_d2(23 downto 20) <= vp_alt_i_r(39 downto 36);
++ELSIF i2c_swap_a = "011" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(35 downto 32);
++ELSIF i2c_swap_a = "100" THEN vp_alt_d2(11 downto 8) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(31 downto 28);
++ELSE vp_alt_d2(11 downto 8) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(23 downto 20) <= vp_alt_i_r(27 downto 24); END IF;
++
++IF i2c_swap_b = "000" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(23 downto 20); vp_alt_d2(19 downto 16) <= vp_alt_i_r(47 downto 44);
++ELSIF i2c_swap_b = "001" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(19 downto 16); vp_alt_d2(19 downto 16) <= vp_alt_i_r(43 downto 40);
++ELSIF i2c_swap_b = "010" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(15 downto 12); vp_alt_d2(19 downto 16) <= vp_alt_i_r(39 downto 36);
++ELSIF i2c_swap_b = "011" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(35 downto 32);
++ELSIF i2c_swap_b = "100" THEN vp_alt_d2( 7 downto 4) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(31 downto 28);
++ELSE vp_alt_d2( 7 downto 4) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(19 downto 16) <= vp_alt_i_r(27 downto 24); END IF;
++
++IF i2c_swap_c = "000" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(23 downto 20); vp_alt_d2(15 downto 12) <= vp_alt_i_r(47 downto 44);
++ELSIF i2c_swap_c = "001" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(19 downto 16); vp_alt_d2(15 downto 12) <= vp_alt_i_r(43 downto 40);
++ELSIF i2c_swap_c = "010" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(15 downto 12); vp_alt_d2(15 downto 12) <= vp_alt_i_r(39 downto 36);
++ELSIF i2c_swap_c = "011" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r(11 downto 8 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(35 downto 32);
++ELSIF i2c_swap_c = "100" THEN vp_alt_d2( 3 downto 0) <= vp_alt_i_r( 7 downto 4 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(31 downto 28);
++ELSE vp_alt_d2( 3 downto 0) <= vp_alt_i_r( 3 downto 0 ); vp_alt_d2(15 downto 12) <= vp_alt_i_r(27 downto 24); END IF;
++
++ in case of RGB DDR 12 bits, we get :
++ . i2c_swap_a = "010"
++ . i2c_swap_b = "011"
++ . i2c_swap_c > "100"
++
++ ;)
++
++*/
++
++const tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6] = {
++ {
++ TMDL_HDMITX_VID_B_0_3_G_4_7, /* Signals connected to VPA[0..3] */
++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED, /* Signals connected to VPA[4..7] */
++ TMDL_HDMITX_VID_B_4_7_R_0_3, /* Signals connected to VPB[0..3] */
++ TMDL_HDMITX_VID_G_0_3_R_4_7, /* Signals connected to VPB[4..7] */
++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED, /* Signals connected to VPC[0..3] */
++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED /* Signals connected to VPC[4..7] */
++ }
++};
++
++/*
++
++ Then VIP targeted order is not RGB but BGR
++ so we use a new register for TDA19988 MUX_VP_VIP_OUT
++ with VIP_OUTPUT_RGB_GBR as defined in cfg.h file
++
++ -------------------------------------------------------------------
++ | | | | | | |
++ | 23...20 | 19...16 | 15...12 | 11...8 | 7...4 | 3...0 |
++ | | | | | | |
++ -------------------------------------------------------------------
++ R[7:4] R[3:0] G[7:4] G[3:0] B[7:3] B[3:0]
++ - . .
++ - . .
++ - . .
++ - . .
++ . - .
++ . - .
++ . - .
++ . -
++ . . -
++ . . -
++ . . -
++
++ G[7:4] G[3:0] B[7:4] B[3:0] R[7:3] R[3:0]
++
++*/
++
++const UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS] = {
++ VIP_MUX_R_R | VIP_MUX_G_G | VIP_MUX_B_B
++};
++
++const UInt8 VideoPortNoMux[MAX_UNITS] = {
++ VIP_MUX_G_B | VIP_MUX_B_R | VIP_MUX_R_G
++};
++
++#endif /* TMFL_RGB_DDR_12BITS */
++
++/* Audio port configuration for SPDIF */
++/* Here you can specify the audio port routing configuration for SPDIF input. */
++/* enableAudioPortSPDIF and groundAudioPortSPDIF should be filled with a */
++/* value build as follows : each bit represent an audio port, LSB is port 0. */
++/* enableAudioClockPortSPDIF and groundAudioClockPortSPDIF can be configured */
++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */
++UInt8 enableAudioPortSPDIF[MAX_UNITS] = {0x02};
++UInt8 enableAudioClockPortSPDIF[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT};
++UInt8 groundAudioPortSPDIF[MAX_UNITS] = {0xFD};
++UInt8 groundAudioClockPortSPDIF[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT_PULLDOWN};
++
++/* Audio port configuration for I2S */
++/* Here you can specify the audio port routing configuration for SPDIF input. */
++/* enableAudioPortI2S and groundAudioPortI2S should be filled with a */
++/* value build as follows : each bit represent an audio port, LSB is port 0. */
++/* enableAudioClockPortI2S and groundAudioClockPortI2S can be configured */
++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */
++UInt8 enableAudioPortI2S[MAX_UNITS] = {0x03};
++UInt8 enableAudioPortI2S8C[MAX_UNITS] = {0x1f};
++UInt8 enableAudioClockPortI2S[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT};
++UInt8 groundAudioPortI2S[MAX_UNITS] = {0xfc};
++UInt8 groundAudioPortI2S8C[MAX_UNITS] = {0xe0};
++UInt8 groundAudioClockPortI2S[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN};
++
++/* Audio port configuration for OBA */
++/* Here you can specify the audio port routing configuration for SPDIF input. */
++/* enableAudioPortOBA and groundAudioPortOBA should be filled with a */
++/* value build as follows : each bit represent an audio port, LSB is port 0. */
++/* enableAudioClockPortOBA and groundAudioClockPortOBA can be configured */
++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */
++UInt8 enableAudioPortOBA[MAX_UNITS] = {0xFF};
++UInt8 enableAudioClockPortOBA[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT};
++UInt8 groundAudioPortOBA[MAX_UNITS] = {0x00};
++UInt8 groundAudioClockPortOBA[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN};
++
++/* Audio port configuration for DST */
++/* Here you can specify the audio port routing configuration for SPDIF input. */
++/* enableAudioPortDST and groundAudioPortDST should be filled with a */
++/* value build as follows : each bit represent an audio port, LSB is port 0. */
++/* enableAudioClockPortDST and groundAudioClockPortDST can be configured */
++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */
++UInt8 enableAudioPortDST[MAX_UNITS] = {0xFF};
++UInt8 enableAudioClockPortDST[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT};
++UInt8 groundAudioPortDST[MAX_UNITS] = {0x00};
++UInt8 groundAudioClockPortDST[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN};
++
++/* Audio port configuration for HBR */
++/* Here you can specify the audio port routing configuration for SPDIF input. */
++/* enableAudioPortHBR and groundAudioPortHBR should be filled with a */
++/* value build as follows : each bit represent an audio port, LSB is port 0. */
++/* enableAudioClockPortHBR and groundAudioClockPortHBR can be configured */
++/* with the corresponding enums (See file tmdlHdmiTx_cfg.h for more details). */
++UInt8 enableAudioPortHBR[MAX_UNITS] = {0x1f};
++UInt8 enableAudioClockPortHBR[MAX_UNITS] = {ENABLE_AUDIO_CLOCK_PORT};
++UInt8 groundAudioPortHBR[MAX_UNITS] = {0xe0};
++UInt8 groundAudioClockPortHBR[MAX_UNITS] = {DISABLE_AUDIO_CLOCK_PORT_PULLDOWN};
++
++/*****************************************************************************
++******************************************************************************
++* THIS PART MUST NOT BE MODIFIED BY CUSTOMER *
++******************************************************************************
++*****************************************************************************/
++
++/* DO NOT MODIFY, those tables are filled dynamically by */
++/* dlHdmiTxGenerateCfgVideoPortTables API */
++UInt8 mirrorTableCCIR656[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 swapTableCCIR656[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 enableVideoPortCCIR656[MAX_UNITS][3] = {{0x00, 0x00, 0x00}};
++UInt8 groundVideoPortCCIR656[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}};
++UInt8 mirrorTableYUV422[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 swapTableYUV422[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 enableVideoPortYUV422[MAX_UNITS][3] = {{0x00, 0x00, 0x00}};
++UInt8 groundVideoPortYUV422[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}};
++UInt8 mirrorTableYUV444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 swapTableYUV444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 enableVideoPortYUV444[MAX_UNITS][3] = {{0x00, 0x00, 0x00}};
++UInt8 groundVideoPortYUV444[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}};
++UInt8 mirrorTableRGB444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 swapTableRGB444[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 enableVideoPortRGB444[MAX_UNITS][3] = {{0x00, 0x00, 0x00}};
++UInt8 groundVideoPortRGB444[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}};
++#ifdef TMFL_RGB_DDR_12BITS
++UInt8 mirrorTableRGB_DDR_12bits[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 swapTableRGB_DDR_12bits[MAX_UNITS][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
++UInt8 enableVideoPortRGB_DDR_12bits[MAX_UNITS][3] = {{0x00, 0x00, 0x00}};
++UInt8 groundVideoPortRGB_DDR_12bits[MAX_UNITS][3] = {{0xFF, 0xFF, 0xFF}};
++UInt8 NoMux[MAX_UNITS] = {0x00};
++UInt8 Mux_RGB_DDR_12bits[MAX_UNITS] = {0x00};
++#endif
++
++/* DO NOT MODIFY, this table is used for transmission of the configuration to */
++/* the core driver */
++tmdlHdmiTxDriverConfigTable_t driverConfigTableTx[MAX_UNITS] = {
++ {
++ COMMAND_TASK_PRIORITY_0,
++ COMMAND_TASK_STACKSIZE_0,
++ COMMAND_TASK_QUEUESIZE_0,
++ HDCP_CHECK_TASK_PRIORITY_0,
++ HDCP_CHECK_TASK_STACKSIZE_0,
++ UNIT_I2C_ADDRESS_0,
++ TxI2cReadFunction,
++ TxI2cWriteFunction,
++ Null, /* filled dynamically, do not modify */
++ &mirrorTableCCIR656[0][0], /* filled dynamically, do not modify */
++ &swapTableCCIR656[0][0], /* filled dynamically, do not modify */
++ &enableVideoPortCCIR656[0][0], /* filled dynamically, do not modify */
++ &groundVideoPortCCIR656[0][0], /* filled dynamically, do not modify */
++ &mirrorTableYUV422[0][0], /* filled dynamically, do not modify */
++ &swapTableYUV422[0][0], /* filled dynamically, do not modify */
++ &enableVideoPortYUV422[0][0], /* filled dynamically, do not modify */
++ &groundVideoPortYUV422[0][0], /* filled dynamically, do not modify */
++ &mirrorTableYUV444[0][0], /* filled dynamically, do not modify */
++ &swapTableYUV444[0][0], /* filled dynamically, do not modify */
++ &enableVideoPortYUV444[0][0], /* filled dynamically, do not modify */
++ &groundVideoPortYUV444[0][0], /* filled dynamically, do not modify */
++ &mirrorTableRGB444[0][0], /* filled dynamically, do not modify */
++ &swapTableRGB444[0][0], /* filled dynamically, do not modify */
++ &enableVideoPortRGB444[0][0], /* filled dynamically, do not modify */
++ &groundVideoPortRGB444[0][0], /* filled dynamically, do not modify */
++#ifdef TMFL_RGB_DDR_12BITS
++ &mirrorTableRGB_DDR_12bits[0][0],
++ &swapTableRGB_DDR_12bits[0][0],
++ &NoMux[0],
++ &Mux_RGB_DDR_12bits[0],
++ &enableVideoPortRGB_DDR_12bits[0][0],
++ &groundVideoPortRGB_DDR_12bits[0][0],
++#endif
++ &enableAudioPortSPDIF[0],
++ &groundAudioPortSPDIF[0],
++ &enableAudioClockPortSPDIF[0],
++ &groundAudioClockPortSPDIF[0],
++ &enableAudioPortI2S[0],
++ &groundAudioPortI2S[0],
++ &enableAudioPortI2S8C[0],
++ &groundAudioPortI2S8C[0],
++ &enableAudioClockPortI2S[0],
++ &groundAudioClockPortI2S[0],
++ &enableAudioPortOBA[0],
++ &groundAudioPortOBA[0],
++ &enableAudioClockPortOBA[0],
++ &groundAudioClockPortOBA[0],
++ &enableAudioPortDST[0],
++ &groundAudioPortDST[0],
++ &enableAudioClockPortDST[0],
++ &groundAudioClockPortDST[0],
++ &enableAudioPortHBR[0],
++ &groundAudioPortHBR[0],
++ &enableAudioClockPortHBR[0],
++ &groundAudioClockPortHBR[0],
++ KEY_SEED,
++ TMDL_HDMITX_PATTERN_BLUE,
++ 1 /* DE signal is available */
++ }
++ };
++
++#ifdef TMFL_CEC_AVAILABLE
++
++tmdlHdmiCecCapabilities_t CeccapabilitiesList = {TMDL_HDMICEC_DEVICE_UNKNOWN, CEC_VERSION_1_3a};
++
++/**
++ * \brief Configuration Tables. This table can be modified by the customer
++ to choose its prefered configuration
++ */
++
++tmdlHdmiCecDriverConfigTable_t CecdriverConfigTable[MAX_UNITS] = {
++ {
++ COMMAND_TASK_PRIORITY_0,
++ COMMAND_TASK_STACKSIZE_0,
++ COMMAND_TASK_QUEUESIZE_0,
++ CEC_UNIT_I2C_ADDRESS_0,
++ TxI2cReadFunction,
++ TxI2cWriteFunction,
++ &CeccapabilitiesList
++ }
++};
++
++
++/******************************************************************************
++******************************************************************************
++* THIS PART MUST NOT BE MODIFIED BY CUSTOMER *
++******************************************************************************
++*****************************************************************************/
++
++/**
++ \brief This function allows to the main driver to retrieve its
++ configuration parameters.
++
++ \param pConfig Pointer to the config structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiCecCfgGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiCecDriverConfigTable_t *pConfig
++)
++{
++ /* check if unit number is in range */
++ if((unit < 0) || (unit >= MAX_UNITS))
++ return TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER;
++
++ /* check if pointer is Null */
++ if(pConfig == Null)
++ return TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS;
++
++ *pConfig = CecdriverConfigTable[unit];
++
++ return TM_OK;
++}
++
++#endif
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h
+new file mode 100755
+index 0000000..1b8cd29
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_IW.h
+@@ -0,0 +1,290 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_IW.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 07/08/07 16:00 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * TDA998x Driver - FRS.doc,
++ * TDA998x Driver - tmdlHdmiTx - SCS.doc
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiTx_IW.h $
++ *
++ * ***************** Version 1 *****************
++ * User: J. Lamotte Date: 07/08/07 Time: 16:00
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMITX_IW_H
++#define TMDLHDMITX_IW_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#ifdef TMFL_OS_WINDOWS
++#define _WIN32_WINNT 0x0500
++#include "windows.h"
++#endif
++
++#include "tmNxTypes.h"
++#include "tmdlHdmiTx_Types.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* TYPE DEFINITIONS */
++/*============================================================================*/
++typedef void (*tmdlHdmiTxIWFuncPtr_t) (void);
++typedef UInt8 tmdlHdmiTxIWTaskHandle_t;
++typedef UInt8 tmdlHdmiTxIWQueueHandle_t;
++#ifdef TMFL_OS_WINDOWS
++typedef HANDLE tmdlHdmiTxIWSemHandle_t;
++#else
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++typedef unsigned long tmdlHdmiTxIWSemHandle_t;
++#else
++typedef UInt8 tmdlHdmiTxIWSemHandle_t;
++#endif
++#endif
++
++/**
++ * \brief Enum listing all available devices for enable/disable interrupts
++ */
++typedef enum
++{
++ TMDL_HDMI_IW_RX_1,
++ TMDL_HDMI_IW_RX_2,
++ TMDL_HDMI_IW_TX_1,
++ TMDL_HDMI_IW_TX_2,
++ TMDL_HDMI_IW_CEC_1,
++ TMDL_HDMI_IW_CEC_2
++} tmdlHdmiIWDeviceInterrupt_t;
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/******************************************************************************
++ \brief This function creates a task and allocates all the necessary
++ resources. Note that creating a task do not start it automatically,
++ an explicit call to tmdlHdmiTxIWTaskStart must be made.
++
++ \param pFunc Pointer to the function that will be executed in the task context.
++ \param Priority Priority of the task. The minimum priority is 0, the maximum is 255.
++ \param StackSize Size of the stack to allocate for this task.
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskCreate(tmdlHdmiTxIWFuncPtr_t pFunc,UInt8 priority, UInt16 stackSize, tmdlHdmiTxIWTaskHandle_t *pHandle);
++
++/******************************************************************************
++ \brief This function destroys an existing task and frees resources used by it.
++
++ \param Handle Handle of the task to be destroyed, as returned by tmdlHdmiTxIWTaskCreate.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskDestroy(tmdlHdmiTxIWTaskHandle_t handle);
++
++/******************************************************************************
++ \brief This function start an existing task.
++
++ \param Handle Handle of the task to be started.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_ALREADY_STARTED: the function is already started
++ - TMDL_ERR_DLHDMITX_NOT_STARTED: the function is not started
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWTaskStart(tmdlHdmiTxIWTaskHandle_t handle);
++
++/******************************************************************************
++ \brief This function blocks the current task for the specified amount time. This is a passive wait.
++
++ \param Duration Duration of the task blocking in milliseconds.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWWait(UInt16 duration);
++
++/******************************************************************************
++ \brief This function creates a message queue.
++
++ \param QueueSize Maximum number of messages in the message queue.
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueCreate(UInt8 queueSize, tmdlHdmiTxIWQueueHandle_t *pHandle);
++
++/******************************************************************************
++ \brief This function destroys an existing message queue.
++
++ \param Handle Handle of the queue to be destroyed.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueDestroy(tmdlHdmiTxIWQueueHandle_t handle);
++
++/******************************************************************************
++ \brief This function sends a message into the specified message queue.
++
++ \param Handle Handle of the queue that will receive the message.
++ \param Message Message to be sent.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_FULL: the queue is full
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueSend(tmdlHdmiTxIWQueueHandle_t handle, UInt8 message);
++
++/******************************************************************************
++ \brief This function reads a message from the specified message queue.
++
++ \param Handle Handle of the queue from which to read the message.
++ \param pMessage Pointer to the message buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWQueueReceive(tmdlHdmiTxIWQueueHandle_t handle, UInt8 *pMessage);
++
++/******************************************************************************
++ \brief This function creates a semaphore.
++
++ \param pHandle Pointer to the handle buffer.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreCreate(tmdlHdmiTxIWSemHandle_t *pHandle);
++
++/******************************************************************************
++ \brief This function destroys an existing semaphore.
++
++ \param Handle Handle of the semaphore to be destroyed.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreDestroy(tmdlHdmiTxIWSemHandle_t handle);
++
++/******************************************************************************
++ \brief This function acquires the specified semaphore.
++
++ \param Handle Handle of the semaphore to be acquired.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreP(tmdlHdmiTxIWSemHandle_t handle);
++
++/******************************************************************************
++ \brief This function releases the specified semaphore.
++
++ \param Handle Handle of the semaphore to be released.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxIWSemaphoreV(tmdlHdmiTxIWSemHandle_t handle);
++
++/******************************************************************************
++ \brief This function disables the interrupts for a specific device.
++
++ \param
++
++ \return The call result:
++ - TM_OK: the call was successful
++
++******************************************************************************/
++void tmdlHdmiTxIWDisableInterrupts(tmdlHdmiIWDeviceInterrupt_t device);
++
++/******************************************************************************
++ \brief This function enables the interrupts for a specific device.
++
++ \param
++
++ \return The call result:
++ - TM_OK: the call was successful
++
++******************************************************************************/
++void tmdlHdmiTxIWEnableInterrupts(tmdlHdmiIWDeviceInterrupt_t device);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITX_IW_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h
+new file mode 100755
+index 0000000..1a672aa
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/cfg/tmdlHdmiTx_cfg.h
+@@ -0,0 +1,298 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_cfg.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 08/08/07 11:00 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmbslHdmiTx_cfg.h $
++ *
++ * ***************** Version 1 *****************
++ * User: J. Lamotte Date: 08/08/07 Time: 11:00
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++/*****************************************************************************/
++/*****************************************************************************/
++/* THIS FILE MUST NOT BE MODIFIED BY CUSTOMER */
++/* Customer specific configuration is set in tmdlHdmiTx_cfg.c file */
++/*****************************************************************************/
++/*****************************************************************************/
++
++#ifndef TMDLHDMITX_CFG_H
++#define TMDLHDMITX_CFG_H
++
++#include "tmNxTypes.h"
++#include "tmbslHdmiTx_types.h"
++#include "tmdlHdmiTx_Types.h"
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++/**
++ * \brief Video signals that can be input to video ports in RGB/YUV 4:4:4 mode
++ */
++typedef enum
++{
++ TMDL_HDMITX_VID444_GY_4_TO_7 = 0x00, /**< Video signal G/Y, bits 4 to 7 */
++ TMDL_HDMITX_VID444_GY_0_TO_3 = 0x01, /**< Video signal G/Y, bits 0 to 3 */
++ TMDL_HDMITX_VID444_BU_4_TO_7 = 0x02, /**< Video signal B/U, bits 4 to 7 */
++ TMDL_HDMITX_VID444_BU_0_TO_3 = 0x03, /**< Video signal B/U, bits 0 to 3 */
++ TMDL_HDMITX_VID444_VR_4_TO_7 = 0x04, /**< Video signal V/R, bits 4 to 7 */
++ TMDL_HDMITX_VID444_VR_0_TO_3 = 0x05, /**< Video signal V/R, bits 0 to 3 */
++ TMDL_HDMITX_VID444_GY_7_TO_4 = 0x80, /**< Video signal G/Y, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VID444_GY_3_TO_0 = 0x81, /**< Video signal G/Y, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VID444_BU_7_TO_4 = 0x82, /**< Video signal B/U, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VID444_BU_3_TO_0 = 0x83, /**< Video signal B/U, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VID444_VR_7_TO_4 = 0x84, /**< Video signal V/R, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VID444_VR_3_TO_0 = 0x85, /**< Video signal V/R, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VID444_NOT_CONNECTED = 0x100 /**< No signal connected */
++} tmdlHdmiTxCfgVideoSignal444;
++
++/**
++ * \brief Video signals that can be input to video ports in semi-planar YUV 4:2:2 mode
++ */
++typedef enum
++{
++ TMDL_HDMITX_VID422_Y_8_TO_11 = 0x00, /**< Video signal G/Y, bits 8 to 11 */
++ TMDL_HDMITX_VID422_Y_4_TO_7 = 0x01, /**< Video signal G/Y, bits 4 to 7 */
++ TMDL_HDMITX_VID422_Y_0_TO_3 = 0x02, /**< Video signal G/Y, bits 0 to 3 */
++ TMDL_HDMITX_VID422_UV_8_TO_11 = 0x03, /**< Video signal B/U, bits 8 to 11 */
++ TMDL_HDMITX_VID422_UV_4_TO_7 = 0x04, /**< Video signal B/U, bits 4 to 7 */
++ TMDL_HDMITX_VID422_UV_0_TO_3 = 0x05, /**< Video signal B/U, bits 0 to 3 */
++ TMDL_HDMITX_VID422_Y_11_TO_8 = 0x80, /**< Video signal G/Y, bits 11 to 8 (mirrored) */
++ TMDL_HDMITX_VID422_Y_7_TO_4 = 0x81, /**< Video signal G/Y, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VID422_Y_3_TO_0 = 0x82, /**< Video signal G/Y, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VID422_UV_11_TO_8 = 0x83, /**< Video signal B/U, bits 11 to 8 (mirrored) */
++ TMDL_HDMITX_VID422_UV_7_TO_4 = 0x84, /**< Video signal B/U, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VID422_UV_3_TO_0 = 0x85, /**< Video signal B/U, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VID422_NOT_CONNECTED = 0x100 /**< No signal connected */
++} tmdlHdmiTxCfgVideoSignal422;
++
++/**
++ * \brief Video signals that can be input to video ports in semi-planar CCIR 656 mode
++ */
++typedef enum
++{
++ TMDL_HDMITX_VIDCCIR_8_TO_11 = 0x00, /**< Video signal CCIR, bits 8 to 11 */
++ TMDL_HDMITX_VIDCCIR_4_TO_7 = 0x01, /**< Video signal CCIR, bits 4 to 7 */
++ TMDL_HDMITX_VIDCCIR_0_TO_3 = 0x02, /**< Video signal CCIR, bits 0 to 3 */
++ TMDL_HDMITX_VIDCCIR_11_TO_8 = 0x80, /**< Video signal CCIR, bits 11 to 8 (mirrored) */
++ TMDL_HDMITX_VIDCCIR_7_TO_4 = 0x81, /**< Video signal CCIR, bits 7 to 4 (mirrored) */
++ TMDL_HDMITX_VIDCCIR_3_TO_0 = 0x82, /**< Video signal CCIR, bits 3 to 0 (mirrored) */
++ TMDL_HDMITX_VIDCCIR_NOT_CONNECTED = 0x100 /**< No signal connected */
++} tmdlHdmiTxCfgVideoSignalCCIR656;
++
++#ifdef TMFL_RGB_DDR_12BITS
++/**
++ * \brief Video signals that can be input to video ports in semi-planar CCIR 656 mode
++ */
++typedef enum
++{
++ TMDL_HDMITX_VID_B_0_3_G_4_7 = 0x00, /**< Video signal blue 0 to 3 then green 4 to 7 */
++ TMDL_HDMITX_VID_B_4_7_R_0_3 = 0x01, /**< Video signal blue 4 to 7 then red 0 to 3 */
++ TMDL_HDMITX_VID_G_0_3_R_4_7 = 0x02, /**< Video signal green 0 to 3 then red 4 to 7 */
++ TMDL_HDMITX_VID_DDR_NOT_CONNECTED = 0x100 /**< No signal connected */
++} tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits;
++
++/**
++ * \brief Video signals can be mux each others using register 0x27 (MUX_VP_MIX_OUT)
++ * Whatch out that VIP output shall be GBR: green on [23:16], blue on [15:8] and red in [7:0]
++ * this is done by default for all video mode but RGB_DDR_12bits where some extra mux is needed
++ */
++typedef enum
++{
++ VIP_MUX_R_B = 0x00, /**< internal vp_r = vp blue */
++ VIP_MUX_R_G = 0x10, /**< internal vp_r = vp green */
++ VIP_MUX_R_R = 0x20, /**< internal vp_r = vp red */
++ VIP_MUX_G_B = 0x00, /**< internal vp_g = vp blue */
++ VIP_MUX_G_G = 0x04, /**< internal vp_g = vp green */
++ VIP_MUX_G_R = 0x08, /**< internal vp_g = vp red */
++ VIP_MUX_B_B = 0x00, /**< internal vp_b = vp blue */
++ VIP_MUX_B_G = 0x01, /**< internal vp_b = vp green */
++ VIP_MUX_B_R = 0x02, /**< internal vp_b = vp red */
++} tmdlHdmiTxCfgVideoSignal_VIP_OUTPUT_MUX;
++#endif
++
++/* Audio port configuration, bitn = 1 to enable port n, = 0 to disable port n */
++#define ENABLE_ALL_AUDIO_PORT 0xFF
++/* Audio clock port configuration */
++#define ENABLE_AUDIO_CLOCK_PORT 1
++#define DISABLE_AUDIO_CLOCK_PORT 0
++/* Audio port configuration, bitn = 1 to pulldown port n*/
++#define DISABLE_ALL_AUDIO_PORT_PULLDOWN 0x00
++/* Audio clock port pulldown configuration */
++#define ENABLE_AUDIO_CLOCK_PORT_PULLDOWN 1
++#define DISABLE_AUDIO_CLOCK_PORT_PULLDOWN 0
++
++/**
++ * \brief Structure defining a video mode
++ */
++typedef struct _tmdlHdmiTxCfgResolution_t {
++ tmdlHdmiTxVidFmt_t resolutionID;
++ UInt16 width;
++ UInt16 height;
++ Bool interlaced;
++ tmdlHdmiTxVfreq_t vfrequency;
++ tmdlHdmiTxPictAspectRatio_t aspectRatio;
++} tmdlHdmiTxCfgResolution_t, *ptmdlHdmiTxCfgResolution_t;
++
++/**
++ * \brief Structure gathering all configuration parameters
++ */
++typedef struct
++{
++ UInt8 commandTaskPriority;
++ UInt8 commandTaskStackSize;
++ UInt8 commandTaskQueueSize;
++ UInt8 hdcpTaskPriority;
++ UInt8 hdcpTaskStackSize;
++ UInt8 i2cAddress;
++ ptmbslHdmiTxSysFunc_t i2cReadFunction;
++ ptmbslHdmiTxSysFunc_t i2cWriteFunction;
++ ptmdlHdmiTxCfgResolution_t pResolutionInfo;
++ UInt8 *pMirrorTableCCIR656;
++ UInt8 *pSwapTableCCIR656;
++ UInt8 *pEnableVideoPortCCIR656;
++ UInt8 *pGroundVideoPortCCIR656;
++ UInt8 *pMirrorTableYUV422;
++ UInt8 *pSwapTableYUV422;
++ UInt8 *pEnableVideoPortYUV422;
++ UInt8 *pGroundVideoPortYUV422;
++ UInt8 *pMirrorTableYUV444;
++ UInt8 *pSwapTableYUV444;
++ UInt8 *pEnableVideoPortYUV444;
++ UInt8 *pGroundVideoPortYUV444;
++ UInt8 *pMirrorTableRGB444;
++ UInt8 *pSwapTableRGB444;
++ UInt8 *pEnableVideoPortRGB444;
++ UInt8 *pGroundVideoPortRGB444;
++#ifdef TMFL_RGB_DDR_12BITS
++ UInt8 *pMirrorTableRGB_DDR_12bits;
++ UInt8 *pSwapTableRGB_DDR_12bits;
++ UInt8 *pNoMux;
++ UInt8 *pMux_RGB_DDR_12bits;
++ UInt8 *pEnableVideoPortRGB_DDR_12bits;
++ UInt8 *pGroundVideoPortRGB_DDR_12bits;
++#endif
++ UInt8 *pEnableAudioPortSPDIF;
++ UInt8 *pGroundAudioPortSPDIF;
++ UInt8 *pEnableAudioClockPortSPDIF;
++ UInt8 *pGroundAudioClockPortSPDIF;
++ UInt8 *pEnableAudioPortI2S;
++ UInt8 *pGroundAudioPortI2S;
++ UInt8 *pEnableAudioPortI2S8C;
++ UInt8 *pGroundAudioPortI2S8C;
++ UInt8 *pEnableAudioClockPortI2S;
++ UInt8 *pGroundAudioClockPortI2S;
++ UInt8 *pEnableAudioPortOBA;
++ UInt8 *pGroundAudioPortOBA;
++ UInt8 *pEnableAudioClockPortOBA;
++ UInt8 *pGroundAudioClockPortOBA;
++ UInt8 *pEnableAudioPortDST;
++ UInt8 *pGroundAudioPortDST;
++ UInt8 *pEnableAudioClockPortDST;
++ UInt8 *pGroundAudioClockPortDST;
++ UInt8 *pEnableAudioPortHBR;
++ UInt8 *pGroundAudioPortHBR;
++ UInt8 *pEnableAudioClockPortHBR;
++ UInt8 *pGroundAudioClockPortHBR;
++ UInt16 keySeed;
++ tmdlHdmiTxTestPattern_t pattern;
++ UInt8 dataEnableSignalAvailable; /* 0 DE is NOT available, 1 DE is there */
++} tmdlHdmiTxDriverConfigTable_t;
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++/* Number of HW units supported by SW driver */
++#define MAX_UNITS 1
++
++#ifdef TMFL_OS_WINDOWS /* OS Windows */
++extern tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6];
++extern tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6];
++extern tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6];
++extern tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6];
++#ifdef TMFL_RGB_DDR_12BITS
++extern tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6];
++extern UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS];
++extern UInt8 VideoPortNoMux[MAX_UNITS];
++#endif
++#else /* TMFL_OS_WINDOWS */
++extern const tmdlHdmiTxCfgVideoSignalCCIR656 videoPortMapping_CCIR656[MAX_UNITS][6];
++extern const tmdlHdmiTxCfgVideoSignal422 videoPortMapping_YUV422[MAX_UNITS][6];
++extern const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_YUV444[MAX_UNITS][6];
++extern const tmdlHdmiTxCfgVideoSignal444 videoPortMapping_RGB444[MAX_UNITS][6];
++#ifdef TMFL_RGB_DDR_12BITS
++extern const tmdlHdmiTxCfgVideoSignal_RGB_DDR_12bits VideoPortMapping_RGB_DDR_12bits[MAX_UNITS][6];
++extern const UInt8 VideoPortMux_RGB_DDR_12bits[MAX_UNITS];
++extern const UInt8 VideoPortNoMux[MAX_UNITS];
++#endif
++#endif /* TMFL_OS_WINDOWS */
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++extern tmdlHdmiTxDriverConfigTable_t driverConfigTableTx[MAX_UNITS];
++
++
++/*============================================================================*/
++/* FUNCTIONS DECLARATIONS */
++/*============================================================================*/
++#ifdef TMFL_CEC_AVAILABLE
++
++#include "tmdlHdmiCEC_Types.h"
++
++typedef struct
++{
++ UInt8 commandTaskPriority;
++ UInt8 commandTaskStackSize;
++ UInt8 commandTaskQueueSize;
++ UInt8 i2cAddress;
++ ptmdlHdmiCecSysFunc_t i2cReadFunction;
++ ptmdlHdmiCecSysFunc_t i2cWriteFunction;
++ tmdlHdmiCecCapabilities_t *pCapabilitiesList;
++} tmdlHdmiCecDriverConfigTable_t;
++
++tmErrorCode_t tmdlHdmiCecCfgGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiCecDriverConfigTable_t *pConfig
++);
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITX_CFG_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip b/drivers/video/nxp/comps/tmdlHdmiTx/docs/02_sw_req_an/tmdlHdmiTx_API.zip
+new file mode 100755
+index 0000000000000000000000000000000000000000..e4eebeb934798ab9e68af4b1e52f105e10827bb9
+GIT binary patch
+literal 131083
+zcmeFZQ<P=VvNpKWwr$(CZL2b~(zb2es<ds}R;6tlmFzmFyT`r%{m<#{mwr2YjEEU?
+zKg5`0tymH9MZ{W)G9aMPfPef*Ww?3&Dg0jy0e}W@w)tr-`P0Ti)!jfyQHnuL6$$`y
+zP@*sM4^ndn1$beg0u=vhKm`B;AOR$QHNeU#tmZ-j0OBM70N($u;lC8p|Fm=er@sBa
+zy8c1`x4vO51E)exWWSeEMU#8`R<*RBW@ZM;DG*pc3*iXmAxF16sL_m*f_ZRs!4(?b
+z&uYmG5m%EkA<PoPWJ3*PET6t@eS~fQysa4b%*@ql7}W5`iRXQ}^yJM`pk7UUn@(b1
+zHMnS-(KOLUjec14%3O5ODz>YAtDf+o%5T*)HciYq8Y~}?fAfeSnfW0~j3GjR77tgv
+z$AcOV%yTm|KyOtv^DXE-r(aR4rj_}Ieojoc&^8o^3x>`4b_Vij8ALfJ^^<qwb>#6l
+zE7_@A*)@+3S2jcMg%?C^&xe+O?M-($mVWQonx|Ah*sWbNfc8=&79Lxq*-Y4B1?DLI
+zDO*`)FmdXBtPG_6nqtE9OZ#RF8*>o$(U^gZqk{S7!j91-E)bPWbJQGrEzomhbL8v~
+z9OJ|S!Pe;vxvZNS-DB-nSuiYe*FIT(pp1y{{*^z8ZzLrg*3O!383-03VJtr`3NGqE
+zrH9NDwhVnp8t7D9at5Up;LdyeQyk5J9mrhJUzEN%H}#^af_~0V{M1VT{Z6LGbK;z!
+zSpDmf+(y4U#MbSo)jOqIO2wwp<SV^b4s=Gn)Z>nPnttQD0s8V*uHsRy&K(8}2iNc$
+zh{0$szi)}6COTqq9TLt58(B&u&Yl{e3T;;>wg1jMFtFHz`eIFko-OV;p!JK2drI8=
+zw5d#(cSOvu*0opQ7PfOLffH$p89N3nf}zZGF@jj?V5EZ8lpalnQM|w4D|fn>^b!YQ
+z)~S5oDce6ro=b*UY-u}2G@a(cCRzaaBmzfvw?6tT?<e6g&m-87tixunwvz)o6m}o+
+zn)_j}!x?Uu2_&^tQ#Psbbk5ymKvoWyM)b=c&nFfZund@3B1EGdfu2pEXwIAfYWbl0
+zzCdoDVSL6suGO^IxPw*7S$*?9f5^CYh-uFyGG?e0B<$|d-x27mwrda+Ka%ok@X$qJ
+zA-y^m6k{_w>tO5a6@=U&qaWc^jp5UgIV~Z3ZNlo|qw&z;giM(6y%b|lC?ctD-Le*c
+zZ%|xn9@gK_h;-d>HV7smTiZ@2VC!h&YQdC}lCEcfI%Oc}o6%h|B1hdA9{gMv0+}L1
+zDiVF2R3jDtCc@_sk{5itv}J<6#kG|O1C#hfxh@mUUw+((Nx&`=SwYrva|6RqWWYNW
+zo+of@)~1z}4||xo%%k9Ic+#L$(O=L@z)<Mu3nYC8jVKnzc}?LrF>~GWqeu=v_*sZ{
+z>+b=1N6kNw+=NPbHq@q!jCc!pfmGEO=QR5;HyJB}o(_Qe-A$sV2v>JX;Negn8L%Ov
+z7O+(?$?a9m0NXrUBJK3a`Ps-;0zK5VdTpiGn5`wj8f@(-EitRr5tzBGNnd1!7VNoq
+zl2&O(d7BMt?I|vAkuc@r&XsV6Ejkhf*u3DsmM{&1i(RU;N5nGi+ViDbFnExGf#YOL
+zVDnGr+myE}D>nLL5teQz0elvpPPSQZRKb5{mL;op?KTPPvz5Yt#`*3sYiG-OJcszG
+zjY8vwnJH9iXvuF*7%uHUQOyJ8z)XbO0TW&wPr`XuA3145Fz@dW)<hw!iZ@s)=n2{x
+z{1SaeqRXadm$z7}mBX;uZ1JPdOJnWABctE<aE~cq0Gt}cd}eI30va>9Ls8B=6TVBN
+zH|~`6C$2R<sq_f}{xUDpYuV-s;>L`ZZ`Rur6bOpiPA0P_;{Eyb`Y-NNAuPxgH7hF(
+zJZsu3)vl&+^5_Vnd1I~Ld<B}cg!1l1lSy?bk1raN70jrLp|XQ0&89bz_;)0ow2#1C
+zV>&UZe6#Z=SN$Q}MO(9Xr;J*07U6$@Em=-D6JSz8PmtiZjA7R))J(OWEr$OvLLI`s
+zLvgw+EosR`Eund5$77KpJUdKN{1McnvE9j^?cMPXhkGv{JHD|RLcF8BvtT+^7!~&p
+zL$#}gy9BlM>v8c1@m6S(e<O7>Px@kD>6dn)?0`7Wv4M}PQ%=_u{rT(uaZ;vdLiQV!
+zYN4Hj&cW<wXf4SL5UC@@LJ(fN9wO^WIS}eDh`P0qATS`yjGilitvf{~r)B)luc^M_
+zLmxOXJjQqgZ*HUuz{YZ1b>jO)N63y!_&~?lawxW9q40Ve*2b6wq<0d!IgHQryEI?l
+zo}&BhS<_Mg3EZ=z3{UB&oUu=UU)A``4v*06)ra*pmq11?kXJ}mdEe@tq<>hs98rzE
+zLK6;j1ZS48Oc^*JjA^ZNYE)k4seaSKVc$njz7e>6%~<~s+)LxGLWt@^qQg`5&CnFp
+zq?2tux$^TZ$46<HW(=g;+Jrx6<|iEZQypTIP>wr5ttH#gmojsfU^1HkX-}OGIC-+F
+zqAztW!-MgF(M9AIWh|-wa|q=}7>mlm8dBxiZ?z)|ty6|2%hrrB4iLvFyc<T7=rA9n
+zjbpFD?anM|ZJ(A3q(>k{ijGkbuxW7hSq$_5Pq{XYSy-vEQEz1fGGB(Bo3p!TcD?F*
+z5;fD>IRNS$)_K@q6(A&6FAG?~>tP&4%vWTAX!S)+UODKvP$M4X$F|_UF#}g_KES=Z
+z)^)|;Vc!#G=9`GVk=p9DQ8!Po&$Ep|FH%i9BJ9fK1=1c<-5LF44=aHlg<>?<RA-gt
+zUfzG|<u2W!+fZVOHR#Pj+Algzojm@_d*oUn#t;mO*dQ$yz4B@>$YBUbgztNK5j*PF
+z9$MAeEB>^qzRzzJn7BYX;b2W?n2pwpFUv()W}@k#8jitkk&S(+pi%L%+)2Dswt<XC
+zO~IPl)ZHYD9DRYSg{z0w54-k>=9r2n?(N6i(Phs%A~qMb;5Q3FydsYa>^Yvti|G>v
+zkR=l5^N5>#`iPEZ4vtKp(~JSmf$ZS@)9p7Kl<ZW6h;RiyhgZ-q=XYvl7`(h)#)$1t
+zty>A<JjZcr8MjHZWHbejgq$q~xe=nhr72`jqYr`qHQPxIsOB>Jn=b|bCG7t_+c7sW
+z{AuDyZ|-bk{V!7;vKS%wK|)y2o34QdN1H$Xdkhw<(Ar6&yCQ#lvK-eFT#FK{)e1=x
+zquKOsMQBRGC;d*vC)Z*z*f&<7?;f%XQa|O|_pmriwXbz<WZ|&eHWVLWF_U6Y0^kT9
+z(hzfAv64m;#GMWP*E754A8)MuJ?}4|e|ct8J3Ht9r!)H~PRb85B6gk7sH5W&oo&se
+zsP8LAAPCC4I-vhis)kd0e~QVf2#0i7-^!SuF$Vx1N#p;>irb)S&eCJEDbtcx*!_Zz
+z#N(}|<YZ1Ax9+%hP@<Fm!-Wp;1JRfxhCb?IU*yufd8Y#pwM(3$8W<E>pok&!4G93v
+z-3=j*pbJ*i%5EJ9Fx{_d3UKc1TDY3FOsUWtedD2kfY1^z)b)NDFE$$`Xf7~X^6m86
+zy4tx8f$A)$#7rcNP|68Rk2OO0#+qHJuJNcudx^0P3ohj@MfTp&{U2GZvO)wH0yqHB
+z_?Q00eKoT+u(mU^qc^iK{g?N3I_XXWB@Ad(1e-A;mE2*-pLH0O3`|;N0&&X}EK!h>
+zE;z6nwN)sAx@R>0q%oEn21z-FRw3voyD+#ANN%Rabu&lzG%x2xzS)k2-L+|LSLLP?
+z#rCmFcl$-xNoVXQ#{0+DXV1-h*Gsiy=LCC;Co1_c$lt3|{3LqWO^60Qjc7?x28X;R
+z(x``-e~4nyEyyc%H(n=ZdVt&@bc~E#wM9@r%A_tV;}wuj*q0!=gdmPADJa|;j!b2U
+z=2K6MFAK5nKP8Gti5L_ExsCCh#@r>T_(yO75jtf5&K>xKG(u#TFu25+mCT6{k#-*x
+zYKSSY;ROh?9~x0!iWwo0P^uG?P_M+3NqI6#nLsiu2{zP_86tsI)XB)MDcq39M2b)f
+zSxgBtP>L5RYDAG)NGX|e9C<AwNgPS_-aC6pDANLF02Y0Ez#-cZGt~qMG$C9*<9;tW
+z<mfHXpA5Zjvf(t$JVPRJoHVd>kCkQ;c~Yi9(g`<=0t9(ma2FJFA`V=dY?W|P2%51_
+zNrpJ#2Ui~Hd;_f@;-Lbmm=dYc$QUyv&a>UK5bLxnWMJO|uiWC7d(Twiyg4daGA3P}
+zZu~D=&I~b!0#GVL%wsS@z#=mWF=QYy^8GzLWehPDX+%8ec#s8PrXI=$(~vYG1*{9B
+z$fN-#|24c<HI>s)3uq1N&Mq~cSnDTQmsW7HqC3b8<btEWVPOJgw50>H9=R8(RII;N
+zL=lkK9O4fl2a})e=<=hC*$3{KSHXLvu_%-4`wsr3R8Z{5pin|}Q^0}oq()jm=?NLP
+z2;VQL)Tw`VFi<VE>RV_VtKL^fZJ#V<3~6nCDQnDWt=d;~S}aqmI1oZ`32+hU0;Ms<
+zX0ULCE??hYrCrHkgc?uHmCM!Zh^Qs0|19^;c}W%ijx9I3DDCXYF4MVB-DyjDPptH9
+z$S*0(uP-}`cQ$jrD^@*0H>u_2=JfLRsya~L{4-nbWPrdrO1<6Y8qA5CX{jmDQ$Ahm
+zPPg&{U7A|OwvxtSvbeEC0v}C!u$S&N$5-Maefd=0rRUFx#gRgub@$i4qJB<q-q?=H
+z{pqvW*Joa=_k7!z%S8{APTb0Jg$6<l!N=>~$S8knzQ)UOq188L3%K!eFM|5}PGwUm
+zicW4aKyT4L*L%f>Q1HjvO^Lj~i|lmLmd29+!JjM!){k6jw9jSn7Y#q_axI-#<JPYR
+z%Mhol*LDaAfv&S9HFw|^@}F@#>#of=7Aj$`pStafdTmCs?TUq5ZEeR_r~Z>mTJ8Qn
+z@fu85eGj3^;$&3?!+KVJ?l_hBCZAoZFAmqP$1?JT<h{1SANn-ANkls3uRj2Jw@hbo
+z9aL)<da6I!hb?G1pKV8gq`_OujNio8C(P?La=dUpx5($>`tm-xY~OBSJqGz`pr>r*
+z;zU`&E96vPujqcP4Jp(9K$Ev&==8aMU7gF5=T}5a{odFSaPH;5jRJN$W=|<7I*2VD
+z<a9rbKHmJSN7Z7fKmDBM81C_+DEQ96Ih*IUjyxVRaq!gJTHv+cZsb$UbNj>3W9sWR
+z5UgF-O){NN^&oHSGD5N5Do~LJ;@knPp|ZhV+4f|4Ju$y9!R_->WpRw@;k&+|%rpNT
+z7WH1L5R~~eE83~veDm>OD>9Q4aMB|;p3b-F$Z^s+o8va>qpiwWvhinn{$Z4bg9rTV
+zMF(7knkE*__dB&>%K^{pYoL5qjVm+kxe#mpH$$b9m6gxT=2lB@*Ie0{mFm%~UVU|_
+z!IOHnqMY5tb5FLmRhzAE^-#f#1Kkw2J`;EN1=jL!qn8fL#i?mn_x`B#*0sn*bvx@k
+z&4^wyK1%+p%^iKetIuNkN$Hcrz6jH0^lmwo+qFRXLYJ6}9(VriMedi&UlaU!R<=~R
+zD<5xXZDqX+`j?(}(omlromabjuQwnE@0PIF*0W)uIfZmYTkh9x8gPv?rW4U5Yo9Y|
+zR%$){(G{uPu~pO(v%QZA9g5mBAuONeBT<%lj#uFp@M9lG<934?#hv%A7+oyur(@%p
+zen(-Yao=x&@^?w!!2fIfZ6%RO)dm9q$Z!DwjDL|c{4KZ88#_7u%fNDlrK51c{+jUx
+zEn{v+CA~0tc2us&Sw0j{agos^!QrqTuG>MH%sk|`V>T*pG<p_blesDm8|drir@_<R
+zmG^DQnYy<cy2z5<vj+=nW=<PZdC~dwG@&^g(`@YB%XWO*_zKqTJo7<1)5#wjc<T|^
+zlbDWM7hr1PF9O0v${WvX50tpad0|Ql_hE6;>?HM6b<!6X874IzxHAqKGo42nVXSn<
+z#dWNQ3%=nVsEd3;nq#S1MRZc%j7*nR=;hg@^{du&@@fAIz8iIn0@>Q_52#JzoJcL+
+z>h-Xl&}9Ni^99xIea;WQjUO+DS>$o`D=tZlQWU4zeFyKTX+`)z;mraCv``=jId-xg
+zC2w0fVw_vxfVvln*QU{2j3J#nCRn3|Er-b}Uqendx{<IrOO05LlpTe1Qp$C>15}Dc
+zVP@q(7ZuyhU!jR^ck5cSIN&SDM>6%*S}71NLA?9qR5L-KOQTY<hoaSHDiKKdb*4U6
+zytR|LxPi1|5if2RWtFRB5Q(W`zfr4Y2oUghYIV*xbCL7wWhh)B<1T>Z0p8D)7UyJf
+zS@FLf>iO_>*BX%gEIFzz$;M46wT=AO$w;&q3mm0Z>7`cODMuq;>1-@q_sH=x1V8z@
+zl&rIhkl<++W!-IUrKJQmuXut3)&?5f9M#mjVw8fv@rdqiG+9X>Hi*f)6oQ8!<n$(E
+z0B(Dw?l?kmO4xyz?i~FI?%<J$oa4`{WF2R$_;oGyx_T?cXV|xBUXShP2&dHV_8bb&
+zC`)G3X(H@WxfBV&w64Z0LS0C)=RVnsaAcSi$$zmIFew%NI{$WnNLJ@+FkqpmU7J#+
+z=&~H5K*{F>AXsG}k*mJ=M~>iku{y?yPRS5LEQJILM#1w!zEqmIomjHOu>FrjV_c+*
+zEmO4x8_nVj)m4Mk;aM<|#iCeRBhlh3yg<I+97l#)ML}%Vu}a52GAssSW#_z^&jyR#
+zq1tK}vE_%$NdjTJtAt@nH}WYY#MJN!Rq@iZvU7{@>*C9EQQj&nJM3&|MyV8l-!BAX
+zjkKK}feX{@<<5u&6im&YWd_MAsEt4tV=#Hd#r|Au{?p=m9R0e*)WK2o{S@m;M=2oi
+z1mjsB#1J>Vf8&yvXaVEctN$FEZBh+Y0m<$_7|=83zDEm2qcs1hur@=FPs%vy9C1k@
+zv?*S<dPpD-G%o{b^83lr<u!2P3slvy*sC&58VP1PwAxn}1@iLTrO2#e*$1OXVp%xp
+zq#QB(ifT-9Nx^#Q&pdMa@dnbA@=&%Itz6-75z0f<u*4_!Q(CrbdusC~K4xn394pz`
+zs5dPh?1kdI=7K90BAV4#nX3U1rzA5Hk))~aVvCoBHWdII$u))_+kvnFHFuDybISNw
+z7UNiPDUP$R&4OC~uv%$~;N!U~^ma^^yTf22Z=Dg^bFT|f1UgrQJGN?uu$J5xPen7P
+zgKvfF0@}+nceagC6qWT#LD{@E=rXZ)xr;hYs+E-pON@<VMG8dPa!y6k!4R69a@jDG
+z4fL^S11o|#u{N>Ek$nvR;M3heGx<FKM^zm`sI2Q}Soo@0%4el;%Mev;!z}XqXs6Kz
+zOsLxk6A7n_Ta1cdEeC!Yx4ho8-L=L}a6CqcQ2TLKvsKSA9FPDG-F52DO0npf3AYao
+z`GZXDlej5JwHI31LUvnvgOxS@(CmI<f%e0CKkE}%9$#H;Z!~7xGk1^Z%W(@EHe;)o
+z&_oYQ8GMh=8V~PvANIZv_}h@59Pt$f!H*6Vi}K!E#a=#(xavmW-}f|`3;g-bsbS|(
+zos6NqG9FhSK>zU3|GEzTuYB}Bah=n@uZRC@O{o9E+y8}z|6a}iSyul?VLn3@kB}G&
+z0ATz}1ph|O--5b_nTajEy{*|lgUA0Y)W@i6sG@`;!%1=wDvJsuvHOQ+iYE|vlVXYq
+z!%&jtV-hV<imfV&awPv+B7`RX5#(P`Aelf+jI0fc1QNc~7f37aIX=jDbMx87Vs@O{
+z?sT0qi&e3R<>kN>j|l)EN^q@m-WZ?yo=4r@Xms17`Va(<&6w2zwr?086(wJ%ck!-l
+zzD&qBa60Az{*b^X#%IV6F5@JeL&Iv0A9{$&fbz4z*ifNc_HzVpm(+7@ww869B_Y+H
+z!+ivH`4!$KODRPiXnXnhIa%1QqUd8S!q2+jRIMl&O^dHJ_1qWGHU87{>L=GZM^%}G
+z$JgogB83Lk1rXw$B_Oqr*u*`<9J<|a(izo$K@qQ{b!PlgxuwSTr;Y1k58TTIVojT*
+zQE5P(H|7TS4N@aB>Z#TdX1g?KUrJ~{k3GVX2k^GWr;Pi*Hux#HV^x#m=nFexrwGG(
+zmeyj;t}mPuhkl^K&CaG?s_?NQjQ$x=>gva{@z{1S${K<;dG#@iUV?1*ek&Xv>bGT5
+z;1~)47_?|@X>wE(#!{Sjn&vDmcp*WaB6%?IoSogv%zNEK33D$?S!9M^cA8oA2SRTI
+z_QyWhwvHN{JSo<5&1f;C=5`pK!-!QAMQr9x1a3>0=TzgTw+sutM>R$F1hUfIu`;*7
+zc4aR{#-={f$=hXc3KxQ9SG&sfS6W|pFs&DDkv8=t8*mqD0WFpuiF?-PVzFCE<s`*H
+zJZi>1Z+bI!IdK~vbguY!OC8fJ|9(($dr;Y)<i|3nOB2z`7vg!EhOR<x4{!V$yhp~_
+z7R42p^bkG}Oo2ikjNsU=Fz#&os94`$HT5chvO5(611lIUC?&PUrB<cE_3O4VT2jay
+zIZF1F-w`p1$ekIE;_`~UlJz4p)yoBqXq%c!mvi)bdwZ*D^7F-wROWywD$Wg6moZ^=
+zETZVAS%1rm058rx`O;>`S`0x*u`nE{_>wGZO3>q*0;utqbS))c)Wc?(*?b>%B+-x%
+z;3CYRK2L(oi0~dNWk$8Tg@e7^bROr`8*e%YQUs#Pk8@nIR(+ldpz7@SJX~%6-f5f~
+z;LQyK@1iG$%XUq@wz|Cr8NHHB3={^0$SKgnsm3r;H>Vkr{vyjPf~IIUjwZIBI+P9v
+zXM4-oX{hVBRK&gIa<6)ABz7Dx_-xa(c9j3J>H3h}l=b+tKTzoT`r{{nf>M~u`Ad1)
+zl9qjB-LZ}m%RQRm$h=DNw}0WQ%e?(N{@ebO0%3F6mWZa|^dROe$K|ebJ@U_SDJ-6;
+zkHY*{OG3LP<4=1Y4+bl5kJm9O%f~Am^;7+84d2csjO*B=%~F&?9F=E@IGWY@Ukt&R
+zi_<G5QC#4Gh<tezj(+?HD(oZE_Fe*9BWw=Uu^KZ`q$Ax<_NMZ>(zHI)%9(RbC@{5~
+z?#w(^mW7XF;FQDe>+Z^k;0z!EJmnHhpHja28w4iTS6sZqN!q0gN6x=CHfzVP(Bg>2
+z$@28=pxuY43z@r^)+ab+u$oL<bC+WEcI=}*A(Cic&II`^yWDL0*)qLGv_03jjCD?i
+zu9m1~8b@#%`P>TIFhxua1JSp?OX`?EV=~f`Ufvdv^2^3Bk_~6r#)`k1foum2WVfa=
+z?KUmXjoDi}J}Tp!DHX{3D;lqFwnu0>hq+@~)AOQzh4w#}&{D`{r^ou@;caGL!3W9o
+zND%3e{G0hMJRFBMMbGG@EOOzZX6>rVtM$FOsI#`6Z$|~#@UfV1h*;(lo5^OtLE7eF
+z;3ZMnULv3L=ofgH`SewFCkxUk#LSwkt;k*4XZ$y;LrSj*BA5nhueK)k$+Bp5?=xt?
+zH#E(NhL-V)Lg!j}Jn?5^esy<$$a^~xL{Qd3_j(__2kzIJ6t45qf699HAHWO!+7DKl
+zpfTW7L4(M@)U~`}_|S^{p->brWmwPQD(P2%fB)k5MRm6&!O!Db@J?N=rFrFD>A$2D
+znRTZ#?6~{(i$?MdUG(Dm3bE>2g8vO%h&cGl06Bw8Z$%Sht0P(6QhFd2s<R{Wv@ZFi
+zKU;a+G8q&!F(-|$>4DFO*&=(H`}%|2;ONxIA|Rt<Y-G3;VG^r;fv$g;^QVA%5{#+`
+z4NBTd(_0;3ggc`%dK4?3CGMU>6=kE1W>^#769|2i=f^Rjmq@g)*(S{uOkhWZW{c{U
+zXYr2DtMk15ZUFjsFZG2QJ#bY(O91*8xKsp6Vxc8&@-J*$i2f(iWJXq1xLg|iHbGat
+zHjBHL4yzbM?`w2r|9U>%CL-j4r~^#B&+Ij1*jF=eds1D&D*Z1IDp{Qadqj<$jOL29
+zH1v_CaWc2=bB?RJcYrgqHS(Q)T?#1oB^d}(y9Ps{sgC>sKRE=R*1}Un`DcB`%xV0C
+z><Z2AsaDuf6P&wB(BTrX8@29LZ+Z)*q{j7=!o)k6Nd-1A(g|sDR{~z5a}h-vFuMrc
+zT$vltZV~e6HF`-ewkg5Y*v=CkR(#k3L41u;T!gLXWduAF(!bE4lo`#~l#XB5mX|GM
+z@o;;Dfu>Xa;n~Oe_AM^lNXp=&2wPUF-ebeOrnbuQ24Nc^kPCO{ki<TIRIbF+fHl~~
+zrF%w*mR&z$_V-x6opR?#oF2z%cjsrD9UqY`j5%%MYBO_aR^cuo&-X7Jma=LPG7eB6
+z6qTKi^0ljG;QBwbxW0e(g7Oeta*u>>azu(GC7s#7J!U_i_Ww}wNH4tyWX1v)iKlSo
+z%mxjFMCsAgySg|kHBaW3-oI&t$F8Hf?I<-^nM-#jfIJ~AVJxF%vnltSuzZxDUU_6*
+zeRYYMsu7JLXDw6tM7PaV>a!hj8^4|Lm%Okttw@==iS-#*l%%#iE9>ZGvF5gi6Zdm$
+zrD61(UQ8)=e7_`qeP87&vKZ<wVm{Q{eCOAZZ+OPn8wMPj_l^PlhoKlj#qMFC`(DA2
+zp!%sL_1bFkC&rUJ6-D?cWkV39qKQYf<BbZ(L<4OFlWV?@ZtD~q=!v3Hrx46{S{FZ7
+zVlh$AC3?DUO5<1sU$L;y4(=G!1qS*Mp~G;54M9Z)0p9*dQwR*pvYI;@cyHB?>jp6X
+z{lA#rAnD4`oBCb*Ed4+Q*K+I2Tkhq)5dI6O|0C!6??4^*-{f58{~fLW&xGqgX#GEE
+z{Xb~^KWP0wX#M{WwEkb<_`i4S{v9~}pDnxp>8t<KvincV?msQN|FrD>)3W<d%kF<^
+z+5H0vL=(H<%>5mgfdT~p@c#`Gu(17U;{IQwKL0bm#Hen_Z!#kKoY0h{uD5Qcrb1_m
+zRs{Q3mo*`Gkx=ByRdKsodQFxX?A&pKxvHJ=o0xjXo=go>c?p!gf&RKoi24zKR;;1v
+zccMHP=>`e)DpZEUH1<x{WQrLheg)K1ld5QngqI<GPB5pVt5HSazRo?`S5T4ukR-f9
+z;tB4HU2lZn$`9lJRy1Yw+`wd1FxyEQV6|l4E&((Rnr6!5QkE}?Vc`HSCHyOu^%q%?
+zNM)N7+B;QqA6*vMWj5>5Xs#6%i~b<QR@)s+m-wMJ4gvG*q0BYcrbnm6=STt1ab$Cm
+zk=YyCnmtX9KxEr|b((l*T6--iwS(%md`4(x@8QMi6;fkq%To*edx5V{)6$bGOZ;RI
+zai)?`6%(UE0L|K2<nW}XPp{8wI{gf!llBdIe(Ua`U8Z9{eEmc0UFdp)A84HNYY+AP
+zhmWXOk&mm9;3b5s5IyMh2p&1jR$oemNWd*jb)oPNbQlIV+F%aIoi=dp@mU7+Jo@|D
+zy0NGafeQi@#kfL$km|MkRlmwK5r~-<R>99-vSthNH6jPz!|EK98%O8Y<uU56eBJpY
+zngK0FTp%|1bObxnvfG=Y4Z;V5Nm)DE=-&Xp|28l54+ELZ<Y06F1_0n7{=I>iT3DMn
+z{d)shR+F>aV1(^{(Xa<@(XpmjmDpGVhX%D_t`hV=W`_;2W@=H?njkHfd%lp+aY!<?
+z(D)H%h@n#;dDl%5DQ&e=_5n&*oe<?JD8kS^@S#i{T#nur3iK*o7GZwq4OeWDDqi>u
+zz-Xi@a<E6pmp<nyqoZe5Px4azhn-BMKj4Jah(E%9m_}edv^_gq#OD<`Namr7Tc5s|
+zGWyf}(@=)NM@+lR6$cry#RlUTG2>OFFy|KhMatWpu-=Ju+N@!IWr@-Wr5ZSu8;;P(
+z8s`r3=(Qc0xzop6*?4Dp;P4*j4#u=rF4WR?tXS6*-fgmXq1;zGf2jq~=y_T+ZOr;m
+zDMe@;RVP!mod?wpTuS};pwzK>Xu?09C7`<`q8NqJ20il+B1TCEvoHQ-42`g`qNo`G
+zgLo=UlZF@Zu=GHTDsfJggTZ$R|Ac3&*;5!;QCdIf?4@lterc_=#Z=HovJGOU-ZEq}
+z*SY}tvE8AP6S)J}bZQnx#=1$N71Z>Ib5#gY4-To{wF>_8x_^1;43~8GgnFE6wIZn?
+z+)?Ks`}h@jbY<dqJqmfFZt&~tXVkZ92p3!E0kks>L;a1&H<{Dh^U=1eDvbPBkvPXs
+zXO*ADEa=zx7w^^=-gTlJQm@=N<l`H=XuMap$gun6`7Dk^Wqj>}Kg+F73y!N51wU|8
+zAmfd03X#|ry4g1}H6RVzz_q1jW+Vt^k`x%FL&pj9{p0;r;Q{b<BVj+{3e)7kW>S|1
+zAFG*DBB<NVLmsfQ<Vp-m8?z*^s;ewL#i5PC)}zT_n>^~g|0wVGuy-nP7PD^ib2zwz
+z`Teuw^<OzOL8!7C%ipPl4I}`7?%%k$|9W}DfYY4L$<D>m*yP_E^suIl-3B}2*S3L!
+zN~0l+<;AeWg?ocPaSaZF1vaVtJOU7~b^)ysa(P0N@y*H&<y!rvcqTL|WkO$pdsi4Q
+z|7d4Y-YG4dKF})^S%OEO#I&<CNRHT<Npk&KM^;~s=0yBJa4{-(9YLVt&-UG9EB_Y`
+zmD?*v$8t)O4?9WH7zy>j{Vhc*7*aWj)P=0%ieP1%fbB!)pB5dzTaY02|G2he`q3A_
+zeSIvP^+`;WlV*xD?(}I^allOUUwP`i&^dEcqV8jt4M6}KN+)A$eKX?EH#h4E&Yxvo
+zY4=kMaBjwfJ=q}l*?HI83*_4p@9CNcb>;AqXZGc!PAW2xsoAIwnX@<N=%?RCQf*o8
+zCx&H0)l{sah%c6*T@#}@C0>*J(Rx9kT$weJG2f!R>@MBmZUS7=CZ0*+f_|1N`;YVn
+z3zH6*gm#2$(T8IiFoT&M=z*L{SU2k!(~b{>YX{`XU~{hO-Wmtsu1gb^O9Q<>F11ce
+z-cE#juo>AyV-W91wn(ym_})Rd$3DQ<^ltaLyvV%3bt$N{u?0cfmKQjNglR2rRIc!_
+zY$%ewiy$cx@(z5<33;d5w$cz4Bv#k87L4E~7J%6o)XUO~(PJ%(+E%2SJ*7vF3Y*TR
+zZeA7oix=nbGDRt-C!m@Hpok37ZywCc>;emu-!UeW^Rj+y8b9MOs(Bbm54}Z5TF$u0
+z1D$eXKzGA;woUSq5xJ&<A@ALCNib|~!)d^_7g5%<LH}vNU(lR?<>zI}2`{Fv3UNPG
+z1;3MGu2%AqHyKIhW)?>~(4!MqvsCO&gcwwDw+-X3Te05;A9caDS64;Hq1qUy(_>mB
+z2!x?f!?UF+0(Wx{za3e>IR#~a=LQ{Z%n68jb_5^Hb%R{90$b}_594a!^$m?ar8aR2
+zpQDSXd1o{%0A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
+zb+1%0D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
+Z$B3xmOMs0uyfrX_o`51`gm>`P{a?^2+|mF5
+
+literal 0
+HcmV?d00001
+
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf b/drivers/video/nxp/comps/tmdlHdmiTx/docs/14_user_doc/TRANSMITTER_TDA998X_SW_UM_Devlib.pdf
+new file mode 100755
+index 0000000000000000000000000000000000000000..510913334135870bdd9370ea2156a3af7e8780a8
+GIT binary patch
+literal 610544
+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%0AAH$k-Nr^{
+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
+z#>GS6iJsivTv9L!)B>#L`b1xXkgG%0Awt*t`h29v-RlOBtYhQ^R3~A45vWh7Z|Kd<
+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
+z@R4!g7e9bsj0eA%0D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
+zj|%0A-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
+EH{2!8L;wH)
+
+literal 0
+HcmV?d00001
+
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h
+new file mode 100755
+index 0000000..d5d34ca
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx.h
+@@ -0,0 +1,52 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 02/08/07 08:32 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiTx.h $
++ *
++ * ***************** Version 13 *****************
++ * User: Demoment Date: 02/08/07 Time: 08:32
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMITX_H
++#define TMDLHDMITX_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#include "tmNxCompId.h"
++#include "tmdlHdmiTx_Types.h"
++#include "tmdlHdmiTx_Functions.h"
++
++
++#endif /* TMDLHDMITX_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h
+new file mode 100755
+index 0000000..050645d
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h
+@@ -0,0 +1,1806 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_Functions.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 02/08/07 8:32 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiTx_Functions.h $
++ *
++ * ***************** Version 1 *****************
++ * User: Demoment Date: 02/08/07 Time: 8:32
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMITX_FUNCTIONS_H
++#define TMDLHDMITX_FUNCTIONS_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxTypes.h"
++#include "tmdlHdmiTx_Types.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* EXTERN FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/*****************************************************************************/
++/**
++ \brief Get the software version of the driver.
++
++ \param pSWVersion Pointer to the version structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetSWVersion
++(
++ tmSWVersion_t *pSWVersion
++);
++
++/*****************************************************************************/
++/**
++ \brief Get the number of available HDMI transmitters devices in the system.
++ A unit directly represents a physical device.
++
++ \param pUnitCount Pointer to the number of available units.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetNumberOfUnits
++(
++ UInt32 *pUnitCount
++);
++
++/*****************************************************************************/
++/**
++ \brief Get the capabilities of unit 0. Capabilities are stored into a
++ dedicated structure and are directly read from the HW device.
++
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetCapabilities
++(
++ tmdlHdmiTxCapabilities_t *pCapabilities
++);
++
++/*****************************************************************************/
++/**
++ \brief Get the capabilities of a specific unit. Capabilities are stored
++ into a dedicated structure and are directly read from the HW
++ device.
++
++ \param unit Unit to be probed.
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetCapabilitiesM
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxCapabilities_t *pCapabilities
++);
++
++/*****************************************************************************/
++/**
++ \brief Open unit 0 of HdmiTx driver and provides the instance number to
++ the caller. Note that one unit of HdmiTx represents one physical
++ HDMI transmitter and that only one instance per unit can be opened.
++
++ \param pInstance Pointer to the variable that will receive the instance
++ identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the transmitter instance is not initialised
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already
++ initialised
++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable
++ with the internal device version code
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxOpen
++(
++ tmInstance_t *pInstance
++);
++
++/*****************************************************************************/
++/**
++ \brief Open a specific unit of HdmiTx driver and provides the instance
++ number to the caller. Note that one unit of HdmiTx represents one
++ physical HDMI transmitter and that only one instance per unit can be
++ opened. This function switches driver's state machine to
++ "initialized" state.
++
++ \param pInstance Pointer to the structure that will receive the instance
++ identifier.
++ \param unit Unit number to be opened.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the transmitter instance is not initialised
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already
++ initialised
++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable
++ with the internal device version code
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxOpenM
++(
++ tmInstance_t *pInstance,
++ tmUnitSelect_t unit
++);
++
++/*****************************************************************************/
++/**
++ \brief Close an instance of HdmiTx driver.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxClose
++(
++ tmInstance_t instance
++);
++
++/*****************************************************************************/
++/**
++ \brief Set the power state of an instance of the HDMI transmitter.
++
++ \param instance Instance identifier.
++ \param powerState Power state to set.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t powerState
++);
++
++/*****************************************************************************/
++/**
++ \brief Get the power state of an instance of the HDMI transmitter.
++
++ \param instance Instance identifier.
++ \param pPowerState Pointer to the power state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t *pPowerState
++);
++
++/*****************************************************************************/
++/**
++ \brief Set the configuration of instance attributes. This function is
++ required by DVP architecture rules but actually does nothing in this
++ driver
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxInstanceConfig
++(
++ tmInstance_t instance
++);
++
++/*****************************************************************************/
++/**
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration like enabling HDCP, choosing
++ HDCP encryption mode or enabling HDCP repeater mode.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxInstanceSetup
++(
++ tmInstance_t instance,
++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo
++);
++
++/*****************************************************************************/
++/**
++ \brief Get instance setup parameters.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure that will receive setup
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetInstanceSetup
++(
++ tmInstance_t instance,
++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo
++);
++
++/*****************************************************************************/
++/**
++ \brief Make device library handle an incoming interrupt. This function is
++ used by application to tell the device library that the hardware
++ sent an interrupt.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_FULL: the queue is full
++
++ ******************************************************************************/
++tmErrorCode_t tmdlHdmiTxHandleInterrupt
++(
++ tmInstance_t instance
++);
++
++/*****************************************************************************/
++/**
++ \brief Register event callbacks. Only one callback is registered through
++ this API. This callback will received the type of event that
++ occured throug a dedicated parameter and will be called as many
++ times as there is pending events.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pCallback Pointer to the callback function that will handle events
++ from the devlib.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxRegisterCallbacks
++(
++ tmInstance_t instance,
++ ptmdlHdmiTxCallback_t pCallback
++);
++
++/*****************************************************************************/
++/**
++ \brief This function allows enabling a specific event. By default, all
++ events are disabled, except input lock.
++
++ \param instance Instance identifier.
++ \param event Event to enable.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxEnableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++);
++
++/*****************************************************************************/
++/**
++ \brief This function allows disabling a specific event. By default, all
++ events are disabled, except input lock.
++
++ \param instance Instance identifier.
++ \param event Event to disable.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDisableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++);
++
++/*****************************************************************************/
++/**
++ \brief Get specifications of a given video format. Application can use
++ this function to retreives all specifications (frequencies,
++ resolution, etc.) of a given IA/CEA 861-D video format.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param resolutionID ID of the resolution to retrieve specs from.
++ \param pResolutionSpecs Pointer to the structure receiving specs.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetVideoFormatSpecs
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t resolutionID,
++ tmdlHdmiTxVidFmtSpecs_t *pResolutionSpecs
++);
++
++/*****************************************************************************/
++/**
++ \brief Configures all input and output parameters : format, modes, rates,
++ etc. This is the main configuration function of the driver. Here
++ are transmitted all crucial input and output parameters of the
++ device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param videoInputConfig Configuration of the input video.
++ \param videoOutputConfig Configuration of the output video.
++ \param audioInputConfig Configuration of the input audio.
++ \param sinkType Type of sink connected to the output of the Tx.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetInputOutput
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVideoInConfig_t videoInputConfig,
++ tmdlHdmiTxVideoOutConfig_t videoOutputConfig,
++ tmdlHdmiTxAudioInConfig_t audioInputConfig,
++ tmdlHdmiTxSinkType_t sinkType
++);
++
++/*****************************************************************************/
++/**
++ \brief Configures audio input parameters : format, rate, etc.
++ This function is similar to tmdlHdmiTxSetInputOutput except that
++ video is not reconfigured.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param audioInputConfig Configuration of the input audio.
++ \param sinkType Type of sink connected to the output of the Tx.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioInput
++(
++ tmInstance_t instance,
++ tmdlHdmiTxAudioInConfig_t audioInputConfig,
++ tmdlHdmiTxSinkType_t sinkType
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of AVI infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAviIfData Pointer to the structure containing AVI infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetVideoInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAviIfData_t *pAviIfData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of AUD infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAudIfData Pointer to the structure containing AUD infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAudIfData_t *pAudIfData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of the audio content protection packet to be
++ sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAcpPktData Pointer to the structure containing ACP infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetACPPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAcpPktData_t *pAcpPktData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of the General Control packet to be sent by Tx
++ device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pGcpPktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetGeneralControlPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxGcpPktData_t *pGcpPktData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of ISRC1 packet to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pIsrc1PktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetISRC1Packet
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxIsrc1PktData_t *pIsrc1PktData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of ISRC2 packet to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pIsrc2PktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetISRC2Packet
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxIsrc2PktData_t *pIsrc2PktData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of MPS infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pMpsIfData Pointer to the structure containing MPS infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetMPSInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxMpsIfData_t *pMpsIfData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of SPD infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pSpdIfData Pointer to the structure containing SPD infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetSpdInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxSpdIfData_t *pSpdIfData
++);
++
++/*****************************************************************************/
++/**
++ \brief Defines the content of VS infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pVsIfData Pointer to the structure containing VS infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetVsInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxVsPktData_t *pVsIfData
++);
++
++/*****************************************************************************/
++/**
++ \brief Enables/disables NULL packet sending (only used for debug purpose).
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable packet insertion.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDebugSetNullPacket
++(
++ tmInstance_t instance,
++ Bool enable
++);
++
++/*****************************************************************************/
++/**
++ \brief Send one single NULL packet (only used for debug purpose).
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDebugSetSingleNullPacket
++(
++ tmInstance_t instance
++);
++
++/*****************************************************************************/
++/**
++ \brief Set the audio output mute status. This function can be used to mute
++ audio output, without muting video. This can be typically used when
++ reconfiguring the audio HW after a sample rate change.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param muteStatus Mute status (True/False).
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioMute
++(
++ tmInstance_t instance,
++ Bool audioMute
++);
++
++/*****************************************************************************/
++/**
++ \brief Reset audio CTS.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxResetAudioCts
++(
++ tmInstance_t instance
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieve EDID Status from driver.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidStatus Pointer to the array that will receive the EDID Status.
++ \param pEdidBlkCount Pointer to the integer that will receive the number of
++ read EDID block.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidStatus_t *pEdidStatus,
++ UInt8 *pEdidBlkCount
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves audio descriptors from receiver's EDID. This function
++ parses the EDID of Tx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \param instance Instance identifier.
++ \param pAudioDescs Pointer to the array that will receive audio
++ descriptors.
++ \param maxAudioDescs Size of the array.
++ \param pWrittenAudioDescs Pointer to the integer that will receive the actual
++ number of written descriptors.
++ \param pAudioFlags Pointer to the byte to receive Audio Capabilities Flags.
++ This byte is filled as such:
++ b7 is the Basic audio bit from CEA Extension Version 3.
++ If this bit is set to 1 this means that the sink handles "Basic audio" i.e.
++ two channel L-PCM audio at sample rates of 32kHz, 44.1kHz, and 48kHz.
++ b6 is the Supports_AI bit from the VSDB
++ This bit set to 1 if the sink supports at least one function that uses
++ information carried by the ACP, ISRC1, or ISRC2 packets.
++ b5-b0 0
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidAudioCaps
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidAudioDesc_t *pAudioDescs,
++ UInt maxAudioDescs,
++ UInt *pWrittenAudioDescs,
++ UInt8 *pAudioFlags
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported video formats (short descriptors) from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pVideoDesc Pointer to the structure that will receive short
++ video descriptors.
++ \param maxVideoFormats Size of the array.
++ \param pWrittenVideoFormats Pointer to the integer that will receive the actual
++ number of written descriptors.
++ \param pVideoFlags Pointer to the byte to receive Video Capability Flags.
++ b7: underscan supported
++ b6: YCbCr 4:4:4 supported
++ b5: YCbCr 4:2:2 supported
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidVideoCaps
++(
++ tmInstance_t instance,
++ tmdlHdmiTxShortVidDesc_t *pVideoDesc,
++ UInt maxVideoFormats,
++ UInt *pWrittenVideoFormats,
++ UInt8 *pVideoFlags
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported video formats (short descriptors) from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pNativeVideoFormat Pointer to the array that will receive video
++ timing descriptor.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidVideoPreferred
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pNativeVideoFormat
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves the sink type from receiver's EDID (HDMI or DVI). This
++ function parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pSinkType Pointer to the array that will receive sink type.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidSinkType
++(
++ tmInstance_t instance,
++ tmdlHdmiTxSinkType_t *pSinkType
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves source address from receivers's EDID. This
++ function parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pSourceAddress Pointer to the integer that will receive the EDID source
++ address.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidSourceAddress
++(
++ tmInstance_t instance,
++ UInt16 *pSourceAddress
++);
++
++
++
++/*****************************************************************************/
++/**
++ \brief Retreives KSV list received by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pKsv Pointer to the array that will receive the KSV list.
++ \param maxKsv Maximum number of KSV that the array can store.
++ \param pWrittenKsv Actual number of KSV written into the array.
++ \param pDepth Connection tree depth.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetKsvList
++(
++ tmInstance_t instance,
++ UInt8 *pKsv,
++ UInt8 maxKsv,
++ UInt8 *pWrittenKsv,
++ UInt8 *pDepth,
++ Bool *pMaxCascExd,
++ Bool *pMaxDevsExd
++);
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++/******************************************************************************
++ \brief Retreives HDCP depth received by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pDepth Connection tree depth returned with KSV list.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetDepth(
++ tmInstance_t instance,
++ UInt8 *pDepth
++);
++
++/******************************************************************************
++ \brief Generate SHA_1 interrupt if not occured.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGeneSHA_1_IT
++(
++ tmInstance_t instance
++);
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++/*****************************************************************************/
++/**
++ \brief Enable/Disable HDCP encryption.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param hdcpEnable HDCP On/Off (true = On, False = Off).
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetHdcp
++(
++ tmInstance_t instance,
++ Bool hdcpEnable
++);
++
++/*****************************************************************************/
++/**
++ \brief Get the driver HDCP state.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pHdcpCheckState Pointer to the integer that will receive the HDCP check state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetHdcpState
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHdcpCheck_t *pHdcpCheckState
++);
++
++/*****************************************************************************/
++/**
++ \brief Check the result of an HDCP encryption attempt, called at
++ intervals (set by timeSinceLastCall) after tmdlHdmiTxSetHdcp(true).
++ This API must be used only in case of No Operating System. if OS,
++ this is manage internally of this device library.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param timeSinceLastCall Time passed in milliseconds since last call,
++ must be shorter than 600 ms.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxHdcpCheck
++(
++ tmInstance_t instance,
++ UInt16 timeSinceLastCall
++);
++
++/*****************************************************************************/
++/**
++ \brief This function loads a gamut metadata packet into the HW. HW will
++ actually send it at the beginning of next VS, during the vertical
++ blanking.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable gamut metadata packet insertion.
++ \param pGamutData Pointer to the structure containing gamut metadata
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetGamutPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxGamutData_t *pGamutData
++);
++
++/*****************************************************************************/
++/**
++ \brief This function set the extended colorimetry with one of the following
++ extended colorimetries(bits EC2-0): xvYCC601, xvYCC709, sYCC601,
++ AdobeYCC601, AdobeRGB. When the parameter extendedColorimetry is
++ xvYCC601 or xvYCC70, this function calls the API tmdlHdmiTxSetGamutPacket
++ to send Gamut Packet Data that does not exist for all other types of
++ extended colorimetries for which pointer pGamutData can be set to NULL.
++ This function also allows to set YCC Quantization Range (YQ1-0)
++
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/Disable extended colorimetry.
++ \param extendedColorimetry value of the extended colorimetry (bits EC2 EC1 EC0).
++ \param yccQR YCC quantisation range
++ \param pGamutData Pointer to the structure containing gamut metadata
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter was out of range
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetExtendedColorimetry
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxExtColorimetry_t extendedColorimetry,
++ tmdlHdmiTxYCCQR_t yccQR,
++ tmdlHdmiTxGamutData_t *pGamutData
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported detailled video descriptors from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pDTDescriptors Pointer to the array that will receive detailled
++ timing descriptors.
++ \param maxDTDesc Size of the array.
++ \param pWrittenDesc Pointer to the integer that will receive the actual
++ number of written descriptors.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidDetailledTimingDescriptors
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ UInt8 maxDTDesc,
++ UInt8 *pWrittenDTDesc
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported monitor descriptor from receiver's EDID.
++ This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidFirstMD Pointer to the array that will receive the first monitor
++ descriptors.
++ \param pEdidSecondMD Pointer to the array that will receive the second monitor
++ descriptors.
++ \param pEdidOtherMD Pointer to the array that will receive the other monitor
++ descriptors.
++ \param maxOtherMD Size of the array.
++ \param pWrittenOtherMD Pointer to the integer that will receive the actual
++ number of written descriptors.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidMonitorDescriptors
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidFirstMD_t *pEdidFirstMD,
++ tmdlHdmiTxEdidSecondMD_t *pEdidSecondMD,
++ tmdlHdmiTxEdidOtherMD_t *pEdidOtherMD,
++ UInt8 maxOtherMD,
++ UInt8 *pWrittenOtherMD
++);
++
++/*****************************************************************************/
++/**
++ \brief Retrieves TV picture ratio from receiver's EDID.
++ This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidTvPictureRatio Pointer to the variable that will receive TV picture ratio
++ value.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidTVPictureRatio
++(
++ tmInstance_t instance,
++ tmdlHdmiTxPictAspectRatio_t *pEdidTvPictureRatio
++);
++
++/******************************************************************************
++ \brief This function set the revocation list use for HDCP
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param listPtr Pointer on revocation list provide by application.
++ \param length length of revocation list.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_DLHDMITX_HDCP_SECURE: the call was successful, RX keys are secure
++ - TMDL_DLHDMITX_HDCP_NOT_SECURE: the call was successful, RX keys are NOT secure
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: we are a repeater
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxSetHDCPRevocationList(
++ tmInstance_t instance,
++ void *listPtr,
++ UInt32 length
++);
++
++
++/*****************************************************************************/
++/**
++ \brief Retreives current HDCP link status. This function is typically used
++ when an "HDCP INACTIVE" event is received to know why HDCP
++ is INACTIVE.
++
++ \param instance Instance identifier.
++ \param pHdcpStatus Pointer to the enum describing the status.
++ \param pRawStatus Pointer to the byte with the raw error code from HW.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetHdcpFailStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHdcpStatus_t *pHdcpStatus,
++ UInt8 *pRawStatus
++);
++
++
++/*****************************************************************************/
++/**
++ \brief Retrieves latency information from receiver's EDID.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \param instance Instance identifier.
++ \param pLatency Pointer to the data structure that receive latency
++ information.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidLatencyInfo
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidLatency_t *pLatency
++);
++
++
++/******************************************************************************
++ \brief Retrieves additional data from receiver's EDID VSDB. This function
++ parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pExtraVsdbData Pointer to the structure of additional VSDB data
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidExtraVsdbData
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidExtraVsdbData_t **pExtraVsdbData
++);
++
++
++/******************************************************************************
++ \brief This function set the B... screen
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxSetBScreen(
++ tmInstance_t instance,
++ tmdlHdmiTxTestPattern_t pattern
++);
++
++/******************************************************************************
++ \brief This function set the Remove B.... screen
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxRemoveBScreen(
++ tmInstance_t instance
++);
++
++/******************************************************************************
++ \brief This function Convert DTD to CEA
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pDTDescriptors Pointer on one DTD
++ \return The call result:
++ - CEA code
++
++
++******************************************************************************/
++tmdlHdmiTxVidFmt_t tmdlHdmiTxConvertDTDtoCEA
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++);
++
++
++/*****************************************************************************/
++/**
++ \brief Retrieve HPD status from driver.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pHPDStatus Pointer to the variable that will receive the HPD Status.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetHPDStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHotPlug_t * pHPDStatus
++);
++
++
++/*****************************************************************************/
++/**
++ \brief Retrieve RXSense status from driver.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pRXSenseStatus Pointer to the variable that will receive the RXSense Status.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetRXSenseStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxRxSense_t * pRXSenseStatus
++);
++
++
++/******************************************************************************
++ \brief Mute or unmute the TMDS outputs.
++
++ \param instance Instance identifier.
++ \param muteTmdsOut Mute or unmute indication.
++
++ \return NA.
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxTmdsSetOutputsMute
++(
++ tmInstance_t instance,
++ Bool muteTmdsOut
++);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITX_FUNCTIONS_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
+new file mode 100755
+index 0000000..f090ce2
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
+@@ -0,0 +1,1066 @@
++/**
++ * Copyright (C) 2007 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_Types.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 02/08/07 08:32 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ * HDMI Tx Driver - tmdlHdmiTx - SCS.doc
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiTx_Types.h $
++ *
++ * ***************** Version 1 *****************
++ * User: Demoment Date: 02/08/07 Time: 08:32
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMITX_TYPES_H
++#define TMDLHDMITX_TYPES_H
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++
++#include "tmNxTypes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++/*============================================================================*/
++/* DEFINES */
++/*============================================================================*/
++
++/**< Error Codes */
++#define TMDL_ERR_DLHDMITX_BASE CID_DL_HDMITX
++#define TMDL_ERR_DLHDMITX_COMP (TMDL_ERR_DLHDMITX_BASE | TM_ERR_COMP_UNIQUE_START)
++
++#define TMDL_ERR_DLHDMITX_COMPATIBILITY (TMDL_ERR_DLHDMITX_BASE + TM_ERR_COMPATIBILITY) /**< SW Interface compatibility */
++#define TMDL_ERR_DLHDMITX_MAJOR_VERSION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_MAJOR_VERSION) /**< SW Major Version error */
++#define TMDL_ERR_DLHDMITX_COMP_VERSION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_COMP_VERSION) /**< SW component version error */
++#define TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_UNIT_NUMBER) /**< Invalid device unit number */
++#define TMDL_ERR_DLHDMITX_BAD_INSTANCE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_INSTANCE) /**< Bad input instance value */
++#define TMDL_ERR_DLHDMITX_BAD_HANDLE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_HANDLE) /**< Bad input handle */
++#define TMDL_ERR_DLHDMITX_BAD_PARAMETER (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_PARAMETER) /**< Invalid input parameter */
++#define TMDL_ERR_DLHDMITX_NO_RESOURCES (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NO_RESOURCES) /**< Resource is not available */
++#define TMDL_ERR_DLHDMITX_RESOURCE_OWNED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_RESOURCE_OWNED) /**< Resource is already in use */
++#define TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_RESOURCE_NOT_OWNED) /**< Caller does not own resource */
++#define TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INCONSISTENT_PARAMS) /**< Inconsistent input params */
++#define TMDL_ERR_DLHDMITX_NOT_INITIALIZED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_INITIALIZED) /**< Component is not initialized */
++#define TMDL_ERR_DLHDMITX_NOT_SUPPORTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_SUPPORTED) /**< Function is not supported */
++#define TMDL_ERR_DLHDMITX_INIT_FAILED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INIT_FAILED) /**< Initialization failed */
++#define TMDL_ERR_DLHDMITX_BUSY (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BUSY) /**< Component is busy */
++#define TMDL_ERR_DLHDMITX_I2C_READ (TMDL_ERR_DLHDMITX_BASE + TM_ERR_READ) /**< Read error */
++#define TMDL_ERR_DLHDMITX_I2C_WRITE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_WRITE) /**< Write error */
++#define TMDL_ERR_DLHDMITX_FULL (TMDL_ERR_DLHDMITX_BASE + TM_ERR_FULL) /**< Queue is full */
++#define TMDL_ERR_DLHDMITX_NOT_STARTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_NOT_STARTED) /**< Function is not started */
++#define TMDL_ERR_DLHDMITX_ALREADY_STARTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_ALREADY_STARTED) /**< Function is already started */
++#define TMDL_ERR_DLHDMITX_ASSERTION (TMDL_ERR_DLHDMITX_BASE + TM_ERR_ASSERTION) /**< Assertion failure */
++#define TMDL_ERR_DLHDMITX_INVALID_STATE (TMDL_ERR_DLHDMITX_BASE + TM_ERR_INVALID_STATE) /**< Invalid state for function */
++#define TMDL_ERR_DLHDMITX_OPERATION_NOT_PERMITTED (TMDL_ERR_DLHDMITX_BASE + TM_ERR_OPERATION_NOT_PERMITTED) /**< Corresponds to posix EPERM */
++#define TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN (TMDL_ERR_DLHDMITX_BASE + TM_ERR_BAD_FORMAT) /**< Bad format */
++
++#define TMDL_DLHDMITX_HDCP_SECURE (TMDL_ERR_DLHDMITX_COMP + 0x0001) /**< Revocation list is secure */
++#define TMDL_DLHDMITX_HDCP_NOT_SECURE (TMDL_ERR_DLHDMITX_COMP + 0x0002) /**< Revocation list is NOT secure */
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++
++/**
++ * \brief Enum listing all events that can be signalled to application
++ */
++typedef enum
++{
++ TMDL_HDMITX_HDCP_ACTIVE = 0, /**< HDCP encryption status switched to active */
++ TMDL_HDMITX_HDCP_INACTIVE = 1, /**< HDCP encryption status switched to inactive */
++ TMDL_HDMITX_HPD_ACTIVE = 2, /**< Hotplug status switched to active */
++ TMDL_HDMITX_HPD_INACTIVE = 3, /**< Hotplug status switched to inactive */
++ TMDL_HDMITX_RX_KEYS_RECEIVED = 4, /**< Receiver(s) key(s) received */
++ TMDL_HDMITX_RX_DEVICE_ACTIVE = 5, /**< Rx device is connected and active */
++ TMDL_HDMITX_RX_DEVICE_INACTIVE = 6, /**< Rx device is connected but inactive (standby) */
++ TMDL_HDMITX_EDID_RECEIVED = 7, /**< EDID has been received */
++ TMDL_HDMITX_VS_RPT_RECEIVED = 8, /**< VS interrupt has been received */
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ TMDL_HDMITX_B_STATUS = 9, /**< TX received BStatus */
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++ TMDL_HDMITX_DEBUG_EVENT_1 = 10 /**< This is a debug event */
++} tmdlHdmiTxEvent_t;
++
++/**
++ * \brief Enum listing all available event status
++ */
++typedef enum
++{
++ TMDL_HDMITX_EVENT_ENABLED, /**< Event is enabled */
++ TMDL_HDMITX_EVENT_DISABLED /**< Event is disabled */
++} tmdlHdmiTxEventStatus_t;
++
++/**
++ * \brief Callback function pointer type, used to allow driver to callback
++ application when activity status is changing at input.
++ * \param Event Identifier of the source event.
++ */
++typedef void (*ptmdlHdmiTxCallback_t) (tmdlHdmiTxEvent_t event);
++
++/**
++ * \brief Enum listing all supported device versions
++ */
++ typedef enum
++ {
++ TMDL_HDMITX_DEVICE_UNKNOWN, /**< HW device is unknown */
++ TMDL_HDMITX_DEVICE_TDA9984, /**< HW device is IC TDA9984 */
++ TMDL_HDMITX_DEVICE_TDA9989, /**< HW device is IC TDA9989 */
++ TMDL_HDMITX_DEVICE_TDA9981, /**< HW device is IC TDA9981 */
++ TMDL_HDMITX_DEVICE_TDA9983, /**< HW device is IC TDA9983 */
++ TMDL_HDMITX_DEVICE_TDA19989, /**< HW device is IC TDA19989 */
++ TMDL_HDMITX_DEVICE_TDA19988 /**< ok, u got it, it's a TDA19988 */
++ } tmdlHdmiTxDeviceVersion_t;
++
++/**
++ * \brief Enum defining the supported HDMI standard version
++ */
++typedef enum
++{
++ TMDL_HDMITX_HDMI_VERSION_UNKNOWN, /**< Unknown */
++ TMDL_HDMITX_HDMI_VERSION_1_1, /**< HDMI 1.1 */
++ TMDL_HDMITX_HDMI_VERSION_1_2a, /**< HDMI 1.2a */
++ TMDL_HDMITX_HDMI_VERSION_1_3a /**< HDMI 1.3 */
++} tmdlHdmiTxHdmiVersion_t;
++
++/**
++ * \brief Enum listing all color depth (8 bits/color, 10 bits/color, etc.)
++ */
++typedef enum
++{
++ TMDL_HDMITX_COLORDEPTH_24 = 0, /**< 8 bits per color */
++ TMDL_HDMITX_COLORDEPTH_30 = 1, /**< 10 bits per color */
++ TMDL_HDMITX_COLORDEPTH_36 = 2, /**< 12 bits per color */
++ TMDL_HDMITX_COLORDEPTH_48 = 3 /**< 16 bits per color */
++} tmdlHdmiTxColorDepth_t;
++
++/**
++ * \brief Enum defining the EDID Status
++ */
++typedef enum
++{
++ TMDL_HDMITX_EDID_READ = 0, /**< All blocks read OK */
++ TMDL_HDMITX_EDID_READ_INCOMPLETE = 1, /**< All blocks read OK but buffer too small to return all of them */
++ TMDL_HDMITX_EDID_ERROR_CHK_BLOCK_0 = 2, /**< Block 0 checksum error */
++ TMDL_HDMITX_EDID_ERROR_CHK = 3, /**< Block 0 OK, checksum error in one or more other blocks */
++ TMDL_HDMITX_EDID_NOT_READ = 4, /**< EDID not read */
++ TMDL_HDMITX_EDID_STATUS_INVALID = 5 /**< Invalid */
++} tmdlHdmiTxEdidStatus_t;
++
++/**
++ * \brief Structure defining the supported audio packets
++ */
++typedef struct
++{
++ Bool HBR; /**< High Bitrate Audio packet */
++ Bool DST; /**< Direct Stream Transport audio packet */
++ Bool oneBitAudio; /**< One Bit Audio sample packet */
++} tmdlHdmiTxAudioPacket_t;
++
++/**
++ * \brief Enum listing all possible audio input formats
++ */
++typedef enum
++{
++ TMDL_HDMITX_AFMT_SPDIF = 0, /**< SPDIF */
++ TMDL_HDMITX_AFMT_I2S = 1, /**< I2S */
++ TMDL_HDMITX_AFMT_OBA = 2, /**< One bit audio / DSD */
++ TMDL_HDMITX_AFMT_DST = 3, /**< DST */
++ TMDL_HDMITX_AFMT_HBR = 4 /**< HBR */
++} tmdlHdmiTxAudioFormat_t;
++
++/**
++ * \brief Enum listing all possible audio input sample rates
++ */
++typedef enum
++{
++ TMDL_HDMITX_AFS_32K = 0, /**< 32kHz */
++ TMDL_HDMITX_AFS_44K = 1, /**< 44.1kHz */
++ TMDL_HDMITX_AFS_48K = 2, /**< 48kHz */
++ TMDL_HDMITX_AFS_88K = 3, /**< 88.2kHz */
++ TMDL_HDMITX_AFS_96K = 4, /**< 96kHz */
++ TMDL_HDMITX_AFS_176K = 5, /**< 176.4kHz */
++ TMDL_HDMITX_AFS_192K = 6 /**< 192kHz */
++} tmdlHdmiTxAudioRate_t;
++
++/**
++ * \brief Enum listing all possible audio input sample rates
++ */
++typedef enum
++{
++ TMDL_HDMITX_I2SQ_16BITS = 16, /**< 16 bits */
++ TMDL_HDMITX_I2SQ_32BITS = 32, /**< 32 bits */
++ TMDL_HDMITX_I2SQ_OTHERS = 0 /**< for SPDIF and DSD */
++} tmdlHdmiTxAudioI2SQualifier_t;
++
++/**
++ * \brief Enum listing all possible audio I2S formats
++ */
++typedef enum
++{
++ TMDL_HDMITX_I2SFOR_PHILIPS_L = 0, /**< Philips like format */
++ TMDL_HDMITX_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */
++ TMDL_HDMITX_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */
++ TMDL_HDMITX_I2SFOR_INVALID = 4 /**< Invalid format */
++} tmdlHdmiTxAudioI2SFormat_t;
++
++/**
++ * \brief Enum listing all possible DST data transfer rates
++ */
++typedef enum
++{
++ TMDL_HDMITX_DSTRATE_SINGLE = 0, /**< Single transfer rate */
++ TMDL_HDMITX_DSTRATE_DOUBLE = 1 /**< Double data rate */
++} tmdlHdmiTxDstRate_t;
++
++/**
++ * \brief Structure describing unit capabilities
++ */
++typedef struct
++{
++ tmdlHdmiTxDeviceVersion_t deviceVersion; /**< HW device version */
++ tmdlHdmiTxHdmiVersion_t hdmiVersion; /**< Supported HDMI standard version */
++ tmdlHdmiTxAudioPacket_t audioPacket; /**< Supported audio packets */
++ tmdlHdmiTxColorDepth_t colorDepth; /**< Supported color depth */
++ Bool hdcp; /**< Supported Hdcp encryption (True/False) */
++ Bool scaler; /**< Supported scaler (True/False) */
++} tmdlHdmiTxCapabilities_t;
++
++/**
++ * \brief Structure gathering all instance setup parameters
++ */
++typedef struct
++{
++ Bool simplayHd; /**< Enable simplayHD support */
++ Bool repeaterEnable; /**< Enable repeater mode */
++ UInt8 *pEdidBuffer; /**< Pointer to raw EDID data */
++ UInt32 edidBufferSize; /**< Size of buffer for raw EDID data */
++} tmdlHdmiTxInstanceSetupInfo_t;
++
++/**
++ * \brief Enum listing all IA/CEA 861-D video formats
++ */
++typedef enum
++{
++ TMDL_HDMITX_VFMT_NULL = 0, /**< Not a valid format... */
++ TMDL_HDMITX_VFMT_NO_CHANGE = 0, /**< ...or no change required */
++ TMDL_HDMITX_VFMT_MIN = 1, /**< Lowest valid format */
++ TMDL_HDMITX_VFMT_TV_MIN = 1, /**< Lowest valid TV format */
++ TMDL_HDMITX_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */
++ TMDL_HDMITX_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */
++ TMDL_HDMITX_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */
++ TMDL_HDMITX_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */
++ TMDL_HDMITX_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */
++ TMDL_HDMITX_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */
++ TMDL_HDMITX_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */
++ TMDL_HDMITX_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */
++ TMDL_HDMITX_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */
++ TMDL_HDMITX_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */
++ TMDL_HDMITX_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */
++ TMDL_HDMITX_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */
++ TMDL_HDMITX_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */
++ TMDL_HDMITX_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */
++ TMDL_HDMITX_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */
++ TMDL_HDMITX_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */
++ TMDL_HDMITX_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */
++ TMDL_HDMITX_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */
++ TMDL_HDMITX_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */
++ TMDL_HDMITX_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */
++ TMDL_HDMITX_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */
++ TMDL_HDMITX_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */
++ TMDL_HDMITX_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */
++ TMDL_HDMITX_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */
++ TMDL_HDMITX_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */
++ TMDL_HDMITX_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */
++ TMDL_HDMITX_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */
++ TMDL_HDMITX_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */
++ TMDL_HDMITX_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */
++ TMDL_HDMITX_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */
++ TMDL_HDMITX_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */
++ TMDL_HDMITX_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */
++ TMDL_HDMITX_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */
++ TMDL_HDMITX_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */
++ TMDL_HDMITX_VFMT_35_2880x480p_60Hz = 35, /**< Format 35 2880 x 480p 60Hz 4:3 */
++ TMDL_HDMITX_VFMT_36_2880x480p_60Hz = 36, /**< Format 36 2880 x 480p 60Hz 16:9 */
++ TMDL_HDMITX_VFMT_37_2880x576p_50Hz = 37, /**< Format 37 2880 x 576p 50Hz 4:3 */
++ TMDL_HDMITX_VFMT_38_2880x576p_50Hz = 38, /**< Format 38 2880 x 576p 50Hz 16:9 */
++
++ TMDL_HDMITX_VFMT_INDEX_60_1280x720p_24Hz = 39,/**< Index of HDMITX_VFMT_60_1280x720p_24Hz */
++ TMDL_HDMITX_VFMT_60_1280x720p_24Hz = 60, /**< Format 60 1280 x 720p 23.97/24Hz 16:9 */
++ TMDL_HDMITX_VFMT_61_1280x720p_25Hz = 61, /**< Format 61 1280 x 720p 25Hz 16:9 */
++ TMDL_HDMITX_VFMT_62_1280x720p_30Hz = 62, /**< Format 60 1280 x 720p 29.97/30Hz 16:9 */
++
++ TMDL_HDMITX_VFMT_TV_MAX = 62, /**< Highest valid TV format */
++ TMDL_HDMITX_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */
++ TMDL_HDMITX_VFMT_TV_NUM = 42, /**< Number of TV formats & null */
++
++ TMDL_HDMITX_VFMT_PC_MIN = 128, /**< Lowest valid PC format */
++ TMDL_HDMITX_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */
++ TMDL_HDMITX_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */
++ TMDL_HDMITX_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */
++ TMDL_HDMITX_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */
++ TMDL_HDMITX_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */
++ TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */
++ TMDL_HDMITX_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */
++ TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */
++ TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */
++ TMDL_HDMITX_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */
++ TMDL_HDMITX_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */
++ TMDL_HDMITX_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */
++ TMDL_HDMITX_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */
++ TMDL_HDMITX_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */
++ TMDL_HDMITX_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */
++ TMDL_HDMITX_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */
++ TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */
++ TMDL_HDMITX_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */
++ TMDL_HDMITX_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */
++ TMDL_HDMITX_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */
++ TMDL_HDMITX_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */
++ TMDL_HDMITX_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */
++ TMDL_HDMITX_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */
++ TMDL_HDMITX_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */
++ TMDL_HDMITX_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */
++ TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */
++ TMDL_HDMITX_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */
++ TMDL_HDMITX_VFMT_PC_MAX = 154, /**< Highest valid PC format */
++ TMDL_HDMITX_VFMT_PC_NUM = (TMDL_HDMITX_VFMT_PC_MAX-TMDL_HDMITX_VFMT_PC_MIN+1) /**< Number of PC formats */
++} tmdlHdmiTxVidFmt_t;
++
++/**
++ * \brief Structure defining the EDID short video descriptor
++ */
++typedef struct
++{
++ tmdlHdmiTxVidFmt_t videoFormat; /**< Video format as defined by EIA/CEA 861-D */
++ Bool nativeVideoFormat; /**< True if format is the preferred video format */
++} tmdlHdmiTxShortVidDesc_t;
++
++/**
++ * \brief Enum listing all picture aspect ratio (H:V) (4:3, 16:9)
++ */
++typedef enum
++{
++ TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED = 0, /**< Undefined picture aspect ratio */
++ TMDL_HDMITX_P_ASPECT_RATIO_6_5 = 1, /**< 6:5 picture aspect ratio (PAR) */
++ TMDL_HDMITX_P_ASPECT_RATIO_5_4 = 2, /**< 5:4 PAR */
++ TMDL_HDMITX_P_ASPECT_RATIO_4_3 = 3, /**< 4:3 PAR */
++ TMDL_HDMITX_P_ASPECT_RATIO_16_10 = 4, /**< 16:10 PAR */
++ TMDL_HDMITX_P_ASPECT_RATIO_5_3 = 5, /**< 5:3 PAR */
++ TMDL_HDMITX_P_ASPECT_RATIO_16_9 = 6, /**< 16:9 PAR */
++ TMDL_HDMITX_P_ASPECT_RATIO_9_5 = 7 /**< 9:5 PAR */
++} tmdlHdmiTxPictAspectRatio_t;
++
++/**
++ * \brief Enum listing all vertical frequency
++ */
++typedef enum
++{
++ TMDL_HDMITX_VFREQ_24Hz = 0, /**< 24Hz */
++ TMDL_HDMITX_VFREQ_25Hz = 1, /**< 25Hz */
++ TMDL_HDMITX_VFREQ_30Hz = 2, /**< 30Hz */
++ TMDL_HDMITX_VFREQ_50Hz = 3, /**< 50Hz */
++ TMDL_HDMITX_VFREQ_59Hz = 4, /**< 59.94Hz */
++ TMDL_HDMITX_VFREQ_60Hz = 5, /**< 60Hz */
++#ifndef FORMAT_PC
++ TMDL_HDMITX_VFREQ_INVALID = 6, /**< Invalid */
++ TMDL_HDMITX_VFREQ_NUM = 6 /**< No. of values */
++#else /* FORMAT_PC */
++ TMDL_HDMITX_VFREQ_70Hz = 6, /**< 70Hz */
++ TMDL_HDMITX_VFREQ_72Hz = 7, /**< 72Hz */
++ TMDL_HDMITX_VFREQ_75Hz = 8, /**< 75Hz */
++ TMDL_HDMITX_VFREQ_85Hz = 9, /**< 85Hz */
++ TMDL_HDMITX_VFREQ_87Hz = 10, /**< 87Hz */
++ TMDL_HDMITX_VFREQ_INVALID = 11, /**< Invalid */
++ TMDL_HDMITX_VFREQ_NUM = 11 /**< No. of values */
++#endif /* FORMAT_PC */
++} tmdlHdmiTxVfreq_t;
++
++/**
++ * \brief Structure storing specifications of a video resolution
++ */
++typedef struct
++{
++ UInt16 width; /**< Width of the frame in pixels */
++ UInt16 height; /**< Height of the frame in pixels */
++ Bool interlaced; /**< Interlaced mode (True/False) */
++ tmdlHdmiTxVfreq_t vfrequency; /**< Vertical frequency in Hz */
++ tmdlHdmiTxPictAspectRatio_t aspectRatio; /**< Picture aspect ratio (H:V) */
++} tmdlHdmiTxVidFmtSpecs_t;
++
++/**
++ * \brief Enum listing all video input modes (CCIR, RGB, etc.)
++ */
++typedef enum
++{
++ TMDL_HDMITX_VINMODE_CCIR656 = 0, /**< CCIR656 */
++ TMDL_HDMITX_VINMODE_RGB444, /**< RGB444 */
++ TMDL_HDMITX_VINMODE_YUV444, /**< YUV444 */
++ TMDL_HDMITX_VINMODE_YUV422, /**< YUV422 */
++#ifdef TMFL_RGB_DDR_12BITS
++ TMDL_HDMITX_VINMODE_RGB_DDR_12BITS, /**< RGB24 bits on a 12 bits bus using double data rate clocking */
++#endif
++ TMDL_HDMITX_VINMODE_NO_CHANGE , /**< No change */
++ TMDL_HDMITX_VINMODE_INVALID /**< Invalid */
++} tmdlHdmiTxVinMode_t;
++
++/**
++ * \brief Enum listing all possible sync sources
++ */
++typedef enum
++{
++ TMDL_HDMITX_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */
++ TMDL_HDMITX_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */
++ TMDL_HDMITX_SYNCSRC_EXT_VS = 2 /**< External sync Vs, Hs */
++} tmdlHdmiTxSyncSource_t;
++
++/**
++ * \brief Enum listing all output pixel rate (Single, Double, etc.)
++ */
++typedef enum
++{
++ TMDL_HDMITX_PIXRATE_DOUBLE = 0, /**< Double pixel rate */
++ TMDL_HDMITX_PIXRATE_SINGLE = 1, /**< Single pixel rate */
++ TMDL_HDMITX_PIXRATE_SINGLE_REPEATED = 2 /**< Single pixel repeated */
++} tmdlHdmiTxPixRate_t;
++
++/**
++ * \brief Enum listing the supported transmission formats of 3D video data
++ */
++typedef enum
++{
++ TMDL_HDMITX_3D_NONE = 0, /**< 3D video data not present */
++ TMDL_HDMITX_3D_FRAME_PACKING = 1, /**< 3D video data Frame Packing structure */
++ TMDL_HDMITX_3D_TOP_AND_BOTTOM = 2, /**< 3D video data Top and Bottom structure */
++ TMDL_HDMITX_3D_SIDE_BY_SIDE_HALF = 3, /**< 3D video data Side by Side Half structure */
++ TMDL_HDMITX_3D_INVALID = 4 /**< Invalid */
++} tmdlHdmiTx3DStructure_t;
++
++/**
++ * \brief Structure defining the video input configuration
++ */
++typedef struct
++{
++ tmdlHdmiTxVidFmt_t format; /**< Video format as defined by EIA/CEA 861-D */
++ tmdlHdmiTxVinMode_t mode; /**< Video mode (CCIR, RGB, YUV, etc.) */
++ tmdlHdmiTxSyncSource_t syncSource; /**< Sync source type */
++ tmdlHdmiTxPixRate_t pixelRate; /**< Pixel rate */
++ tmdlHdmiTx3DStructure_t structure3D; /**< 3D structure as defined in HDMI1.4a */
++} tmdlHdmiTxVideoInConfig_t;
++
++/**
++ * \brief Enum listing all video output modes (YUV, RGB, etc.)
++ */
++typedef enum
++{
++ TMDL_HDMITX_VOUTMODE_RGB444 = 0, /**< RGB444 */
++ TMDL_HDMITX_VOUTMODE_YUV422 = 1, /**< YUV422 */
++ TMDL_HDMITX_VOUTMODE_YUV444 = 2 /**< YUV444 */
++} tmdlHdmiTxVoutMode_t;
++
++/**
++ * \brief Enum defining possible quantization range
++ */
++typedef enum
++{
++ TMDL_HDMITX_VQR_DEFAULT = 0, /* Follow HDMI spec. */
++ TMDL_HDMITX_RGB_FULL = 1, /* Force RGB FULL , DVI only */
++ TMDL_HDMITX_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */
++} tmdlHdmiTxVQR_t;
++
++
++/**
++ * \brief Enum defining possible YCC Quantization Range
++ */
++typedef enum
++{
++ TMDL_HDMITX_YQR_LIMITED = 0, /* LIMITED range */
++ TMDL_HDMITX_YQR_FULL = 1, /* FULL range */
++ TMDL_HDMITX_YQR_INVALID = 2 /* Invalid range */
++} tmdlHdmiTxYCCQR_t;
++
++
++/**
++ * \brief Structure defining the video output configuration
++ */
++typedef struct
++{
++ tmdlHdmiTxVidFmt_t format; /**< Video format as defined by EIA/CEA 861-D */
++ tmdlHdmiTxVoutMode_t mode; /**< Video mode (CCIR, RGB, YUV, etc.) */
++ tmdlHdmiTxColorDepth_t colorDepth; /**< Color depth */
++ tmdlHdmiTxVQR_t dviVqr; /**< VQR applied in DVI mode */
++} tmdlHdmiTxVideoOutConfig_t;
++
++
++typedef enum
++{
++ TMDL_HDMITX_AUDIO_DATA_PCM = 0, /**< Main data field represents linear PCM samples. */
++ TMDL_HDMITX_AUDIO_DATA_OTHER = 1, /**< Main data field used for purposes other purposes. */
++ TMDL_HDMITX_AUDIO_DATA_INVALID = 2 /**< Invalid value */
++} tmdlHdmiTxAudioData_t;
++
++
++typedef enum
++{
++ TMDL_HDMITX_CSCOPYRIGHT_PROTECTED = 0, /**< Copyright protected */
++ TMDL_HDMITX_CSCOPYRIGHT_UNPROTECTED = 1, /**< Not copyright protected */
++ TMDL_HDMITX_CSCOPYRIGHT_INVALID = 2 /**< Invalid value */
++} tmdlHdmiTxCScopyright_t;
++
++typedef enum
++{
++ TMDL_HDMITX_CSFI_PCM_2CHAN_NO_PRE = 0, /**< PCM 2 channels without pre-emphasis or NON Linear PCM */
++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE = 1, /**< PCM 2 channels with 50us/15us pre-emphasis */
++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE_RSVD1 = 2, /**< PCM Reserved for 2 channels with pre-emphasis */
++ TMDL_HDMITX_CSFI_PCM_2CHAN_PRE_RSVD2 = 3, /**< PCM Reserved for 2 channels with pre-emphasis */
++ TMDL_HDMITX_CSFI_INVALID = 4 /**< Invalid value */
++} tmdlHdmiTxCSformatInfo_t;
++
++
++typedef enum
++{
++ TMDL_HDMITX_CSCLK_LEVEL_II = 0, /**< Level II */
++ TMDL_HDMITX_CSCLK_LEVEL_I = 1, /**< Level I */
++ TMDL_HDMITX_CSCLK_LEVEL_III = 2, /**< Level III */
++ TMDL_HDMITX_CSCLK_NOT_MATCHED = 3, /**< Not matched to sample freq. */
++ TMDL_HDMITX_CSCLK_INVALID = 4 /**< Invalid */
++} tmdlHdmiTxCSclkAcc_t;
++
++
++typedef enum
++{
++ TMDL_HDMITX_CSMAX_LENGTH_20 = 0, /**< Max word length is 20 bits */
++ TMDL_HDMITX_CSMAX_LENGTH_24 = 1, /**< Max word length is 24 bits */
++ TMDL_HDMITX_CSMAX_INVALID = 2 /**< Invalid value */
++} tmdlHdmiTxCSmaxWordLength_t;
++
++
++
++typedef enum
++{
++ TMDL_HDMITX_CSWORD_DEFAULT = 0, /**< Word length is not indicated */
++ TMDL_HDMITX_CSWORD_20_OF_24 = 1, /**< Sample length is 20 bits out of max 24 possible */
++ TMDL_HDMITX_CSWORD_16_OF_20 = 1, /**< Sample length is 16 bits out of max 20 possible */
++ TMDL_HDMITX_CSWORD_22_OF_24 = 2, /**< Sample length is 22 bits out of max 24 possible */
++ TMDL_HDMITX_CSWORD_18_OF_20 = 2, /**< Sample length is 18 bits out of max 20 possible */
++ TMDL_HDMITX_CSWORD_RESVD = 3, /**< Reserved - shall not be used */
++ TMDL_HDMITX_CSWORD_23_OF_24 = 4, /**< Sample length is 23 bits out of max 24 possible */
++ TMDL_HDMITX_CSWORD_19_OF_20 = 4, /**< Sample length is 19 bits out of max 20 possible */
++ TMDL_HDMITX_CSWORD_24_OF_24 = 5, /**< Sample length is 24 bits out of max 24 possible */
++ TMDL_HDMITX_CSWORD_20_OF_20 = 5, /**< Sample length is 20 bits out of max 20 possible */
++ TMDL_HDMITX_CSWORD_21_OF_24 = 6, /**< Sample length is 21 bits out of max 24 possible */
++ TMDL_HDMITX_CSWORD_17_OF_20 = 6, /**< Sample length is 17 bits out of max 20 possible */
++ TMDL_HDMITX_CSWORD_INVALID = 7 /**< Invalid */
++} tmdlHdmiTxCSwordLength_t;
++
++
++typedef enum
++{
++ TMDL_HDMITX_CSOFREQ_NOT_INDICATED = 0, /**< Not Indicated */
++ TMDL_HDMITX_CSOFREQ_192k = 1, /**< 192kHz */
++ TMDL_HDMITX_CSOFREQ_12k = 2, /**< 12kHz */
++ TMDL_HDMITX_CSOFREQ_176_4k = 3, /**< 176.4kHz */
++ TMDL_HDMITX_CSOFREQ_RSVD1 = 4, /**< Reserved */
++ TMDL_HDMITX_CSOFREQ_96k = 5, /**< 96kHz */
++ TMDL_HDMITX_CSOFREQ_8k = 6, /**< 8kHz */
++ TMDL_HDMITX_CSOFREQ_88_2k = 7, /**< 88.2kHz */
++ TMDL_HDMITX_CSOFREQ_16k = 8, /**< 16kHz */
++ TMDL_HDMITX_CSOFREQ_24k = 9, /**< 24kHz */
++ TMDL_HDMITX_CSOFREQ_11_025k = 10, /**< 11.025kHz */
++ TMDL_HDMITX_CSOFREQ_22_05k = 11, /**< 22.05kHz */
++ TMDL_HDMITX_CSOFREQ_32k = 12, /**< 32kHz */
++ TMDL_HDMITX_CSOFREQ_48k = 13, /**< 48kHz */
++ TMDL_HDMITX_CSOFREQ_RSVD2 = 14, /**< Reserved */
++ TMDL_HDMITX_CSOFREQ_44_1k = 15, /**< 44.1kHz */
++ TMDL_HDMITX_CSAFS_INVALID = 16 /**< Invalid value */
++} tmdlHdmiTxCSorigAfs_t;
++
++
++
++typedef struct
++{
++ tmdlHdmiTxAudioData_t PcmIdentification;
++ tmdlHdmiTxCScopyright_t CopyrightInfo;
++ tmdlHdmiTxCSformatInfo_t FormatInfo;
++ UInt8 categoryCode;
++ tmdlHdmiTxCSclkAcc_t clockAccuracy;
++ tmdlHdmiTxCSmaxWordLength_t maxWordLength;
++ tmdlHdmiTxCSwordLength_t wordLength;
++ tmdlHdmiTxCSorigAfs_t origSampleFreq;
++} tmdlHdmiTxAudioInChannelStatus;
++
++
++/**
++ * \brief Structure defining the audio input configuration
++ */
++typedef struct
++{
++ tmdlHdmiTxAudioFormat_t format; /**< Audio format (I2S, SPDIF, etc.) */
++ tmdlHdmiTxAudioRate_t rate; /**< Audio sampling rate */
++ tmdlHdmiTxAudioI2SFormat_t i2sFormat; /**< I2S format of the audio input */
++ tmdlHdmiTxAudioI2SQualifier_t i2sQualifier; /**< I2S qualifier of the audio input (8,16,32 bits) */
++ tmdlHdmiTxDstRate_t dstRate; /**< DST data transfer rate */
++ UInt8 channelAllocation; /**< Ref to CEA-861D p85 */
++ tmdlHdmiTxAudioInChannelStatus channelStatus; /**< Ref to IEC 60958-3 */
++} tmdlHdmiTxAudioInConfig_t;
++
++/**
++ * \brief Enum listing all the type of sunk
++ */
++typedef enum
++{
++ TMDL_HDMITX_SINK_DVI = 0, /**< DVI */
++ TMDL_HDMITX_SINK_HDMI = 1, /**< HDMI */
++ TMDL_HDMITX_SINK_EDID = 2 /**< As currently defined in EDID */
++} tmdlHdmiTxSinkType_t;
++
++/**
++ * \brief Structure defining the content of a gamut packet
++ */
++typedef struct
++{
++ Bool nextField; /**< Gamut relevant for field following packet insertion */
++ UInt8 GBD_Profile; /**< Profile of the gamut packet : 0 = P0, 1 = P1 */
++ UInt8 affectedGamutSeqNum; /**< Gamut sequence number of the field that have to be affected by this gamut packet */
++ Bool noCurrentGBD; /**< Current field not using specific gamut */
++ UInt8 currentGamutSeqNum; /**< Gamut sequence number of the current field */
++ UInt8 packetSequence; /**< Sequence of the packet inside a multiple packet gamut */
++ UInt8 payload[28]; /**< Payload of the gamut packet */
++} tmdlHdmiTxGamutData_t;
++
++/**
++ * \brief Type defining the content of a generic packet
++ */
++typedef UInt8 tmdlHdmiTxGenericPacket[28];
++
++/**
++ * \brief Structure defining the content of an ACP packet
++ */
++typedef struct
++{
++ UInt8 acpType;
++ UInt8 acpData[28];
++} tmdlHdmiTxAcpPktData_t;
++
++/**
++ * \brief Structure defining the content of an AVI infoframe
++ */
++typedef struct
++{
++ UInt8 colorIndicator; /**< RGB or YCbCr indicator. See CEA-861-B table 8 for details */
++ UInt8 activeInfoPresent; /**< Active information present. Indicates if activeFormatAspectRatio field is valid */
++ UInt8 barInformationDataValid; /**< Bar information data valid */
++ UInt8 scanInformation; /**< Scan information. See CEA-861-B table 8 for details */
++ UInt8 colorimetry; /**< Colorimetry. See CEA-861-B table 9 for details */
++ UInt8 pictureAspectRatio; /**< Picture aspect ratio. See CEA-861-B table 9 for details */
++ UInt8 activeFormatAspectRatio; /**< Active Format aspect ratio. See CEA-861-B table 10 and Annex H for details */
++ UInt8 nonUniformPictureScaling; /**< Non-uniform picture scaling. See CEA-861-B table 11 for details */
++ UInt8 videoFormatIdentificationCode; /**< Video format indentification code. See CEA-861-B section 6.3 for details */
++ UInt8 pixelRepetitionFactor; /**< Pixel repetition factor. See CEA-861-B table 11 for details */
++ UInt16 lineNumberEndTopBar;
++ UInt16 lineNumberStartBottomBar;
++ UInt16 lineNumberEndLeftBar;
++ UInt16 lineNumberStartRightBar;
++} tmdlHdmiTxAviIfData_t;
++
++/**
++ * \brief Structure defining the content of an ACP packet
++ */
++typedef struct
++{
++ Bool avMute;
++} tmdlHdmiTxGcpPktData_t;
++
++/**
++ * \brief Structure defining the content of an AUD infoframe
++ */
++typedef struct
++{
++ UInt8 codingType; /**< Coding type (always set to zero) */
++ UInt8 channelCount; /**< Channel count. See CEA-861-B table 17 for details */
++ UInt8 samplefrequency; /**< Sample frequency. See CEA-861-B table 18 for details */
++ UInt8 sampleSize; /**< Sample frequency. See CEA-861-B table 18 for details */
++ UInt8 channelAllocation; /**< Channel allocation. See CEA-861-B section 6.3.2 for details */
++ Bool downmixInhibit; /**< Downmix inhibit. See CEA-861-B section 6.3.2 for details */
++ UInt8 levelShiftValue; /**< level shift value for downmixing. See CEA-861-B section 6.3.2 and table 23 for details */
++} tmdlHdmiTxAudIfData_t;
++
++/**
++ * \brief Structure defining the content of an ISRC1 packet
++ */
++typedef struct
++{
++ Bool isrcCont; /**< ISRC packet continued in next packet */
++ Bool isrcValid; /**< Set to one when ISRCStatus and UPC_EAN_ISRC_xx are valid */
++ UInt8 isrcStatus; /**< ISRC status */
++ UInt8 UPC_EAN_ISRC[16]; /**< ISRC packet data */
++} tmdlHdmiTxIsrc1PktData_t;
++
++/**
++ * \brief Structure defining the content of an ISRC2 packet
++ */
++typedef struct
++{
++ UInt8 UPC_EAN_ISRC[16]; /**< ISRC packet data */
++} tmdlHdmiTxIsrc2PktData_t;
++
++/**
++ * \brief Structure defining the content of an MPS infoframe
++ */
++typedef struct
++{
++ UInt32 bitRate; /**< MPEG bit rate in Hz */
++ UInt32 frameType; /**< MPEG frame type */
++ Bool fieldRepeat; /**< 0: new field, 1:repeated field */
++} tmdlHdmiTxMpsIfData_t;
++
++/**
++ * \brief Structure defining the content of an SPD infoframe
++ */
++typedef struct
++{
++ UInt8 vendorName[8]; /**< Vendor name */
++ UInt8 productDesc[16]; /**< Product Description */
++ UInt32 sourceDevInfo; /**< Source Device Info */
++} tmdlHdmiTxSpdIfData_t;
++
++
++/**
++ * \brief Structure defining the content of a VS infoframe packet according to HDMI 1.4a standard
++ */
++
++/* HDMI version */
++#define TMDL_HDMITX_VERSION 0x01
++
++/* HDMI video format [3bits] */
++#define TMDL_HDMITX_VIDEO_FORMAT_SHIFT 5
++#define TMDL_HDMITX_FORMAT_EXTENDED (0x01 << TMDL_HDMITX_VIDEO_FORMAT_SHIFT)
++#define TMDL_HDMITX_3D (0x02 << TMDL_HDMITX_VIDEO_FORMAT_SHIFT)
++
++/* IEEE registration identifier (0x000C03) with least significant byte first */
++#define TMDL_HDMITX_HDMI_IEEE_BYTE0 0x03
++#define TMDL_HDMITX_HDMI_IEEE_BYTE1 0x0C
++#define TMDL_HDMITX_HDMI_IEEE_BYTE2 0x00
++
++/* 3D structure [4bits] */
++#define TMDL_HDMITX_3D_STRUCTURE_SHIFT 4
++#define TMDL_HDMITX_FRAME_PACKING (0x00 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_FIELD_ALTERNATIVE (0x01 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_LINE_ALTERNATIVE (0x02 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_SIDE_BY_SIDE_FULL (0x03 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_L_DEPTH (0x04 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_L_DEPTH_GFX (0x05 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_TOP_AND_BOTTOM (0x06 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++#define TMDL_HDMITX_SIDE_BY_SIDE_HALF (0x08 << TMDL_HDMITX_3D_STRUCTURE_SHIFT)
++
++/* 3D EXT Data [4bits] */
++#define TMDL_HDMITX_3D_EXT_DATA_SHIFT 4
++#define TMDL_HDMITX_HORIZONTAL_SUB (0x00 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Horizontal sub-sampling */
++#define TMDL_HDMITX_QUINCUNX_OLOR (0x04 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Odd/Left picture, Odd/Right picture */
++#define TMDL_HDMITX_QUINCUNX_OLER (0x05 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Odd/Left picture, Even/Right picture */
++#define TMDL_HDMITX_QUINCUNX_ELOR (0x06 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Even/Left picture, Odd/Right picture */
++#define TMDL_HDMITX_QUINCUNX_ELER (0x07 << TMDL_HDMITX_3D_EXT_DATA_SHIFT) /* Even/Left picture, Even/Right picture */
++
++/* 3D Meta field */
++#define TMDL_HDMITX_3D_META_TYPE_SHIFT 5
++#define TMDL_HDMITX_3D_META_PRESENT (0x01 << 3)
++#define TMDL_HDMITX_3D_META_PARALLAX (0x00 << TMDL_HDMITX_3D_META_TYPE_SHIFT)
++
++#define TMDL_HDMITX_VS_PKT_DATA_LEN 27
++typedef struct
++{
++ UInt8 version;
++ /*
++ Packet Byte # 7 6 5 4 3 2 1 0
++
++ PB1 24bit IEEE Registration Identifier (0x000C03)
++ PB2 ( least significant byte first )
++ PB3
++ PB4 (HDMI_Video_Format ) (0) (0) (0) (0) (0)
++ PB5 (3D_Structure ) +Meta (0) (0) (0)
++ PB6 (3D_Ext_Data ) (0) (0) (0) (0)
++ PB7 (3D_Metadata_type ) (3D_Metadata_Length (= N))
++ PB8 (3D_Metadata_1 )
++ ... ...
++ PB [7+N] (3D_Metadata_N )
++ PB[8+N]~[Nv] (Reserved (0) )
++ */
++ UInt8 vsData[TMDL_HDMITX_VS_PKT_DATA_LEN];
++
++} tmdlHdmiTxVsPktData_t;
++
++/**
++ * \brief Structure defining the additional Edid VSDB data according to HDMI 1.4a standard
++ */
++typedef struct
++{
++ UInt8 maxTmdsClock; /* maximum supported TMDS clock */
++ UInt8 cnc0; /* content type Graphics (text) */
++ UInt8 cnc1; /* content type Photo */
++ UInt8 cnc2; /* content type Cinema */
++ UInt8 cnc3; /* content type Game */
++ UInt8 hdmiVideoPresent; /* additional video format */
++ UInt8 h3DPresent; /* 3D support by the HDMI Sink */
++ UInt8 h3DMultiPresent; /* 3D multi strctures present */
++ UInt8 imageSize; /* additional info for the values in the image size area */
++ UInt8 hdmi3DLen; /* total length of 3D video formats */
++ UInt8 hdmiVicLen; /* total length of extended video formats */
++ UInt8 ext3DData[21]; /* max_len-10, ie: 31-10=21 */
++} tmdlHdmiTxEdidExtraVsdbData_t;
++
++/**
++ * \brief Structure defining the Edid audio descriptor
++ */
++typedef struct
++{
++ UInt8 format; /* EIA/CEA861 mode */
++ UInt8 channels; /* number of channels */
++ UInt8 supportedFreqs; /* bitmask of supported frequencies */
++ UInt8 supportedRes; /* bitmask of supported resolutions (LPCM only) */
++ UInt8 maxBitrate; /* Maximum bitrate divided by 8KHz (compressed formats only) */
++} tmdlHdmiTxEdidAudioDesc_t;
++
++/**
++ * \brief Structure defining detailed timings of a video format
++ */
++typedef struct
++{
++ UInt16 pixelClock; /**< Pixel Clock/10 000 */
++ UInt16 hActivePixels; /**< Horizontal Active Pixels */
++ UInt16 hBlankPixels; /**< Horizontal Blanking Pixels */
++ UInt16 vActiveLines; /**< Vertical Active Lines */
++ UInt16 vBlankLines; /**< Vertical Blanking Lines */
++ UInt16 hSyncOffset; /**< Horizontal Sync Offset */
++ UInt16 hSyncWidth; /**< Horiz. Sync Pulse Width */
++ UInt16 vSyncOffset; /**< Vertical Sync Offset */
++ UInt16 vSyncWidth; /**< Vertical Sync Pulse Width */
++ UInt16 hImageSize; /**< Horizontal Image Size */
++ UInt16 vImageSize; /**< Vertical Image Size */
++ UInt16 hBorderPixels; /**< Horizontal Border */
++ UInt16 vBorderPixels; /**< Vertical Border */
++ UInt8 flags; /**< Interlace/sync info */
++} tmdlHdmiTxEdidVideoTimings_t;
++
++/** size descriptor block of monitor descriptor */
++#define EDID_MONITOR_DESCRIPTOR_SIZE 13
++
++/**
++ * \brief Structure defining the first monitor descriptor
++ */
++typedef struct
++{
++ Bool descRecord; /**< True when parameters of struct are available */
++ UInt8 monitorName[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Monitor Name */
++} tmdlHdmiTxEdidFirstMD_t;
++
++/**
++ * \brief Structure defining the second monitor descriptor
++ */
++typedef struct
++{
++ Bool descRecord; /**< True when parameters of struct are available */
++ UInt8 minVerticalRate; /**< Min vertical rate in Hz */
++ UInt8 maxVerticalRate; /**< Max vertical rate in Hz */
++ UInt8 minHorizontalRate; /**< Min horizontal rate in Hz */
++ UInt8 maxHorizontalRate; /**< Max horizontal rate in Hz */
++ UInt8 maxSupportedPixelClk; /**< Max suuported pixel clock rate in MHz */
++} tmdlHdmiTxEdidSecondMD_t;
++
++/**
++ * \brief Structure defining the other monitor descriptor
++ */
++typedef struct
++{
++ Bool descRecord; /**< True when parameters of struct are available */
++ UInt8 otherDescriptor[EDID_MONITOR_DESCRIPTOR_SIZE]; /**< Other monitor Descriptor */
++} tmdlHdmiTxEdidOtherMD_t;
++
++/**
++ * \brief Test pattern types
++ */
++typedef enum
++{
++ TMDL_HDMITX_PATTERN_OFF = 0, /**< Insert test pattern */
++ TMDL_HDMITX_PATTERN_CBAR4 = 1, /**< Insert 4-bar colour bar */
++ TMDL_HDMITX_PATTERN_CBAR8 = 2, /**< Insert 8-bar colour bar */
++ TMDL_HDMITX_PATTERN_BLUE = 3, /**< Insert Blue screen */
++ TMDL_HDMITX_PATTERN_BLACK = 4, /**< Insert Black screen */
++ TMDL_HDMITX_PATTERN_INVALID = 5 /**< Invalid pattern */
++} tmdlHdmiTxTestPattern_t;
++
++/**
++ * \brief Enum listing all hdcp state
++ */
++typedef enum
++{
++ TMDL_HDMITX_HDCP_CHECK_NOT_STARTED = 0, /**< Check not started */
++ TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS = 1, /**< No failures, more to do */
++ TMDL_HDMITX_HDCP_CHECK_PASS = 2, /**< Final check has passed */
++ TMDL_HDMITX_HDCP_CHECK_FAIL_FIRST = 3, /**< First check failure code */
++ TMDL_HDMITX_HDCP_CHECK_FAIL_DRIVER_STATE = 3, /**< Driver not AUTHENTICATED */
++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_T0 = 4, /**< A T0 interrupt occurred */
++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_RI = 5, /**< Device RI changed */
++ TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM = 6, /**< Device FSM not 10h */
++ TMDL_HDMITX_HDCP_CHECK_NUM = 7 /**< Number of check results */
++}tmdlHdmiTxHdcpCheck_t;
++
++/**
++ * \brief Enum listing all hdcp option flags
++ */
++typedef enum
++{
++ TMDL_HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED = 0x01, /* Not set: obey PJ result */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_SLOW_DDC = 0x02, /* Not set: obey BCAPS setting */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_NO_1_1 = 0x04, /* Not set: obey BCAPS setting */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_REPEATER = 0x08, /* Not set: obey BCAPS setting */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_NO_REPEATER = 0x10, /* Not set: obey BCAPS setting */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_V_EQU_VBAR = 0x20, /* Not set: obey V=V' result */
++ TMDL_HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC = 0x40, /* Set: 50kHz DDC */
++ TMDL_HDMITX_HDCP_OPTION_DEFAULT = 0x00, /* All the above Not Set vals */
++ TMDL_HDMITX_HDCP_OPTION_MASK = 0x7F, /* Only these bits are allowed */
++ TMDL_HDMITX_HDCP_OPTION_MASK_BAD = 0x80 /* These bits are not allowed */
++}tmdlHdmiTxHdcpOptions_t;
++
++#ifndef NO_HDCP
++/** KSV list sizes */
++typedef enum
++{
++ TMDL_HDMITX_KSV_LIST_MAX_DEVICES = 128,
++ TMDL_HDMITX_KSV_BYTES_PER_DEVICE = 5
++} tmdlHdmiTxHdcpHandleSHA_1;
++
++/**
++ * \brief Structure defining information about hdcp
++ */
++typedef struct
++{
++ tmdlHdmiTxHdcpCheck_t hdcpCheckState; /* Hdcp check state */
++ UInt8 hdcpErrorState; /* Error State when T0 occured */
++ Bool bKsvSecure; /* BKSV is secured */
++ UInt8 hdcpBksv[TMDL_HDMITX_KSV_BYTES_PER_DEVICE]; /* BKSV read from B sink */
++ UInt8 hdcpKsvList[TMDL_HDMITX_KSV_BYTES_PER_DEVICE *
++ TMDL_HDMITX_KSV_LIST_MAX_DEVICES]; /* KSV list read from B sink during
++ SHA-1 interrupt */
++ UInt8 hdcpKsvDevices; /* Number of devices read from
++ B sink during SHA-1 interrupt */
++ UInt8 hdcpDeviceDepth; /* Connection tree depth */
++ Bool hdcpMaxCascExceeded;
++ Bool hdcpMaxDevsExceeded;
++} tmdlHdmiTxHdcpInfo_t;
++#endif /* NO_HDCP */
++
++/**
++ * \brief Enum defining possible HDCP
++ */
++typedef enum
++{
++ TMDL_HDMITX_HDCP_OK = 0,
++ TMDL_HDMITX_HDCP_BKSV_RCV_FAIL, /* Source does not receive Sink BKsv */
++ TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL, /* BKsv does not contain 20 zeros and 20 ones */
++ TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL, /* Source does not receive Sink Bcaps */
++ TMDL_HDMITX_HDCP_AKSV_SEND_FAIL, /* Source does not send AKsv */
++ TMDL_HDMITX_HDCP_R0_RCV_FAIL, /* Source does not receive R'0 */
++ TMDL_HDMITX_HDCP_R0_CHECK_FAIL, /* R0 = R'0 check fail */
++ TMDL_HDMITX_HDCP_BKSV_NOT_SECURE,
++ TMDL_HDMITX_HDCP_RI_RCV_FAIL, /* Source does not receive R'i */
++ TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL, /* Source does not receive R'i repeater mode */
++ TMDL_HDMITX_HDCP_RI_CHECK_FAIL, /* RI = R'I check fail */
++ TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL, /* RI = R'I check fail repeater mode */
++ TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL, /* Source does not receive Sink Bcaps repeater mode */
++ TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT,
++ TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL, /* Source does not receive V'*/
++ TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL, /* Source does not receive BSTATUS repeater mode */
++ TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL, /* Source does not receive Ksv list in repeater mode */
++ TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE,
++ TMDL_HDMITX_HDCP_UNKNOWN_STATUS
++
++}tmdlHdmiTxHdcpStatus_t;
++
++
++/**
++ * \brief EDID information about sink latency
++ */
++typedef struct
++{
++ Bool latency_available;
++ Bool Ilatency_available;
++ UInt8 Edidvideo_latency;
++ UInt8 Edidaudio_latency;
++ UInt8 EdidIvideo_latency;
++ UInt8 EdidIaudio_latency;
++
++} tmdlHdmiTxEdidLatency_t;
++
++
++/**
++ * \brief Enum defining possible HotPlug status
++ */
++typedef enum
++{
++ TMDL_HDMITX_HOTPLUG_INACTIVE = 0, /**< Hotplug inactive */
++ TMDL_HDMITX_HOTPLUG_ACTIVE = 1, /**< Hotplug active */
++ TMDL_HDMITX_HOTPLUG_INVALID = 2 /**< Invalid Hotplug */
++} tmdlHdmiTxHotPlug_t;
++
++
++/**
++ * \brief Enum defining possible RxSense status
++ */
++typedef enum
++{
++ TMDL_HDMITX_RX_SENSE_INACTIVE = 0, /**< RxSense inactive */
++ TMDL_HDMITX_RX_SENSE_ACTIVE = 1, /**< RxSense active */
++ TMDL_HDMITX_RX_SENSE_INVALID = 2 /**< Invalid RxSense */
++} tmdlHdmiTxRxSense_t;
++
++
++/**
++ * \brief Enum listing all the types of extented colorimetries
++ */
++typedef enum
++{
++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601 = 0,
++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709 = 1,
++ TMDL_HDMITX_EXT_COLORIMETRY_SYCC601 = 2,
++ TMDL_HDMITX_EXT_COLORIMETRY_ADOBEYCC601 = 3,
++ TMDL_HDMITX_EXT_COLORIMETRY_ADOBERGB = 4,
++ TMDL_HDMITX_EXT_COLORIMETRY_INVALID = 5
++} tmdlHdmiTxExtColorimetry_t;
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITX_TYPES_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
++
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c
+new file mode 100755
+index 0000000..b80b9f2
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx.c
+@@ -0,0 +1,7166 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx.c
++ *
++ * \version Revision: 1
++ *
++ * \date Date: 10/08/07 10:00
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ History: tmdlHdmiTx.c
++ *
++ * ***************** Version 1 *****************
++ * User: J. Lamotte Date: 10/08/07 Time: 10:00
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++
++ \endverbatim
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#include "tmdlHdmiTx_IW.h"
++#include "tmdlHdmiTx.h"
++#include "tmdlHdmiTx_local.h"
++#include "tmdlHdmiTx_cfg.h"
++#include "tmbslHdmiTx_funcMapping.h"
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++/* Macro to avoid compilation warnings */
++#ifdef TMFL_OS_WINDOWS
++#define DUMMY_ACCESS(x) x
++#else
++#define DUMMY_ACCESS(x)
++#endif
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++
++
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/* Prototypes of internal functions */
++/* Task functions */
++#ifndef TMFL_NO_RTOS
++static void CommandTaskUnit0(void);
++static void HdcpTaskUnit0(void);
++#endif /* TMFL_NO_RTOS */
++
++/* Interrupt callback functions */
++static void dlHdmiTxHandleENCRYPT(tmInstance_t instance);
++static void dlHdmiTxHandleHPD(tmInstance_t instance);
++static void dlHdmiTxHandleT0(tmInstance_t instance);
++static void dlHdmiTxHandleBCAPS(tmInstance_t instance);
++static void dlHdmiTxHandleBSTATUS(tmInstance_t instance);
++static void dlHdmiTxHandleSHA_1(tmInstance_t instance);
++static void dlHdmiTxHandlePJ(tmInstance_t instance);
++static void dlHdmiTxHandleR0(tmInstance_t instance);
++static void dlHdmiTxHandleSW_INT(tmInstance_t instance);
++static void dlHdmiTxHandleRX_SENSE(tmInstance_t instance);
++static void dlHdmiTxHandleEDID_READ(tmInstance_t instance);
++static void dlHdmiTxHandleVS_RPT(tmInstance_t instance);
++
++/* Devlib internal color bar management functions */
++#ifndef NO_HDCP
++static void dlHdmiTxCheckColorBar(tmInstance_t instance);
++static void dlHdmiTxCheckHdcpColorBar(tmInstance_t instance);
++#endif
++
++#ifndef NO_HDCP
++static void dlHdmiTxFindHdcpSeed(tmInstance_t instance);
++#endif /* NO_HDCP */
++
++/* Set the state machine of device library */
++static void dlHdmiTxSetState
++(
++ tmInstance_t instance,
++ tmdlHdmiTxDriverState_t state
++);
++
++/* Get the event status (enable or disable) in order to known
++ if event should be signaled */
++static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++);
++
++/* Use by tmdlHdmiTxSetInputOutput in scaler mode */
++static Bool dlHdmiTxGetReflineRefpix
++(
++ tmdlHdmiTxVidFmt_t vinFmt,
++ tmdlHdmiTxVinMode_t vinMode,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ UInt8 syncIn,
++ tmdlHdmiTxPixRate_t pixRate,
++ UInt16 *pRefPix,
++ UInt16 *pRefLine,
++ UInt16 *pScRefPix,
++ UInt16 *pScRefLine,
++ Bool *pbVerified
++);
++
++/* Use by tmdlHdmiTxSetInputOutput to set AVI infoframe */
++static tmErrorCode_t dlHdmiTxSetVideoInfoframe
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode
++);
++
++/* Use to set AVI infoframe with raw data */
++static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe
++(
++ tmInstance_t instance,
++ tmdlHdmiTxAviIfData_t *pContentVif,
++ Bool enable
++);
++
++/* Calculate Checksum for info frame */
++static UInt8
++dlHdmiTxcalculateCheksumIF
++(
++ tmbslHdmiTxPktRawAvi_t *pData /* Pointer to checksum data */
++);
++
++/* IMPORTANT: The 3 functions define below should not be declared in static
++ in order to allow applicative API to call them. Those functions are not
++ in tmdlHdmiTx_Functions.h but are in tmdlHdmiTxCore.def */
++
++/* Get the device library state */
++tmdlHdmiTxDriverState_t dlHdmiTxGetState(tmInstance_t instance);
++
++/* Set pattern ON (Blue screen or color bar) */
++tmErrorCode_t dlHdmiTxSetTestPatternOn
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode,
++ tmdlHdmiTxTestPattern_t pattern
++);
++
++/* Set pattern OFF */
++tmErrorCode_t dlHdmiTxSetTestPatternOff
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode
++);
++
++/* Get DTD from BSL */
++static tmErrorCode_t dlHdmiTxEdidGetDTD
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ UInt8 maxDTDesc,
++ UInt8 *pWrittenDTDesc
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ Bool formatInterlaced
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio,
++ Bool formatInterlaced
++);
++
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio,
++ Bool formatInterlaced
++);
++
++static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio (
++ UInt16 HImageSize,
++ UInt16 VImageSize
++);
++
++#ifndef NO_HDCP
++static void dlHdmiTxCheckHdcpBksv
++(
++ tmInstance_t instance,
++ UInt8 * pHdcpBksvTested,
++ Bool * pbBksvSecure,
++ Bool bBigEndian
++);
++#endif
++
++/* Calculate table index according to video format value */
++static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt);
++
++extern tmErrorCode_t tmbslDebugWriteFakeRegPage( tmUnitSelect_t txUnit );
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++tmdlHdmiTxIWSemHandle_t dlHdmiTxItSemaphore[MAX_UNITS];
++
++/* Unit configuration structure (device library system configuration) */
++unitConfig_t unitTableTx[MAX_UNITS] =
++{
++ {
++ False,
++ False,
++ (tmdlHdmiTxHdcpOptions_t) HDCP_OPT_DEFAULT,
++ False,
++ False,
++ TMDL_HDMITX_DEVICE_UNKNOWN,
++ 0,
++ 0,
++ (tmdlHdmiTxIWTaskHandle_t) 0,
++ (tmdlHdmiTxIWQueueHandle_t) 0,
++ (tmdlHdmiTxIWTaskHandle_t) 0,
++ STATE_NOT_INITIALIZED,
++ (ptmdlHdmiTxCallback_t) 0,
++ {Null, 0,},
++ }
++};
++
++#ifndef TMFL_NO_RTOS
++
++tmdlHdmiTxIWFuncPtr_t commandTaskTableTx[MAX_UNITS] = {
++ CommandTaskUnit0
++ };
++
++tmdlHdmiTxIWFuncPtr_t hdcpTaskTableTx[MAX_UNITS] = {
++ HdcpTaskUnit0
++ };
++
++#endif /* TMFL_NO_RTOS */
++
++tmbslHdmiTxCallbackList_t callbackFuncTableTx;
++
++/* Device library configuration structure completed by dlHdmiTxGetConfig with
++ informations contained in config file */
++tmdlHdmiTxDriverConfigTable_t gtmdlHdmiTxDriverConfigTable[MAX_UNITS] = {
++ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, TMDL_HDMITX_PATTERN_OFF,0},
++};
++
++/* Video info (see instanceStatusInfoTx) */
++tmdlHdmiTxVideoInfo_t videoInfoListTx = {
++ False,
++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VINMODE_YUV422, TMDL_HDMITX_SYNCSRC_EXT_VS, TMDL_HDMITX_PIXRATE_SINGLE, TMDL_HDMITX_3D_NONE},
++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, TMDL_HDMITX_VOUTMODE_YUV422, TMDL_HDMITX_COLORDEPTH_24,TMDL_HDMITX_VQR_DEFAULT}
++};
++
++/* Audio info (see instanceStatusInfoTx) */
++tmdlHdmiTxAudioInfo_t audioInfoListTx = {
++ False,
++ {TMDL_HDMITX_AFMT_SPDIF, TMDL_HDMITX_AFS_48K,TMDL_HDMITX_I2SFOR_PHILIPS_L,TMDL_HDMITX_I2SQ_16BITS,TMDL_HDMITX_DSTRATE_SINGLE,0x00}
++};
++
++/* Event state (see instanceStatusInfoTx) */
++tmdlHdmiTxEventState_t eventStateListTx[EVENT_NB] = {
++ {TMDL_HDMITX_HDCP_ACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_HDCP_INACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_HPD_ACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_HPD_INACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_RX_KEYS_RECEIVED, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_RX_DEVICE_ACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_RX_DEVICE_INACTIVE, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_EDID_RECEIVED, TMDL_HDMITX_EVENT_DISABLED},
++ {TMDL_HDMITX_VS_RPT_RECEIVED, TMDL_HDMITX_EVENT_DISABLED}
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ ,{TMDL_HDMITX_B_STATUS, TMDL_HDMITX_EVENT_DISABLED}
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++};
++
++/* Color bars state (see instanceStatusInfoTx) */
++tmdlHdmiTxColBarState_t colorBarStateTx = {
++ False,
++ True,
++ True,
++ False,
++ False,
++ True,
++ False
++};
++
++tmdlHdmiTxGamutState_t gamutStateTx = {
++ False,
++ 0,
++ TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601,
++ False,
++ TMDL_HDMITX_YQR_LIMITED
++};
++
++
++/* Instance status (save the actual configuration) */
++instanceStatus_t instanceStatusInfoTx[MAX_UNITS] = {
++ {(ptmdlHdmiTxVideoInfo_t) &videoInfoListTx,
++ (ptmdlHdmiTxAudioInfo_t) &audioInfoListTx,
++ (ptmdlHdmiTxEventState_t) eventStateListTx,
++ (ptmdlHdmiTxColBarState_t) &colorBarStateTx,
++ (ptmdlHdmiTxGamutState_t) &gamutStateTx }
++};
++
++/* HDCP seed table, arranged as pairs of 16-bit integers: lookup value, seed value.
++ * If no table is programmed and if KEY_SEED in config file is null, HDCP will be disabled */
++#define SEED_TABLE_LEN 10
++static const UInt16 kSeedTable[SEED_TABLE_LEN][2] = {
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0},
++ {0, 0}
++};
++
++#ifndef NO_HDCP
++tmdlHdmiTxHdcpInfo_t hdcpInfoListTx[MAX_UNITS];
++#endif /* NO_HDCP */
++
++
++static Bool gI2CDebugAccessesEnabled = True; /* For debug purpose only, used to manage underlying I2C accessed */
++
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++static Bool gIgnoreNextSha1 = False;
++#endif /*HDMI_TX_REPEATER_ISR_MODE*/
++
++/*============================================================================*/
++/* FUNCTIONS */
++/*============================================================================*/
++
++/******************************************************************************
++ \brief Get the software version of the driver.
++
++ \param pSWVersion Pointer to the version structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetSWVersion
++(
++ tmSWVersion_t *pSWVersion
++)
++{
++ /* Check if SWVersion pointer is Null */
++ RETIF(pSWVersion == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Copy SW version */
++ pSWVersion->compatibilityNr = VERSION_COMPATIBILITY;
++ pSWVersion->majorVersionNr = VERSION_MAJOR;
++ pSWVersion->minorVersionNr = VERSION_MINOR;
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Get the number of available HDMI transmitters devices in the system.
++ A unit directly represents a physical device.
++
++ \param pUnitCount Pointer to the number of available units.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetNumberOfUnits
++(
++ UInt32 *pUnitCount
++)
++{
++ /* Check if UnitCount pointer is Null */
++ RETIF(pUnitCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Copy the maximum number of units */
++ *pUnitCount = MAX_UNITS;
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Get the capabilities of unit 0. Capabilities are stored into a
++ dedicated structure and are directly read from the HW device.
++
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetCapabilities
++(
++ tmdlHdmiTxCapabilities_t *pCapabilities
++)
++{
++ /* Directly call GetCapabilitiesM function for unit 0 and return the result */
++ return(tmdlHdmiTxGetCapabilitiesM((tmUnitSelect_t)0, pCapabilities));
++}
++
++/******************************************************************************
++ \brief Get the capabilities of a specific unit. Capabilities are stored
++ into a dedicated structure and are directly read from the HW
++ device.
++
++ \param unit Unit to be probed.
++ \param pCapabilities Pointer to the capabilities structure.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetCapabilitiesM
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxCapabilities_t *pCapabilities
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++ Bool featureSupported;
++
++ /* Check if unit number is in range */
++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER)
++
++ /* Check if Capalities pointer is Null */
++ RETIF(pCapabilities == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Device version */
++ pCapabilities->deviceVersion = unitTableTx[unit].deviceVersion ;
++
++ /* Retrieve the capabilities from the BSL layer */
++
++ /* HDCP support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)
++
++ pCapabilities->hdcp = featureSupported;
++
++ /* Scaler support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_SCALER, &featureSupported) ) != TM_OK, errCode)
++
++ pCapabilities->scaler = featureSupported;
++
++ /* Audio HBR support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_AUDIO_HBR, &featureSupported) ) != TM_OK, errCode)
++
++ pCapabilities->audioPacket.HBR = featureSupported;
++
++ /* Audio OBA support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_AUDIO_OBA, &featureSupported) ) != TM_OK, errCode)
++
++ pCapabilities->audioPacket.oneBitAudio = featureSupported;
++
++ /* Audio DST support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_AUDIO_DST, &featureSupported) ) != TM_OK, errCode)
++
++ pCapabilities->audioPacket.DST = featureSupported;
++
++ /* HDMI version 1.1 support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_HDMI_1_1, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_1;
++ }
++
++ /* HDMI version 1.2A support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_HDMI_1_2A, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_2a;
++ }
++
++ /* HDMI version 1.3 support */
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_HDMI_1_3A, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->hdmiVersion = TMDL_HDMITX_HDMI_VERSION_1_3a;
++ }
++
++ /* Deep Color support */
++ /* By default */
++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_24;
++
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_DEEP_COLOR_30, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_30;
++ }
++
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_DEEP_COLOR_36, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_36;
++ }
++
++ RETIF( (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_DEEP_COLOR_48, &featureSupported) ) != TM_OK, errCode)
++
++ if (featureSupported)
++ {
++ pCapabilities->colorDepth = TMDL_HDMITX_COLORDEPTH_48;
++ }
++
++ return errCode;
++}
++
++/******************************************************************************
++ \brief Open unit 0 of HdmiTx driver and provides the instance number to
++ the caller. Note that one unit of HdmiTx represents one physical
++ HDMI transmitter and that only one instance per unit can be opened.
++
++ \param pInstance Pointer to the variable that will receive the instance
++ identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the transmitter instance is not initialised
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already
++ initialised
++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable
++ with the internal device version code
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxOpen
++(
++ tmInstance_t *pInstance
++)
++{
++ /* Directly call OpenM function for unit 0 and return the result */
++ return(tmdlHdmiTxOpenM(pInstance, (tmUnitSelect_t)0));
++}
++
++/******************************************************************************
++ \brief Open a specific unit of HdmiTx driver and provides the instance
++ number to the caller. Note that one unit of HdmiTx represents one
++ physical HDMI transmitter and that only one instance per unit can be
++ opened. This function switches driver's state machine to
++ "initialized" state.
++
++ \param pInstance Pointer to the structure that will receive the instance
++ identifier.
++ \param unit Unit number to be opened.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the transmitter instance is not initialised
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_OWNED: the resource is already in use
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INIT_FAILED: the unit instance is already
++ initialised or something wrong happened at lower level.
++ - TMDL_ERR_DLHDMITX_NO_RESOURCES: the resource is not available
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: the unit is not initialized
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMBSL_ERR_HDMI_INIT_FAILED: the unit instance is already
++ initialised
++ - TMBSL_ERR_HDMI_COMPATIBILITY: the driver is not compatiable
++ with the internal device version code
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxOpenM
++(
++ tmInstance_t *pInstance,
++ tmUnitSelect_t unit
++)
++{
++ tmErrorCode_t errCode;
++ tmErrorCode_t errCodeSem;
++ UInt16 i;
++ UInt8 deviceVersion;
++ Bool featureSupported;
++
++ /* Check if unit number is in range */
++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER)
++
++ /* Check if Instance pointer is Null */
++ RETIF(pInstance == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Create the semaphore to protect variables modified under interruption */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreCreate(&dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCode)
++
++ /* Take the sempahore */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)
++
++ /* Check if unit is already instanciated */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ unitTableTx[unit].opened == True, TMDL_ERR_DLHDMITX_RESOURCE_OWNED)
++
++ /* Check the state */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ dlHdmiTxGetState(unit) != STATE_NOT_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Instanciate unit and return corresponding instance number */
++ /* Since HW unit are only instanciable once, instance = unit */
++ unitTableTx[unit].opened = True;
++ unitTableTx[unit].hdcpEnable = False;
++ unitTableTx[unit].repeaterEnable = False;
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_UNKNOWN;
++ unitTableTx[unit].simplayHd = False;
++ unitTableTx[unit].pCallback = Null;
++ unitTableTx[unit].revocationList.pList = Null;
++ unitTableTx[unit].revocationList.length = 0;
++
++ /* Recover the configuration of the device library */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ dlHdmiTxGetConfig(unit, &gtmdlHdmiTxDriverConfigTable[unit])!= TM_OK, TMDL_ERR_DLHDMITX_INIT_FAILED)
++
++#ifndef TMFL_NO_RTOS
++
++ /* Create message queue associated to this instance/unit */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ tmdlHdmiTxIWQueueCreate(gtmdlHdmiTxDriverConfigTable[unit].commandTaskQueueSize,
++ &(unitTableTx[unit].queueHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++
++ /* Create the command task associated to this instance/unit */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ tmdlHdmiTxIWTaskCreate(commandTaskTableTx[unit],
++ gtmdlHdmiTxDriverConfigTable[unit].commandTaskPriority,
++ gtmdlHdmiTxDriverConfigTable[unit].commandTaskStackSize,
++ &(unitTableTx[unit].commandTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ tmdlHdmiTxIWTaskStart(unitTableTx[unit].commandTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++
++ /* Create the hdcp check task associated to this instance/unit */
++#ifndef NO_HDCP
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ tmdlHdmiTxIWTaskCreate(hdcpTaskTableTx[unit],
++ gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskPriority,
++ gtmdlHdmiTxDriverConfigTable[unit].hdcpTaskStackSize,
++ &(unitTableTx[unit].hdcpTaskHandle)) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++#endif /* NO_HDCP */
++
++#endif /* TMFL_NO_RTOS */
++
++ *pInstance = (tmInstance_t)unit;
++
++#ifndef NO_HDCP
++ hdcpInfoListTx[unit].bKsvSecure = False;
++ hdcpInfoListTx[unit].hdcpKsvDevices = 0;
++ for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[unit].hdcpBksv[i] = 0; }
++ hdcpInfoListTx[unit].hdcpDeviceDepth = 0;
++#endif /* NO_HDCP */
++
++ /* Init the BSL */
++ /* Make sure all events are disabled */
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HDCP_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HDCP_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HPD_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_HPD_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_KEYS_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_DEVICE_ACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_RX_DEVICE_INACTIVE].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_EDID_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_VS_RPT_RECEIVED].status = TMDL_HDMITX_EVENT_DISABLED;
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ instanceStatusInfoTx[unit].pEventState[TMDL_HDMITX_B_STATUS].status = TMDL_HDMITX_EVENT_DISABLED;
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++ instanceStatusInfoTx[unit].pColBarState->disableColorBarOnR0 = False;
++ instanceStatusInfoTx[unit].pColBarState->hdcpColbarChange = False;
++ instanceStatusInfoTx[unit].pColBarState->hdcpEncryptOrT0 = True;
++ instanceStatusInfoTx[unit].pColBarState->hdcpSecureOrT0 = False;
++ instanceStatusInfoTx[unit].pColBarState->inOutFirstSetDone = False;
++ instanceStatusInfoTx[unit].pColBarState->colorBarOn = False;
++ instanceStatusInfoTx[unit].pColBarState->changeColorBarNow = False;
++
++ instanceStatusInfoTx[unit].pGamutState->gamutOn = False;
++ instanceStatusInfoTx[unit].pGamutState->gamutBufNum = 0; /* use buffer 0 by default */
++ instanceStatusInfoTx[unit].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601;
++ instanceStatusInfoTx[unit].pGamutState->extColOn = False;
++ instanceStatusInfoTx[unit].pGamutState->yccQR = TMDL_HDMITX_YQR_LIMITED;
++
++
++ instanceStatusInfoTx[unit].pAudioInfo->audioMuteState = False; /* Initially audio is not muted */
++
++
++
++ /* The funcCallback is not the same between BSL, so fill it dynamically */
++ for(i=0; i<HDMITX_CALLBACK_INT_NUM; i++)
++ {
++ callbackFuncTableTx.funcCallback[i] = Null;
++ }
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_ENCRYPT] = dlHdmiTxHandleENCRYPT;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_HPD] = dlHdmiTxHandleHPD;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_T0] = dlHdmiTxHandleT0;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_BCAPS] = dlHdmiTxHandleBCAPS;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_BSTATUS] = dlHdmiTxHandleBSTATUS;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_SHA_1] = dlHdmiTxHandleSHA_1;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_PJ] = dlHdmiTxHandlePJ;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_R0] = dlHdmiTxHandleR0;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_SW_INT] = dlHdmiTxHandleSW_INT;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_RX_SENSE] = dlHdmiTxHandleRX_SENSE;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_EDID_BLK_READ] = dlHdmiTxHandleEDID_READ;
++ callbackFuncTableTx.funcCallback[HDMITX_CALLBACK_INT_VS_RPT] = dlHdmiTxHandleVS_RPT;
++
++ /* Prepare static TDA9984 driver data as the compiler doesn't seem to */
++
++ tmbslHdmiTxHwStartup();
++ errCode = tmbslHdmiTxInit(*pInstance,
++ gtmdlHdmiTxDriverConfigTable[unit].i2cAddress,
++ gtmdlHdmiTxDriverConfigTable[unit].i2cWriteFunction,
++ gtmdlHdmiTxDriverConfigTable[unit].i2cReadFunction,
++ (ptmbslHdmiTxSysFuncEdid_t)0, /* Not used for TDA9984 */
++ (ptmbslHdmiTxSysFuncTimer_t)tmdlHdmiTxIWWait,
++ &callbackFuncTableTx,
++ False, /* Alternate EDID address not used */
++ (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[unit].pVideoInfo->videoInConfig.format,
++ (tmbslHdmiTxPixRate_t)instanceStatusInfoTx[unit].pVideoInfo->videoInConfig.pixelRate);
++ if (errCode != TM_OK)
++ {
++ /* Init failed */
++ tmbslHdmiTxDeinit(unit);
++
++ /* Release the sempahore */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)
++
++ return errCode;
++ }
++ else
++ {
++ /* Init passed, continue */
++
++ /* Start by forcing the TMDS ouputs off */
++ errCode = tmbslHdmiTxTmdsSetOutputs(unit,
++ HDMITX_TMDSOUT_FORCED0);
++ RETIF_SEM(dlHdmiTxItSemaphore[unit], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ (errCode = tmbslHdmiTxHwGetCapabilities(unit,
++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)
++
++#ifndef NO_HDCP
++ if (featureSupported == True)
++ {
++ dlHdmiTxFindHdcpSeed(unit);
++ }
++#endif /* NO_HDCP */
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ tmbslHdmiTxHdcpPowerDown(unit,True);
++#endif
++ /* Retrieve the hardware device version from the BSL layer */
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ (errCode = tmbslHdmiTxHwGetVersion(unit,&deviceVersion) ) \
++ != TM_OK, errCode);
++
++ /* Store the hardware device version in the global variable */
++ switch (deviceVersion)
++ {
++ case BSLHDMITX_TDA9984:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9984;
++ break;
++
++ case BSLHDMITX_TDA9989:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9989;
++ break;
++
++ case BSLHDMITX_TDA9981:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9981;
++ break;
++
++ case BSLHDMITX_TDA9983:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA9983;
++ break;
++
++ case BSLHDMITX_TDA19989:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19989;
++ break;
++
++ case BSLHDMITX_TDA19988:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_TDA19988;
++ break;
++
++ default:
++ unitTableTx[unit].deviceVersion = TMDL_HDMITX_DEVICE_UNKNOWN;
++ break;
++ }
++ }
++
++
++#ifndef TMFL_NO_RTOS
++ /* Start HDCP check task */
++
++#ifndef NO_HDCP
++ RETIF_SEM(dlHdmiTxItSemaphore[unit],
++ tmdlHdmiTxIWTaskStart(unitTableTx[unit].hdcpTaskHandle) != TM_OK, TMDL_ERR_DLHDMITX_NO_RESOURCES)
++#endif /* NO_HDCP */
++
++#endif /* TMFL_NO_RTOS */
++
++
++ /* Set the state machine to initialized */
++ dlHdmiTxSetState(unit, STATE_INITIALIZED);
++
++ /* Release the sempahore */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[unit]) ) != TM_OK, errCodeSem)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Close an instance of HdmiTx driver.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxClose
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check if unit corresponding to instance is opened */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)
++
++ /* Close instance */
++ unitTableTx[instance].opened = False;
++
++ /* Set the state machine */
++ dlHdmiTxSetState(instance, STATE_NOT_INITIALIZED);
++
++ /* Destroy resources allocated for this instance/unit */
++
++#ifndef TMFL_NO_RTOS
++
++#ifndef NO_HDCP
++ tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].hdcpTaskHandle);
++#endif /* NO_HDCP */
++
++ tmdlHdmiTxIWTaskDestroy(unitTableTx[instance].commandTaskHandle);
++ tmdlHdmiTxIWQueueDestroy(unitTableTx[instance].queueHandle);
++
++#endif /* TMFL_NO_RTOS */
++
++ /* Reset an instance of an HDMI transmitter */
++ tmbslHdmiTxDeinit(instance);
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Close the handle to the semaphore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreDestroy(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Set the power state of an instance of the HDMI transmitter.
++
++ \param instance Instance identifier.
++ \param powerState Power state to set.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t powerState
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9984)
++ {
++ if (powerState == tmPowerSuspend)
++ {
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++ }
++ }
++
++
++
++
++ /* Switch off HDCP */
++ if ( ((powerState == tmPowerOff) && (unitTableTx[instance].hdcpEnable == True))
++ || ((powerState == tmPowerStandby) && (unitTableTx[instance].hdcpEnable == True))
++ || ((powerState == tmPowerSuspend) && (unitTableTx[instance].hdcpEnable == True))
++ )
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ /* Switch off HDCP */
++ RETIF( (errCode = tmdlHdmiTxSetHdcp(instance, False) ) != TM_OK, errCode)
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ }
++
++
++ /* TDA9989, TDA19989 and TDA19988 only */
++ if ( (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA9989)
++ ||
++ (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19989)
++ ||
++ (unitTableTx[instance].deviceVersion == TMDL_HDMITX_DEVICE_TDA19988))
++
++ {
++ if ((powerState != tmPowerOn) && (powerState != tmPowerSuspend)) {
++ dlHdmiTxSetState(instance, STATE_INITIALIZED);
++ }
++
++ if ((powerState == tmPowerOn) && (unitTableTx[instance].simplayHd == True)) {
++
++ instanceStatusInfoTx[0].pColBarState->disableColorBarOnR0 = False;
++ instanceStatusInfoTx[0].pColBarState->hdcpColbarChange = False;
++ instanceStatusInfoTx[0].pColBarState->hdcpEncryptOrT0 = True;
++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;
++ instanceStatusInfoTx[0].pColBarState->inOutFirstSetDone = False;
++ instanceStatusInfoTx[0].pColBarState->colorBarOn = True;
++ instanceStatusInfoTx[0].pColBarState->changeColorBarNow = True;
++
++ }
++
++ }
++
++ /* Set the power state of the transmitter */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPowerSetState(instance,
++ powerState) ) != TM_OK, errCode)
++
++ /* Get Hot Plug status */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHotPlugGetStatus(instance,
++ &hpdStatus,False) ) != TM_OK, errCode)
++
++ if (powerState == tmPowerOn)
++ {
++ if ((hpdStatus == HDMITX_HOTPLUG_ACTIVE) && (dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE))
++ {
++ /* Yes: Wait for DDC line to settle before reading EDID */
++ tmbslHdmiTxSysTimerWait(instance,
++ 500); /* ms */
++
++ /* Request EDID read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidRequestBlockData(instance,
++ unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7),
++ (Int)(unitTableTx[instance].edidBufferSize)) ) != TM_OK, errCode)
++ }
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Get the power state of an instance of the HDMI transmitter.
++
++ \param instance Instance identifier.
++ \param pPowerState Pointer to the power state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetPowerState
++(
++ tmInstance_t instance,
++ tmPowerState_t *pPowerState
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if PowerState pointer is Null */
++ RETIF(pPowerState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Get the power state of the transmitter */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPowerGetState(instance,
++ pPowerState) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Set the configuration of instance attributes. This function is
++ required by DVP architecture rules but actually does nothing in this
++ driver.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxInstanceConfig
++(
++ tmInstance_t instance
++)
++{
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Setup the instance with its configuration parameters. This function
++ allows basic instance configuration like enabling HDCP, choosing
++ HDCP encryption mode or enabling HDCP repeater mode.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure containing all setup parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxInstanceSetup
++(
++ tmInstance_t instance,
++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo
++)
++{
++ tmErrorCode_t errCode;
++#ifndef NO_HDCP
++ UInt16 i;
++#endif
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if SetupInfo pointer is NULL */
++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check if unit corresponding to instance is opened */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)
++
++ /* Check the state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ unitTableTx[instance].repeaterEnable = pSetupInfo->repeaterEnable;
++ unitTableTx[instance].simplayHd = pSetupInfo->simplayHd;
++ unitTableTx[instance].pEdidBuffer = pSetupInfo->pEdidBuffer;
++ unitTableTx[instance].edidBufferSize = pSetupInfo->edidBufferSize;
++
++#ifndef NO_HDCP
++ /* Reset HDCP DevLib data */
++ hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED;
++ hdcpInfoListTx[instance].hdcpErrorState = 0;
++ hdcpInfoListTx[instance].hdcpKsvDevices = 0;
++ hdcpInfoListTx[instance].bKsvSecure = False;
++ for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[instance].hdcpBksv[i] = 0; }
++ hdcpInfoListTx[instance].hdcpDeviceDepth = 0;
++
++ hdcpInfoListTx[instance].hdcpMaxCascExceeded = False;
++ hdcpInfoListTx[instance].hdcpMaxDevsExceeded = False;
++#endif /* NO_HDCP */
++
++ /* Set state machine to Unplugged */
++ dlHdmiTxSetState(instance, STATE_UNPLUGGED);
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Get instance setup parameters.
++
++ \param instance Instance identifier.
++ \param pSetupInfo Pointer to the structure that will receive setup
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetInstanceSetup
++(
++ tmInstance_t instance,
++ tmdlHdmiTxInstanceSetupInfo_t *pSetupInfo
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if SetupInfo pointer is NULL */
++ RETIF(pSetupInfo == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check if unit corresponding to instance is opened */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)
++
++ pSetupInfo->simplayHd = unitTableTx[instance].simplayHd;
++ pSetupInfo->repeaterEnable = unitTableTx[instance].repeaterEnable;
++ /* JL, TODO */
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Make device library handle an incoming interrupt. This function is
++ used by application to tell the device library that the hardware
++ sent an interrupt.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_FULL: the queue is full
++
++ ******************************************************************************/
++tmErrorCode_t tmdlHdmiTxHandleInterrupt
++(
++ tmInstance_t instance
++)
++{
++#ifndef TMFL_NO_RTOS
++ tmErrorCode_t errCode;
++ UInt8 message = 0;
++#else
++ tmErrorCode_t err = TM_OK;
++#endif /* TMFL_NO_RTOS */
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++#ifndef TMFL_NO_RTOS
++ RETIF( (errCode = tmdlHdmiTxIWQueueSend(unitTableTx[instance].queueHandle, message)) != TM_OK, errCode)
++
++ /* Disable interrupts for Tx until the callbacks have been done by the command task */
++ switch(instance)
++ {
++ case INSTANCE_0:
++ tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_1);
++ break;
++ case INSTANCE_1:
++ tmdlHdmiTxIWDisableInterrupts(TMDL_HDMI_IW_TX_2);
++ break;
++ default:
++ return TMDL_ERR_DLHDMITX_BAD_INSTANCE;
++ }
++#else
++
++ /* Clear T0 flag before polling for interrupts */
++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;
++
++ if (gI2CDebugAccessesEnabled == True)
++ {
++
++ err = tmbslHdmiTxHwHandleInterrupt(0);
++
++ if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ))
++ {
++
++ unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1);
++ }
++
++ }/* (gI2CDebugAccessesEnabled == True) */
++
++
++#endif /* TMFL_NO_RTOS */
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Register event callbacks. Only one callback is registered through
++ this API. This callback will received the type of event that
++ occured throug a dedicated parameter and will be called as many
++ times as there is pending events.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pCallback Pointer to the callback function that will handle events
++ from the devlib.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED: the caller does not own
++ the resource
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxRegisterCallbacks
++(
++ tmInstance_t instance,
++ ptmdlHdmiTxCallback_t pCallback
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check if unit corresponding to instance is opened */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ unitTableTx[instance].opened == False, TMDL_ERR_DLHDMITX_RESOURCE_NOT_OWNED)
++
++ /* Check if instance state is correct */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_INITIALIZED, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Store callback pointers */
++ unitTableTx[instance].pCallback = pCallback;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief This function allows enabling a specific event. By default, all
++ events are disabled, except input lock.
++
++ \param instance Instance identifier.
++ \param event Event to enable.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxEnableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if the event exists */
++ RETIF_BADPARAM(event >= EVENT_NB)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Protect the access to this ressource */
++ instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_ENABLED;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief This function allows disabling a specific event. By default, all
++ events are disabled, except input lock.
++
++ \param instance Instance identifier.
++ \param event Event to disable.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDisableEvent
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if the event exists */
++ RETIF_BADPARAM(event >= EVENT_NB)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Protect the access to this ressource */
++ instanceStatusInfoTx[instance].pEventState[event].status = TMDL_HDMITX_EVENT_DISABLED;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Get specifications of a given video format. Application can use
++ this function to retreives all specifications (frequencies,
++ resolution, etc.) of a given IA/CEA 861-D video format.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param resolutionID ID of the resolution to retrieve specs from.
++ \param pResolutionSpecs Pointer to the structure receiving specs.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetVideoFormatSpecs
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t resolutionID,
++ tmdlHdmiTxVidFmtSpecs_t *pResolutionSpecs
++)
++{
++ UInt8 i;
++ Bool find = False;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if ResolutionSpecs pointer is Null */
++ RETIF(pResolutionSpecs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ for (i = 0; i < RESOLUTION_NB; i++)
++ {
++ if(resolutionID == gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].resolutionID)
++ {
++ find = True;
++ pResolutionSpecs->height = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].height;
++ pResolutionSpecs->width = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].width;
++ pResolutionSpecs->interlaced = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].interlaced;
++ pResolutionSpecs->vfrequency = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].vfrequency;
++ pResolutionSpecs->aspectRatio = gtmdlHdmiTxDriverConfigTable[instance].pResolutionInfo[i].aspectRatio;
++
++ /* Transformation of 2D-interlaced formats into 3DFP-progressif formats */
++ if((instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D == TMDL_HDMITX_3D_FRAME_PACKING)
++ && pResolutionSpecs->interlaced && ((resolutionID == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz)
++ || (resolutionID == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz)))
++ {
++ pResolutionSpecs->interlaced = False;
++ if(pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_50Hz)
++ {
++ pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_25Hz;
++ }
++ else if((pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_60Hz) || (pResolutionSpecs->vfrequency == TMDL_HDMITX_VFREQ_59Hz))
++ {
++ pResolutionSpecs->vfrequency = TMDL_HDMITX_VFREQ_30Hz;
++ }
++ }
++
++ break;
++ }
++ }
++
++ /* Resolution not found in table */
++ RETIF(find == False, TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Configures all input and output parameters : format, modes, rates,
++ etc. This is the main configuration function of the driver. Here
++ are transmitted all crucial input and output parameters of the
++ device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param videoInputConfig Configuration of the input video.
++ \param videoOutputConfig Configuration of the output video.
++ \param audioInputConfig Configuration of the input audio.
++ \param sinkType Type of sink connected to the output of the Tx.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetInputOutput
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVideoInConfig_t videoInputConfig,
++ tmdlHdmiTxVideoOutConfig_t videoOutputConfig,
++ tmdlHdmiTxAudioInConfig_t audioInputConfig,
++ tmdlHdmiTxSinkType_t sinkType
++)
++{
++ tmErrorCode_t errCode;
++ UInt8 pixRepeat; /* Pixel repetition */
++ tmbslHdmiTxVoutDbits_t pathBits; /* Data path bit width */
++ tmbslHdmiTxPixEdge_t pixelEdge; /* Pixel sampling edge */
++ tmbslHdmiTxVsMeth_t syncMethod; /* Sync method */
++ tmbslHdmiTxPixTogl_t toggle; /* Toggling */
++ UInt8 syncIn; /* Embedded or external */
++ tmbslHdmiTxPixSubpkt_t spSync; /* Subpacket sync */
++ tmbslHdmiTxBlnkSrc_t blankit; /* Blanking */
++ tmbslHdmiTxPixRate_t pixRateSingleDouble; /* HDMITX_PIXRATE_SINGLE */
++ UInt16 uRefPix; /* REFPIX for output */
++ UInt16 uRefLine; /* REFLINE for output */
++ UInt16 uScRefPix=0; /* REFPIX for scaler */
++ UInt16 uScRefLine=0; /* REFLINE for scaler */
++ Bool bVerified; /* Scaler setting verified */
++ tmbslHdmiTxTopSel_t topSel; /* Adjustment for interlaced output */
++ tmbslHdmiTxHPhases_t phasesH; /* Horizontal phase */
++ tmbslHdmiTxVsOnce_t once; /* Line/pixel counters sync */
++ tmbslHdmiTxScaMode_t scalerMode; /* Current scaler mode */
++ Bool OBASupported; /* OBA supported or not */
++ Bool DSTSupported; /* DST supported or not */
++ Bool HBRSupported; /* HBR supporeted or not */
++
++ UInt8 *pSwapTable = Null; /* Initialized after (depend on video mode used) */
++ UInt8 *pMirrorTable = Null; /* Initialized after (depend on video mode used) */
++#ifdef TMFL_RGB_DDR_12BITS
++ UInt8 *pMux = Null; /* Initialized after (depend on video mode used) */
++#endif
++ UInt8 *pEnaVideoPortTable = Null; /* Initialized after (depend on video mode used) */
++ UInt8 *pGndVideoPortTable = Null; /* Initialized after (depend on video mode used) */
++ tmdlHdmiTxVidFmt_t vinFmtIndex; /* index in table kVfmtToShortFmt_TV */
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Update the instance status information */
++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.format = videoInputConfig.format;
++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.mode = videoInputConfig.mode;
++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.syncSource = videoInputConfig.syncSource;
++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.pixelRate = videoInputConfig.pixelRate;
++ instanceStatusInfoTx[instance].pVideoInfo->videoInConfig.structure3D = videoInputConfig.structure3D;
++
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format = videoOutputConfig.format;
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode = videoOutputConfig.mode;
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.colorDepth = videoOutputConfig.colorDepth;
++
++ /* TODO */
++ /*instanceStatusInfoTx[instance].pVideoInfo->videoMuteState = */
++
++ /* Audio OBA support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode)
++
++ /* Audio DST support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode)
++
++ /* Audio HBR support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode)
++
++ /* Test if audio input format is supported */
++ if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) ||
++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) ||
++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) )
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++ }
++
++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.format = audioInputConfig.format;
++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sFormat = audioInputConfig.i2sFormat;
++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.i2sQualifier = audioInputConfig.i2sQualifier;
++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.rate = audioInputConfig.rate;
++ instanceStatusInfoTx[instance].pAudioInfo->audioInCfg.channelAllocation = audioInputConfig.channelAllocation;
++
++
++ if (sinkType == TMDL_HDMITX_SINK_EDID)
++ {
++ /* Change sink type with the currently defined in EDID */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetSinkType(instance,
++ (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode)
++ }
++
++ /* forbid format with pixel repetition in DVI */
++ if (sinkType == TMDL_HDMITX_SINK_DVI)
++ {
++ if(((videoOutputConfig.format >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_15_1440x480p_60Hz))
++ || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (videoOutputConfig.format <= TMDL_HDMITX_VFMT_30_1440x576p_50Hz))
++ || ((videoOutputConfig.format >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz)&& (videoOutputConfig.format <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz))
++ )
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER;
++ }
++ }
++
++ /* Set color depth according to output config, transmitter termination is disable */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxSetColorDepth(instance,
++ (tmbslHdmiTxColorDepth)(videoOutputConfig.colorDepth), False) ) != TM_OK, errCode)
++
++ /* Set the TMDS outputs to a forced state */
++ errCode = tmbslHdmiTxTmdsSetOutputs(instance,
++ HDMITX_TMDSOUT_FORCED0);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)
++
++ /* Fine-tune the TMDS serializer */
++ errCode = tmbslHdmiTxTmdsSetSerializer(instance,
++ 4, 8);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)
++
++ /* Set video output configuration */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoOutSetConfig(instance,
++ (tmbslHdmiTxSinkType_t)sinkType, (tmbslHdmiTxVoutMode_t)videoOutputConfig.mode, HDMITX_VOUT_PREFIL_OFF,
++ HDMITX_VOUT_YUV_BLNK_16, HDMITX_VOUT_QRANGE_FS) ) != TM_OK, errCode)
++
++ /* Set default config */
++ pixRepeat = HDMITX_PIXREP_DEFAULT;
++ pathBits = HDMITX_VOUT_DBITS_12;
++ pixelEdge = HDMITX_PIXEDGE_CLK_POS;
++ syncMethod = HDMITX_VSMETH_V_H;
++ toggle = HDMITX_PIXTOGL_ENABLE;
++
++ /* Set sync details */
++ if (videoInputConfig.syncSource == TMDL_HDMITX_SYNCSRC_EMBEDDED)
++ {
++ /* Embedded sync */
++ syncIn = EMB;
++ spSync = HDMITX_PIXSUBPKT_SYNC_HEMB;
++ blankit = HDMITX_BLNKSRC_VS_HEMB_VEMB;
++ syncMethod = HDMITX_VSMETH_V_XDE;
++ }
++ else
++ {
++ /* External sync */
++ syncIn = EXT;
++
++
++ if (gtmdlHdmiTxDriverConfigTable[instance].dataEnableSignalAvailable == 1)
++ {
++ /* DE is available */
++ spSync = HDMITX_PIXSUBPKT_SYNC_DE;
++ }
++ else
++ {
++ /* DE is NOT available */
++ spSync = HDMITX_PIXSUBPKT_SYNC_HS;
++ }
++
++
++
++ blankit = HDMITX_BLNKSRC_NOT_DE;
++ }
++
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /* by default, mux is not used */
++ pMux = &gtmdlHdmiTxDriverConfigTable[instance].pNoMux[0];
++#endif
++
++ /* Port swap table */
++ switch(videoInputConfig.mode)
++ {
++ case TMDL_HDMITX_VINMODE_CCIR656:
++ pathBits = HDMITX_VOUT_DBITS_8;
++ pixelEdge = HDMITX_PIXEDGE_CLK_NEG;
++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableCCIR656;
++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableCCIR656;
++#ifdef TMFL_RGB_DDR_12BITS
++ pMux = &gtmdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0];
++#endif
++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortCCIR656;
++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortCCIR656;
++ break;
++
++ case TMDL_HDMITX_VINMODE_RGB444:
++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB444;
++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB444;
++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB444;
++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB444;
++ break;
++
++ case TMDL_HDMITX_VINMODE_YUV444:
++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV444;
++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV444;
++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV444;
++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV444;
++ break;
++
++ case TMDL_HDMITX_VINMODE_YUV422:
++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableYUV422;
++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableYUV422;
++#ifdef TMFL_RGB_DDR_12BITS
++ pMux = &gtmdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0];
++#endif
++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortYUV422;
++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortYUV422;
++ break;
++
++#ifdef TMFL_RGB_DDR_12BITS
++ case TMDL_HDMITX_VINMODE_RGB_DDR_12BITS:
++ pSwapTable = gtmdlHdmiTxDriverConfigTable[instance].pSwapTableRGB_DDR_12bits;
++ pMirrorTable = gtmdlHdmiTxDriverConfigTable[instance].pMirrorTableRGB_DDR_12bits;
++ pMux = &gtmdlHdmiTxDriverConfigTable[instance].pMux_RGB_DDR_12bits[0];
++ pEnaVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pEnableVideoPortRGB_DDR_12bits;
++ pGndVideoPortTable = gtmdlHdmiTxDriverConfigTable[instance].pGroundVideoPortRGB_DDR_12bits;
++ break;
++#endif
++ default:
++ break;
++ }
++
++ /* Set the audio and video input port configuration */
++ errCode = tmbslHdmiTxSetVideoPortConfig(instance, pEnaVideoPortTable, pGndVideoPortTable);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);
++
++#ifdef TMFL_RGB_DDR_12BITS
++ errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable, pMux);
++#else
++ errCode = tmbslHdmiTxVideoInSetMapping(instance, pSwapTable, pMirrorTable);
++#endif
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);
++
++ /* Set fine image position */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoInSetFine(instance, spSync, HDMITX_PIXTOGL_NO_ACTION) ) != TM_OK, errCode);
++
++ /* Set input blanking */
++ errCode = tmbslHdmiTxVideoInSetBlanking(instance, blankit, HDMITX_BLNKCODE_ALL_0);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode);
++
++ /* Configure video input options and control the upsampler */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoInSetConfig(instance,
++ (tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format,
++ (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D, pixelEdge,
++ (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate, HDMITX_UPSAMPLE_AUTO) ) != TM_OK, errCode);
++
++
++ /* Set input ouput - may give NOT_SUPPORTED error */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoSetInOut(instance, (tmbslHdmiTxVidFmt_t)videoInputConfig.format,
++ (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D,
++ HDMITX_SCAMODE_AUTO, (tmbslHdmiTxVidFmt_t)videoOutputConfig.format,
++ pixRepeat, HDMITX_MATMODE_AUTO, pathBits, (tmbslHdmiTxVQR_t) videoOutputConfig.dviVqr) ) != TM_OK, errCode);
++
++
++ /* Only set audio for HDMI, not DVI */
++ if (sinkType == TMDL_HDMITX_SINK_HDMI)
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ /* Set audio parameters */
++ RETIF( (errCode = tmdlHdmiTxSetAudioInput(instance, audioInputConfig, sinkType) ) != TM_OK, errCode)
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ }
++
++ /* Output fine adjustment */
++ pixRateSingleDouble = (tmbslHdmiTxPixRate_t)videoInputConfig.pixelRate;
++ if (videoInputConfig.pixelRate == HDMITX_PIXRATE_SINGLE_REPEATED)
++ {
++ pixRateSingleDouble = HDMITX_PIXRATE_SINGLE;
++ }
++
++
++ if ((videoInputConfig.structure3D != HDMITX_3D_FRAME_PACKING) &&
++ dlHdmiTxGetReflineRefpix(videoInputConfig.format, videoInputConfig.mode, videoOutputConfig.format,
++ syncIn, (tmdlHdmiTxPixRate_t)pixRateSingleDouble, &uRefPix, &uRefLine,
++ &uScRefPix, &uScRefLine, &bVerified) > 0)
++ {
++ /* From 720p50/60 or 1080i50/60 up-scaling to 1080p50/60, when external sync,
++ toggleV, toggleH and toggleX need to be set to 0 */
++ if (syncIn == EXT)
++ {
++ switch (videoInputConfig.format)
++ {
++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz:
++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz:
++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz:
++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz:
++ if ( (videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz)
++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz) )
++ {
++ toggle = HDMITX_PIXTOGL_NO_ACTION;
++ }
++ break;
++ default:
++ toggle = HDMITX_PIXTOGL_ENABLE;
++ break;
++ }
++ }
++
++ /* Combination found in table for scaler: configure input manually */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoInSetSyncManual(instance,
++ (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, syncMethod, toggle, toggle, toggle, uRefPix, uRefLine) ) != TM_OK, errCode)
++ }
++ else
++ {
++ /* Not found so assume non-scaler and auto-configure input */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoInSetSyncAuto(instance,
++ (tmbslHdmiTxSyncSource_t)videoInputConfig.syncSource, (tmbslHdmiTxVidFmt_t)videoInputConfig.format,
++ (tmbslHdmiTxVinMode_t)videoInputConfig.mode, (tmbslHdmiTx3DStructure_t)videoInputConfig.structure3D)) != TM_OK, errCode)
++ }
++
++ /* Only set infoframes for HDMI, not DVI */
++ if (sinkType == TMDL_HDMITX_SINK_HDMI)
++ {
++ /* Set avi infoframe */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = dlHdmiTxSetVideoInfoframe(instance, videoOutputConfig.format, videoOutputConfig.mode) ) != TM_OK,
++ errCode)
++ }
++
++ errCode = tmbslHdmiTxScalerGetMode(instance,
++ &scalerMode);
++
++ /* Ignore scaler TMBSL_ERR_HDMI_NOT_SUPPORTED error */
++ if ((errCode == TM_OK) && (scalerMode == HDMITX_SCAMODE_ON))
++ {
++ /* Enable scaler mode */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerInDisable(instance,
++ False) ) != TM_OK, errCode)
++
++ /* Correction to interlace */
++ topSel = HDMITX_TOPSEL_INTERNAL;
++ if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_05_1920x1080i_60Hz)
++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_20_1920x1080i_50Hz))
++ {
++ /* video input format is range-checked by tmbslHdmiTxVideoSetInOut above */
++ vinFmtIndex = dlHdmiTxCalcVidFmtIndex(videoInputConfig.format);
++ if ((kVfmtToShortFmt_TV[vinFmtIndex] == TV_480p_60Hz)
++ || (kVfmtToShortFmt_TV[vinFmtIndex] == TV_576p_50Hz))
++ {
++ /* Correct for 1080i output for p->i conversion only */
++ topSel = HDMITX_TOPSEL_VRF;
++ }
++ }
++
++ /* Set scaler field positions */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerSetFieldOrder(instance,
++ HDMITX_INTEXT_NO_CHANGE, HDMITX_INTEXT_NO_CHANGE, topSel, HDMITX_TOPTGL_NO_CHANGE) ) != TM_OK, errCode)
++
++ /* Scaler fine adjustment */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerSetFine(instance,
++ uScRefPix, uScRefLine) ) != TM_OK, errCode)
++
++ if ((videoOutputConfig.format == TMDL_HDMITX_VFMT_16_1920x1080p_60Hz)
++ || (videoOutputConfig.format == TMDL_HDMITX_VFMT_31_1920x1080p_50Hz))
++ {
++ phasesH = HDMITX_H_PHASES_16;
++ }
++ else
++ {
++ phasesH = HDMITX_H_PHASES_15;
++ }
++
++ /* Set scaler phase */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerSetPhase(instance,
++ phasesH) ) != TM_OK, errCode)
++
++ /* Set scaler latency */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerSetLatency(instance,
++ 0x22) ) != TM_OK, errCode)
++
++ /* Set scaler synchronisation option */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxScalerSetSync(instance,
++ syncMethod, HDMITX_VSONCE_EACH_FRAME) ) != TM_OK, errCode)
++
++ /* With scaler, use Only Once setting for tmbslHdmiTxVideoOutSetSync */
++ once = HDMITX_VSONCE_ONCE;
++ }
++ else
++ {
++ once = HDMITX_VSONCE_EACH_FRAME;
++ }
++
++ /* Set video synchronisation */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxVideoOutSetSync(instance,
++ HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL, HDMITX_VSSRC_INTERNAL,
++ HDMITX_VSTGL_TABLE, once) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone = True;
++
++ /* Test if pattern is already on */
++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True)
++ {
++ /* If pattern is On, apply new settings */
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
++ }
++
++ return TM_OK;
++}
++
++/*****************************************************************************/
++/**
++ \brief Configures audio input parameters : format, rate, etc.
++ This function is similar to tmdlHdmiTxSetInputOutput except that
++ video is not reconfigured.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param audioInputConfig Configuration of the input audio.
++ \param sinkType Type of sink connected to the output of the Tx.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioInput
++(
++ tmInstance_t instance,
++ tmdlHdmiTxAudioInConfig_t audioInputConfig,
++ tmdlHdmiTxSinkType_t sinkType
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiTxVidFmtSpecs_t resolutionSpecs; /* Used to convert video format to video frequency */
++ UInt8 layout; /* 0 or 1 */
++ UInt8 aifChannelCountCode = 0; /* audio info frame channels */
++ tmbslHdmiTxVfreq_t vOutFreq; /* Vertical output frequency */
++ tmbslHdmiTxctsRef_t ctsRef; /* CTS ref source */
++ UInt16 uCtsX; /* CtsX value */
++ tmbslHdmiTxPktAif_t pktAif; /* Audio infoframe packet */
++ Bool OBASupported; /* OBA supported or not */
++ Bool DSTSupported; /* DST supported or not */
++ Bool HBRSupported; /* HBR supporeted or not */
++ UInt8 *pEnaAudioPortCfg;
++ UInt8 *pGndAudioPortCfg;
++ UInt8 *pEnaAudioClockPortCfg;
++ UInt8 *pGndAudioClockPortCfg;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the semaphore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Audio OBA support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_OBA, &OBASupported) ) != TM_OK, errCode)
++
++ /* Audio DST support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_DST, &DSTSupported) ) != TM_OK, errCode)
++
++ /* Audio HBR support */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_AUDIO_HBR, &HBRSupported) ) != TM_OK, errCode)
++
++ /* Test if audio input format is supported */
++ if ( ((audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) && (OBASupported == False)) ||
++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_DST) && (DSTSupported == False)) ||
++ ((audioInputConfig.format == TMDL_HDMITX_AFMT_HBR) && (HBRSupported == False)) )
++ {
++ /* Release the semaphore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++ }
++
++ if (sinkType == TMDL_HDMITX_SINK_EDID)
++ {
++ /* Change sink type with the currently defined in EDID */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetSinkType(instance,
++ (tmbslHdmiTxSinkType_t *)&sinkType) ) != TM_OK, errCode)
++ }
++
++ if (sinkType == TMDL_HDMITX_SINK_HDMI)
++ {
++ /* Set audio layout */
++ layout = 1;
++ if (audioInputConfig.channelAllocation == 0x00) {
++ layout = 0;
++ }
++ aifChannelCountCode = kChanAllocChanNum[audioInputConfig.channelAllocation] - 1;
++
++ /* Port audio configuration */
++ switch(audioInputConfig.format)
++ {
++ case TMDL_HDMITX_AFMT_SPDIF:
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortSPDIF;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortSPDIF;
++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortSPDIF;
++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortSPDIF;
++ break;
++
++ case TMDL_HDMITX_AFMT_I2S:
++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortI2S;
++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortI2S;
++
++ if(audioInputConfig.channelAllocation >= 1 ) /* For Multi channels */
++ {
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S8C;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S8C;
++ }
++ else
++ {
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortI2S;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortI2S;
++ }
++ break;
++
++ case TMDL_HDMITX_AFMT_OBA:
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortOBA;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortOBA;
++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortOBA;
++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortOBA;
++ break;
++
++ case TMDL_HDMITX_AFMT_DST:
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortDST;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortDST;
++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortDST;
++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortDST;
++ break;
++
++ case TMDL_HDMITX_AFMT_HBR:
++ pEnaAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioPortHBR;
++ pGndAudioPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioPortHBR;
++ pEnaAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pEnableAudioClockPortHBR;
++ pGndAudioClockPortCfg = gtmdlHdmiTxDriverConfigTable[instance].pGroundAudioClockPortHBR;
++ break;
++
++ default:
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER;
++ }
++
++ errCode = tmbslHdmiTxSetAudioPortConfig(instance,
++ pEnaAudioPortCfg, pGndAudioPortCfg);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)
++
++ errCode = tmbslHdmiTxSetAudioClockPortConfig(instance,
++ pEnaAudioClockPortCfg, pGndAudioClockPortCfg);
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode != TM_OK) && (errCode != TMBSL_ERR_HDMI_NOT_SUPPORTED), errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioInSetConfig(instance,
++ (tmbslHdmiTxaFmt_t)audioInputConfig.format, (tmbslHdmiTxI2sFor_t)audioInputConfig.i2sFormat,
++ audioInputConfig.channelAllocation, HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE, HDMITX_SWAPDSD_NO_CHANGE,
++ layout, HDMITX_LATENCY_CURRENT, (tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode)
++
++ /* Find output vertical frequency from output format */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ &resolutionSpecs) ) != TM_OK, errCode)
++ vOutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency;
++
++ if ((audioInputConfig.format == TMDL_HDMITX_AFMT_SPDIF)
++ || (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA))
++ {
++ ctsRef = HDMITX_CTSREF_FS64SPDIF;
++ uCtsX = HDMITX_CTSX_64;
++ }
++ else /* I2S */
++ {
++ ctsRef = HDMITX_CTSREF_ACLK;
++ if (audioInputConfig.i2sQualifier == TMDL_HDMITX_I2SQ_32BITS)
++ {
++ uCtsX = HDMITX_CTSX_64;
++ }
++ else
++ {
++ uCtsX = HDMITX_CTSX_32;
++ }
++ }
++
++ /* Set the Clock Time Stamp generator in HDMI mode only */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioInSetCts(instance,
++ ctsRef, (tmbslHdmiTxafs_t)audioInputConfig.rate, (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ vOutFreq, HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX, HDMITX_CTSMTS_USE_CTSX,
++ (tmbslHdmiTxDstRate_t)audioInputConfig.dstRate) ) != TM_OK, errCode)
++
++ /* Set Channel Status registers
++ No need to call tmbslTDA9984AudioOutSetChanStatusMapping, since default Byte 2
++ values of "Do not take into account" are adequate */
++
++
++ if (audioInputConfig.format != TMDL_HDMITX_AFMT_SPDIF) /* channel status automatically copied from SPDIF*/
++ {
++
++ if (audioInputConfig.format != TMDL_HDMITX_AFMT_HBR) {
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance,
++ (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification,
++ (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo,
++ (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo,
++ audioInputConfig.channelStatus.categoryCode,
++ (tmbslHdmiTxafs_t)audioInputConfig.rate,
++ (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy,
++ (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength,
++ (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength,
++ (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode)
++ }
++ else {
++
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioOutSetChanStatus(instance,
++ (tmbslHdmiTxAudioData_t)audioInputConfig.channelStatus.PcmIdentification,
++ (tmbslHdmiTxCSformatInfo_t)audioInputConfig.channelStatus.FormatInfo,
++ (tmbslHdmiTxCScopyright_t)audioInputConfig.channelStatus.CopyrightInfo,
++ audioInputConfig.channelStatus.categoryCode,
++ HDMITX_AFS_768K,
++ (tmbslHdmiTxCSclkAcc_t)audioInputConfig.channelStatus.clockAccuracy,
++ (tmbslHdmiTxCSmaxWordLength_t)audioInputConfig.channelStatus.maxWordLength,
++ (tmbslHdmiTxCSwordLength_t)audioInputConfig.channelStatus.wordLength,
++ (tmbslHdmiTxCSorigAfs_t)audioInputConfig.channelStatus.origSampleFreq))!= TM_OK, errCode)
++
++
++ }
++
++ }
++
++
++ /* Set reset_fifo to 1 */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioOutSetMute(instance,
++ HDMITX_AMUTE_ON) ) != TM_OK, errCode)
++
++ /* UN Mute audio only if previously not muted */
++ if (instanceStatusInfoTx[instance].pAudioInfo->audioMuteState == False) {
++
++ /* Wait for 20 ms */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],(errCode = tmdlHdmiTxIWWait(20) ) != TM_OK, errCode)
++ /* Set reset_fifo to 0 */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioOutSetMute(instance,
++ HDMITX_AMUTE_OFF) ) != TM_OK, errCode)
++
++ }
++
++
++ /* Set audio infoframe */
++ pktAif.ChannelCount = aifChannelCountCode;
++ pktAif.CodingType = 0; /* refer to stream header */
++ pktAif.SampleSize = 0; /* refer to stream header */
++ pktAif.ChannelAlloc = audioInputConfig.channelAllocation;
++ pktAif.LevelShift = 0; /* 0dB level shift */
++ pktAif.DownMixInhibit = 0; /* down-mix stereo permitted */
++ pktAif.SampleFreq = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */
++
++ /* SampleFreq parameter need to be set for OBA and DST audio stream */
++ if ( (audioInputConfig.format == TMDL_HDMITX_AFMT_OBA) ||
++ (audioInputConfig.format == TMDL_HDMITX_AFMT_DST) )
++ {
++ switch (audioInputConfig.rate)
++ {
++ case TMDL_HDMITX_AFS_32K:
++ pktAif.SampleFreq = AIF_SF_32K; /* see table 18 of CEA-861 */
++ break;
++ case TMDL_HDMITX_AFS_44K:
++ pktAif.SampleFreq = AIF_SF_44K;
++ break;
++ case TMDL_HDMITX_AFS_48K:
++ pktAif.SampleFreq = AIF_SF_48K;
++ break;
++ case TMDL_HDMITX_AFS_88K:
++ pktAif.SampleFreq = AIF_SF_88K;
++ break;
++ case TMDL_HDMITX_AFS_96K:
++ pktAif.SampleFreq = AIF_SF_96K;
++ break;
++ case TMDL_HDMITX_AFS_176K:
++ pktAif.SampleFreq = AIF_SF_176K;
++ break;
++ case TMDL_HDMITX_AFS_192K:
++ pktAif.SampleFreq = AIF_SF_192K;
++ break;
++ default:
++ pktAif.SampleFreq = AIF_SF_REFER_TO_STREAM_HEADER; /* refer to stream header */
++ break;
++ }
++ }
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance,
++ &pktAif, True) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of AVI infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAviIfData Pointer to the structure containing AVI infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetVideoInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAviIfData_t *pAviIfData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if AviIfData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAviIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, pAviIfData, enable);
++ }
++ else
++ {
++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, Null, enable);
++ }
++
++ /* Ignore infoframe interlock in DVI mode */
++ if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++ {
++ errCode = TM_OK;
++ }
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], errCode != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of AUD infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAudIfData Pointer to the structure containing AUD infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAudIfData_t *pAudIfData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if AudIfData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAudIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance,
++ (tmbslHdmiTxPktAif_t *)pAudIfData, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetAudioInfoframe(instance,
++ Null, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of the audio content protection packet to be
++ sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pAcpPktData Pointer to the structure containing ACP infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetACPPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxAcpPktData_t *pAcpPktData
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxPkt_t pkt;
++ UInt8 i;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if AcpPktData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pAcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ switch (pAcpPktData->acpType)
++ {
++ /* Make sure bytes reserved are 0 */
++ case 0 : /* Generic audio */
++ for (i=0; i<28; i++) { pkt.dataByte[i] = 0; }
++ break;
++
++ case 1 : /* IEC 60958 identified audio */
++ for (i=0; i<28; i++) { pkt.dataByte[i] = 0; }
++ break;
++
++ case 2 : /* DVD Audio */
++ for (i=0; i<2; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; }
++ for (i=2; i<28; i++) { pkt.dataByte[i] = 0; }
++ break;
++
++ case 3 : /* SuperAudio CD */
++ for (i=0; i<17; i++) { pkt.dataByte[i] = pAcpPktData->acpData[i]; }
++ for (i=17; i<28; i++) { pkt.dataByte[i] = 0; }
++ break;
++
++ default :
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ return TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS;
++ }
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetAcp(instance,
++ &pkt, 28, pAcpPktData->acpType, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetAcp(instance,
++ Null, 0, 0, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of the General Control packet to be sent by Tx
++ device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pGcpPktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetGeneralControlPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxGcpPktData_t *pGcpPktData
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxaMute_t aMute;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if GcpPktData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pGcpPktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ if(pGcpPktData->avMute == False)
++ {
++ aMute = HDMITX_AMUTE_OFF;
++ }
++ else
++ {
++ aMute = HDMITX_AMUTE_ON;
++ }
++
++ /* Set contents of general control packet & enable/disable packet insertion */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance,
++ &aMute, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetGeneralCntrl(instance,
++ Null, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of ISRC1 packet to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pIsrc1PktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetISRC1Packet
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxIsrc1PktData_t *pIsrc1PktData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if Isrc1PktData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc1PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetIsrc1(instance,
++ (tmbslHdmiTxPkt_t *)pIsrc1PktData->UPC_EAN_ISRC, 16, pIsrc1PktData->isrcCont,
++ pIsrc1PktData->isrcValid, pIsrc1PktData->isrcStatus, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetIsrc1(instance,
++ Null, 0, 0, 0, 0, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of ISRC2 packet to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pIsrc2PktData Pointer to the structure containing GCP packet parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetISRC2Packet
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxIsrc2PktData_t *pIsrc2PktData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if Isrc1PktData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pIsrc2PktData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetIsrc2(instance,
++ (tmbslHdmiTxPkt_t *)pIsrc2PktData->UPC_EAN_ISRC, 16, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetIsrc2(instance,
++ Null, 0, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of MPS infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pMpsIfData Pointer to the structure containing MPS infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetMPSInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxMpsIfData_t *pMpsIfData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if MpsIfData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pMpsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance,
++ (tmbslHdmiTxPktMpeg_t *)pMpsIfData, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetMpegInfoframe(instance,
++ Null, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of SPD infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pSpdIfData Pointer to the structure containing SPD infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetSpdInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxSpdIfData_t *pSpdIfData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if SpdIfData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pSpdIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance,
++ (tmbslHdmiTxPktSpd_t *)pSpdIfData, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetSpdInfoframe(instance,
++ Null, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Defines the content of VS infoframe to be sent by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable infoframe insertion.
++ \param pVsIfData Pointer to the structure containing VS infoframe
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetVsInfoframe
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxVsPktData_t *pVsIfData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ if (enable == True)
++ {
++ /* Check if VsIfData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pVsIfData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetVsInfoframe(instance,
++ (tmbslHdmiTxPkt_t *)pVsIfData->vsData, HDMITX_PKT_DATA_BYTE_CNT-1, pVsIfData->version, enable) ) != TM_OK, errCode)
++ }
++ else
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetVsInfoframe(instance,
++ Null, 0, pVsIfData->version, enable) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Enables/disables NULL packet sending (only used for debug purpose).
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable packet insertion.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDebugSetNullPacket
++(
++ tmInstance_t instance,
++ Bool enable
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetNullInsert(instance,
++ enable) ) != TM_OK, errCode)
++
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Send one single NULL packet (only used for debug purpose).
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxDebugSetSingleNullPacket
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSetNullSingle(instance) )
++ != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Set the audio output mute status. This function can be used to mute
++ audio output, without muting video. This can be typically used when
++ reconfiguring the audio HW after a sample rate change.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param muteStatus Mute status (True/False).
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetAudioMute
++(
++ tmInstance_t instance,
++ Bool audioMute
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Mute or Un-mute the audio output */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioOutSetMute(instance,
++ (tmbslHdmiTxaMute_t)audioMute) ) != TM_OK, errCode)
++
++ /* Store current audio mute status */
++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = audioMute;
++
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Reset audio CTS.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxResetAudioCts
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Reset the audio Clock Time Stamp generator */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxAudioInResetCts(instance)
++ ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retrieve EDID Status from driver.
++ This function is synchronous.
++ This function is ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidStatus Pointer to the array that will receive the EDID Status.
++ \param pEdidBlkCount Pointer to the integer that will receive the number of
++ read EDID block.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidStatus_t *pEdidStatus,
++ UInt8 *pEdidBlkCount
++)
++{
++ tmErrorCode_t errCode;
++ UInt8 edidStatus;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if EdidStatus and pReadBytesNumber pointers are Null */
++ RETIF(pEdidStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pEdidBlkCount == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Get the EDID status from BSL driver */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetStatus(instance,
++ (UInt8 *)&edidStatus) ) != TM_OK, errCode)
++
++ if (edidStatus >= TMDL_HDMITX_EDID_STATUS_INVALID)
++ {
++ *pEdidStatus = TMDL_HDMITX_EDID_STATUS_INVALID;
++ }
++ else
++ {
++ *pEdidStatus = (tmdlHdmiTxEdidStatus_t)edidStatus;
++ }
++
++ if ((*pEdidStatus == TMDL_HDMITX_EDID_READ) ||
++ (*pEdidStatus == TMDL_HDMITX_EDID_ERROR_CHK))
++ {
++ /* Get the read EDID block number from BSL driver */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetBlockCount(instance,
++ pEdidBlkCount) ) != TM_OK, errCode)
++ }
++
++ if (errCode != TM_OK)
++ {
++ /* Error during read EDID, number of read block is 0 */
++ *pEdidBlkCount = 0;
++
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++
++ return errCode;
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retrieves audio descriptors from receiver's EDID. This function
++ parses the EDID of Tx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++
++ \param instance Instance identifier.
++ \param pAudioDescs Pointer to the array that will receive audio
++ descriptors.
++ \param maxAudioDescs Size of the array.
++ \param pWrittenAudioDescs Pointer to the integer that will receive the actual
++ number of written descriptors.
++ \param pAudioFlags Pointer to the byte to receive Audio Capabilities Flags.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidAudioCaps
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidAudioDesc_t *pAudioDescs,
++ UInt maxAudioDescs,
++ UInt *pWrittenAudioDescs,
++ UInt8 *pAudioFlags
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxEdidSad_t edidSad[HDMI_TX_SAD_MAX_CNT];
++ UInt i;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if AudioDescs, WrittenAudioDescs and AudioFlags pointers are Null */
++ RETIF(pAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pWrittenAudioDescs == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pAudioFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetAudioCapabilities(instance,
++ edidSad, maxAudioDescs, pWrittenAudioDescs, pAudioFlags) ) != TM_OK, errCode)
++
++ for (i=0; i<*pWrittenAudioDescs; i++)
++ {
++ pAudioDescs[i].format = (edidSad[i].ModeChans & 0x78) >> 3; /* Bits[6:3]: EIA/CEA861 mode */
++ pAudioDescs[i].channels = edidSad[i].ModeChans & 0x07; /* Bits[2:0]: channels */
++ pAudioDescs[i].supportedFreqs = edidSad[i].Freqs; /* Supported frequencies */
++
++ if (pAudioDescs[i].format == 1) /* LPCM format */
++ {
++ pAudioDescs[i].supportedRes = edidSad[i].Byte3 & 0x07;
++ pAudioDescs[i].maxBitrate = 0x00;
++ }
++ else if ( (pAudioDescs[i].format >= 2) && /* Compressed format */
++ (pAudioDescs[i].format <= 8) )
++ {
++ pAudioDescs[i].supportedRes = 0x00;
++ pAudioDescs[i].maxBitrate = edidSad[i].Byte3;
++ }
++ else
++ {
++ pAudioDescs[i].supportedRes = 0x00;
++ pAudioDescs[i].maxBitrate = 0x00;
++ }
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retrieves supported video formats (short descriptors) from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pVideoDesc Pointer to the structure that will receive short
++ video descriptors.
++ \param maxVideoFormats Size of the array.
++ \param pWrittenVideoFormats Pointer to the integer that will receive the actual
++ number of written descriptors.
++ \param pVideoFlags Pointer to the byte to receive Video Capability Flags.
++ b7: underscan supported
++ b6: YCbCr 4:4:4 supported
++ b5: YCbCr 4:2:2 supported
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidVideoCaps
++(
++ tmInstance_t instance,
++ tmdlHdmiTxShortVidDesc_t *pVideoDesc,
++ UInt maxVideoFormats,
++ UInt *pWrittenVideoFormats,
++ UInt8 *pVideoFlags
++)
++{
++ tmErrorCode_t errCode;
++ UInt8 edidVFmtsBuffer[HDMI_TX_SVD_MAX_CNT];
++ tmdlHdmiTxEdidVideoTimings_t edidDTDBuffer[NUMBER_DTD_STORED];
++ UInt8 i;
++ UInt8 writtenDTD = 0;
++ UInt8 dtdCounter = 0;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if Videoformats, WrittenVideoFormats and VideoFlags pointers are Null */
++ RETIF(pVideoDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pWrittenVideoFormats == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pVideoFlags == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(maxVideoFormats == 0, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get video capabilities from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetVideoCapabilities(instance,
++ edidVFmtsBuffer, HDMI_TX_SVD_MAX_CNT, pWrittenVideoFormats, pVideoFlags) ) != TM_OK, errCode)
++
++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = dlHdmiTxEdidGetDTD(instance, edidDTDBuffer, NUMBER_DTD_STORED, &writtenDTD) ) != TM_OK, errCode)
++
++ dtdCounter = 0;
++ if (writtenDTD > 0)
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Write first DTD in first position of table video desc */
++ pVideoDesc[0].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter]));
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ dtdCounter++;
++
++ pVideoDesc[0].nativeVideoFormat = False;
++ }
++
++ /* Start with i = 1 keep the first position for the first DTD */
++ for (i = dtdCounter; i< maxVideoFormats ; i++)
++ {
++ if ((i < (HDMI_TX_SVD_MAX_CNT + dtdCounter)) && (i < ((*pWrittenVideoFormats) + dtdCounter)))
++ {
++ /* Store SVD */
++ pVideoDesc[i].videoFormat = (tmdlHdmiTxVidFmt_t)((Int)edidVFmtsBuffer[i - dtdCounter] & 0x7F);
++ /* if bit 7 is true, it means that is a preferred video format */
++ if ((edidVFmtsBuffer[i - dtdCounter] & 0x80) == 0x80)
++ {
++ pVideoDesc[i].nativeVideoFormat = True;
++ }
++ else
++ {
++ pVideoDesc[i].nativeVideoFormat = False;
++ }
++ }
++ else
++ {
++ if ((dtdCounter < NUMBER_DTD_STORED) && (dtdCounter < writtenDTD))
++ {
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++ /* Store DTD except first DTD */
++ pVideoDesc[i].videoFormat = tmdlHdmiTxConvertDTDtoCEA(instance, &(edidDTDBuffer[dtdCounter]));
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ dtdCounter++;
++
++ pVideoDesc[i].nativeVideoFormat = False;
++ }
++ else
++ {
++ /* VGA is always supported */
++ pVideoDesc[i].videoFormat = TMDL_HDMITX_VFMT_01_640x480p_60Hz;
++ pVideoDesc[i].nativeVideoFormat = False;
++ /* Last format supported exit from loop for */
++ break;
++ }
++ }
++ }
++
++ *pWrittenVideoFormats = *pWrittenVideoFormats + dtdCounter + 1; /* + 1 for VGA format */
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retrieves supported video formats (short descriptors) from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pNativeVideoFormat Pointer to the array that will receive video
++ timing descriptor.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidVideoPreferred
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pNativeVideoFormat
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if NativeVideoFormat pointer is Null */
++ RETIF(pNativeVideoFormat == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get preferred video format from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetVideoPreferred(instance,
++ (tmbslHdmiTxEdidDtd_t *)pNativeVideoFormat) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported detailled video descriptors from
++ receiver's EDID. This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pDTDescriptors Pointer to the array that will receive detailled
++ timing descriptors.
++ \param maxDTDesc Size of the array.
++ \param pWrittenDesc Pointer to the integer that will receive the actual
++ number of written descriptors.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidDetailledTimingDescriptors
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ UInt8 maxDTDesc,
++ UInt8 *pWrittenDTDesc
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
++ RETIF(pDTDescriptors == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pWrittenDTDesc == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = dlHdmiTxEdidGetDTD(instance, pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/*****************************************************************************/
++/**
++ \brief Retrieves supported monitor descriptor from receiver's EDID.
++ This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidFirstMD Pointer to the array that will receive the first monitor
++ descriptors.
++ \param pEdidSecondMD Pointer to the array that will receive the second monitor
++ descriptors.
++ \param pEdidOtherMD Pointer to the array that will receive the other monitor
++ descriptors.
++ \param maxOtherMD Size of the array.
++ \param pWrittenOtherMD Pointer to the integer that will receive the actual
++ number of written descriptors.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidMonitorDescriptors
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidFirstMD_t *pEdidFirstMD,
++ tmdlHdmiTxEdidSecondMD_t *pEdidSecondMD,
++ tmdlHdmiTxEdidOtherMD_t *pEdidOtherMD,
++ UInt8 maxOtherMD,
++ UInt8 *pWrittenOtherMD
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
++ RETIF(pEdidFirstMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pEdidSecondMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pEdidOtherMD == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get monitor descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetMonitorDescriptors(instance,
++ (tmbslHdmiTxEdidFirstMD_t *)pEdidFirstMD, (tmbslHdmiTxEdidSecondMD_t *)pEdidSecondMD,
++ (tmbslHdmiTxEdidOtherMD_t *)pEdidOtherMD, maxOtherMD, pWrittenOtherMD) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/*****************************************************************************/
++/**
++ \brief Retrieves TV picture ratio from receiver's EDID.
++ This function parses the EDID of Rx device to get
++ the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pEdidTvPictureRatio Pointer to the array that will receive the TV picture
++ ratio.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidTVPictureRatio
++(
++ tmInstance_t instance,
++ tmdlHdmiTxPictAspectRatio_t *pEdidTvPictureRatio
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxEdidBDParam_t edidBDParam;
++ UInt16 horizontalSize;
++ UInt16 verticalSize;
++ tmbslHdmiTxEdidDtd_t edidDTDBuffer;
++ UInt8 writtenDTD = 0;
++ Bool bDataAvailable = False; /* Data available in EDID for calcul TV picture ratio */
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if DTDescriptors, WrittenDTDesc pointers are Null */
++ RETIF(pEdidTvPictureRatio == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetBasicDisplayParam(instance,
++ &edidBDParam) ) != TM_OK, errCode)
++
++ horizontalSize = (UInt16)edidBDParam.uMaxHorizontalSize;
++ verticalSize = (UInt16)edidBDParam.uMaxVerticalSize;
++
++ if ((horizontalSize == 0) && (verticalSize == 0))
++ {
++ /* Get Basic Display Parameter from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors
++ (instance, &edidDTDBuffer, 1, &writtenDTD) ) != TM_OK, errCode);
++
++ if (writtenDTD == 1)
++ {
++ horizontalSize = edidDTDBuffer.uHImageSize;
++ verticalSize = edidDTDBuffer.uVImageSize;
++ bDataAvailable = True;
++ }
++ else
++ {
++ *pEdidTvPictureRatio = TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED;
++ }
++ }
++ else
++ {
++ bDataAvailable = True;
++ }
++
++ if (bDataAvailable == True)
++ {
++ *pEdidTvPictureRatio = dlHdmiTxCalcAspectRatio(horizontalSize, verticalSize);
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++
++
++}
++
++/******************************************************************************
++ \brief Retrieves the sink type from receiver's EDID (HDMI or DVI). This
++ function parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pSinkType Pointer to the array that will receive sink type.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidSinkType
++(
++ tmInstance_t instance,
++ tmdlHdmiTxSinkType_t *pSinkType
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if SinkType pointer is Null */
++ RETIF(pSinkType == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetSinkType(instance,
++ (tmbslHdmiTxSinkType_t *)pSinkType) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retrieves source address from receivers's EDID. This
++ function parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pSourceAddress Pointer to the integer that will receive the EDID source
++ address.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidSourceAddress
++(
++ tmInstance_t instance,
++ UInt16 *pSourceAddress
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if SourceAddress pointer is Null */
++ RETIF(pSourceAddress == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Read the source address from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetSourceAddress(instance,
++ pSourceAddress) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Retreives KSV list received by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pKsv Pointer to the array that will receive the KSV list.
++ \param maxKsv Maximum number of KSV that the array can store.
++ \param pWrittenKsv Actual number of KSV written into the array.
++ \param pDepth Connection tree depth returned with KSV list.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetKsvList
++(
++ tmInstance_t instance,
++ UInt8 *pKsv,
++ UInt8 maxKsv,
++ UInt8 *pWrittenKsv,
++ UInt8 *pDepth,
++ Bool *pMaxCascExd,
++ Bool *pMaxDevsExd
++)
++{
++ tmErrorCode_t errCode;
++#ifndef NO_HDCP
++ UInt16 i,j;
++#endif
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if pDepth, Ksv and WrittenKsv pointers are Null */
++ RETIF(pKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pWrittenKsv == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pMaxCascExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pMaxDevsExd == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Maximum Ksv is HDMITX_KSV_LIST_MAX_DEVICES, 128 devices */
++ RETIF_BADPARAM(maxKsv > HDMITX_KSV_LIST_MAX_DEVICES)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Make sure that *pWrittenKsv is 0 */
++ *pWrittenKsv = 0;
++
++ /* Make sure that *pDepth is 0 */
++ *pDepth = 0;
++
++#ifndef NO_HDCP
++
++ *pMaxCascExd = hdcpInfoListTx[instance].hdcpMaxCascExceeded;
++ *pMaxDevsExd = hdcpInfoListTx[instance].hdcpMaxDevsExceeded;
++
++
++ /* Copy the bKsv */
++ if (maxKsv) {
++
++ for (j=0; j<5 ;j++) {
++ pKsv[j] = hdcpInfoListTx[instance].hdcpBksv[4-j];
++ }
++ *pWrittenKsv = *pWrittenKsv + 1;
++
++ } /* maxKsv */
++
++
++ /* Copy the Ksv list */
++ for (i=1; i <= hdcpInfoListTx[instance].hdcpKsvDevices; i++)
++ {
++ if (i < maxKsv)
++ {
++ for (j=0; j<5 ;j++)
++ {
++ pKsv[(5*i)+j] = hdcpInfoListTx[instance].hdcpKsvList[(5*(i-1))+j];
++ }
++ *pWrittenKsv = *pWrittenKsv + 1;
++ }
++ }
++
++ *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++#else
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++#endif /* NO_HDCP */
++}
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++/******************************************************************************
++ \brief Retreives HDCP depth received by Tx device.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pDepth Connection tree depth returned with KSV list.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetDepth
++(
++ tmInstance_t instance,
++ UInt8 *pDepth
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if pDepth, is Null */
++ RETIF(pDepth == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Make sure that *pDepth is 0 */
++ *pDepth = 0;
++
++#ifndef NO_HDCP
++
++
++ *pDepth = hdcpInfoListTx[instance].hdcpDeviceDepth;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++#else
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief Generate SHA_1 interrupt if not occured.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGeneSHA_1_IT
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ dlHdmiTxHandleSHA_1(instance);
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++/******************************************************************************
++ \brief Enable/Disable HDCP encryption.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param hdcpEnable HDCP On/Off (true = On, False = Off).
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: the resolution is unknown
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetHdcp
++(
++ tmInstance_t instance,
++ Bool hdcpEnable
++)
++{
++ tmErrorCode_t errCode;
++#ifndef NO_HDCP
++ tmdlHdmiTxVidFmtSpecs_t resolutionSpecs;
++ tmbslHdmiTxVfreq_t voutFreq;
++ tmbslHdmiTxVidFmt_t voutFmt;
++ tmbslHdmiTxHdcpTxMode_t txMode;
++ tmbslHdmiTxHdcpOptions_t options;
++ UInt8 slaveAddress;
++ UInt16 i;
++#endif
++ tmbslHdmiTxRxSense_t rxSenseStatus; /* Rx Sense status */
++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Hdcp is not supported if keySeed is null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ gtmdlHdmiTxDriverConfigTable[instance].keySeed == HDCP_SEED_NULL, TMDL_ERR_DLHDMITX_NOT_SUPPORTED)
++
++ /* Read rxSenseStatus and hpdStatus to authorize HDCP only if active */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxRxSenseGetStatus(instance,
++ &rxSenseStatus,False) ) != TM_OK, errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHotPlugGetStatus(instance,
++ &hpdStatus,False) ) != TM_OK, errCode)
++
++#ifndef NO_HDCP
++ if (hdcpEnable == True) /* HDCP ON */
++ {
++ if ( (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE) && (hpdStatus == HDMITX_HOTPLUG_ACTIVE) )
++ {
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ tmbslHdmiTxHdcpPowerDown(instance,False);
++#endif
++ /* Reset HDCP DevLib data to ensure that new values are used */
++ hdcpInfoListTx[instance].hdcpCheckState = TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS;
++ hdcpInfoListTx[instance].hdcpErrorState = 0;
++ hdcpInfoListTx[instance].hdcpKsvDevices = 0;
++ hdcpInfoListTx[instance].bKsvSecure = True;
++ for(i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) { hdcpInfoListTx[instance].hdcpBksv[i] = 0; }
++ hdcpInfoListTx[instance].hdcpDeviceDepth = 0;
++
++ hdcpInfoListTx[instance].hdcpMaxCascExceeded = False;
++ hdcpInfoListTx[instance].hdcpMaxDevsExceeded = False;
++
++ /* Current used video output format */
++ voutFmt = (tmbslHdmiTxVidFmt_t)instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format;
++
++ /* Find output vertical frequency from output format */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmdlHdmiTxGetVideoFormatSpecs(instance, (tmdlHdmiTxVidFmt_t)voutFmt, &resolutionSpecs) ) != TM_OK, errCode)
++ voutFreq = (tmbslHdmiTxVfreq_t)resolutionSpecs.vfrequency;
++
++ /* Configure HDCP */
++
++ /* HDCP DDC Slave address */
++ slaveAddress = HDMITX_HDCP_SLAVE_PRIMARY;
++
++ /* Top level or repeater HDCP mode */
++ if (unitTableTx[instance].repeaterEnable == True)
++ {
++ txMode = HDMITX_HDCP_TXMODE_REPEATER;
++ }
++ else
++ {
++ txMode = HDMITX_HDCP_TXMODE_TOP_LEVEL;
++ }
++
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
++ dlHdmiTxCheckColorBar(instance);
++
++ /* HDCP options */
++ options = (tmbslHdmiTxHdcpOptions_t)unitTableTx[instance].hdcpOptions;
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHdcpConfigure(instance,
++ slaveAddress, txMode, options, HDCP_CHECK_INTERVAL_MS, HDCP_NUM_CHECKS) ) != TM_OK, errCode)
++
++ /* Start HDCP */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHdcpInit(instance,
++ voutFmt, voutFreq) ) != TM_OK, errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHdcpRun(instance)
++ ) != TM_OK, errCode)
++
++ unitTableTx[instance].hdcpEnable = True;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return errCode;
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_INVALID_STATE;
++ }
++ else /* HDCP OFF */
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHdcpStop(instance)
++ ) != TM_OK, errCode)
++
++ unitTableTx[instance].hdcpEnable = False;
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode);
++
++#ifdef TMFL_HDCP_OPTIMIZED_POWER
++ tmbslHdmiTxHdcpPowerDown(instance,True);
++#endif
++ return TM_OK;
++ }
++#else
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief Get the driver HDCP state.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pHdcpCheckState Pointer to the integer that will receive the HDCP check state.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetHdcpState
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHdcpCheck_t *pHdcpCheckState
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check if HdcpCheckState pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pHdcpCheckState == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++#ifndef NO_HDCP
++ /* Result of tmbslHdmiTxHdcpCheck */
++ *pHdcpCheckState = hdcpInfoListTx[instance].hdcpCheckState;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++#else
++ *pHdcpCheckState = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief Check the result of an HDCP encryption attempt, called at
++ intervals (set by timeSinceLastCall) after tmdlHdmiTxSetHdcp(true).
++ This API must be used only in case of No Operating System. if OS,
++ this is manage internally of this device library.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param timeSinceLastCall Time passed in milliseconds since last call,
++ must be shorter than 600 ms.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_NOT_SUPPORTED: device does not support HDCP
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading the I2C bus
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing the I2C bus
++ - TMBSL_ERR_HDMI_NOT_SUPPORTED: device does not support HDCP
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxHdcpCheck
++(
++ tmInstance_t instance,
++ UInt16 timeSinceLastCall
++)
++{
++ tmErrorCode_t errCode;
++ Bool featureSupported;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHwGetCapabilities(instance,
++ HDMITX_FEATURE_HW_HDCP, &featureSupported) ) != TM_OK, errCode)
++
++#ifndef NO_HDCP
++ dlHdmiTxCheckColorBar(instance);
++ dlHdmiTxCheckHdcpColorBar(instance);
++
++ if (featureSupported == True)
++ {
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxHdcpCheck(instance,
++ timeSinceLastCall, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[instance].hdcpCheckState)) ) != TM_OK, errCode)
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++#else
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TMDL_ERR_DLHDMITX_NOT_SUPPORTED;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief This function loads a gamut metadata packet into the HW. HW will
++ actually send it at the beginning of next VS, during the vertical
++ blanking.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/disable gamut metadata packet insertion.
++ \param pGamutData Pointer to the structure containing gamut metadata
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetGamutPacket
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxGamutData_t *pGamutData
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxPktGamut_t pkt;
++ UInt8 i;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ if (enable == True)
++ {
++ /* Check if GamutData pointer is Null */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], pGamutData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Fill data */
++ pkt.HB[0] = 0x0A;
++
++ pkt.HB[1] = 0x00;
++ pkt.HB[1] = (UInt8)(pkt.HB[1] | ((pGamutData->nextField & 0x01) << 7));
++ pkt.HB[1] |= (pGamutData->GBD_Profile & 0x07) << 4;
++ pkt.HB[1] |= (pGamutData->affectedGamutSeqNum & 0x0F);
++
++ pkt.HB[2] = 0x00;
++ pkt.HB[2] = (UInt8)(pkt.HB[2] | ((pGamutData->noCurrentGBD & 0x01) << 7));
++ pkt.HB[2] |= (pGamutData->packetSequence & 0x03) << 4;
++ pkt.HB[2] |= (pGamutData->currentGamutSeqNum & 0x0F);
++
++ for(i=0; i<28; i++)
++ {
++ pkt.PB[i] = pGamutData->payload[i];
++ }
++
++ /* Store GBD color space */
++ if ( ((pGamutData->payload[0]) & 0x03) == 2 )
++ {
++ instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709;
++ }
++ else
++ {
++ instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601;
++ }
++
++ /* Fill Gamut metadata packet */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktFillGamut(instance,
++ &pkt, instanceStatusInfoTx[instance].pGamutState->gamutBufNum) ) != TM_OK, errCode)
++
++ /* Enable Gamut metadata transmission */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSendGamut(instance,
++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum, enable) ) != TM_OK, errCode)
++
++ /* Use next buffer for next time */
++ if (instanceStatusInfoTx[instance].pGamutState->gamutBufNum == 0)
++ {
++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 1;
++ }
++ else
++ {
++ instanceStatusInfoTx[instance].pGamutState->gamutBufNum = 0;
++ }
++ }
++ else
++ {
++ /* Disable Gamut metadata transmission */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxPktSendGamut(instance,
++ 0, enable) ) != TM_OK, errCode)
++ }
++
++ /* Store gamut status */
++ instanceStatusInfoTx[instance].pGamutState->gamutOn = enable;
++ if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False;
++
++ /* Set avi infoframe */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = dlHdmiTxSetVideoInfoframe(instance,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief This function set the extended colorimetry with one of the following
++ extended colorimetries(bits EC2-0): xvYCC601, xvYCC709, sYCC601,
++ AdobeYCC601, AdobeRGB. When the parameter extendedColorimetry is
++ xvYCC601 or xvYCC70, this function calls the API tmdlHdmiTxSetGamutPacket
++ to send Gamut Packet Data that does not exist for all other types of
++ extended colorimetries for which pointer pGamutData can be set to NULL.
++ This function also allows to set YCC Quantization Range (YQ1-0)
++
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param enable Enable/Disable extended colorimetry.
++ \param extendedColorimetry value of the extended colorimetry (bits EC2 EC1 EC0).
++ \param yccQR YCC quantisation range
++ \param pGamutData Pointer to the structure containing gamut metadata
++ parameters.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter was out of range
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxSetExtendedColorimetry
++(
++ tmInstance_t instance,
++ Bool enable,
++ tmdlHdmiTxExtColorimetry_t extendedColorimetry,
++ tmdlHdmiTxYCCQR_t yccQR,
++ tmdlHdmiTxGamutData_t *pGamutData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check if extendedColorimetry & yccQR values are in the correct range */
++ if(enable) // no need to check them for disable handling
++ {
++ RETIF(extendedColorimetry >= TMDL_HDMITX_EXT_COLORIMETRY_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER)
++ RETIF(yccQR >= TMDL_HDMITX_YQR_INVALID, TMDL_ERR_DLHDMITX_BAD_PARAMETER)
++ }
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Store YCC quantisation range value for later AVI InfoFrame insertion */
++ if(enable) instanceStatusInfoTx[instance].pGamutState->yccQR = yccQR;
++
++ /* Extended colorimetries that need to send Gamut Packet Data */
++ if( ( (enable == True) && ( (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC601) ||
++ (extendedColorimetry == TMDL_HDMITX_EXT_COLORIMETRY_XVYCC709) ) )
++ ||
++ ( (enable == False) && (instanceStatusInfoTx[instance].pGamutState->gamutOn == True) ) )
++ {
++ /* can not have two different types of extended colorimeties enabled in the same time */
++ if(enable) instanceStatusInfoTx[instance].pGamutState->extColOn = False;
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Call the API that handles Gamut MetaData */
++ RETIF( (errCode = tmdlHdmiTxSetGamutPacket(instance, enable, pGamutData) ) != TM_OK, errCode)
++
++ return TM_OK;
++ }
++
++ /* Extended colorimetries that do not need to send Gamut Packet Data */
++ if (instanceStatusInfoTx[instance].pGamutState->gamutOn == True)
++ {
++ /* Disable Gamut metadata transmission */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance], (errCode = tmbslHdmiTxPktSendGamut(instance, 0, False) ) != TM_OK, errCode)
++
++ instanceStatusInfoTx[instance].pGamutState->gamutOn = False;
++ }
++
++ /* Store the extended colorimetry that does not need sending Gamut Packet Data */
++ if(enable) instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace = extendedColorimetry;
++ instanceStatusInfoTx[instance].pGamutState->extColOn = enable;
++
++ /* Set avi infoframe */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = dlHdmiTxSetVideoInfoframe(instance,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief This function set the revocation list use for HDCP
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param listPtr Pointer on revocation list provide by application.
++ \param length length of revocation list.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_DLHDMITX_HDCP_SECURE: the call was successful, RX keys are secure
++ - TMDL_DLHDMITX_HDCP_NOT_SECURE: the call was successful, RX keys are NOT secure
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: we are a repeater
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxSetHDCPRevocationList(
++ tmInstance_t instance,
++ void *listPtr,
++ UInt32 length
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++#ifndef NO_HDCP
++ tmErrorCode_t errCodeSem = TM_OK;
++ UInt8 aCounter = 0;
++ UInt8 indexKSVList = 0;
++ UInt8 i;
++ Bool bIsSecure = True;
++#endif
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check parameters */
++ RETIF((listPtr == Null) || (length == 0), TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++#ifndef NO_HDCP
++ /* --------------------- */
++ /* Take the semaphore */
++ /* --------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ /* Register revocation list */
++ unitTableTx[instance].revocationList.pList = (UInt8 *)listPtr;
++ unitTableTx[instance].revocationList.length = length;
++
++ /* Look if hdcpBksv is filled in */
++ for (i=0; i<TMDL_HDMITX_KSV_BYTES_PER_DEVICE; i++) {
++ if ( hdcpInfoListTx[instance].hdcpBksv[i] == 0) aCounter++;
++ }
++
++ /* If it the case ,check bksv */
++ if (aCounter != TMDL_HDMITX_KSV_BYTES_PER_DEVICE) {
++
++ dlHdmiTxCheckHdcpBksv (instance, hdcpInfoListTx[instance].hdcpBksv,&bIsSecure, True);
++
++ /* bksv is secure */
++ if (bIsSecure == True) {
++
++ /* if HDMI TX is at top level */
++ if (unitTableTx[instance].repeaterEnable == False) {
++
++ /* if present, check ksv list */
++ if (hdcpInfoListTx[instance].hdcpKsvDevices) {
++
++ while (( indexKSVList < TMDL_HDMITX_KSV_LIST_MAX_DEVICES ) &&
++ ( indexKSVList < hdcpInfoListTx[instance].hdcpKsvDevices ) &&
++ ( bIsSecure == True)) {
++
++ dlHdmiTxCheckHdcpBksv (instance,
++ &(hdcpInfoListTx[instance].hdcpKsvList[indexKSVList * TMDL_HDMITX_KSV_BYTES_PER_DEVICE]),
++ &bIsSecure,
++ False);
++ indexKSVList++;
++ }
++
++ if (bIsSecure == True) {
++ errCode = TMDL_DLHDMITX_HDCP_SECURE;
++ }
++ else {
++ errCode = TMDL_DLHDMITX_HDCP_NOT_SECURE;
++ }
++ }
++ else { /* ksv list does NOT exist */
++
++ /* we suppose that application calls the API after RX_KEYS_RECEIVED */
++ errCode = TMDL_DLHDMITX_HDCP_SECURE;
++ }
++
++ }
++ else { /* we are a repeater */
++ errCode = TMDL_ERR_DLHDMITX_INVALID_STATE;
++ }
++
++ }
++ else { /* bksv NOT secure */
++
++ errCode = TMDL_DLHDMITX_HDCP_NOT_SECURE;
++ }
++
++ }
++ else {
++ /* bksv is not read, could not be tested */
++ errCode = TM_OK;
++ }
++
++ /* --------------------------- */
++ /* Release the sempahore */
++ /* --------------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++#else
++ (void)instance; /* Remove compiler warning */
++#endif /* NO_HDCP */
++ return errCode;
++}
++
++/******************************************************************************
++ \brief This function set the B... screen
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxSetBScreen(
++ tmInstance_t instance,
++ tmdlHdmiTxTestPattern_t pattern
++)
++{
++
++ tmErrorCode_t errCodeSem = TM_OK;
++ tmErrorCode_t errCode = TM_OK;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* --------------------- */
++ /* Take the semaphore */
++ /* --------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ gtmdlHdmiTxDriverConfigTable[instance].pattern = pattern;
++
++ /* Set service mode colour bar on/off (also used as HDCP logo pattern) */
++ (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode,
++ gtmdlHdmiTxDriverConfigTable[instance].pattern);
++
++ /* --------------------------- */
++ /* Release the sempahore */
++ /* --------------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ return errCode;
++
++}
++
++/******************************************************************************
++ \brief This function set the Remove B.... screen
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++
++ \return The call result:
++ - TM_OK: the call was successful, however RX keys have
++ not been checked with provided revocation list
++ because they are not available.
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++
++
++******************************************************************************/
++
++tmErrorCode_t tmdlHdmiTxRemoveBScreen(
++ tmInstance_t instance
++)
++{
++
++ tmErrorCode_t errCodeSem = TM_OK;
++ tmErrorCode_t errCode = TM_OK;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* --------------------- */
++ /* Take the semaphore */
++ /* --------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ /* Restore last output format and mode */
++ (void)dlHdmiTxSetTestPatternOff(instance,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode);
++
++ /* --------------------------- */
++ /* Release the sempahore */
++ /* --------------------------- */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ return errCode;
++
++}
++
++/******************************************************************************
++ \brief tmdlHdmiTxConvertDTDtoCEA .
++
++ \param DTDescriptors DTD to convert.
++
++ \return NA.
++
++******************************************************************************/
++tmdlHdmiTxVidFmt_t tmdlHdmiTxConvertDTDtoCEA
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++)
++{
++
++ tmdlHdmiTxVidFmt_t codeCEA;
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio;
++ Bool formatInterlaced;
++
++ /* --------------------- */
++ /* Take the semaphore */
++ /* --------------------- */
++ tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++
++ formatInterlaced = False;
++
++ if ((pDTDescriptors->flags) & 0x80)
++ {
++ formatInterlaced = True;
++ }
++
++ pictureAspectRatio = dlHdmiTxCalcAspectRatio (pDTDescriptors->hImageSize, pDTDescriptors->vImageSize);
++
++ switch (pDTDescriptors->hActivePixels)
++ {
++ case 640:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_640HAP(pDTDescriptors);
++ break;
++
++ case 720:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_720HAP(pDTDescriptors, pictureAspectRatio);
++ break;
++
++ case 1280:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_1280HAP(pDTDescriptors);
++ break;
++
++ case 1920:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_1920HAP(pDTDescriptors, formatInterlaced);
++ break;
++
++ case 1440:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_1440HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced);
++ break;
++
++ case 2880:
++ codeCEA = dlHdmiTxConvertDTDtoCEA_2880HAP(pDTDescriptors, pictureAspectRatio, formatInterlaced);
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++ /* --------------------------- */
++ /* Release the sempahore */
++ /* --------------------------- */
++ tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++
++ return codeCEA;
++
++}
++
++/*============================================================================*/
++/* INTERNAL FUNCTION */
++/*============================================================================*/
++
++/******************************************************************************
++ \brief Get the REFPIX and REFLINE for output and scaler
++ for the current settings.
++
++ \param vinFmt Video input format.
++ \param vinMode Video input mode.
++ \param voutFmt Video output format.
++ \param syncIn Type of synchro (ext or emb).
++ \param pixRate Video pixel rate.
++ \param pRefPix RefPix for output.
++ \param pRefLine RefLine for output.
++ \param pScRefPix RefPix for scaler.
++ \param pScRefLine RefLine for scaler.
++ \param pbVerified Pointer to the boolean that will receive the fact that
++ this scaler setting was verified.
++
++ \return True (Found) or False (Not found).
++
++******************************************************************************/
++static Bool dlHdmiTxGetReflineRefpix
++(
++ tmdlHdmiTxVidFmt_t vinFmt,
++ tmdlHdmiTxVinMode_t vinMode,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ UInt8 syncIn,
++ tmdlHdmiTxPixRate_t pixRate,
++ UInt16 *pRefPix,
++ UInt16 *pRefLine,
++ UInt16 *pScRefPix,
++ UInt16 *pScRefLine,
++ Bool *pbVerified
++)
++{
++ UInt8 shortVinFmt;
++ UInt8 shortVoutFmt;
++ int i;
++ Bool bFound;
++ tmdlHdmiTxVidFmt_t vinFmtIndex, voutFmtIndex;
++
++ /* Search for all values to match in table, until table end is reached
++ * when both refPix values are zero */
++ *pRefPix = 0;
++ *pRefLine = 0;
++ *pScRefPix = 0;
++ *pScRefLine = 0;
++
++ /* If match is not found in table, we can assume a verified non-scaler
++ * combination */
++ *pbVerified = 1;
++ bFound = False;
++
++ if ((voutFmt < TMDL_HDMITX_VFMT_TV_NO_REG_MIN)
++ || ((voutFmt >= HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= HDMITX_VFMT_38_2880x576p_50Hz)))
++ {
++ vinFmtIndex = dlHdmiTxCalcVidFmtIndex(vinFmt);
++ voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt);
++ shortVinFmt = kVfmtToShortFmt_TV[vinFmtIndex];
++ shortVoutFmt = kVfmtToShortFmt_TV[voutFmtIndex];
++
++ for (i = 0; kRefpixRefline[i].shortVinFmt != TV_INVALID; i++)
++ {
++ if ((kRefpixRefline[i].shortVinFmt == shortVinFmt)
++ && (UNPKMODE(kRefpixRefline[i].modeRateSyncVerf) == vinMode)
++ && (kRefpixRefline[i].shortVoutFmt == shortVoutFmt)
++ && (UNPKRATE(kRefpixRefline[i].modeRateSyncVerf) == pixRate)
++ && (UNPKSYNC(kRefpixRefline[i].modeRateSyncVerf) == syncIn))
++ {
++ *pRefPix = kRefpixRefline[i].refPix;
++ *pRefLine = kRefpixRefline[i].refLine;
++ *pScRefPix = kRefpixRefline[i].scRefPix;
++ *pScRefLine = kRefpixRefline[i].scRefLine;
++ *pbVerified = UNPKVERF(kRefpixRefline[i].modeRateSyncVerf);
++ bFound = True;
++ break;
++ }
++ }
++ }
++
++ return bFound;
++}
++
++/******************************************************************************
++ \brief Set the video infoframe.
++
++ \param instance Instance identifier.
++ \param voutFmt Video output format.
++ \param voutMode Video output mode.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++static tmErrorCode_t dlHdmiTxSetVideoInfoframe
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode
++)
++{
++ tmErrorCode_t errCode;
++ tmdlHdmiTxAviIfData_t contentVif;
++ tmdlHdmiTxVidFmt_t voutFmtIndex;
++
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ contentVif.colorIndicator = voutMode; /* 3rd api_set_avi_infoframe param */
++ contentVif.activeInfoPresent = 0;
++ contentVif.barInformationDataValid = 0;
++ contentVif.scanInformation = 0;
++
++ voutFmtIndex = dlHdmiTxCalcVidFmtIndex(voutFmt);
++ contentVif.pictureAspectRatio = kVfmtToAspect_TV[voutFmtIndex];
++
++ contentVif.activeFormatAspectRatio = 8;
++ contentVif.nonUniformPictureScaling = 0;
++
++#ifdef FORMAT_PC
++ if (voutFmt >= TMDL_HDMITX_VFMT_PC_MIN)
++ {
++ if (voutFmt == TMDL_HDMITX_VFMT_PC_640x480p_60Hz)
++ {
++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_01_640x480p_60Hz;
++ }
++ else
++ {
++ /* Format PC not Valid in EIA861b */
++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)TMDL_HDMITX_VFMT_NULL;
++ }
++ }
++ else
++ {
++#endif /* FORMAT_PC */
++
++ contentVif.videoFormatIdentificationCode = (tmbslHdmiTxVidFmt_t)voutFmt;
++
++#ifdef FORMAT_PC
++ }
++#endif /* FORMAT_PC */
++
++
++ if (((voutFmt >= TMDL_HDMITX_VFMT_06_720x480i_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_09_720x240p_60Hz))
++ || ((voutFmt >= TMDL_HDMITX_VFMT_21_720x576i_50Hz) && (voutFmt <= TMDL_HDMITX_VFMT_24_720x288p_50Hz)))
++ {
++ /* Force pixel repeat for formats where it's mandatory (Pixel Frequency < 20 Mpix/s)*/
++ contentVif.pixelRepetitionFactor = 1;
++ }
++ else if((voutFmt == TMDL_HDMITX_VFMT_10_720x480i_60Hz) || (voutFmt == TMDL_HDMITX_VFMT_11_720x480i_60Hz) ||
++ (voutFmt == TMDL_HDMITX_VFMT_25_720x576i_50Hz) || (voutFmt == TMDL_HDMITX_VFMT_26_720x576i_50Hz) )
++ {
++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3; // pixel sent 1 or 10 times, here 4 times
++ }
++ else if((voutFmt == TMDL_HDMITX_VFMT_14_1440x480p_60Hz) || (voutFmt == TMDL_HDMITX_VFMT_15_1440x480p_60Hz) ||
++ (voutFmt == TMDL_HDMITX_VFMT_29_1440x576p_50Hz) || (voutFmt == TMDL_HDMITX_VFMT_30_1440x576p_50Hz))
++ {
++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_1; // pixel sent 1 or 2 times, here 2 times
++ }
++ else if((voutFmt >= TMDL_HDMITX_VFMT_35_2880x480p_60Hz) && (voutFmt <= TMDL_HDMITX_VFMT_38_2880x576p_50Hz))
++ {
++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_3;
++ }
++ else /* Default to no repeat for all other formats */
++ {
++ contentVif.pixelRepetitionFactor = HDMITX_PIXREP_NONE;
++ }
++
++ if ((instanceStatusInfoTx[instance].pGamutState->gamutOn == True) ||
++ (instanceStatusInfoTx[instance].pGamutState->extColOn == True))
++ {
++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_EXTENDED;
++ }
++ else
++ {
++ switch (voutFmt)
++ {
++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz:
++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz:
++ case TMDL_HDMITX_VFMT_16_1920x1080p_60Hz:
++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz:
++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz:
++ case TMDL_HDMITX_VFMT_31_1920x1080p_50Hz:
++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU709;
++ break;
++
++ default:
++ contentVif.colorimetry = (UInt8)TMDL_HDMITX_COLORIMETRY_ITU601;
++ break;
++ }
++ }
++
++ contentVif.lineNumberEndTopBar = 0;
++ contentVif.lineNumberStartBottomBar = 0;
++ contentVif.lineNumberEndLeftBar = 0;
++ contentVif.lineNumberStartRightBar = 0;
++
++ errCode = dlHdmiTxSetRawVideoInfoframe(instance, &contentVif, True);
++
++ /* Ignore infoframe interlock in DVI mode */
++ if (errCode == TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED)
++ {
++ errCode = TM_OK;
++ }
++
++ return errCode;
++}
++
++/******************************************************************************
++ \brief Set the video infoframe.
++
++ \param instance Instance identifier.
++ \param voutFmt Video output format.
++ \param voutMode Video output mode.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++ - TMBSL_ERR_HDMI_I2C_READ: failed when reading to the I2C bus
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_OPERATION_NOT_PERMITTED: not allowed in DVI mode
++
++******************************************************************************/
++static tmErrorCode_t dlHdmiTxSetRawVideoInfoframe
++(
++ tmInstance_t instance,
++ tmdlHdmiTxAviIfData_t *pContentVif,
++ Bool enable
++)
++{
++
++ tmErrorCode_t errCode;
++ tmbslHdmiTxPktRawAvi_t PktInfoFrame;
++ UInt8 i;
++
++ if(pContentVif != Null)
++ {
++
++ for(i=0; i<sizeof(PktInfoFrame.PB); i++) { PktInfoFrame.PB[i] = 0; }
++
++ /* Prepare VIF header */
++ PktInfoFrame.HB[0] = 0x82; /* Video InfoFrame */
++ PktInfoFrame.HB[1] = 0x02; /* Version 2 [HDMI 1.2] */
++ PktInfoFrame.HB[2] = 0x0D; /* Length [HDMI 1.2] */
++
++ /* Prepare VIF packet (byte numbers offset by 3) */
++ PktInfoFrame.PB[0] = 0; /* Preset checksum to zero so calculation works! */
++ PktInfoFrame.PB[1] = ((pContentVif->colorIndicator& 0x03) << 5) | /* Y1-0, B1-0,S1-0 */
++ ((pContentVif->barInformationDataValid& 0x03) << 2) |
++ (pContentVif->scanInformation & 0x03);
++ if(pContentVif->activeInfoPresent == True)
++ {
++ PktInfoFrame.PB[1] += 0x10; /* A0 bit */
++ }
++
++ PktInfoFrame.PB[2] = ((pContentVif->colorimetry & 0x03) << 6) | /* C1-0, M1-0, R3-0 */
++ ((pContentVif->pictureAspectRatio & 0x03) << 4) |
++ (pContentVif->activeFormatAspectRatio & 0x0F);
++
++ PktInfoFrame.PB[3] = (pContentVif->nonUniformPictureScaling & 0x03); /* SC1-0 */ /* [HDMI 1.2] */
++
++ /* Q1-0 = 00 => RGB Quantization Range depends on video format (CEA-861) */
++ /* Limited Range for all video formats except PC formats which requires Full Range */
++
++ if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED)
++ {
++ PktInfoFrame.PB[3] = (( ((UInt8)instanceStatusInfoTx[instance].pGamutState->wideGamutColorSpace) & 0x07) <<4)
++ | PktInfoFrame.PB[3];
++ }
++
++ /* Bit ITC = 0 => No Content Type ; Bit ITC = 1 => Content Type (see CN1-0) */
++ /* Today ITC = 0 => No Content Type */
++
++ PktInfoFrame.PB[4] = (pContentVif->videoFormatIdentificationCode & 0x7F); /* VIC6-0 */
++
++ PktInfoFrame.PB[5] = (pContentVif->pixelRepetitionFactor & 0x0F); /* PR3-0 */
++
++ /* CN1-0 => Content Type */
++ /* Today CN1-0 = 00 => No Data */
++
++ /* YQ1-0 => YCC Quantization Range, only managed for those extended colorimetries */
++ if (pContentVif->colorimetry == TMDL_HDMITX_COLORIMETRY_EXTENDED)
++ {
++ PktInfoFrame.PB[5] |= ( ((UInt8)instanceStatusInfoTx[instance].pGamutState->yccQR) & 0x03) << 6;
++ }
++ PktInfoFrame.PB[6] = (UInt8)(pContentVif->lineNumberEndTopBar & 0x00FF);
++ PktInfoFrame.PB[7] = (UInt8)((pContentVif->lineNumberEndTopBar & 0xFF00) >> 8);
++ PktInfoFrame.PB[8] = (UInt8)(pContentVif->lineNumberStartBottomBar & 0x00FF);
++ PktInfoFrame.PB[9] = (UInt8)((pContentVif->lineNumberStartBottomBar & 0xFF00) >> 8);
++ PktInfoFrame.PB[10] = (UInt8)(pContentVif->lineNumberEndLeftBar & 0x00FF);
++ PktInfoFrame.PB[11] = (UInt8)((pContentVif->lineNumberEndLeftBar & 0xFF00) >> 8);
++ PktInfoFrame.PB[12] = (UInt8)(pContentVif->lineNumberStartRightBar & 0x00FF);
++ PktInfoFrame.PB[13] = (UInt8)((pContentVif->lineNumberStartRightBar & 0xFF00) >> 8);
++
++ /* Calculate checksum - this is worked out on "Length" bytes of the
++ * packet, the checksum (which we've preset to zero), and the three
++ * header bytes.
++ */
++ PktInfoFrame.PB[0] = dlHdmiTxcalculateCheksumIF(&PktInfoFrame);
++
++ errCode = tmbslHdmiTxPktSetRawVideoInfoframe(instance,
++ &PktInfoFrame, enable);
++ }
++ else
++ {
++ errCode = tmbslHdmiTxPktSetVideoInfoframe(instance,
++ Null, enable);
++ }
++
++ return errCode;
++
++}
++
++/*============================================================================*/
++/* calculateChecksum - returns the byte needed to yield a checksum of zero */
++/*============================================================================*/
++static UInt8
++dlHdmiTxcalculateCheksumIF
++(
++ tmbslHdmiTxPktRawAvi_t *pData /* Pointer to checksum data */
++)
++{
++ UInt8 checksum = 0; /* Working checksum calculation */
++ UInt8 result = 0; /* Value to be returned */
++ UInt8 numBytes = 0;
++ Int i;
++
++ if(pData != Null)
++ {
++
++ numBytes = sizeof(pData->HB);
++
++ for (i = 0; i < numBytes; i++)
++ {
++ checksum = checksum + pData->HB[i];
++ }
++
++ numBytes = sizeof(pData->PB);
++
++ for (i = 0; i < numBytes; i++)
++ {
++ checksum = checksum + pData->PB[i];
++ }
++
++ result = (UInt8)((255 - checksum) + 1);
++ }
++ return result; /* returns 0 in the case of null ptr or 0 bytes */
++}
++
++/******************************************************************************
++ \brief Set colourbar test pattern on with RGB infoframe
++
++ \param instance Instance identifier.
++ \param voutFmt Video output format.
++ \param voutMode Video output mode.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++******************************************************************************/
++tmErrorCode_t dlHdmiTxSetTestPatternOn
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode,
++ tmdlHdmiTxTestPattern_t pattern
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance,
++ (tmbslHdmiTxTestPattern_t)pattern) ) != TM_OK, errCode)
++
++ if (pattern > TMDL_HDMITX_PATTERN_CBAR8)
++ {
++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode)
++ }
++ else
++ {
++ /* For TMDL_HDMITX_PATTERN_CBAR8 and TMDL_HDMITX_PATTERN_CBAR4, video mode in infoframe should be RGB */
++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, TMDL_HDMITX_VOUTMODE_RGB444) ) != TM_OK, errCode)
++ }
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief Set colourbar test pattern off with previous infoframe
++
++ \param instance Instance identifier.
++ \param voutFmt Video output format.
++ \param voutMode Video output mode.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++ - TMBSL_ERR_HDMI_I2C_WRITE: failed when writing to the I2C bus
++
++******************************************************************************/
++tmErrorCode_t dlHdmiTxSetTestPatternOff
++(
++ tmInstance_t instance,
++ tmdlHdmiTxVidFmt_t voutFmt,
++ tmdlHdmiTxVoutMode_t voutMode
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ RETIF( (errCode = tmbslHdmiTxTestSetPattern(instance,
++ (tmbslHdmiTxTestPattern_t)TMDL_HDMITX_PATTERN_OFF) ) != TM_OK, errCode)
++
++ /* Restore video infoframe */
++ RETIF( (errCode = dlHdmiTxSetVideoInfoframe(instance, voutFmt, voutMode) ) != TM_OK, errCode)
++
++ return TM_OK;
++}
++
++/******************************************************************************
++ \brief HDCP ENCRYPT interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleENCRYPT
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++
++ tmbslHdmiTxHdcpHandleENCRYPT(instance);
++
++ if (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == False)
++ {
++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True;
++ }
++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False;
++#else
++ (void)instance; /* Remove compiler warning */
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief HPD interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleHPD
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */
++ tmPowerState_t powerState; /* Power state of transmitter */
++
++ hpdStatus = HDMITX_HOTPLUG_INVALID;
++
++ /* Get Hot Plug status */
++ errCode = tmbslHdmiTxHotPlugGetStatus(instance,
++ &hpdStatus,False);
++
++ if (errCode != TM_OK) return;
++
++ /* Get the power state of the transmitter */
++ errCode = tmbslHdmiTxPowerGetState(instance,
++ &powerState);
++
++ if (errCode != TM_OK) return;
++
++ /* Has hot plug changed to Active? */
++ if (hpdStatus == HDMITX_HOTPLUG_ACTIVE)
++ {
++ /* Set state machine to Plugged */
++ dlHdmiTxSetState(instance, STATE_PLUGGED);
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_ACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++ if (powerState == tmPowerOn)
++ {
++ /* Yes: Wait for DDC line to settle before reading EDID */
++ tmbslHdmiTxSysTimerWait(instance,
++ 500); /* ms */
++
++ /* Request EDID read */
++ errCode = tmbslHdmiTxEdidRequestBlockData(instance,
++ unitTableTx[instance].pEdidBuffer, (Int)((unitTableTx[instance].edidBufferSize) >> 7),
++ (Int)(unitTableTx[instance].edidBufferSize));
++
++ if (errCode != TM_OK) return;
++ }
++ }
++ else
++ {
++#ifndef NO_HDCP
++ if (unitTableTx[instance].hdcpEnable == True)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ /* Switch off HDCP */
++ (void)tmdlHdmiTxSetHdcp(instance, False);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++#endif /* NO_HDCP */
++
++ /* Set state machine to Unplugged */
++ dlHdmiTxSetState(instance, STATE_UNPLUGGED);
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HPD_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_HPD_INACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++ }
++}
++
++/******************************************************************************
++ \brief T0 interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleT0
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ tmErrorCode_t errCode;
++
++ errCode = tmbslHdmiTxHdcpHandleT0(instance);
++
++ if (errCode != TM_OK) return;
++
++ tmbslHdmiTxHdcpGetT0FailState(instance,
++ &(hdcpInfoListTx[instance].hdcpErrorState));
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_INACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = True;
++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True;
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief BCAPS interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleBCAPS
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ Bool bCheckRequired;
++ tmErrorCode_t errCode;
++
++ /* Handle BCAPS interrupt immediately */
++ errCode = tmbslHdmiTxHdcpHandleBCAPS(instance);
++
++ if (errCode != TM_OK) return;
++
++ /* Wait for TDA9984 to read BKSV from B device */
++ tmbslHdmiTxSysTimerWait(instance, 10);
++
++ /* Handle BKSV read */
++ errCode = tmbslHdmiTxHdcpHandleBKSV(instance,
++ hdcpInfoListTx[instance].hdcpBksv, &bCheckRequired);
++
++ if (errCode != TM_OK) return;
++
++ if (bCheckRequired)
++ {
++ /* check HdcpBksv against a revocation list */
++ dlHdmiTxCheckHdcpBksv (instance, hdcpInfoListTx[instance].hdcpBksv,&(hdcpInfoListTx[instance].bKsvSecure), True);
++ }
++ else
++ {
++ /* Result is always secure if no check required */
++ hdcpInfoListTx[instance].bKsvSecure = True;
++ }
++
++ /* Handle BKSV result */
++ errCode = tmbslHdmiTxHdcpHandleBKSVResult(instance,
++ hdcpInfoListTx[instance].bKsvSecure);
++
++ if (errCode != TM_OK) return;
++
++
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief BSTATUS interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleBSTATUS
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ UInt16 bstatus = 0;
++
++ tmbslHdmiTxHdcpHandleBSTATUS(instance,
++ &bstatus);
++
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ gIgnoreNextSha1 = False;
++#endif /*HDMI_TX_REPEATER_ISR_MODE*/
++
++ if (((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0)
++ || ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0))
++ {
++
++ hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8);
++
++ /* The KsvList length is limited by the smaller of the list array
++ * length and the number of devices returned in BSTATUS */
++ hdcpInfoListTx[instance].hdcpKsvDevices =
++ (UInt8)(bstatus & HDMITX_HDCP_BSTATUS_DEVICE_COUNT);
++
++ if (HDMITX_KSV_LIST_MAX_DEVICES < hdcpInfoListTx[instance].hdcpKsvDevices)
++ {
++ hdcpInfoListTx[instance].hdcpKsvDevices = HDMITX_KSV_LIST_MAX_DEVICES;
++ }
++
++ if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_CASCADE_EXCEEDED) > 0)
++ {
++ hdcpInfoListTx[instance].hdcpMaxCascExceeded = True;
++ }
++
++ if ((bstatus & HDMITX_HDCP_BSTATUS_MAX_DEVS_EXCEEDED) > 0)
++ {
++ hdcpInfoListTx[instance].hdcpMaxDevsExceeded = True;
++ }
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++ }
++ else
++ {
++
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ /* Call SHA_1 otherwise this ISR is missed */
++ hdcpInfoListTx[instance].hdcpDeviceDepth = (UInt8)((bstatus & HDMITX_HDCP_BSTATUS_CASCADE_DEPTH)>>8);
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_B_STATUS) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_B_STATUS);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++ }
++
++
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief SHA_1 interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleSHA_1
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ tmErrorCode_t errCode;
++ UInt8 indexKSVList;
++
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ if (gIgnoreNextSha1 == False)
++ {
++ gIgnoreNextSha1 = True;
++#endif /*HDMI_TX_REPEATER_ISR_MODE*/
++
++ errCode = tmbslHdmiTxHdcpHandleSHA_1(instance,
++ HDMITX_KSV_LIST_MAX_DEVICES, hdcpInfoListTx[instance].hdcpKsvList,
++ &(hdcpInfoListTx[instance].hdcpKsvDevices),&(hdcpInfoListTx[instance].hdcpDeviceDepth));
++ if (errCode != TM_OK) return;
++
++ /* Top level or repeater HDCP mode */
++ if (unitTableTx[instance].repeaterEnable == False)
++ {
++ /* check HdcpKsvList against revocation list */
++
++ indexKSVList = 0;
++ while (( indexKSVList < TMDL_HDMITX_KSV_LIST_MAX_DEVICES ) &&
++ ( indexKSVList < hdcpInfoListTx[instance].hdcpKsvDevices ) &&
++ (hdcpInfoListTx[instance].bKsvSecure == True)
++ )
++ {
++ dlHdmiTxCheckHdcpBksv (instance,
++ &(hdcpInfoListTx[instance].hdcpKsvList[indexKSVList * TMDL_HDMITX_KSV_BYTES_PER_DEVICE]),
++ &(hdcpInfoListTx[instance].bKsvSecure),
++ False);
++ indexKSVList++;
++ }
++ }
++ else
++ {
++ hdcpInfoListTx[instance].bKsvSecure = True;
++ }
++
++ /* Handle SHA_1 result */
++ errCode = tmbslHdmiTxHdcpHandleSHA_1Result(instance,
++ hdcpInfoListTx[instance].bKsvSecure);
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++ if (!hdcpInfoListTx[instance].bKsvSecure)
++ {
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
++ dlHdmiTxCheckColorBar(instance);
++ }
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ }
++#endif /*HDMI_TX_REPEATER_ISR_MODE*/
++
++
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief PJ interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandlePJ
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ tmbslHdmiTxHdcpHandlePJ(instance);
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief R0 interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleR0
++(
++ tmInstance_t instance
++)
++{
++#ifndef NO_HDCP
++ tmErrorCode_t errCode;
++ tmbslHdmiTxSinkCategory_t category;
++
++
++
++ if (hdcpInfoListTx[instance].bKsvSecure == True)
++ {
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_HDCP_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_HDCP_ACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = False;
++ }
++
++
++ errCode = tmbslHdmiTxHdcpGetSinkCategory(instance,
++ &category);
++ if (errCode != TM_OK) return;
++
++ if (category == HDMITX_SINK_CAT_NOT_REPEATER)
++ {
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_KEYS_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_KEYS_RECEIVED);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++ }
++
++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = True;
++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = True;
++#else
++ (void)instance;
++#endif /* NO_HDCP */
++}
++
++/******************************************************************************
++ \brief SW_INT interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleSW_INT
++(
++ tmInstance_t instance
++)
++{
++ DUMMY_ACCESS(instance);
++}
++
++/******************************************************************************
++ \brief RX_SENSE interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleRX_SENSE
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++ tmbslHdmiTxRxSense_t rxSenseStatus; /* Rx Sense status */
++ tmbslHdmiTxHotPlug_t hpdStatus; /* HPD status */
++
++ errCode = tmbslHdmiTxRxSenseGetStatus(instance,
++ &rxSenseStatus,False);
++
++ if (errCode != TM_OK) return;
++
++ errCode = tmbslHdmiTxHotPlugGetStatus(instance,
++ &hpdStatus,False);
++
++ if (errCode != TM_OK) return;
++
++// if (hpdStatus == HDMITX_HOTPLUG_ACTIVE)
++// {
++ if (rxSenseStatus == HDMITX_RX_SENSE_ACTIVE)
++ {
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_ACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_ACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++ }
++ else if (rxSenseStatus == HDMITX_RX_SENSE_INACTIVE)
++ {
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_RX_DEVICE_INACTIVE) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_RX_DEVICE_INACTIVE);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++#ifndef NO_HDCP
++ if (unitTableTx[instance].hdcpEnable == True)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ /* Switch off HDCP */
++ (void)tmdlHdmiTxSetHdcp(instance, False);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++#endif /* NO_HDCP */
++ }
++// }
++}
++
++/******************************************************************************
++ \brief EDID_READ interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleEDID_READ
++(
++ tmInstance_t instance
++)
++{
++ tmErrorCode_t errCode;
++ UInt8 edidStatus = TMDL_HDMITX_EDID_NOT_READ;
++
++ /* Get the edid status and read the connected device's EDID */
++
++ /* Get Edid status */
++ errCode = tmbslHdmiTxEdidGetStatus(instance,
++ &edidStatus);
++
++ if (errCode != TM_OK)
++ {
++ /* Set state machine to Plugged */
++ dlHdmiTxSetState(instance, STATE_PLUGGED);
++ return;
++ }
++
++ /* Has hot plug changed to Active? */
++ if ((edidStatus == TMDL_HDMITX_EDID_READ) ||
++ (edidStatus == TMDL_HDMITX_EDID_ERROR_CHK))
++ {
++ /* Set state machine to EDID available */
++ dlHdmiTxSetState(instance, STATE_EDID_AVAILABLE);
++ }
++ else
++ {
++ /* Set state machine to Plugged */
++ dlHdmiTxSetState(instance, STATE_PLUGGED);
++ }
++
++
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_EDID_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_EDID_RECEIVED);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++
++
++}
++
++/******************************************************************************
++ \brief VS_RPT interrupt callback.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxHandleVS_RPT
++(
++ tmInstance_t instance
++)
++{
++ if (dlHdmiTxGetEventStatus(instance, TMDL_HDMITX_VS_RPT_RECEIVED) == TMDL_HDMITX_EVENT_ENABLED)
++ {
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]);
++ unitTableTx[instance].pCallback(TMDL_HDMITX_VS_RPT_RECEIVED);
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]);
++ }
++}
++
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_640HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_640HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->vActiveLines)
++ {
++ case 480:
++ codeCEA = TMDL_HDMITX_VFMT_01_640x480p_60Hz;
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++ return codeCEA;
++
++}
++
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_720HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_720HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->vActiveLines)
++ {
++ case 480:
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_03_720x480p_60Hz;
++ }
++ break;
++
++ case 576:
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_17_720x576p_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_18_720x576p_50Hz;
++ }
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++ return codeCEA;
++
++}
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_1280HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1280HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->vActiveLines)
++ {
++ case 720:
++ switch (pDTDescriptors->hBlankPixels)
++ {
++ case 370:
++ codeCEA = TMDL_HDMITX_VFMT_04_1280x720p_60Hz;
++ break;
++
++ case 700:
++ codeCEA = TMDL_HDMITX_VFMT_19_1280x720p_50Hz;
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++
++ return codeCEA;
++}
++
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_1920HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1920HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ Bool formatInterlaced
++
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->hBlankPixels)
++ {
++ case 280:
++ if (formatInterlaced)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_05_1920x1080i_60Hz;
++ }
++ else
++ {
++ if ( pDTDescriptors->pixelClock == 14850 )
++ {
++ codeCEA = TMDL_HDMITX_VFMT_16_1920x1080p_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_34_1920x1080p_30Hz;
++ }
++ }
++ break;
++
++ case 720:
++ if (formatInterlaced)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_20_1920x1080i_50Hz;
++ }
++ else
++ {
++ switch (pDTDescriptors->pixelClock)
++ {
++ case 14850:
++ codeCEA = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz;
++ break;
++
++ case 7425:
++ codeCEA = TMDL_HDMITX_VFMT_33_1920x1080p_25Hz;
++ break;
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++ }
++ break;
++
++ case 830:
++ codeCEA = TMDL_HDMITX_VFMT_32_1920x1080p_24Hz;
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++
++ return codeCEA;
++}
++
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_1440HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_1440HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio,
++ Bool formatInterlaced
++
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->vActiveLines)
++ {
++ case 240:
++ if (formatInterlaced)
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_06_720x480i_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_07_720x480i_60Hz;
++ }
++ }
++ else
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_08_720x240p_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_09_720x240p_60Hz;
++ }
++ }
++ break;
++
++ case 288:
++ if (formatInterlaced)
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_21_720x576i_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_22_720x576i_50Hz;
++ }
++ }
++ else
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_23_720x288p_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_24_720x288p_50Hz;
++ }
++ }
++ break;
++
++ case 480:
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_14_1440x480p_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_15_1440x480p_60Hz;
++ }
++ break;
++
++ case 576:
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_29_1440x576p_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_30_1440x576p_50Hz;
++ }
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++ return codeCEA;
++}
++
++/******************************************************************************
++ \brief dlHdmiTxConvertDTDtoCEA_2880HAP .
++
++ \param pDTDescriptors DTD to convert.
++ pictureAspectRatio aspect ratio of DTD
++ formatInterlaced DTD Interlaced or progressif
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxConvertDTDtoCEA_2880HAP
++(
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio,
++ Bool formatInterlaced
++)
++{
++ tmdlHdmiTxVidFmt_t codeCEA;
++
++ switch (pDTDescriptors->vActiveLines)
++ {
++ case 240:
++ if (formatInterlaced)
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_10_720x480i_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_11_720x480i_60Hz;
++ }
++ }
++ else
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_12_720x240p_60Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_13_720x240p_60Hz;
++ }
++ }
++ break;
++
++ case 288:
++ if (formatInterlaced)
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_25_720x576i_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_26_720x576i_50Hz;
++ }
++ }
++ else
++ {
++ if (pictureAspectRatio == TMDL_HDMITX_P_ASPECT_RATIO_4_3)
++ {
++ codeCEA = TMDL_HDMITX_VFMT_27_720x288p_50Hz;
++ }
++ else
++ {
++ codeCEA = TMDL_HDMITX_VFMT_28_720x288p_50Hz;
++ }
++ }
++ break;
++
++ default:
++ /* Not a valid format */
++ codeCEA = TMDL_HDMITX_VFMT_NULL;
++ break;
++ }
++
++ return codeCEA;
++}
++
++/******************************************************************************
++ \brief EdidGetDTD .
++
++ \param .
++
++ \return NA.
++
++******************************************************************************/
++tmErrorCode_t dlHdmiTxEdidGetDTD
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidVideoTimings_t *pDTDescriptors,
++ UInt8 maxDTDesc,
++ UInt8 *pWrittenDTDesc
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check the current state */
++ RETIF( dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ /* Get detailled descriptors from EDID, return TMDL_ERR_DLHDMITX_NO_RESOURCES if EDID are not read */
++ RETIF((errCode = tmbslHdmiTxEdidGetDetailedTimingDescriptors(
++ instance, (tmbslHdmiTxEdidDtd_t *)pDTDescriptors, maxDTDesc, pWrittenDTDesc) ) != TM_OK, errCode);
++
++ return TM_OK;
++}
++
++
++/******************************************************************************
++ \brief Command processing task, dedicated to unit/instance 0.
++
++ \param NA.
++
++ \return NA.
++
++******************************************************************************/
++
++#ifndef TMFL_NO_RTOS
++static void CommandTaskUnit0()
++{
++ UInt8 command;
++ Bool loop = True; /* Just to avoid compiler warning */
++ tmErrorCode_t err = TM_OK;
++
++ while(loop)
++ {
++ tmdlHdmiTxIWQueueReceive(unitTableTx[0].queueHandle, &command);
++
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]);
++
++ /* Clear T0 flag before polling for interrupts */
++ instanceStatusInfoTx[0].pColBarState->hdcpSecureOrT0 = False;
++
++ if (gI2CDebugAccessesEnabled == True)
++ {
++
++ err = tmbslHdmiTxHwHandleInterrupt(0);
++
++ if ((err == TMBSL_ERR_HDMI_I2C_WRITE) || (err == TMBSL_ERR_HDMI_I2C_READ))
++ {
++
++ unitTableTx[0].pCallback(TMDL_HDMITX_DEBUG_EVENT_1);
++ }
++
++ }/* (gI2CDebugAccessesEnabled == True) */
++
++ /* Enable interrupts for Tx (interrupts are disabled in the HandleInterrupt function) */
++ tmdlHdmiTxIWEnableInterrupts(TMDL_HDMI_IW_TX_1);
++
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]);
++ };
++}
++#endif /* TMFL_NO_RTOS */
++
++/******************************************************************************
++ \brief Hdcp check task, dedicated to unit/instance 0.
++
++ \param NA.
++
++ \return NA.
++
++******************************************************************************/
++#ifndef TMFL_NO_RTOS
++static void HdcpTaskUnit0()
++{
++ Bool loop = True; /* Just to avoid compiler warning */
++ Bool featureSupported;
++
++ tmbslHdmiTxHwGetCapabilities(0,
++ HDMITX_FEATURE_HW_HDCP, &featureSupported);
++
++#ifndef NO_HDCP
++ while(loop)
++ {
++ (void)tmdlHdmiTxIWWait(35);
++
++ /* Take the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[0]);
++
++ if (gI2CDebugAccessesEnabled == True)
++ {
++
++ dlHdmiTxCheckColorBar(0);
++ dlHdmiTxCheckHdcpColorBar(0);
++
++ if (featureSupported == True)
++ {
++ tmbslHdmiTxHdcpCheck(0,35, (tmbslHdmiTxHdcpCheck_t *)&(hdcpInfoListTx[0].hdcpCheckState));
++ }
++
++ } /* gI2CDebugAccessesEnabled == True*/
++
++ /* Release the sempahore */
++ (void)tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[0]);
++ };
++#else
++ (void)loop;
++#endif /* NO_HDCP */
++}
++#endif /* TMFL_NO_RTOS */
++
++#ifndef NO_HDCP
++/******************************************************************************
++ \brief Check hdcp state to manage color bar.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxCheckHdcpColorBar
++(
++ tmInstance_t instance
++)
++{
++ /* Use HDCP check result to control HDCP colour bars */
++ if ( (instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 == True)
++ && (instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange == True)
++ && (instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 == False) )
++ {
++ /* Remove test pattern once if Authenticated with no error interrupts */
++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != False)
++ {
++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = False;
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
++
++ if (unitTableTx[instance].simplayHd == True) {
++
++ /* Mute or Un-mute the audio output */
++ tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_OFF);
++
++ /* Store current audio mute status */
++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = False;
++ }
++
++
++ }
++ /* Reset state flags */
++ instanceStatusInfoTx[instance].pColBarState->hdcpColbarChange = False;
++ instanceStatusInfoTx[instance].pColBarState->hdcpSecureOrT0 = True;
++
++#ifdef TMFL_TDA19989
++ instanceStatusInfoTx[instance].pColBarState->disableColorBarOnR0 = False;
++#endif /* TMFL_TDA19989 */
++
++
++
++ }
++
++ if ( (instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 == True)
++ && (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True))
++ {
++ /* Set test pattern once if not Authenticated, to mask HDCP failure */
++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn != True)
++ {
++ instanceStatusInfoTx[instance].pColBarState->colorBarOn = True;
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = True;
++
++ if (unitTableTx[instance].simplayHd == True) {
++
++ /* Mute or Un-mute the audio output */
++ tmbslHdmiTxAudioOutSetMute(instance,(tmbslHdmiTxaMute_t)HDMITX_AMUTE_ON);
++
++ /* Store current audio mute status */
++ instanceStatusInfoTx[instance].pAudioInfo->audioMuteState = True;
++ }
++
++ }
++ /* Reset state flag */
++ instanceStatusInfoTx[instance].pColBarState->hdcpEncryptOrT0 = False;
++ }
++}
++#endif
++
++#ifndef NO_HDCP
++/******************************************************************************
++ \brief Show color bars or restore the last video format.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxCheckColorBar
++(
++ tmInstance_t instance
++)
++{
++ if ( (instanceStatusInfoTx[instance].pColBarState->inOutFirstSetDone == True)
++ && (instanceStatusInfoTx[instance].pColBarState->changeColorBarNow == True) )
++ {
++ instanceStatusInfoTx[instance].pColBarState->changeColorBarNow = False;
++
++ if (unitTableTx[instance].simplayHd == True)
++ {
++ if (instanceStatusInfoTx[instance].pColBarState->colorBarOn == True)
++ {
++ /* Set service mode colour bar on/off (also used as HDCP logo pattern) */
++ (void)dlHdmiTxSetTestPatternOn(instance, instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode,
++ gtmdlHdmiTxDriverConfigTable[instance].pattern);
++ }
++ else
++ {
++ /* Restore last output format and mode */
++ (void)dlHdmiTxSetTestPatternOff(instance,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.format,
++ instanceStatusInfoTx[instance].pVideoInfo->videoOutConfig.mode);
++ }
++ }
++ }
++}
++#endif
++
++#ifndef NO_HDCP
++/******************************************************************************
++ \brief Get hdcp seed.
++
++ \param instance Instance identifier.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxFindHdcpSeed
++(
++ tmInstance_t instance
++)
++{
++#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL
++ UInt8 otp[3];
++#endif
++
++ /* If no seed is coded in this file then find it somewhere else */
++#if HDCP_SEED_DEFAULT == HDCP_SEED_NULL
++ /* See if a seed table has been programmed in flash */
++ if (kSeedTable[0][0] != 0xFFFF)
++ {
++ /* Read OTP LSB at address 0x00 and try to match in flash table */
++ if ( (tmbslHdmiTxHdcpGetOtp(instance,
++ 0x00, otp)) == TM_OK)
++ {
++ int i;
++ for (i = 0; i < SEED_TABLE_LEN; i++)
++ {
++ if (kSeedTable[i][0] == otp[2]) /* OTP_DATA_LSB */
++ {
++ /* Found seed! */
++ gtmdlHdmiTxDriverConfigTable[instance].keySeed = kSeedTable[i][1];
++ break;
++ }
++ }
++ }
++ }
++#endif /* HDCP_SEED_DEFAULT != HDCP_SEED_NULL */
++
++ /* Initialise the TDA9984 HDCP keys */
++ if (gtmdlHdmiTxDriverConfigTable[instance].keySeed != HDCP_SEED_NULL)
++ {
++ /* Initialise the HDMI Transmitter HDCP keys */
++ tmbslHdmiTxHdcpDownloadKeys(instance,
++ gtmdlHdmiTxDriverConfigTable[instance].keySeed, HDMITX_HDCP_DECRYPT_ENABLE);
++ }
++}
++#endif /* NO_HDCP */
++
++/******************************************************************************
++ \brief Set the state of the state machine.
++
++ \param instance Instance identifier.
++ \param state State of the state machine.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxSetState
++(
++ tmInstance_t instance,
++ tmdlHdmiTxDriverState_t state
++)
++{
++ /* Set the state */
++ unitTableTx[instance].state = state;
++}
++
++/******************************************************************************
++ \brief Get the state of the state machine.
++
++ \param instance Instance identifier.
++
++ \return tmdlHdmiTxDriverState_t Current State of the state machine.
++
++******************************************************************************/
++tmdlHdmiTxDriverState_t dlHdmiTxGetState
++(
++ tmInstance_t instance
++)
++{
++ tmdlHdmiTxDriverState_t state;
++
++ /* Get the state */
++ state = unitTableTx[instance].state;
++
++ return (state);
++}
++
++/******************************************************************************
++ \brief Get the state of the event (enabled or disabled).
++
++ \param instance Instance identifier.
++ \param event Event to give the state.
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxEventStatus_t dlHdmiTxGetEventStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEvent_t event
++)
++{
++ tmdlHdmiTxEventStatus_t eventStatus;
++
++ /* Get the event status */
++ eventStatus = instanceStatusInfoTx[instance].pEventState[event].status;
++
++ return (eventStatus);
++}
++
++/******************************************************************************
++ \brief Caculation of aspect ratio.
++
++ \param HImageSize Horizontal image size.
++ \param VImageSize Vertical image size.
++
++ \return NA.
++
++******************************************************************************/
++static tmdlHdmiTxPictAspectRatio_t dlHdmiTxCalcAspectRatio (
++ UInt16 HImageSize,
++ UInt16 VImageSize
++)
++{
++ tmdlHdmiTxPictAspectRatio_t pictureAspectRatio;
++ UInt16 calcPictureAspectRatio;
++
++ /* Define picture Aspect Ratio */
++ /* 16/9 = 1.77777 so the result approach is 2 */
++ /* 4/3 = 1.33333 so the result approach is 1 */
++ /* operation : */
++ /* ImageSize + (vImageSize/2) */
++ /* -------------------------- > vImageSize ->True 16/9 False 4/3 */
++ /* 2 */
++
++ calcPictureAspectRatio = ((UInt16)(HImageSize + ((VImageSize)>>1)))>>1;
++
++ if(calcPictureAspectRatio > VImageSize)
++ {
++ pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_16_9;
++ }
++ else
++ {
++ pictureAspectRatio = TMDL_HDMITX_P_ASPECT_RATIO_4_3;
++ }
++
++ return pictureAspectRatio;
++
++}
++
++#ifndef NO_HDCP
++/******************************************************************************
++ \brief dlHdmiTxCheckHdcpBksv .
++
++ \param pHdcpBksvTested ksv To test.
++ \param pbBksvSecure Test result.
++ \param bBigEndian ksv provide by hardware are in little or big endian.
++
++ \return NA.
++
++******************************************************************************/
++static void dlHdmiTxCheckHdcpBksv
++(
++ tmInstance_t instance,
++ UInt8 * pHdcpBksvTested,
++ Bool * pbBksvSecure,
++ Bool bBigEndian
++)
++{
++
++ UInt32 NbInRevocationList;
++
++ NbInRevocationList = 0;
++
++ /* CBE: force secure, otherwise we will not look at anything */
++ *pbBksvSecure = True;
++
++ if ((unitTableTx[instance].revocationList.pList != Null) && (unitTableTx[instance].revocationList.length > 0))
++ {
++ while ((*pbBksvSecure == True) && (NbInRevocationList < unitTableTx[instance].revocationList.length))
++ {
++ if (bBigEndian)
++ {
++ if ((pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE])
++ &&
++ (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ )
++ {
++ *pbBksvSecure = False;
++ }
++ }
++ else
++ {
++ if ((pHdcpBksvTested[4] == unitTableTx[instance].revocationList.pList[NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE])
++ &&
++ (pHdcpBksvTested[3] == unitTableTx[instance].revocationList.pList[1 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[2] == unitTableTx[instance].revocationList.pList[2 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[1] == unitTableTx[instance].revocationList.pList[3 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ &&
++ (pHdcpBksvTested[0] == unitTableTx[instance].revocationList.pList[4 + (NbInRevocationList * HDMITX_KSV_BYTES_PER_DEVICE)])
++ )
++ {
++ *pbBksvSecure = False;
++ }
++ }
++ NbInRevocationList++;
++ }
++
++ }
++
++
++}
++#endif
++
++/******************************************************************************
++ \brief dlHdmiTxCalcVidFmtIndex.
++
++ \param vidFmt video format.
++
++ \return table index.
++
++******************************************************************************/
++static tmdlHdmiTxVidFmt_t dlHdmiTxCalcVidFmtIndex(tmdlHdmiTxVidFmt_t vidFmt)
++{
++ tmdlHdmiTxVidFmt_t vidFmtIndex = vidFmt;
++
++ /* Hanlde VIC or table index discontinuity */
++ if((vidFmt >= TMDL_HDMITX_VFMT_60_1280x720p_24Hz) && (vidFmt <= TMDL_HDMITX_VFMT_62_1280x720p_30Hz))
++ {
++ vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_INDEX_60_1280x720p_24Hz + (vidFmt - TMDL_HDMITX_VFMT_60_1280x720p_24Hz));
++ }
++#ifdef FORMAT_PC
++ else if (vidFmt >= TMDL_HDMITX_VFMT_PC_MIN)
++ {
++ vidFmtIndex = (tmdlHdmiTxVidFmt_t)(TMDL_HDMITX_VFMT_TV_NUM + (vidFmt - TMDL_HDMITX_VFMT_PC_MIN));
++ }
++#endif /* FORMAT_PC */
++ return(vidFmtIndex);
++}
++
++
++tmErrorCode_t tmdlHdmiTxDebugEnableI2CAccesses ( tmInstance_t instance,
++ Bool enableI2C)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++ /* Check if instance number is in range */
++ if( (instance < 0) || (instance >= MAX_UNITS) )
++ {
++ errCode = TMDL_ERR_DLHDMITX_BAD_INSTANCE;
++ return errCode;
++ }
++
++ if (enableI2C == True)
++ {
++ errCode = tmbslDebugWriteFakeRegPage(instance);
++ gI2CDebugAccessesEnabled = True;
++ }
++ else
++ {
++ gI2CDebugAccessesEnabled = False;
++ }
++
++
++ return errCode;
++
++} /* tmdlHdmiTxDebugManageI2CAccesses */
++
++/*****************************************************************************/
++/**
++ \brief Retreives current HDCP link status. This function is typically used
++ when an "HDCP INACTIVE" event is received to know why HDCP
++ is INACTIVE.
++
++ \param instance Instance identifier.
++ \param pHdcpStatus Pointer to the enum describing the status.
++ \param pRawStatus Pointer to the byte with the raw error code from HW.
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_BAD_HANDLE: the handle number is wrong
++ - TMDL_ERR_DLHDMITX_BAD_PARAMETER: a parameter is invalid or out
++ of range
++ - TMDL_ERR_DLHDMITX_NOT_INITIALIZED: the transmitter is not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetHdcpFailStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHdcpStatus_t *pHdcpStatus,
++ UInt8 *pRawStatus
++)
++{
++ tmErrorCode_t errCode = TM_OK;
++
++#ifndef NO_HDCP
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++ RETIF(pHdcpStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++ RETIF(pRawStatus == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ *pRawStatus = hdcpInfoListTx[instance].hdcpErrorState;
++
++ switch (hdcpInfoListTx[instance].hdcpErrorState)
++ {
++
++ case 0:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_OK;
++ break;
++
++ case 0x02:
++ case 0x03:
++ case 0x04:
++ case 0x05:
++ case 0x06:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_RCV_FAIL;
++ break;
++
++ case 0x08:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL;
++ break;
++
++ case 0x0C:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL;
++ break;
++
++ case 0x0F:
++ case 0x10:
++ case 0x11:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_AKSV_SEND_FAIL;
++ break;
++
++ case 0x23:
++ case 0x24:
++ case 0x25:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_R0_RCV_FAIL;
++ break;
++
++ case 0x26:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_R0_CHECK_FAIL;
++ break;
++
++ case 0x27:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_BKSV_NOT_SECURE;
++ break;
++
++ case 0x2B:
++ case 0x2C:
++ case 0x2D:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RI_RCV_FAIL;
++ break;
++
++ case 0x77:
++ case 0x78:
++ case 0x79:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL;
++ break;
++
++ case 0x2E:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RI_CHECK_FAIL;
++ break;
++
++ case 0x7A:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL;
++ break;
++
++ case 0x66:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL;
++ break;
++
++ case 0x67:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT;
++ break;
++
++ case 0x6A:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL;
++ break;
++
++ case 0x6C:
++ case 0x6D:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL;
++ break;
++
++ case 0x6F:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL;
++ break;
++
++ case 0x74:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE;
++ break;
++
++ default:
++ *pHdcpStatus = TMDL_HDMITX_HDCP_UNKNOWN_STATUS;
++ break;
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++#else
++ (void)instance; /* Remove compiler warning */
++#endif /* NO_HDCP */
++
++ return errCode;
++}
++
++
++tmErrorCode_t tmdlHdmiTxGetEdidLatencyInfo
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidLatency_t *pLatency
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check pointer is Null */
++ RETIF( pLatency == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetLatencyInfo(instance, (tmbslHdmiTxEdidLatency_t *) pLatency) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++} /* tmdlHdmiTxGetEdidLatencyInfo */
++
++/******************************************************************************
++ \brief Retrieves additional data from receiver's EDID VSDB. This function
++ parses the EDID of Rx device to get the relevant data.
++ This function is synchronous.
++ This function is not ISR friendly.
++
++ \param instance Instance identifier.
++ \param pExtraVsdbData Pointer to the structure of additional VSDB data
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_INSTANCE: the instance number is wrong or
++ out of range
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++ - TMDL_ERR_DLHDMITX_INVALID_STATE: the state is invalid for
++ the function
++ - TMBSL_ERR_HDMI_BAD_PARAMETER: a parameter was out of range
++ - TMBSL_ERR_HDMI_BAD_UNIT_NUMBER: bad transmitter unit number
++ - TMBSL_ERR_HDMI_RESOURCE_NOT_AVAILABLE : EDID not read
++ - TMBSL_ERR_HDMI_NOT_INITIALIZED: transmitter not initialized
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxGetEdidExtraVsdbData
++(
++ tmInstance_t instance,
++ tmdlHdmiTxEdidExtraVsdbData_t **pExtraVsdbData
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ /* Check pointer is Null */
++ RETIF(pExtraVsdbData == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Check the current state */
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ dlHdmiTxGetState(instance) != STATE_EDID_AVAILABLE, TMDL_ERR_DLHDMITX_INVALID_STATE)
++
++ RETIF_SEM(dlHdmiTxItSemaphore[instance],
++ (errCode = tmbslHdmiTxEdidGetExtraVsdbData(instance, (tmbslHdmiTxEdidExtraVsdbData_t **)pExtraVsdbData) ) != TM_OK, errCode)
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++} /* tmdlHdmiTxGetEdidExtraVsdbData */
++
++
++tmErrorCode_t tmdlHdmiTxGetHPDStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxHotPlug_t * pHPDStatus
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ RETIF( pHPDStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Get the HPD status from BSL driver */
++ errCode = tmbslHdmiTxHotPlugGetStatus(instance,(tmbslHdmiTxHotPlug_t *)pHPDStatus,True);
++
++ if (errCode == TM_OK) {
++ /* do nothing */
++ }
++ else {
++ *pHPDStatus = TMDL_HDMITX_HOTPLUG_INVALID;
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++
++} /* tmdlHdmiTxGetHPDStatus */
++
++
++
++tmErrorCode_t tmdlHdmiTxGetRXSenseStatus
++(
++ tmInstance_t instance,
++ tmdlHdmiTxRxSense_t * pRXSenseStatus
++)
++{
++ tmErrorCode_t errCode;
++
++ /* Check if instance number is in range */
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ RETIF( pRXSenseStatus== Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++
++ /* Take the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ /* Get the RXS sense status from BSL driver */
++ errCode = tmbslHdmiTxRxSenseGetStatus(instance,( tmbslHdmiTxRxSense_t*)pRXSenseStatus,True);
++
++ if (errCode == TM_OK) {
++ /* do nothing */
++ }
++ else {
++ *pRXSenseStatus = TMDL_HDMITX_RX_SENSE_INVALID;
++ }
++
++ /* Release the sempahore */
++ RETIF( (errCode = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCode)
++
++ return TM_OK;
++
++} /* tmdlHdmiTxGetRXSenseStatus */
++
++
++/******************************************************************************
++ \brief Mute or unmute the TMDS outputs.
++
++ \param instance Instance identifier.
++ \param muteTmdsOut Mute or unmute indication.
++
++ \return NA.
++
++******************************************************************************/
++tmErrorCode_t tmdlHdmiTxTmdsSetOutputsMute
++(
++ tmInstance_t instance,
++ Bool muteTmdsOut
++)
++{
++ tmErrorCode_t errCode;
++ tmErrorCode_t errCodeSem;
++ tmbslHdmiTxTmdsOut_t tmdsOut;
++
++ RETIF((instance < 0) || (instance >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_INSTANCE)
++
++ if (muteTmdsOut)
++ tmdsOut = HDMITX_TMDSOUT_FORCED0; // forced 0 outputs
++ else
++ tmdsOut = HDMITX_TMDSOUT_NORMAL; // normal outputs
++
++ /* Take the sempahore */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreP(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++ errCode = tmbslHdmiTxTmdsSetOutputs (instance, tmdsOut);
++
++ /* Release the sempahore */
++ RETIF( (errCodeSem = tmdlHdmiTxIWSemaphoreV(dlHdmiTxItSemaphore[instance]) ) != TM_OK, errCodeSem)
++
++
++ return errCode;
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c
+new file mode 100755
+index 0000000..fc6886d
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.c
+@@ -0,0 +1,342 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_local.c
++ *
++ * \version Revision: 1
++ *
++ * \date Date: 21/02/08
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ History: tmdlHdmiTx_local.c
++ *
++ * ***************** Version 1 *****************
++ * User: G. Burnouf Date: 21/02/08
++ * Updated in $/Source/tmdlHdmiTx/src
++ * initial version
++
++ \endverbatim
++ *
++*/
++
++/*============================================================================*/
++/* INCLUDE FILES */
++/*============================================================================*/
++#include "tmdlHdmiTx_local.h"
++#include "tmdlHdmiTx_cfg.h"
++#include "tmdlHdmiTx.h"
++
++/*============================================================================*/
++/* TYPES DECLARATIONS */
++/*============================================================================*/
++
++typedef struct _dlHdmiTxResolution_t {
++ tmdlHdmiTxVidFmt_t resolutionID;
++ UInt16 width;
++ UInt16 height;
++ Bool interlaced;
++ tmdlHdmiTxVfreq_t vfrequency;
++ tmdlHdmiTxPictAspectRatio_t aspectRatio;
++} dlHdmiTxResolution_t, *pdlHdmiTxResolution_t;
++
++
++/*============================================================================*/
++/* CONSTANTS DECLARATIONS */
++/*============================================================================*/
++/* macro for quick error handling */
++#ifndef RETIF
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++#endif
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++/******************************************************************************/
++/* DO NOT MODIFY */
++/******************************************************************************/
++
++static void dlHdmiTxGenerateVideoPortTables
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxDriverConfigTable_t *pConfig
++);
++
++
++/*============================================================================*/
++/* VARIABLES DECLARATIONS */
++/*============================================================================*/
++
++/**
++ * \brief List of the resolution to be detected by the device library
++ */
++
++#ifdef TMFL_OS_WINDOWS /* OS Windows */
++dlHdmiTxResolution_t resolutionInfoTx[RESOLUTION_NB] = {
++#else /* OS ARM7 */
++const dlHdmiTxResolution_t resolutionInfoTx[RESOLUTION_NB] = {
++#endif /* endif TMFL_OS_WINDOWS */
++ /* TV Formats */
++ /* 60 HZ */
++ {TMDL_HDMITX_VFMT_01_640x480p_60Hz, 640, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_02_720x480p_60Hz, 720, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_03_720x480p_60Hz, 720, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_04_1280x720p_60Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_05_1920x1080i_60Hz, 1920, 1080, True, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_06_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_07_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_08_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_09_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_10_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_11_720x480i_60Hz, 720, 480, True, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_12_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_13_720x240p_60Hz, 720, 240, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_14_1440x480p_60Hz, 1440, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_15_1440x480p_60Hz, 1440, 480, False, TMDL_HDMITX_VFREQ_59Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_16_1920x1080p_60Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_35_2880x480p_60Hz, 2880, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_36_2880x480p_60Hz, 2880, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++
++ /* 50 HZ */
++ {TMDL_HDMITX_VFMT_17_720x576p_50Hz, 720, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_18_720x576p_50Hz, 720, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_19_1280x720p_50Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_20_1920x1080i_50Hz, 1920, 1080, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_21_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_22_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_23_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_24_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_25_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_26_720x576i_50Hz, 720, 576, True, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_27_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_28_720x288p_50Hz, 720, 288, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_29_1440x576p_50Hz, 1440, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_30_1440x576p_50Hz, 1440, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_31_1920x1080p_50Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_37_2880x576p_50Hz, 2880, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_38_2880x576p_50Hz, 2880, 576, False, TMDL_HDMITX_VFREQ_50Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++
++ /* Low Tv */
++ {TMDL_HDMITX_VFMT_32_1920x1080p_24Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_24Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_33_1920x1080p_25Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_25Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_34_1920x1080p_30Hz, 1920, 1080, False, TMDL_HDMITX_VFREQ_30Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_60_1280x720p_24Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_24Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_61_1280x720p_25Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_25Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_62_1280x720p_30Hz, 1280, 720, False, TMDL_HDMITX_VFREQ_30Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9}
++
++#ifdef FORMAT_PC
++ /* PC Formats */
++ /* 60 HZ */
++ ,{TMDL_HDMITX_VFMT_PC_640x480p_60Hz, 640, 480, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_800x600p_60Hz, 800, 600, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1152x960p_60Hz, 1152, 960, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_6_5},
++ {TMDL_HDMITX_VFMT_PC_1024x768p_60Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1280x768p_60Hz, 1280, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_3},
++ {TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4},
++ {TMDL_HDMITX_VFMT_PC_1360x768p_60Hz, 1360, 768, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_9},
++ {TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz, 1400, 1050, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz, 1600, 1200, False, TMDL_HDMITX_VFREQ_60Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ /* 70 HZ */
++ {TMDL_HDMITX_VFMT_PC_1024x768p_70Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_70Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ /* 72 HZ */
++ {TMDL_HDMITX_VFMT_PC_640x480p_72Hz, 640, 480, False, TMDL_HDMITX_VFREQ_72Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_800x600p_72Hz, 800, 600, False, TMDL_HDMITX_VFREQ_72Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ /* 75 HZ */
++ {TMDL_HDMITX_VFMT_PC_640x480p_75Hz, 640, 480, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1024x768p_75Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_800x600p_75Hz, 800, 600, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1024x864p_75Hz, 1024, 864, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED},
++ {TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_75Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4},
++ /* 85 HZ */
++ {TMDL_HDMITX_VFMT_PC_640x350p_85Hz, 640, 350, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED},
++ {TMDL_HDMITX_VFMT_PC_640x400p_85Hz, 640, 400, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_16_10},
++ {TMDL_HDMITX_VFMT_PC_720x400p_85Hz, 720, 400, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_9_5},
++ {TMDL_HDMITX_VFMT_PC_640x480p_85Hz, 640, 480, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_800x600p_85Hz, 800, 600, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1024x768p_85Hz, 1024, 768, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1152x864p_85Hz, 1152, 864, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1280x960p_85Hz, 1280, 960, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3},
++ {TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz, 1280, 1024, False, TMDL_HDMITX_VFREQ_85Hz, TMDL_HDMITX_P_ASPECT_RATIO_5_4},
++ /* 87 HZ */
++ {TMDL_HDMITX_VFMT_PC_1024x768i_87Hz, 1024, 768, True, TMDL_HDMITX_VFREQ_87Hz, TMDL_HDMITX_P_ASPECT_RATIO_4_3}
++#endif /* FORMAT_PC */
++};
++
++
++/*============================================================================*/
++/* FUNCTION */
++/*============================================================================*/
++
++/******************************************************************************/
++/* DO NOT MODIFY */
++/******************************************************************************
++ \brief This function allows to the main driver to retrieve its
++ configuration parameters.
++
++ \param pConfig Pointer to the config structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t dlHdmiTxGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxDriverConfigTable_t *pConfig
++)
++{
++ /* Check if unit number is in range */
++ RETIF((unit < 0) || (unit >= MAX_UNITS), TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER)
++
++ /* Check if pointer is Null */
++ RETIF(pConfig == Null, TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS)
++
++ *pConfig = driverConfigTableTx[unit];
++
++ /* Done here because of const declaration of tables in ARM7 case */
++ pConfig->pResolutionInfo = (ptmdlHdmiTxCfgResolution_t)resolutionInfoTx;
++
++ /* Generate swap and mirror tables in function of video port mapping tables */
++ dlHdmiTxGenerateVideoPortTables(unit, pConfig);
++
++ return TM_OK;
++}
++
++
++/*============================================================================*/
++/* INTERNAL FUNCTION */
++/*============================================================================*/
++/******************************************************************************/
++/* DO NOT MODIFY */
++/******************************************************************************/
++static void dlHdmiTxGenerateVideoPortTables
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxDriverConfigTable_t *pConfig
++)
++{
++ UInt8 i;
++
++ for (i=0; i<6; i++)
++ {
++ /* CCIR656 */
++ if (videoPortMapping_CCIR656[unit][i] != TMDL_HDMITX_VIDCCIR_NOT_CONNECTED)
++ {
++ pConfig->pSwapTableCCIR656[videoPortMapping_CCIR656[unit][i] & 0x07F] = 5-i;
++ pConfig->pMirrorTableCCIR656[videoPortMapping_CCIR656[unit][i] & 0x07F] = (UInt8)(videoPortMapping_CCIR656[unit][i] >> 7);
++ /* Enable port and disable ground port */
++ if (((5-i) % 2) == 0)
++ {
++ pConfig->pEnableVideoPortCCIR656[i/2] |= 0x0F;
++ pConfig->pGroundVideoPortCCIR656[i/2] = (UInt8)(pConfig->pGroundVideoPortCCIR656[i/2] & 0xF0);
++ }
++ else
++ {
++ pConfig->pEnableVideoPortCCIR656[i/2] = (UInt8)(pConfig->pEnableVideoPortCCIR656[i/2] | 0xF0);
++ pConfig->pGroundVideoPortCCIR656[i/2] &= 0x0F;
++ }
++ }
++
++ /* YUV422 */
++ if (videoPortMapping_YUV422[unit][i] != TMDL_HDMITX_VID422_NOT_CONNECTED)
++ {
++ pConfig->pSwapTableYUV422[videoPortMapping_YUV422[unit][i] & 0x07F] = 5-i;
++ pConfig->pMirrorTableYUV422[videoPortMapping_YUV422[unit][i] & 0x07F] = (UInt8)(videoPortMapping_YUV422[unit][i] >> 7);
++ /* Enable port and disable ground port */
++ if (((5-i) % 2) == 0)
++ {
++ pConfig->pEnableVideoPortYUV422[i/2] |= 0x0F;
++ pConfig->pGroundVideoPortYUV422[i/2] = (UInt8)(pConfig->pGroundVideoPortYUV422[i/2] & 0xF0);
++ }
++ else
++ {
++ pConfig->pEnableVideoPortYUV422[i/2] = (UInt8)(pConfig->pEnableVideoPortYUV422[i/2] | 0xF0);
++ pConfig->pGroundVideoPortYUV422[i/2] &= 0x0F;
++ }
++ }
++
++ /* YUV444 */
++ if (videoPortMapping_YUV444[unit][i] != TMDL_HDMITX_VID444_NOT_CONNECTED)
++ {
++ pConfig->pSwapTableYUV444[videoPortMapping_YUV444[unit][i] & 0x07F] = 5-i;
++ pConfig->pMirrorTableYUV444[videoPortMapping_YUV444[unit][i] & 0x07F] = (UInt8)(videoPortMapping_YUV444[unit][i] >> 7);
++ /* Enable port and disable ground port */
++ if (((5-i) % 2) == 0)
++ {
++ pConfig->pEnableVideoPortYUV444[i/2] |= 0x0F;
++ pConfig->pGroundVideoPortYUV444[i/2] = (UInt8)(pConfig->pGroundVideoPortYUV444[i/2] & 0xF0);
++ }
++ else
++ {
++ pConfig->pEnableVideoPortYUV444[i/2] = (UInt8)(pConfig->pEnableVideoPortYUV444[i/2] | 0xF0);
++ pConfig->pGroundVideoPortYUV444[i/2] &= 0x0F;
++ }
++ }
++
++ /* RGB444 */
++ if (videoPortMapping_RGB444[unit][i] != TMDL_HDMITX_VID444_NOT_CONNECTED)
++ {
++ pConfig->pSwapTableRGB444[videoPortMapping_RGB444[unit][i] & 0x07F] = 5-i;
++ pConfig->pMirrorTableRGB444[videoPortMapping_RGB444[unit][i] & 0x07F] = (UInt8)(videoPortMapping_RGB444[unit][i] >> 7);
++ /* Enable port and disable ground port */
++ if (((5-i) % 2) == 0)
++ {
++ pConfig->pEnableVideoPortRGB444[i/2] |= 0x0F;
++ pConfig->pGroundVideoPortRGB444[i/2] = (UInt8)(pConfig->pGroundVideoPortRGB444[i/2] & 0xF0);
++ }
++ else
++ {
++ pConfig->pEnableVideoPortRGB444[i/2] = (UInt8)(pConfig->pEnableVideoPortRGB444[i/2] | 0xF0);
++ pConfig->pGroundVideoPortRGB444[i/2] &= 0x0F;
++ }
++ }
++
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /* RGB DDR 12bits */
++ if (VideoPortMapping_RGB_DDR_12bits[unit][i] != TMDL_HDMITX_VID_DDR_NOT_CONNECTED)
++ {
++ pConfig->pSwapTableRGB_DDR_12bits[VideoPortMapping_RGB_DDR_12bits[unit][i] & 0x07F] = 5-i;
++ pConfig->pMirrorTableRGB_DDR_12bits[VideoPortMapping_RGB_DDR_12bits[unit][i] & 0x07F] = (UInt8)(VideoPortMapping_RGB_DDR_12bits[unit][i] >> 7);
++ /* Enable port and disable ground port */
++ if (((5-i) % 2) == 0)
++ {
++ pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] |= 0x0F;
++ pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] = (UInt8)(pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] & 0xF0);
++ }
++ else
++ {
++ pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] = (UInt8)(pConfig->pEnableVideoPortRGB_DDR_12bits[i/2] | 0xF0);
++ pConfig->pGroundVideoPortRGB_DDR_12bits[i/2] &= 0x0F;
++ }
++ }
++#endif
++ }
++
++#ifdef TMFL_RGB_DDR_12BITS
++ /* VIP internal mux for RGB DDR */
++ pConfig->pNoMux = (UInt8*)&VideoPortNoMux[unit];
++ pConfig->pMux_RGB_DDR_12bits = (UInt8*)&VideoPortMux_RGB_DDR_12bits[unit];
++#endif
++
++}
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h
+new file mode 100755
+index 0000000..ccda7bf
+--- /dev/null
++++ b/drivers/video/nxp/comps/tmdlHdmiTx/src/tmdlHdmiTx_local.h
+@@ -0,0 +1,702 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * \file tmdlHdmiTx_local.h
++ *
++ * \version $Revision: 1 $
++ *
++ * \date $Date: 02/08/07 08:32 $
++ *
++ * \brief devlib driver component API for the TDA998x HDMI Transmitters
++ *
++ * \section refs Reference Documents
++ * HDMI Tx Driver - FRS.doc,
++ *
++ * \section info Change Information
++ *
++ * \verbatim
++
++ $History: tmdlHdmiTx_local.h $
++ *
++ * ***************** Version 13 *****************
++ * User: J. Lamotte Date: 02/08/07 Time: 08:32
++ * Updated in $/Source/tmdlHdmiTx/inc
++ * initial version
++ *
++
++ \endverbatim
++ *
++*/
++
++#ifndef TMDLHDMITX_LOCAL_H
++#define TMDLHDMITX_LOCAL_H
++
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#include <linux/kernel.h>
++#endif
++
++#include "tmdlHdmiTx_IW.h"
++#include "tmNxTypes.h"
++#include "tmdlHdmiTx_Types.h"
++#include "tmdlHdmiTx_cfg.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*============================================================================*/
++/* MACRO DEFINITIONS */
++/*============================================================================*/
++
++/* Version of the SW driver */
++#define VERSION_COMPATIBILITY 0
++#define VERSION_MAJOR 5
++#define VERSION_MINOR 3
++
++/* Invalid HDCP seed */
++#define HDCP_SEED_NULL 0
++
++/* A default seed value may be defined here, or set to HDCP_SEED_NULL.
++ * If HDCP_SEED_NULL, a table of seeds may instead be programmed separately
++ * into flash at the location of kSeedTable, below */
++#define HDCP_SEED_DEFAULT HDCP_SEED_NULL
++
++/* Default SHA-1 test handling */
++#define HDCP_OPT_DEFAULT ( TMDL_HDMITX_HDCP_OPTION_FORCE_PJ_IGNORED \
++ | TMDL_HDMITX_HDCP_OPTION_FORCE_VSLOW_DDC \
++ | TMDL_HDMITX_HDCP_OPTION_FORCE_NO_1_1 )
++
++/**
++ * A macro to check a condition and if true return a result
++ */
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#define RETIF(cond, rslt) if ((cond)){ \
++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \
++ return (rslt);}
++#else
++#define RETIF(cond, rslt) if ((cond)){return (rslt);}
++#endif
++
++/**
++ * A macro to check a condition and if true return
++ * TMDL_ERR_DLHDMITX_BAD_PARAMETER.
++ * To save code space, it can be compiled out by defining NO_RETIF_BADPARAM on
++ * the compiler command line.
++ */
++#ifdef NO_RETIF_BADPARAM
++#define RETIF_BADPARAM(cond)
++#else
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#define RETIF_BADPARAM(cond) if ((cond)){ \
++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \
++ return TMDL_ERR_DLHDMITX_BAD_PARAMETER;}
++#else
++#define RETIF_BADPARAM(cond) if ((cond)){return TMDL_ERR_DLHDMITX_BAD_PARAMETER;}
++#endif
++#endif
++
++/**
++ * A macro to check a condition and if true, release the semaphore describe by handle and return a result
++ */
++#ifdef TMFL_LINUX_OS_KERNEL_DRIVER
++#define RETIF_SEM(handle, cond, rslt) if ((cond)){ \
++ tmdlHdmiTxIWSemaphoreV(handle); \
++ printk(KERN_INFO "%s %d\n",__func__,__LINE__); \
++ return (rslt);}
++#else
++#define RETIF_SEM(handle, cond, rslt) if ((cond)){tmdlHdmiTxIWSemaphoreV(handle); return (rslt);}
++#endif
++
++ /* Resolution supported */
++#ifndef FORMAT_PC
++#define RESOLUTION_NB 41
++#else
++#define RESOLUTION_NB 68
++#endif /* FORMAT_PC */
++
++/* Instance number */
++#define INSTANCE_0 0
++#define INSTANCE_1 1
++
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++/* Number of event */
++#define EVENT_NB 10
++#else /* HDMI_TX_REPEATER_ISR_MODE */
++/* Number of event */
++#define EVENT_NB 9
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++
++/* Size of a KSV is five bytes */
++#define KSV_SIZE 5
++
++/* Arbitrary short TV format values */
++#define TV_INVALID 0
++#define TV_VGA_60Hz 1
++#define TV_240p_60Hz 2
++#define TV_480p_60Hz 3
++#define TV_480i_60Hz 4
++#define TV_720p_60Hz 5
++#define TV_1080p_60Hz 6
++#define TV_1080i_60Hz 7
++#define TV_288p_50Hz 8
++#define TV_576p_50Hz 9
++#define TV_576i_50Hz 10
++#define TV_720p_50Hz 11
++#define TV_1080p_50Hz 12
++#define TV_1080i_50Hz 13
++
++/* Shorthands for vinMode values in tmbslTDA9984.h */
++#define iINVALID TMDL_HDMITX_VINMODE_INVALID
++#define iCCIR656 TMDL_HDMITX_VINMODE_CCIR656
++#define iRGB444 TMDL_HDMITX_VINMODE_RGB444
++#define iYUV444 TMDL_HDMITX_VINMODE_YUV444
++#define iYUV422 TMDL_HDMITX_VINMODE_YUV422
++
++/* Shorthands for input sync */
++#define EMB 1
++#define EXT 0
++
++/* Shorthands for single/double pixel rate in tmbslTDA9984.h */
++#define SINGLE TMDL_HDMITX_PIXRATE_SINGLE
++#define DOUBLE TMDL_HDMITX_PIXRATE_DOUBLE
++
++/* Shorthands for sampling frequency in tmdlHdmiTxSetAudioInput API */
++#define AIF_SF_REFER_TO_STREAM_HEADER 0
++#define AIF_SF_32K 1
++#define AIF_SF_44K 2
++#define AIF_SF_48K 3
++#define AIF_SF_88K 4
++#define AIF_SF_96K 5
++#define AIF_SF_176K 6
++#define AIF_SF_192K 7
++
++/* HDCP check interval in milliseconds */
++#define HDCP_CHECK_INTERVAL_MS 2500
++
++/* Number of HDCP checks to carry out after HDCP is started */
++#define HDCP_NUM_CHECKS 5
++
++#define TMDL_HDMITX_CHANNELALLOC_LUT_SIZE 32
++
++
++static CONST_DAT UInt8 kChanAllocChanNum[TMDL_HDMITX_CHANNELALLOC_LUT_SIZE] = \
++{2,3,3,4,3,4,4,5,4,5,5,6,5,6,6,7,6,7,7,8,4,5,5,6,5,6,6,7,6,7,7,8 };
++
++
++/**
++ * Lookup table to convert from EIA/CEA TV video format to
++ * aspect ratio used in video infoframe:
++ * Aspect ratio 1=4:3, 2=16:9
++ */
++#ifndef FORMAT_PC
++static CONST_DAT UInt8 kVfmtToAspect_TV[TMDL_HDMITX_VFMT_TV_NUM] =
++#else /* FORMAT_PC */
++static CONST_DAT UInt8 kVfmtToAspect_TV[TMDL_HDMITX_VFMT_TV_NUM + TMDL_HDMITX_VFMT_PC_NUM] =
++#endif /* FORMAT_PC */
++{
++ 0, /* HDMITX_VFMT_NULL */
++ 1, /* HDMITX_VFMT_01_640x480p_60Hz */
++ 1, /* HDMITX_VFMT_02_720x480p_60Hz */
++ 2, /* HDMITX_VFMT_03_720x480p_60Hz */
++ 2, /* HDMITX_VFMT_04_1280x720p_60Hz */
++ 2, /* HDMITX_VFMT_05_1920x1080i_60Hz */
++ 1, /* HDMITX_VFMT_06_720x480i_60Hz */
++ 2, /* HDMITX_VFMT_07_720x480i_60Hz */
++ 1, /* HDMITX_VFMT_08_720x240p_60Hz */
++ 2, /* HDMITX_VFMT_09_720x240p_60Hz */
++ 1, /* HDMITX_VFMT_10_720x480i_60Hz */
++ 2, /* HDMITX_VFMT_11_720x480i_60Hz */
++ 1, /* HDMITX_VFMT_12_720x240p_60Hz */
++ 2, /* HDMITX_VFMT_13_720x240p_60Hz */
++ 1, /* HDMITX_VFMT_14_1440x480p_60Hz */
++ 2, /* HDMITX_VFMT_15_1440x480p_60Hz */
++ 2, /* HDMITX_VFMT_16_1920x1080p_60Hz */
++ 1, /* HDMITX_VFMT_17_720x576p_50Hz */
++ 2, /* HDMITX_VFMT_18_720x576p_50Hz */
++ 2, /* HDMITX_VFMT_19_1280x720p_50Hz */
++ 2, /* HDMITX_VFMT_20_1920x1080i_50Hz */
++ 1, /* HDMITX_VFMT_21_720x576i_50Hz */
++ 2, /* HDMITX_VFMT_22_720x576i_50Hz */
++ 1, /* HDMITX_VFMT_23_720x288p_50Hz */
++ 2, /* HDMITX_VFMT_24_720x288p_50Hz */
++ 1, /* HDMITX_VFMT_25_720x576i_50Hz */
++ 2, /* HDMITX_VFMT_26_720x576i_50Hz */
++ 1, /* HDMITX_VFMT_27_720x288p_50Hz */
++ 2, /* HDMITX_VFMT_28_720x288p_50Hz */
++ 1, /* HDMITX_VFMT_29_1440x576p_50Hz */
++ 2, /* HDMITX_VFMT_30_1440x576p_50Hz */
++ 2, /* HDMITX_VFMT_31_1920x1080p_50Hz */
++ 2, /* HDMITX_VFMT_32_1920x1080p_24Hz */
++ 2, /* HDMITX_VFMT_33_1920x1080p_25Hz */
++ 2, /* HDMITX_VFMT_34_1920x1080p_30Hz */
++
++ 1, /* TMDL_HDMITX_VFMT_35_2880x480p_60Hz */
++ 2, /* TMDL_HDMITX_VFMT_36_2880x480p_60Hz */
++ 1, /* TMDL_HDMITX_VFMT_37_2880x576p_50Hz */
++ 2, /* TMDL_HDMITX_VFMT_38_2880x576p_50Hz */
++
++ 2, /* TMDL_HDMITX_VFMT_60_1280x720p_24HZ */
++ 2, /* TMDL_HDMITX_VFMT_61_1280_720p_25HZ */
++ 2 /* TMDL_HDMITX_VFMT_62_1280_720p_30HZ */
++
++#ifdef FORMAT_PC
++ ,1, /* HDMITX_VFMT_PC_640x480p_60Hz */
++ 1, /* HDMITX_VFMT_PC_800x600p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1152x960p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1024x768p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1280x768p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1280x1024p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1360x768p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1400x1050p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1600x1200p_60Hz */
++ 1, /* HDMITX_VFMT_PC_1024x768p_70Hz */
++ 1, /* HDMITX_VFMT_PC_640x480p_72Hz */
++ 1, /* HDMITX_VFMT_PC_800x600p_72Hz */
++ 1, /* HDMITX_VFMT_PC_640x480p_75Hz */
++ 1, /* HDMITX_VFMT_PC_1024x768p_75Hz */
++ 1, /* HDMITX_VFMT_PC_800x600p_75Hz */
++ 1, /* HDMITX_VFMT_PC_1024x864p_75Hz */
++ 1, /* HDMITX_VFMT_PC_1280x1024p_75Hz */
++ 1, /* HDMITX_VFMT_PC_640x350p_85Hz */
++ 1, /* HDMITX_VFMT_PC_640x400p_85Hz */
++ 1, /* HDMITX_VFMT_PC_720x400p_85Hz */
++ 1, /* HDMITX_VFMT_PC_640x480p_85Hz */
++ 1, /* HDMITX_VFMT_PC_800x600p_85Hz */
++ 1, /* HDMITX_VFMT_PC_1024x768p_85Hz */
++ 1, /* HDMITX_VFMT_PC_1152x864p_85Hz */
++ 1, /* HDMITX_VFMT_PC_1280x960p_85Hz */
++ 1, /* HDMITX_VFMT_PC_1280x1024p_85Hz */
++ 1 /* HDMITX_VFMT_PC_1024x768i_87Hz */
++#endif /* FORMAT_PC */
++};
++
++/**
++ * Lookup table to convert from EIA/CEA TV video format to
++ * the short format of resolution/interlace/frequency
++ */
++static CONST_DAT UInt8 kVfmtToShortFmt_TV[TMDL_HDMITX_VFMT_TV_NUM] =
++{
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_VGA_60Hz, /* HDMITX_VFMT_01_640x480p_60Hz */
++ TV_480p_60Hz, /* HDMITX_VFMT_02_720x480p_60Hz */
++ TV_480p_60Hz, /* HDMITX_VFMT_03_720x480p_60Hz */
++ TV_720p_60Hz, /* HDMITX_VFMT_04_1280x720p_60Hz */
++ TV_1080i_60Hz, /* HDMITX_VFMT_05_1920x1080i_60Hz */
++ TV_480i_60Hz, /* HDMITX_VFMT_06_720x480i_60Hz */
++ TV_480i_60Hz, /* HDMITX_VFMT_07_720x480i_60Hz */
++ TV_240p_60Hz, /* HDMITX_VFMT_08_720x240p_60Hz */
++ TV_240p_60Hz, /* HDMITX_VFMT_09_720x240p_60Hz */
++ TV_480i_60Hz, /* HDMITX_VFMT_10_720x480i_60Hz */
++ TV_480i_60Hz, /* HDMITX_VFMT_11_720x480i_60Hz */
++ TV_240p_60Hz, /* HDMITX_VFMT_12_720x240p_60Hz */
++ TV_240p_60Hz, /* HDMITX_VFMT_13_720x240p_60Hz */
++ TV_480p_60Hz, /* HDMITX_VFMT_14_1440x480p_60Hz */
++ TV_480p_60Hz, /* HDMITX_VFMT_15_1440x480p_60Hz */
++ TV_1080p_60Hz, /* HDMITX_VFMT_16_1920x1080p_60Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_17_720x576p_50Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_18_720x576p_50Hz */
++ TV_720p_50Hz, /* HDMITX_VFMT_19_1280x720p_50Hz */
++ TV_1080i_50Hz, /* HDMITX_VFMT_20_1920x1080i_50Hz */
++ TV_576i_50Hz, /* HDMITX_VFMT_21_720x576i_50Hz */
++ TV_576i_50Hz, /* HDMITX_VFMT_22_720x576i_50Hz */
++ TV_288p_50Hz, /* HDMITX_VFMT_23_720x288p_50Hz */
++ TV_288p_50Hz, /* HDMITX_VFMT_24_720x288p_50Hz */
++ TV_576i_50Hz, /* HDMITX_VFMT_25_720x576i_50Hz */
++ TV_576i_50Hz, /* HDMITX_VFMT_26_720x576i_50Hz */
++ TV_288p_50Hz, /* HDMITX_VFMT_27_720x288p_50Hz */
++ TV_288p_50Hz, /* HDMITX_VFMT_28_720x288p_50Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_29_1440x576p_50Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_30_1440x576p_50Hz */
++ TV_1080p_50Hz, /* HDMITX_VFMT_31_1920x1080p_50Hz */
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_480p_60Hz, /* HDMITX_VFMT_35_2880x480p_60Hz */
++ TV_480p_60Hz, /* HDMITX_VFMT_36_2880x480p_60Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_37_2880x576p_50Hz */
++ TV_576p_50Hz, /* HDMITX_VFMT_38_2880x576p_50Hz */
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_INVALID, /* HDMITX_VFMT_NULL */
++ TV_INVALID /* HDMITX_VFMT_NULL */
++};
++
++/**
++ * Macro to pack vinMode(0-5), pixRate(0-1), syncIn(0-1) and bVerified(0-1)
++ * into a byte
++ */
++#define PKBYTE(mode,rate,sync,verf) (((rate)<<7)|((sync)<<6)|((verf)<<5)|((mode)&0x1F))
++
++/**
++ * Macros to unpack vinMode(0-5), pixRate(0-1), syncIn(0-1) and bVerified(0-1)
++ * from a byte
++ */
++#define UNPKRATE(byte) (((byte)>>7)&1)
++#define UNPKSYNC(byte) (((byte)>>6)&1)
++#define UNPKVERF(byte) (((byte)>>5)&1)
++#define UNPKMODE(byte) ((byte)&0x1F)
++
++/**
++ * Lookup table to match main video settings and look up sets of
++ * Refpix and Refline values
++ */
++static CONST_DAT struct
++{
++ /* Values to match */
++ UInt8 modeRateSyncVerf; /* Packed vinMode, pixRate, syncIn, bVerified */
++ UInt8 shortVinFmt;
++ UInt8 shortVoutFmt;
++ /* Values to look up */
++ UInt16 refPix; /* Output values */
++ UInt16 refLine;
++ UInt16 scRefPix; /* Scaler values */
++ UInt16 scRefLine;
++} kRefpixRefline [] =
++{
++ /*************************************************************/
++ /** Rows formatted in "Refpix_Refline.xls" and pasted here **/
++ /** DO NOT DELETE ANY ROWS, to keep all scaler combinations **/
++ /*************************************************************/
++ /* mode_____Rate___Sync_Verf shortVinFmt shortVoutFmt refPix refLine scRefPix scRefLine Test ID */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08b, 0x024, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08b, 0x012, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08b, 0x00e, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08b, 0x021, 0x078, 0x017}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08b, 0x017, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08b, 0x013, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08b, 0x027, 0x07A, 0x02c}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x091, 0x026, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x091, 0x013, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x091, 0x00f, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x091, 0x022, 0x085, 0x018}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x091, 0x019, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x091, 0x014, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,SINGLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x091, 0x028, 0x087, 0x02e}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x014, 0x20d, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x014, 0x2cb, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x014, 0x44c, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x014, 0x436, 0x359, 0x004}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x011, 0x2d3, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x011, 0x452, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x011, 0x43e, 0x358, 0x007}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00d, 0x26b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00d, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00d, 0x44b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00d, 0x435, 0x35f, 0x001}, /* */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00d, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00d, 0x451, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,SINGLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00d, 0x43d, 0x35f, 0x001}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08b, 0x024, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08b, 0x012, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08b, 0x00e, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08b, 0x021, 0x078, 0x017}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08b, 0x017, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08b, 0x013, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08b, 0x027, 0x07A, 0x02c}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x091, 0x026, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x091, 0x013, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x091, 0x00f, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x091, 0x022, 0x085, 0x018}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x091, 0x019, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x091, 0x014, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,DOUBLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x091, 0x028, 0x087, 0x02e}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x014, 0x20d, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x014, 0x2cb, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x014, 0x44c, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x014, 0x436, 0x359, 0x004}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x011, 0x2d3, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x011, 0x452, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x011, 0x43e, 0x358, 0x007}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00d, 0x26b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00d, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00d, 0x44b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00d, 0x435, 0x35f, 0x001}, /* */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00d, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00d, 0x451, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iCCIR656,DOUBLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00d, 0x43d, 0x35f, 0x001}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_480p_60Hz, 0x08d, 0x028, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_720p_60Hz, 0x08d, 0x014, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x08d, 0x010, 0x078, 0x017}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x08d, 0x021, 0x078, 0x017}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_720p_60Hz, 0x08d, 0x017, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x08d, 0x014, 0x078, 0x02c}, /* VID_F_01 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x08d, 0x027, 0x07C, 0x02c}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_576p_50Hz, 0x093, 0x02a, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_720p_50Hz, 0x093, 0x013, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x093, 0x00e, 0x085, 0x018}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x093, 0x022, 0x085, 0x018}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_720p_50Hz, 0x093, 0x019, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x093, 0x014, 0x085, 0x02e}, /* VID_F_06 */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x093, 0x028, 0x089, 0x02e}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_720p_50Hz, TV_1080p_50Hz, 0x2bf, 0x024, 0x105, 0x019}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_720p_60Hz, TV_1080p_60Hz, 0x175, 0x024, 0x105, 0x019}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_1080i_50Hz, TV_1080p_50Hz, 0x2d3, 0x023, 0x0c3, 0x014}, /* */
++ {PKBYTE(iYUV422, SINGLE,EMB, 1), TV_1080i_60Hz, TV_1080p_60Hz, 0x11b, 0x023, 0x0c3, 0x014}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_480p_60Hz, 0x016, 0x20d, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_720p_60Hz, 0x016, 0x2cb, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_1080i_60Hz, 0x016, 0x44c, 0x359, 0x004}, /* VID_F_04 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480i_60Hz, TV_1080p_60Hz, 0x016, 0x436, 0x359, 0x004}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_720p_60Hz, 0x013, 0x2d3, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_1080i_60Hz, 0x013, 0x452, 0x358, 0x007}, /* VID_F_01 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_480p_60Hz, TV_1080p_60Hz, 0x013, 0x43e, 0x358, 0x007}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_576p_50Hz, 0x00f, 0x26b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_720p_50Hz, 0x00f, 0x2cb, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_1080i_50Hz, 0x00f, 0x44b, 0x35f, 0x001}, /* VID_F_09 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576i_50Hz, TV_1080p_50Hz, 0x00f, 0x435, 0x35f, 0x001}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_720p_50Hz, 0x00f, 0x2d1, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_1080i_50Hz, 0x00f, 0x451, 0x35f, 0x001}, /* VID_F_06 */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_576p_50Hz, TV_1080p_50Hz, 0x00f, 0x43d, 0x35f, 0x001}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_720p_50Hz, TV_1080p_50Hz, 0x1bb, 0x463, 0x7bb, 0x000}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_720p_60Hz, TV_1080p_60Hz, 0x071, 0x463, 0x671, 0x000}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_1080i_50Hz, TV_1080p_50Hz, 0x213, 0x460, 0xa4f, 0x000}, /* */
++ {PKBYTE(iYUV422, SINGLE,EXT, 1), TV_1080i_60Hz, TV_1080p_60Hz, 0x05b, 0x460, 0x897, 0x000}, /* */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV422, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV422, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, SINGLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, SINGLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iYUV444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, SINGLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_480p_60Hz, TV_VGA_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, SINGLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, DOUBLE,EMB, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_480p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480i_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_04 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_720p_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_480p_60Hz, TV_1080i_60Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_01 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_576p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576i_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_09 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_720p_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iRGB444, DOUBLE,EXT, 0), TV_576p_50Hz, TV_1080i_50Hz, 0x000, 0x000, 0x000, 0x000}, /* VID_F_06 */
++ {PKBYTE(iINVALID,DOUBLE,EMB, 0), TV_INVALID, TV_INVALID, 0x000, 0x000, 0x000, 0x000} /* EndTable */
++};
++
++
++/*============================================================================*/
++/* ENUM OR TYPE DEFINITIONS */
++/*============================================================================*/
++/* Enum listing all the type of colorimetry */
++typedef enum
++{
++ TMDL_HDMITX_COLORIMETRY_NO_DATA = 0,
++ TMDL_HDMITX_COLORIMETRY_ITU601 = 1,
++ TMDL_HDMITX_COLORIMETRY_ITU709 = 2,
++ TMDL_HDMITX_COLORIMETRY_EXTENDED = 3
++} tmdlHdmiTxColorimetry_t;
++
++/* Possible states of the state machine */
++typedef enum
++{
++ STATE_NOT_INITIALIZED, /**< Driver is not initialized */
++ STATE_INITIALIZED, /**< Driver is initialized */
++ STATE_UNPLUGGED, /**< Receiver device not connected */
++ STATE_PLUGGED, /**< Receiver device connected, clock lock */
++ STATE_EDID_AVAILABLE /**< Managed to read receiver's EDID */
++} tmdlHdmiTxDriverState_t;
++
++/* revocation list structure */
++typedef struct
++{
++ UInt8* pList;
++ UInt32 length;
++} revocationList_t;
++
++
++/* unit configuration structure */
++typedef struct
++{
++ Bool opened; /**< Is unit instanciated ? */
++ Bool hdcpEnable; /**< Is HDCP enabled ? */
++ tmdlHdmiTxHdcpOptions_t hdcpOptions; /**< HDCP options */
++ Bool repeaterEnable; /**< Is repeater enabled ? */
++ Bool simplayHd; /**< Enable simplayHD support */
++ tmdlHdmiTxDeviceVersion_t deviceVersion; /**< Version of the HW device */
++ UInt8 *pEdidBuffer; /**< Pointer to raw EDID data */
++ UInt32 edidBufferSize; /**< Size of buffer for raw EDID data */
++ tmdlHdmiTxIWTaskHandle_t commandTaskHandle; /**< Handle of the command task associated to this unit */
++ tmdlHdmiTxIWQueueHandle_t queueHandle; /**< Handle of the message queue associated to this unit */
++ tmdlHdmiTxIWTaskHandle_t hdcpTaskHandle; /**< Handle of the hdcp check task associated to this unit */
++ tmdlHdmiTxDriverState_t state; /**< Current state of the driver */
++ ptmdlHdmiTxCallback_t pCallback; /**< Data callback */
++ revocationList_t revocationList; /**< Revolation List */
++} unitConfig_t;
++
++
++/* Instance status */
++
++/* Video information structure */
++typedef struct _tmdlHdmiTxVideoInfo_t
++{
++ Bool videoMuteState; /* Video mute state: on/off */
++ tmdlHdmiTxVideoInConfig_t videoInConfig; /* Video input configuration */
++ tmdlHdmiTxVideoOutConfig_t videoOutConfig; /* Video output configuration */
++} tmdlHdmiTxVideoInfo_t, *ptmdlHdmiTxVideoInfo_t;
++
++/* Audio information structure */
++typedef struct _tmdlHdmiTxAudioInfo_t
++{
++ Bool audioMuteState; /* Audio mute state: on/off */
++ tmdlHdmiTxAudioInConfig_t audioInCfg; /* Audio input configuration */
++} tmdlHdmiTxAudioInfo_t, *ptmdlHdmiTxAudioInfo_t;
++
++/* Event state structure */
++typedef struct _tmdlHdmiTxEventState_t
++{
++ tmdlHdmiTxEvent_t event; /* Event */
++ tmdlHdmiTxEventStatus_t status; /* Event status: enabled or disabled */
++} tmdlHdmiTxEventState_t, *ptmdlHdmiTxEventState_t;
++
++/* Color bars state structure */
++typedef struct _tmdlHdmiTxColBarState_t
++{
++ Bool disableColorBarOnR0; /* To be able to disable colorBar on R0*/
++ Bool hdcpColbarChange; /* Used to auto-reset colour bars */
++ Bool hdcpEncryptOrT0; /* True when ENCRYPT or T0 interrupt */
++ Bool hdcpSecureOrT0; /* True when BKSV secure or T0 */
++ Bool inOutFirstSetDone; /* API tmdlHdmiTxSetInputOutput call at least one time*/
++ Bool colorBarOn;
++ Bool changeColorBarNow;
++} tmdlHdmiTxColBarState_t, *ptmdlHdmiTxColBarState_t;
++
++/* Gamut state structure */
++typedef struct _tmdlHdmiTxGamutState_t
++{
++ Bool gamutOn; /* Gamut status : able or disable */
++ UInt8 gamutBufNum; /* Numero of the buffer used for Gamut metadata (0 or 1) */
++ tmdlHdmiTxExtColorimetry_t wideGamutColorSpace; /* Store extended colorimetry */
++ Bool extColOn; /* extended colorimetry status : enabled or disabled */
++ tmdlHdmiTxYCCQR_t yccQR; /* Store YCC quantisation range */
++} tmdlHdmiTxGamutState_t, *ptmdlHdmiTxGamutState_t;
++
++
++/* instance status structure */
++typedef struct
++{
++ ptmdlHdmiTxVideoInfo_t pVideoInfo; /* Video information: current mode and format... */
++ ptmdlHdmiTxAudioInfo_t pAudioInfo; /* Audio information: current mode and format... */
++ ptmdlHdmiTxEventState_t pEventState; /* Event state: enabled or disabled */
++ ptmdlHdmiTxColBarState_t pColBarState; /* Color bars state */
++ ptmdlHdmiTxGamutState_t pGamutState; /* Gamut state */
++} instanceStatus_t;
++
++/*============================================================================*/
++/* FUNCTION PROTOTYPES */
++/*============================================================================*/
++
++
++/******************************************************************************
++ \brief This function allows to the main driver to retrieve its
++ configuration parameters.
++
++ \param pConfig Pointer to the config structure
++
++ \return The call result:
++ - TM_OK: the call was successful
++ - TMDL_ERR_DLHDMITX_BAD_UNIT_NUMBER: the unit number is wrong or
++ the receiver instance is not initialised
++ - TMDL_ERR_DLHDMITX_INCONSISTENT_PARAMS: an input parameter is
++ inconsistent
++
++******************************************************************************/
++tmErrorCode_t dlHdmiTxGetConfig
++(
++ tmUnitSelect_t unit,
++ tmdlHdmiTxDriverConfigTable_t *pConfig
++);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMDLHDMITX_LOCAL_H */
++
++/*============================================================================*/
++/* END OF FILE */
++/*============================================================================*/
+diff --git a/drivers/video/nxp/inc/tmFlags.h b/drivers/video/nxp/inc/tmFlags.h
+new file mode 100755
+index 0000000..deabca6
+--- /dev/null
++++ b/drivers/video/nxp/inc/tmFlags.h
+@@ -0,0 +1,237 @@
++/* MoReUse 2002-09-13 Continuus Version 2 */
++/* */
++/* Changes: made ansi compliant */
++/*-------------------------------------------------------------------------- */
++ /* (C) Copyright 2002 Koninklijke Philips Electronics N.V., All Rights Reserved*/
++ /* */
++ /* This source code and any compilation or derivative thereof is the sole */
++ /* property of Philips Corporation and is provided pursuant to a Software */
++ /* License Agreement. This code is the proprietary information of */
++ /* Philips Corporation and is confidential in nature. Its use and */
++ /* dissemination by any party other than Philips Corporation is strictly */
++ /* limited by the confidential information provisions of the Agreement */
++ /* referenced above. */
++ /*------------------------------------------------------------------------- */
++ /* FILENAME: tmFlags.h */
++ /* */
++ /* DESCRIPTION: Platform dependent build flags (typically generated by the */
++ /* SDE build process if it doesn't already exist). */
++ /* */
++ /* DOCUMENT REF: DVP Build Process Specification */
++ /* */
++ /* NOTES: This file defines the TMFL_xxx build flags configuration. */
++ /* It does not include specific component diversity flags that */
++ /* are defined in the component makefiles (e.g., TMFL_SCOPE */
++ /* defined in BSL board files) */
++ /* */
++ /* This file is based on SDE Version 1.2 generated output. */
++ /*------------------------------------------------------------------------- */
++ /* */
++ #ifndef TM_FLAGS_H
++ #define TM_FLAGS_H
++
++/* Configurable build flags */
++/* NOTE: The following flags are configurable (typically generated by SDE */
++/* based on _TMXXX build environment variables). See individual flags */
++/* for comments about the settings and consistency requirements. */
++
++/* TMFL_BUILD_VERSION: <Major>.<Minor>.<BuildNumber> as decimal digits. This */
++/* number is product/release dependent and not standardized as of now. */
++/*#define TMFL_BUILD_VERSION 00.01.00*/
++
++/* RIDE tool does not support . in define value */
++/* TMFL_BUILD_VERSION is not used to specify neither TDA9975_SW version not TDA9983_SW version */
++#define TMFL_BUILD_VERSION 00
++
++/* TMFL_CPU: CPU type/model numbers: (TMFL_CPU_TYPE_XXX | TMFL_CPU_MODEL_XXX). */
++/* Example: (TMFL_CPU_TYPE_X86 | TMFL_CPU_MODEL_I486) or (TMFL_CPU_I486) for */
++/* an x86 i486 CPU. */
++ #define TMFL_CPU (TMFL_CPU_TYPE_X86 | TMFL_CPU_MODEL_I486)
++
++/* TMFL_ENDIAN: CPU endianness: <TMFL_ENDIAN_BIG | TMFL_ENDIAN_LITTLE> */
++ #define TMFL_ENDIAN (TMFL_ENDIAN_LITTLE)
++
++/* TMFL_OS: Operating system type/version where the version number should be */
++/* included if defined: (TMFL_OS_<TTT>[VVV]). Example: TMFL_OS_PSOS250 */
++/* indicates that the target OS is pSOS Version 2.50. */
++ #define TMFL_OS (TMFL_OS_NULLOS)
++
++/* TMFL_CPU_IS_XXX: These are boolean flags that reflects the CPU type and */
++/* must be consistent with the TMFL_CPU setting (i.e., if TMFL_CPU = */
++/* TMFL_CPU_I486, then TMFL_CPU_IS_X86 = 1) and all other TMFL_CPU_IS_XXX */
++/* flags are 0. */
++ #define TMFL_CPU_IS_X86 1
++ #define TMFL_CPU_IS_MIPS 0
++ #define TMFL_CPU_IS_HP 0
++ #define TMFL_CPU_IS_TM 0
++ #define TMFL_CPU_IS_ARM 0
++ #define TMFL_CPU_IS_REAL 0
++
++/* TMFL_OS_IS_XXX: These are boolean flags that reflects the OS type and */
++/* must be consistent with the TMFL_OS setting (i.e., if TMFL_OS = */
++/* TMFL_OS_PSOS250, then TMFL_OS_IS_PSOS = 1) and all other TMFL_OS_IS_XXX */
++/* flags are 0. */
++ #define TMFL_OS_IS_BTM 0
++ #define TMFL_OS_IS_CE 0
++ #define TMFL_OS_IS_NT 0
++ #define TMFL_OS_IS_PSOS 0
++ #define TMFL_OS_IS_NULLOS 1
++ #define TMFL_OS_IS_ECOS 0
++ #define TMFL_OS_IS_VXWORKS 0
++ #define TMFL_OS_IS_MTOS 0
++
++
++/* Non-configurable constants */
++/* NOTE: These values do not change and should not be modified ! */
++ #define TMFL_CPU_TYPE_MASK 0xffff0000
++ #define TMFL_CPU_TYPE_X86 0x00010000
++ #define TMFL_CPU_TYPE_MIPS 0x00020000
++ #define TMFL_CPU_TYPE_TM 0x00030000
++ #define TMFL_CPU_TYPE_HP 0x00040000
++ #define TMFL_CPU_TYPE_ARM 0x00050000
++ #define TMFL_CPU_TYPE_REAL 0x00060000
++ #define TMFL_CPU_MODEL_MASK 0x0000ffff
++ #define TMFL_CPU_MODEL_I486 0x00000001
++ #define TMFL_CPU_MODEL_R3940 0x00000002
++ #define TMFL_CPU_MODEL_R4300 0x00000003
++ #define TMFL_CPU_MODEL_TM1100 0x00000004
++ #define TMFL_CPU_MODEL_TM1300 0x00000005
++ #define TMFL_CPU_MODEL_TM32 0x00000006
++ #define TMFL_CPU_MODEL_HP 0x00000007
++ #define TMFL_CPU_MODEL_R4640 0x00000008
++ #define TMFL_CPU_MODEL_ARM7 0x00000009
++ #define TMFL_CPU_MODEL_ARM920T 0x0000000a
++ #define TMFL_CPU_MODEL_ARM940T 0x0000000b
++ #define TMFL_CPU_MODEL_ARM10 0x0000000c
++ #define TMFL_CPU_MODEL_STRONGARM 0x0000000d
++ #define TMFL_CPU_MODEL_RD24120 0x0000000e
++ #define TMFL_CPU_MODEL_ARM926EJS 0x0000000f
++ #define TMFL_CPU_MODEL_ARM946 0x00000010
++ #define TMFL_CPU_MODEL_R1910 0x00000011
++ #define TMFL_CPU_MODEL_R4450 0x00000012
++ #define TMFL_CPU_MODEL_TM3260 0x00000013
++ #define TMFL_ENDIAN_BIG 1
++ #define TMFL_ENDIAN_LITTLE 0
++ #define TMFL_OS_MASK 0xff000000
++ #define TMFL_OS_VERSION_MASK 0x00ffffff
++ #define TMFL_OS_BTM 0x00000000
++ #define TMFL_OS_CE 0x01000000
++ #define TMFL_OS_CE212 0x01020102
++ #define TMFL_OS_CE300 0x01030000
++ #define TMFL_OS_NT 0x02000000
++ #define TMFL_OS_NT4 0x02040000
++ #define TMFL_OS_PSOS 0x03000000
++ #define TMFL_OS_PSOS250 0x03020500
++ #define TMFL_OS_PSOS200 0x03020000
++ #define TMFL_OS_NULLOS 0x04000000
++ #define TMFL_OS_ECOS 0x05000000
++ #define TMFL_OS_VXWORKS 0x06000000
++ #define TMFL_OS_MTOS 0x07000000
++ #define TMFL_SCOPE_SP 0
++ #define TMFL_SCOPE_MP 1
++ #define TMFL_REL_ASSERT 0x00000002
++ #define TMFL_REL_DEBUG 0x00000001
++ #define TMFL_REL_RETAIL 0x00000000
++ #define TMFL_CPU_I486 0x00010001
++ #define TMFL_CPU_R3940 0x00020002
++ #define TMFL_CPU_R4300 0x00020003
++ #define TMFL_CPU_TM1100 0x00030004
++ #define TMFL_CPU_TM1300 0x00030005
++ #define TMFL_CPU_TM32 0x00030006
++ #define TMFL_CPU_HP 0x00040007
++ #define TMFL_CPU_R4640 0x00020008
++ #define TMFL_CPU_ARM7 0x00050009
++ #define TMFL_CPU_ARM920T 0x0005000a
++ #define TMFL_CPU_ARM940T 0x0005000b
++ #define TMFL_CPU_ARM10 0x0005000c
++ #define TMFL_CPU_STRONGARM 0x0005000d
++ #define TMFL_CPU_RD24120 0x0006000e
++ #define TMFL_CPU_ARM926EJS 0x0005000f
++ #define TMFL_CPU_ARM946 0x00050010
++ #define TMFL_CPU_R1910 0x00020011
++ #define TMFL_CPU_R4450 0x00020012
++ #define TMFL_CPU_TM3260 0x00030013
++ #define TMFL_MODE_KERNEL 1
++ #define TMFL_MODE_USER 0
++
++/******************************************************************************/
++/* Components features defines */
++/******************************************************************************/
++#ifdef TMFL_TDA19988
++# ifndef TMFL_TDA19989
++# define TMFL_TDA19989
++# endif /* TMFL_TDA19989 */
++# define TMFL_RGB_DDR_12BITS
++# define TMFL_HDCP_OPTIMIZED_POWER
++#endif /* TMFL_TDA19988 */
++
++#ifdef TMFL_TDA19989
++# ifndef TMFL_TDA9989
++# define TMFL_TDA9989
++# define SUPPORT_3D_FP
++# endif /* TMFL_TDA9989 */
++#endif /* TMFL_TDA19989 */
++/******************************************************************************/
++/* Preprocessor checks for invalid settings (if file is manually modified) */
++/******************************************************************************/
++/* */
++
++/* Check if TMFL_CPU flag changed from its default setting. */
++#if (TMFL_CPU == (TMFL_CPU_TYPE_MASK | TMFL_CPU_MODEL_MASK))
++#error ERROR: TMFL_CPU must be set (TMFL_CPU_TYPE_XXX | TMFL_CPU_MODEL_XXX) !
++#endif
++
++/* Check if TMFL_ENDIAN flag setting is valid. */
++#if ((TMFL_ENDIAN != TMFL_ENDIAN_BIG) && (TMFL_ENDIAN != TMFL_ENDIAN_LITTLE))
++#error ERROR: TMFL_ENDIAN must be set to a valid TMFL_ENDIAN_XXX value !
++#endif
++
++/* Check if TMFL_OS flag changed from its default setting. */
++#if (TMFL_OS == (TMFL_OS_MASK | TMFL_OS_VERSION_MASK))
++#error ERROR: TMFL_OS must be set to a valid value (TMFL_OS_<TYPE>[<VERSION>]) !
++#endif
++
++/* The TMFL_CPU_IS_XXX is a Boolean; one and only one flag can be true (=1). */
++#if ((TMFL_CPU_IS_X86 + TMFL_CPU_IS_MIPS + TMFL_CPU_IS_TM + TMFL_CPU_IS_HP + TMFL_CPU_IS_ARM + TMFL_CPU_IS_REAL) != 1)
++#error ERROR: One or more TMFL_CPU_IS_XXX values are incorrect or missing !
++#endif
++
++/* TMFL_CPU and TMFL_CPU_IS_XXX must be consistent */
++#if (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_X86) && (TMFL_CPU_IS_X86 != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_X86 settings !
++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_MIPS) && (TMFL_CPU_IS_MIPS != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_MIPS settings !
++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_TM) && (TMFL_CPU_IS_TM != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_TM settings !
++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_HP) && (TMFL_CPU_IS_HP != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_HP settings !
++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_ARM) && (TMFL_CPU_IS_ARM != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_ARM settings !
++#elif (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_REAL) && (TMFL_CPU_IS_REAL != 1))
++#error ERROR: Inconsistent TMFL_CPU and TMFL_CPU_IS_REAL settings !
++#endif /* (((TMFL_CPU & TMFL_CPU_TYPE_MASK) == TMFL_CPU_TYPE_X86) && ... */
++
++/* The TMFL_OS_IS_XXX is a Boolean; one and only one flag can be true (=1). */
++#if ((TMFL_OS_IS_BTM + TMFL_OS_IS_CE + TMFL_OS_IS_NT + TMFL_OS_IS_PSOS + TMFL_OS_IS_NULLOS + TMFL_OS_IS_ECOS + TMFL_OS_IS_VXWORKS + TMFL_OS_IS_MTOS) != 1)
++#error ERROR: One or more TMFL_OS_IS_XXX values are incorrect or missing !
++#endif
++
++#if (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_BTM) && (TMFL_OS_IS_BTM != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_BTM settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_CE) && (TMFL_OS_IS_CE != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_CE settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_NT) && (TMFL_OS_IS_NT != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_NT settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_PSOS) && (TMFL_OS_IS_PSOS != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_PSOS settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_NULLOS) && (TMFL_OS_IS_NULLOS != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_NULLOS settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_ECOS) && (TMFL_OS_IS_ECOS != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_ECOS settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_VXWORKS) && (TMFL_OS_IS_VXWORKS != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_VXWORKS settings !
++#elif (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_MTOS) && (TMFL_OS_IS_MTOS != 1))
++#error ERROR: Inconsistent TMFL_OS and TMFL_OS_IS_MTOS settings !
++#endif /* (((TMFL_OS & TMFL_OS_MASK) == TMFL_OS_XX) && (TMFL_OS_IS_XX != 1)) */
++
++#endif /* TM_FLAGS_H */
+diff --git a/drivers/video/nxp/inc/tmNxCompId.h b/drivers/video/nxp/inc/tmNxCompId.h
+new file mode 100755
+index 0000000..2302901
+--- /dev/null
++++ b/drivers/video/nxp/inc/tmNxCompId.h
+@@ -0,0 +1,1743 @@
++/* -------------------------------------------------------------------------- */
++/* (C) Copyright 2000-2005 Koninklijke Philips Electronics N.V., */
++/* All rights reserved */
++/* */
++/* This source code and any compilation or derivative thereof is the */
++/* proprietary information of Konlinklijke Philips Electronics N.V. and is */
++/* Confidential in nature. */
++/* Under no circumstances is this software to be exposed to or placed under an*/
++/* Open Source License of any type without the expressed written permission of*/
++/* Koninklijke Philips Electronics N.V. */
++/* -------------------------------------------------------------------------- */
++/* */
++/* MoReUse - 2005-10-24 Version 118 */
++/* */
++/* Added: */
++/* CID_AACPENC */
++/* */
++/* */
++/* Changed: */
++/* */
++/* */
++/* */
++/* Removed: */
++/* */
++/* */
++/* */
++/* General Error Codes Added */
++/* */
++/* -------------------------------------------------------------------------- */
++/* FILE NAME: tmNxCompId.h */
++/* */
++/* DESCRIPTION: This header file identifies the standard component */
++/* identifiers (CIDs) and interface identifiers (IID) for */
++/* Nexperia platforms. */
++/* The objective of these identifiers is to enable unique */
++/* identification of software components and interfaces. */
++/* In addition, standard status values are also defined to make */
++/* determination of typical error cases much easier. */
++/* */
++/* Functional errors are not real errors in the sense of */
++/* unexpected behaviour but are part of the normal communication*/
++/* between a client an a server component. They are linked to */
++/* an interface, rather than to a component. All implementations*/
++/* of an interface must have the same behaviour with respect to */
++/* functional errors. Functional erros are all positive */
++/* One global functional error is defined: TM_OK 0x00000000 */
++/* */
++/* Non-functional errors (all negative numbers) indicate */
++/* unexpected behaviour. They are linked to concrete component */
++/* implementations */
++/* */
++/* NOTE: The current implementation is different from the prev. */
++/* component identifier implementation, based on classes, */
++/* types and layers. However, the new system is backward */
++/* compatitible with the old implementation. */
++/* */
++/* tmNxCompId.h defines a number of general error codes that can*/
++/* be used by all components. These error codes are concatenated*/
++/* to the CID or IID value in the local component headerfile of */
++/* the component that wants to (re-)use this general error code */
++/* General error codes can be used for both functional and */
++/* non-functional errors. They should only be used if they */
++/* semantically fully match (if not, defined a new component or */
++/* interface specific error code. */
++/* */
++/* General Rules: */
++/* A return value has a length of 32 bits. At the binary level, */
++/* 1 bit indicates the component or interface flag; 16 bits are */
++/* used for the actual component id (CID) or interface id (IID) */
++/* and 12 bits for the return status. */
++/* The component/interface flag is bit 31. */
++/* Bits 30--28 are all 0. */
++/* The component/interface id occupies bits 27--12. */
++/* The return status occupies bits 11--0. */
++/* */
++/* +--------+-----+-------+-----------+ */
++/* | flag:1 | 0:3 | id:16 | status:12 | */
++/* +--------+-----+-------+-----------+ */
++/* */
++/* Format of interface ids: */
++/* */
++/* +-----+-----+--------+-----------+ */
++/* | 0:1 | 0:3 | iid:16 | status:12 | */
++/* +-----+-----+--------+-----------+ */
++/* */
++/* Format of component ids: */
++/* */
++/* +-----+-----+--------+-----------+ */
++/* | 1:1 | 0:3 | cid:16 | status:12 | */
++/* +-----+-----+--------+-----------+ */
++/* */
++/* At the macro level, we use the prefix "CID_" for component */
++/* ids (previous version "CID_COMP_") and "IID_" for interface */
++/* ids. */
++/* */
++/* Each component id will be used by only one component; each */
++/* component will have its own component id. */
++/* Each interface id will be used by only one interface; each */
++/* interface will have its own interface id. */
++/* */
++/* In order to avoid problems when promoting a UNIQUE interface */
++/* to a SEPARATE interface, the ranges for CIDs and IIDS must */
++/* not overlap. */
++/* */
++/* Component names and component ids have to be registered */
++/* together; the same applies for interface names and ids. */
++/* */
++/* NOTE about Compatibility */
++/* In the previous implementation the first four bits were */
++/* reserved for class, and there were separate fields for */
++/* type and tag, like this: */
++/* */
++/* +---------+--------+-------+---------+-----------+ */
++/* | class:4 | type:4 | tag:8 | layer:4 | status:12 | */
++/* +---------+--------+-------+---------+-----------+ */
++/* */
++/* The values 0 or 8 are not valid classes, and this fact */
++/* can be used to distinguish a new-style IID (class == 0), */
++/* a new-style CID (class == 8), and an old-style CID */
++/* (otherwise). */
++/* */
++/* NOTE about error codes */
++/* The general error codes use the range 0x001 to 0x7FF. */
++/* The component specific error codes are defined in the */
++/* local component header file and can use 0x800 to 0xFFF. */
++/* TM_OK has the value 0x00000000. */
++/* The proposed error code ranges (general and specific) are */
++/* the same for functional and non-functional errors. */
++/* */
++/* The previously defined ranges for external customers, */
++/* assert errors and fatal errors have been dropped. */
++/* The previously defined range for general errors started */
++/* at 0x000 instead of 0x001 */
++/* */
++/* DOCUMENT REF: Nexperia/MoReUse Naming Conventions */
++/* */
++/* -------------------------------------------------------------------------- */
++
++#ifndef TMNXCOMPID_H
++#define TMNXCOMPID_H
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Standard include files: */
++/* */
++/* -------------------------------------------------------------------------- */
++#include "tmNxTypes.h"
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Types and defines: */
++/* */
++/* -------------------------------------------------------------------------- */
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* TM_OK is the 32 bit global status value used by all Nexperia components */
++/* to indicate successful function/operation status. If a non-zero value is*/
++/* returned as status, it should use the component ID formats defined. */
++/* */
++/* -------------------------------------------------------------------------- */
++#define TM_OK 0U /* Global success return status */
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* General Defines */
++/* */
++/* -------------------------------------------------------------------------- */
++#define CID_IID_FLAG_BITSHIFT 31
++#define CID_ID_BITSHIFT 12
++#define IID_ID_BITSHIFT 12
++
++#define CID_FLAG (0x1U << CID_IID_FLAG_BITSHIFT)
++#define IID_FLAG (0x0U << CID_IID_FLAG_BITSHIFT)
++
++#define CID_ID(number) ((number) << CID_ID_BITSHIFT)
++#define CID_ID_BITMASK (0x7FFFFU << CID_ID_BITSHIFT)
++
++#define IID_ID(number) ((number) << IID_ID_BITSHIFT)
++#define IID_ID_BITMASK (0x7FFFFU << IID_ID_BITSHIFT)
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Definition of the interface IDs */
++/* */
++/* -------------------------------------------------------------------------- */
++#define IID_IENUMUNKNOWN (IID_ID(0x001U) | IID_FLAG)
++#define IID_IBIND (IID_ID(0x002U) | IID_FLAG)
++#define IID_IBINDINFO (IID_ID(0x003U) | IID_FLAG)
++#define IID_IMEM (IID_ID(0x004U) | IID_FLAG)
++#define IID_IUNKNOWN (IID_ID(0x005U) | IID_FLAG)
++#define IID_IIC (IID_ID(0x006U) | IID_FLAG)
++#define IID_ACHAN (IID_ID(0x007U) | IID_FLAG)
++#define IID_AFEAT (IID_ID(0x008U) | IID_FLAG)
++#define IID_AMIX (IID_ID(0x009U) | IID_FLAG)
++#define IID_ANAADEC (IID_ID(0x00aU) | IID_FLAG)
++#define IID_ANAVENC (IID_ID(0x00bU) | IID_FLAG)
++#define IID_ANAVENCRYPT (IID_ID(0x00cU) | IID_FLAG)
++#define IID_ANAVDEC (IID_ID(0x00dU) | IID_FLAG)
++#define IID_BBARDETEXT (IID_ID(0x00eU) | IID_FLAG)
++#define IID_BLEVELDETEXT (IID_ID(0x00fU) | IID_FLAG)
++#define IID_BLEVELMODEXT (IID_ID(0x010U) | IID_FLAG)
++#define IID_BSLSPDI (IID_ID(0x011U) | IID_FLAG)
++#define IID_BSLSPDO (IID_ID(0x012U) | IID_FLAG)
++#define IID_BSL_AI (IID_ID(0x013U) | IID_FLAG)
++#define IID_BSL_AO (IID_ID(0x014U) | IID_FLAG)
++#define IID_BSL_AVI (IID_ID(0X015U) | IID_FLAG)
++#define IID_BSL_AVO (IID_ID(0x016U) | IID_FLAG)
++#define IID_BSL_EEPROM (IID_ID(0X017U) | IID_FLAG)
++#define IID_BSL_IDE (IID_ID(0X018U) | IID_FLAG)
++#define IID_BSL_NANDFLASH (IID_ID(0X019U) | IID_FLAG)
++#define IID_BSL_NORFLASH (IID_ID(0X01aU) | IID_FLAG)
++#define IID_BSL_PARPORT (IID_ID(0X01bU) | IID_FLAG)
++#define IID_BSL_RTC (IID_ID(0X01cU) | IID_FLAG)
++#define IID_COLENH (IID_ID(0x01dU) | IID_FLAG)
++#define IID_COLENHEXT (IID_ID(0x01eU) | IID_FLAG)
++#define IID_CONNMGR (IID_ID(0x01fU) | IID_FLAG)
++#define IID_CRT (IID_ID(0x020U) | IID_FLAG)
++#define IID_CTI (IID_ID(0X021U) | IID_FLAG)
++#define IID_CTIEXT (IID_ID(0X022U) | IID_FLAG)
++#define IID_DIGADEC (IID_ID(0X023U) | IID_FLAG)
++#define IID_DIGVDEC (IID_ID(0X024U) | IID_FLAG)
++#define IID_DMX (IID_ID(0X025U) | IID_FLAG)
++#define IID_DNR (IID_ID(0X026U) | IID_FLAG)
++#define IID_DNREXT (IID_ID(0X027U) | IID_FLAG)
++#define IID_DVBSUBTDEC (IID_ID(0X028U) | IID_FLAG)
++#define IID_FATERR (IID_ID(0X029U) | IID_FLAG)
++#define IID_FREND (IID_ID(0X02aU) | IID_FLAG)
++#define IID_GAMMAEXT (IID_ID(0X02bU) | IID_FLAG)
++#define IID_HISTOMEASEXT (IID_ID(0X02cU) | IID_FLAG)
++#define IID_HISTOMODEXT (IID_ID(0X02dU) | IID_FLAG)
++#define IID_MML (IID_ID(0X02eU) | IID_FLAG)
++#define IID_NOISEESTEXT (IID_ID(0X02fU) | IID_FLAG)
++#define IID_OSAL (IID_ID(0X030U) | IID_FLAG)
++#define IID_PIPSTORE (IID_ID(0X031U) | IID_FLAG)
++#define IID_SCANRATECONV (IID_ID(0X032U) | IID_FLAG)
++#define IID_SCANRATECONVEXT (IID_ID(0X033U) | IID_FLAG)
++#define IID_SHARPENH (IID_ID(0X034U) | IID_FLAG)
++#define IID_SHARPENHEXT (IID_ID(0X035U) | IID_FLAG)
++#define IID_SHARPMEASEXT (IID_ID(0X036U) | IID_FLAG)
++#define IID_SPDIFIN (IID_ID(0X037U) | IID_FLAG)
++#define IID_SPDIFOUT (IID_ID(0X038U) | IID_FLAG)
++#define IID_SPEAKER (IID_ID(0X039U) | IID_FLAG)
++#define IID_STCDEC (IID_ID(0X03aU) | IID_FLAG)
++#define IID_STREAMINJ (IID_ID(0X03bU) | IID_FLAG)
++#define IID_SYNCTAG (IID_ID(0X03cU) | IID_FLAG)
++#define IID_TSSACOM (IID_ID(0X03dU) | IID_FLAG)
++#define IID_TXTDEC (IID_ID(0X03eU) | IID_FLAG)
++#define IID_UTILCRYPT (IID_ID(0X03fU) | IID_FLAG)
++#define IID_UVBWDETEXT (IID_ID(0X040U) | IID_FLAG)
++#define IID_VBIINSERT (IID_ID(0X041U) | IID_FLAG)
++#define IID_VBISLICE (IID_ID(0X042U) | IID_FLAG)
++#define IID_VDCC (IID_ID(0X043U) | IID_FLAG)
++#define IID_VDSTSCAN (IID_ID(0X044U) | IID_FLAG)
++#define IID_VFEAT (IID_ID(0X045U) | IID_FLAG)
++#define IID_VMIX (IID_ID(0X046U) | IID_FLAG)
++#define IID_VSCALEEXT (IID_ID(0X047U) | IID_FLAG)
++#define IID_VSRCPROP (IID_ID(0X048U) | IID_FLAG)
++#define IID_VSRCSCANPROP (IID_ID(0X049U) | IID_FLAG)
++#define IID_GENI2C (IID_ID(0X04aU) | IID_FLAG)
++#define IID_PLFINSTVIN (IID_ID(0X04bU) | IID_FLAG)
++#define IID_PLFINSTAIN (IID_ID(0X04cU) | IID_FLAG)
++#define IID_PLFINSTAOUT (IID_ID(0X04dU) | IID_FLAG)
++#define IID_PLFINSTGFX (IID_ID(0X04eU) | IID_FLAG)
++#define IID_CONNMGRATV (IID_ID(0X04fU) | IID_FLAG)
++#define IID_IAMALIVE (IID_ID(0X050U) | IID_FLAG)
++#define IID_BBARDET (IID_ID(0X051U) | IID_FLAG)
++#define IID_CONTRRESEXT (IID_ID(0X052U) | IID_FLAG)
++#define IID_NOISEMEAS (IID_ID(0X053U) | IID_FLAG)
++#define IID_SHARPMEAS (IID_ID(0X054U) | IID_FLAG)
++#define IID_HISTOMOD (IID_ID(0X055U) | IID_FLAG)
++#define IID_ANTIAGING (IID_ID(0X056U) | IID_FLAG)
++#define IID_AMBIENTLEVEL (IID_ID(0X057U) | IID_FLAG)
++#define IID_HAD_DRV_IIC (IID_ID(0X058U) | IID_FLAG)
++#define IID_HAD_DRV_GPIO (IID_ID(0X059U) | IID_FLAG)
++#define IID_HAD_DRV_CSM (IID_ID(0X05aU) | IID_FLAG)
++#define IID_DRIVERHAL (IID_ID(0X05bU) | IID_FLAG)
++#define IID_MUTISTR (IID_ID(0X05cU) | IID_FLAG)
++#define IID_MUTIVEC (IID_ID(0X05dU) | IID_FLAG)
++#define IID_MUTISTRX (IID_ID(0X05eU) | IID_FLAG)
++#define IID_MUTICMD (IID_ID(0X05fU) | IID_FLAG)
++#define IID_TASK_CONDITION (IID_ID(0X060U) | IID_FLAG)
++#define IID_PACKET_POOL (IID_ID(0X061U) | IID_FLAG)
++#define IID_PACKET_QUEUE (IID_ID(0X062U) | IID_FLAG)
++#define IID_UDSDCD (IID_ID(0X063U) | IID_FLAG)
++#define IID_DCSS_RL (IID_ID(0X064U) | IID_FLAG)
++#define IID_DCSS_DD (IID_ID(0X065U) | IID_FLAG)
++#define IID_DCSS_GD (IID_ID(0X066U) | IID_FLAG)
++#define IID_DCSS_RSC (IID_ID(0X067U) | IID_FLAG)
++#define IID_DCSS_P (IID_ID(0X068U) | IID_FLAG)
++#define IID_DCSS (IID_ID(0X069U) | IID_FLAG)
++#define IID_CC_BURST_CUTTING_AREA (IID_ID(0X06aU) | IID_FLAG)
++#define IID_CC_CONFIGURATION (IID_ID(0X06bU) | IID_FLAG)
++#define IID_CC_CONTROL (IID_ID(0X06cU) | IID_FLAG)
++#define IID_CC_DEBUG (IID_ID(0X06dU) | IID_FLAG)
++#define IID_CC_DECODER (IID_ID(0X06eU) | IID_FLAG)
++#define IID_CC_ENCODER (IID_ID(0X06fU) | IID_FLAG)
++#define IID_CC_HF_PROCESSING (IID_ID(0X070U) | IID_FLAG)
++#define IID_CC_INTERFACE (IID_ID(0X071U) | IID_FLAG)
++#define IID_CC_NATLAB (IID_ID(0X072U) | IID_FLAG)
++#define IID_CC_PIC (IID_ID(0X073U) | IID_FLAG)
++#define IID_CC_WOBBLE (IID_ID(0X074U) | IID_FLAG)
++#define IID_CC_REGISTERMAP (IID_ID(0X075U) | IID_FLAG)
++#define IID_CC_WOBBLE_REG (IID_ID(0X076U) | IID_FLAG)
++#define IID_CC_PIC_REG (IID_ID(0X077U) | IID_FLAG)
++#define IID_CC_NATLAB_REG (IID_ID(0X078U) | IID_FLAG)
++#define IID_CC_INTERFACE_REG (IID_ID(0X079U) | IID_FLAG)
++#define IID_CC_HF_PROCESSING_REG (IID_ID(0X07aU) | IID_FLAG)
++#define IID_CC_ENCODER_REG (IID_ID(0X07bU) | IID_FLAG)
++#define IID_CC_DECODER_REG (IID_ID(0X07cU) | IID_FLAG)
++#define IID_CC_DEBUG_REG (IID_ID(0X07dU) | IID_FLAG)
++#define IID_CC_CONTROL_REG (IID_ID(0X07eU) | IID_FLAG)
++#define IID_CC_CONFIGURATION_REG (IID_ID(0X07fU) | IID_FLAG)
++#define IID_CC_BURST_CUTTING_AREA_REG (IID_ID(0X080U) | IID_FLAG)
++#define IID_CC_PHYSICAL_VALUES (IID_ID(0X081U) | IID_FLAG)
++#define IID_CC_GENERAL_SETTINGS (IID_ID(0X082U) | IID_FLAG)
++#define IID_CC_COEFFICIENTS (IID_ID(0X083U) | IID_FLAG)
++#define IID_REMOTE_CONTROL (IID_ID(0X084U) | IID_FLAG)
++#define IID_TUNER (IID_ID(0X085U) | IID_FLAG)
++#define IID_MUTITST (IID_ID(0X086U) | IID_FLAG)
++#define IID_CHIP_CONTEXT (IID_ID(0X087U) | IID_FLAG)
++#define IID_API (IID_ID(0X088U) | IID_FLAG)
++#define IID_CHANDEC (IID_ID(0X089U) | IID_FLAG)
++#define IID_TUNING (IID_ID(0X08aU) | IID_FLAG)
++#define IID_TUNINGAFC (IID_ID(0X08bU) | IID_FLAG)
++#define IID_TUNINGAFCNTF (IID_ID(0X08cU) | IID_FLAG)
++#define IID_TUNINGCHAN (IID_ID(0X08dU) | IID_FLAG)
++#define IID_TUNINGSEARCHNTF (IID_ID(0X08eU) | IID_FLAG)
++#define IID_ID3EXTR (IID_ID(0X08fU) | IID_FLAG)
++#define IID_ANAAVDEM (IID_ID(0X090U) | IID_FLAG)
++#define IID_ANAAVDEMNTF (IID_ID(0X091U) | IID_FLAG)
++#define IID_CCEXTR (IID_ID(0X092U) | IID_FLAG)
++#define IID_CHANDECDVBC (IID_ID(0X093U) | IID_FLAG)
++#define IID_CHANDECDVBS (IID_ID(0X094U) | IID_FLAG)
++#define IID_CHANDECDVBT (IID_ID(0X095U) | IID_FLAG)
++#define IID_CHANDECNTF (IID_ID(0X096U) | IID_FLAG)
++#define IID_OOB (IID_ID(0X097U) | IID_FLAG)
++#define IID_RFAMP (IID_ID(0X098U) | IID_FLAG)
++#define IID_SIGSTRENGTH (IID_ID(0X099U) | IID_FLAG)
++#define IID_SIGSTRENGTHNTF (IID_ID(0X09aU) | IID_FLAG)
++#define IID_IMAGEDEC (IID_ID(0X09bU) | IID_FLAG)
++#define IID_TUNINGSEARCH (IID_ID(0X09cU) | IID_FLAG)
++#define IID_PINOBJECTS (IID_ID(0X09dU) | IID_FLAG)
++#define IID_URLSRC (IID_ID(0X09eU) | IID_FLAG)
++#define IID_OSDKERNELAPP (IID_ID(0X09fU) | IID_FLAG)
++#define IID_OSDKERNELMEM (IID_ID(0X0a0U) | IID_FLAG)
++#define IID_OSDKERNELOSD (IID_ID(0X0a1U) | IID_FLAG)
++#define IID_OSDKERNELOSDCONTROL (IID_ID(0X0a2U) | IID_FLAG)
++#define IID_RTC (IID_ID(0X0a3U) | IID_FLAG)
++#define IID_FS (IID_ID(0X0a4U) | IID_FLAG)
++#define IID_BE (IID_ID(0X0a5U) | IID_FLAG)
++#define IID_CD_LIB (IID_ID(0X0a6U) | IID_FLAG)
++#define IID_DB (IID_ID(0X0a7U) | IID_FLAG)
++#define IID_AVIN (IID_ID(0X0a8U) | IID_FLAG)
++#define IID_AVOUT (IID_ID(0X0a9U) | IID_FLAG)
++#define IID_INT (IID_ID(0X0aaU) | IID_FLAG)
++#define IID_EVT (IID_ID(0X0abU) | IID_FLAG)
++#define IID_DMA (IID_ID(0X0acU) | IID_FLAG)
++#define IID_CLK (IID_ID(0X0adU) | IID_FLAG)
++#define IID_VMIXBORDERPAINTER (IID_ID(0X0aeU) | IID_FLAG)
++#define IID_CPROCTVFLOW (IID_ID(0X0afU) | IID_FLAG)
++#define IID_VTRANTIAGING (IID_ID(0X0b0U) | IID_FLAG)
++#define IID_VTRFADE (IID_ID(0X0b1U) | IID_FLAG)
++#define IID_VTRSCALE (IID_ID(0X0b2U) | IID_FLAG)
++#define IID_VTRSTROBE (IID_ID(0X0b3U) | IID_FLAG)
++#define IID_HDMIIN (IID_ID(0X0b4U) | IID_FLAG)
++#define IID_ACHANSEL (IID_ID(0X0b5U) | IID_FLAG)
++#define IID_SSP (IID_ID(0X0b6U) | IID_FLAG)
++#define IID_CONNMGR_STILL (IID_ID(0X0b7U) | IID_FLAG)
++#define IID_CONNMGR_AUDIO (IID_ID(0X0b8U) | IID_FLAG)
++#define IID_CONNMGR_MPEG2PS (IID_ID(0X0b9U) | IID_FLAG)
++#define IID_SPI_SD (IID_ID(0X0baU) | IID_FLAG)
++#define IID_DECODERHALCST (IID_ID(0X0bbU) | IID_FLAG)
++#define IID_SOD (IID_ID(0X0bcU) | IID_FLAG)
++#define IID_DCSS_AA (IID_ID(0X0bdU) | IID_FLAG)
++#define IID_DCSS_AVI (IID_ID(0X0beU) | IID_FLAG)
++#define IID_DCSS_BC (IID_ID(0X0bfU) | IID_FLAG)
++#define IID_DCSS_CLUT (IID_ID(0X0c0U) | IID_FLAG)
++#define IID_DCSS_COL (IID_ID(0X0c1U) | IID_FLAG)
++#define IID_DCSS_DFC (IID_ID(0X0c2U) | IID_FLAG)
++#define IID_DCSS_DOC (IID_ID(0X0c3U) | IID_FLAG)
++#define IID_DCSS_GIO (IID_ID(0X0c4U) | IID_FLAG)
++#define IID_DCSS_ISD (IID_ID(0X0c5U) | IID_FLAG)
++#define IID_DCSS_KBI (IID_ID(0X0c6U) | IID_FLAG)
++#define IID_DCSS_OSD (IID_ID(0X0c7U) | IID_FLAG)
++#define IID_DCSS_PIF (IID_ID(0X0c8U) | IID_FLAG)
++#define IID_DCSS_PVI (IID_ID(0X0c9U) | IID_FLAG)
++#define IID_DCSS_SIS (IID_ID(0X0caU) | IID_FLAG)
++#define IID_DCSS_TIG (IID_ID(0X0cbU) | IID_FLAG)
++#define IID_DCSS_USC (IID_ID(0X0ccU) | IID_FLAG)
++#define IID_DCSS_VCR (IID_ID(0X0cdU) | IID_FLAG)
++#define IID_CONNMGR_MP4RTP_PLAYER (IID_ID(0X0ceU) | IID_FLAG)
++#define IID_CONNMGR_AVIMP4_PLAYER (IID_ID(0X0cfU) | IID_FLAG)
++#define IID_VDECANAEXT2 (IID_ID(0X0d0U) | IID_FLAG)
++#define IID_STBCOMMON (IID_ID(0X0d1U) | IID_FLAG)
++#define IID_AVSYNCCTRL (IID_ID(0X0d2U) | IID_FLAG)
++#define IID_PRIVNETSCHEMECONFIG (IID_ID(0X0d3U) | IID_FLAG)
++#define IID_SHAREDVARIABLE (IID_ID(0X0d4U) | IID_FLAG)
++#define IID_NETSCHEMECONFIG (IID_ID(0X0d5U) | IID_FLAG)
++#define IID_AVSYNCTRICK (IID_ID(0X0d6U) | IID_FLAG)
++#define IID_SETINTF (IID_ID(0X0d7U) | IID_FLAG)
++#define IID_URLDMXMONITOR (IID_ID(0X0d8U) | IID_FLAG)
++#define IID_VDECMONITOR (IID_ID(0X0d9U) | IID_FLAG)
++#define IID_STBVIDEOTYPES (IID_ID(0X0daU) | IID_FLAG)
++
++#define IID_RESERVED (CID_ID(0x7fffU) | CID_FLAG)
++/* ************************************************************************** */
++/* Interface Id's reserved for external organizations */
++/* */
++/* None */
++/* */
++/* ************************************************************************** */
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Definition of the component IDs */
++/* */
++/* -------------------------------------------------------------------------- */
++#define CID_MPMP1_GRINDER (CID_ID(0x8001U) | CID_FLAG)
++#define CID_MUSB_GRINDER (CID_ID(0x8002U) | CID_FLAG)
++#define CID_UOTGPFL (CID_ID(0x8003U) | CID_FLAG)
++#define CID_CHIPBUILDER_GRINDER (CID_ID(0x8004U) | CID_FLAG)
++
++#define CID_AANALYZER (CID_ID(0x8009U) | CID_FLAG)
++#define CID_ADEC_AAC4 (CID_ID(0x800aU) | CID_FLAG)
++#define CID_ADEC_ATV (CID_ID(0x800bU) | CID_FLAG)
++#define CID_ADEC_CELP4 (CID_ID(0x800cU) | CID_FLAG)
++#define CID_ADEC_CORE (CID_ID(0x800dU) | CID_FLAG)
++#define CID_ADEC_MP3PRO (CID_ID(0x800eU) | CID_FLAG)
++#define CID_ADEC_PL2 (CID_ID(0x800fU) | CID_FLAG)
++#define CID_ADEC_STB (CID_ID(0x8010U) | CID_FLAG)
++#define CID_ADEEMPH (CID_ID(0x8011U) | CID_FLAG)
++#define CID_AENCAAC4 (CID_ID(0x8012U) | CID_FLAG)
++#define CID_AREND_AO_MUX (CID_ID(0x8013U) | CID_FLAG)
++#define CID_ASP_IIRZ2 (CID_ID(0x8014U) | CID_FLAG)
++#define CID_ASRC (CID_ID(0x8015U) | CID_FLAG)
++#define CID_ASYS_CORE (CID_ID(0x8016U) | CID_FLAG)
++#define CID_ATV_PLF_BASIC (CID_ID(0x8017U) | CID_FLAG)
++#define CID_ATV_STUBS (CID_ID(0x8018U) | CID_FLAG)
++#define CID_AVI_READ_DIVX (CID_ID(0x8019U) | CID_FLAG)
++#define CID_BOOTINFO (CID_ID(0x801aU) | CID_FLAG)
++#define CID_BROWSE_EIS (CID_ID(0x801bU) | CID_FLAG)
++#define CID_BSL_7113 (CID_ID(0x801cU) | CID_FLAG)
++#define CID_BSL_7113QT (CID_ID(0x801dU) | CID_FLAG)
++#define CID_BSL_7114 (CID_ID(0x801eU) | CID_FLAG)
++#define CID_BSL_7118 (CID_ID(0x801fU) | CID_FLAG)
++#define CID_BSL_ANABEL (CID_ID(0x8020U) | CID_FLAG)
++#define CID_BSL_ANABELQT (CID_ID(0x8021U) | CID_FLAG)
++#define CID_BSL_AVIP (CID_ID(0x8022U) | CID_FLAG)
++#define CID_BSL_BOARDS (CID_ID(0x8023U) | CID_FLAG)
++#define CID_BSL_CORE (CID_ID(0x8024U) | CID_FLAG)
++#define CID_BSL_DENC (CID_ID(0x8025U) | CID_FLAG)
++#define CID_BSL_EEPROM_ATMEL (CID_ID(0x8026U) | CID_FLAG)
++#define CID_BSL_IDEXIO (CID_ID(0x8027U) | CID_FLAG)
++#define CID_BSL_NANDSAMSUNG (CID_ID(0x8028U) | CID_FLAG)
++#define CID_BSL_NORINTEL (CID_ID(0x8029U) | CID_FLAG)
++#define CID_BSL_RTCPCF8563 (CID_ID(0x802aU) | CID_FLAG)
++#define CID_BSL_UART_HWAPI (CID_ID(0x802bU) | CID_FLAG)
++#define CID_BSL_UDA1344 (CID_ID(0x802cU) | CID_FLAG)
++#define CID_BT_1500 (CID_ID(0x802dU) | CID_FLAG)
++#define CID_BT_API (CID_ID(0x802eU) | CID_FLAG)
++#define CID_BT_CORE (CID_ID(0x802fU) | CID_FLAG)
++#define CID_BT_CPU (CID_ID(0x8030U) | CID_FLAG)
++#define CID_BT_MIPS (CID_ID(0x8031U) | CID_FLAG)
++#define CID_BT_TRIMEDIA (CID_ID(0x8032U) | CID_FLAG)
++#define CID_BT_V2PCI (CID_ID(0x8033U) | CID_FLAG)
++#define CID_BT_VPCI (CID_ID(0x8034U) | CID_FLAG)
++#define CID_BT_VSTB (CID_ID(0x8035U) | CID_FLAG)
++#define CID_BUFFEREDREAD (CID_ID(0x8036U) | CID_FLAG)
++#define CID_CONN_MGRAUDSYSSTB (CID_ID(0x8037U) | CID_FLAG)
++#define CID_DEMUXMPEGTS_SW (CID_ID(0x8038U) | CID_FLAG)
++#define CID_DIG_ADEC_AUDSYS_STB (CID_ID(0x8039U) | CID_FLAG)
++#define CID_DL_AI (CID_ID(0x803aU) | CID_FLAG)
++#define CID_DL_AICP (CID_ID(0x803bU) | CID_FLAG)
++#define CID_DL_AO (CID_ID(0x803cU) | CID_FLAG)
++#define CID_DL_AVFS (CID_ID(0x803dU) | CID_FLAG)
++#define CID_DL_CLOCK (CID_ID(0x803eU) | CID_FLAG)
++#define CID_DL_DFS (CID_ID(0x803fU) | CID_FLAG)
++#define CID_DL_DISKSCHED (CID_ID(0x8040U) | CID_FLAG)
++#define CID_DL_DMA (CID_ID(0x8041U) | CID_FLAG)
++#define CID_DL_ETH_IP3902 (CID_ID(0x8042U) | CID_FLAG)
++#define CID_DL_GPIO (CID_ID(0x8043U) | CID_FLAG)
++#define CID_DL_I2C (CID_ID(0x8044U) | CID_FLAG)
++#define CID_DL_IDE (CID_ID(0x8045U) | CID_FLAG)
++#define CID_DL_IDESTUB (CID_ID(0x8046U) | CID_FLAG)
++#define CID_DL_IIC (CID_ID(0x8047U) | CID_FLAG)
++#define CID_DL_IR (CID_ID(0x8048U) | CID_FLAG)
++#define CID_DL_MBS (CID_ID(0x8049U) | CID_FLAG)
++#define CID_DL_MBS2 (CID_ID(0x804aU) | CID_FLAG)
++#define CID_DL_NANDFLASH (CID_ID(0x804bU) | CID_FLAG)
++#define CID_DL_NORFLASH (CID_ID(0x804cU) | CID_FLAG)
++#define CID_DL_PCI (CID_ID(0x804dU) | CID_FLAG)
++#define CID_DL_PROCESSOR (CID_ID(0x804eU) | CID_FLAG)
++#define CID_DL_QTNR (CID_ID(0x804fU) | CID_FLAG)
++#define CID_DL_QVCP (CID_ID(0x8050U) | CID_FLAG)
++#define CID_DL_SEM (CID_ID(0x8051U) | CID_FLAG)
++#define CID_DL_SPDI (CID_ID(0x8052U) | CID_FLAG)
++#define CID_DL_SPDO (CID_ID(0x8053U) | CID_FLAG)
++#define CID_DL_TIMER (CID_ID(0x8054U) | CID_FLAG)
++#define CID_DL_TSDMA (CID_ID(0x8055U) | CID_FLAG)
++#define CID_DL_TSIO (CID_ID(0x8056U) | CID_FLAG)
++#define CID_DL_UDMA (CID_ID(0x8057U) | CID_FLAG)
++#define CID_DL_VID_MEAS (CID_ID(0x8058U) | CID_FLAG)
++#define CID_DL_VIP (CID_ID(0x8059U) | CID_FLAG)
++#define CID_DL_VMPG (CID_ID(0x805aU) | CID_FLAG)
++#define CID_DL_XIO (CID_ID(0x805bU) | CID_FLAG)
++#define CID_DRAWTEXT (CID_ID(0x805cU) | CID_FLAG)
++#define CID_DVPDEBUG (CID_ID(0x805dU) | CID_FLAG)
++#define CID_FATALERROR (CID_ID(0x805eU) | CID_FLAG)
++#define CID_FATALERROR_VT (CID_ID(0x805fU) | CID_FLAG)
++#define CID_FREADAVPROP (CID_ID(0x8060U) | CID_FLAG)
++#define CID_FWRITEAVPROP (CID_ID(0x8061U) | CID_FLAG)
++#define CID_HELP (CID_ID(0x8062U) | CID_FLAG)
++#define CID_HTTP_IO_DRIVER (CID_ID(0x8063U) | CID_FLAG)
++#define CID_HW_AICP (CID_ID(0x8064U) | CID_FLAG)
++#define CID_HW_CLOCK (CID_ID(0x8065U) | CID_FLAG)
++#define CID_HW_DMA (CID_ID(0x8066U) | CID_FLAG)
++#define CID_HW_DRAW (CID_ID(0x8067U) | CID_FLAG)
++#define CID_HW_DRAWCOMMON (CID_ID(0x8068U) | CID_FLAG)
++#define CID_HW_DRAWDE (CID_ID(0x8069U) | CID_FLAG)
++#define CID_HW_DRAWREF (CID_ID(0x806aU) | CID_FLAG)
++#define CID_HW_DRAWSHARED (CID_ID(0x806bU) | CID_FLAG)
++#define CID_HW_DRAWTMH (CID_ID(0x806cU) | CID_FLAG)
++#define CID_HW_DRAWTMT (CID_ID(0x806dU) | CID_FLAG)
++#define CID_HW_DRAWTMTH (CID_ID(0x806eU) | CID_FLAG)
++#define CID_HW_DSP (CID_ID(0x806fU) | CID_FLAG)
++#define CID_HW_ETH_IP3902 (CID_ID(0x8070U) | CID_FLAG)
++#define CID_HW_GIC (CID_ID(0x8071U) | CID_FLAG)
++#define CID_HW_GPIO (CID_ID(0x8072U) | CID_FLAG)
++#define CID_HW_I2C (CID_ID(0x8073U) | CID_FLAG)
++#define CID_HW_IIC (CID_ID(0x8074U) | CID_FLAG)
++#define CID_HW_MBS (CID_ID(0x8075U) | CID_FLAG)
++#define CID_HW_MMIARB (CID_ID(0x8076U) | CID_FLAG)
++#define CID_HW_MMIARB1010 (CID_ID(0x8077U) | CID_FLAG)
++#define CID_HW_PCI (CID_ID(0x8078U) | CID_FLAG)
++#define CID_HW_PIC (CID_ID(0x8079U) | CID_FLAG)
++#define CID_HW_SMC (CID_ID(0x807aU) | CID_FLAG)
++#define CID_HW_TSDMA (CID_ID(0x807bU) | CID_FLAG)
++#define CID_HW_UART (CID_ID(0x807cU) | CID_FLAG)
++#define CID_HW_UDMA (CID_ID(0x807dU) | CID_FLAG)
++#define CID_HW_VIP (CID_ID(0x807eU) | CID_FLAG)
++#define CID_HW_VMSP (CID_ID(0x807fU) | CID_FLAG)
++#define CID_HW_XIO (CID_ID(0x8080U) | CID_FLAG)
++#define CID_INFRA_MISC (CID_ID(0x8081U) | CID_FLAG)
++#define CID_INTERRUPT (CID_ID(0x8082U) | CID_FLAG)
++#define CID_IPC_DT (CID_ID(0x8083U) | CID_FLAG)
++#define CID_IPC_READ (CID_ID(0x8084U) | CID_FLAG)
++#define CID_IPC_RPC (CID_ID(0x8085U) | CID_FLAG)
++#define CID_IPC_WRITE (CID_ID(0x8086U) | CID_FLAG)
++#define CID_LIBLOAD_TM (CID_ID(0x8087U) | CID_FLAG)
++#define CID_MEMDBG (CID_ID(0x8088U) | CID_FLAG)
++#define CID_MENU (CID_ID(0x8089U) | CID_FLAG)
++#define CID_MP4READ (CID_ID(0x808aU) | CID_FLAG)
++#define CID_MPEGCOLORBAR (CID_ID(0x808bU) | CID_FLAG)
++#define CID_NETSTACK_FUSION (CID_ID(0x808cU) | CID_FLAG)
++#define CID_NETSTACK_TARGET_TCP (CID_ID(0x808dU) | CID_FLAG)
++#define CID_NETSTACK_UPNP_ALLEGRO (CID_ID(0x808dU) | CID_FLAG)
++#define CID_NETSTACK_UPNP_INTEL (CID_ID(0x808eU) | CID_FLAG)
++#define CID_NETWORKREAD (CID_ID(0x8090U) | CID_FLAG)
++#define CID_NM_COMMON (CID_ID(0x8091U) | CID_FLAG)
++#define CID_NM_DEI (CID_ID(0x8092U) | CID_FLAG)
++#define CID_NM_EST (CID_ID(0x8093U) | CID_FLAG)
++#define CID_NM_QFD (CID_ID(0x8094U) | CID_FLAG)
++#define CID_NM_UPC (CID_ID(0x8095U) | CID_FLAG)
++#define CID_NM_UPC_SPIDER (CID_ID(0x8096U) | CID_FLAG)
++#define CID_OS (CID_ID(0x8097U) | CID_FLAG)
++#define CID_PROBE (CID_ID(0x8098U) | CID_FLAG)
++#define CID_PSIUTIL (CID_ID(0x8099U) | CID_FLAG)
++#define CID_REALNETWORKS_ENGINE (CID_ID(0x809aU) | CID_FLAG)
++#define CID_SCAN_RATE_CONV_VSYS_TV (CID_ID(0x809bU) | CID_FLAG)
++#define CID_SPOSAL (CID_ID(0x809cU) | CID_FLAG)
++#define CID_TIMEDOCTOR (CID_ID(0x809dU) | CID_FLAG)
++#define CID_TSA_CLOCK (CID_ID(0x809eU) | CID_FLAG)
++
++#define CID_TST_AVETC_SINK (CID_ID(0x80a0U) | CID_FLAG)
++#define CID_TST_DEMUX (CID_ID(0x80a1U) | CID_FLAG)
++#define CID_TST_DEMUX_FOR_MUX (CID_ID(0x80a2U) | CID_FLAG)
++#define CID_TST_SPTS_SINK (CID_ID(0x80a3U) | CID_FLAG)
++#define CID_TTI_UTIL (CID_ID(0x80a4U) | CID_FLAG)
++#define CID_UART (CID_ID(0x80a5U) | CID_FLAG)
++#define CID_UPCONV100MC (CID_ID(0x80a6U) | CID_FLAG)
++#define CID_UTILCPIREC (CID_ID(0x80a7U) | CID_FLAG)
++#define CID_UTILCRYPTRIJNDAEL (CID_ID(0x80a8U) | CID_FLAG)
++#define CID_VATV (CID_ID(0x80a9U) | CID_FLAG)
++#define CID_VATV_TR (CID_ID(0x80aaU) | CID_FLAG)
++#define CID_VBI_INSERT_VSYS_TV (CID_ID(0x80abU) | CID_FLAG)
++#define CID_VCAP_VIP2 (CID_ID(0x80acU) | CID_FLAG)
++#define CID_VDEC_BMP (CID_ID(0x80adU) | CID_FLAG)
++#define CID_VDEC_DIVX (CID_ID(0x80aeU) | CID_FLAG)
++#define CID_VDEC_GIF (CID_ID(0x80afU) | CID_FLAG)
++#define CID_VDEC_JPEG (CID_ID(0x80b0U) | CID_FLAG)
++#define CID_VDEC_JPEG2K (CID_ID(0x80b1U) | CID_FLAG)
++#define CID_VDEC_MP (CID_ID(0x80b2U) | CID_FLAG)
++#define CID_VDECMPEG4 (CID_ID(0x80b3U) | CID_FLAG)
++#define CID_VENC_MPEG4 (CID_ID(0x80b4U) | CID_FLAG)
++#define CID_VENCMJPEG (CID_ID(0x80b5U) | CID_FLAG)
++#define CID_VENCMPEG2 (CID_ID(0x80b6U) | CID_FLAG)
++#define CID_VIDEOUTIL (CID_ID(0x80b7U) | CID_FLAG)
++#define CID_VPACK (CID_ID(0x80b8U) | CID_FLAG)
++#define CID_VPIP_REC_PLAY (CID_ID(0x80b9U) | CID_FLAG)
++#define CID_VPOST_ICP (CID_ID(0x80baU) | CID_FLAG)
++#define CID_VREND_VCP (CID_ID(0x80bbU) | CID_FLAG)
++#define CID_VRENDVO (CID_ID(0x80bcU) | CID_FLAG)
++#define CID_VSCHED (CID_ID(0x80bdU) | CID_FLAG)
++#define CID_VTBLBASE (CID_ID(0x80beU) | CID_FLAG)
++#define CID_VTRANS_MBS2 (CID_ID(0x80bfU) | CID_FLAG)
++#define CID_VTRANS_QTNR (CID_ID(0x80c0U) | CID_FLAG)
++#define CID_VXWORKS_BSP (CID_ID(0x80c1U) | CID_FLAG)
++#define CID_WREAD (CID_ID(0x80c2U) | CID_FLAG)
++#define CID_CONNMGR_ATV (CID_ID(0x80c3U) | CID_FLAG)
++#define CID_DL_VPK (CID_ID(0x80c4U) | CID_FLAG)
++#define CID_VTRANS_VPK (CID_ID(0x80c5U) | CID_FLAG)
++#define CID_DL_VIP2 (CID_ID(0x80c6U) | CID_FLAG)
++#define CID_VX_GEN_UART (CID_ID(0x80c7U) | CID_FLAG)
++#define CID_VX_GPIO (CID_ID(0x80c8U) | CID_FLAG)
++#define CID_VX_GEN_TIMER (CID_ID(0x80c9U) | CID_FLAG)
++#define CID_M4VENC_DIS (CID_ID(0x80caU) | CID_FLAG)
++#define CID_VENC_ANA (CID_ID(0x80cbU) | CID_FLAG)
++#define CID_BSL_VENC_ANA (CID_ID(0x80ccU) | CID_FLAG)
++#define CID_BSL_VENC_ANA_EXT (CID_ID(0x80cdU) | CID_FLAG)
++#define CID_BSL_VENC_ANAVBI_EXT (CID_ID(0x80ceU) | CID_FLAG)
++#define CID_CMDX (CID_ID(0x80cfU) | CID_FLAG)
++#define CID_LL_GPIO (CID_ID(0x80d0U) | CID_FLAG)
++#define CID_LL_KEYPAD (CID_ID(0x80d1U) | CID_FLAG)
++#define CID_LL_TIMER (CID_ID(0x80d2U) | CID_FLAG)
++#define CID_LL_SPI (CID_ID(0x80d3U) | CID_FLAG)
++#define CID_LL_UART (CID_ID(0x80d4U) | CID_FLAG)
++#define CID_LL_I2C (CID_ID(0x80d5U) | CID_FLAG)
++#define CID_LL_TR (CID_ID(0x80d6U) | CID_FLAG)
++#define CID_HW_KEYPAD (CID_ID(0x80d7U) | CID_FLAG)
++#define CID_HW_TIMER (CID_ID(0x80d8U) | CID_FLAG)
++#define CID_HW_SPI (CID_ID(0x80d9U) | CID_FLAG)
++#define CID_HW_VATV_IOSYNC (CID_ID(0x80daU) | CID_FLAG)
++#define CID_DL_VO (CID_ID(0x80dbU) | CID_FLAG)
++#define CID_DL_LVDS (CID_ID(0x80dcU) | CID_FLAG)
++#define CID_HW_DDR2031 (CID_ID(0x80ddU) | CID_FLAG)
++#define CID_BSL_PHY (CID_ID(0x80deU) | CID_FLAG)
++#define CID_ETH_TTCP (CID_ID(0x80dfU) | CID_FLAG)
++#define CID_CDIGADEC_MP3PRO (CID_ID(0x80e0U) | CID_FLAG)
++#define CID_CID3EXTR (CID_ID(0x80e1U) | CID_FLAG)
++#define CID_IMAGEDEC_JPEG (CID_ID(0x80e2U) | CID_FLAG)
++#define CID_CURLSRC_MP3PRO (CID_ID(0x80e3U) | CID_FLAG)
++#define CID_CURLSRC_IMAGEDEC (CID_ID(0x80e4U) | CID_FLAG)
++#define CID_DVP_MAIN (CID_ID(0x80e5U) | CID_FLAG)
++#define CID_TMMAN32 (CID_ID(0x80e6U) | CID_FLAG)
++#define CID_TMMAN_CRT (CID_ID(0x80e7U) | CID_FLAG)
++#define CID_UHS_HAL_PCI (CID_ID(0x80e8U) | CID_FLAG)
++#define CID_UHS_OSAL_VXWORKS (CID_ID(0x80e9U) | CID_FLAG)
++#define CID_UHS_OSAL_PSOS (CID_ID(0x80eaU) | CID_FLAG)
++#define CID_UHS_USBD (CID_ID(0x80ebU) | CID_FLAG)
++#define CID_UHS_RBC (CID_ID(0x80ecU) | CID_FLAG)
++#define CID_UHS_UFI (CID_ID(0x80edU) | CID_FLAG)
++#define CID_UHS_SCSI (CID_ID(0x80eeU) | CID_FLAG)
++#define CID_UHS_PRINTER (CID_ID(0x80efU) | CID_FLAG)
++#define CID_UHS_MOUSE (CID_ID(0x80f0U) | CID_FLAG)
++#define CID_UHS_KEYBOARD (CID_ID(0x80f1U) | CID_FLAG)
++#define CID_UHS_HUB (CID_ID(0x80f2U) | CID_FLAG)
++#define CID_UHS_HCD_1561 (CID_ID(0x80f3U) | CID_FLAG)
++#define CID_CLEANUP (CID_ID(0x80f4U) | CID_FLAG)
++#define CID_ALLOCATOR (CID_ID(0x80f5U) | CID_FLAG)
++#define CID_TCS_CORE_LIBDEV (CID_ID(0x80f6U) | CID_FLAG)
++#define CID_VDI_VDO_ROUTER (CID_ID(0x80f7U) | CID_FLAG)
++#define CID_CONNMGR_ATSC (CID_ID(0x80f8U) | CID_FLAG)
++#define CID_ASPDIF (CID_ID(0x80f9U) | CID_FLAG)
++#define CID_APLL (CID_ID(0x80faU) | CID_FLAG)
++#define CID_ATVPLFINSTVIN (CID_ID(0x80fbU) | CID_FLAG)
++#define CID_ATV_PLF (CID_ID(0x80fcU) | CID_FLAG)
++#define CID_DL_WATCHDOG (CID_ID(0x80fdU) | CID_FLAG)
++#define CID_WMT_NET_READER (CID_ID(0x80feU) | CID_FLAG)
++#define CID_DL_FGPO (CID_ID(0x80ffU) | CID_FLAG)
++#define CID_DL_FGPI (CID_ID(0x8100U) | CID_FLAG)
++#define CID_WMT_DECODER (CID_ID(0x8101U) | CID_FLAG)
++#define CID_HAD_DRV_IIC (CID_ID(0x8102U) | CID_FLAG)
++#define CID_HAD_DRV_GPIO (CID_ID(0x8103U) | CID_FLAG)
++#define CID_HAD_GLOBAL (CID_ID(0x8104U) | CID_FLAG)
++#define CID_HAD_SMM (CID_ID(0x8105U) | CID_FLAG)
++#define CID_HAD_DRV_CSM (CID_ID(0x8106U) | CID_FLAG)
++#define CID_CARACASWDOG (CID_ID(0x8107U) | CID_FLAG)
++#define CID_CARACASADC (CID_ID(0x8108U) | CID_FLAG)
++#define CID_CARACASDMA (CID_ID(0x8109U) | CID_FLAG)
++#define CID_CARACASFLASHCTRL (CID_ID(0x810aU) | CID_FLAG)
++#define CID_CARACASGPTIMER (CID_ID(0x810bU) | CID_FLAG)
++#define CID_CARACASGPIO (CID_ID(0x810cU) | CID_FLAG)
++#define CID_CARACASI2CMO (CID_ID(0x810dU) | CID_FLAG)
++#define CID_CARACASI2CMS (CID_ID(0x810eU) | CID_FLAG)
++#define CID_CARACASRTC (CID_ID(0x810fU) | CID_FLAG)
++#define CID_CARACASSPI (CID_ID(0x8110U) | CID_FLAG)
++#define CID_CARACASTIMER (CID_ID(0x8111U) | CID_FLAG)
++#define CID_CARACASUART (CID_ID(0x8112U) | CID_FLAG)
++#define CID_TSSA40 (CID_ID(0x8113U) | CID_FLAG)
++#define CID_PACKET_POOL (CID_ID(0x8114U) | CID_FLAG)
++#define CID_TSSA15_WRAPPER (CID_ID(0x8115U) | CID_FLAG)
++#define CID_TASK_SYNC (CID_ID(0x8116U) | CID_FLAG)
++#define CID_TASK_CONDITION (CID_ID(0x8117U) | CID_FLAG)
++#define CID_PACKET_QUEUE (CID_ID(0x8118U) | CID_FLAG)
++#define CID_CONNECTION_TOOLKIT (CID_ID(0x8119U) | CID_FLAG)
++#define CID_TSSA16 (CID_ID(0x811aU) | CID_FLAG)
++#define CID_UDSDFU (CID_ID(0x811bU) | CID_FLAG)
++#define CID_BTH (CID_ID(0x811cU) | CID_FLAG)
++#define CID_DCDIP9021 (CID_ID(0x811dU) | CID_FLAG)
++#define CID_DCDIP3501V1X (CID_ID(0x811eU) | CID_FLAG)
++#define CID_ISP1581 (CID_ID(0x811fU) | CID_FLAG)
++#define CID_DCSS_TV (CID_ID(0x8120U) | CID_FLAG)
++#define CID_DCSS_MON (CID_ID(0x8121U) | CID_FLAG)
++#define CID_DCSS_RSC_PC (CID_ID(0x8122U) | CID_FLAG)
++#define CID_DCSS_RSC_INT (CID_ID(0x8123U) | CID_FLAG)
++#define CID_DCSS_RSC_EXT (CID_ID(0x8124U) | CID_FLAG)
++#define CID_DCSS_LIT (CID_ID(0x8125U) | CID_FLAG)
++#define CID_DCSS_LIT_C (CID_ID(0x8126U) | CID_FLAG)
++#define CID_DCSS_45A (CID_ID(0x8127U) | CID_FLAG)
++#define CID_UDSCORE (CID_ID(0x8128U) | CID_FLAG)
++#define CID_HW_AUDIO7135 (CID_ID(0x8129U) | CID_FLAG)
++#define CID_DL_AUDIO3X (CID_ID(0x812aU) | CID_FLAG)
++#define CID_REGACC (CID_ID(0x812bU) | CID_FLAG)
++#define CID_HW_MJPEG (CID_ID(0x812cU) | CID_FLAG)
++#define CID_ISP1582 (CID_ID(0x812dU) | CID_FLAG)
++#define CID_MUTI (CID_ID(0x812eU) | CID_FLAG)
++#define CID_CHANNEL_DECODER_ENCODER (CID_ID(0x812fU) | CID_FLAG)
++#define CID_RESMGR (CID_ID(0x8130U) | CID_FLAG)
++#define CID_WIDGET (CID_ID(0x8131U) | CID_FLAG)
++#define CID_FB (CID_ID(0x8132U) | CID_FLAG)
++#define CID_GFX (CID_ID(0x8133U) | CID_FLAG)
++#define CID_HPS_DISPATCHER (CID_ID(0x8134U) | CID_FLAG)
++#define CID_DL_PLXGPIO (CID_ID(0x8135U) | CID_FLAG)
++#define CID_HW_PLXGPIO (CID_ID(0x8136U) | CID_FLAG)
++#define CID_DL_PLXPHI (CID_ID(0x8137U) | CID_FLAG)
++#define CID_HW_PLXPHI_EVALUATOR (CID_ID(0x8138U) | CID_FLAG)
++#define CID_DL_SCALER (CID_ID(0x8139U) | CID_FLAG)
++#define CID_EFM (CID_ID(0x813aU) | CID_FLAG)
++#define CID_HW_TUNER_FM1236MK3 (CID_ID(0x813bU) | CID_FLAG)
++#define CID_HW_TUNER_FM1216MK3 (CID_ID(0x813cU) | CID_FLAG)
++#define CID_HW_TUNER_FM1216MK2 (CID_ID(0x813dU) | CID_FLAG)
++#define CID_ANALOG_CHANNEL_TABLE (CID_ID(0x813eU) | CID_FLAG)
++#define CID_TUNER_CONTROL (CID_ID(0x813fU) | CID_FLAG)
++#define CID_DL_UIMS (CID_ID(0x8140U) | CID_FLAG)
++#define CID_DL_RCTRANSMITTER (CID_ID(0x8141U) | CID_FLAG)
++#define CID_HW_CST_RCRECEIVER (CID_ID(0x8142U) | CID_FLAG)
++#define CID_HW_CST_RCTRANSMITTER (CID_ID(0x8143U) | CID_FLAG)
++#define CID_DCDIP3506 (CID_ID(0x8144U) | CID_FLAG)
++#define CID_DCDIP3501V2X (CID_ID(0x8145U) | CID_FLAG)
++#define CID_MTV_COORD (CID_ID(0x8146U) | CID_FLAG)
++#define CID_MTV_IMG_ROT_CTRL (CID_ID(0x8147U) | CID_FLAG)
++#define CID_TFE_TRACE (CID_ID(0x8148U) | CID_FLAG)
++#define CID_TMCAL_SERVER (CID_ID(0x8149U) | CID_FLAG)
++#define CID_BOOT_LOADER (CID_ID(0x814aU) | CID_FLAG)
++#define CID_TD_SAVE_DATA (CID_ID(0x814bU) | CID_FLAG)
++#define CID_TFE_TRACE_PROCESS_DATA (CID_ID(0x814cU) | CID_FLAG)
++#define CID_VIDEOCTRL (CID_ID(0x814dU) | CID_FLAG)
++#define CID_BOOT (CID_ID(0x814eU) | CID_FLAG)
++#define CID_EVENT (CID_ID(0x814fU) | CID_FLAG)
++#define CID_USERINPUT (CID_ID(0x8150U) | CID_FLAG)
++#define CID_BSL_TUNER (CID_ID(0x8151U) | CID_FLAG)
++#define CID_P5KIIC (CID_ID(0x8152U) | CID_FLAG)
++#define CID_HW_PMANSECURITY (CID_ID(0x8153U) | CID_FLAG)
++#define CID_DRM_DIVX (CID_ID(0x8154U) | CID_FLAG)
++#define CID_TMHWVIDEODEC7136 (CID_ID(0x8155U) | CID_FLAG)
++#define CID_TMDLVIDEODEC (CID_ID(0x8156U) | CID_FLAG)
++#define CID_OSD_KERNEL (CID_ID(0x8157U) | CID_FLAG)
++#define CID_HW_DCSNETWORK (CID_ID(0x8158U) | CID_FLAG)
++#define CID_DL_RCRECEIVER (CID_ID(0x8159U) | CID_FLAG)
++#define CID_INT (CID_ID(0x815aU) | CID_FLAG)
++#define CID_RTC (CID_ID(0x815bU) | CID_FLAG)
++#define CID_TIMER (CID_ID(0x815cU) | CID_FLAG)
++#define CID_IPC (CID_ID(0x815dU) | CID_FLAG)
++#define CID_P5KTELETEXT (CID_ID(0x815eU) | CID_FLAG)
++#define CID_P5KAUDIOVIDEO (CID_ID(0x815fU) | CID_FLAG)
++#define CID_P5KCONFIG (CID_ID(0x8160U) | CID_FLAG)
++#define CID_HW_CST_TRANSPSTREAMIN (CID_ID(0x8161U) | CID_FLAG)
++#define CID_HOMER_KERNEL (CID_ID(0x8162U) | CID_FLAG)
++#define CID_HOMER_DRIVER (CID_ID(0x8163U) | CID_FLAG)
++#define CID_CD_FILE_SYSTEM (CID_ID(0x8164U) | CID_FLAG)
++#define CID_COBALT_APP (CID_ID(0x8165U) | CID_FLAG)
++#define CID_COBALT_UI (CID_ID(0x8166U) | CID_FLAG)
++#define CID_CD_SERVO (CID_ID(0x8167U) | CID_FLAG)
++#define CID_CD_UTILS (CID_ID(0x8168U) | CID_FLAG)
++#define CID_COBALT_SYSTEM (CID_ID(0x8169U) | CID_FLAG)
++#define CID_CDSLIM (CID_ID(0x816aU) | CID_FLAG)
++#define CID_CD_DATABASE (CID_ID(0x816bU) | CID_FLAG)
++#define CID_CANAVENC (CID_ID(0x816cU) | CID_FLAG)
++#define CID_CANTIAGING (CID_ID(0x816dU) | CID_FLAG)
++#define CID_CAUTOPICTCTRL (CID_ID(0x816eU) | CID_FLAG)
++#define CID_CBBARCTRL (CID_ID(0x816fU) | CID_FLAG)
++#define CID_CBBARDET (CID_ID(0x8170U) | CID_FLAG)
++#define CID_CBBARDETEXT (CID_ID(0x8171U) | CID_FLAG)
++#define CID_CBLEVELDETEXT (CID_ID(0x8172U) | CID_FLAG)
++#define CID_CCOLENH (CID_ID(0x8173U) | CID_FLAG)
++#define CID_CCOLENHEXT (CID_ID(0x8174U) | CID_FLAG)
++#define CID_CCONTRESEXT (CID_ID(0x8175U) | CID_FLAG)
++#define CID_CCTI (CID_ID(0x8176U) | CID_FLAG)
++#define CID_CCTIEXT (CID_ID(0x8177U) | CID_FLAG)
++#define CID_CDNR (CID_ID(0x8178U) | CID_FLAG)
++#define CID_CDNREXT (CID_ID(0x8179U) | CID_FLAG)
++#define CID_CGAMMAEXT (CID_ID(0x817aU) | CID_FLAG)
++#define CID_CHISTOMEASEXT (CID_ID(0x817bU) | CID_FLAG)
++#define CID_CHISTOMOD (CID_ID(0x817cU) | CID_FLAG)
++#define CID_CHISTOMODEXT (CID_ID(0x817dU) | CID_FLAG)
++#define CID_CMBSXRAY (CID_ID(0x817eU) | CID_FLAG)
++#define CID_CNOISE (CID_ID(0x817fU) | CID_FLAG)
++#define CID_CNOISEESTEXT (CID_ID(0x8180U) | CID_FLAG)
++#define CID_CPFSPD (CID_ID(0x8181U) | CID_FLAG)
++#define CID_CQVCPXRAY (CID_ID(0x8182U) | CID_FLAG)
++#define CID_CSCANRATECONV (CID_ID(0x8183U) | CID_FLAG)
++#define CID_CSCANRATECONVEXT (CID_ID(0x8184U) | CID_FLAG)
++#define CID_CSHARPENH (CID_ID(0x8185U) | CID_FLAG)
++#define CID_CSHARPENHEXT (CID_ID(0x8186U) | CID_FLAG)
++#define CID_CSHARPMEAS (CID_ID(0x8187U) | CID_FLAG)
++#define CID_CSHARPMEASEXT (CID_ID(0x8188U) | CID_FLAG)
++#define CID_CSYNCTAG (CID_ID(0x8189U) | CID_FLAG)
++#define CID_CUVBWDETEXT (CID_ID(0x818aU) | CID_FLAG)
++#define CID_CVBISLICE (CID_ID(0x818bU) | CID_FLAG)
++#define CID_CVFEAT (CID_ID(0x818cU) | CID_FLAG)
++#define CID_CVFEAT2 (CID_ID(0x818dU) | CID_FLAG)
++#define CID_CVIPXRAY (CID_ID(0x818eU) | CID_FLAG)
++#define CID_CVIPXRAYDITHER (CID_ID(0x818fU) | CID_FLAG)
++#define CID_CVMIX (CID_ID(0x8190U) | CID_FLAG)
++#define CID_CVTRSCALEEXT (CID_ID(0x8191U) | CID_FLAG)
++#define CID_CVTRANTIAGING (CID_ID(0x8192U) | CID_FLAG)
++#define CID_CVTRFADEVCP (CID_ID(0x8193U) | CID_FLAG)
++#define CID_CVTRSCALEMBSVCP (CID_ID(0x8194U) | CID_FLAG)
++#define CID_CVTRSTROBEMBS (CID_ID(0x8195U) | CID_FLAG)
++#define CID_NM_UTILS (CID_ID(0x8196U) | CID_FLAG)
++#define CID_VSEQSCHEDENGINE (CID_ID(0x8197U) | CID_FLAG)
++#define CID_VCPSCHEDENGINE (CID_ID(0x8198U) | CID_FLAG)
++#define CID_VGENTEST (CID_ID(0x8199U) | CID_FLAG)
++#define CID_VMENU (CID_ID(0x819aU) | CID_FLAG)
++#define CID_VPROCCOMMON (CID_ID(0x819bU) | CID_FLAG)
++#define CID_VPROCTV (CID_ID(0x819cU) | CID_FLAG)
++#define CID_VPROCTV505E (CID_ID(0x819dU) | CID_FLAG)
++#define CID_SCHEDENGINE (CID_ID(0x819eU) | CID_FLAG)
++#define CID_VSLNMCOMMON (CID_ID(0x819fU) | CID_FLAG)
++#define CID_VSLVCAPVIP (CID_ID(0x81a0U) | CID_FLAG)
++#define CID_VSLVCAPVIPVBI (CID_ID(0x81a1U) | CID_FLAG)
++#define CID_VSLVINCONVERT (CID_ID(0x81a2U) | CID_FLAG)
++#define CID_VSLIOSYNC (CID_ID(0x81a3U) | CID_FLAG)
++#define CID_VSLVRENDVCP (CID_ID(0x81a4U) | CID_FLAG)
++#define CID_VSLVRENDVCPVBI (CID_ID(0x81a5U) | CID_FLAG)
++#define CID_VSLSYNCTAG (CID_ID(0x81a6U) | CID_FLAG)
++#define CID_VSLVTRANSMBS (CID_ID(0x81a7U) | CID_FLAG)
++#define CID_VSLVTRANSNM (CID_ID(0x81a8U) | CID_FLAG)
++#define CID_VSLVTRANSQTNR (CID_ID(0x81a9U) | CID_FLAG)
++#define CID_VSLVTRANSSWTNR (CID_ID(0x81aaU) | CID_FLAG)
++#define CID_VTRANSSWTNR (CID_ID(0x81abU) | CID_FLAG)
++#define CID_LL_DMA (CID_ID(0x81acU) | CID_FLAG)
++#define CID_BSL_PNX8550 (CID_ID(0x81adU) | CID_FLAG)
++#define CID_BSL_PNX1500 (CID_ID(0x81aeU) | CID_FLAG)
++#define CID_BSL_NULL (CID_ID(0x81afU) | CID_FLAG)
++#define CID_BSL_PNX2015 (CID_ID(0x81b0U) | CID_FLAG)
++#define CID_HW_SCALER7136 (CID_ID(0x81b1U) | CID_FLAG)
++#define CID_SPI_IP3409 (CID_ID(0x81b2U) | CID_FLAG)
++#define CID_SPI_3409 (CID_ID(0x81b3U) | CID_FLAG)
++#define CID_SPISD_3409 (CID_ID(0x81b4U) | CID_FLAG)
++#define CID_CONNMGRMP4RTPPLAYER (CID_ID(0x81b5U) | CID_FLAG)
++#define CID_DL_NANDFLASH2 (CID_ID(0x81b6U) | CID_FLAG)
++#define CID_HW_HOSTIF (CID_ID(0x81b7U) | CID_FLAG)
++#define CID_LL_HOSTIF (CID_ID(0x81b8U) | CID_FLAG)
++#define CID_LL_MJPEG (CID_ID(0x81b9U) | CID_FLAG)
++#define CID_HW_SENSORIF (CID_ID(0x81baU) | CID_FLAG)
++#define CID_LL_SENSORIF (CID_ID(0x81bbU) | CID_FLAG)
++#define CID_HW_ECSP (CID_ID(0x81bcU) | CID_FLAG)
++#define CID_LL_ECSP (CID_ID(0x81bdU) | CID_FLAG)
++#define CID_HW_DOWNSCALER (CID_ID(0x81beU) | CID_FLAG)
++#define CID_LL_DOWNSCALER (CID_ID(0x81bfU) | CID_FLAG)
++#define CID_HW_UPSCALER (CID_ID(0x81c0U) | CID_FLAG)
++#define CID_LL_UPSCALER (CID_ID(0x81c1U) | CID_FLAG)
++#define CID_HW_JITTEREX (CID_ID(0x81c2U) | CID_FLAG)
++#define CID_LL_JITTEREX (CID_ID(0x81c3U) | CID_FLAG)
++#define CID_HW_NOISERED (CID_ID(0x81c4U) | CID_FLAG)
++#define CID_LL_NOISERED (CID_ID(0x81c5U) | CID_FLAG)
++#define CID_HW_JPEGENCODER (CID_ID(0x81c6U) | CID_FLAG)
++#define CID_LL_JPEGENCODER (CID_ID(0x81c7U) | CID_FLAG)
++#define CID_HW_FLASHLIGHT (CID_ID(0x81c8U) | CID_FLAG)
++#define CID_LL_FLASHLIGHT (CID_ID(0x81c9U) | CID_FLAG)
++#define CID_HW_TVCONVERTER (CID_ID(0x81caU) | CID_FLAG)
++#define CID_LL_TVCONVERTER (CID_ID(0x81cbU) | CID_FLAG)
++#define CID_HW_DVDOMATRIX (CID_ID(0x81ccU) | CID_FLAG)
++#define CID_LL_DVDOMATRIX (CID_ID(0x81cdU) | CID_FLAG)
++#define CID_HW_CLCD (CID_ID(0x81ceU) | CID_FLAG)
++#define CID_LL_CLCD (CID_ID(0x81cfU) | CID_FLAG)
++#define CID_HW_VDE (CID_ID(0x81d0U) | CID_FLAG)
++#define CID_LL_VDE (CID_ID(0x81d1U) | CID_FLAG)
++#define CID_HW_MCSPI (CID_ID(0x81d2U) | CID_FLAG)
++#define CID_LL_MCSPI (CID_ID(0x81d3U) | CID_FLAG)
++#define CID_HW_PWM (CID_ID(0x81d4U) | CID_FLAG)
++#define CID_LL_PWM (CID_ID(0x81d5U) | CID_FLAG)
++#define CID_OSAL_NXM (CID_ID(0x81d6U) | CID_FLAG)
++#define CID_MEMPROF (CID_ID(0x81d7U) | CID_FLAG)
++#define CID_ALCONSTRETCH (CID_ID(0x81d8U) | CID_FLAG)
++#define CID_AUTOFOCUS (CID_ID(0x81d9U) | CID_FLAG)
++#define CID_LL_DVDO2DTL (CID_ID(0x81daU) | CID_FLAG)
++#define CID_HW_DVDO2DTL (CID_ID(0x81dbU) | CID_FLAG)
++#define CID_LL_DTL2DVDO (CID_ID(0x81dcU) | CID_FLAG)
++#define CID_HW_DTL2DVDO (CID_ID(0x81ddU) | CID_FLAG)
++#define CID_LL_COLORMATRIX (CID_ID(0x81deU) | CID_FLAG)
++#define CID_HW_COLORMATRIX (CID_ID(0x81dfU) | CID_FLAG)
++#define CID_UHSPDIFOUT_ASYSATV (CID_ID(0x81e0U) | CID_FLAG)
++#define CID_DL_NANDFLASH1 (CID_ID(0x81e1U) | CID_FLAG)
++#define CID_NANDBOOTFFS (CID_ID(0x81e2U) | CID_FLAG)
++#define CID_CONNMGR_APROCTV (CID_ID(0x81e3U) | CID_FLAG)
++#define CID_CONNMGRSTILLPLAYER (CID_ID(0x81e4U) | CID_FLAG)
++#define CID_CONNMGRAUDIOPLAYER (CID_ID(0x81e5U) | CID_FLAG)
++#define CID_DCDIP9028 (CID_ID(0x81e6U) | CID_FLAG)
++#define CID_CURLSRC_AUDIO (CID_ID(0x81e7U) | CID_FLAG)
++#define CID_CONNMGRAVIMP4PLAYER (CID_ID(0x81e8U) | CID_FLAG)
++#define CID_AUDIOVIDEOSYNC (CID_ID(0x81e9U) | CID_FLAG)
++#define CID_PACKETLIST (CID_ID(0x81eaU) | CID_FLAG)
++#define CID_ASYNCSINK (CID_ID(0x81ebU) | CID_FLAG)
++#define CID_VSYNCSINK (CID_ID(0x81ecU) | CID_FLAG)
++#define CID_XSYNCSINK (CID_ID(0x81edU) | CID_FLAG)
++#define CID_PCIEXP (CID_ID(0x81eeU) | CID_FLAG)
++#define CID_SOD_KERNEL (CID_ID(0x81efU) | CID_FLAG)
++#define CID_SOD_EMULATE (CID_ID(0x81f0U) | CID_FLAG)
++#define CID_SOD_MGR (CID_ID(0x81f1U) | CID_FLAG)
++#define CID_NANDPARTTABLE (CID_ID(0x81f2U) | CID_FLAG)
++#define CID_HW_AUDIO7136 (CID_ID(0x81f3U) | CID_FLAG)
++#define CID_SPI3409 (CID_ID(0x81f4U) | CID_FLAG)
++#define CID_DCSS_MATH (CID_ID(0x81f5U) | CID_FLAG)
++#define CID_DCSS_LIT_CSD (CID_ID(0x81f6U) | CID_FLAG)
++#define CID_DCSS_LIT_M (CID_ID(0x81f7U) | CID_FLAG)
++#define CID_ADT (CID_ID(0x81f8U) | CID_FLAG)
++#define CID_ACS (CID_ID(0x81f9U) | CID_FLAG)
++#define CID_ACB (CID_ID(0x81faU) | CID_FLAG)
++#define CID_ACL (CID_ID(0x81fbU) | CID_FLAG)
++#define CID_AVEPP (CID_ID(0x81fcU) | CID_FLAG)
++#define CID_UDSSIC (CID_ID(0x81fdU) | CID_FLAG)
++#define CID_PROXYI2C (CID_ID(0x81feU) | CID_FLAG)
++#define CID_PL081DMA (CID_ID(0x81feU) | CID_FLAG)
++#define CID_DD_CPIPE (CID_ID(0x81ffU) | CID_FLAG)
++#define CID_DD_MBVP (CID_ID(0x8200U) | CID_FLAG)
++#define CID_CARENDAOUT (CID_ID(0x8201U) | CID_FLAG)
++#define CID_CADIGAIN (CID_ID(0x8202U) | CID_FLAG)
++#define CID_CONNMGR_TV506E (CID_ID(0x8203U) | CID_FLAG)
++#define CID_ASYNCHANDLER (CID_ID(0x8204U) | CID_FLAG)
++#define CID_COMP_M4VENCPSC (CID_ID(0x8205U) | CID_FLAG)
++#define CID_CONNMGRNETSCHEMECONFIG (CID_ID(0x8206U) | CID_FLAG)
++#define CID_CARACASSPIAHB (CID_ID(0x8207U) | CID_FLAG)
++#define CID_COMP_ADECLPCM (CID_ID(0x8208U) | CID_FLAG)
++#define CID_CDIGADEC_MULTISTD (CID_ID(0x8209U) | CID_FLAG)
++#define CID_ADB (CID_ID(0x820aU) | CID_FLAG)
++#define CID_ADR (CID_ID(0x820bU) | CID_FLAG)
++#define CID_AGN (CID_ID(0x820cU) | CID_FLAG)
++#define CID_ANT (CID_ID(0x820dU) | CID_FLAG)
++#define CID_APP (CID_ID(0x820eU) | CID_FLAG)
++#define CID_ASC (CID_ID(0x820fU) | CID_FLAG)
++#define CID_ASM (CID_ID(0x8210U) | CID_FLAG)
++#define CID_ASS (CID_ID(0x8211U) | CID_FLAG)
++#define CID_ATP (CID_ID(0x8212U) | CID_FLAG)
++#define CID_VDEC_MJPEG (CID_ID(0x8213U) | CID_FLAG)
++#define CID_MOV_READ (CID_ID(0x8214U) | CID_FLAG)
++#define CID_EWIFI (CID_ID(0x8215U) | CID_FLAG)
++#define CID_SCR (CID_ID(0x8216U) | CID_FLAG)
++#define CID_AEPP (CID_ID(0x8217U) | CID_FLAG)
++#define CID_VEPP (CID_ID(0x8218U) | CID_FLAG)
++#define CID_MP3ENC (CID_ID(0x8219U) | CID_FLAG)
++#define CID_TDFLOADER (CID_ID(0x821aU) | CID_FLAG)
++#define CID_VIOSYNC (CID_ID(0x821bU) | CID_FLAG)
++#define CID_STBDP (CID_ID(0x821cU) | CID_FLAG)
++#define CID_STBEVENT (CID_ID(0x821dU) | CID_FLAG)
++#define CID_STBFB (CID_ID(0x821eU) | CID_FLAG)
++#define CID_STBDEMUX (CID_ID(0x821fU) | CID_FLAG)
++#define CID_STBFILE (CID_ID(0x8220U) | CID_FLAG)
++#define CID_STBGPIO (CID_ID(0x8221U) | CID_FLAG)
++#define CID_STBI2C (CID_ID(0x8222U) | CID_FLAG)
++#define CID_STBMMIOBUS (CID_ID(0x8223U) | CID_FLAG)
++#define CID_STBPROC (CID_ID(0x8224U) | CID_FLAG)
++#define CID_STBROOT (CID_ID(0x8225U) | CID_FLAG)
++#define CID_STBRPC (CID_ID(0x8226U) | CID_FLAG)
++#define CID_STBRTC (CID_ID(0x8227U) | CID_FLAG)
++#define CID_STBTMLOAD (CID_ID(0x8228U) | CID_FLAG)
++#define CID_STBSTREAMINGSYSTEM (CID_ID(0x8229U) | CID_FLAG)
++#define CID_STBVIDEOSCALER (CID_ID(0x822aU) | CID_FLAG)
++#define CID_STBANALOGBACKEND (CID_ID(0x822bU) | CID_FLAG)
++#define CID_STBVIDEORENDERER (CID_ID(0x822cU) | CID_FLAG)
++#define CID_DRV_MMU (CID_ID(0x822dU) | CID_FLAG)
++#define CID_COMP_AINJECTOR (CID_ID(0x822eU) | CID_FLAG)
++#define CID_VDEC_ANA (CID_ID(0x822fU) | CID_FLAG)
++#define CID_STBAC3AUD (CID_ID(0x8230U) | CID_FLAG)
++#define CID_STBAUDIO (CID_ID(0x8231U) | CID_FLAG)
++#define CID_PHMODARM11WRAPPER (CID_ID(0x8232U) | CID_FLAG)
++#define CID_GPIO_IP4004 (CID_ID(0x8233U) | CID_FLAG)
++#define CID_TMCADIGSPDIFIN (CID_ID(0x8234U) | CID_FLAG)
++#define CID_TMCARENDSPDIFOUT (CID_ID(0x8235U) | CID_FLAG)
++#define CID_TMCPLFINSTAIN (CID_ID(0x8236U) | CID_FLAG)
++#define CID_TMCPLFINSTAOUT (CID_ID(0x8237U) | CID_FLAG)
++#define CID_TMCSPDIFIN (CID_ID(0x8238U) | CID_FLAG)
++#define CID_TMCSPDIFOUT (CID_ID(0x8239U) | CID_FLAG)
++#define CID_BSL_HDMIRX (CID_ID(0x823aU) | CID_FLAG)
++#define CID_AACPENC (CID_ID(0x823bU) | CID_FLAG)
++#define CID_DL_HDMIRX (CID_ID(0x823cU) | CID_FLAG)
++#define CID_APP_HDMIRX (CID_ID(0x823dU) | CID_FLAG)
++#define CID_INFRA_HDMI (CID_ID(0x823eU) | CID_FLAG)
++#define CID_DL_HDMICEC (CID_ID(0x823fU) | CID_FLAG)
++#define CID_BSL_HDMITX (CID_ID(0x8240U) | CID_FLAG)
++#define CID_DL_HDMITX (CID_ID(0x8241U) | CID_FLAG)
++#define CID_APP_HDMITX (CID_ID(0x8242U) | CID_FLAG)
++
++/*define CID_UART (CID_ID(0x80a5U) | CID_FLAG) already defined*/
++#define CID_CHIP (CID_ID(0x815bU) | CID_FLAG)
++
++#define CID_RESERVED (CID_ID(0xff80U) | CID_FLAG)
++/* ************************************************************************** */
++/* Component Id's reserved for external organizations */
++/* */
++/* 0xff80 thru 0xffbf */
++/* Range of component ID's is reserved for the use of parties outside of */
++/* Philips that wish to use component ID's privately. */
++/* If a component is going to be exchanged in the 'PS Ecosystem', then a */
++/* public component ID should be registered with MoReUse. */
++/* */
++/* Range to be used by CE Television Systems */
++/* 0xffc0 thru 0xffff */
++/* */
++/* ************************************************************************** */
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Component ID types are defined as unsigned 32 bit integers (UInt32) */
++/* Interface ID types are defined as unsigned 32 bit integers (UInt32) */
++/* */
++/* -------------------------------------------------------------------------- */
++
++/* -------------------------------------------------------------------------- */
++/* */
++/* Obsolete Component ID values */
++/* */
++/* -------------------------------------------------------------------------- */
++
++/* -------------------------------------------------------------------------- */
++/* Component Class definitions (bits 31:28, 4 bits) */
++/* NOTE: A class of 0x0 must not be defined to ensure that the overall 32 bit */
++/* component ID/status combination is always non-0 (no TM_OK conflict). */
++/* -------------------------------------------------------------------------- */
++#define CID_CLASS_BITSHIFT 28
++#define CID_CLASS_BITMASK (0xFU << CID_CLASS_BITSHIFT)
++#define CID_GET_CLASS(compId) ((compId & CID_CLASS_BITMASK) >> CID_CLASS_BITSHIFT)
++
++#define CID_CLASS_NONE (0x1U << CID_CLASS_BITSHIFT)
++#define CID_CLASS_VIDEO (0x2U << CID_CLASS_BITSHIFT)
++#define CID_CLASS_AUDIO (0x3U << CID_CLASS_BITSHIFT)
++#define CID_CLASS_GRAPHICS (0x4U << CID_CLASS_BITSHIFT)
++#define CID_CLASS_BUS (0x5U << CID_CLASS_BITSHIFT)
++#define CID_CLASS_INFRASTR (0x6U << CID_CLASS_BITSHIFT)
++
++#define CID_CLASS_CUSTOMER (0xFU << CID_CLASS_BITSHIFT)
++
++/* -------------------------------------------------------------------------- */
++/* Component Type definitions (bits 27:24, 4 bits) */
++/* -------------------------------------------------------------------------- */
++#define CID_TYPE_BITSHIFT 24
++#define CID_TYPE_BITMASK (0xFU << CID_TYPE_BITSHIFT)
++#define CID_GET_TYPE(compId) ((compId & CID_TYPE_BITMASK) >> CID_TYPE_BITSHIFT)
++
++#define CID_TYPE_NONE (0x0U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_SOURCE (0x1U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_SINK (0x2U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_ENCODER (0x3U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_DECODER (0x4U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_MUX (0x5U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_DEMUX (0x6U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_DIGITIZER (0x7U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_RENDERER (0x8U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_FILTER (0x9U << CID_TYPE_BITSHIFT)
++#define CID_TYPE_CONTROL (0xAU << CID_TYPE_BITSHIFT)
++#define CID_TYPE_DATABASE (0xBU << CID_TYPE_BITSHIFT)
++#define CID_TYPE_SUBSYSTEM (0xCU << CID_TYPE_BITSHIFT)
++#define CID_TYPE_CUSTOMER (0xFU << CID_TYPE_BITSHIFT)
++
++/* -------------------------------------------------------------------------- */
++/* Component Tag definitions (bits 23:16, 8 bits) */
++/* NOTE: Component tags are defined in groups, dependent on the class and */
++/* type. */
++/* -------------------------------------------------------------------------- */
++#define CID_TAG_BITSHIFT 16
++#define CID_TAG_BITMASK (0xFFU << CID_TAG_BITSHIFT)
++
++#define CID_TAG_NONE (0x00U << CID_TAG_BITSHIFT)
++
++#define CID_TAG_CUSTOMER (0xE0U << CID_TAG_BITSHIFT)
++
++#define TAG(number) ((number) << CID_TAG_BITSHIFT)
++
++/* -------------------------------------------------------------------------- */
++/* General Component Layer definitions (bits 15:12, 4 bits) */
++/* -------------------------------------------------------------------------- */
++#define CID_LAYER_BITSHIFT 12
++#define CID_LAYER_BITMASK (0xF << CID_LAYER_BITSHIFT)
++#define CID_GET_LAYER(compId) ((compId & CID_LAYER_BITMASK) >> CID_LAYER_BITSHIFT)
++
++#define CID_LAYER_NONE (0x0U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_BTM (0x1U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_HWAPI (0x2U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_BSL (0x3U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_DEVLIB (0x4U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_TMAL (0x5U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_TMOL (0x6U << CID_LAYER_BITSHIFT)
++#define CID_LAYER_TMNL (0xEU << CID_LAYER_BITSHIFT)
++
++/* -------------------------------------------------------------------------- */
++/* "new" i.e. after 2002-01-31 layer definitions */
++/* "New" Component Layers depend on the component type and class */
++/* So we can have an identical layer value for each type/class combination */
++/* In order not to break existing code that assumes that layers are unique, */
++/* we start new layers at 0x7 */
++/* -------------------------------------------------------------------------- */
++
++/*------------------ CTYP_BUS_NOTYPE dependent layer definitions -------------*/
++#define CID_LAYER_UDS (0x7U << CID_LAYER_BITSHIFT) /* USB Device Stack */
++#define CID_LAYER_UHS (0x8U << CID_LAYER_BITSHIFT) /* USB Host stack */
++#define CID_LAYER_UOTG (0x9U << CID_LAYER_BITSHIFT) /* USB OTG stack */
++
++#define CID_LAYER_CUSTOMER (0xFU << CID_LAYER_BITSHIFT) /* Customer Defined */
++
++/* -------------------------------------------------------------------------- */
++/* Component Identifier definitions (bits 31:12, 20 bits) */
++/* NOTE: These DVP platform component identifiers are designed to be unique */
++/* within the system. The component identifier encompasses the class */
++/* (CID_CLASS_XXX), type (CID_TYPE_XXX), tag, and layer (CID_LAYER_XXX) */
++/* fields to form the unique component identifier. This allows any */
++/* error/progress status value to be identified as to its original */
++/* source, whether or not the source component s header file is present.*/
++/* The standard error/progress status definitions should be used */
++/* whenever possible to ease status interpretation. No layer */
++/* information is defined at this point; it should be ORed into the API */
++/* status values defined in the APIs header file. */
++/* -------------------------------------------------------------------------- */
++#if (CID_LAYER_NONE != 0)
++#error ERROR: DVP component identifiers require the layer type 'NONE' = 0 !
++#endif
++
++/* -------------------------------------------------------------------------- */
++/* Classless Types/Components (don t fit into other class categories) */
++/* -------------------------------------------------------------------------- */
++#define CTYP_NOCLASS_NOTYPE (CID_CLASS_NONE | CID_TYPE_NONE)
++#define CTYP_NOCLASS_SOURCE (CID_CLASS_NONE | CID_TYPE_SOURCE)
++#define CTYP_NOCLASS_SINK (CID_CLASS_NONE | CID_TYPE_SINK)
++#define CTYP_NOCLASS_MUX (CID_CLASS_NONE | CID_TYPE_MUX)
++#define CTYP_NOCLASS_DEMUX (CID_CLASS_NONE | CID_TYPE_DEMUX)
++#define CTYP_NOCLASS_FILTER (CID_CLASS_NONE | CID_TYPE_FILTER)
++#define CTYP_NOCLASS_CONTROL (CID_CLASS_NONE | CID_TYPE_CONTROL)
++#define CTYP_NOCLASS_DATABASE (CID_CLASS_NONE | CID_TYPE_DATABASE)
++#define CTYP_NOCLASS_SUBSYS (CID_CLASS_NONE | CID_TYPE_SUBSYSTEM)
++
++#define CID_COMP_CLOCK (TAG(0x01U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_DMA (TAG(0x02U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_PIC (TAG(0x03U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_NORFLASH (TAG(0x04U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_NANDFLASH (TAG(0x05U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_GPIO (TAG(0x06U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_SMARTCARD (TAG(0x07U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_UDMA (TAG(0x08U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_DSP (TAG(0x09U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_TIMER (TAG(0x0AU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_TSDMA (TAG(0x0BU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_MMIARB (TAG(0x0CU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_EEPROM (TAG(0x0DU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_PARPORT (TAG(0x0EU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_VSS (TAG(0x0FU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_TSIO (TAG(0x10U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_DBG (TAG(0x11U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_TTE (TAG(0x12U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_AVPROP (TAG(0x13U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_SERIAL_RAM (TAG(0x14U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_SMARTMEDIA (TAG(0x15U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_COMPACT_FLASH (TAG(0x16U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_CI (TAG(0x17U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_INT_ALARM (TAG(0x18U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_TASK_ALARM (TAG(0x19U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_XDMA (TAG(0x1AU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_ICC (TAG(0x1BU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_CONNMGR (TAG(0x1CU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_CONNMGRVSYSTV (TAG(0x1DU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_VBISLICERVSYSTV (TAG(0x1EU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_VMIXVSYSTV (TAG(0x1FU) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_NTF (TAG(0x20U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_NTY CID_COMP_NTF /* legacy */
++#define CID_COMP_FATERR (TAG(0x21U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_DVBTDEMOD (TAG(0x22U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_HYBRIDTUNER (TAG(0x23U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_VLD (TAG(0x24U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_GIC (TAG(0x25U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_WEB (TAG(0x26U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_ANAEPGDB (TAG(0x27U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_HWSEM (TAG(0x28U) | CTYP_NOCLASS_NOTYPE)
++#define CID_COMP_MMON (TAG(0x29U) | CTYP_NOCLASS_NOTYPE)
++
++#define CID_COMP_FREAD (TAG(0x01U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_CDRREAD (TAG(0x02U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_VSB (TAG(0x03U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_ANALOGTVTUNER (TAG(0x04U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_TPINMPEG2 (TAG(0x05U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_DREAD (TAG(0x06U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_TREAD (TAG(0x07U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_RTC (TAG(0x08U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_TOUCHC (TAG(0x09U) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_KEYPAD (TAG(0x0AU) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_ADC (TAG(0x0BU) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_READLIST (TAG(0x0CU) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_FROMDISK (TAG(0x0DU) | CTYP_NOCLASS_SOURCE)
++#define CID_COMP_SOURCE (TAG(0x0EU) | CTYP_NOCLASS_SOURCE)
++
++#define CID_COMP_FWRITE (TAG(0x01U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_CDWRITE (TAG(0x02U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_CHARLCD (TAG(0x03U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_PWM (TAG(0x04U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_DAC (TAG(0x05U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_TSDMAINJECTOR (TAG(0x06U) | CTYP_NOCLASS_SINK)
++#define CID_COMP_TODISK (TAG(0x07U) | CTYP_NOCLASS_SINK)
++
++#define CID_COMP_MUXMPEGPS (TAG(0x01U) | CTYP_NOCLASS_MUX)
++#define CID_COMP_MUXMPEG (TAG(0x02U) | CTYP_NOCLASS_MUX)
++
++#define CID_COMP_DEMUXMPEGTS (TAG(0x01U) | CTYP_NOCLASS_DEMUX)
++#define CID_COMP_DEMUXMPEGPS (TAG(0x02U) | CTYP_NOCLASS_DEMUX)
++#define CID_COMP_DEMUXDV (TAG(0x03U) | CTYP_NOCLASS_DEMUX)
++
++#define CID_COMP_COPYIO (TAG(0x01U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_COPYINPLACE (TAG(0x02U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_UART (TAG(0x03U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_SSI (TAG(0x04U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_MODEMV34 (TAG(0x05U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_MODEMV42 (TAG(0x06U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_HTMLPARSER (TAG(0x07U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_VMSP (TAG(0x08U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_X (TAG(0x09U) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_TXTSUBTDECEBU (TAG(0x0AU) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_CPI (TAG(0x0BU) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_TRICK (TAG(0x0CU) | CTYP_NOCLASS_FILTER)
++#define CID_COMP_FWRITEFREAD (TAG(0x0DU) | CTYP_NOCLASS_FILTER)
++
++#define CID_COMP_REMCTL5 (TAG(0x01U) | CTYP_NOCLASS_CONTROL)
++#define CID_COMP_INFRARED (TAG(0x02U) | CTYP_NOCLASS_CONTROL)
++
++#define CID_COMP_PSIP (TAG(0x01U) | CTYP_NOCLASS_DATABASE)
++#define CID_COMP_IDE (TAG(0x02U) | CTYP_NOCLASS_DATABASE)
++#define CID_COMP_DISKSCHED (TAG(0x03U) | CTYP_NOCLASS_DATABASE)
++#define CID_COMP_AVFS (TAG(0x04U) | CTYP_NOCLASS_DATABASE)
++#define CID_COMP_MDB (TAG(0x05U) | CTYP_NOCLASS_DATABASE)
++#define CID_COMP_ATAPI_CMDS (TAG(0x06U) | CTYP_NOCLASS_DATABASE)
++
++#define CID_COMP_IRDMMPEG (TAG(0x01U) | CTYP_NOCLASS_SUBSYS)
++#define CID_COMP_STORSYS (TAG(0x02U) | CTYP_NOCLASS_SUBSYS)
++#define CID_COMP_PMU (TAG(0x03U) | CTYP_NOCLASS_SUBSYS)
++
++/* -------------------------------------------------------------------------- */
++/* Video Class Types/Components (video types handle video/graphics data) */
++/* -------------------------------------------------------------------------- */
++#define CTYP_VIDEO_SINK (CID_CLASS_VIDEO | CID_TYPE_SINK)
++#define CTYP_VIDEO_SOURCE (CID_CLASS_VIDEO | CID_TYPE_SOURCE)
++#define CTYP_VIDEO_ENCODER (CID_CLASS_VIDEO | CID_TYPE_ENCODER)
++#define CTYP_VIDEO_DECODER (CID_CLASS_VIDEO | CID_TYPE_DECODER)
++#define CTYP_VIDEO_DIGITIZER (CID_CLASS_VIDEO | CID_TYPE_DIGITIZER)
++#define CTYP_VIDEO_RENDERER (CID_CLASS_VIDEO | CID_TYPE_RENDERER)
++#define CTYP_VIDEO_FILTER (CID_CLASS_VIDEO | CID_TYPE_FILTER)
++#define CTYP_VIDEO_SUBSYS (CID_CLASS_VIDEO | CID_TYPE_SUBSYSTEM)
++
++#define CID_COMP_LCD (TAG(0x01U) | CTYP_VIDEO_SINK)
++
++#define CID_COMP_VCAPVI (TAG(0x01U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_VIP (TAG(0x02U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_VI (TAG(0x03U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_VSLICER (TAG(0x04U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_FBREAD (TAG(0x05U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_QVI (TAG(0x06U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_CAMERA (TAG(0x07U) | CTYP_VIDEO_SOURCE)
++#define CID_COMP_CAM_SENSOR (TAG(0x08U) | CTYP_VIDEO_SOURCE)
++
++#define CID_COMP_VENCM1 (TAG(0x01U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_VENCM2 (TAG(0x02U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_VENCMJ (TAG(0x03U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_VENCH263 (TAG(0x04U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_VENCH261 (TAG(0x05U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_M4VENC (TAG(0x06U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_M4VENCME (TAG(0x07U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_M4VENCTC (TAG(0x08U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_M4VENCBSG (TAG(0x09U) | CTYP_VIDEO_ENCODER)
++#define CID_COMP_M4VENCJPEG (TAG(0x0AU) | CTYP_VIDEO_ENCODER)
++
++#define CID_COMP_VDECM1 (TAG(0x01U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECM2 (TAG(0x02U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECMPEG (TAG(0x03U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECMJ (TAG(0x04U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECSUBPICSVCD (TAG(0x05U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECH263 (TAG(0x06U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECH261 (TAG(0x07U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDEC (TAG(0x08U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECSUBPICDVD (TAG(0x09U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECSUBPICBMPDVD (TAG(0x0AU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECSUBPICRENDDVD (TAG(0x0BU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_M4PP (TAG(0x0CU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_M4MC (TAG(0x0DU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_M4CSC (TAG(0x0EU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECTXT (TAG(0x0FU) | CTYP_VIDEO_DECODER)
++#define CID_COMP_VDECDV (TAG(0x10U) | CTYP_VIDEO_DECODER)
++#define CID_COMP_BACKANIM (TAG(0x11U) | CTYP_VIDEO_DECODER)
++
++#define CID_COMP_VDIG (TAG(0x01U) | CTYP_VIDEO_DIGITIZER)
++#define CID_COMP_VDIGVIRAW (TAG(0x02U) | CTYP_VIDEO_DIGITIZER)
++#define CID_COMP_VDIG_EXT (TAG(0x03U) | CTYP_VIDEO_DIGITIZER)
++#define CID_COMP_VDIG_VBI (TAG(0x04U) | CTYP_VIDEO_DIGITIZER)
++#define CID_COMP_VDIG_EXT_VBI (TAG(0x05U) | CTYP_VIDEO_DIGITIZER)
++
++#define CID_COMP_VREND (TAG(0x01U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_HDVO (TAG(0x02U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VRENDGFXVO (TAG(0x03U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_AICP (TAG(0x04U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VRENDVORAW (TAG(0x05U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VO (TAG(0x06U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VRENDVOICP (TAG(0x07U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VMIX (TAG(0x08U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_QVCP (TAG(0x09U) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VREND_EXT (TAG(0x0AU) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_VENCANA (TAG(0x0BU) | CTYP_VIDEO_RENDERER)
++#define CID_COMP_QVO (TAG(0x0CU) | CTYP_VIDEO_RENDERER)
++
++#define CID_COMP_MBS (TAG(0x01U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_VTRANS (TAG(0x02U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_QNM (TAG(0x03U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_ICP (TAG(0x04U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_VTRANSNM (TAG(0x05U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_QFD (TAG(0x06U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_VTRANSDVD (TAG(0x07U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_VTRANSCRYSTAL (TAG(0x08U) | CTYP_VIDEO_FILTER)
++#define CID_COMP_VTRANSUD (TAG(0x09U) | CTYP_VIDEO_FILTER)
++/*#define CID_COMP_QTNR (TAG(0x0AU) | CTYP_VIDEO_FILTER) Removed v17: Replaced with CID_VTRANS_QTNR */
++
++#define CID_COMP_VSYSMT3 (TAG(0x01U) | CTYP_VIDEO_SUBSYS)
++#define CID_COMP_VSYSSTB (TAG(0x01U) | CTYP_VIDEO_SUBSYS)
++#define CID_COMP_DVDVIDSYS (TAG(0x02U) | CTYP_VIDEO_SUBSYS)
++#define CID_COMP_VDECUD (TAG(0x03U) | CTYP_VIDEO_SUBSYS)
++#define CID_COMP_VIDSYS (TAG(0x04U) | CTYP_VIDEO_SUBSYS)
++#define CID_COMP_VSYSTV (TAG(0x05U) | CTYP_VIDEO_SUBSYS)
++
++/* -------------------------------------------------------------------------- */
++/* Audio Class Types/Components (audio types primarily handle audio data) */
++/* -------------------------------------------------------------------------- */
++#define CTYP_AUDIO_NOTYPE (CID_CLASS_AUDIO | CID_TYPE_NONE)
++#define CTYP_AUDIO_SINK (CID_CLASS_AUDIO | CID_TYPE_SINK)
++#define CTYP_AUDIO_SOURCE (CID_CLASS_AUDIO | CID_TYPE_SOURCE)
++#define CTYP_AUDIO_ENCODER (CID_CLASS_AUDIO | CID_TYPE_ENCODER)
++#define CTYP_AUDIO_DECODER (CID_CLASS_AUDIO | CID_TYPE_DECODER)
++#define CTYP_AUDIO_DIGITIZER (CID_CLASS_AUDIO | CID_TYPE_DIGITIZER)
++#define CTYP_AUDIO_RENDERER (CID_CLASS_AUDIO | CID_TYPE_RENDERER)
++#define CTYP_AUDIO_FILTER (CID_CLASS_AUDIO | CID_TYPE_FILTER)
++#define CTYP_AUDIO_SUBSYS (CID_CLASS_AUDIO | CID_TYPE_SUBSYSTEM)
++
++#define CID_COMP_CODEC (TAG(0x01U) | CTYP_AUDIO_NOTYPE)
++
++#define CID_COMP_SDAC (TAG(0x01U) | CTYP_AUDIO_SINK)
++
++#define CID_COMP_ADIGAI (TAG(0x01U) | CTYP_AUDIO_DIGITIZER)
++#define CID_COMP_ADIGSPDIF (TAG(0x02U) | CTYP_AUDIO_DIGITIZER)
++
++#define CID_COMP_ARENDAO (TAG(0x01U) | CTYP_AUDIO_RENDERER)
++#define CID_COMP_ARENDSPDIF (TAG(0x02U) | CTYP_AUDIO_RENDERER)
++
++#define CID_COMP_NOISESEQ (TAG(0x03U) | CTYP_AUDIO_SOURCE)
++
++#define CID_COMP_AENCAC3 (TAG(0x01U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCMPEG1 (TAG(0x02U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCAAC (TAG(0x03U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCG723 (TAG(0x04U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCG728 (TAG(0x05U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCWMA (TAG(0x06U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AVENCMPEG (TAG(0x07U) | CTYP_AUDIO_ENCODER)
++#define CID_COMP_AENCMP3 (TAG(0x08U) | CTYP_AUDIO_ENCODER)
++
++#define CID_COMP_ADECPROLOGIC (TAG(0x01U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECAC3 (TAG(0x02U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECMPEG1 (TAG(0x03U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECMP3 (TAG(0x04U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECAAC (TAG(0x05U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECG723 (TAG(0x06U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECG728 (TAG(0x07U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECWMA (TAG(0x08U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECTHRU (TAG(0x09U) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADEC (TAG(0x0AU) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECPCM (TAG(0x0BU) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECDV (TAG(0x0CU) | CTYP_AUDIO_DECODER)
++#define CID_COMP_ADECDTS (TAG(0x0DU) | CTYP_AUDIO_DECODER)
++
++#define CID_COMP_ASPLIB (TAG(0x01U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_IIR (TAG(0x02U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPEQ2 (TAG(0x03U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPEQ5 (TAG(0x04U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPBASSREDIR (TAG(0x05U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPLAT2 (TAG(0x06U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPPLUGIN (TAG(0x07U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_AMIXDTV (TAG(0x08U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_AMIXSIMPLE (TAG(0x09U) | CTYP_AUDIO_FILTER)
++#define CID_COMP_AMIXSTB (TAG(0x0AU) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ASPEQ (TAG(0x0BU) | CTYP_AUDIO_FILTER)
++#define CID_COMP_ATESTSIG (TAG(0x0CU) | CTYP_AUDIO_FILTER)
++#define CID_COMP_APROC (TAG(0x0DU) | CTYP_AUDIO_FILTER)
++
++#define CID_COMP_AUDSUBSYS (TAG(0x01U) | CTYP_AUDIO_SUBSYS)
++#define CID_COMP_AUDSYSSTB (TAG(0x02U) | CTYP_AUDIO_SUBSYS)
++#define CID_COMP_AUDSYSDVD (TAG(0x03U) | CTYP_AUDIO_SUBSYS)
++#define CID_COMP_MMC (TAG(0x04U) | CTYP_AUDIO_SUBSYS)
++#define CID_COMP_COMP_MMC CID_COMP_MMC /* legacy */
++#define CID_COMP_ASYSATV (TAG(0x05U) | CTYP_AUDIO_SUBSYS)
++
++/* -------------------------------------------------------------------------- */
++/* Graphics Class Types/Components */
++/* -------------------------------------------------------------------------- */
++#define CTYP_GRAPHICS_RENDERER (CID_CLASS_GRAPHICS | CID_TYPE_SINK)
++
++#define CID_COMP_WM (TAG(0x01U) | CTYP_GRAPHICS_RENDERER)
++#define CID_COMP_WIDGET (TAG(0x02U) | CTYP_GRAPHICS_RENDERER)
++#define CID_COMP_OM (TAG(0x03U) | CTYP_GRAPHICS_RENDERER)
++#define CID_COMP_HTMLRENDER (TAG(0x04U) | CTYP_GRAPHICS_RENDERER)
++#define CID_COMP_VRENDEIA708 (TAG(0x05U) | CTYP_GRAPHICS_RENDERER)
++#define CID_COMP_VRENDEIA608 (TAG(0x06U) | CTYP_GRAPHICS_RENDERER)
++
++#define CTYP_GRAPHICS_DRAW (CID_CLASS_GRAPHICS | CID_TYPE_NONE)
++
++#define CID_COMP_DRAW (TAG(0x10U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_UT (TAG(0x11U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_DE (TAG(0x12U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_REF (TAG(0x13U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_TMH (TAG(0x14U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_TMT (TAG(0x15U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_DRAW_TMTH (TAG(0x16U) | CTYP_GRAPHICS_DRAW)
++
++#define CID_COMP_3D (TAG(0x30U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_JAWT (TAG(0x31U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_JINPUT (TAG(0x32U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_LWM (TAG(0x33U) | CTYP_GRAPHICS_DRAW)
++#define CID_COMP_2D (TAG(0x34U) | CTYP_GRAPHICS_DRAW)
++
++/* -------------------------------------------------------------------------- */
++/* Bus Class Types/Components (busses connect hardware components together) */
++/* -------------------------------------------------------------------------- */
++#define CTYP_BUS_NOTYPE (CID_CLASS_BUS | CID_TYPE_NONE)
++
++#define CID_COMP_XIO (TAG(0x01U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_IIC (TAG(0x02U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_PCI (TAG(0x03U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_P1394 (TAG(0x04U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_ENET (TAG(0x05U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_ATA (TAG(0x06U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_CAN (TAG(0x07U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UCGDMA (TAG(0x08U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_I2S (TAG(0x09U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_SPI (TAG(0x0AU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_PCM (TAG(0x0BU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_L3 (TAG(0x0CU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSPFL (TAG(0x0DU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSRSL (TAG(0x0EU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSMSBOT (TAG(0x0FU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSMSCBI (TAG(0x10U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSAUDIO (TAG(0x11U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSHID (TAG(0x12U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSCDC (TAG(0x13U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSPRINTER (TAG(0x14U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSSCSI (TAG(0x15U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSMODEM (TAG(0x16U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UDSETHERNET (TAG(0x17U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UHSPFL (TAG(0x18U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UHSMS (TAG(0x19U) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UHSAUDIO (TAG(0x1AU) | CTYP_BUS_NOTYPE)
++#define CID_COMP_UHSSCSI (TAG(0x1BU) | CTYP_BUS_NOTYPE)
++
++/* -------------------------------------------------------------------------- */
++/* Infrastructure Class Types/Components */
++/* -------------------------------------------------------------------------- */
++#define CTYP_INFRASTR_NOTYPE (CID_CLASS_INFRASTR | CID_TYPE_NONE)
++#define CTYP_INFRASTR_DATABASE (CID_CLASS_INFRASTR | CID_TYPE_DATABASE)
++
++#define CID_COMP_OSAL (TAG(0x01U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_MML (TAG(0x02U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_TSSA_DEFAULTS (TAG(0x03U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_RPC (TAG(0x04U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_THI (TAG(0x05U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_REGISTRY (TAG(0x06U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_TMMAN (TAG(0x07U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_LDT (TAG(0x08U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_CPUCONN (TAG(0x09U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_COMMQUE (TAG(0x0AU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_BSLMGR (TAG(0x0BU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_CR (TAG(0x0CU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_NODE (TAG(0x0DU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_COM (TAG(0x0EU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_UTIL (TAG(0x0FU) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_SGLIST (TAG(0x10U) | CTYP_INFRASTR_NOTYPE)
++#define CID_COMP_ARITH (TAG(0x11U) | CTYP_INFRASTR_NOTYPE)
++
++#define CID_COMP_MULTIFS (TAG(0x01U) | CTYP_INFRASTR_DATABASE)
++#define CID_COMP_SFS (TAG(0x02U) | CTYP_INFRASTR_DATABASE)
++
++/* -------------------------------------------------------------------------- */
++/* Component Standard Error/Progress Status definitions (bits 11:0, 12 bits) */
++/* NOTE: These status codes are ORed with the component identifier to create */
++/* component unique 32 bit status values. The component status values */
++/* should be defined in the header files where the APIs are defined. */
++/* -------------------------------------------------------------------------- */
++#define CID_ERR_BITMASK 0xFFFU
++#define CID_ERR_BITSHIFT 0
++#define CID_GET_ERROR(compId) ((compId & CID_ERR_BITMASK) >> CID_ERR_BITSHIFT)
++
++#define TM_ERR_COMPATIBILITY 0x001U /* SW Interface compatibility */
++#define TM_ERR_MAJOR_VERSION 0x002U /* SW Major Version error */
++#define TM_ERR_COMP_VERSION 0x003U /* SW component version error */
++#define TM_ERR_BAD_MODULE_ID 0x004U /* SW - HW module ID error */
++#define TM_ERR_BAD_UNIT_NUMBER 0x005U /* Invalid device unit number */
++#define TM_ERR_BAD_INSTANCE 0x006U /* Bad input instance value */
++#define TM_ERR_BAD_HANDLE 0x007U /* Bad input handle */
++#define TM_ERR_BAD_INDEX 0x008U /* Bad input index */
++#define TM_ERR_BAD_PARAMETER 0x009U /* Invalid input parameter */
++#define TM_ERR_NO_INSTANCES 0x00AU /* No instances available */
++#define TM_ERR_NO_COMPONENT 0x00BU /* Component is not present */
++#define TM_ERR_NO_RESOURCES 0x00CU /* Resource is not available */
++#define TM_ERR_INSTANCE_IN_USE 0x00DU /* Instance is already in use */
++#define TM_ERR_RESOURCE_OWNED 0x00EU /* Resource is already in use */
++#define TM_ERR_RESOURCE_NOT_OWNED 0x00FU /* Caller does not own resource */
++#define TM_ERR_INCONSISTENT_PARAMS 0x010U /* Inconsistent input params */
++#define TM_ERR_NOT_INITIALIZED 0x011U /* Component is not initialized */
++#define TM_ERR_NOT_ENABLED 0x012U /* Component is not enabled */
++#define TM_ERR_NOT_SUPPORTED 0x013U /* Function is not supported */
++#define TM_ERR_INIT_FAILED 0x014U /* Initialization failed */
++#define TM_ERR_BUSY 0x015U /* Component is busy */
++#define TM_ERR_NOT_BUSY 0x016U /* Component is not busy */
++#define TM_ERR_READ 0x017U /* Read error */
++#define TM_ERR_WRITE 0x018U /* Write error */
++#define TM_ERR_ERASE 0x019U /* Erase error */
++#define TM_ERR_LOCK 0x01AU /* Lock error */
++#define TM_ERR_UNLOCK 0x01BU /* Unlock error */
++#define TM_ERR_OUT_OF_MEMORY 0x01CU /* Memory allocation failed */
++#define TM_ERR_BAD_VIRT_ADDRESS 0x01DU /* Bad virtual address */
++#define TM_ERR_BAD_PHYS_ADDRESS 0x01EU /* Bad physical address */
++#define TM_ERR_TIMEOUT 0x01FU /* Timeout error */
++#define TM_ERR_OVERFLOW 0x020U /* Data overflow/overrun error */
++#define TM_ERR_FULL 0x021U /* Queue (etc.) is full */
++#define TM_ERR_EMPTY 0x022U /* Queue (etc.) is empty */
++#define TM_ERR_NOT_STARTED 0x023U /* Streaming function failed */
++#define TM_ERR_ALREADY_STARTED 0x024U /* Start function failed */
++#define TM_ERR_NOT_STOPPED 0x025U /* Non-streaming function failed*/
++#define TM_ERR_ALREADY_STOPPED 0x026U /* Stop function failed */
++#define TM_ERR_ALREADY_SETUP 0x027U /* Setup function failed */
++#define TM_ERR_NULL_PARAMETER 0x028U /* Null input parameter */
++#define TM_ERR_NULL_DATAINFUNC 0x029U /* Null data input function */
++#define TM_ERR_NULL_DATAOUTFUNC 0x02AU /* Null data output function */
++#define TM_ERR_NULL_CONTROLFUNC 0x02BU /* Null control function */
++#define TM_ERR_NULL_COMPLETIONFUNC 0x02CU /* Null completion function */
++#define TM_ERR_NULL_PROGRESSFUNC 0x02DU /* Null progress function */
++#define TM_ERR_NULL_ERRORFUNC 0x02EU /* Null error handler function */
++#define TM_ERR_NULL_MEMALLOCFUNC 0x02FU /* Null memory alloc function */
++#define TM_ERR_NULL_MEMFREEFUNC 0x030U /* Null memory free function */
++#define TM_ERR_NULL_CONFIGFUNC 0x031U /* Null configuration function */
++#define TM_ERR_NULL_PARENT 0x032U /* Null parent data */
++#define TM_ERR_NULL_IODESC 0x033U /* Null in/out descriptor */
++#define TM_ERR_NULL_CTRLDESC 0x034U /* Null control descriptor */
++#define TM_ERR_UNSUPPORTED_DATACLASS 0x035U /* Unsupported data class */
++#define TM_ERR_UNSUPPORTED_DATATYPE 0x036U /* Unsupported data type */
++#define TM_ERR_UNSUPPORTED_DATASUBTYPE 0x037U /* Unsupported data subtype */
++#define TM_ERR_FORMAT 0x038U /* Invalid/unsupported format */
++#define TM_ERR_INPUT_DESC_FLAGS 0x039U /* Bad input descriptor flags */
++#define TM_ERR_OUTPUT_DESC_FLAGS 0x03AU /* Bad output descriptor flags */
++#define TM_ERR_CAP_REQUIRED 0x03BU /* Capabilities required ??? */
++#define TM_ERR_BAD_TMALFUNC_TABLE 0x03CU /* Bad TMAL function table */
++#define TM_ERR_INVALID_CHANNEL_ID 0x03DU /* Invalid channel identifier */
++#define TM_ERR_INVALID_COMMAND 0x03EU /* Invalid command/request */
++#define TM_ERR_STREAM_MODE_CONFUSION 0x03FU /* Stream mode config conflict */
++#define TM_ERR_UNDERRUN 0x040U /* Data underflow/underrun */
++#define TM_ERR_EMPTY_PACKET_RECVD 0x041U /* Empty data packet received */
++#define TM_ERR_OTHER_DATAINOUT_ERR 0x042U /* Other data input/output err */
++#define TM_ERR_STOP_REQUESTED 0x043U /* Stop in progress */
++#define TM_ERR_ASSERTION 0x049U /* Assertion failure */
++#define TM_ERR_HIGHWAY_BANDWIDTH 0x04AU /* Highway bandwidth bus error */
++#define TM_ERR_HW_RESET_FAILED 0x04BU /* Hardware reset failed */
++#define TM_ERR_BAD_FLAGS 0x04DU /* Bad flags */
++#define TM_ERR_BAD_PRIORITY 0x04EU /* Bad priority */
++#define TM_ERR_BAD_REFERENCE_COUNT 0x04FU /* Bad reference count */
++#define TM_ERR_BAD_SETUP 0x050U /* Bad setup */
++#define TM_ERR_BAD_STACK_SIZE 0x051U /* Bad stack size */
++#define TM_ERR_BAD_TEE 0x052U /* Bad tee */
++#define TM_ERR_IN_PLACE 0x053U /* In place */
++#define TM_ERR_NOT_CACHE_ALIGNED 0x054U /* Not cache aligned */
++#define TM_ERR_NO_ROOT_TEE 0x055U /* No root tee */
++#define TM_ERR_NO_TEE_ALLOWED 0x056U /* No tee allowed */
++#define TM_ERR_NO_TEE_EMPTY_PACKET 0x057U /* No tee empty packet */
++#define TM_ERR_NULL_PACKET 0x059U /* Null packet */
++#define TM_ERR_FORMAT_FREED 0x05AU /* Format freed */
++#define TM_ERR_FORMAT_INTERNAL 0x05BU /* Format internal */
++#define TM_ERR_BAD_FORMAT 0x05CU /* Bad format */
++#define TM_ERR_FORMAT_NEGOTIATE_DATACLASS 0x05DU /* Format negotiate class */
++#define TM_ERR_FORMAT_NEGOTIATE_DATATYPE 0x05EU /* Format negotiate type */
++#define TM_ERR_FORMAT_NEGOTIATE_DATASUBTYPE 0x05FU /* Format negotiate subtype */
++#define TM_ERR_FORMAT_NEGOTIATE_DESCRIPTION 0x060U /* Format negotiate desc */
++#define TM_ERR_NULL_FORMAT 0x061U /* Null format */
++#define TM_ERR_FORMAT_REFERENCE_COUNT 0x062U /* Format reference count */
++#define TM_ERR_FORMAT_NOT_UNIQUE 0x063U /* Format not unique */
++#define TM_NEW_FORMAT 0x064U /* New format (not an error) */
++#define TM_ERR_FORMAT_NEGOTIATE_EXTENSION 0x065U /* Format negotiate extension */
++#define TM_ERR_INVALID_STATE 0x066U /* Invalid state for function */
++#define TM_ERR_NULL_CONNECTION 0x067U /* No connection to this pin */
++#define TM_ERR_OPERATION_NOT_PERMITTED 0x068U /* corresponds to posix EPERM */
++#define TM_ERR_NOT_CLOCKED 0x069U /* Power down - clocked off */
++
++
++#define PH_ERR_COMPATIBILITY 0x001U /* SW Interface compatibility */
++#define PH_ERR_MAJOR_VERSION 0x002U /* SW Major Version error */
++#define PH_ERR_COMP_VERSION 0x003U /* SW component version error */
++#define PH_ERR_BAD_MODULE_ID 0x004U /* SW - HW module ID error */
++#define PH_ERR_BAD_UNIT_NUMBER 0x005U /* Invalid device unit number */
++#define PH_ERR_BAD_INSTANCE 0x006U /* Bad input instance value */
++#define PH_ERR_BAD_HANDLE 0x007U /* Bad input handle */
++#define PH_ERR_BAD_INDEX 0x008U /* Bad input index */
++#define PH_ERR_BAD_PARAMETER 0x009U /* Invalid input parameter */
++#define PH_ERR_NO_INSTANCES 0x00AU /* No instances available */
++#define PH_ERR_NO_COMPONENT 0x00BU /* Component is not present */
++#define PH_ERR_NO_RESOURCES 0x00CU /* Resource is not available */
++#define PH_ERR_INSTANCE_IN_USE 0x00DU /* Instance is already in use */
++#define PH_ERR_RESOURCE_OWNED 0x00EU /* Resource is already in use */
++#define PH_ERR_RESOURCE_NOT_OWNED 0x00FU /* Caller does not own resource */
++#define PH_ERR_INCONSISTENT_PARAMS 0x010U /* Inconsistent input params */
++#define PH_ERR_NOT_INITIALIZED 0x011U /* Component is not initialized */
++#define PH_ERR_NOT_ENABLED 0x012U /* Component is not enabled */
++#define PH_ERR_NOT_SUPPORTED 0x013U /* Function is not supported */
++#define PH_ERR_INIT_FAILED 0x014U /* Initialization failed */
++#define PH_ERR_BUSY 0x015U /* Component is busy */
++#define PH_ERR_NOT_BUSY 0x016U /* Component is not busy */
++#define PH_ERR_READ 0x017U /* Read error */
++#define PH_ERR_WRITE 0x018U /* Write error */
++#define PH_ERR_ERASE 0x019U /* Erase error */
++#define PH_ERR_LOCK 0x01AU /* Lock error */
++#define PH_ERR_UNLOCK 0x01BU /* Unlock error */
++#define PH_ERR_OUT_OF_MEMORY 0x01CU /* Memory allocation failed */
++#define PH_ERR_BAD_VIRT_ADDRESS 0x01DU /* Bad virtual address */
++#define PH_ERR_BAD_PHYS_ADDRESS 0x01EU /* Bad physical address */
++#define PH_ERR_TIMEOUT 0x01FU /* Timeout error */
++#define PH_ERR_OVERFLOW 0x020U /* Data overflow/overrun error */
++#define PH_ERR_FULL 0x021U /* Queue (etc.) is full */
++#define PH_ERR_EMPTY 0x022U /* Queue (etc.) is empty */
++#define PH_ERR_NOT_STARTED 0x023U /* Streaming function failed */
++#define PH_ERR_ALREADY_STARTED 0x024U /* Start function failed */
++#define PH_ERR_NOT_STOPPED 0x025U /* Non-streaming function failed*/
++#define PH_ERR_ALREADY_STOPPED 0x026U /* Stop function failed */
++#define PH_ERR_ALREADY_SETUP 0x027U /* Setup function failed */
++#define PH_ERR_NULL_PARAMETER 0x028U /* Null input parameter */
++#define PH_ERR_NULL_DATAINFUNC 0x029U /* Null data input function */
++#define PH_ERR_NULL_DATAOUTFUNC 0x02AU /* Null data output function */
++#define PH_ERR_NULL_CONTROLFUNC 0x02BU /* Null control function */
++#define PH_ERR_NULL_COMPLETIONFUNC 0x02CU /* Null completion function */
++#define PH_ERR_NULL_PROGRESSFUNC 0x02DU /* Null progress function */
++#define PH_ERR_NULL_ERRORFUNC 0x02EU /* Null error handler function */
++#define PH_ERR_NULL_MEMALLOCFUNC 0x02FU /* Null memory alloc function */
++#define PH_ERR_NULL_MEMFREEFUNC 0x030U /* Null memory free function */
++#define PH_ERR_NULL_CONFIGFUNC 0x031U /* Null configuration function */
++#define PH_ERR_NULL_PARENT 0x032U /* Null parent data */
++#define PH_ERR_NULL_IODESC 0x033U /* Null in/out descriptor */
++#define PH_ERR_NULL_CTRLDESC 0x034U /* Null control descriptor */
++#define PH_ERR_UNSUPPORTED_DATACLASS 0x035U /* Unsupported data class */
++#define PH_ERR_UNSUPPORTED_DATATYPE 0x036U /* Unsupported data type */
++#define PH_ERR_UNSUPPORTED_DATASUBTYPE 0x037U /* Unsupported data subtype */
++#define PH_ERR_FORMAT 0x038U /* Invalid/unsupported format */
++#define PH_ERR_INPUT_DESC_FLAGS 0x039U /* Bad input descriptor flags */
++#define PH_ERR_OUTPUT_DESC_FLAGS 0x03AU /* Bad output descriptor flags */
++#define PH_ERR_CAP_REQUIRED 0x03BU /* Capabilities required ??? */
++#define PH_ERR_BAD_TMALFUNC_TABLE 0x03CU /* Bad TMAL function table */
++#define PH_ERR_INVALID_CHANNEL_ID 0x03DU /* Invalid channel identifier */
++#define PH_ERR_INVALID_COMMAND 0x03EU /* Invalid command/request */
++#define PH_ERR_STREAM_MODE_CONFUSION 0x03FU /* Stream mode config conflict */
++#define PH_ERR_UNDERRUN 0x040U /* Data underflow/underrun */
++#define PH_ERR_EMPTY_PACKET_RECVD 0x041U /* Empty data packet received */
++#define PH_ERR_OTHER_DATAINOUT_ERR 0x042U /* Other data input/output err */
++#define PH_ERR_STOP_REQUESTED 0x043U /* Stop in progress */
++#define PH_ERR_ASSERTION 0x049U /* Assertion failure */
++#define PH_ERR_HIGHWAY_BANDWIDTH 0x04AU /* Highway bandwidth bus error */
++#define PH_ERR_HW_RESET_FAILED 0x04BU /* Hardware reset failed */
++#define PH_ERR_BAD_FLAGS 0x04DU /* Bad flags */
++#define PH_ERR_BAD_PRIORITY 0x04EU /* Bad priority */
++#define PH_ERR_BAD_REFERENCE_COUNT 0x04FU /* Bad reference count */
++#define PH_ERR_BAD_SETUP 0x050U /* Bad setup */
++#define PH_ERR_BAD_STACK_SIZE 0x051U /* Bad stack size */
++#define PH_ERR_BAD_TEE 0x052U /* Bad tee */
++#define PH_ERR_IN_PLACE 0x053U /* In place */
++#define PH_ERR_NOT_CACHE_ALIGNED 0x054U /* Not cache aligned */
++#define PH_ERR_NO_ROOT_TEE 0x055U /* No root tee */
++#define PH_ERR_NO_TEE_ALLOWED 0x056U /* No tee allowed */
++#define PH_ERR_NO_TEE_EMPTY_PACKET 0x057U /* No tee empty packet */
++#define PH_ERR_NULL_PACKET 0x059U /* Null packet */
++#define PH_ERR_FORMAT_FREED 0x05AU /* Format freed */
++#define PH_ERR_FORMAT_INTERNAL 0x05BU /* Format internal */
++#define PH_ERR_BAD_FORMAT 0x05CU /* Bad format */
++#define PH_ERR_FORMAT_NEGOTIATE_DATACLASS 0x05DU /* Format negotiate class */
++#define PH_ERR_FORMAT_NEGOTIATE_DATATYPE 0x05EU /* Format negotiate type */
++#define PH_ERR_FORMAT_NEGOTIATE_DATASUBTYPE 0x05FU /* Format negotiate subtype */
++#define PH_ERR_FORMAT_NEGOTIATE_DESCRIPTION 0x060U /* Format negotiate desc */
++#define PH_ERR_NULL_FORMAT 0x061U /* Null format */
++#define PH_ERR_FORMAT_REFERENCE_COUNT 0x062U /* Format reference count */
++#define PH_ERR_FORMAT_NOT_UNIQUE 0x063U /* Format not unique */
++#define PH_NEW_FORMAT 0x064U /* New format (not an error) */
++#define PH_ERR_FORMAT_NEGOTIATE_EXTENSION 0x065U /* Format negotiate extension */
++#define PH_ERR_INVALID_STATE 0x066U /* Invalid state for function */
++#define PH_ERR_NULL_CONNECTION 0x067U /* No connection to this pin */
++#define PH_ERR_OPERATION_NOT_PERMITTED 0x068U /* corresponds to posix EPERM */
++#define PH_ERR_NOT_CLOCKED 0x069U /* Power down - clocked off */
++
++/* Add new standard error/progress status codes here */
++
++#define TM_ERR_COMP_UNIQUE_START 0x800U /* 0x800-0xBFF: Component unique */
++#define PH_ERR_COMP_UNIQUE_START 0x800U /* 0x800-0xBFF: Component unique */
++#define TM_ERR_CUSTOMER_START 0xC00U /* 0xC00-0xDFF: Customer defined */
++#define PH_ERR_CUSTOMER_START 0xC00U /* 0xC00-0xDFF: Customer defined */
++
++/* Legacy and withdrawn error codes */
++#define TM_ERR_FORMAT_NEGOTIATE_SUBCLASS TM_ERR_FORMAT_NEGOTIATE_DATACLASS
++#define TM_ERR_NEW_FORMAT TM_NEW_FORMAT
++#define TM_ERR_PAUSE_PIN_REQUESTED TM_ERR_STOP_REQUESTED
++#define TM_ERR_PIN_ALREADY_STARTED TM_ERR_ALREADY_STARTED
++#define TM_ERR_PIN_ALREADY_STOPPED TM_ERR_ALREADY_STOPPED
++#define TM_ERR_PIN_NOT_STARTED TM_ERR_NOT_STARTED
++#define TM_ERR_PIN_NOT_STOPPED TM_ERR_NOT_STOPPED
++#define TM_ERR_PIN_PAUSED TM_ERR_NOT_STARTED
++
++/* -------------------------------------------------------------------------- */
++/* Standard assert error code start offset */
++/* NOTE: These ranges are FOR LEGACY CODE ONLY and must not be used in new */
++/* components */
++/* -------------------------------------------------------------------------- */
++#define TM_ERR_ASSERT_START 0xE00U /* 0xE00-0xEFF: Assert failures */
++#define TM_ERR_ASSERT_LAST 0xEFFU /* Last assert error range value */
++#define CID_IS_ASSERT_ERROR(compId) ((CID_GET_ERROR(compId) >= TM_ERR_ASSERT_START) && (CID_GET_ERROR(compId) <= TM_ERR_ASSERT_LAST))
++
++/* -------------------------------------------------------------------------- */
++/* Standard fatal error code start offset */
++/* NOTE: These ranges are FOR LEGACY CODE ONLY and must not be used in new */
++/* components */
++/* -------------------------------------------------------------------------- */
++
++#define TM_ERR_FATAL_START 0xF00U /* 0xF00-0xFFF: Fatal failures */
++#define TM_ERR_FATAL_LAST 0xFFFU /* Last fatal error range value */
++#define CID_IS_FATAL_ERROR(compId) ((CID_GET_ERROR(compId) >= TM_ERR_FATAL_START) && (CID_GET_ERROR(compId) <= TM_ERR_FATAL_LAST))
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* TMNXCOMPID_H ----------------- */
+diff --git a/drivers/video/nxp/inc/tmNxTypes.h b/drivers/video/nxp/inc/tmNxTypes.h
+new file mode 100755
+index 0000000..af67f61
+--- /dev/null
++++ b/drivers/video/nxp/inc/tmNxTypes.h
+@@ -0,0 +1,366 @@
++/*==========================================================================*/
++/* (Copyright (C) 2003 Koninklijke Philips Electronics N.V. */
++/* All rights reserved. */
++/* This source code and any compilation or derivative thereof is the */
++/* proprietary information of Koninklijke Philips Electronics N.V. */
++/* and is confidential in nature. */
++/* Under no circumstances is this software to be exposed to or placed */
++/* under an Open Source License of any type without the expressed */
++/* written permission of Koninklijke Philips Electronics N.V. */
++/*==========================================================================*/
++/*
++ * Copyright (C) 2000,2001
++ * Koninklijke Philips Electronics N.V.
++ * All Rights Reserved.
++ *
++ * Copyright (C) 2000,2001 TriMedia Technologies, Inc.
++ * All Rights Reserved.
++ *
++ *############################################################
++ *
++ * Module name : tmNxTypes.h %version: 7 %
++ *
++ * Last Update : %date_modified: Tue Jul 8 18:08:00 2003 %
++ *
++ * Description: TriMedia/MIPS global type definitions.
++ *
++ * Document Ref: DVP Software Coding Guidelines Specification
++ * DVP/MoReUse Naming Conventions specification
++ * DVP Software Versioning Specification
++ * DVP Device Library Architecture Specification
++ * DVP Board Support Library Architecture Specification
++ * DVP Hardware API Architecture Specification
++ *
++ *
++ *############################################################
++ */
++
++#ifndef TMNXTYPES_H
++#define TMNXTYPES_H
++
++//-----------------------------------------------------------------------------
++// Standard include files:
++//-----------------------------------------------------------------------------
++//
++
++//-----------------------------------------------------------------------------
++// Project include files:
++//-----------------------------------------------------------------------------
++//
++#include "tmFlags.h" // DVP common build control flags
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++//-----------------------------------------------------------------------------
++// Types and defines:
++//-----------------------------------------------------------------------------
++//
++
++/*Under the TCS, <tmlib/tmtypes.h> may have been included by our client. In
++ order to avoid errors, we take account of this possibility, but in order to
++ support environments where the TCS is not available, we do not include the
++ file by name.*/
++
++#ifndef _TMtypes_h
++#define _TMtypes_h
++
++#define False 0
++#define True 1
++
++#ifdef __cplusplus
++#define Null 0
++#else
++#define Null ((Void *) 0)
++#endif
++
++//
++// Standard Types
++//
++typedef signed char Int8; // 8 bit signed integer
++typedef signed short Int16; // 16 bit signed integer
++typedef signed long Int32; // 32 bit signed integer
++typedef unsigned char UInt8; // 8 bit unsigned integer
++typedef unsigned short UInt16; // 16 bit unsigned integer
++typedef unsigned long UInt32; // 32 bit unsigned integer
++typedef float Float; // 32 bit floating point
++typedef unsigned int Bool; // Boolean (True/False)
++typedef char Char; // character, character array ptr
++typedef int Int; // machine-natural integer
++typedef unsigned int UInt; // machine-natural unsigned integer
++typedef char *String; // Null terminated 8 bit char str
++
++//-----------------------------------------------------------------------------
++// Legacy TM Types/Structures (Not necessarily DVP Coding Guideline compliant)
++// NOTE: For DVP Coding Gudeline compliant code, do not use these types.
++//
++typedef char *Address; // Ready for address-arithmetic
++typedef char const *ConstAddress;
++typedef unsigned char Byte; // Raw byte
++typedef float Float32; // Single-precision float
++typedef double Float64; // Double-precision float
++typedef void *Pointer; // Pointer to anonymous object
++typedef void const *ConstPointer;
++typedef char const *ConstString;
++
++typedef Int Endian;
++#define BigEndian 0
++#define LittleEndian 1
++
++typedef struct tmVersion
++{
++ UInt8 majorVersion;
++ UInt8 minorVersion;
++ UInt16 buildVersion;
++} tmVersion_t, *ptmVersion_t;
++#endif /*ndef _TMtypes_h*/
++
++/*Define DVP types that are not TCS types.*/
++/*
++** ===== Updated from SDE2/2.3_Beta/sde_template/inc/tmNxTypes.h =====
++**
++** NOTE: IBits32/UBits32 types are defined for use with 32 bit bitfields.
++** This is done because ANSI/ISO compliant compilers require bitfields
++** to be of type "int" else a large number of compiler warnings will
++** result. To avoid the risks associated with redefining Int32/UInt32
++** to type "int" instead of type "long" (which are the same size on 32
++** bit CPUs) separate 32bit signed/unsigned bitfield types are defined.
++*/
++typedef signed int IBits32; /* 32 bit signed integer bitfields */
++typedef unsigned int UBits32; /* 32 bit unsigned integer bitfields */
++typedef IBits32 *pIBits32; /* 32 bit signed integer bitfield ptr */
++typedef UBits32 *pUBits32; /* 32 bit unsigned integer bitfield ptr */
++
++typedef Int8 *pInt8; // 8 bit signed integer
++typedef Int16 *pInt16; // 16 bit signed integer
++typedef Int32 *pInt32; // 32 bit signed integer
++typedef UInt8 *pUInt8; // 8 bit unsigned integer
++typedef UInt16 *pUInt16; // 16 bit unsigned integer
++typedef UInt32 *pUInt32; // 32 bit unsigned integer
++typedef void Void, *pVoid; // Void (typeless)
++typedef Float *pFloat; // 32 bit floating point
++typedef double Double, *pDouble; // 32/64 bit floating point
++typedef Bool *pBool; // Boolean (True/False)
++typedef Char *pChar; // character, character array ptr
++typedef Int *pInt; // machine-natural integer
++typedef UInt *pUInt; // machine-natural unsigned integer
++typedef String *pString; // Null terminated 8 bit char str,
++
++/*Assume that 64-bit integers are supported natively by C99 compilers and Visual
++ C version 6.00 and higher. More discrimination in this area may be added
++ here as necessary.*/
++#if defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L
++/*This can be enabled only when all explicit references to the hi and lo
++ structure members are eliminated from client code.*/
++#define TMFL_NATIVE_INT64 1
++typedef signed long long int Int64, *pInt64; // 64-bit integer
++typedef unsigned long long int UInt64, *pUInt64; // 64-bit bitmask
++// #elif defined _MSC_VER && _MSC_VER >= 1200
++// /*This can be enabled only when all explicit references to the hi and lo
++// structure members are eliminated from client code.*/
++// #define TMFL_NATIVE_INT64 1
++// typedef signed __int64 Int64, *pInt64; // 64-bit integer
++// typedef unsigned __int64 UInt64, *pUInt64; // 64-bit bitmask
++#else /*!(defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L)*/
++#define TMFL_NATIVE_INT64 0
++typedef
++ struct
++ {
++ /*Get the correct endianness (this has no impact on any other part of
++ the system, but may make memory dumps easier to understand).*/
++#if TMFL_ENDIAN == TMFL_ENDIAN_BIG
++ Int32 hi; UInt32 lo;
++#else
++ UInt32 lo; Int32 hi;
++#endif
++ }
++ Int64, *pInt64; // 64-bit integer
++typedef
++ struct
++ {
++#if TMFL_ENDIAN == TMFL_ENDIAN_BIG
++ UInt32 hi; UInt32 lo;
++#else
++ UInt32 lo; UInt32 hi;
++#endif
++ }
++ UInt64, *pUInt64; // 64-bit bitmask
++#endif /*defined __STDC_VERSION__ && __STDC_VERSION__ > 199409L*/
++
++// Maximum length of device name in all BSP and capability structures
++#define HAL_DEVICE_NAME_LENGTH 16
++
++typedef UInt32 tmErrorCode_t;
++typedef UInt32 tmProgressCode_t;
++
++/* timestamp definition */
++typedef UInt64 tmTimeStamp_t, *ptmTimeStamp_t;
++
++//for backwards compatibility with the older tmTimeStamp_t definition
++#define ticks lo
++#define hiTicks hi
++
++typedef union tmColor3 // 3 byte color structure
++{
++ UBits32 u32;
++#if (TMFL_ENDIAN == TMFL_ENDIAN_BIG)
++ struct {
++ UBits32 : 8;
++ UBits32 red : 8;
++ UBits32 green : 8;
++ UBits32 blue : 8;
++ } rgb;
++ struct {
++ UBits32 : 8;
++ UBits32 y : 8;
++ UBits32 u : 8;
++ UBits32 v : 8;
++ } yuv;
++ struct {
++ UBits32 : 8;
++ UBits32 u : 8;
++ UBits32 m : 8;
++ UBits32 l : 8;
++ } uml;
++#else
++ struct {
++ UBits32 blue : 8;
++ UBits32 green : 8;
++ UBits32 red : 8;
++ UBits32 : 8;
++ } rgb;
++ struct {
++ UBits32 v : 8;
++ UBits32 u : 8;
++ UBits32 y : 8;
++ UBits32 : 8;
++ } yuv;
++ struct {
++ UBits32 l : 8;
++ UBits32 m : 8;
++ UBits32 u : 8;
++ UBits32 : 8;
++ } uml;
++#endif
++} tmColor3_t, *ptmColor3_t;
++
++typedef union tmColor4 // 4 byte color structure
++{
++ UBits32 u32;
++#if (TMFL_ENDIAN == TMFL_ENDIAN_BIG)
++ struct {
++ UBits32 alpha : 8;
++ UBits32 red : 8;
++ UBits32 green : 8;
++ UBits32 blue : 8;
++ } argb;
++ struct {
++ UBits32 alpha : 8;
++ UBits32 y : 8;
++ UBits32 u : 8;
++ UBits32 v : 8;
++ } ayuv;
++ struct {
++ UBits32 alpha : 8;
++ UBits32 u : 8;
++ UBits32 m : 8;
++ UBits32 l : 8;
++ } auml;
++#else
++ struct {
++ UBits32 blue : 8;
++ UBits32 green : 8;
++ UBits32 red : 8;
++ UBits32 alpha : 8;
++ } argb;
++ struct {
++ UBits32 v : 8;
++ UBits32 u : 8;
++ UBits32 y : 8;
++ UBits32 alpha : 8;
++ } ayuv;
++ struct {
++ UBits32 l : 8;
++ UBits32 m : 8;
++ UBits32 u : 8;
++ UBits32 alpha : 8;
++ } auml;
++#endif
++} tmColor4_t, *ptmColor4_t;
++
++//-----------------------------------------------------------------------------
++// Hardware device power states
++//
++typedef enum tmPowerState
++{
++ tmPowerOn, // Device powered on (D0 state)
++ tmPowerStandby, // Device power standby (D1 state)
++ tmPowerSuspend, // Device power suspended (D2 state)
++ tmPowerOff // Device powered off (D3 state)
++
++} tmPowerState_t, *ptmPowerState_t;
++
++//-----------------------------------------------------------------------------
++// Software Version Structure
++//
++typedef struct tmSWVersion
++{
++ UInt32 compatibilityNr; // Interface compatibility number
++ UInt32 majorVersionNr; // Interface major version number
++ UInt32 minorVersionNr; // Interface minor version number
++
++} tmSWVersion_t, *ptmSWVersion_t;
++
++/*Under the TCS, <tm1/tmBoardDef.h> may have been included by our client. In
++ order to avoid errors, we take account of this possibility, but in order to
++ support environments where the TCS is not available, we do not include the
++ file by name.*/
++#ifndef _TMBOARDDEF_H_
++#define _TMBOARDDEF_H_
++
++//-----------------------------------------------------------------------------
++// HW Unit Selection
++//
++typedef Int tmUnitSelect_t, *ptmUnitSelect_t;
++
++#define tmUnitNone (-1)
++#define tmUnit0 0
++#define tmUnit1 1
++#define tmUnit2 2
++#define tmUnit3 3
++#define tmUnit4 4
++
++/*+compatibility*/
++#define unitSelect_t tmUnitSelect_t
++#define unit0 tmUnit0
++#define unit1 tmUnit1
++#define unit2 tmUnit2
++#define unit3 tmUnit3
++#define unit4 tmUnit4
++#define DEVICE_NAME_LENGTH HAL_DEVICE_NAME_LENGTH
++/*-compatibility*/
++
++#endif /*ndef _TMBOARDDEF_H_ */
++
++//-----------------------------------------------------------------------------
++// Instance handle
++//
++typedef Int tmInstance_t, *ptmInstance_t;
++
++// Callback function declaration
++typedef Void (*ptmCallback_t) (UInt32 events, Void *pData, UInt32 userData);
++#define tmCallback_t ptmCallback_t /*compatibility*/
++
++// Kernel debugging function declaration
++#ifdef TMFL_CFG_INTELCE4100
++#define KERN_INFO void
++#define printk(fmt, args...) printf(fmt, ## args)
++#endif
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif //ndef TMNXTYPES_H
+diff --git a/drivers/video/nxp/linux_hdmi_release_note.txt b/drivers/video/nxp/linux_hdmi_release_note.txt
+new file mode 100755
+index 0000000..d06be0d
+--- /dev/null
++++ b/drivers/video/nxp/linux_hdmi_release_note.txt
+@@ -0,0 +1,417 @@
++Release note:
++
++-------------------------------
++ HDMI Tx modules for TDA998x
++ by
++ NXP Semiconductors BV
++-------------------------------
++
++---------------------------------
++ /!\ WARNING /!\
++If you want to use the HDMI driver from the user space (easier for non-Linux-expert, but needs to have an I2C driver available
++from the user space), PLEASE DON'T USE THE LINUX DELIVERY. USE THE BASIC DELIVERY INSTEAD, and refer to the install_DL.txt note.
++An exemple of application is available in HdmiTx\sde2\comps\tmdlHdmiTx\tst\tmdlHdmiTx_ExampleApplication\src folder.
++---------------------------------
++
++The release note gives all necessary detail for installation in Linux
++kernel and application tunning. Installation is Linux typical and does
++not require any HDMI background. A default video and audio setting is
++defined in hdmi_tx_init function. It can be changed at will.
++There is no porting to do, it is already provided in module. And the
++classical HDMI DevLib is embedded in it. But the UserManual is still
++usefull for customers who like to optimise the module according to
++their needs. If so, feedback is welcome. ;)
++Customers who like to drive the module from userland can do it using
++IOCTL. IOCTL maps the classical HDMI API. Using the WAIT_FRAME IOCTL,
++userland can catch HDMI events like Hot Plug Detect, RxSens or EDID.
++
++So the two main functions the customer needs to take care are :
++- hdmi_tx_init : to setup the default HDMI settings. These settings can be
++ overwritten using the TDA_SET_INPUT_OUTPUT_CMD IOCTL
++- eventCallbackTx : to fetch HDMI events from userland OR add more
++ automatic behavior in the module itself. For example basic EDID check
++ after reading EDID from the sink.
++
++For customers who like to understand how the HDMI stack works, please
++read the TRANSMITTER_TDA998X_SW_UM_Devlib.pdf user manuel. You learn that:
++1- this module is a 3 levels stack
++2- HDMI core driver API in defined in comps/tmdlHdmiTx/inc
++
++HDCP is delivered in a proprietary module to avoid GPL license constraints.
++For customer that uses HDCP, don't forget to get additional stuff from NXP
++
++For OMAP architecture, a DSS plugin is provided. So to activate
++HDMI (switch DSS to HDMI output) just prompt on target:
++echo "3" > /sys/power/vdd2_lock
++echo "1" > /sys/devices/platform/omapdss/display2/enabled
++And desactivate :
++echo "0" > /sys/devices/platform/omapdss/display2/enabled
++
++-------------------------------
++ ^ ^
++/!\ CAUTION /!\
++--- ---
++
++This release note and it's FAQ below covers every known questions from customers
++up to now. Thank you for reading it carefully. If you modify the driver, we would
++appreciate to gain from your update. So any feedback is welcome.
++
++-------------------------------
++
++- Contains :
++ . HdmiTx Linux module
++ . HdmiCec linux module
++ . HDCP linux module (on request only)
++ . test_hdmi/demo_tda test application
++ . TRANSMITTER_TDA998X_SW_UM_Devlib.pdf for HDMI TX API
++ . HDMI_CEC_User_Manual.pdf for HDMI CEC API
++ . this release note
++
++- Features :
++ . HDMI transmiter
++ . Hot Plug Detection
++ . HDCP (on request only)
++ . Customer Electronics Control (v1.4)
++ . 3D video format, including frame packing
++
++- Target :
++ . OMAP3430-ZOOMII (http://omappedia.org/wiki/Android_Getting_Started)
++
++- OS :
++ . Linux Kernel 2.6.29, Android RLS25.12
++
++- Directory :
++ . driver/video/hdmi
++ . driver/video/hdcp (only if hdcp is delivered)
++
++- Compilation tool :
++ . arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu
++
++-------------------------------
++
++- Release :
++ * V1.3.0: 2011, 4th May by Vincent Vrignaud
++ . HDMI1565 improved HDCP robustness in show_video function
++ * V1.2: 2010, 22th Oct by Andre Lepine
++ . TDA19988 support
++ * V1.1: 2010, 15th Oct by Andre Lepine
++ . TDA9983 version (only) has been produced in pure Linux style
++ * V1.03: 2010, 26th Augut by Andre Lepine
++ . USER_SET_INPUT_OUPUT
++ . use suspend mode for event catching when DSS HDMI panel is off (hdmi_disable(1))
++ . prevent IOCTL from updating power mode when used by DSS HDMI panel
++ * V1.02: 2010, 22th Jully by Andre Lepine
++ . SetHdcp with IOCTL
++ * V1.01: 2010, 15th Jully by Andre Lepine
++ . copy_from_user EDID IOCTL
++ . hdcp_onoff rework
++ . SimplayHD feature
++ . kernel i2c_client
++ . start implementing sysfs_attrs : first is resolution
++ * V1.0: 2010, 1st Jully by Andre Lepine
++ . ATC compliancy
++ . BCaps polling during 5s when CCLK is not devided by 2
++ . It HPD+RxSens rebound (several changes before SW polling)
++ . EDID used for video mode switch (HDMI, DVI)
++ . blue screen before the HDCP authentification is passed
++ . TDA reset when removing Linux module
++ . hdcp_fail_status not used in TDA9981
++ * V0.964: 2010, 25th may by Andre Lepine
++ . Check incoming REQUEST_ACTIVE_SOURCE is a broadcast
++ * V0.963: 2010, 21th may by Andre Lepine
++ . External HDCP module validation
++ * V0.963: 2010, 18th may by Andre Lepine
++ . External HDCP module validation
++ * V0.962: 2010, 11th may by Andre Lepine
++ . Clean up
++ * V0.961: 2010, 4th may by Andre Lepine
++ . Put image_view_on under compilation flag because it is not suitable for
++ "only hdmi with videoplay" usecase
++ . DEVICE_VENDOR_ID boradcast after logical address retrival
++ . Allow CEC_OPCODE_VENDOR_COMMAND and CEC_OPCODE_DEVICE_VENDOR_ID (not send FEATURE ABORTED)
++ * V0.96: 2010, 16th april by Andre Lepine
++ . Accept HDCP support using the proprietary module nwolc.ko
++ * V0.95: 2010, 23th march by Andre Lepine
++ . Add TDA9981 driver
++ * V0.94: 2010, 19th march by Andre Lepine
++ . Merge TDA19989, TDA9984 and TDA9983 drivers
++ * V0.92: 2010, 11th march by Andre Lepine
++ . Clean-up
++ . DSS pixclock inversion
++ * V0.91: 2010, 18th february by Andre Lepine
++ . porting for TDA9983
++ * V0.9: 2010, 2nd february by Andre Lepine
++ . Change directory structure
++ . Update NXP DevLib
++ . CEC & HDP event handeling fix
++ * V0.8: 2010, 18 january by Andre Lepine
++ . Pure IRQ (remove IRQ flag for polling with timer)
++ . Merge with last HdmiTx and HdmiCec version
++ . Cec initialization and power state
++ . Check argument of IOCTL and use -EFAULT when inconsistant
++ * V0.7: 2010, 11 january by Andre Lepine
++ . Automatic CEC answering for following opcodes :
++ > GIVE_PHYSICAL_ADDRESS
++ > GET_CEC_VERSION
++ > GIVE_OSD_NAME
++ > GIVE_DEVICE_VENDOR_ID
++ > REQUEST_ACTIVE_SOURCE
++ > GIVE_DEVICE_POWER_STATUS
++ > STANDBY
++ > SET_STREAM_PATH
++ > ROUTING_CHANGE
++ > ABORT_MESSAGE
++ . Automatic logical address negociation
++ . HdmiCec gets EDID physical address and HDMI status from HdmiTx
++
++-------------------------------
++
++- Installation :
++
++ * On host:
++ . mkdir $KERNEL_MODULES
++ . cp nxp-TDA1998X-linux-hdmi-cec-(hdcp)-L###-DL##-BSL##.tar.cvfj $KERNEL_MODULES/.
++ . cd $KERNEL_MODULES
++ . tar xvfj nxp-TDA1998X-linux-hdmi-cec-(hdcp)-L###-DL##-BSL##.tar.cvfj
++ . update LINUX_DIR in hdmi/MakeModules with your kernel directory path
++ . select your TDA target in Makefile : for example TDA_TX := TDA19988 !!! CAUTION, don't forget this !!!
++ . select your platform in Makefile : for example TDA_PLATFORM := ZOOMII
++ . cd hdmi
++ . make -f MakeModules clean (optional for the first time)
++ . make -f MakeModules (then you get hdmitx.ko and hdmicecc.ko modules)
++ . make -f MakeModules uptx (or any download mean that does not use adb)
++ . make -f MakeModules upcec (or any download mean that does not use adb) (19988/89 only)
++ . cd hdcp (for 19988/89 and 9984 only)
++ . update the KEY_SEED value in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c
++ . make -f MakeModules (then you get nwolc.ko module)
++ . make -f MakeModules up (or any download mean that does not use adb)
++ * Application (optional), better use your own, this one is just a sample
++ . cd test
++ . make clean (optional for the first time)
++ . make
++ . make upload (or any download mean that does not use adb)
++ * On target:
++ . insmod hdmitx.ko verbose=1 (remove verbose to make the module silent)
++ . insmod hdmicec.ko verbose=1 device=4 (remove verbose to make the module silent)
++ . insmod nwolc.ko (only for HDCP)
++ * On TV
++ . connect TV to target
++
++- Usage :
++
++ . hdmitx module parameters used with insmod :
++ > verbose: Make the driver verbose
++ > major: The major number of the device mapper
++ . hdmicec module parameters used with insmod :
++ > verbose: Make the driver verbose
++ > major: The major number of the device mapper
++ > device: Device type can be 0:tv, 1:rec 3:tuner 4:mediaplayer, 5:audio
++ > addr: Physical address (until EDID received)
++ . modules handles automaticaly HPD, EDID and following CEC messaging :
++ device connectivity and addressing, routing, standby, OSD name,
++ vendor name features.
++ . tda_demo test application show how to take control of the two modules
++ from userland and catch CEC messages
++ BUT HDMI MODULES CAN RUN WITHOUT IT
++ . HDCP feature is only supported if nwolc module is installed, you can
++ add it or remove it dynamically using insmod nwolc.ko and rmmod nwolk.
++
++- FAQ :
++
++ . "Can I modify file tda998x.c ?"
++ YES ! It's only a kind of "application" sample of the core driver below.
++ Feel free to customize it at will !
++
++ . "Can I modify files in comps directoty ?"
++ NO ! Core driver bug shall be discussed with NXP otherwise you may break down
++ some patches and introduce regressions
++
++ . "this->driver.i2c_client not allocated" :
++ 1) Declare your I2C bus usage in arch/arm/mach-omap2/board-zoom2.c as follow :
++ | static struct i2c_board_info __initdata zoom2_i2c_bus3_info[] = {
++ | {I2C_BOARD_INFO(TX_NAME, TDA998X_I2C_SLAVEADDRESS),},
++ | {I2C_BOARD_INFO(CEC_NAME, TDA99XCEC_I2C_SLAVEADDRESS),},
++ | };
++ 2) Check the TDA target in Makefile : for example TDA_TX := TDA9984
++
++ . "Video format and plan are strange..." :
++ Check tda.setio.videoout/in in hdmi_tx_init() function of tda998x.c
++
++ . "The resolution is not the one I want" :
++ Update or create your own omap_video_timings structure and change
++ the video resolution of this->tda.setio.video_out.format in hdmi_tx_init()
++
++ . "I want 720p@60Hz" :
++ 1- Line 860: Uncomment> /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz; */
++ 2- Line 862: Comment> this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
++ 3- Line 1051: Replace> video_720x480at60Hz_panel_timings with video_1280x720at60Hz_panel_timings
++
++ . "RGB colors are swapped, for example I see RBG instead of RGB" : (for TDA9984 and TDA19989 only)
++ Modify the videoPortMapping_RGB444 video port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c.
++
++ . "YUV signals are swapped, for example I see UVY instead of YUV" : (for TDA9984 and TDA19989 only)
++ Modify the videoPortMapping_YUV444/YUV422 video port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c.
++
++ . "I2C or SPDIF audio does not work, signals are swapped" : (for TDA9984 and TDA19989 only)
++ Modify the enableAudioPortI2S/SPDIF audio port mapping in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c.
++
++ . "Where can I find all video format definition ?":
++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
++
++ . "Where can I find all audio format definition ?":
++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
++
++ . "Where can I find all HDMI types definition ?":
++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
++
++ . "Where can I find all power management types definition ?":
++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Types.h
++
++ . "Where can I find all HDMI Tx API definition ?":
++ in hdmi/comps/tmdlHdmiTx/inc/tmdlHdmiTx_Functions.h
++
++ . "Where can I find all HDMI CEC types definition ?":
++ in hdmi/comps/tmdlHdmiCec/inc/tmdlHdmiCec_Types.h
++
++ . "Where can I find all HDMI CEC API definition ?":
++ in hdmi/comps/tmdlHdmiCec/inc/tmdlHdmiCec_Functions.h
++
++ . "I would like to get debug message":
++ Install the module with debug messages > insmod hdmitx.ko verbose=1
++
++ . "I would like to see the EDID of the TV":
++ Install the module with debug messages > insmod hdmitx.ko verbose=1
++
++ . "On the TV display some pixel are flickering":
++ Check the OMAP DSS setup and update the dssdev->panel.config parameters
++
++ . "CEC send Samsung vendor ID":
++ Yes, otherwise you cannot use Samsung devices... replace is by your own
++
++ . "I don't use OMAP":
++ This module contains an OMAP Display SubSystem plugin that automatically
++ drives video output of OMAP (video input of TDA). If you don't have OMAP
++ remove the ANDROID_DSS (or add your PLATFORM flag in Makefile) and do
++ the video bus configuration at your convience. Anyhow, any other usefull
++ plugin is welcome... So please feedback ;)
++
++ . "How to install HDMI module ?":
++ See installation chapter above.
++
++ . "HDCP is not supported":
++ Ask NXP to deliver you the proprietary HDCP module
++
++ . "HDCP module does not work":
++ Ask NXP to provide you your customer seed number...
++
++ . "How can I control the HDMI with my apps ?":
++ Use open("/dev/hdmitx") to get access to HdmiTx module.
++ Then use ioctl as described in tda998x_ioctl.h.
++
++ . "How can I control CEC with my apps ?":
++ Use open("/dev/hdmicec") to get access to HdmiCec module.
++ Then use ioctl as described in tda998x_ioctl.h.
++
++ . "How can my application get the HDMI event ?":
++ Create a dedicated incoming event thread in your apps and use ioctl WAIT_EVENT
++
++ . "Is is mandatory to create an incoming event thread in my apps ?":
++ No if you don't care.
++
++ . "Did I need to create some apps to make HDMI running ?":
++ No, you can modify hdmi_tx_init according to your needs and install the
++ modules in your init.rc. Hdmi will run automatically.
++
++ . "HDCP device is not authenticated":
++ Check your personnal customer ROMCODE and update accordingly your KEY_SEED value
++ in comps/tmdlHdmiTx/cfg/TDA9989/tmdlHdmiTx_Linux_cfg.c
++
++ . "Where can I get the the KEY_SEED value for HDCP":
++ Ask direcly NXP technical software support
++
++ . "How can I get PC video format like 600x480"
++ Watch out the "features on demand" part of Makefile
++
++ . "I don't get any interrupt wired nor IRQ on my board"
++ Remove the IRQ flag for timer based polling of interrupt
++
++ . "I want to use HDCP"
++ 1) Add the nwolc.ko module (or ask it to NXP)
++ 2) Add TDA_HDCP := TMFL_HDCP_SUPPORT flag
++ 3) set your KEY_SEED number in tmdlHdmiTx_Linux_cfg.c file
++
++ . "HDCP does not work"
++ Ask you key seed to NXP
++
++ . "got unexpected TMDS activity between EDID reading and SetInputOuput"
++ use USER_SET_INPUT_OUTPUT flag
++
++ . "I don't want the module to automatically setup TMDS but from userland instead"
++ use USER_SET_INPUT_OUTPUT flag
++
++ . "I2S audio does not work, N value is not good"
++ Check the audio frequence in hdmi_tx_init or using IOCTL TDA_SET_AUDIO_INPUT_CMD
++ For example, N=6144 at 48KHz, but N=6272 at 44.1Khz
++
++ . "I2S audio does not work, CTS value is not good"
++ Check the audio I2S format in hdmi_tx_init or using IOCTL TDA_SET_AUDIO_INPUT_CMD
++ CTS is automatically computed by the TDA accordingly to the audio input
++ so accordingly to the upstream settings (like an OMAP ;)
++ For example, I2S 16 bits or 32 bits do not produce the same CTS value
++
++ . "How can I change the audio settings ?"
++ Put your own settings in setio.audio_in structure. For example :
++ this->tda.setio.audio_in.format = TMDL_HDMITX_AFMT_I2S;
++ this->tda.setio.audio_in.rate = TMDL_HDMITX_AFS_44K;
++ this->tda.setio.audio_in.i2sFormat = TMDL_HDMITX_I2SFOR_PHILIPS_L;
++ this->tda.setio.audio_in.i2sQualifier = TMDL_HDMITX_I2SQ_16BITS;
++ this->tda.setio.audio_in.dstRate = TMDL_HDMITX_DSTRATE_SINGLE; /* not relevant here */
++ this->tda.setio.audio_in.channelAllocation = 0; /* audio channel allocation L+R (Ref to CEA-861D p85) */
++
++ . "When shall I set audio ?"
++ Default (at module startup) is in hdmi_tx_init
++ At will using IOCTL TDA_SET_AUDIO_INPUT_CMD
++
++- Restriction :
++
++ . Remove IRQ flag in Makefile for timer based polling
++ . Add ZOOMII_PATCH to reverse clock edge in ZOOMII
++ . add TWL4030_HACK to get keypad handle and inject CEC::USER_CONTROL events
++ . omap_dss_driver might not be supported by kernel, then hdmi_enable
++ and hdmi_disable should be triggered by any other kernel means or
++ replaced by direct call from application using:
++ --> ioctl(my_fd,TDA_IOCTL_SET_POWER,[tmPowerOn|tmPowerStandby]);
++ . HDCP can be switch off dynamically with TDA_IOCTL_SET_HDCP but not hw engine,
++ stop it by removing nwolc.ko module
++
++- License :
++
++ . hdmitx and hdmicec modules are 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, using version 2 of the License.
++ These modules are distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ for more details.
++ . nwolc module source code and any compilation or derivative thereof is
++ the proprietary information of NXP N.V. and is confidential in nature.
++ Under no circumstances is this software to be exposed to or placed under
++ an Open Source License of any type without the expressed written permission
++ of NXP N.V.
++
++- DV :
++
++ . How to create a DV :
++ -> update tda998xversion.h and set PATCH_LEVEL to 0
++ -> update linux_hdmi_release_note.txt
++ $>cd driver/video/hdmi
++ $>make -f MakeModules clean
++ $>cd ..
++ $>tar cvfj $DV_FOLDER/linux-hdmi-nxp-modules.vXYZ.tar.cvfj hdmi
++
++-----------------------------------
++
++- Feedback : vincent.vrignaud@nxp.com -
++
++-----------------------------------
++
+diff --git a/drivers/video/nxp/tda998x.c b/drivers/video/nxp/tda998x.c
+new file mode 100755
+index 0000000..4b45e41
+--- /dev/null
++++ b/drivers/video/nxp/tda998x.c
+@@ -0,0 +1,2307 @@
++/*****************************************************************************/
++/* Copyright (c) 2009 NXP Semiconductors BV */
++/* */
++/* 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, using version 2 of the License. */
++/* */
++/* This program is distributed in the hope that it will be useful, */
++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
++/* GNU General Public License for more details. */
++/* */
++/* You should have received a copy of the GNU General Public License */
++/* along with this program; if not, write to the Free Software */
++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
++/* USA. */
++/* */
++/*****************************************************************************/
++
++#define _tx_c_
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/ioctl.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/workqueue.h>
++#include <linux/interrupt.h>
++#include <asm/uaccess.h>
++#include <mach/gpio.h>
++// #include <mach/display.h>
++
++/* HDMI DevLib */
++#include "tmNxCompId.h"
++#include "tmdlHdmiTx_Types.h"
++#include "tmdlHdmiTx_Functions.h"
++
++/* local */
++#include "tda998x_version.h"
++#include "tda998x.h"
++#include "tda998x_ioctl.h"
++
++#ifdef I2C_DBG
++#include "tmbslHdmiTx_types.h"
++#include "tmbslTDA9989_local.h"
++#endif
++
++#ifdef ANDROID_DSS
++/* DSS hack */
++#endif
++
++/*
++ *
++ * DEFINITION
++ * ----------
++ * LEVEL 0
++ *
++ */
++
++#define FRAME_PACKING 200
++#define NO_FP(x) ((x) % FRAME_PACKING)
++#define IS_FP(x) ((x) > FRAME_PACKING)
++#define WITH_FP(x) ((x) + FRAME_PACKING * (this->tda.setio.video_in.structure3D == TMDL_HDMITX_3D_FRAME_PACKING))
++/*
++ * Global
++ */
++
++tda_instance our_instance;
++static struct cdev our_cdev, *this_cdev=&our_cdev;
++#ifdef ANDROID_DSS
++static struct omap_video_timings video_640x480at60Hz_panel_timings = {
++ .x_res = 640,
++ .y_res = 480,
++ .pixel_clock = 25175,
++ .hfp = 16,
++ .hsw = 96,
++ .hbp = 48,
++ .vfp = 10,
++ .vsw = 2,
++ .vbp = 33,
++};
++static struct omap_video_timings video_640x480at72Hz_panel_timings = {
++ .x_res = 640,
++ .y_res = 480,
++ .pixel_clock = 31500,
++ .hfp = 24,
++ .hsw = 40,
++ .hbp = 128,
++ .vfp = 9,
++ .vsw = 3,
++ .vbp = 28,
++};
++static struct omap_video_timings video_720x480at60Hz_panel_timings = {
++ .x_res = 720,
++ .y_res = 480,
++ .pixel_clock = 27027,
++ .hfp = 16,
++ .hbp = 60,
++ .hsw = 62,
++ .vfp = 9,
++ .vbp = 30,
++ .vsw = 6,
++};
++static struct omap_video_timings video_1280x720at50Hz_panel_timings = {
++ .x_res = 1280,
++ .y_res = 720,
++ .pixel_clock = 74250,
++#ifdef ZOOMII_PATCH
++ .hfp = 400,
++ .hbp = 260,
++#else
++ .hfp = 440,
++ .hbp = 220,
++#endif
++ .hsw = 40,
++ .vfp = 5,
++ .vbp = 20,
++ .vsw = 5,
++};
++static struct omap_video_timings video_1280x720at60Hz_panel_timings = {
++ .x_res = 1280,
++ .y_res = 720,
++ .pixel_clock = 74250,
++#ifdef ZOOMII_PATCH
++ .hfp = 70,
++ .hbp = 260,
++#else
++ .hfp = 110,
++ .hbp = 220,
++#endif
++ .hsw = 40,
++ .vfp = 5,
++ .vbp = 20,
++ .vsw = 5,
++};
++static struct omap_video_timings video_1920x1080at50Hz_panel_timings = {
++ .x_res = 1920,
++ .y_res = 1080,
++ .pixel_clock = 148500, /* 2640 x 1125 x 50 /2 */
++#ifdef ZOOMII_PATCH
++ .hfp = 488,
++ .hbp = 188,
++#else
++ .hfp = 528,
++ .hbp = 148,
++#endif
++ .hsw = 44,
++ .vfp = 4,
++ .vbp = 36,
++ .vsw = 5,
++};
++static struct omap_video_timings video_800x480at60Hz_panel_timings = {
++ /* .x_res = 800 /\* 1280 *\/, */
++ /* .y_res = 480 /\* 720 *\/, */
++ /* .pixel_clock = 21800 /\* 21800 23800 25700 *\/, */
++ .x_res = 800,
++ .y_res = 480,
++ .pixel_clock = 21800,
++ .hfp = 6,
++ .hsw = 1,
++ .hbp = 4,
++ .vfp = 3,
++ .vsw = 1,
++ .vbp = 4,
++};
++
++#endif
++
++/* #define HDCP_TEST 1 */
++#ifdef HDCP_TEST
++/* TEST */
++int test = 0;
++#endif
++
++/*
++ * Module params
++ */
++
++static int param_verbose=0,param_major=0,param_minor=0;
++module_param_named(verbose,param_verbose,int,S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(verbose, "Make the driver verbose");
++module_param_named(major, param_major, int, S_IRUGO);
++MODULE_PARM_DESC(major, "The major number of the device mapper");
++
++/*
++ *
++ * TOOLBOX
++ * -------
++ * LEVEL 1
++ *
++ * - i2c read/write
++ * - chip Id check
++ * - i2c client info
++ *
++ */
++
++/*
++ * Get main and unique I2C Client driver handle
++ */
++struct i2c_client *GetThisI2cClient(void)
++{
++ tda_instance *this=&our_instance;
++ return this->driver.i2c_client;
++}
++
++/*
++ * error handling
++ */
++char *hdmi_tx_err_string(int err)
++{
++ switch (err & 0x0FFF)
++ {
++ case TM_ERR_COMPATIBILITY: {return "SW Interface compatibility";break;}
++ case TM_ERR_MAJOR_VERSION: {return "SW Major Version error";break;}
++ case TM_ERR_COMP_VERSION: {return "SW component version error";break;}
++ case TM_ERR_BAD_UNIT_NUMBER: {return "Invalid device unit number";break;}
++ case TM_ERR_BAD_INSTANCE: {return "Bad input instance value ";break;}
++ case TM_ERR_BAD_HANDLE: {return "Bad input handle";break;}
++ case TM_ERR_BAD_PARAMETER: {return "Invalid input parameter";break;}
++ case TM_ERR_NO_RESOURCES: {return "Resource is not available ";break;}
++ case TM_ERR_RESOURCE_OWNED: {return "Resource is already in use";break;}
++ case TM_ERR_RESOURCE_NOT_OWNED: {return "Caller does not own resource";break;}
++ case TM_ERR_INCONSISTENT_PARAMS: {return "Inconsistent input params";break;}
++ case TM_ERR_NOT_INITIALIZED: {return "Component is not initialised";break;}
++ case TM_ERR_NOT_SUPPORTED: {return "Function is not supported";break;}
++ case TM_ERR_INIT_FAILED: {return "Initialization failed";break;}
++ case TM_ERR_BUSY: {return "Component is busy";break;}
++ case TMDL_ERR_DLHDMITX_I2C_READ: {return "Read error";break;}
++ case TMDL_ERR_DLHDMITX_I2C_WRITE: {return "Write error";break;}
++ case TM_ERR_FULL: {return "Queue is full";break;}
++ case TM_ERR_NOT_STARTED: {return "Function is not started";break;}
++ case TM_ERR_ALREADY_STARTED: {return "Function is already starte";break;}
++ case TM_ERR_ASSERTION: {return "Assertion failure";break;}
++ case TM_ERR_INVALID_STATE: {return "Invalid state for function";break;}
++ case TM_ERR_OPERATION_NOT_PERMITTED: {return "Corresponds to posix EPERM";break;}
++ case TMDL_ERR_DLHDMITX_RESOLUTION_UNKNOWN: {return "Bad format";break;}
++ case TM_OK: {return "OK";break;}
++ default : {printk(KERN_INFO "(err:%x) ",err);return "unknown";break;}
++ }
++}
++
++static char *tda_spy_event(int event)
++{
++ switch (event)
++ {
++ case TMDL_HDMITX_HDCP_ACTIVE: {return "HDCP active";break;}
++ case TMDL_HDMITX_HDCP_INACTIVE: {return "HDCP inactive";break;}
++ case TMDL_HDMITX_HPD_ACTIVE: {return "HPD active";break;}
++ case TMDL_HDMITX_HPD_INACTIVE: {return "HPD inactive";break;}
++ case TMDL_HDMITX_RX_KEYS_RECEIVED: {return "Rx keys received";break;}
++ case TMDL_HDMITX_RX_DEVICE_ACTIVE: {return "Rx device active";break;}
++ case TMDL_HDMITX_RX_DEVICE_INACTIVE: {return "Rx device inactive";break;}
++ case TMDL_HDMITX_EDID_RECEIVED: {return "EDID received";break;}
++ case TMDL_HDMITX_VS_RPT_RECEIVED: {return "VS interrupt has been received";break;}
++ /* case TMDL_HDMITX_B_STATUS: {return "TX received BStatus";break;} */
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ case TMDL_HDMITX_DEBUG_EVENT_1: {return "DEBUG_EVENT_1";break;}
++#endif
++ default : {return "Unkonwn event";break;}
++ }
++}
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++static char *tda_spy_hsdc_fail_status(int fail)
++{
++ switch (fail)
++ {
++ case TMDL_HDMITX_HDCP_OK: {return "ok";break;}
++ case TMDL_HDMITX_HDCP_BKSV_RCV_FAIL: {return "Source does not receive Sink BKsv ";break;}
++ case TMDL_HDMITX_HDCP_BKSV_CHECK_FAIL: {return "BKsv does not contain 20 zeros and 20 ones";break;}
++ case TMDL_HDMITX_HDCP_BCAPS_RCV_FAIL: {return "Source does not receive Sink Bcaps";break;}
++ case TMDL_HDMITX_HDCP_AKSV_SEND_FAIL: {return "Source does not send AKsv";break;}
++ case TMDL_HDMITX_HDCP_R0_RCV_FAIL: {return "Source does not receive R'0";break;}
++ case TMDL_HDMITX_HDCP_R0_CHECK_FAIL: {return "R0 = R'0 check fail";break;}
++ case TMDL_HDMITX_HDCP_BKSV_NOT_SECURE: {return "bksv not secure";break;}
++ case TMDL_HDMITX_HDCP_RI_RCV_FAIL: {return "Source does not receive R'i";break;}
++ case TMDL_HDMITX_HDCP_RPT_RI_RCV_FAIL: {return "Source does not receive R'i repeater mode";break;}
++ case TMDL_HDMITX_HDCP_RI_CHECK_FAIL: {return "RI = R'I check fail";break;}
++ case TMDL_HDMITX_HDCP_RPT_RI_CHECK_FAIL: {return "RI = R'I check fail repeater mode";break;}
++ case TMDL_HDMITX_HDCP_RPT_BCAPS_RCV_FAIL: {return "Source does not receive Sink Bcaps repeater mode";break;}
++ case TMDL_HDMITX_HDCP_RPT_BCAPS_READY_TIMEOUT: {return "bcaps ready timeout";break;}
++ case TMDL_HDMITX_HDCP_RPT_V_RCV_FAIL: {return "Source does not receive V";break;}
++ case TMDL_HDMITX_HDCP_RPT_BSTATUS_RCV_FAIL: {return "Source does not receive BSTATUS repeater mode";break;}
++ case TMDL_HDMITX_HDCP_RPT_KSVLIST_RCV_FAIL: {return "Source does not receive Ksv list in repeater mode";break;}
++ case TMDL_HDMITX_HDCP_RPT_KSVLIST_NOT_SECURE: {return "ksvlist not secure";break;}
++ default: {return "";break;}
++ }
++}
++
++static char *tda_spy_hdcp_status(int status)
++{
++ switch (status)
++ {
++ case TMDL_HDMITX_HDCP_CHECK_NOT_STARTED: {return "Check not started";break;}
++ case TMDL_HDMITX_HDCP_CHECK_IN_PROGRESS: {return "No failures, more to do";break;}
++ case TMDL_HDMITX_HDCP_CHECK_PASS: {return "Final check has passed";break;}
++ case TMDL_HDMITX_HDCP_CHECK_FAIL_FIRST: {return "First check failure code\nDriver not AUTHENTICATED";break;}
++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_T0: {return "A T0 interrupt occurred";break;}
++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_RI: {return "Device RI changed";break;}
++ case TMDL_HDMITX_HDCP_CHECK_FAIL_DEVICE_FSM: {return "Device FSM not 10h";break;}
++ default : {return "Unknown hdcp status";break;}
++ }
++
++}
++#endif
++
++static char *tda_spy_sink(int sink)
++{
++ switch (sink)
++ {
++ case TMDL_HDMITX_SINK_DVI: {return "DVI";break;}
++ case TMDL_HDMITX_SINK_HDMI: {return "HDMI";break;}
++ case TMDL_HDMITX_SINK_EDID: {return "As currently defined in EDID";break;}
++ default : {return "Unkonwn sink";break;}
++ }
++}
++
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++static char *tda_spy_aspect_ratio(int ar)
++{
++ switch (ar)
++ {
++ case TMDL_HDMITX_P_ASPECT_RATIO_UNDEFINED: {return "Undefined picture aspect rati";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_6_5: {return "6:5 picture aspect ratio (PAR";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_5_4: {return "5:4 PA";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_4_3: {return "4:3 PA";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_16_10: {return "16:10 PA";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_5_3: {return "5:3 PA";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_16_9: {return "16:9 PA";break;}
++ case TMDL_HDMITX_P_ASPECT_RATIO_9_5: {return "9:5 PA";break;}
++ default : {return "Unknown aspect ratio";break;}
++ }
++}
++
++#if 0 /* no more used */
++static char *tda_spy_edid_status(int status)
++{
++ switch (status)
++ {
++ case TMDL_HDMITX_EDID_READ: {return "All blocks read";break;}
++ case TMDL_HDMITX_EDID_READ_INCOMPLETE: {return "All blocks read OK but buffer too small to return all of the";break;}
++ case TMDL_HDMITX_EDID_ERROR_CHK_BLOCK_0: {return "Block 0 checksum erro";break;}
++ case TMDL_HDMITX_EDID_ERROR_CHK: {return "Block 0 OK, checksum error in one or more other block";break;}
++ case TMDL_HDMITX_EDID_NOT_READ: {return "EDID not read";break;}
++ case TMDL_HDMITX_EDID_STATUS_INVALID: {return "Invalid ";break;}
++ default : {return "Unknown edid status";break;}
++ }
++}
++#endif
++
++static char *tda_spy_vfmt(int fmt)
++{
++ switch (fmt)
++ {
++ case TMDL_HDMITX_VFMT_NULL: {return "NOT a valid format...";break;}
++ case TMDL_HDMITX_VFMT_01_640x480p_60Hz: {return "vic 01: 640x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_02_720x480p_60Hz: {return "vic 02: 720x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_03_720x480p_60Hz: {return "vic 03: 720x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_04_1280x720p_60Hz: {return "vic 04: 1280x720p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_05_1920x1080i_60Hz: {return "vic 05: 1920x1080i 60Hz";break;}
++ case TMDL_HDMITX_VFMT_06_720x480i_60Hz: {return "vic 06: 720x480i 60Hz";break;}
++ case TMDL_HDMITX_VFMT_07_720x480i_60Hz: {return "vic 07: 720x480i 60Hz";break;}
++ case TMDL_HDMITX_VFMT_08_720x240p_60Hz: {return "vic 08: 720x240p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_09_720x240p_60Hz: {return "vic 09: 720x240p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_10_720x480i_60Hz: {return "vic 10: 720x480i 60Hz";break;}
++ case TMDL_HDMITX_VFMT_11_720x480i_60Hz: {return "vic 11: 720x480i 60Hz";break;}
++ case TMDL_HDMITX_VFMT_12_720x240p_60Hz: {return "vic 12: 720x240p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_13_720x240p_60Hz: {return "vic 13: 720x240p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_14_1440x480p_60Hz: {return "vic 14: 1440x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_15_1440x480p_60Hz: {return "vic 15: 1440x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_16_1920x1080p_60Hz: {return "vic 16: 1920x1080p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_17_720x576p_50Hz: {return "vic 17: 720x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_18_720x576p_50Hz: {return "vic 18: 720x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_19_1280x720p_50Hz: {return "vic 19: 1280x720p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_20_1920x1080i_50Hz: {return "vic 20: 1920x1080i 50Hz";break;}
++ case TMDL_HDMITX_VFMT_21_720x576i_50Hz: {return "vic 21: 720x576i 50Hz";break;}
++ case TMDL_HDMITX_VFMT_22_720x576i_50Hz: {return "vic 22: 720x576i 50Hz";break;}
++ case TMDL_HDMITX_VFMT_23_720x288p_50Hz: {return "vic 23: 720x288p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_24_720x288p_50Hz: {return "vic 24: 720x288p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_25_720x576i_50Hz: {return "vic 25: 720x576i 50Hz";break;}
++ case TMDL_HDMITX_VFMT_26_720x576i_50Hz: {return "vic 26: 720x576i 50Hz";break;}
++ case TMDL_HDMITX_VFMT_27_720x288p_50Hz: {return "vic 27: 720x288p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_28_720x288p_50Hz: {return "vic 28: 720x288p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_29_1440x576p_50Hz: {return "vic 29: 1440x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_30_1440x576p_50Hz: {return "vic 30: 1440x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_31_1920x1080p_50Hz: {return "vic 31: 1920x1080p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_32_1920x1080p_24Hz: {return "vic 32: 1920x1080p 24Hz";break;}
++ case TMDL_HDMITX_VFMT_33_1920x1080p_25Hz: {return "vic 33: 1920x1080p 25Hz";break;}
++ case TMDL_HDMITX_VFMT_34_1920x1080p_30Hz: {return "vic 34: 1920x1080p 30Hz";break;}
++ case TMDL_HDMITX_VFMT_35_2880x480p_60Hz: {return "vic 3: 2880x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_36_2880x480p_60Hz: {return "vic 3: 2880x480p 60Hz";break;}
++ case TMDL_HDMITX_VFMT_37_2880x576p_50Hz: {return "vic 3: 2880x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_38_2880x576p_50Hz: {return "vic 3: 2880x576p 50Hz";break;}
++ case TMDL_HDMITX_VFMT_60_1280x720p_24Hz: {return "vic 60: 1280x720p 24Hz";break;}
++ case TMDL_HDMITX_VFMT_61_1280x720p_25Hz: {return "vic 61: 1280x720p 25Hz";break;}
++ case TMDL_HDMITX_VFMT_62_1280x720p_30Hz: {return "vic 62: 1280x720p 30Hz";break;}
++ case TMDL_HDMITX_VFMT_PC_800x600p_60Hz: {return "PC 129";break;}
++ case TMDL_HDMITX_VFMT_PC_1152x960p_60Hz: {return "PC 130";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x768p_60Hz: {return "PC 131";break;}
++ case TMDL_HDMITX_VFMT_PC_1280x768p_60Hz: {return "PC 132";break;}
++ case TMDL_HDMITX_VFMT_PC_1280x1024p_60Hz: {return "PC 133";break;}
++ case TMDL_HDMITX_VFMT_PC_1360x768p_60Hz: {return "PC 134";break;}
++ case TMDL_HDMITX_VFMT_PC_1400x1050p_60Hz: {return "PC 135";break;}
++ case TMDL_HDMITX_VFMT_PC_1600x1200p_60Hz: {return "PC 136";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x768p_70Hz: {return "PC 137";break;}
++ case TMDL_HDMITX_VFMT_PC_640x480p_72Hz: {return "PC 138";break;}
++ case TMDL_HDMITX_VFMT_PC_800x600p_72Hz: {return "PC 139";break;}
++ case TMDL_HDMITX_VFMT_PC_640x480p_75Hz: {return "PC 140";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x768p_75Hz: {return "PC 141";break;}
++ case TMDL_HDMITX_VFMT_PC_800x600p_75Hz: {return "PC 142";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x864p_75Hz: {return "PC 143";break;}
++ case TMDL_HDMITX_VFMT_PC_1280x1024p_75Hz: {return "PC 144";break;}
++ case TMDL_HDMITX_VFMT_PC_640x350p_85Hz: {return "PC 145";break;}
++ case TMDL_HDMITX_VFMT_PC_640x400p_85Hz: {return "PC 146";break;}
++ case TMDL_HDMITX_VFMT_PC_720x400p_85Hz: {return "PC 147";break;}
++ case TMDL_HDMITX_VFMT_PC_640x480p_85Hz: {return "PC 148";break;}
++ case TMDL_HDMITX_VFMT_PC_800x600p_85Hz: {return "PC 149";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x768p_85Hz: {return "PC 150";break;}
++ case TMDL_HDMITX_VFMT_PC_1152x864p_85Hz: {return "PC 151";break;}
++ case TMDL_HDMITX_VFMT_PC_1280x960p_85Hz: {return "PC 152";break;}
++ case TMDL_HDMITX_VFMT_PC_1280x1024p_85Hz: {return "PC 153";break;}
++ case TMDL_HDMITX_VFMT_PC_1024x768i_87Hz: {return "PC 154";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_02_720x480p_60Hz: {return "vic 02: 720x480p 60Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_17_720x576p_50Hz: {return "vic 17: 720x576p 50Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_60_1280x720p_24Hz: {return "vic 60: 1280x720p 24Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_61_1280x720p_25Hz: {return "vic 61: 1280x720p 25Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_62_1280x720p_30Hz: {return "vic 62: 1280x720p 30Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_19_1280x720p_50Hz: {return "vic 19: 1280x720p 50Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_04_1280x720p_60Hz: {return "vic 04: 1280x720p 60Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_32_1920x1080p_24Hz: {return "vic 32: 1920x1080p 24Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_33_1920x1080p_25Hz: {return "vic 33: 1920x1080p 25Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_34_1920x1080p_30Hz: {return "vic 34: 1920x1080p 30Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_31_1920x1080p_50Hz: {return "vic 31: 1920x1080p 50Hz frame packing";break;}
++ case FRAME_PACKING + TMDL_HDMITX_VFMT_16_1920x1080p_60Hz: {return "vic 16: 1920x1080p 60Hz frame packing";break;}
++ default : {return "unknown video format";break;}
++ }
++}
++#endif
++
++static char *tda_spy_audio_fmt(int fmt)
++{
++ switch (fmt)
++ {
++ case TMDL_HDMITX_AFMT_SPDIF: {return "SPDIF";break;}
++ case TMDL_HDMITX_AFMT_I2S: {return "I2S";break;}
++ case TMDL_HDMITX_AFMT_OBA: {return "OBA";break;}
++ case TMDL_HDMITX_AFMT_DST: {return "DST";break;}
++ case TMDL_HDMITX_AFMT_HBR: {return "HBR";break;}
++ default : {return "Unknown audio format";break;}
++ }
++}
++
++static char *tda_spy_audio_freq(int freq)
++{
++ switch (freq)
++ {
++ case TMDL_HDMITX_AFS_32K: {return "32k";break;}
++ case TMDL_HDMITX_AFS_44K: {return "44k";break;}
++ case TMDL_HDMITX_AFS_48K: {return "48k";break;}
++ case TMDL_HDMITX_AFS_88K: {return "88k";break;}
++ case TMDL_HDMITX_AFS_96K: {return "96k";break;}
++ case TMDL_HDMITX_AFS_176K: {return "176k";break;}
++ case TMDL_HDMITX_AFS_192K: {return "192k";break;}
++ default : {return "Unknown audio freq";break;}
++ }
++}
++
++static char *tda_spy_audio_i2c(int bits)
++{
++ switch (bits)
++ {
++ case TMDL_HDMITX_I2SQ_16BITS: {return "16 bits";break;}
++ case TMDL_HDMITX_I2SQ_32BITS: {return "32 bits";break;}
++ default : {return "Unknown audio i2c sampling";break;}
++ }
++}
++
++static char *tda_spy_audio_i2c4(int align)
++{
++ switch (align)
++ {
++ case TMDL_HDMITX_I2SFOR_PHILIPS_L: {return "Philips Left";break;}
++ case TMDL_HDMITX_I2SFOR_OTH_L: {return "other left";break;}
++ case TMDL_HDMITX_I2SFOR_OTH_R: {return "other right";break;}
++ default : {return "Unknown audio I2C alignement";break;}
++ }
++}
++
++static void tda_spy_audio(tmdlHdmiTxAudioInConfig_t *audio)
++{
++ printk(KERN_INFO "hdmitx audio input\n format:%d(%s) rate:%d(%s) i2c_format:%d(%s) i2c_qualif:%d(%s) dst_rate:%d channel:%d\n", \
++ audio->format, \
++ tda_spy_audio_fmt(audio->format), \
++ audio->rate, \
++ tda_spy_audio_freq(audio->rate), \
++ audio->i2sFormat, \
++ tda_spy_audio_i2c4(audio->i2sFormat), \
++ audio->i2sQualifier, \
++ tda_spy_audio_i2c(audio->i2sQualifier), \
++ audio->dstRate, \
++ audio->channelAllocation);
++ }
++
++
++static char *tda_ioctl(int io)
++{
++ switch (io)
++ {
++ case TDA_VERBOSE_ON_CMD: {return "TDA_VERBOSE_ON_CMD";break;}
++ case TDA_VERBOSE_OFF_CMD: {return "TDA_VERBOSE_OFF_CMD";break;}
++ case TDA_BYEBYE_CMD: {return "TDA_BYEBYE_CMD";break;}
++ case TDA_GET_SW_VERSION_CMD: {return "TDA_GET_SW_VERSION_CMD";break;}
++ case TDA_SET_POWER_CMD: {return "TDA_SET_POWER_CMD";break;}
++ case TDA_GET_POWER_CMD: {return "TDA_GET_POWER_CMD";break;}
++ case TDA_SETUP_CMD: {return "TDA_SETUP_CMD";break;}
++ case TDA_GET_SETUP_CMD: {return "TDA_GET_SETUP_CMD";break;}
++ case TDA_WAIT_EVENT_CMD: {return "TDA_WAIT_EVENT_CMD";break;}
++ case TDA_ENABLE_EVENT_CMD: {return "TDA_ENABLE_EVENT_CMD";break;}
++ case TDA_DISABLE_EVENT_CMD: {return "TDA_DISABLE_EVENT_CMD";break;}
++ case TDA_GET_VIDEO_SPEC_CMD: {return "TDA_GET_VIDEO_SPEC_CMD";break;}
++ case TDA_SET_INPUT_OUTPUT_CMD: {return "TDA_SET_INPUT_OUTPUT_CMD";break;}
++ case TDA_SET_AUDIO_INPUT_CMD: {return "TDA_SET_AUDIO_INPUT_CMD";break;}
++ case TDA_SET_VIDEO_INFOFRAME_CMD: {return "TDA_SET_VIDEO_INFOFRAME_CMD";break;}
++ case TDA_SET_AUDIO_INFOFRAME_CMD: {return "TDA_SET_AUDIO_INFOFRAME_CMD";break;}
++ case TDA_SET_ACP_CMD: {return "TDA_SET_ACP_CMD";break;}
++ case TDA_SET_GCP_CMD: {return "TDA_SET_GCP_CMD";break;}
++ case TDA_SET_ISRC1_CMD: {return "TDA_SET_ISRC1_CMD";break;}
++ case TDA_SET_ISRC2_CMD: {return "TDA_SET_ISRC2_CMD";break;}
++ case TDA_SET_MPS_INFOFRAME_CMD: {return "TDA_SET_MPS_INFOFRAME_CMD";break;}
++ case TDA_SET_SPD_INFOFRAME_CMD: {return "TDA_SET_SPD_INFOFRAME_CMD";break;}
++ case TDA_SET_VS_INFOFRAME_CMD: {return "TDA_SET_VS_INFOFRAME_CMD";break;}
++ case TDA_SET_AUDIO_MUTE_CMD: {return "TDA_SET_AUDIO_MUTE_CMD";break;}
++ case TDA_RESET_AUDIO_CTS_CMD: {return "TDA_RESET_AUDIO_CTS_CMD";break;}
++ case TDA_GET_EDID_STATUS_CMD: {return "TDA_GET_EDID_STATUS_CMD";break;}
++ case TDA_GET_EDID_AUDIO_CAPS_CMD: {return "TDA_GET_EDID_AUDIO_CAPS_CMD";break;}
++ case TDA_GET_EDID_VIDEO_CAPS_CMD: {return "TDA_GET_EDID_VIDEO_CAPS_CMD";break;}
++ case TDA_GET_EDID_VIDEO_PREF_CMD: {return "TDA_GET_EDID_VIDEO_PREF_CMD";break;}
++ case TDA_GET_EDID_SINK_TYPE_CMD: {return "TDA_GET_EDID_SINK_TYPE_CMD";break;}
++ case TDA_GET_EDID_SOURCE_ADDRESS_CMD: {return "TDA_GET_EDID_SOURCE_ADDRESS_CMD";break;}
++ case TDA_SET_GAMMUT_CMD: {return "TDA_SET_GAMMUT_CMD";break;}
++ case TDA_GET_EDID_DTD_CMD: {return "TDA_GET_EDID_DTD_CMD";break;}
++ case TDA_GET_EDID_MD_CMD: {return "TDA_GET_EDID_MD_CMD";break;}
++ case TDA_GET_EDID_TV_ASPECT_RATIO_CMD: {return "TDA_GET_EDID_TV_ASPECT_RATIO_CMD";break;}
++ case TDA_GET_EDID_LATENCY_CMD: {return "TDA_GET_EDID_LATENCY_CMD";break;}
++ case TDA_GET_HPD_STATUS_CMD: {return "TDA_GET_HPD_STATUS_CMD";break;}
++ default : {return "unknown";break;}
++ }
++
++
++}
++
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++/*
++ *
++ */
++static int tda_spy(int verbose)
++{
++ tda_instance *this=&our_instance;
++ int i,err=0;
++
++ if (!verbose) {
++ return err;
++ }
++
++ printk(KERN_INFO "\n<edid video caps>\n");
++ this->tda.edid_video_caps.max=EXAMPLE_MAX_SVD;
++ TRY(tmdlHdmiTxGetEdidVideoCaps(this->tda.instance, \
++ this->tda.edid_video_caps.desc, \
++ this->tda.edid_video_caps.max, \
++ &this->tda.edid_video_caps.written, \
++ &this->tda.edid_video_caps.flags));
++ printk(KERN_INFO "written:%d\n",this->tda.edid_video_caps.written);
++ printk(KERN_INFO "flags:0X%x\n",this->tda.edid_video_caps.flags);
++ if (this->tda.edid_video_caps.written > this->tda.edid_video_caps.max) {
++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \
++ this->tda.edid_video_caps.written, \
++ this->tda.edid_video_caps.max);
++ this->tda.edid_video_caps.written = this->tda.edid_video_caps.max;
++ }
++ for(i=0; i<this->tda.edid_video_caps.written;i++) {
++ printk(KERN_INFO "videoFormat: %s\n",tda_spy_vfmt(this->tda.edid_video_caps.desc[i].videoFormat));
++ printk(KERN_INFO "nativeVideoFormat:%s\n",(this->tda.edid_video_caps.desc[i].nativeVideoFormat?"yes":"no"));
++ }
++
++ printk(KERN_INFO "\n<edid video timings>\n");
++ TRY(tmdlHdmiTxGetEdidVideoPreferred(this->tda.instance, \
++ &this->tda.edid_video_timings));
++ printk(KERN_INFO "Pixel Clock/10 000:%d\n",this->tda.edid_video_timings.pixelClock);
++ printk(KERN_INFO "Horizontal Active Pixels:%d\n",this->tda.edid_video_timings.hActivePixels);
++ printk(KERN_INFO "Horizontal Blanking Pixels:%d\n",this->tda.edid_video_timings.hBlankPixels);
++ printk(KERN_INFO "Vertical Active Lines:%d\n",this->tda.edid_video_timings.vActiveLines);
++ printk(KERN_INFO "Vertical Blanking Lines:%d\n",this->tda.edid_video_timings.vBlankLines);
++ printk(KERN_INFO "Horizontal Sync Offset:%d\n",this->tda.edid_video_timings.hSyncOffset);
++ printk(KERN_INFO "Horiz. Sync Pulse Width:%d\n",this->tda.edid_video_timings.hSyncWidth);
++ printk(KERN_INFO "Vertical Sync Offset:%d\n",this->tda.edid_video_timings.vSyncOffset);
++ printk(KERN_INFO "Vertical Sync Pulse Width:%d\n",this->tda.edid_video_timings.vSyncWidth);
++ printk(KERN_INFO "Horizontal Image Size:%d\n",this->tda.edid_video_timings.hImageSize);
++ printk(KERN_INFO "Vertical Image Size:%d\n",this->tda.edid_video_timings.vImageSize);
++ printk(KERN_INFO "Horizontal Border:%d\n",this->tda.edid_video_timings.hBorderPixels);
++ printk(KERN_INFO "Vertical Border:%d\n",this->tda.edid_video_timings.vBorderPixels);
++ printk(KERN_INFO "Interlace/sync info:%x\n",this->tda.edid_video_timings.flags);
++
++ printk(KERN_INFO "\n<sink type>\n");
++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \
++ &this->tda.setio.sink));
++ printk(KERN_INFO "%s\n",tda_spy_sink(this->tda.setio.sink));
++ printk(KERN_INFO "\n<source address>\n");
++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \
++ &this->tda.src_address));
++ printk(KERN_INFO "%x\n",this->tda.src_address);
++ printk(KERN_INFO "\n<detailled timing descriptors>\n");
++ this->tda.edid_dtd.max=EXAMPLE_MAX_SVD;
++ TRY(tmdlHdmiTxGetEdidDetailledTimingDescriptors(this->tda.instance, \
++ this->tda.edid_dtd.desc, \
++ this->tda.edid_dtd.max, \
++ &this->tda.edid_dtd.written));
++ printk(KERN_INFO "Interlace/sync info:%x\n",this->tda.edid_dtd.desc[i].flags);
++ printk(KERN_INFO "written:%d\n",this->tda.edid_dtd.written);
++ if (this->tda.edid_dtd.written > this->tda.edid_dtd.max) {
++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \
++ this->tda.edid_dtd.written, \
++ this->tda.edid_dtd.max);
++ this->tda.edid_dtd.written = this->tda.edid_dtd.max;
++ }
++ for(i=0; i<this->tda.edid_dtd.written;i++) {
++ printk(KERN_INFO "Pixel Clock/10 000:%d\n",this->tda.edid_dtd.desc[i].pixelClock);
++ printk(KERN_INFO "Horizontal Active Pixels:%d\n",this->tda.edid_dtd.desc[i].hActivePixels);
++ printk(KERN_INFO "Horizontal Blanking Pixels:%d\n",this->tda.edid_dtd.desc[i].hBlankPixels);
++ printk(KERN_INFO "Vertical Active Lines:%d\n",this->tda.edid_dtd.desc[i].vActiveLines);
++ printk(KERN_INFO "Vertical Blanking Lines:%d\n",this->tda.edid_dtd.desc[i].vBlankLines);
++ printk(KERN_INFO "Horizontal Sync Offset:%d\n",this->tda.edid_dtd.desc[i].hSyncOffset);
++ printk(KERN_INFO "Horiz. Sync Pulse Width:%d\n",this->tda.edid_dtd.desc[i].hSyncWidth);
++ printk(KERN_INFO "Vertical Sync Offset:%d\n",this->tda.edid_dtd.desc[i].vSyncOffset);
++ printk(KERN_INFO "Vertical Sync Pulse Width:%d\n",this->tda.edid_dtd.desc[i].vSyncWidth);
++ printk(KERN_INFO "Horizontal Image Size:%d\n",this->tda.edid_dtd.desc[i].hImageSize);
++ printk(KERN_INFO "Vertical Image Size:%d\n",this->tda.edid_dtd.desc[i].vImageSize);
++ printk(KERN_INFO "Horizontal Border:%d\n",this->tda.edid_dtd.desc[i].hBorderPixels);
++ printk(KERN_INFO "Vertical Border:%d\n",this->tda.edid_dtd.desc[i].vBorderPixels);
++ }
++
++ printk(KERN_INFO "\n<monitor descriptors>\n");
++ this->tda.edid_md.max=EXAMPLE_MAX_SVD;
++ TRY(tmdlHdmiTxGetEdidMonitorDescriptors(this->tda.instance, \
++ this->tda.edid_md.desc1, \
++ this->tda.edid_md.desc2, \
++ this->tda.edid_md.other, \
++ this->tda.edid_md.max, \
++ &this->tda.edid_md.written));
++ printk(KERN_INFO "written:%d\n",this->tda.edid_md.written);
++ if (this->tda.edid_md.written > this->tda.edid_md.max) {
++ printk(KERN_ERR "get %d video caps but was waiting for %d\n", \
++ this->tda.edid_md.written, \
++ this->tda.edid_md.max);
++ this->tda.edid_md.written = this->tda.edid_md.max;
++ }
++ for(i=0; i<this->tda.edid_md.written;i++) {
++ if (this->tda.edid_md.desc1[i].descRecord) {
++ this->tda.edid_md.desc1[i].monitorName[EDID_MONITOR_DESCRIPTOR_SIZE-1]=0;
++ printk(KERN_INFO "Monitor name:%s\n",this->tda.edid_md.desc1[i].monitorName);
++ }
++ if (this->tda.edid_md.desc1[i].descRecord) {
++ printk(KERN_INFO "Min vertical rate in Hz:%d\n",this->tda.edid_md.desc2[i].minVerticalRate);
++ printk(KERN_INFO "Max vertical rate in Hz:%d\n",this->tda.edid_md.desc2[i].maxVerticalRate);
++ printk(KERN_INFO "Min horizontal rate in Hz:%d\n",this->tda.edid_md.desc2[i].minHorizontalRate);
++ printk(KERN_INFO "Max horizontal rate in Hz:%d\n",this->tda.edid_md.desc2[i].maxHorizontalRate);
++ printk(KERN_INFO "Max supported pixel clock rate in MHz:%d\n",this->tda.edid_md.desc2[i].maxSupportedPixelClk);
++ }
++ }
++
++ printk(KERN_INFO "\n<TV picture ratio>\n");
++ TRY(tmdlHdmiTxGetEdidTVPictureRatio(this->tda.instance, \
++ &this->tda.edid_tv_aspect_ratio));
++ printk(KERN_INFO "%s\n",tda_spy_aspect_ratio(this->tda.edid_tv_aspect_ratio));
++
++ printk(KERN_INFO "\n<latency info>\n");
++ TRY(tmdlHdmiTxGetEdidLatencyInfo(this->tda.instance, \
++ &this->tda.edid_latency));
++ if (this->tda.edid_latency.latency_available) {
++ printk(KERN_INFO "Edid video:%d\n",this->tda.edid_latency.Edidvideo_latency);
++ printk(KERN_INFO "Edid audio:%d\n",this->tda.edid_latency.Edidaudio_latency);
++ }
++ if (this->tda.edid_latency.Ilatency_available) {
++ printk(KERN_INFO "Edid Ivideo:%d\n",this->tda.edid_latency.EdidIvideo_latency);
++ printk(KERN_INFO "Edid Iaudio:%d\n",this->tda.edid_latency.EdidIaudio_latency);
++ }
++ TRY_DONE:
++ return err;
++}
++#endif
++
++/*
++ *
++ * PROCESSING
++ * ----------
++ * LEVEL 2
++ *
++ * -
++ *
++ */
++
++/*
++ * On HDCP
++ */
++void hdcp_on(tda_instance *this) {
++
++ int err=0;
++
++ if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED) { /* check HDCP is installed ... */
++ if (this->tda.hdcp_enable) { /* ... but requested ! */
++ TRY(tmdlHdmiTxSetHdcp(this->tda.instance,True)); /* switch if on */
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ /* hide video content until HDCP authentification is finished */
++ if (!this->tda.setup.simplayHd) {
++ TRY(tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE));
++ }
++#endif
++ }
++ }
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * Off HDCP
++ */
++void hdcp_off(tda_instance *this) {
++
++ int err=0;
++
++ if (this->tda.hdcp_status != HDCP_IS_NOT_INSTALLED) { /* check HDCP is installed ... */
++
++ if (this->tda.hdcp_enable) { /* but no more requested */
++ TRY(tmdlHdmiTxSetHdcp(this->tda.instance,False)); /* switch if off */
++ }
++ }
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * Run video
++ */
++void show_video(tda_instance *this) {
++
++ int err=0;
++
++ if (this->tda.rx_device_active) { /* check RxSens */
++ if (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE) { /* should be useless, but legacy... */
++ if (this->tda.power == tmPowerOn) { /* check CEC or DSS didn't switch it off */
++ if (this->tda.src_address != 0xFFFF) { /* check EDID has been received */
++ hdcp_off(this);
++ TRY(tmdlHdmiTxSetInputOutput(this->tda.instance, \
++ this->tda.setio.video_in, \
++ this->tda.setio.video_out, \
++ this->tda.setio.audio_in, \
++ this->tda.setio.sink));
++ hdcp_on(this);
++ /*
++ Mind that SetInputOutput disable the blue color matrix settings of tmdlHdmiTxSetBScreen ...
++ so put tmdlHdmiTxSetBScreen (or hdcp_on) always after
++ */
++ }
++ }
++ }
++ }
++
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * TDA interrupt polling
++ */
++static void interrupt_polling(struct work_struct *dummy)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ /* Tx part */
++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
++
++ /* CEC part */
++ if (this->driver.cec_callback) this->driver.cec_callback(dummy);
++
++ /* FIX : IT anti debounce */
++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
++
++ TRY_DONE:
++
++ /* setup next polling */
++#ifndef IRQ
++ mod_timer(&this->driver.no_irq_timer,jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 ));
++#endif
++
++ (void)0;
++}
++
++/*
++ * TDA interrupt polling
++ */
++static void hdcp_check(struct work_struct *dummy)
++{
++ int err=0;
++ tda_instance *this=&our_instance;
++ tmdlHdmiTxHdcpCheck_t hdcp_status;
++
++ down(&this->driver.sem);
++
++ if (this->tda.hdcp_status == HDCP_IS_NOT_INSTALLED) goto TRY_DONE;
++
++ TRY(tmdlHdmiTxHdcpCheck(this->tda.instance,HDCP_CHECK_EVERY_MS));
++ TRY(tmdlHdmiTxGetHdcpState(this->tda.instance, &hdcp_status));
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ if (this->tda.hdcp_status != hdcp_status) {
++ LOG(KERN_INFO,"HDCP status:%s\n",tda_spy_hdcp_status(hdcp_status));
++ this->tda.hdcp_status = hdcp_status;
++ }
++#endif
++#ifdef HDCP_TEST
++ /* TEST */
++ if (test++>500) {
++ test=0;
++ this->tda.hdcp_enable=1-this->tda.hdcp_enable;
++ printk("TEST hdcp:%d\n",this->tda.hdcp_enable);
++ if (this->tda.rx_device_active) { /* check RxSens */
++ if (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE) { /* should be useless, but legacy... */
++ if (this->tda.power == tmPowerOn) { /* check CEC didn't switch it off */
++ if (this->tda.src_address != 0xFFFF) { /* check EDID has been received */
++ hdcp_off(this);
++ hdcp_on(this);
++ }
++ }
++ }
++ }
++ }
++#endif
++
++ TRY_DONE:
++
++ /* setup next polling */
++ mod_timer(&this->driver.hdcp_check,jiffies + ( HDCP_CHECK_EVERY_MS * HZ / 1000 ));
++
++ up(&this->driver.sem);
++}
++
++void register_cec_interrupt(cec_callback_t fct)
++{
++ tda_instance *this=&our_instance;
++
++ this->driver.cec_callback = fct;
++}
++EXPORT_SYMBOL(register_cec_interrupt);
++
++void unregister_cec_interrupt(void)
++{
++ tda_instance *this=&our_instance;
++
++ this->driver.cec_callback = NULL;
++}
++EXPORT_SYMBOL(unregister_cec_interrupt);
++
++static DECLARE_WORK(wq_irq, interrupt_polling);
++void polling_timeout(unsigned long arg)
++{
++ /* derefered because ATOMIC context of timer does not support I2C_transfert */
++ schedule_work(&wq_irq);
++}
++
++static DECLARE_WORK(wq_hdcp, hdcp_check);
++void hdcp_check_timeout(unsigned long arg)
++{
++ /* derefered because ATOMIC context of timer does not support I2C_transfert */
++ schedule_work(&wq_hdcp);
++}
++
++#ifdef IRQ
++/*
++ * TDA irq
++ */
++static irqreturn_t tda_irq(int irq, void *_udc)
++{
++
++ /* do it now */
++ schedule_work(&wq_irq);
++
++ return IRQ_HANDLED;
++}
++#endif
++
++/*
++ * TDA callback
++ */
++static void eventCallbackTx(tmdlHdmiTxEvent_t event)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++ unsigned short new_addr;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ tda_hdcp_fail hdcp_fail;
++#endif
++
++ this->tda.event=event;
++ if (TMDL_HDMITX_HDCP_INACTIVE != event) {
++ printk(KERN_INFO "hdmi %s\n",tda_spy_event(event));
++ }
++
++ switch (event) {
++ case TMDL_HDMITX_EDID_RECEIVED:
++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \
++ &new_addr));
++ LOG(KERN_INFO,"phy.@:%x\n",new_addr);
++ /* if (this->tda.src_address == new_addr) { */
++ /* break; */
++ /* } */
++ this->tda.src_address = new_addr;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ tda_spy(this->param.verbose>1);
++#endif
++ /*
++ Customer may add stuff to analyse EDID (see tda_spy())
++ and select automatically some video/audio settings.
++ By default, let go on with next case and activate
++ default video/audio settings with tmdlHdmiTxSetInputOutput()
++ */
++
++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \
++ &this->tda.setio.sink));
++ if (TMDL_HDMITX_SINK_HDMI != this->tda.setio.sink) {
++ printk(KERN_INFO "/!\\ CAUTION /!\\ sink is not HDMI but %s\n",tda_spy_sink(this->tda.setio.sink));
++ }
++
++ msleep(100);
++ /*
++ /!\ WARNING /! \
++ the core driver does not send any HPD nor RXSENS when HDMI was plugged after at boot time
++ and only EDID_RECEIVED is send, so rx_device_active shall be forced now.
++ Do not skip the next case nor add any break here please
++ */
++ case TMDL_HDMITX_RX_DEVICE_ACTIVE: /* TV is ready to receive */
++ this->tda.rx_device_active = 1;
++ show_video(this);
++ break;
++ case TMDL_HDMITX_RX_DEVICE_INACTIVE: /* TV is ignoring the source */
++ this->tda.rx_device_active = 0;
++ break;
++ case TMDL_HDMITX_HPD_ACTIVE: /* HDMI is so funny u can get RxSens without being plugged !!! */
++ this->tda.hot_plug_detect = TMDL_HDMITX_HOTPLUG_ACTIVE;
++ show_video(this);
++ break;
++ case TMDL_HDMITX_HPD_INACTIVE: /* unplug */
++ this->tda.hot_plug_detect = TMDL_HDMITX_HOTPLUG_INACTIVE;
++ this->tda.src_address = 0xFFFF;
++ break;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ case TMDL_HDMITX_HDCP_INACTIVE: /* HDCP drops off */
++ tmdlHdmiTxGetHdcpFailStatus(this->tda.instance, \
++ &hdcp_fail, \
++ &this->tda.hdcp_raw_status);
++ if (this->tda.hdcp_fail != hdcp_fail) {
++ if (this->tda.hdcp_fail) {
++ LOG(KERN_INFO,"%s (%d)\n",tda_spy_hsdc_fail_status(this->tda.hdcp_fail),this->tda.hdcp_raw_status);
++ }
++ this->tda.hdcp_fail = hdcp_fail;
++ tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE);
++ }
++ break;
++ case TMDL_HDMITX_RX_KEYS_RECEIVED: /* end of HDCP authentification */
++ if (!this->tda.setup.simplayHd) {
++ tmdlHdmiTxRemoveBScreen(this->tda.instance);
++ }
++ break;
++#endif
++ default:
++ break;
++ }
++
++ this->driver.poll_done=true;
++ wake_up_interruptible(&this->driver.wait);
++
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * hdmi Tx init
++ */
++static int hdmi_tx_init(tda_instance *this)
++{
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++
++ /*Initialize HDMI Transmiter*/
++ TRY(tmdlHdmiTxOpen(&this->tda.instance));
++ /* Register the HDMI TX events callbacks */
++ TRY(tmdlHdmiTxRegisterCallbacks(this->tda.instance,(ptmdlHdmiTxCallback_t)eventCallbackTx));
++ /* EnableEvent, all by default */
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HDCP_ACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HDCP_INACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HPD_ACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_HPD_INACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_KEYS_RECEIVED));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_DEVICE_ACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_RX_DEVICE_INACTIVE));
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,TMDL_HDMITX_EDID_RECEIVED));
++
++ /* Size of the application EDID buffer */
++ this->tda.setup.edidBufferSize=EDID_BLOCK_COUNT * EDID_BLOCK_SIZE;
++ /* Buffer to store the application EDID data */
++ this->tda.setup.pEdidBuffer=this->tda.raw_edid;
++ /* To Enable/disable repeater feature, nor relevant here */
++ this->tda.setup.repeaterEnable=false;
++ /* To enable/disable simplayHD feature: blue screen when not authenticated */
++#ifdef SIMPLAYHD
++ this->tda.setup.simplayHd=(this->tda.hdcp_enable?true:false);
++#else
++ this->tda.setup.simplayHd=false;
++#endif
++
++ /* Provides HDMI TX instance configuration */
++ TRY(tmdlHdmiTxInstanceSetup(this->tda.instance,&this->tda.setup));
++ /* Get IC version */
++ TRY(tmdlHdmiTxGetCapabilities(&this->tda.capabilities));
++
++ /* Main settings */
++ this->tda.setio.video_out.mode = TMDL_HDMITX_VOUTMODE_RGB444;
++ this->tda.setio.video_out.colorDepth = TMDL_HDMITX_COLORDEPTH_24;
++#ifdef TMFL_TDA19989
++ this->tda.setio.video_out.dviVqr = TMDL_HDMITX_VQR_DEFAULT; /* Use HDMI rules for DVI output */
++#endif
++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz; */
++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_60Hz; */
++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_72Hz; */
++ // this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz;
++ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_19_1280x720p_50Hz; */
++ this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
++
++ this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_RGB444;
++ /* this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_CCIR656; */
++ /* this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_YUV422; */
++ this->tda.setio.video_in.format = this->tda.setio.video_out.format;
++ this->tda.setio.video_in.pixelRate = TMDL_HDMITX_PIXRATE_SINGLE;
++ this->tda.setio.video_in.syncSource = TMDL_HDMITX_SYNCSRC_EXT_VS; /* we use HS,VS as synchronisation source */
++
++ this->tda.setio.audio_in.format = TMDL_HDMITX_AFMT_I2S; /* audio I2S is coming in */
++ this->tda.setio.audio_in.rate = TMDL_HDMITX_AFS_48K; /* audio sampling rate */
++ this->tda.setio.audio_in.i2sFormat = TMDL_HDMITX_I2SFOR_PHILIPS_L; /* I2S format of the audio input */
++ this->tda.setio.audio_in.i2sQualifier = TMDL_HDMITX_I2SQ_32BITS; /* we use a 32 bits bus */
++ this->tda.setio.audio_in.dstRate = TMDL_HDMITX_DSTRATE_SINGLE; /* not relevant here */
++ this->tda.setio.audio_in.channelAllocation = 0; /* audio channel allocation (Ref to CEA-861D p85) */
++ /* set default channel status */
++ this->tda.setio.audio_in.channelStatus.PcmIdentification = TMDL_HDMITX_AUDIO_DATA_PCM;
++ this->tda.setio.audio_in.channelStatus.CopyrightInfo = TMDL_HDMITX_CSCOPYRIGHT_PROTECTED;
++ this->tda.setio.audio_in.channelStatus.FormatInfo = TMDL_HDMITX_CSFI_PCM_2CHAN_NO_PRE;
++ this->tda.setio.audio_in.channelStatus.categoryCode = 0x00;
++ this->tda.setio.audio_in.channelStatus.clockAccuracy = TMDL_HDMITX_CSCLK_LEVEL_II;
++ this->tda.setio.audio_in.channelStatus.maxWordLength = TMDL_HDMITX_CSMAX_LENGTH_20;
++ this->tda.setio.audio_in.channelStatus.wordLength = TMDL_HDMITX_CSWORD_DEFAULT;
++ this->tda.setio.audio_in.channelStatus.origSampleFreq = TMDL_HDMITX_CSOFREQ_NOT_INDICATED;
++
++
++ this->tda.setio.sink = TMDL_HDMITX_SINK_HDMI; /* skip edid reading */
++ /* this->tda.src_address = 0x1000; /\* debug *\/ */
++ this->tda.src_address = NO_PHY_ADDR; /* it's unref */
++
++ TRY_DONE:
++ return err;
++}
++
++void reset_hdmi(int hdcp_module)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ down(&this->driver.sem);
++
++ /* PATCH because of SetPowerState that calls SetHdcp that has just been removed by nwolc :( */
++ if (hdcp_module==2) {
++ tmdlHdmiTxSetHdcp(this->tda.instance,0);
++ goto TRY_DONE;
++ }
++
++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,tmPowerStandby));
++ tmdlHdmiTxClose(this->tda.instance);
++
++ /* reset */
++ this->tda.hdcp_enable = (hdcp_module?1:0);
++ hdmi_tx_init(this);
++ /* recover previous power state */
++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power));
++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect); /* check if activ for timer */
++#ifndef USER_SET_INPUT_OUTPUT
++ show_video(this);
++#endif
++
++ /* wake up or shut down hdcp checking */
++ if (hdcp_module) {
++ this->driver.hdcp_check.expires = jiffies + ( HDCP_CHECK_EVERY_MS * HZ / 1000 );
++ add_timer(&this->driver.hdcp_check);
++ this->tda.hdcp_status = TMDL_HDMITX_HDCP_CHECK_NOT_STARTED;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ tmdlHdmiTxSetBScreen(this->tda.instance,TMDL_HDMITX_PATTERN_BLUE);
++#endif
++ }
++ else {
++ del_timer(&this->driver.hdcp_check);
++ this->tda.hdcp_status = HDCP_IS_NOT_INSTALLED;
++ }
++
++ TRY_DONE:
++ up(&this->driver.sem);
++}
++EXPORT_SYMBOL(reset_hdmi);
++
++/*
++ *
++ */
++short edid_phy_addr(void)
++{
++ tda_instance *this=&our_instance;
++
++ return this->tda.src_address;
++}
++EXPORT_SYMBOL(edid_phy_addr);
++
++/*
++ *
++ */
++tda_power get_hdmi_status(void)
++{
++ tda_instance *this=&our_instance;
++
++ return this->tda.power;
++}
++EXPORT_SYMBOL(get_hdmi_status);
++
++/*
++ *
++ */
++tda_power get_hpd_status(void)
++{
++ tda_instance *this=&our_instance;
++
++ return (this->tda.hot_plug_detect == TMDL_HDMITX_HOTPLUG_ACTIVE);
++}
++EXPORT_SYMBOL(get_hpd_status);
++
++/*
++ *
++ */
++int edid_received(void)
++{
++ tda_instance *this=&our_instance;
++
++ return (this->tda.event == TMDL_HDMITX_EDID_RECEIVED);
++}
++EXPORT_SYMBOL(edid_received);
++
++/*
++ *
++ */
++int hdmi_enable(void)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++ down(&this->driver.sem);
++
++ this->driver.omap_dss_hdmi_panel = true;
++
++ this->tda.power = tmPowerOn;
++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power));
++ if (err==TM_ERR_NO_RESOURCES) {
++ LOG(KERN_INFO,"Busy...\n");
++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
++ TRY(tmdlHdmiTxHandleInterrupt(this->tda.instance));
++ }
++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect);
++ show_video(this);
++
++ TRY_DONE:
++ up(&this->driver.sem);
++ return err;
++}
++EXPORT_SYMBOL(hdmi_enable);
++
++/*
++ *
++ */
++int hdmi_disable(int event_tracking)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++ down(&this->driver.sem);
++ this->tda.power = (event_tracking?tmPowerSuspend:tmPowerStandby);
++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power));
++
++ TRY_DONE:
++ this->driver.omap_dss_hdmi_panel = false;
++ up(&this->driver.sem);
++ return err;
++}
++EXPORT_SYMBOL(hdmi_disable);
++
++/*
++ *
++ * ENTRY POINTS
++ * ------------
++ * LEVEL 3
++ *
++ * -
++ *
++ */
++
++#ifdef ANDROID_DSS
++/*
++ * DSS driver :: probe
++ */
++static int hdmi_panel_probe(struct omap_dss_device *dssdev)
++{
++ tda_instance *this=&our_instance;
++
++ LOG(KERN_INFO," called\n");
++
++ /* 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, */
++
++ dssdev->panel.config = OMAP_DSS_LCD_ONOFF | OMAP_DSS_LCD_IPC | \
++ OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS;
++ dssdev->panel.timings = video_1280x720at50Hz_panel_timings;
++ (void)video_1280x720at60Hz_panel_timings;
++ (void)video_720x480at60Hz_panel_timings;
++ (void)video_1280x720at50Hz_panel_timings;
++ (void)video_800x480at60Hz_panel_timings;
++ (void)video_1280x720at50Hz_panel_timings;
++ (void)video_1920x1080at50Hz_panel_timings;
++ (void)video_640x480at72Hz_panel_timings;
++ (void)video_640x480at60Hz_panel_timings;
++
++ return 0;
++}
++
++/*
++ * DSS driver :: enable
++ */
++static void hdmi_panel_remove(struct omap_dss_device *dssdev)
++{
++}
++
++/*
++ * DSS driver :: enable
++ */
++static int hdmi_panel_enable(struct omap_dss_device *dssdev)
++{
++ int r = 0;
++
++ if (dssdev->platform_enable)
++ r = dssdev->platform_enable(dssdev);
++
++ if (r)
++ goto ERROR0;
++
++ r = hdmi_enable();
++ if (r)
++ goto ERROR0;
++ /* wait couple of vsyncs until enabling the LCD */
++ msleep(50);
++
++ return 0;
++ ERROR0:
++ return r;
++}
++
++/*
++ * DSS driver :: disable
++ */
++static void hdmi_panel_disable(struct omap_dss_device *dssdev)
++{
++ hdmi_disable(1); /* keep HPD int actif */
++
++ /* wait couple of vsyncs until enabling the hdmi */
++ msleep(50);
++
++ if (dssdev->platform_disable)
++ dssdev->platform_disable(dssdev);
++}
++
++/*
++ * DSS driver :: suspend
++ */
++static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
++{
++ hdmi_panel_disable(dssdev);
++ return 0;
++}
++
++/*
++ * DSS driver :: resume
++ */
++static int hdmi_panel_resume(struct omap_dss_device *dssdev)
++{
++ return hdmi_panel_enable(dssdev);
++}
++
++/*
++ * DSS driver (frontend with omapzoom)
++ * -----------------------------------
++ */
++static struct omap_dss_driver hdmi_driver = {
++ .probe = hdmi_panel_probe,
++ .remove = hdmi_panel_remove,
++ .enable = hdmi_panel_enable,
++ .disable = hdmi_panel_disable,
++ .suspend = hdmi_panel_suspend,
++ .resume = hdmi_panel_resume,
++ .driver = {
++ .name = "hdmi_panel",
++ .owner = THIS_MODULE,
++ }
++};
++#endif
++
++/*
++ * ioctl driver :: opening
++ */
++
++static int this_cdev_open(struct inode *pInode, struct file *pFile)
++{
++ tda_instance *this;
++ int minor=iminor(pInode);
++
++ if(minor >= MAX_MINOR) {
++ printk(KERN_ERR "hdmitx:%s:only one tda can be open\n",__func__);
++ return -EINVAL;
++ }
++
++ if ((pFile->private_data != NULL) && (pFile->private_data != &our_instance)) {
++ printk(KERN_ERR "hdmitx:%s:pFile missmatch\n",__func__);
++ }
++ this = pFile->private_data = &our_instance;
++ down(&this->driver.sem);
++
++ LOG(KERN_INFO,"major:%d minor:%d user:%d\n", imajor(pInode), iminor(pInode), this->driver.user_counter);
++
++ if ((this->driver.user_counter++) && (this->driver.minor == minor)) {
++ /* init already done */
++ up(&this->driver.sem);
++ return 0;
++ }
++ this->driver.minor = minor;
++
++
++ up(&this->driver.sem);
++ return 0;
++}
++
++/*
++ * ioctl driver :: ioctl
++ */
++static int this_cdev_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
++{
++ tda_instance* this = pFile->private_data;
++ int err=0;
++
++ LOG(KERN_INFO,":%s\n",tda_ioctl(_IOC_NR(cmd)));
++
++ BUG_ON(this->driver.minor!=iminor(pInode));
++ if (_IOC_TYPE(cmd) != TDA_IOCTL_BASE) {
++ printk(KERN_INFO "hdmitx:%s:unknown ioctl type: %x\n",__func__,_IOC_TYPE(cmd));
++ return -ENOIOCTLCMD;
++ }
++
++ if (_IOC_DIR(cmd) & _IOC_READ)
++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)) || !arg;
++ else if (_IOC_DIR(cmd) & _IOC_WRITE)
++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)) || !arg;
++ if (err) {
++ printk(KERN_ERR "hdmitx:%s:argument access denied (check address vs value)\n",__func__);
++ printk(KERN_ERR "_IOC_DIR:%d arg:%lx\n",_IOC_DIR(cmd),arg);
++ return -EFAULT;
++ }
++
++ down(&this->driver.sem);
++
++ /* Check DevLib consistancy here */
++
++ switch ( _IOC_NR(cmd) )
++ {
++ case TDA_VERBOSE_ON_CMD:
++ {
++ this->param.verbose=1;
++ printk(KERN_INFO "hdmitx:verbose on\n");
++ break;
++ }
++
++ case TDA_VERBOSE_OFF_CMD:
++ {
++ printk(KERN_INFO "hdmitx:verbose off\n");
++ this->param.verbose=0;
++ break;
++ }
++
++ case TDA_BYEBYE_CMD:
++ {
++ LOG(KERN_INFO,"release event handeling request\n");
++ this->tda.event=RELEASE;
++ this->driver.poll_done = true;
++ wake_up_interruptible(&this->driver.wait);
++ break;
++ }
++
++ case TDA_GET_SW_VERSION_CMD:
++ {
++ TRY(tmdlHdmiTxGetSWVersion(&this->tda.version));
++ BUG_ON(copy_to_user((tda_version*)arg,&this->tda.version,sizeof(tda_version)) != 0);
++ break;
++ }
++
++ case TDA_SET_POWER_CMD:
++ {
++ if (this->driver.omap_dss_hdmi_panel) {
++ /* DSS uses HDMI panel => do not switch the power through the ioctl, this will be done be DSS */
++ }
++ else {
++ BUG_ON(copy_from_user(&this->tda.power,(tda_power*)arg,sizeof(tda_power)) != 0);
++ TRY(tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power));
++ }
++ break;
++ }
++
++ case TDA_GET_POWER_CMD:
++ {
++ TRY(tmdlHdmiTxGetPowerState(this->tda.instance, \
++ &this->tda.power));
++ BUG_ON(copy_to_user((tda_power*)arg,&this->tda.power,sizeof(tda_power)) != 0);
++ break;
++ }
++
++ case TDA_SETUP_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.setup,(tda_setup_info*)arg,sizeof(tda_setup_info)) != 0);
++ TRY(tmdlHdmiTxInstanceSetup(this->tda.instance, \
++ &this->tda.setup));
++ break;
++ }
++
++ case TDA_GET_SETUP_CMD:
++ {
++ TRY(tmdlHdmiTxGetInstanceSetup(this->tda.instance, \
++ &this->tda.setup));
++ BUG_ON(copy_to_user((tda_setup*)arg,&this->tda.setup,sizeof(tda_setup)) != 0);
++ break;
++ }
++
++ case TDA_WAIT_EVENT_CMD:
++ {
++ this->driver.poll_done = false;
++ up(&this->driver.sem);
++ if (wait_event_interruptible(this->driver.wait,this->driver.poll_done)) return -ERESTARTSYS;
++ down(&this->driver.sem);
++ BUG_ON(copy_to_user((tda_event*)arg,&this->tda.event,sizeof(tda_event)) != 0);
++ break;
++ }
++
++ case TDA_ENABLE_EVENT_CMD:
++ {
++ tmdlHdmiTxEvent_t event;
++ BUG_ON(copy_from_user(&event,(tmdlHdmiTxEvent_t*)arg,sizeof(tmdlHdmiTxEvent_t)) != 0);
++ TRY(tmdlHdmiTxEnableEvent(this->tda.instance,event));
++ break;
++ }
++
++ case TDA_DISABLE_EVENT_CMD:
++ {
++ tmdlHdmiTxEvent_t event;
++ BUG_ON(copy_from_user(&event,(tmdlHdmiTxEvent_t*)arg,sizeof(tmdlHdmiTxEvent_t)) != 0);
++ TRY(tmdlHdmiTxDisableEvent(this->tda.instance,event));
++ break;
++ }
++
++ case TDA_GET_VIDEO_SPEC_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.video_fmt,(tda_video_format*)arg,sizeof(tda_video_format)) != 0);
++ TRY(tmdlHdmiTxGetVideoFormatSpecs(this->tda.instance, \
++ this->tda.video_fmt.id, \
++ &this->tda.video_fmt.spec));
++ BUG_ON(copy_to_user((tda_video_format*)arg,&this->tda.video_fmt,sizeof(tda_video_format)) != 0);
++ break;
++ }
++
++ case TDA_SET_INPUT_OUTPUT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.setio,(tda_set_in_out*)arg,sizeof(tda_set_in_out)) != 0);
++
++ /* TRY(tmdlHdmiTxSetInputOutput(this->tda.instance, \ */
++ /* this->tda.setio.video_in, \ */
++ /* this->tda.setio.video_out, \ */
++ /* this->tda.setio.audio_in, \ */
++ /* this->tda.setio.sink)); */
++ break;
++ }
++
++ case TDA_SET_AUDIO_INPUT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.setio.audio_in,(tda_set_audio_in*)arg,sizeof(tda_set_audio_in)) != 0);
++ TRY(tmdlHdmiTxSetAudioInput(this->tda.instance, \
++ this->tda.setio.audio_in, \
++ this->tda.setio.sink));
++ break;
++ }
++
++ case TDA_SET_VIDEO_INFOFRAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.video_infoframe,(tda_video_infoframe*)arg,sizeof(tda_video_infoframe)) != 0);
++ TRY(tmdlHdmiTxSetVideoInfoframe(this->tda.instance, \
++ this->tda.video_infoframe.enable, \
++ &this->tda.video_infoframe.data));
++ break;
++ }
++
++ case TDA_SET_AUDIO_INFOFRAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.audio_infoframe,(tda_audio_infoframe*)arg,sizeof(tda_audio_infoframe)) != 0);
++ TRY(tmdlHdmiTxSetAudioInfoframe(this->tda.instance, \
++ this->tda.audio_infoframe.enable, \
++ &this->tda.audio_infoframe.data));
++ break;
++ }
++
++ case TDA_SET_ACP_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.acp,(tda_acp*)arg,sizeof(tda_acp)) != 0);
++ TRY(tmdlHdmiTxSetACPPacket(this->tda.instance, \
++ this->tda.acp.enable, \
++ &this->tda.acp.data));
++ break;
++ }
++
++ case TDA_SET_GCP_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.gcp,(tda_gcp*)arg,sizeof(tda_gcp)) != 0);
++ TRY(tmdlHdmiTxSetGeneralControlPacket(this->tda.instance, \
++ this->tda.gcp.enable, \
++ &this->tda.gcp.data));
++ break;
++ }
++
++ case TDA_SET_ISRC1_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.isrc1,(tda_isrc1*)arg,sizeof(tda_isrc1)) != 0);
++ TRY(tmdlHdmiTxSetISRC1Packet(this->tda.instance, \
++ this->tda.isrc1.enable, \
++ &this->tda.isrc1.data));
++ break;
++ }
++
++ case TDA_SET_MPS_INFOFRAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.mps_infoframe,(tda_mps_infoframe*)arg,sizeof(tda_mps_infoframe)) != 0);
++ TRY(tmdlHdmiTxSetMPSInfoframe(this->tda.instance, \
++ this->tda.mps_infoframe.enable, \
++ &this->tda.mps_infoframe.data));
++ break;
++ }
++
++ case TDA_SET_SPD_INFOFRAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.spd_infoframe,(tda_spd_infoframe*)arg,sizeof(tda_spd_infoframe)) != 0);
++ TRY(tmdlHdmiTxSetSpdInfoframe(this->tda.instance, \
++ this->tda.spd_infoframe.enable, \
++ &this->tda.spd_infoframe.data));
++ break;
++ }
++
++ case TDA_SET_VS_INFOFRAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.vs_infoframe,(tda_vs_infoframe*)arg,sizeof(tda_vs_infoframe)) != 0);
++ TRY(tmdlHdmiTxSetVsInfoframe(this->tda.instance, \
++ this->tda.vs_infoframe.enable, \
++ &this->tda.vs_infoframe.data));
++ break;
++ }
++
++ case TDA_SET_AUDIO_MUTE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.audio_mute,(bool*)arg,sizeof(bool)) != 0);
++ TRY(tmdlHdmiTxSetAudioMute(this->tda.instance, \
++ this->tda.audio_mute));
++ break;
++ }
++
++ case TDA_RESET_AUDIO_CTS_CMD:
++ {
++ TRY(tmdlHdmiTxResetAudioCts(this->tda.instance));
++ break;
++ }
++
++ case TDA_GET_EDID_STATUS_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidStatus(this->tda.instance, \
++ &this->tda.edid.status, \
++ &this->tda.edid.block_count));
++ BUG_ON(copy_to_user((tda_edid*)arg,&this->tda.edid,sizeof(tda_edid)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_AUDIO_CAPS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.edid_audio_caps,(tda_edid_audio_caps*)arg,sizeof(tda_edid_audio_caps)) != 0);
++ TRY(tmdlHdmiTxGetEdidAudioCaps(this->tda.instance, \
++ this->tda.edid_audio_caps.desc, \
++ this->tda.edid_audio_caps.max, \
++ &this->tda.edid_audio_caps.written, \
++ &this->tda.edid_audio_caps.flags));
++ BUG_ON(copy_to_user((tda_edid_audio_caps*)arg,&this->tda.edid_audio_caps,sizeof(tda_edid_audio_caps)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_VIDEO_CAPS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.edid_video_caps,(tda_edid_video_caps*)arg,sizeof(tda_edid_video_caps)) != 0);
++ TRY(tmdlHdmiTxGetEdidVideoCaps(this->tda.instance, \
++ this->tda.edid_video_caps.desc, \
++ this->tda.edid_video_caps.max, \
++ &this->tda.edid_video_caps.written, \
++ &this->tda.edid_video_caps.flags));
++ BUG_ON(copy_to_user((tda_edid_video_caps*)arg,&this->tda.edid_video_caps,sizeof(tda_edid_video_caps)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_VIDEO_PREF_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidVideoPreferred(this->tda.instance, \
++ &this->tda.edid_video_timings));
++ BUG_ON(copy_to_user((tda_edid_video_timings*)arg,&this->tda.edid_video_timings,sizeof(tda_edid_video_timings)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_SINK_TYPE_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidSinkType(this->tda.instance, \
++ &this->tda.setio.sink));
++ BUG_ON(copy_to_user((tda_sink*)arg,&this->tda.setio.sink,sizeof(tda_sink)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_SOURCE_ADDRESS_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidSourceAddress(this->tda.instance, \
++ &this->tda.src_address));
++ BUG_ON(copy_to_user((unsigned short*)arg,&this->tda.src_address,sizeof(unsigned short)) != 0);
++ break;
++ }
++
++ case TDA_SET_GAMMUT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.gammut,(tda_gammut*)arg,sizeof(tda_gammut)) != 0);
++ TRY(tmdlHdmiTxSetGamutPacket(this->tda.instance, \
++ this->tda.gammut.enable, \
++ &this->tda.gammut.data));
++ break;
++ }
++
++ case TDA_GET_EDID_DTD_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.edid_dtd,(tda_edid_dtd*)arg,sizeof(tda_edid_dtd)) != 0);
++ TRY(tmdlHdmiTxGetEdidDetailledTimingDescriptors(this->tda.instance, \
++ this->tda.edid_dtd.desc, \
++ this->tda.edid_dtd.max, \
++ &this->tda.edid_dtd.written));
++ BUG_ON(copy_to_user((tda_edid_dtd*)arg,&this->tda.edid_dtd,sizeof(tda_edid_dtd)) != 0);
++ break;
++ }
++
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ case TDA_GET_EDID_MD_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.edid_md,(tda_edid_md*)arg,sizeof(tda_edid_md)) != 0);
++ TRY(tmdlHdmiTxGetEdidMonitorDescriptors(this->tda.instance, \
++ this->tda.edid_md.desc1, \
++ this->tda.edid_md.desc2, \
++ this->tda.edid_md.other, \
++ this->tda.edid_md.max, \
++ &this->tda.edid_md.written));
++ BUG_ON(copy_to_user((tda_edid_md*)arg,&this->tda.edid_md,sizeof(tda_edid_md)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_TV_ASPECT_RATIO_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidTVPictureRatio(this->tda.instance, \
++ &this->tda.edid_tv_aspect_ratio));
++ BUG_ON(copy_to_user((tda_edid_tv_aspect_ratio*)arg,&this->tda.edid_tv_aspect_ratio,sizeof(tda_edid_tv_aspect_ratio)) != 0);
++ break;
++ }
++
++ case TDA_GET_EDID_LATENCY_CMD:
++ {
++ TRY(tmdlHdmiTxGetEdidLatencyInfo(this->tda.instance, \
++ &this->tda.edid_latency));
++ BUG_ON(copy_to_user((tda_edid_latency*)arg,&this->tda.edid_latency,sizeof(tda_edid_latency)) != 0);
++ break;
++ }
++
++ case TDA_SET_HDCP_CMD:
++ {
++ BUG_ON(copy_from_user(&this->tda.hdcp_enable,(bool*)arg,sizeof(bool)) != 0);
++ break;
++ }
++
++ case TDA_GET_HPD_STATUS_CMD:
++ {
++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect);
++ BUG_ON(copy_to_user((tmdlHdmiTxHotPlug_t*)arg,&this->tda.hot_plug_detect,sizeof(tmdlHdmiTxHotPlug_t)) != 0);
++ break;
++ }
++ case TDA_GET_HDCP_STATUS_CMD:
++ {
++ BUG_ON(copy_to_user((tda_edid_latency*)arg,&this->tda.hdcp_status,sizeof(tda_hdcp_status)) != 0);
++ break;
++ }
++#endif
++
++ default:
++ {
++ /* unrecognized ioctl */
++ printk(KERN_INFO "hdmitx:%s:unknown ioctl number: %x\n",__func__,cmd);
++ up(&this->driver.sem);
++ return -ENOIOCTLCMD;
++ }
++ }
++
++ TRY_DONE:
++ up(&this->driver.sem);
++ return err;
++}
++
++/*
++ * ioctl driver :: releasing
++ */
++static int this_cdev_release(struct inode *pInode, struct file *pFile)
++{
++ tda_instance* this = pFile->private_data;
++ int minor = iminor(pInode);
++
++ LOG(KERN_INFO,"called\n");
++
++ if(minor >= MAX_MINOR) {
++ LOG(KERN_ERR,"minor too big!\n");
++ return -EINVAL;
++ }
++
++ BUG_ON(this->driver.minor!=iminor(pInode));
++ down(&this->driver.sem);
++
++ this->driver.user_counter--;
++ if(this->driver.user_counter == 0) {
++ pFile->private_data = NULL;
++ }
++ else {
++ LOG(KERN_INFO,"Still %d users pending\n",this->driver.user_counter);
++ }
++
++ up(&this->driver.sem);
++ return 0;
++}
++
++/*
++ * I2C client :: creation
++ */
++static int this_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ printk(KERN_ERR "i2c probe called.....\n");
++
++ LOG(KERN_INFO,"called\n");
++
++ /*
++ I2C setup
++ */
++ if (this->driver.i2c_client) {
++ dev_err(&this->driver.i2c_client->dev, "<%s> HDMI Device already created \n",
++ __func__);
++ return -ENODEV;
++ }
++
++ this->driver.i2c_client = client;
++ i2c_set_clientdata(client, this);
++
++ /* I2C ok, then let's startup TDA */
++ err = hdmi_tx_init(this);
++ if (err) goto i2c_out;
++ this->tda.hdcp_enable = 0;
++ /* Standby the HDMI TX instance : this is mandatory for TDA boot up sequence, do not change it */
++ this->tda.power = tmPowerStandby; /* power start sequence phase 1, see phase 2 */
++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power);
++ /* update HPD */
++ tmdlHdmiTxGetHPDStatus(this->tda.instance,&this->tda.hot_plug_detect);
++
++#ifdef ANDROID_DSS
++ /* probe DSS */
++ err = omap_dss_register_driver(&hdmi_driver);
++#endif
++ if (err) goto i2c_tx_out;
++
++ /* prepare event */
++ this->driver.poll_done = true; /* currently idle */
++ init_waitqueue_head(&this->driver.wait);
++
++#ifdef IRQ
++ if (client->irq > 0) {
++ this->driver.gpio = irq_to_gpio(client->irq);
++ } else {
++ this->driver.gpio = TDA_IRQ_CALIB;
++ }
++
++ /* FRO calibration */
++ err=gpio_request(this->driver.gpio, "tda998x calibration");
++ if (err < 0) {
++ printk(KERN_ERR "hdmitx:%s:cannot use GPIO %d, err:%d\n",__func__, this->driver.gpio,err);
++ goto i2c_out;
++ }
++ /* turn GPIO into IRQ */
++ gpio_direction_input(this->driver.gpio);
++ msleep(1);
++
++ err=request_irq(gpio_to_irq(this->driver.gpio), tda_irq,
++ IRQF_TRIGGER_FALLING|IRQF_DISABLED, "TDA IRQ", this);
++ if (err <0) {
++ printk(KERN_ERR "hdmitx:%s:Cannot request irq, err:%d\n",__func__,err);
++ gpio_free(this->driver.gpio);
++ goto i2c_out;
++ }
++#else
++ init_timer(&this->driver.no_irq_timer);
++ this->driver.no_irq_timer.function=polling_timeout;
++ this->driver.no_irq_timer.data=0;
++ this->driver.no_irq_timer.expires = jiffies + HZ; /* start polling in one sec */
++ add_timer(&this->driver.no_irq_timer);
++#endif
++
++ /* setup hdcp check timer */
++ init_timer(&this->driver.hdcp_check);
++ this->driver.hdcp_check.function=hdcp_check_timeout;
++ this->driver.hdcp_check.data=0;
++
++ tmdlHdmiTxGetSWVersion(&this->tda.version);
++ printk(KERN_INFO "HDMI TX SW Version:%lu.%lu compatibility:%lu\n", \
++ this->tda.version.majorVersionNr,\
++ this->tda.version.minorVersionNr,\
++ this->tda.version.compatibilityNr);
++ return 0;
++
++ i2c_tx_out:
++ LOG(KERN_INFO,"tmdlHdmiTx closed\n");
++ /* close DevLib */
++ err=tmdlHdmiTxClose(this->tda.instance);
++
++ i2c_out:
++ LOG(KERN_INFO,"this->driver.i2c_client removed\n");
++ this->driver.i2c_client = NULL;
++
++ return err;
++}
++
++/*
++ * I2C client :: destroy
++ */
++static int this_i2c_remove(struct i2c_client *client)
++{
++ tda_instance *this=&our_instance;
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++#ifdef ANDROID_DSS
++ /* unplug DSS */
++ omap_dss_unregister_driver(&hdmi_driver);
++#endif
++
++ /* close DevLib */
++ err=tmdlHdmiTxClose(this->tda.instance);
++
++ if (!client->adapter) {
++ dev_err(&this->driver.i2c_client->dev, "<%s> No HDMI Device \n",
++ __func__);
++ return -ENODEV;
++ }
++ this->driver.i2c_client = NULL;
++
++ return err;
++}
++
++/*
++ * I2C client driver (backend)
++ * -----------------
++ */
++static const struct i2c_device_id this_i2c_id[] = {
++ { TX_NAME, 0 },
++ { },
++};
++
++MODULE_DEVICE_TABLE(i2c, this_i2c_id);
++
++static struct i2c_driver this_i2c_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = TX_NAME,
++ },
++ .probe = this_i2c_probe,
++ .remove = this_i2c_remove,
++ .id_table = this_i2c_id,
++};
++
++/*
++ * ioctl driver (userland frontend)
++ * ------------
++ */
++static struct file_operations this_cdev_fops = {
++ owner: THIS_MODULE,
++ open: this_cdev_open,
++ release: this_cdev_release,
++// ioctl: this_cdev_ioctl,
++};
++
++/*
++ * sysfs_attrs
++ * -----------
++ */
++
++static ssize_t reso_show(struct device *dev,struct device_attribute *attr, char *buf)
++{
++ tda_instance *this=&our_instance;
++
++ return sprintf(buf,"format video %d ( %s )\n", \
++ this->tda.setio.video_in.format, \
++ tda_spy_vfmt(this->tda.setio.video_in.format));
++}
++
++static ssize_t reso_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ tda_instance *this=&our_instance;
++ int resolution=0;
++
++ sscanf(buf,"%d",&resolution);
++ if (resolution != WITH_FP(this->tda.setio.video_in.format)) {
++ LOG(KERN_INFO,"sys_attr new video format\n from %d:( %s )\n to %d:( %s )\n", \
++ this->tda.setio.video_in.format, \
++ tda_spy_vfmt(this->tda.setio.video_in.format), \
++ resolution, \
++ tda_spy_vfmt(resolution));
++ this->tda.setio.video_out.format = NO_FP(resolution);
++ this->tda.setio.video_in.format = this->tda.setio.video_out.format;
++ this->tda.setio.video_in.structure3D = (IS_FP(resolution)?TMDL_HDMITX_3D_FRAME_PACKING:TMDL_HDMITX_3D_NONE);
++
++ if (resolution == 0) {
++ this->tda.power = tmPowerStandby;
++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power);
++ } else {
++ this->tda.power = tmPowerOn;
++ tmdlHdmiTxSetPowerState(this->tda.instance,this->tda.power);
++ show_video(this);
++ }
++ }
++ return 0;
++}
++
++
++static ssize_t audio_show(struct device *dev,struct device_attribute *attr, char *buf)
++{
++ tda_instance *this=&our_instance;
++ printk("Audio Show\n");
++
++ tda_spy_audio(&this->tda.setio.audio_in);
++ return sprintf(buf,"audio format %d - %d - %d - %d - %d - %d\n", \
++ this->tda.setio.audio_in.format, \
++ this->tda.setio.audio_in.rate, \
++ this->tda.setio.audio_in.i2sFormat, \
++ this->tda.setio.audio_in.i2sQualifier, \
++ this->tda.setio.audio_in.dstRate, \
++ this->tda.setio.audio_in.channelAllocation);
++}
++
++static ssize_t audio_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ tda_instance *this=&our_instance;
++ char desc_format[]="%d - %d - %d - %d - %d - %d\n";
++ tda_audio_in audio;
++
++ /*
++ Example:
++
++ adb shell "echo '1 - 1 - 0 - 32 - 0 -' >/sys/hdmitx/audio"
++
++ with :
++
++ TMDL_HDMITX_AFMT_I2S,
++ TMDL_HDMITX_AFS_44K,
++ TMDL_HDMITX_I2SFOR_PHILIPS_L,
++ TMDL_HDMITX_I2SQ_32BITS,
++ TMDL_HDMITX_DSTRATE_SINGLE,
++ channel:0
++ */
++
++ memcpy(&audio,&this->tda.setio.audio_in,sizeof(audio));
++ sscanf(buf,desc_format, \
++ &audio.format, \
++ &audio.rate, \
++ &audio.i2sFormat, \
++ &audio.i2sQualifier, \
++ &audio.dstRate, \
++ &audio.channelAllocation);
++
++ if (memcmp(&this->tda.setio.audio_in,&audio,sizeof(audio))) {
++ tda_spy_audio(&this->tda.setio.audio_in);
++ memcpy(&this->tda.setio.audio_in,&audio,sizeof(audio));
++ tmdlHdmiTxSetAudioInput(this->tda.instance, \
++ this->tda.setio.audio_in, \
++ this->tda.setio.sink);
++ }
++ return 0;
++}
++
++#ifdef I2C_DBG
++static ssize_t i2cR_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ /*
++ adb shell "echo '2 1' >/sys/hdmitx/i2cR"
++ ... read page 0x02 address 0x01
++ */
++ tda_instance *this=&our_instance;
++ tmHdmiTxobject_t *p;
++ tmErrorCode_t err;
++ unsigned int address;
++ unsigned int value,page;
++ char desc_format[]="%x %x\n";
++
++ err = checkUnitSetDis(this->tda.instance, &p);
++ sscanf(buf,desc_format,&page,&address);
++ err = getHwRegister(p, SPA(E_SNONE,page,address), (unsigned char *)&value);
++ printk("i2c read %x @ page:%x address:%x\n",value,page,address);
++ return 0;
++}
++
++static ssize_t i2cW_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ /*
++ adb shell "echo '2 1 0x03 2' >/sys/hdmitx/i2cW"
++ ... write 0x02 page 0x02 address 0x01 using mask 0x03
++ */
++
++ tda_instance *this=&our_instance;
++ tmHdmiTxobject_t *p;
++ tmErrorCode_t err;
++ unsigned int page,address,mask,value;
++ char desc_format[]="%x %x %x %x\n";
++
++ err = checkUnitSetDis(this->tda.instance, &p);
++ sscanf(buf,desc_format,&page,&address,&mask,&value);
++ err = setHwRegisterField(p,SPA(E_SNONE,page,address),mask,value);
++ printk("i2c write %x @ page:%x address:%x mask:%x\n",value,page,address,mask);
++ return 0;
++}
++#endif
++
++static DEVICE_ATTR(resolution, S_IRUGO|S_IWUSR, reso_show, reso_store);
++static DEVICE_ATTR(audio, S_IRUGO|S_IWUSR, audio_show, audio_store);
++#ifdef I2C_DBG
++static DEVICE_ATTR(i2cW, S_IRUGO|S_IWUSR, NULL, i2cW_store);
++static DEVICE_ATTR(i2cR, S_IRUGO|S_IWUSR, NULL, i2cR_store);
++#endif
++static struct device_attribute *display_sysfs_attrs[] = {
++ &dev_attr_resolution,
++ &dev_attr_audio,
++#ifdef I2C_DBG
++ &dev_attr_i2cW,
++ &dev_attr_i2cR,
++#endif
++ NULL
++};
++
++static int comm_init(void)
++{
++ tda_instance *this=&our_instance;
++ int retval=0;
++ int i=0;
++ struct device_attribute *attr;
++
++ while ((attr = display_sysfs_attrs[i++]) != NULL) {
++ retval=device_create_file (this->driver.dev,attr);
++ if (retval != 0) {
++ goto out_create_file;
++ }
++ }
++ /* create display sysfs links */
++ retval = sysfs_create_link(NULL,&(this->driver.dev->kobj),HDMITX_NAME);
++ if (retval != 0)
++ goto out_create_link;
++ return retval;
++
++ out_create_link:
++ sysfs_remove_link(NULL, HDMITX_NAME);
++ out_create_file:
++ while ((attr = display_sysfs_attrs[i++]) != NULL) {
++ device_remove_file (this->driver.dev,attr);
++ }
++ return retval;
++}
++
++static void comm_exit(void)
++{
++ tda_instance *this=&our_instance;
++ int i=0;
++ struct device_attribute *attr;
++ while ((attr = display_sysfs_attrs[i++]) != NULL) {
++ device_remove_file (this->driver.dev,attr);
++ }
++ sysfs_remove_link(NULL, HDMITX_NAME);
++}
++
++/*
++ * Module :: start up
++ */
++static int __init tx_init(void)
++{
++ tda_instance *this=&our_instance;
++ dev_t dev=0;
++ int err=0;
++
++ /*
++ general device context
++ */
++ memset(this,0,sizeof(tda_instance));
++ this->param.verbose = param_verbose;
++ this->param.major = param_major;
++ this->param.minor = param_minor;
++
++ /* Hello word */
++ printk(KERN_INFO "%s(%s) %d.%d.%d compiled: %s %s %s\n", HDMITX_NAME, TDA_NAME,
++ TDA_VERSION_MAJOR,
++ TDA_VERSION_MINOR,
++ TDA_VERSION_PATCHLEVEL,
++ __DATE__, __TIME__, TDA_VERSION_EXTRA);
++ if (this->param.verbose) LOG(KERN_INFO,".verbose mode\n");
++
++ /*
++ plug I2C (backend : Hw interfacing)
++ */
++ err = i2c_add_driver(&this_i2c_driver);
++ if (err < 0) {
++ printk(KERN_ERR "Driver registration failed\n");
++ return -ENODEV;
++ }
++
++ if (this->driver.i2c_client == NULL) {
++ printk(KERN_ERR "this->driver.i2c_client not allocated\n");
++ /* unregister i2c */
++ err = -ENODEV;
++ goto init_out;
++ }
++
++ /*
++ cdev init (userland frontend)
++ */
++
++ /* arbitray range of device numbers */
++ if (this->param.major) {
++ /* user force major number @ insmod */
++ dev = MKDEV(this->param.major, this->param.minor);
++ err = register_chrdev_region(dev,MAX_MINOR,HDMITX_NAME);
++ if (err) {
++ printk(KERN_ERR "unable to register %s, dev=%d %s\n",HDMITX_NAME,dev,ERR_TO_STR(err));
++ goto init_out;
++ }
++ } else {
++ /* fully dynamic major number */
++ err = alloc_chrdev_region(&dev, this->param.minor, MAX_MINOR,HDMITX_NAME);
++ if (err) {
++ printk(KERN_ERR "unable to alloc chrdev region for %s, dev=%d %s\n",HDMITX_NAME,dev,ERR_TO_STR(err));
++ goto init_out;
++ }
++ this->param.major = MAJOR(dev);
++ this->param.minor = MINOR(dev);
++ /* create_dev("/dev/hdmitx",dev); */
++ LOG(KERN_INFO,"/dev/hdmitx created major:%d minor:%d\n",this->param.major, this->param.minor);
++ }
++
++ cdev_init(this_cdev, &this_cdev_fops);
++ this_cdev->owner = THIS_MODULE;
++
++ this->driver.class = class_create(THIS_MODULE, HDMITX_NAME);
++ if (IS_ERR(this->driver.class)) {
++ printk(KERN_INFO "Error creating mmap device class.\n");
++ err =-EIO;
++ goto init_out;
++ }
++ this->driver.dev=device_create(this->driver.class, NULL /* parent */, dev, NULL, HDMITX_NAME);
++
++ this->driver.devno = dev;
++ err = cdev_add(this_cdev, this->driver.devno, MAX_MINOR);
++ if (err){
++ printk(KERN_INFO "unable to add device for %s, ipp_driver.devno=%d %s\n",HDMITX_NAME,this->driver.devno,ERR_TO_STR(err));
++ device_destroy(this->driver.class,this->driver.devno);
++ class_destroy(this->driver.class);
++ unregister_chrdev_region(this->driver.devno, MAX_MINOR);
++ goto init_out;
++ }
++
++ /*
++ general device context
++ */
++ sema_init(&this->driver.sem, 1);
++
++ /*
++ /!\ WARNING /! \
++ the startup power sequence SHALL BE standby AND THEN suspend (core driver legacy...)
++ this is the only way to get the TDA idle but with active HDP and RxSens interrupt listening
++ */
++ hdmi_disable(1); /* power start sequence phase 2 */
++
++ /*
++ /!\ WARNING /! \
++ if HDMI is plugged, the core driver will send HDP nor RXSENS event when beeing powered on !
++ So the Android HDMI service shall start by asking the HDP status using the IOCTL GET_HPD_STATUS
++ */
++ tmdlHdmiTxGetHPDStatus(this->tda.instance,
++ &this->tda.hot_plug_detect); /* power start sequence phase 3 */
++
++ /* sysfs_attrs */
++ comm_init();
++ hdmi_enable();
++ return 0;
++
++ init_out:
++ i2c_del_driver(&this_i2c_driver);
++ return err;
++}
++
++/*
++ * Module :: shut down
++ */
++static void __exit tx_exit(void)
++{
++ tda_instance *this=&our_instance;
++
++ LOG(KERN_INFO,"called\n");
++
++#ifdef IRQ
++ free_irq(gpio_to_irq(this->driver.gpio), this);
++ gpio_free(this->driver.gpio);
++#else
++ del_timer(&this->driver.no_irq_timer);
++#endif
++
++ del_timer(&this->driver.hdcp_check);
++
++ /* sysfs_attrs */
++ comm_exit();
++
++ /* unregister cdevice */
++ cdev_del(this_cdev);
++ unregister_chrdev_region(this->driver.devno, MAX_MINOR);
++
++ /* unregister device */
++ device_destroy(this->driver.class,this->driver.devno);
++ class_destroy(this->driver.class);
++
++ /* unregister i2c */
++ i2c_del_driver(&this_i2c_driver);
++}
++
++
++/*
++ * Module
++ * ------
++ */
++late_initcall(tx_init);
++// module_init(tx_init);
++module_exit(tx_exit);
++
++/*
++ * Disclamer
++ * ---------
++ */
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Andre Lepine <andre.lepine@nxp.com>");
++MODULE_DESCRIPTION(HDMITX_NAME " driver");
+diff --git a/drivers/video/nxp/tda998x.h b/drivers/video/nxp/tda998x.h
+new file mode 100755
+index 0000000..3759474
+--- /dev/null
++++ b/drivers/video/nxp/tda998x.h
+@@ -0,0 +1,143 @@
++/*****************************************************************************/
++/* Copyright (c) 2009 NXP Semiconductors BV */
++/* */
++/* 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, using version 2 of the License. */
++/* */
++/* This program is distributed in the hope that it will be useful, */
++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
++/* GNU General Public License for more details. */
++/* */
++/* You should have received a copy of the GNU General Public License */
++/* along with this program; if not, write to the Free Software */
++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
++/* USA. */
++/* */
++/*****************************************************************************/
++
++#ifndef __tx_h__
++#define __tx_h__
++
++#include "tda998x_ioctl.h"
++
++#define HDMITX_NAME "hdmitx"
++
++#define POLLING_WQ_NAME "TDA_POLLING"
++#define HDCP_CHECK_EVERY_MS 35
++#define CHECK_EVERY_XX_MS 200
++#define OMAP_LCD_GPIO 8
++
++#define TDA_MAJOR 234 /* old-style interval of device numbers */
++#define MAX_MINOR 1 /* 1 minor but 2 access : 1 more for pooling */
++
++
++/* common I2C define with kernel */
++/* should be the same as arch/arm/mach-omap2/board-zoom2.c */
++#define TX_NAME "tda998X"
++#define TDA998X_I2C_SLAVEADDRESS 0x70
++
++#define TDA_IRQ_CALIB 107
++
++#define EDID_BLOCK_COUNT 4
++#define EDID_BLOCK_SIZE 128
++#define MAX_EDID_TRIAL 5
++#define NO_PHY_ADDR 0xFFFF
++
++#define HDCP_IS_NOT_INSTALLED TMDL_HDMITX_HDCP_CHECK_NUM /* ugly is bad ! */
++
++#define LOG(type,fmt,args...) {if (this->param.verbose) {printk(type HDMITX_NAME":%s:" fmt, __func__, ## args);}}
++/* not found the kernel "strerror" one! If someone knows, please replace it */
++#define ERR_TO_STR(e)((e == -ENODATA)?"ENODATA, no data available":\
++ (e == -ENOMEM)? "ENOMEM, no memory available":\
++ (e == -EINVAL)? "EINVAL, invalid argument":\
++ (e == -EIO)? "EIO, input/output error":\
++ (e == -ETIMEDOUT)? "ETIMEOUT, timeout has expired":\
++ (e == -EBUSY)? "EBUSY, device or resource busy":\
++ (e == -ENOENT)? "ENOENT, no such file or directory":\
++ (e == -EACCES)? "EACCES, permission denied":\
++ (e == 0)? "":\
++ "!UNKNOWN!")
++
++#define TRY(fct) { \
++ err=(fct); \
++ if (err) { \
++ printk(KERN_ERR "%s returned in %s line %d\n",hdmi_tx_err_string(err),__func__,__LINE__); \
++ goto TRY_DONE; \
++ } \
++ }
++
++typedef void (*cec_callback_t)(struct work_struct *dummy);
++
++typedef struct {
++ /* module params */
++ struct {
++ int verbose;
++ int major;
++ int minor;
++ } param;
++ /* driver */
++ struct {
++ struct class *class;
++ struct device *dev;
++ int devno;
++ struct i2c_client *i2c_client;
++ struct semaphore sem;
++ int user_counter;
++ int minor;
++ wait_queue_head_t wait;
++ bool poll_done;
++#ifndef IRQ
++ struct timer_list no_irq_timer;
++#endif
++ struct timer_list hdcp_check;
++ cec_callback_t cec_callback;
++ bool omap_dss_hdmi_panel;
++ int gpio;
++ } driver;
++ /* HDMI */
++ struct {
++ int instance;
++ tda_version version;
++ tda_setup setup;
++ tda_power power;
++ tmdlHdmiTxHotPlug_t hot_plug_detect;
++ bool rx_device_active;
++ tda_video_format video_fmt;
++ tda_set_in_out setio;
++ bool audio_mute;
++ tda_video_infoframe video_infoframe;
++ tda_audio_infoframe audio_infoframe;
++ tda_acp acp;
++ tda_gcp gcp;
++ tda_isrc1 isrc1;
++ tda_isrc2 isrc2;
++ tda_gammut gammut;
++ tda_mps_infoframe mps_infoframe;
++ tda_spd_infoframe spd_infoframe;
++ tda_vs_infoframe vs_infoframe;
++ tda_edid edid;
++ tda_edid_dtd edid_dtd;
++ tda_edid_md edid_md;
++ tda_edid_audio_caps edid_audio_caps;
++ tda_edid_video_caps edid_video_caps;
++ tda_edid_video_timings edid_video_timings;
++ tda_edid_tv_aspect_ratio edid_tv_aspect_ratio;
++#ifdef TMFL_TDA19989
++ tda_edid_latency edid_latency;
++#endif
++ unsigned short src_address;
++ unsigned char raw_edid[EDID_BLOCK_COUNT*EDID_BLOCK_SIZE];
++ tda_capabilities capabilities;
++ tda_event event;
++ tda_hdcp_status hdcp_status;
++ bool hdcp_enable;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++ tda_hdcp_fail hdcp_fail;
++#endif
++ unsigned char hdcp_raw_status;
++ } tda;
++} tda_instance;
++
++#endif /* __tx_h__ */
+diff --git a/drivers/video/nxp/tda998x_cec.c b/drivers/video/nxp/tda998x_cec.c
+new file mode 100755
+index 0000000..90f3536
+--- /dev/null
++++ b/drivers/video/nxp/tda998x_cec.c
+@@ -0,0 +1,2157 @@
++/*****************************************************************************/
++/* Copyright (c) 2009 NXP Semiconductors BV */
++/* */
++/* 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, using version 2 of the License. */
++/* */
++/* This program is distributed in the hope that it will be useful, */
++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
++/* GNU General Public License for more details. */
++/* */
++/* You should have received a copy of the GNU General Public License */
++/* along with this program; if not, write to the Free Software */
++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
++/* USA. */
++/* */
++/*****************************************************************************/
++
++#define _cec_c_
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/cdev.h>
++#include <linux/fs.h>
++#include <linux/ioctl.h>
++#include <linux/i2c.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <asm/uaccess.h>
++#include <mach/gpio.h>
++
++/* HDMI DevLib */
++#include "tmNxCompId.h"
++#include "tmdlHdmiCEC.h"
++#include "tmdlHdmiCEC_local.h"
++
++/* local */
++#include "tda998x_version.h"
++#include "tda998x_cec.h"
++#include "tda998x_ioctl.h"
++
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/vt_kern.h>
++#include <asm/types.h>
++
++
++/*
++ *
++ * DEFINITION
++ * ----------
++ * LEVEL 0
++ *
++ */
++
++/*
++ * Global
++ */
++
++MODULE_DEVICE_TABLE(i2c, this_i2c_id);
++static const struct i2c_device_id this_i2c_id[] = {
++ { CEC_NAME, 0 },
++ { },
++};
++cec_instance our_instance;
++static struct cdev our_cdev, *this_cdev=&our_cdev;
++
++#ifdef TWL4030_HACK
++/* AL : hack to bypass keypad */
++struct input_dev *gkp_input;
++extern struct input_dev *get_twm4030_input(void);
++#endif
++
++/*
++ * Dependancies to HdmiTx module
++ */
++
++extern void register_cec_interrupt(cec_callback_t fct);
++extern void unregister_cec_interrupt(void);
++extern short edid_phy_addr(void);
++extern int hdmi_enable(void);
++extern int hdmi_disable(int event_tracking);
++extern cec_power get_hdmi_status(void);
++extern cec_power get_hpd_status(void);
++extern int edid_received(void);
++
++/*
++ * Module params
++ */
++
++static int param_verbose=0,param_major=0,param_minor=0,param_device=4,param_addr=0xFFFF;
++module_param_named(verbose,param_verbose,int,S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(verbose, "Make the driver verbose");
++module_param_named(major, param_major, int, S_IRUGO);
++MODULE_PARM_DESC(major, "The major number of the device mapper");
++module_param_named(device, param_device, int, S_IRUGO);
++MODULE_PARM_DESC(device, "Device type can be 0:tv, 1:rec 3:tuner 4:mediaplayer, 5:audio");
++module_param_named(addr, param_addr, int, S_IRUGO);
++MODULE_PARM_DESC(addr, "Physical address (until EDID received)");
++
++/*
++ *
++ * TOOLBOX
++ * -------
++ * LEVEL 1
++ *
++ * - i2c read/write
++ * - chip Id check
++ * - i2c client info
++ *
++ */
++
++
++/*
++ * Get main and unique I2C Client driver handle
++ */
++struct i2c_client *GetThisI2cClient(void)
++{
++ cec_instance *this=&our_instance;
++ return this->driver.i2c_client;
++}
++
++/*
++ * error handling
++ */
++static char *hdmi_cec_err_string(int err)
++{
++ switch (err)
++ {
++ case TMDL_ERR_DLHDMICEC_COMPATIBILITY: {return "SW Interface compatibility";break;}
++ case TMDL_ERR_DLHDMICEC_MAJOR_VERSION: {return "SW Major Version error";break;}
++ case TMDL_ERR_DLHDMICEC_COMP_VERSION: {return "SW component version error";break;}
++ case TMDL_ERR_DLHDMICEC_BAD_UNIT_NUMBER: {return "Invalid device unit number";break;}
++ case TMDL_ERR_DLHDMICEC_BAD_INSTANCE: {return "Bad input instance value ";break;}
++ case TMDL_ERR_DLHDMICEC_BAD_HANDLE: {return "Bad input handle";break;}
++ case TMDL_ERR_DLHDMICEC_BAD_PARAMETER: {return "Invalid input parameter";break;}
++ case TMDL_ERR_DLHDMICEC_NO_RESOURCES: {return "Resource is not available ";break;}
++ case TMDL_ERR_DLHDMICEC_RESOURCE_OWNED: {return "Resource is already in use";break;}
++ case TMDL_ERR_DLHDMICEC_RESOURCE_NOT_OWNED: {return "Caller does not own resource";break;}
++ case TMDL_ERR_DLHDMICEC_INCONSISTENT_PARAMS: {return "Inconsistent input params";break;}
++ case TMDL_ERR_DLHDMICEC_NOT_INITIALIZED: {return "Component is not initializ";break;}
++ case TMDL_ERR_DLHDMICEC_NOT_SUPPORTED: {return "Function is not supported";break;}
++ case TMDL_ERR_DLHDMICEC_INIT_FAILED: {return "Initialization failed";break;}
++ case TMDL_ERR_DLHDMICEC_BUSY: {return "Component is busy";break;}
++ case TMDL_ERR_DLHDMICEC_I2C_READ: {return "Read error";break;}
++ case TMDL_ERR_DLHDMICEC_I2C_WRITE: {return "Write error";break;}
++ case TMDL_ERR_DLHDMICEC_FULL: {return "Queue is full";break;}
++ case TMDL_ERR_DLHDMICEC_NOT_STARTED: {return "Function is not started";break;}
++ case TMDL_ERR_DLHDMICEC_ALREADY_STARTED: {return "Function is already starte";break;}
++ case TMDL_ERR_DLHDMICEC_ASSERTION: {return "Assertion failure";break;}
++ case TMDL_ERR_DLHDMICEC_INVALID_STATE: {return "Invalid state for function";break;}
++ case TMDL_ERR_DLHDMICEC_OPERATION_NOT_PERMITTED: {return "Corresponds to posix EPERM";break;}
++ default : {return "Unexpected error";break;}
++ }
++}
++
++char *cec_opcode(int op)
++{
++ switch (op)
++ {
++ case CEC_OPCODE_FEATURE_ABORT: {return "CEC_OPCODE_FEATURE_ABORT";break;}
++ case CEC_OPCODE_IMAGE_VIEW_ON: {return "CEC_OPCODE_IMAGE_VIEW_ON";break;}
++ case CEC_OPCODE_TUNER_STEP_INCREMENT: {return "CEC_OPCODE_TUNER_STEP_INCREMENT";break;}
++ case CEC_OPCODE_TUNER_STEP_DECREMENT: {return "CEC_OPCODE_TUNER_STEP_DECREMENT";break;}
++ case CEC_OPCODE_TUNER_DEVICE_STATUS: {return "CEC_OPCODE_TUNER_DEVICE_STATUS";break;}
++ case CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS: {return "CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS";break;}
++ case CEC_OPCODE_RECORD_ON: {return "CEC_OPCODE_RECORD_ON";break;}
++ case CEC_OPCODE_RECORD_STATUS: {return "CEC_OPCODE_RECORD_STATUS";break;}
++ case CEC_OPCODE_RECORD_OFF: {return "CEC_OPCODE_RECORD_OFF";break;}
++ case CEC_OPCODE_TEXT_VIEW_ON: {return "CEC_OPCODE_TEXT_VIEW_ON";break;}
++ case CEC_OPCODE_RECORD_TV_SCREEN: {return "CEC_OPCODE_RECORD_TV_SCREEN";break;}
++ case CEC_OPCODE_GIVE_DECK_STATUS: {return "CEC_OPCODE_GIVE_DECK_STATUS";break;}
++ case CEC_OPCODE_DECK_STATUS: {return "CEC_OPCODE_DECK_STATUS";break;}
++ case CEC_OPCODE_SET_MENU_LANGUAGE: {return "CEC_OPCODE_SET_MENU_LANGUAGE";break;}
++ case CEC_OPCODE_CLEAR_ANALOGUE_TIMER: {return "CEC_OPCODE_CLEAR_ANALOGUE_TIMER";break;}
++ case CEC_OPCODE_SET_ANALOGUE_TIMER: {return "CEC_OPCODE_SET_ANALOGUE_TIMER";break;}
++ case CEC_OPCODE_TIMER_STATUS: {return "CEC_OPCODE_TIMER_STATUS";break;}
++ case CEC_OPCODE_STANDBY: {return "CEC_OPCODE_STANDBY";break;}
++ case CEC_OPCODE_PLAY: {return "CEC_OPCODE_PLAY";break;}
++/* case CEC_OPCODE_DECK_CONTROL: {return "CEC_OPCODE_DECK_CONTROL";break;} */
++ case CEC_OPCODE_TIMER_CLEARED_STATUS: {return "CEC_OPCODE_TIMER_CLEARED_STATUS";break;}
++ case CEC_OPCODE_USER_CONTROL_PRESSED: {return "CEC_OPCODE_USER_CONTROL_PRESSED";break;}
++ case CEC_OPCODE_USER_CONTROL_RELEASED: {return "CEC_OPCODE_USER_CONTROL_RELEASED";break;}
++ case CEC_OPCODE_GIVE_OSD_NAME: {return "CEC_OPCODE_GIVE_OSD_NAME";break;}
++ case CEC_OPCODE_SET_OSD_NAME: {return "CEC_OPCODE_SET_OSD_NAME";break;}
++ case CEC_OPCODE_SET_OSD_STRING: {return "CEC_OPCODE_SET_OSD_STRING";break;}
++ case CEC_OPCODE_SET_TIMER_PROGRAM_TITLE: {return "CEC_OPCODE_SET_TIMER_PROGRAM_TITLE";break;}
++ case CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST: {return "CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST";break;}
++ case CEC_OPCODE_GIVE_AUDIO_STATUS: {return "CEC_OPCODE_GIVE_AUDIO_STATUS";break;}
++ case CEC_OPCODE_SET_SYSTEM_AUDIO_MODE: {return "CEC_OPCODE_SET_SYSTEM_AUDIO_MODE";break;}
++ case CEC_OPCODE_REPORT_AUDIO_STATUS: {return "CEC_OPCODE_REPORT_AUDIO_STATUS";break;}
++ case CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS: {return "CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS";break;}
++ case CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS: {return "CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS";break;}
++ case CEC_OPCODE_ROUTING_CHANGE: {return "CEC_OPCODE_ROUTING_CHANGE";break;}
++ case CEC_OPCODE_ROUTING_INFORMATION: {return "CEC_OPCODE_ROUTING_INFORMATION";break;}
++ case CEC_OPCODE_ACTIVE_SOURCE: {return "CEC_OPCODE_ACTIVE_SOURCE";break;}
++ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: {return "CEC_OPCODE_GIVE_PHYSICAL_ADDRESS";break;}
++ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS: {return "CEC_OPCODE_REPORT_PHYSICAL_ADDRESS";break;}
++ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE: {return "CEC_OPCODE_REQUEST_ACTIVE_SOURCE";break;}
++ case CEC_OPCODE_SET_STREAM_PATH: {return "CEC_OPCODE_SET_STREAM_PATH";break;}
++ case CEC_OPCODE_DEVICE_VENDOR_ID: {return "CEC_OPCODE_DEVICE_VENDOR_ID";break;}
++ case CEC_OPCODE_VENDOR_COMMAND: {return "CEC_OPCODE_VENDOR_COMMAND";break;}
++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN: {return "CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN";break;}
++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP: {return "CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP";break;}
++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID: {return "CEC_OPCODE_GIVE_DEVICE_VENDOR_ID";break;}
++ case CEC_OPCODE_MENU_REQUEST: {return "CEC_OPCODE_MENU_REQUEST";break;}
++ case CEC_OPCODE_MENU_STATUS: {return "CEC_OPCODE_MENU_STATUS";break;}
++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS: {return "CEC_OPCODE_GIVE_DEVICE_POWER_STATUS";break;}
++ case CEC_OPCODE_REPORT_POWER_STATUS: {return "CEC_OPCODE_REPORT_POWER_STATUS";break;}
++ case CEC_OPCODE_GET_MENU_LANGUAGE: {return "CEC_OPCODE_GET_MENU_LANGUAGE";break;}
++ case CEC_OPCODE_SET_ANALOGUE_SERVICE: {return "CEC_OPCODE_SET_ANALOGUE_SERVICE";break;}
++ case CEC_OPCODE_SET_DIGITAL_SERVICE: {return "CEC_OPCODE_SET_DIGITAL_SERVICE";break;}
++ case CEC_OPCODE_SET_DIGITAL_TIMER: {return "CEC_OPCODE_SET_DIGITAL_TIMER";break;}
++ case CEC_OPCODE_CLEAR_DIGITAL_TIMER: {return "CEC_OPCODE_CLEAR_DIGITAL_TIMER";break;}
++ case CEC_OPCODE_SET_AUDIO_RATE: {return "CEC_OPCODE_SET_AUDIO_RATE";break;}
++ case CEC_OPCODE_INACTIVE_SOURCE: {return "CEC_OPCODE_INACTIVE_SOURCE";break;}
++ case CEC_OPCODE_CEC_VERSION: {return "CEC_OPCODE_CEC_VERSION";break;}
++ case CEC_OPCODE_GET_CEC_VERSION: {return "CEC_OPCODE_GET_CEC_VERSION";break;}
++ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID: {return "CEC_OPCODE_VENDOR_COMMAND_WITH_ID";break;}
++ case CEC_OPCODE_CLEAR_EXTERNAL_TIMER: {return "CEC_OPCODE_CLEAR_EXTERNAL_TIMER";break;}
++ case CEC_OPCODE_SET_EXTERNAL_TIMER: {return "CEC_OPCODE_SET_EXTERNAL_TIMER";break;}
++ case CEC_OPCODE_ABORT_MESSAGE: {return "CEC_OPCODE_ABORT_MESSAGE";break;}
++ default : {return "unknown";break;}
++ }
++}
++
++
++static char *cec_ioctl(int io)
++{
++ switch (io)
++ {
++ case CEC_VERBOSE_ON_CMD: {return "CEC_VERBOSE_ON_CMD";break;}
++ case CEC_VERBOSE_OFF_CMD: {return "CEC_VERBOSE_OFF_CMD";break;}
++ case CEC_BYEBYE_CMD: {return "CEC_BYEBYE_CMD";break;}
++ case CEC_IOCTL_RX_ADDR_CMD: {return "CEC_IOCTL_RX_ADDR_CMD";break;}
++ case CEC_IOCTL_PHY_ADDR_CMD: {return "CEC_IOCTL_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_WAIT_FRAME_CMD: {return "CEC_IOCTL_WAIT_FRAME_CMD";break;}
++ case CEC_IOCTL_ABORT_MSG_CMD: {return "CEC_IOCTL_ABORT_MSG_CMD";break;}
++ case CEC_IOCTL_ACTIVE_SRC_CMD: {return "CEC_IOCTL_ACTIVE_SRC_CMD";break;}
++ case CEC_IOCTL_VERSION_CMD: {return "CEC_IOCTL_VERSION_CMD";break;}
++ case CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD: {return "CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD";break;}
++ case CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD: {return "CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD";break;}
++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD: {return "CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD";break;}
++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD: {return "CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_DECK_CTRL_CMD: {return "CEC_IOCTL_DECK_CTRL_CMD";break;}
++ case CEC_IOCTL_DECK_STATUS_CMD: {return "CEC_IOCTL_DECK_STATUS_CMD";break;}
++ case CEC_IOCTL_DEVICE_VENDOR_ID_CMD: {return "CEC_IOCTL_DEVICE_VENDOR_ID_CMD";break;}
++ case CEC_IOCTL_FEATURE_ABORT_CMD: {return "CEC_IOCTL_FEATURE_ABORT_CMD";break;}
++ case CEC_IOCTL_GET_CEC_VERSION_CMD: {return "CEC_IOCTL_GET_CEC_VERSION_CMD";break;}
++ case CEC_IOCTL_GET_MENU_LANGUAGE_CMD: {return "CEC_IOCTL_GET_MENU_LANGUAGE_CMD";break;}
++ case CEC_IOCTL_GIVE_AUDIO_STATUS_CMD: {return "CEC_IOCTL_GIVE_AUDIO_STATUS_CMD";break;}
++ case CEC_IOCTL_GIVE_DECK_STATUS_CMD: {return "CEC_IOCTL_GIVE_DECK_STATUS_CMD";break;}
++ case CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD: {return "CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD";break;}
++ case CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD: {return "CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD";break;}
++ case CEC_IOCTL_GIVE_OSD_NAME_CMD: {return "CEC_IOCTL_GIVE_OSD_NAME_CMD";break;}
++ case CEC_IOCTL_GIVE_PHY_ADDR_CMD: {return "CEC_IOCTL_GIVE_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD: {return "CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD";break;}
++ case CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD: {return "CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD";break;}
++ case CEC_IOCTL_IMAGE_VIEW_ON_CMD: {return "CEC_IOCTL_IMAGE_VIEW_ON_CMD";break;}
++ case CEC_IOCTL_INACTIVE_SRC_CMD: {return "CEC_IOCTL_INACTIVE_SRC_CMD";break;}
++ case CEC_IOCTL_MENU_REQUEST_CMD: {return "CEC_IOCTL_MENU_REQUEST_CMD";break;}
++ case CEC_IOCTL_MENU_STATUS_CMD: {return "CEC_IOCTL_MENU_STATUS_CMD";break;}
++ case CEC_IOCTL_PLAY_CMD: {return "CEC_IOCTL_PLAY_CMD";break;}
++ case CEC_IOCTL_POLLING_MSG_CMD: {return "CEC_IOCTL_POLLING_MSG_CMD";break;}
++ case CEC_IOCTL_REC_OFF_CMD: {return "CEC_IOCTL_REC_OFF_CMD";break;}
++ case CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD: {return "CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD";break;}
++ case CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD: {return "CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD";break;}
++ case CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD: {return "CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_REC_ON_EXT_PLUG_CMD: {return "CEC_IOCTL_REC_ON_EXT_PLUG_CMD";break;}
++ case CEC_IOCTL_REC_ON_OWN_SRC_CMD: {return "CEC_IOCTL_REC_ON_OWN_SRC_CMD";break;}
++ case CEC_IOCTL_REC_STATUS_CMD: {return "CEC_IOCTL_REC_STATUS_CMD";break;}
++ case CEC_IOCTL_REC_TV_SCREEN_CMD: {return "CEC_IOCTL_REC_TV_SCREEN_CMD";break;}
++ case CEC_IOCTL_REPORT_AUDIO_STATUS_CMD: {return "CEC_IOCTL_REPORT_AUDIO_STATUS_CMD";break;}
++ case CEC_IOCTL_REPORT_PHY_ADDR_CMD: {return "CEC_IOCTL_REPORT_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_REPORT_POWER_STATUS_CMD: {return "CEC_IOCTL_REPORT_POWER_STATUS_CMD";break;}
++ case CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD: {return "CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD";break;}
++ case CEC_IOCTL_ROUTING_CHANGE_CMD: {return "CEC_IOCTL_ROUTING_CHANGE_CMD";break;}
++ case CEC_IOCTL_ROUTING_INFORMATION_CMD: {return "CEC_IOCTL_ROUTING_INFORMATION_CMD";break;}
++ case CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD: {return "CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD";break;}
++ case CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD: {return "CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD";break;}
++ case CEC_IOCTL_SET_ANALOGUE_TIMER_CMD: {return "CEC_IOCTL_SET_ANALOGUE_TIMER_CMD";break;}
++ case CEC_IOCTL_SET_AUDIO_RATE_CMD: {return "CEC_IOCTL_SET_AUDIO_RATE_CMD";break;}
++ case CEC_IOCTL_SET_DIGITAL_TIMER_CMD: {return "CEC_IOCTL_SET_DIGITAL_TIMER_CMD";break;}
++ case CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD: {return "CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD";break;}
++ case CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD: {return "CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD";break;}
++ case CEC_IOCTL_SET_MENU_LANGUAGE_CMD: {return "CEC_IOCTL_SET_MENU_LANGUAGE_CMD";break;}
++ case CEC_IOCTL_SET_OSD_NAME_CMD: {return "CEC_IOCTL_SET_OSD_NAME_CMD";break;}
++ case CEC_IOCTL_SET_OSD_STRING_CMD: {return "CEC_IOCTL_SET_OSD_STRING_CMD";break;}
++ case CEC_IOCTL_SET_STREAM_PATH_CMD: {return "CEC_IOCTL_SET_STREAM_PATH_CMD";break;}
++ case CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD: {return "CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD";break;}
++ case CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD: {return "CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD";break;}
++ case CEC_IOCTL_STANDBY_CMD: {return "CEC_IOCTL_STANDBY_CMD";break;}
++ case CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD: {return "CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD";break;}
++ case CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD: {return "CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD";break;}
++ case CEC_IOCTL_TEXT_VIEW_ON_CMD: {return "CEC_IOCTL_TEXT_VIEW_ON_CMD";break;}
++ case CEC_IOCTL_TIMER_CLEARED_STATUS_CMD: {return "CEC_IOCTL_TIMER_CLEARED_STATUS_CMD";break;}
++ case CEC_IOCTL_TIMER_STATUS_CMD: {return "CEC_IOCTL_TIMER_STATUS_CMD";break;}
++ case CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD: {return "CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD";break;}
++ case CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD: {return "CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD";break;}
++ case CEC_IOCTL_TUNER_STEP_DECREMENT_CMD: {return "CEC_IOCTL_TUNER_STEP_DECREMENT_CMD";break;}
++ case CEC_IOCTL_TUNER_STEP_INCREMENT_CMD: {return "CEC_IOCTL_TUNER_STEP_INCREMENT_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_CMD: {return "CEC_IOCTL_USER_CTRL_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_PLAY_CMD: {return "CEC_IOCTL_USER_CTRL_PLAY_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD: {return "CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_TUNE_CMD: {return "CEC_IOCTL_USER_CTRL_TUNE_CMD";break;}
++ case CEC_IOCTL_USER_CTRL_RELEASED_CMD: {return "CEC_IOCTL_USER_CTRL_RELEASED_CMD";break;}
++ case CEC_IOCTL_VENDOR_COMMAND_CMD: {return "CEC_IOCTL_VENDOR_COMMAND_CMD";break;}
++ case CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD: {return "CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD";break;}
++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD: {return "CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD";break;}
++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD: {return "CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD";break;}
++ case CEC_IOCTL_GET_SW_VERSION_CMD: {return "CEC_IOCTL_GET_SW_VERSION_CMD";break;}
++ case CEC_IOCTL_SET_POWER_STATE_CMD: {return "CEC_IOCTL_SET_POWER_STATE_CMD";break;}
++ case CEC_IOCTL_GET_POWER_STATE_CMD: {return "CEC_IOCTL_GET_POWER_STATE_CMD";break;}
++ case CEC_IOCTL_INSTANCE_CONFIG_CMD: {return "CEC_IOCTL_INSTANCE_CONFIG_CMD";break;}
++ case CEC_IOCTL_INSTANCE_SETUP_CMD: {return "CEC_IOCTL_INSTANCE_SETUP_CMD";break;}
++ case CEC_IOCTL_GET_INSTANCE_SETUP_CMD: {return "CEC_IOCTL_GET_INSTANCE_SETUP_CMD";break;}
++ case CEC_IOCTL_ENABLE_EVENT_CMD: {return "CEC_IOCTL_ENABLE_EVENT_CMD";break;}
++ case CEC_IOCTL_DISABLE_EVENT_CMD: {return "CEC_IOCTL_DISABLE_EVENT_CMD";break;}
++ case CEC_IOCTL_ENABLE_CALIBRATION_CMD: {return "CEC_IOCTL_ENABLE_CALIBRATION_CMD";break;}
++ case CEC_IOCTL_DISABLE_CALIBRATION_CMD: {return "CEC_IOCTL_DISABLE_CALIBRATION_CMD";break;}
++ case CEC_IOCTL_SEND_MSG_CMD: {return "CEC_IOCTL_SEND_MSG_CMD";break;}
++ case CEC_IOCTL_SET_REGISTER_CMD: {return "CEC_IOCTL_SET_REGISTER_CMD";break;}
++ default : {return "unknown";break;}
++ }
++}
++
++
++static char *cec_rxstatus(int s)
++{
++ switch (s)
++ {
++ case CEC_MSG_SUCCESS :{return "success";break;}
++ case CEC_MSG_FAIL_DATA_NOT_ACK :{return "data not ack";break;}
++ case CEC_CSP_OFF_STATE :{return "CSP off";break;}
++ case CEC_BAD_REQ_SERVICE :{return "bad Req";break;}
++ case CEC_MSG_FAIL_UNABLE_TO_ACCESS :{return "CEC line error";break;}
++ case CEC_MSG_FAIL_ARBITRATION_ERROR :{return "arb error";break;}
++ case CEC_MSG_FAIL_BIT_TIMMING_ERROR :{return "bit error";break;}
++ case CEC_MSG_FAIL_DEST_NOT_ACK :{return "destination not ack";break;}
++ default : {return "unknown";break;}
++ }
++}
++
++
++static unsigned char get_next_logical_addr(cec_device_type device,unsigned char la)
++{
++ switch (device) {
++ case CEC_DEVICE_TYPE_TV:
++ switch (la) {
++ case CEC_LOGICAL_ADDRESS_TV:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ default:
++ return CEC_LOGICAL_ADDRESS_TV;
++ }
++ case CEC_DEVICE_TYPE_REC_DEVICE:
++ switch (la) {
++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1:
++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2;
++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_2:
++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3;
++ case CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_3:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ default:
++ return CEC_LOGICAL_ADDRESS_RECORDING_DEVICE_1;
++ }
++ case CEC_DEVICE_TYPE_TUNER:
++ switch (la) {
++ case CEC_LOGICAL_ADDRESS_TUNER_1:
++ return CEC_LOGICAL_ADDRESS_TUNER_2;
++ case CEC_LOGICAL_ADDRESS_TUNER_2:
++ return CEC_LOGICAL_ADDRESS_TUNER_3;
++ case CEC_LOGICAL_ADDRESS_TUNER_3:
++ return CEC_LOGICAL_ADDRESS_TUNER_4;
++ case CEC_LOGICAL_ADDRESS_TUNER_4:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ default:
++ return CEC_LOGICAL_ADDRESS_TUNER_1;
++ }
++ case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
++ switch (la) {
++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1:
++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2;
++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_2:
++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3;
++ case CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_3:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ default:
++ return CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1;
++ }
++ case CEC_DEVICE_TYPE_AUDIO_DEVICE:
++ switch (la) {
++ case CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ default:
++ return CEC_LOGICAL_ADDRESS_AUDIO_SYSTEM;
++ }
++ default:
++ return CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ }
++}
++
++static int device_type(int type)
++{
++ printk(KERN_INFO "hdmicec declared as a ");
++ switch (type) {
++ case CEC_DEVICE_TYPE_TV:
++ printk("TV");
++ break;
++ case CEC_DEVICE_TYPE_REC_DEVICE:
++ printk("record");
++ break;
++ case CEC_DEVICE_TYPE_TUNER:
++ printk("tuner");
++ break;
++ case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
++ printk("playback");
++ break;
++ case CEC_DEVICE_TYPE_AUDIO_DEVICE:
++ printk("audio");
++ break;
++ default:
++ printk("default (playback)");
++ type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
++ break;
++ }
++ printk(" device type\n");
++ return type;
++}
++
++
++/*
++ *
++ * PROCESSING
++ * ----------
++ * LEVEL 2
++ *
++ */
++
++
++/*
++ * CEC Power On
++ */
++static void cec_on(cec_instance *this)
++{
++ int err;
++ struct task_struct *tsk = current;
++
++ // disable_irq(gpio_to_irq(TDA_IRQ_CALIB));
++
++ this->cec.power = tmPowerOn;
++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power));
++
++ /* turn GPIO into calib pulse generator */
++ gpio_direction_output(TDA_IRQ_CALIB,0); /* output (1 means try-state or high) */
++ __gpio_set_value(TDA_IRQ_CALIB,1);
++ this->cec.clock = TMDL_HDMICEC_CLOCK_FRO;
++ TRY(tmdlHdmiCecEnableCalibration(this->cec.inst,this->cec.clock));
++ msleep(10);
++ set_current_state(TASK_UNINTERRUPTIBLE);
++
++ /* CAUTION : TDA needs a real 10ms pulse */
++ cpu_relax();
++ spin_lock_irq(&tsk->sighand->siglock);
++ __gpio_set_value(TDA_IRQ_CALIB,0);
++ __udelay(10000);
++ __gpio_set_value(TDA_IRQ_CALIB,1);
++ spin_unlock_irq(&tsk->sighand->siglock);
++
++ msleep(10);
++ TRY(tmdlHdmiCecDisableCalibration(this->cec.inst));
++
++ /* setup */
++ TRY(tmdlHdmiCecGetInstanceSetup(this->cec.inst,&this->cec.setup));
++ this->cec.setup.DeviceLogicalAddress = this->cec.rx_addr;
++ this->cec.clock = TMDL_HDMICEC_CLOCK_FRO;
++ this->cec.setup.cecClockSource = this->cec.clock;
++ TRY(tmdlHdmiCecInstanceSetup(this->cec.inst,&this->cec.setup));
++
++ /* turn GPIO into IRQ */
++ gpio_direction_input(TDA_IRQ_CALIB);
++ // enable_irq(gpio_to_irq(TDA_IRQ_CALIB));
++
++ LOG(KERN_INFO,"standby --> on\n");
++
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * CEC Power Off
++ */
++static void cec_standby(cec_instance *this)
++{
++ int err;
++
++ this->cec.power = tmPowerStandby;
++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power));
++
++ LOG(KERN_INFO,"on --> standby\n");
++
++ TRY_DONE:
++ (void)0;
++}
++
++/*
++ * CEC interrupt polling
++ */
++static void cec_interrupt(struct work_struct *dummy)
++{
++ cec_instance *this=&our_instance;
++ unsigned short new_phy_addr=edid_phy_addr();
++ int err=0;
++
++ LOG(KERN_INFO,"%s called\n",__func__);
++
++ /* switch on/off CEC */
++ if (!get_hpd_status() && \
++ (this->cec.power == tmPowerOn)) {
++ this->cec.source_status = CEC_POWER_STATUS_STANDBY;
++/* TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \ */
++/* this->cec.initiator, \ */
++/* this->cec.phy_addr)); */
++ cec_standby(this);
++ }
++ else if (get_hpd_status() && \
++ (this->cec.power == tmPowerStandby)) {
++ /* send active msg when hdmi has been abled */
++ cec_on(this);
++ }
++ /* new phy addr means new EDID, mean HPD ! */
++ else if ((this->cec.phy_addr != new_phy_addr) && \
++ (this->cec.source_status == CEC_POWER_STATUS_ON)) {
++ LOG(KERN_INFO,"New physical address %02x\n",new_phy_addr);
++ this->cec.phy_addr = new_phy_addr;
++ if (this->cec.phy_addr != 0xFFFF) {
++ this->cec.rx_addr = get_next_logical_addr(this->cec.device_type,CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST);
++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr));
++ }
++ else {
++ this->cec.rx_addr = CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++ }
++ }
++#ifdef GUI_OVER_HDMI
++ else if (edid_received()) { /* Check me */
++ if (this->cec.source_status == CEC_POWER_STATUS_STANDBY) {
++ /* only for GFX on HDMI, do not use if only video playback on HDMI */
++ TRY(tmdlHdmiCecImageViewOn(this->cec.inst,this->cec.initiator));
++ TRY(tmdlHdmiCecHandleInterrupt(this->cec.inst));
++ msleep(200);
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr));
++ this->cec.source_status = CEC_POWER_STATUS_ON;
++ }
++ }
++#endif
++
++#if 0
++ if (this->cec.phy_addr != 0xFFFF) {
++
++ /* claim source status */
++ if ((get_hdmi_status() == tmPowerStandby) && \
++ (this->cec.source_status == CEC_POWER_STATUS_ON)) {
++ /* send inactive msg when hdmi has been disabled */
++ this->cec.source_status = CEC_POWER_STATUS_STANDBY;
++ TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.phy_addr));
++ }
++ else if ((get_hdmi_status() == tmPowerOn) && \
++ (this->cec.source_status == CEC_POWER_STATUS_STANDBY)) {
++ /* send active msg when hdmi has been abled */
++ this->cec.source_status = CEC_POWER_STATUS_ON;
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst, \
++ this->cec.phy_addr));
++ }
++/* printk(KERN_INFO "DBG phd_status:%s cec.power:%s\n", \ */
++/* get_hpd_status()?"Active":"Inactive", \ */
++/* (this->cec.power==tmPowerOn)?"On":"Standby"); */
++ }
++#endif
++
++ /* internal handeling */
++ TRY(tmdlHdmiCecHandleInterrupt(this->cec.inst));
++
++ TRY_DONE:
++
++ /* setup next tick */
++ if (!this->driver.deinit_req) {
++ /* setup next polling */
++#ifndef IRQ
++/* this->driver.timer.expires = jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 ); */
++/* add_timer(&this->driver.timer); */
++ mod_timer(&this->driver.timer,jiffies + ( CHECK_EVERY_XX_MS * HZ / 1000 ));
++#endif
++ }
++ else {
++ this->driver.deinit_req++;
++ wake_up_interruptible(&this->driver.wait);
++ }
++}
++
++#ifndef IRQ
++static DECLARE_WORK(wq_name, cec_interrupt);
++
++void polling_timeout(unsigned long arg)
++{
++
++#if 0
++ /* fake frame for equipement-less testing */
++
++ cec_instance *this=&our_instance;
++
++ if (this->driver.timer.data++>1000) {
++ printk(KERN_INFO "Fake Rx message\n");
++ this->driver.timer.data=0;
++
++ this->cec.frame.count = 4;
++ this->cec.frame.addr = 4; /* 0-->4 (TV-->MediaPlayer1) */
++ this->cec.frame.data[0]=0x46; /* opcode: "GiveOsd" */
++ this->cec.frame.service = CEC_RX_DONE;
++
++ this->driver.poll_done = true;
++ wake_up_interruptible(&this->driver.wait);
++ }
++#endif
++
++ /* derefered because ATOMIC context of timer does not support I2C_transfert */
++ schedule_work(&wq_name);
++
++}
++#endif
++
++#ifndef IRQ
++/*
++ * TDA irq
++ */
++static irqreturn_t tda_irq(int irq, void *_udc)
++{
++ cec_instance *this=&our_instance;
++ /* printk(KERN_INFO "DBG caught irq:%d\n",irq); */
++
++ /* do it now */
++ mod_timer(&this->driver.timer,jiffies);
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#ifdef TWL4030_HACK
++/*
++ * User Control
++ */
++static void user_control(int key, int press)
++{
++ input_report_key(gkp_input, key, press);
++ input_sync(gkp_input);
++ msleep(20);
++ input_report_key(gkp_input, key, 0);
++ input_sync(gkp_input);
++}
++#endif
++
++/*
++ * CEC callback
++ */
++static void eventCallbackCEC(tmdlHdmiCecEvent_t event, unsigned char *data, unsigned char length)
++{
++ int err=0;
++ cec_instance *this=&our_instance;
++ int opcode;
++ int initiator,receiver;
++
++ if (event == TMDL_HDMICEC_CALLBACK_MESSAGE_AVAILABLE) {
++
++ this->cec.frame.count = length;
++ this->cec.frame.addr = data[1]; /* .AddressByte */
++ initiator = (this->cec.frame.addr >> 4) & 0x0F;
++ this->cec.initiator = initiator;
++ receiver = this->cec.frame.addr & 0x0F;
++ memcpy(&this->cec.frame.data,&data[2],length-2); /* .DataBytes[], length - siezof(length,addr,ack) */
++ opcode=this->cec.frame.data[0];
++ printk(KERN_INFO "hdmicec:Rx:[%x--->%x] %s length:%d addr:%d %02x%02x%02x%02x\n",initiator,receiver,cec_opcode(opcode), \
++ length,data[1],
++ this->cec.frame.data[0], \
++ this->cec.frame.data[1], \
++ this->cec.frame.data[2], \
++ this->cec.frame.data[3]);
++ this->cec.frame.service = CEC_RX_DONE;
++
++ msleep(20);
++
++ /* automatic answering */
++ switch (opcode) {
++ case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \
++ this->cec.phy_addr, \
++ this->cec.device_type));
++ break;
++ case CEC_OPCODE_GET_CEC_VERSION:
++ TRY(tmdlHdmiCecVersion(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.version));
++ break;
++ case CEC_OPCODE_GIVE_OSD_NAME:
++ TRY(tmdlHdmiCecSetOsdName(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.osd_name.data, \
++ this->cec.osd_name.length));
++ break;
++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, \
++ this->cec.vendor_id));
++ break;
++ case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
++ if (this->cec.source_status == CEC_POWER_STATUS_ON) {
++ if (this->cec.initiator != 0x0F) {
++ if (receiver == 0x0F) {
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr));
++ }
++ }
++ }
++ break;
++ case CEC_OPCODE_ACTIVE_SOURCE:
++ if (this->cec.source_status == CEC_POWER_STATUS_ON) {
++ this->cec.source_status = CEC_POWER_STATUS_STANDBY;
++ hdmi_disable(1);
++ this->cec.power = tmPowerOn;
++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); /* keeps CEC alive */
++ }
++ break;
++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
++ TRY(tmdlHdmiCecReportPowerStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.source_status));
++ break;
++ case CEC_OPCODE_STANDBY:
++ /* mind recording device can only be stopped by appli */
++ if (this->cec.device_type != CEC_DEVICE_TYPE_REC_DEVICE) {
++ this->cec.source_status = CEC_POWER_STATUS_STANDBY;
++ hdmi_disable(1);
++ this->cec.power = tmPowerOn;
++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power)); /* keeps CEC alive */
++ }
++ break;
++ case CEC_OPCODE_ROUTING_INFORMATION:
++ case CEC_OPCODE_SET_STREAM_PATH:
++ /* wake-up if called */
++ if (this->cec.phy_addr == (((int)this->cec.frame.data[1] << 8) + this->cec.frame.data[2])) {
++ if (this->cec.source_status != CEC_POWER_STATUS_ON) {
++ this->cec.source_status = CEC_POWER_STATUS_ON;
++ hdmi_enable();
++ }
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr));
++ }
++ break;
++/* case /\* NEW DECK ??? *\/ */
++ case CEC_OPCODE_ROUTING_CHANGE:
++ /* wake-up if called */
++ if (this->cec.phy_addr == (((int)this->cec.frame.data[3] << 8) + this->cec.frame.data[4])) {
++ if (this->cec.source_status != CEC_POWER_STATUS_ON) {
++ this->cec.source_status = CEC_POWER_STATUS_ON;
++ hdmi_enable();
++ }
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr));
++ }
++ break;
++ case CEC_OPCODE_ABORT_MESSAGE:
++ if (this->cec.phy_addr == (((int)this->cec.frame.data[3] << 8) + this->cec.frame.data[4])) {
++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.feature_abort.FeatureOpcode, \
++ this->cec.feature_abort.AbortReason));
++ }
++ break;
++ case CEC_OPCODE_MENU_REQUEST:
++#ifdef TWL4030_HACK
++ this->cec.menu_status = CEC_MENU_STATE_ACTIVATE;
++ TRY(tmdlHdmiCecMenuStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.menu_status));
++ break;
++#endif
++ case CEC_OPCODE_USER_CONTROL_PRESSED:
++ switch (this->cec.frame.data[1]) {
++#ifdef TWL4030_HACK /* AL : hack to bypass keypad */
++ case CEC_REMOTE_BUTTON_SELECT:
++ user_control(353,64);
++ break;
++ case CEC_REMOTE_BUTTON_UP:
++ user_control(103,128);
++ break;
++ case CEC_REMOTE_BUTTON_DOWN:
++ user_control(108,128);
++ break;
++ case CEC_REMOTE_BUTTON_LEFT:
++ user_control(105,128);
++ break;
++ case CEC_REMOTE_BUTTON_RIGHT:
++ user_control(106,128);
++ break;
++ case CEC_REMOTE_BUTTON_EXIT:
++ user_control(14,8);
++ break;
++#endif
++ case CEC_REMOTE_BUTTON_POWER:
++ this->cec.source_status = CEC_POWER_STATUS_ON;
++ hdmi_enable();
++ break;
++ default:
++ this->cec.feature_abort.FeatureOpcode=opcode;
++ this->cec.feature_abort.AbortReason=CEC_ABORT_INVALID_OPERAND;
++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.feature_abort.FeatureOpcode, \
++ this->cec.feature_abort.AbortReason));
++ break;
++ }
++ break;
++#ifdef TWL4030_HACK
++ case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
++ user_control(59,8);
++#endif
++ break;
++ case CEC_OPCODE_FEATURE_ABORT:
++ /* stop any state machine transition */
++ break;
++ case CEC_OPCODE_VENDOR_COMMAND:
++ case CEC_OPCODE_DEVICE_VENDOR_ID:
++ /* hopefully will be handle in userspace */
++ break;
++ default:
++ if (receiver != 0x0F) {
++ this->cec.feature_abort.FeatureOpcode=opcode;
++ this->cec.feature_abort.AbortReason=CEC_ABORT_UNKNOWN_OPCODE;
++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.feature_abort.FeatureOpcode, \
++ this->cec.feature_abort.AbortReason));
++ }
++ break;
++ }
++ this->driver.poll_done = true;
++ wake_up_interruptible(&this->driver.wait);
++ }
++ else if (event == TMDL_HDMICEC_CALLBACK_STATUS) {
++
++ this->cec.frame.count = length;
++ this->cec.frame.addr = data[1]; /* .AddressByte */
++ initiator = (this->cec.frame.addr >> 4) & 0x0F;
++ receiver = this->cec.frame.addr & 0x0F;
++ memcpy(&this->cec.frame.data,&data[2],length-2); /* .DataBytes[], length - siezof(length,addr) */
++ opcode=this->cec.frame.data[0];
++ this->cec.frame.service = CEC_TX_DONE;
++
++ if (length==POLLING_LENGTH) {
++ if (opcode == CEC_MSG_FAIL_DEST_NOT_ACK) {
++ /* no echo means it's mine ! */
++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr));
++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \
++ this->cec.phy_addr, \
++ this->cec.device_type));
++ /* DEVICE VENDOR ID sending after logicial address allocation according to spec 1.4 */
++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, this->cec.vendor_id));
++ }
++ else if (opcode == CEC_MSG_SUCCESS) {
++ /* try next one */
++ this->cec.rx_addr=get_next_logical_addr(this->cec.device_type,this->cec.rx_addr);
++ if (this->cec.rx_addr != CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST) {
++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr));
++ }
++ else {
++ /* no more room, keep and claim unregistred */
++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr));
++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \
++ this->cec.phy_addr, \
++ this->cec.device_type));
++ }
++ }
++ else {
++ printk(KERN_INFO "ACK [%x--->%x] %s\n",initiator,receiver,cec_rxstatus(opcode));
++ }
++ }
++ else {
++ if (CEC_MSG_SUCCESS != opcode) {
++ printk(KERN_INFO "ACK [%x--->%x] %s\n",initiator,receiver,cec_rxstatus(opcode));
++ }
++ }
++
++ this->driver.poll_done = true;
++ wake_up_interruptible(&this->driver.wait);
++
++ }
++ else {
++ LOG(KERN_ERR,"Oups ! Callback got invalid event %d !\n",event);
++ }
++
++ TRY_DONE:
++ (void)err;
++}
++
++/*
++ * DevLib CEC opening
++ */
++static int hdmi_cec_init(cec_instance *this)
++{
++ int err=0;
++
++ /* Real opening */
++ TRY(tmdlHdmiCecOpen(&this->cec.inst));
++
++/* this->cec.vendor_id = 0x006037; /\* NXP (IEEE OUI) *\/ */
++/* this->cec.vendor_id = 0x0000f0; /\* Samsung *\/ */
++ this->cec.vendor_id = 0x00e091; /* LGE */
++
++/* this->cec.version = CEC_VERSION_1_4; */
++ this->cec.version = CEC_VERSION_1_3a;
++ this->cec.osd_name.data[0]=0x54; /* TDA19989 by default */
++ this->cec.osd_name.data[1]=0x44;
++ this->cec.osd_name.data[2]=0x41;
++ this->cec.osd_name.data[3]=0x31;
++ this->cec.osd_name.data[4]=0x39;
++ this->cec.osd_name.data[5]=0x39;
++ this->cec.osd_name.data[6]=0x38;
++ this->cec.osd_name.data[7]=0x39;
++ this->cec.osd_name.length=8;
++
++ TRY(tmdlHdmiCecRegisterCallbacks(this->cec.inst,eventCallbackCEC));
++
++ this->cec.phy_addr = param_addr;
++ this->cec.device_type = device_type(param_device);
++
++ TRY_DONE:
++ return err;
++}
++
++
++/*
++ *
++ * ENTRY POINTS
++ * ------------
++ * LEVEL 3
++ *
++ * -
++ *
++ */
++
++
++
++/*
++ * ioctl driver :: opening
++ */
++
++static int this_cdev_open(struct inode *pInode, struct file *pFile)
++{
++ cec_instance *this;
++ int minor=iminor(pInode);
++
++ if(minor >= MAX_MINOR) {
++ printk(KERN_ERR "hdmicec:%s:only one cec opening please\n",__func__);
++ return -EINVAL;
++ }
++
++ if ((pFile->private_data != NULL) && (pFile->private_data != &our_instance)) {
++ printk(KERN_ERR "hdmicec:%s:pFile missmatch\n",__func__);
++ }
++ this = pFile->private_data = &our_instance;
++ down(&this->driver.sem);
++
++ LOG(KERN_INFO,"major:%d minor:%d user:%d\n", imajor(pInode), iminor(pInode), this->driver.user_counter);
++
++ if ((this->driver.user_counter++) && (this->driver.minor == minor)) {
++ /* init already done */
++ up(&this->driver.sem);
++ return 0;
++ }
++ this->driver.minor = minor;
++
++
++ up(&this->driver.sem);
++ return 0;
++}
++
++/*
++ * ioctl driver :: ioctl
++ */
++static int this_cdev_ioctl(struct inode *pInode, struct file *pFile, unsigned int cmd, unsigned long arg)
++{
++ cec_instance* this = pFile->private_data;
++ int err=0;
++
++ LOG(KERN_INFO,":%s\n",cec_ioctl(_IOC_NR(cmd)));
++
++ BUG_ON(this->driver.minor!=iminor(pInode));
++ if (_IOC_TYPE(cmd) != CEC_IOCTL_BASE) {
++ printk(KERN_INFO "hdmicec:%s:unknown ioctl type: %x\n",__func__,_IOC_TYPE(cmd));
++ return -ENOIOCTLCMD;
++ }
++
++ if (_IOC_DIR(cmd) & _IOC_READ)
++ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)) || !arg;
++ else if (_IOC_DIR(cmd) & _IOC_WRITE)
++ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)) || !arg;
++ if (err) {
++ printk(KERN_ERR "hdmicec:%s:argument access denied (check address vs value)\n",__func__);
++ printk(KERN_ERR "_IOC_DIR:%d arg:%lx\n",_IOC_DIR(cmd),arg);
++ return -EFAULT;
++ }
++
++ down(&this->driver.sem);
++
++ /* Check DevLib consistancy here */
++
++ switch ( _IOC_NR(cmd) )
++ {
++ case CEC_VERBOSE_ON_CMD:
++ {
++ printk(KERN_INFO "verbose on\n");
++ this->param.verbose=1;
++ break;
++ }
++
++ case CEC_VERBOSE_OFF_CMD:
++ {
++ printk(KERN_INFO "verbose off\n");
++ this->param.verbose=0;
++ break;
++ }
++
++ case CEC_BYEBYE_CMD:
++ {
++ LOG(KERN_INFO,"callback release request\n");
++ this->cec.frame.service=CEC_RELEASE;
++ this->driver.poll_done = true;
++ wake_up_interruptible(&this->driver.wait);
++ break;
++ }
++
++ /*
++ no param
++ */
++
++ case CEC_IOCTL_DISABLE_CALIBRATION_CMD:
++ {
++ TRY(tmdlHdmiCecDisableCalibration(this->cec.inst));
++ break;
++ }
++
++ case CEC_IOCTL_INSTANCE_CONFIG_CMD:
++ {
++ TRY(tmdlHdmiCecInstanceConfig(this->cec.inst));
++ break;
++ }
++
++ case CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD:
++ {
++ TRY(tmdlHdmiCecRequestActiveSource(this->cec.inst));
++ break;
++ }
++
++ case CEC_IOCTL_ABORT_MSG_CMD:
++ {
++ TRY(tmdlHdmiCecAbortMessage(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GET_MENU_LANGUAGE_CMD:
++ {
++ TRY(tmdlHdmiCecGetMenuLanguage(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_AUDIO_STATUS_CMD:
++ {
++ TRY(tmdlHdmiCecGiveAudioStatus(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD:
++ {
++ TRY(tmdlHdmiCecGiveDevicePowerStatus(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD:
++ {
++ TRY(tmdlHdmiCecGiveDeviceVendorID(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_OSD_NAME_CMD:
++ {
++ TRY(tmdlHdmiCecGiveOsdName(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_PHY_ADDR_CMD:
++ {
++ TRY(tmdlHdmiCecGivePhysicalAddress(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD:
++ {
++ TRY(tmdlHdmiCecGiveSystemAudioModeStatus(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_IMAGE_VIEW_ON_CMD:
++ {
++ TRY(tmdlHdmiCecImageViewOn(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_POLLING_MSG_CMD:
++ {
++ TRY(tmdlHdmiCecPollingMessage(this->cec.inst,this->cec.rx_addr));
++ break;
++ }
++
++ case CEC_IOCTL_REC_OFF_CMD:
++ {
++ TRY(tmdlHdmiCecRecordOff(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_REC_ON_OWN_SRC_CMD:
++ {
++ TRY(tmdlHdmiCecRecordOnOwnSource(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_REC_TV_SCREEN_CMD:
++ {
++ TRY(tmdlHdmiCecRecordTvScreen(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_STANDBY_CMD:
++ {
++ TRY(tmdlHdmiCecStandby(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_TEXT_VIEW_ON_CMD:
++ {
++ TRY(tmdlHdmiCecTextViewOn(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_TUNER_STEP_DECREMENT_CMD:
++ {
++ TRY(tmdlHdmiCecTunerStepDecrement(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_TUNER_STEP_INCREMENT_CMD:
++ {
++ TRY(tmdlHdmiCecTunerStepIncrement(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_RELEASED_CMD:
++ {
++ TRY(tmdlHdmiCecUserControlReleased(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD:
++ {
++ TRY(tmdlHdmiCecVendorRemoteButtonUp(this->cec.inst,this->cec.initiator));
++ break;
++ }
++
++ case CEC_IOCTL_ROUTING_INFORMATION_CMD:
++ {
++ TRY(tmdlHdmiCecRoutingInformation(this->cec.inst,this->cec.phy_addr));
++ break;
++ }
++
++ case CEC_IOCTL_SET_STREAM_PATH_CMD:
++ {
++ TRY(tmdlHdmiCecSetStreamPath(this->cec.inst,this->cec.phy_addr));
++ break;
++ }
++
++ case CEC_IOCTL_ACTIVE_SRC_CMD:
++ {
++ /* NEW first do a <image view on> */
++ /* NEW when switch by DSS and was inactive */
++ TRY(tmdlHdmiCecActiveSource(this->cec.inst,this->cec.phy_addr));
++ break;
++ }
++
++ case CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD:
++ {
++ TRY(tmdlHdmiCecSystemAudioModeRequest(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.phy_addr));
++ break;
++ }
++
++ /*
++ 1 param
++ */
++
++ case CEC_IOCTL_RX_ADDR_CMD:
++ {
++ /* BUG_ON(copy_from_user(&this->cec.rx_addr,(unsigned char*)arg,sizeof(unsigned char)) != 0); */
++ this->cec.rx_addr=arg;
++ TRY(tmdlHdmiCecSetLogicalAddress(this->cec.inst,this->cec.rx_addr));
++ break;
++ }
++
++ case CEC_IOCTL_PHY_ADDR_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.phy_addr,(unsigned short*)arg,sizeof(unsigned short)) != 0);
++ break;
++ }
++
++ case CEC_IOCTL_GET_CEC_VERSION_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.version,(cec_version*)arg,sizeof(cec_version)) != 0);
++ TRY(tmdlHdmiCecGetCecVersion(this->cec.inst,this->cec.version));
++ break;
++ }
++
++ case CEC_IOCTL_GET_SW_VERSION_CMD:
++ {
++ TRY(tmdlHdmiCecGetSWVersion(&this->cec.sw_version));
++ BUG_ON(copy_to_user((cec_sw_version*)arg,&this->cec.sw_version,sizeof(cec_sw_version)) != 0);
++ break;
++ }
++
++ case CEC_IOCTL_SET_POWER_STATE_CMD:
++ {
++ /* NEW : log : please use DSS */
++ BUG_ON(copy_from_user(&this->cec.power,(cec_power*)arg,sizeof(cec_power)) != 0);
++ TRY(tmdlHdmiCecSetPowerState(this->cec.inst,this->cec.power));
++ break;
++ }
++
++ case CEC_IOCTL_GET_POWER_STATE_CMD:
++ {
++ TRY(tmdlHdmiCecGetPowerState(this->cec.inst,&this->cec.power));
++ BUG_ON(copy_to_user((cec_power*)arg,&this->cec.power,sizeof(cec_power)) != 0);
++ break;
++ }
++
++ case CEC_IOCTL_INSTANCE_SETUP_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.setup,(cec_setup*)arg,sizeof(cec_setup)) != 0);
++ TRY(tmdlHdmiCecInstanceSetup(this->cec.inst,&this->cec.setup));
++ break;
++ }
++
++ case CEC_IOCTL_GET_INSTANCE_SETUP_CMD:
++ {
++ TRY(tmdlHdmiCecGetInstanceSetup(this->cec.inst,&this->cec.setup));
++ BUG_ON(copy_to_user((cec_setup*)arg,&this->cec.setup,sizeof(cec_setup)) != 0);
++ break;
++ }
++
++ /*
++ case CEC_IOCTL_ENABLE_EVENT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.an_event,(cec_event*)arg,sizeof(cec_event)) != 0);
++ TRY(tmdlHdmiCecEnableEvent(this->cec.inst,this->cec.an_event));
++ break;
++ }
++
++ case CEC_IOCTL_DISABLE_EVENT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.an_event,(cec_event*)arg,sizeof(cec_event)) != 0);
++ TRY(tmdlHdmiCecDisableEvent(this->cec.inst,this->cec.an_event));
++ break;
++ }
++ */
++
++ case CEC_IOCTL_SET_MENU_LANGUAGE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.clock,(cec_string*)arg,sizeof(cec_string)) != 0);
++ TRY(tmdlHdmiCecSetMenuLanguage(this->cec.inst,this->cec.string.data));
++ break;
++ }
++
++ case CEC_IOCTL_ENABLE_CALIBRATION_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.clock,(cec_clock*)arg,sizeof(cec_clock)) != 0);
++ TRY(tmdlHdmiCecEnableCalibration(this->cec.inst,this->cec.clock));
++ break;
++ }
++
++ /*
++ >1 param
++ */
++
++ case CEC_IOCTL_WAIT_FRAME_CMD:
++ {
++ this->cec.frame.service = CEC_WAITING;
++ this->driver.poll_done = false;
++ up(&this->driver.sem);
++ if (wait_event_interruptible(this->driver.wait,this->driver.poll_done)) return -ERESTARTSYS;
++ down(&this->driver.sem);
++ BUG_ON(copy_to_user((cec_frame*)arg,&this->cec.frame,sizeof(cec_frame)) != 0);
++ break;
++ }
++
++ case CEC_IOCTL_VERSION_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.version,(cec_version*)arg,sizeof(cec_version)) != 0);
++ TRY(tmdlHdmiCecVersion(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.version));
++ break;
++ }
++
++ case CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.analog_timer,(cec_analogue_timer*)arg,sizeof(cec_analogue_timer)) != 0);
++ TRY(tmdlHdmiCecClearAnalogueTimer(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.analog_timer.DayOfMonth, \
++ this->cec.analog_timer.MonthOfYear, \
++ this->cec.analog_timer.StartTime, \
++ &this->cec.analog_timer.Duration, \
++ this->cec.analog_timer.RecordingSequence, \
++ this->cec.analog_timer.AnalogueBroadcastType, \
++ this->cec.analog_timer.AnalogueFrequency, \
++ this->cec.analog_timer.BroadcastSystem));
++ break;
++ }
++
++ case CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.digital_timer,(cec_digital_timer*)arg,sizeof(cec_digital_timer)) != 0);
++ TRY(tmdlHdmiCecClearDigitalTimer(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.digital_timer.DayOfMonth, \
++ this->cec.digital_timer.MonthOfYear, \
++ this->cec.digital_timer.StartTime, \
++ &this->cec.digital_timer.Duration, \
++ this->cec.digital_timer.RecordingSequence, \
++ &this->cec.digital_timer.ServiceIdentification));
++ break;
++ }
++
++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.etwep,(cec_ext_timer_with_ext_plug*)arg,sizeof(cec_ext_timer_with_ext_plug)) != 0);
++ TRY(tmdlHdmiCecClearExternalTimerWithExternalPlug(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.etwep.DayOfMonth, \
++ this->cec.etwep.MonthOfYear, \
++ this->cec.etwep.StartTime, \
++ &this->cec.etwep.Duration, \
++ this->cec.etwep.RecordingSequence, \
++ this->cec.etwep.ExternalPlug));
++ break;
++ }
++
++ case CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.etwpa,(cec_ext_timer_with_phy_addr*)arg,sizeof(cec_ext_timer_with_phy_addr)) != 0);
++ TRY(tmdlHdmiCecClearExternalTimerWithPhysicalAddress(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.etwpa.DayOfMonth, \
++ this->cec.etwpa.MonthOfYear, \
++ this->cec.etwpa.StartTime, \
++ &this->cec.etwpa.Duration, \
++ this->cec.etwpa.RecordingSequence, \
++ this->cec.etwpa.ExternalPhysicalAddress));
++ break;
++ }
++
++ case CEC_IOCTL_DECK_CTRL_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.deck_ctrl,(cec_deck_ctrl*)arg,sizeof(cec_deck_ctrl)) != 0);
++ TRY(tmdlHdmiCecDeckControl(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.deck_ctrl));
++ break;
++ }
++
++ case CEC_IOCTL_DECK_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.deck_status,(cec_deck_status*)arg,sizeof(cec_deck_status)) != 0);
++ TRY(tmdlHdmiCecDeckStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.deck_status));
++ break;
++ }
++
++ case CEC_IOCTL_DEVICE_VENDOR_ID_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.vendor_id,(unsigned long*)arg,sizeof(unsigned long)) != 0);
++ TRY(tmdlHdmiCecDeviceVendorID(this->cec.inst, \
++ this->cec.vendor_id));
++ break;
++ }
++
++ case CEC_IOCTL_FEATURE_ABORT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.feature_abort,(cec_feature_abort*)arg,sizeof(cec_feature_abort)) != 0);
++ TRY(tmdlHdmiCecFeatureAbort(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.feature_abort.FeatureOpcode, \
++ this->cec.feature_abort.AbortReason));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_DECK_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.satus_request,(cec_status_request*)arg,sizeof(cec_status_request)) != 0);
++ TRY(tmdlHdmiCecGiveDeckStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.satus_request));
++ break;
++ }
++
++ case CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.satus_request,(cec_status_request*)arg,sizeof(cec_status_request*)) != 0);
++ TRY(tmdlHdmiCecGiveTunerDeviceStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.satus_request));
++ break;
++ }
++
++ case CEC_IOCTL_INACTIVE_SRC_CMD:
++ {
++ /* NEW first stand by video */
++ /* NEW when hdmi_disable and was active */
++ TRY(tmdlHdmiCecInactiveSource(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.phy_addr));
++ break;
++ }
++
++ case CEC_IOCTL_MENU_REQUEST_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.menu_request,(cec_menu_request*)arg,sizeof(cec_menu_request)) != 0);
++ TRY(tmdlHdmiCecMenuRequest(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.menu_request));
++ break;
++ }
++
++ case CEC_IOCTL_MENU_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.menu_status,(cec_menu_status*)arg,sizeof(cec_menu_status)) != 0);
++ TRY(tmdlHdmiCecMenuStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.menu_status));
++ break;
++ }
++
++ case CEC_IOCTL_PLAY_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.play,(cec_play*)arg,sizeof(cec_play)) != 0);
++ TRY(tmdlHdmiCecPlay(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.play));
++ break;
++ }
++
++ case CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.analog_service,(cec_analogue_service*)arg,sizeof(cec_analogue_service)) != 0);
++ TRY(tmdlHdmiCecRecordOnAnalogueService(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.analog_service.AnalogueBroadcastType, \
++ this->cec.analog_service.AnalogueFrequency, \
++ this->cec.analog_service.BroadcastSystem));
++ break;
++ }
++
++ case CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.digital_service,(cec_digital_service*)arg,sizeof(cec_digital_service)) != 0);
++ TRY(tmdlHdmiCecRecordOnDigitalService(this->cec.inst, \
++ this->cec.initiator, \
++ &this->cec.digital_service));
++ break;
++ }
++
++ case CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD:
++ {
++ TRY(tmdlHdmiCecRecordOnExternalPhysicalAddress(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.phy_addr));
++ break;
++ }
++
++ case CEC_IOCTL_REC_ON_EXT_PLUG_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.ext_plug,(cec_ext_plug*)arg,sizeof(cec_ext_plug)) != 0);
++ TRY(tmdlHdmiCecRecordOnExternalPlug(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.ext_plug));
++ break;
++ }
++
++ case CEC_IOCTL_REC_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.rec_status,(cec_rec_status*)arg,sizeof(cec_rec_status)) != 0);
++ TRY(tmdlHdmiCecRecordStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.rec_status));
++ break;
++ }
++
++ case CEC_IOCTL_REPORT_AUDIO_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.audio_status,(cec_audio_status*)arg,sizeof(cec_audio_status)) != 0);
++ TRY(tmdlHdmiCecReportAudioStatus(this->cec.inst, \
++ this->cec.initiator, \
++ &this->cec.audio_status));
++ break;
++ }
++
++ case CEC_IOCTL_REPORT_PHY_ADDR_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.device_type,(cec_device_type*)arg,sizeof(cec_device_type)) != 0);
++ TRY(tmdlHdmiCecReportPhysicalAddress(this->cec.inst, \
++ this->cec.phy_addr, \
++ this->cec.device_type));
++ break;
++ }
++
++ case CEC_IOCTL_REPORT_POWER_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.source_status,(cec_power_status*)arg,sizeof(cec_power_status)) != 0);
++ TRY(tmdlHdmiCecReportPowerStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.source_status));
++ break;
++ }
++
++ case CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.analog_service,(cec_analogue_service*)arg,sizeof(cec_analogue_service)) != 0);
++ TRY(tmdlHdmiCecSelectAnalogueService(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.analog_service.AnalogueBroadcastType, \
++ this->cec.analog_service.AnalogueFrequency, \
++ this->cec.analog_service.BroadcastSystem));
++ break;
++ }
++
++ case CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.digital_service,(cec_digital_service*)arg,sizeof(cec_digital_service)) != 0);
++ TRY(tmdlHdmiCecSelectDigitalService(this->cec.inst, \
++ this->cec.initiator, \
++ &this->cec.digital_service));
++ break;
++ }
++
++ case CEC_IOCTL_SET_ANALOGUE_TIMER_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.analog_timer,(cec_analogue_timer*)arg,sizeof(cec_analogue_timer)) != 0);
++ TRY(tmdlHdmiCecSetAnalogueTimer(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.analog_timer.DayOfMonth, \
++ this->cec.analog_timer.MonthOfYear, \
++ this->cec.analog_timer.StartTime, \
++ &this->cec.analog_timer.Duration, \
++ this->cec.analog_timer.RecordingSequence, \
++ this->cec.analog_timer.AnalogueBroadcastType, \
++ this->cec.analog_timer.AnalogueFrequency, \
++ this->cec.analog_timer.BroadcastSystem));
++ break;
++ }
++
++ case CEC_IOCTL_SET_AUDIO_RATE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.audio_rate,(cec_audio_rate*)arg,sizeof(cec_audio_rate)) != 0);
++ TRY(tmdlHdmiCecSetAudioRate(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.audio_rate));
++ break;
++ }
++
++ case CEC_IOCTL_SET_DIGITAL_TIMER_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.digital_timer,(cec_digital_timer*)arg,sizeof(cec_digital_timer)) != 0);
++ TRY(tmdlHdmiCecSetDigitalTimer(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.digital_timer.DayOfMonth, \
++ this->cec.digital_timer.MonthOfYear, \
++ this->cec.digital_timer.StartTime, \
++ &this->cec.digital_timer.Duration, \
++ this->cec.digital_timer.RecordingSequence, \
++ &this->cec.digital_timer.ServiceIdentification));
++ break;
++ }
++
++ case CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.etwep,(cec_ext_timer_with_ext_plug*)arg,sizeof(cec_ext_timer_with_ext_plug)) != 0);
++ TRY(tmdlHdmiCecSetExternalTimerWithExternalPlug(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.etwep.DayOfMonth, \
++ this->cec.etwep.MonthOfYear, \
++ this->cec.etwep.StartTime, \
++ &this->cec.etwep.Duration, \
++ this->cec.etwep.RecordingSequence, \
++ this->cec.etwep.ExternalPlug));
++ break;
++ }
++
++ case CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.etwpa,(cec_ext_timer_with_phy_addr*)arg,sizeof(cec_ext_timer_with_phy_addr)) != 0);
++ TRY(tmdlHdmiCecSetExternalTimerWithPhysicalAddress(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.etwpa.DayOfMonth, \
++ this->cec.etwpa.MonthOfYear, \
++ this->cec.etwpa.StartTime, \
++ &this->cec.etwpa.Duration, \
++ this->cec.etwpa.RecordingSequence, \
++ this->cec.etwpa.ExternalPhysicalAddress));
++ break;
++ }
++
++ case CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.sys_audio_status,(cec_sys_audio_status*)arg,sizeof(cec_sys_audio_status)) != 0);
++ TRY(tmdlHdmiCecSetSystemAudioMode(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.sys_audio_status));
++ break;
++ }
++
++ case CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.sys_audio_status,(cec_sys_audio_status*)arg,sizeof(cec_sys_audio_status)) != 0);
++ TRY(tmdlHdmiCecSystemAudioModeStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.sys_audio_status));
++ break;
++ }
++
++ case CEC_IOCTL_TIMER_CLEARED_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.timer_cleared_status,(cec_timer_cleared_status*)arg,sizeof(cec_timer_cleared_status)) != 0);
++ TRY(tmdlHdmiCecTimerClearedStatus(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.timer_cleared_status));
++ break;
++ }
++
++ case CEC_IOCTL_TIMER_STATUS_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.timer_status,(cec_timer_status*)arg,sizeof(cec_timer_status)) != 0);
++ TRY(tmdlHdmiCecTimerStatus(this->cec.inst, \
++ this->cec.initiator, \
++ &this->cec.timer_status));
++ break;
++ }
++
++ case CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.tdsa,(cec_tuner_device_status_analogue*)arg,sizeof(cec_tuner_device_status_analogue)) != 0);
++ TRY(tmdlHdmiCecTunerDeviceStatusAnalogue(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.tdsa.RecordingFlag, \
++ this->cec.tdsa.TunerDisplayInfo, \
++ this->cec.tdsa.AnalogueBroadcastType, \
++ this->cec.tdsa.AnalogueFrequency, \
++ this->cec.tdsa.BroadcastSystem));
++ break;
++ }
++
++ case CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.tdsd,(cec_tuner_device_status_digital*)arg,sizeof(cec_tuner_device_status_digital)) != 0);
++ TRY(tmdlHdmiCecTunerDeviceStatusDigital(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.tdsd.RecordingFlag, \
++ this->cec.tdsd.TunerDisplayInfo, \
++ &this->cec.tdsd.ServiceIdentification));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.user_ctrl,(cec_user_ctrl*)arg,sizeof(cec_user_ctrl)) != 0);
++ TRY(tmdlHdmiCecUserControlPressed(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.user_ctrl));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_PLAY_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.play,(cec_play*)arg,sizeof(cec_play)) != 0);
++ TRY(tmdlHdmiCecUserControlPressedPlay(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.play));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0);
++ TRY(tmdlHdmiCecUserControlPressedSelectAudioInput(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.select));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0);
++ TRY(tmdlHdmiCecUserControlPressedSelectAVInput(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.select));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.select,(unsigned char*)arg,sizeof(unsigned char)) != 0);
++ TRY(tmdlHdmiCecUserControlPressedSelectMedia(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.select));
++ break;
++ }
++
++ case CEC_IOCTL_USER_CTRL_TUNE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.user_ctrl_tune,(cec_user_ctrl_tune*)arg,sizeof(cec_user_ctrl_tune)) != 0);
++ TRY(tmdlHdmiCecUserControlPressedTune(this->cec.inst, \
++ this->cec.initiator, \
++ &this->cec.user_ctrl_tune));
++ break;
++ }
++
++ case CEC_IOCTL_SET_OSD_NAME_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.osd_name,(cec_string*)arg,sizeof(cec_string)) != 0);
++ TRY(tmdlHdmiCecSetOsdName(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.osd_name.data, \
++ this->cec.osd_name.length));
++ break;
++ }
++
++ case CEC_IOCTL_SET_OSD_STRING_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.osd_string,(cec_osd_string*)arg,sizeof(cec_osd_string)) != 0);
++ TRY(tmdlHdmiCecSetOsdString(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.osd_string.DisplayControl, \
++ this->cec.osd_string.data, \
++ this->cec.osd_string.length));
++ break;
++ }
++
++ case CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0);
++ TRY(tmdlHdmiCecSetTimerProgramTitle(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.string.data, \
++ this->cec.string.length));
++ break;
++ }
++
++ case CEC_IOCTL_VENDOR_COMMAND_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0);
++ TRY(tmdlHdmiCecVendorCommand(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.string.data, \
++ this->cec.string.length));
++ break;
++ }
++
++ case CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.string,(cec_string*)arg,sizeof(cec_string)) != 0);
++ TRY(tmdlHdmiCecVendorRemoteButtonDown(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.string.data, \
++ this->cec.string.length));
++ break;
++ }
++
++ case CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD:
++ {
++ BUG_ON(copy_from_user(&this->cec.vcwi,(cec_vendor_command_with_id*)arg,sizeof(cec_vendor_command_with_id)) != 0);
++ TRY(tmdlHdmiCecVendorCommandWithID(this->cec.inst, \
++ this->cec.initiator, \
++ this->cec.vcwi.VendorID, \
++ this->cec.vcwi.cmd.data, \
++ this->cec.vcwi.cmd.length));
++ break;
++ }
++
++ /* case : */
++ /* { */
++ /* BUG_ON(copy_from_user(&this->cec.,(*)arg,sizeof()) != 0); */
++ /* TRY((this->cec.inst, \ */
++ /* this->cec., \ */
++ /* &this->cec.)); */
++ /* break; */
++ /* } */
++
++ default:
++ {
++ /* unrecognized ioctl */
++ printk(KERN_INFO " unknown ioctl %x\n",cmd);
++ up(&this->driver.sem);
++ return -ENOIOCTLCMD;
++ }
++ }
++
++ TRY_DONE:
++ up(&this->driver.sem);
++ return err;
++}
++
++/*
++ * ioctl driver :: releasing
++ */
++static int this_cdev_release(struct inode *pInode, struct file *pFile)
++{
++ cec_instance* this = pFile->private_data;
++ int minor = iminor(pInode);
++
++ LOG(KERN_INFO,"called\n");
++
++ if(minor >= MAX_MINOR) {
++ return -EINVAL;
++ }
++
++ BUG_ON(this->driver.minor!=iminor(pInode));
++ down(&this->driver.sem);
++
++ this->driver.user_counter--;
++ if(this->driver.user_counter == 0) {
++ pFile->private_data = NULL;
++ }
++ else {
++ LOG(KERN_INFO,"Still %d user pending\n",this->driver.user_counter);
++ }
++
++ up(&this->driver.sem);
++ return 0;
++}
++
++/*
++ * I2C client :: creation
++ */
++static int __devinit this_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++ cec_instance *this=&our_instance;
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++ /*
++ I2C setup
++ */
++ if (this->driver.i2c_client) {
++ dev_err(&this->driver.i2c_client->dev, "<%s> CEC Device already created \n",
++ __func__);
++ return -ENODEV;
++ }
++
++ this->driver.i2c_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
++ if (!this->driver.i2c_client) {
++ return -ENOMEM;
++ }
++ memset(this->driver.i2c_client, 0, sizeof(struct i2c_client));
++
++ strncpy(this->driver.i2c_client->name, CEC_NAME, I2C_NAME_SIZE);
++ this->driver.i2c_client->addr = TDA99XCEC_I2C_SLAVEADDRESS;
++ this->driver.i2c_client->adapter = client->adapter;
++
++ i2c_set_clientdata(client, this->driver.i2c_client);
++
++ tmdlHdmiCecGetSWVersion(&this->cec.sw_version);
++ LOG(KERN_INFO,"HDMI CEC SW Version:%lu.%lu compatibility:%lu\n", \
++ this->cec.sw_version.majorVersionNr,\
++ this->cec.sw_version.minorVersionNr,\
++ this->cec.sw_version.compatibilityNr);
++
++ /* I2C ok, then let's startup CEC */
++
++ /* prepare event */
++ this->driver.poll_done = true; /* currently idle */
++ init_waitqueue_head(&this->driver.wait);
++#ifndef IRQ
++ init_timer(&this->driver.timer); /* do it before request_irq */
++ this->driver.timer.function=polling_timeout;
++ this->driver.timer.data=0;
++ this->driver.timer.expires = jiffies + HZ; /* start polling in one sec */
++ add_timer(&this->driver.timer);
++#else
++ register_cec_interrupt((cec_callback_t)cec_interrupt);
++#endif
++
++#ifndef IRQ
++ /* FRO calibration */
++ err=gpio_request(TDA_IRQ_CALIB,"tda19989 calibration");
++ if (err < 0) {
++ printk(KERN_ERR "hdmicec:%s:cannot use GPIO 107\n",__func__);
++ goto i2c_out;
++ }
++ /* turn GPIO into IRQ
++ gpio_direction_input(TDA_IRQ_CALIB);
++ msleep(1);
++ if (request_irq(gpio_to_irq(TDA_IRQ_CALIB), \
++ tda_irq, IRQF_TRIGGER_FALLING|IRQF_DISABLED, "TDA IRQ", NULL)) {
++ printk(KERN_ERR "hdmicec:%s:Cannot request irq, err:%d\n",__func__,err);
++ gpio_free(TDA_IRQ_CALIB);
++ goto i2c_out;
++ }
++ */
++#endif
++
++ err = hdmi_cec_init(this);
++ if (err) goto i2c_out;
++ this->cec.rx_addr=CEC_LOGICAL_ADDRESS_UNREGISTRED_BROADCAST;
++
++ if (get_hpd_status()) {
++ cec_on(this);
++ // disable_irq(gpio_to_irq(TDA_IRQ_CALIB));
++ cec_interrupt(NULL); /* initiate polling */
++ // enable_irq(gpio_to_irq(TDA_IRQ_CALIB));
++ }
++ else {
++ cec_standby(this);
++ }
++
++ return 0;
++
++ i2c_out:
++ LOG(KERN_INFO,"HDMICEC eject: this->driver.i2c_client removed\n");
++ tmdlHdmiCecClose(this->cec.inst);
++ kfree(this->driver.i2c_client);
++ this->driver.i2c_client = NULL;
++
++ return err;
++}
++
++/*
++ * I2C client :: destroy
++ */
++static int this_i2c_remove(struct i2c_client *client)
++{
++ cec_instance *this=&our_instance;
++ int err=0;
++
++ LOG(KERN_INFO,"called\n");
++
++ err=tmdlHdmiCecClose(this->cec.inst);
++
++ if (!client->adapter) {
++ dev_err(&this->driver.i2c_client->dev, "<%s> No CEC Device \n",
++ __func__);
++ return -ENODEV;
++ }
++ kfree(this->driver.i2c_client);
++ this->driver.i2c_client = NULL;
++
++ return err;
++}
++
++/*
++ * I2C client driver (backend)
++ * -----------------
++ */
++static struct i2c_driver this_i2c_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = CEC_NAME,
++ },
++ .probe = this_i2c_probe,
++ .remove = this_i2c_remove,
++ .id_table = this_i2c_id,
++};
++
++/*
++ * ioctl driver (userland frontend)
++ * ------------
++ */
++static struct file_operations this_cdev_fops = {
++ owner: THIS_MODULE,
++ open: this_cdev_open,
++ release: this_cdev_release,
++// ioctl: this_cdev_ioctl,
++};
++
++/*
++ * Module :: start up
++ */
++static int __init cec_init(void)
++{
++ cec_instance *this=&our_instance;
++ dev_t dev=0;
++ int err=0;
++
++ /*
++ general device context
++ */
++ memset(this,0,sizeof(cec_instance));
++ this->param.verbose = param_verbose;
++ this->param.major = param_major;
++ this->param.minor = param_minor;
++
++ /* Hello word */
++ printk(KERN_INFO "%s(%s) %d.%d.%d compiled: %s %s %s\n", HDMICEC_NAME, TDA_NAME, TDA_VERSION_MAJOR,
++ TDA_VERSION_MINOR, TDA_VERSION_PATCHLEVEL, __DATE__, __TIME__, TDA_VERSION_EXTRA);
++ if (this->param.verbose) LOG(KERN_INFO,".verbose mode\n");
++
++ /*
++ plug I2C (backend : Hw interfacing)
++ */
++ err = i2c_add_driver(&this_i2c_driver);
++ if (err < 0) {
++ printk(KERN_ERR "Driver registration failed\n");
++ return -ENODEV;
++ }
++
++ if (this->driver.i2c_client == NULL) {
++ printk(KERN_ERR "this->driver.i2c_client not allocated\n");
++ err = -ENODEV;
++ goto init_out;
++ }
++
++ /*
++ cdev init (userland frontend)
++ */
++
++ /* arbitray range of device numbers */
++ if (this->param.major) {
++ /* user force major number @ insmod */
++ dev = MKDEV(this->param.major, this->param.minor);
++ err = register_chrdev_region(dev,MAX_MINOR,HDMICEC_NAME);
++ if (err) {
++ printk(KERN_ERR "unable to register %s, dev=%d %s\n",HDMICEC_NAME,dev,ERR_TO_STR(err));
++ goto init_out;
++ }
++ } else {
++ /* fully dynamic major number */
++ err = alloc_chrdev_region(&dev, this->param.minor, MAX_MINOR,HDMICEC_NAME);
++ if (err) {
++ printk(KERN_ERR "unable to alloc chrdev region for %s, dev=%d %s\n",HDMICEC_NAME,dev,ERR_TO_STR(err));
++ goto init_out;
++ }
++ this->param.major = MAJOR(dev);
++ }
++
++ cdev_init(this_cdev, &this_cdev_fops);
++ this_cdev->owner = THIS_MODULE;
++
++ this->driver.class = class_create(THIS_MODULE, HDMICEC_NAME);
++ if (IS_ERR(this->driver.class)) {
++ printk(KERN_INFO "Error creating mmap device class.\n");
++ err =-EIO;
++ goto init_out;
++ }
++ this->driver.dev = device_create(this->driver.class, NULL, dev, NULL, HDMICEC_NAME);
++
++ this->driver.devno = dev;
++ err = cdev_add(this_cdev, this->driver.devno, MAX_MINOR);
++ if (err){
++ printk(KERN_INFO "unable to add device for %s, ipp_driver.devno=%d %s\n",HDMICEC_NAME,this->driver.devno,ERR_TO_STR(err));
++ device_destroy(this->driver.class,this->driver.devno);
++ class_destroy(this->driver.class);
++ unregister_chrdev_region(this->driver.devno, MAX_MINOR);
++ goto init_out;
++ }
++
++#ifdef TWL4030_HACK
++ /* AL : hack to bypass keypad */
++ gkp_input = get_twm4030_input();
++#endif
++
++ /*
++ general device context
++ */
++ sema_init(&this->driver.sem, 1);
++ this->driver.deinit_req=0;
++
++ return 0;
++
++ init_out:
++ i2c_del_driver(&this_i2c_driver);
++ return err;
++}
++
++/*
++ * Module :: shut down
++ */
++static void __exit cec_exit(void)
++{
++ cec_instance *this=&our_instance;
++
++ LOG(KERN_INFO,"called\n");
++
++#ifndef IRQ
++ // free_irq(gpio_to_irq(TDA_IRQ_CALIB), NULL);
++#endif
++
++ unregister_cec_interrupt();
++ this->driver.deinit_req=1;
++#ifndef IRQ
++ if (wait_event_interruptible(this->driver.wait,this->driver.deinit_req>1)) {
++ /* oups... just wait... */
++ msleep(CHECK_EVERY_XX_MS*20);
++ }
++#endif
++
++#ifndef IRQ
++ /* release GPIO */
++ gpio_free(TDA_IRQ_CALIB);
++#endif
++
++ /* unregister cdevice */
++ cdev_del(this_cdev);
++ unregister_chrdev_region(this->driver.devno, MAX_MINOR);
++
++ /* unregister device */
++ device_destroy(this->driver.class,this->driver.devno);
++ class_destroy(this->driver.class);
++
++ /* unregister i2c */
++ i2c_del_driver(&this_i2c_driver);
++
++}
++
++
++/*
++ * Module
++ * ------
++ */
++/* late_initcall(cec_init); */
++module_init(cec_init);
++module_exit(cec_exit);
++
++/*
++ * Disclamer
++ * ---------
++ */
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Andre Lepine <andre.lepine@nxp.com>");
++MODULE_DESCRIPTION(HDMICEC_NAME " driver");
++
+diff --git a/drivers/video/nxp/tda998x_cec.h b/drivers/video/nxp/tda998x_cec.h
+new file mode 100755
+index 0000000..fcc3cfa
+--- /dev/null
++++ b/drivers/video/nxp/tda998x_cec.h
+@@ -0,0 +1,140 @@
++/*****************************************************************************/
++/* Copyright (c) 2009 NXP Semiconductors BV */
++/* */
++/* 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, using version 2 of the License. */
++/* */
++/* This program is distributed in the hope that it will be useful, */
++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
++/* GNU General Public License for more details. */
++/* */
++/* You should have received a copy of the GNU General Public License */
++/* along with this program; if not, write to the Free Software */
++/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
++/* USA. */
++/* */
++/*****************************************************************************/
++
++#ifndef __cec_h__
++#define __cec_h__
++
++#include "tda998x_ioctl.h"
++
++#define HDMICEC_NAME "hdmicec"
++
++#define CEC_MAJOR 234 /* old-style interval of device numbers */
++#define MAX_MINOR 1 /* 1 minor but 2 access : 1 more for pooling */
++
++/* common I2C define with kernel */
++/* should be the same as arch/arm/mach-omap2/board-zoom2.c */
++#define CEC_NAME "tda99Xcec"
++#define TDA99XCEC_I2C_SLAVEADDRESS 0x34
++
++#define TDA_IRQ_CALIB 107
++#define POLLING_LENGTH 3
++
++#define EDID_BLOCK_COUNT 4
++#define EDID_BLOCK_SIZE 128
++
++#ifdef GPL
++#define CHECK_EVERY_XX_MS 500 /* ms */
++#else
++#define CHECK_EVERY_XX_MS 10 /* ms */
++#endif
++
++#define LOG(type,fmt,args...) {if (this->param.verbose) {printk(type HDMICEC_NAME":%s:" fmt, __func__, ## args);}}
++/* not found the kernel "strerror" one! If someone knows, please replace it */
++#define ERR_TO_STR(e)((e == -ENODATA)?"ENODATA, no data available":\
++ (e == -ENOMEM)? "ENOMEM, no memory available":\
++ (e == -EINVAL)? "EINVAL, invalid argument":\
++ (e == -EIO)? "EIO, input/output error":\
++ (e == -ETIMEDOUT)? "ETIMEOUT, timeout has expired":\
++ (e == -EBUSY)? "EBUSY, device or resource busy":\
++ (e == -ENOENT)? "ENOENT, no such file or directory":\
++ (e == -EACCES)? "EACCES, permission denied":\
++ (e == 0)? "":\
++ "!UNKNOWN!")
++
++#define TRY(fct) { \
++ err=(fct); \
++ if (err) { \
++ printk(KERN_ERR "%s? in %s line %d\n",hdmi_cec_err_string(err),__func__,__LINE__); \
++ goto TRY_DONE; \
++ } \
++ }
++
++typedef void (*cec_callback_t) (struct work_struct *dummy);
++
++typedef struct {
++ /* module params */
++ struct {
++ int verbose;
++ int major;
++ int minor;
++ } param;
++ /* driver */
++ struct {
++ struct class *class;
++ struct device *dev;
++ int devno;
++ struct i2c_client *i2c_client;
++ struct semaphore sem;
++ int user_counter;
++ int minor;
++ wait_queue_head_t wait;
++ bool poll_done;
++ int deinit_req;
++ struct timer_list timer;
++ } driver;
++ /* cec */
++ struct {
++ int inst;
++ unsigned char rx_addr;
++ unsigned short phy_addr;
++ unsigned char initiator;
++ cec_version version;
++ cec_sw_version sw_version;
++ cec_power power;
++ cec_setup setup;
++ cec_clock clock;
++ cec_analogue_timer analog_timer;
++ cec_digital_timer digital_timer;
++ cec_ext_timer_with_ext_plug etwep;
++ cec_ext_timer_with_phy_addr etwpa;
++ cec_deck_ctrl deck_ctrl;
++ cec_deck_status deck_status;
++ unsigned long vendor_id;
++ cec_feature_abort feature_abort;
++ cec_status_request satus_request;
++ cec_menu_request menu_request;
++ cec_menu_status menu_status;
++ cec_play play;
++ cec_analogue_service analog_service;
++ cec_digital_service digital_service;
++ cec_ext_plug ext_plug;
++ cec_rec_status rec_status;
++ cec_audio_status audio_status;
++ cec_device_type device_type;
++ cec_power_status source_status;
++ cec_audio_rate audio_rate;
++ cec_sys_audio_status sys_audio_status;
++ cec_timer_cleared_status timer_cleared_status;
++ cec_timer_status timer_status;
++ cec_tuner_device_status_analogue tdsa;
++ cec_tuner_device_status_digital tdsd;
++ cec_user_ctrl user_ctrl;
++ unsigned char select;
++ cec_user_ctrl_tune user_ctrl_tune;
++ cec_frame frame;
++ bool byebye;
++ cec_string string;
++ cec_string osd_name;
++ cec_osd_string osd_string;
++ cec_vendor_command_with_id vcwi;
++ } cec;
++} cec_instance;
++
++#endif /* __cec_h__ */
++
+diff --git a/drivers/video/nxp/tda998x_ioctl.h b/drivers/video/nxp/tda998x_ioctl.h
+new file mode 100755
+index 0000000..cd5b0cd
+--- /dev/null
++++ b/drivers/video/nxp/tda998x_ioctl.h
+@@ -0,0 +1,1123 @@
++/**
++ * Copyright (C) 2006 NXP N.V., All Rights Reserved.
++ * This source code and any compilation or derivative thereof is the proprietary
++ * information of NXP N.V. and is confidential in nature. Under no circumstances
++ * is this software to be exposed to or placed under an Open Source License of
++ * any type without the expressed written permission of NXP N.V.
++ *
++ * Version Revision: 1.0
++ *
++ * Date Date: 27/10/09
++ *
++ * Brief API for the TDA1998x HDMI Transmitters
++ *
++ **/
++
++#include <linux/types.h>
++
++#ifndef __tx_ioctl__
++#define __tx_ioctl__
++
++#ifdef __tx_h__
++
++#define TRANS_TYPE 1
++
++#if TRANS_TYPE
++
++#define EXAMPLE_MAX_SVD 30
++
++/*
++ trans-type
++*/
++typedef tmSWVersion_t tda_version;
++typedef tmPowerState_t tda_power;
++typedef tmdlHdmiTxInstanceSetupInfo_t tda_setup;
++typedef tmdlHdmiTxCapabilities_t tda_capabilities;
++typedef tmdlHdmiTxVideoOutConfig_t tda_video_out;
++typedef tmdlHdmiTxVideoInConfig_t tda_video_in;
++typedef tmdlHdmiTxSinkType_t tda_sink;
++typedef tmdlHdmiTxAudioInConfig_t tda_audio_in;
++typedef tmdlHdmiTxEdidAudioDesc_t tda_edid_audio_desc;
++typedef tmdlHdmiTxShortVidDesc_t tda_edid_video_desc;
++typedef tmdlHdmiTxEvent_t tda_event;
++typedef tmdlHdmiTxInstanceSetupInfo_t tda_setup_info;
++typedef tmdlHdmiTxEdidVideoTimings_t tda_edid_video_timings;
++typedef tmdlHdmiTxPictAspectRatio_t tda_edid_tv_aspect_ratio;
++typedef tmdlHdmiTxHdcpCheck_t tda_hdcp_status;
++#if defined (TMFL_TDA19989) || defined (TMFL_TDA9984)
++typedef tmdlHdmiTxHdcpStatus_t tda_hdcp_fail;
++#endif
++#ifdef TMFL_TDA19989
++typedef tmdlHdmiTxEdidLatency_t tda_edid_latency;
++#endif
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxGamutData_t data;
++} tda_gammut;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxVsPktData_t data;
++} tda_vs_infoframe;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxSpdIfData_t data;
++} tda_spd_infoframe;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxMpsIfData_t data;
++} tda_mps_infoframe;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxIsrc1PktData_t data;
++} tda_isrc1;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxIsrc2PktData_t data;
++} tda_isrc2;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxAcpPktData_t data;
++} tda_acp;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxGcpPktData_t data;
++} tda_gcp;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxAviIfData_t data;
++} tda_video_infoframe;
++
++typedef struct {
++ Bool enable;
++ tmdlHdmiTxAudIfData_t data;
++} tda_audio_infoframe;
++
++typedef struct {
++ tmdlHdmiTxVidFmt_t id;
++ tmdlHdmiTxVidFmtSpecs_t spec;
++} tda_video_format;
++
++typedef struct {
++ tda_video_in video_in;
++ tda_video_out video_out;
++ tda_audio_in audio_in; /* Mind tda_set_audio_in if you change this */
++ tda_sink sink; /* Mind tda_set_audio_in if you change this */
++} tda_set_in_out;
++
++typedef struct {
++ tda_audio_in audio_in;
++ tda_sink sink;
++} tda_set_audio_in;
++
++typedef struct {
++ tda_edid_audio_desc desc[EXAMPLE_MAX_SVD];
++ unsigned int max;
++ unsigned int written;
++ unsigned char flags;
++} tda_edid_audio_caps;
++
++typedef struct {
++ tda_edid_video_desc desc[EXAMPLE_MAX_SVD];
++ unsigned int max;
++ unsigned int written;
++ unsigned char flags;
++} tda_edid_video_caps;
++
++typedef struct {
++ tmdlHdmiTxEdidStatus_t status;
++ unsigned char block_count;
++} tda_edid;
++
++typedef struct {
++ tmdlHdmiTxEdidVideoTimings_t desc[EXAMPLE_MAX_SVD];
++ unsigned char max;
++ unsigned char written;
++} tda_edid_dtd;
++
++typedef struct {
++ tmdlHdmiTxEdidFirstMD_t desc1[EXAMPLE_MAX_SVD];
++ tmdlHdmiTxEdidSecondMD_t desc2[EXAMPLE_MAX_SVD];
++ tmdlHdmiTxEdidOtherMD_t other[EXAMPLE_MAX_SVD];
++ unsigned char max;
++ unsigned char written;
++} tda_edid_md;
++
++#else
++
++#error do not compiled this !
++
++typedef enum
++{
++ TDA_HDCP_ACTIVE = 0, /**< HDCP encryption status switched to active */
++ TDA_HDCP_INACTIVE = 1, /**< HDCP encryption status switched to inactive */
++ TDA_HPD_ACTIVE = 2, /**< Hotplug status switched to active */
++ TDA_HPD_INACTIVE = 3, /**< Hotplug status switched to inactive */
++ TDA_RX_KEYS_RECEIVED = 4, /**< Receiver(s) key(s) received */
++ TDA_RX_DEVICE_ACTIVE = 5, /**< Rx device is connected and active */
++ TDA_RX_DEVICE_INACTIVE = 6, /**< Rx device is connected but inactive (standby) */
++ TDA_EDID_RECEIVED = 7, /**< EDID has been received */
++ TDA_VS_RPT_RECEIVED = 8, /**< VS interrupt has been received */
++#ifdef HDMI_TX_REPEATER_ISR_MODE
++ TDA_B_STATUS = 9, /**< TX received BStatus */
++#endif /* HDMI_TX_REPEATER_ISR_MODE */
++ TDA_DEBUG_EVENT_1 = 10 /**< This is a debug event */
++} tda_event;
++
++typedef struct {
++ unsigned char format; /* EIA/CEA861 mode */
++ unsigned char channels; /* number of channels */
++ unsigned char supportedFreqs; /* bitmask of supported frequencies */
++ unsigned char supportedRes; /* bitmask of supported resolutions (LPCM only) */
++ unsigned char maxBitrate; /* Maximum bitrate divided by 8KHz (compressed formats only) */
++} tda_edid_audio_desc;
++
++typedef enum {
++ TDA_EDID_READ = 0, /**< All blocks read OK */
++ TDA_EDID_READ_INCOMPLETE = 1, /**< All blocks read OK but buffer too small to return all of them */
++ TDA_EDID_ERROR_CHK_BLOCK_0 = 2, /**< Block 0 checksum error */
++ TDA_EDID_ERROR_CHK = 3, /**< Block 0 OK, checksum error in one or more other blocks */
++ TDA_EDID_NOT_READ = 4, /**< EDID not read */
++ TDA_EDID_STATUS_INVALID = 5 /**< Invalid */
++} tda_edid_status;
++
++typedef struct {
++ int HBR; /**< High Bitrate Audio packet */
++ int DST; /**< Direct Stream Transport audio packet */
++ int oneBitAudio; /**< One Bit Audio sample packet */
++} tda_audio_packet;
++
++typedef enum {
++ TDA_AFMT_SPDIF = 0, /**< SPDIF */
++ TDA_AFMT_I2S = 1, /**< I2S */
++ TDA_AFMT_OBA = 2, /**< One bit audio / DSD */
++ TDA_AFMT_DST = 3, /**< DST */
++ TDA_AFMT_HBR = 4 /**< HBR */
++} tda_audio_format;
++
++typedef enum {
++ TDA_AFS_32K = 0, /**< 32kHz */
++ TDA_AFS_44K = 1, /**< 44.1kHz */
++ TDA_AFS_48K = 2, /**< 48kHz */
++ TDA_AFS_88K = 3, /**< 88.2kHz */
++ TDA_AFS_96K = 4, /**< 96kHz */
++ TDA_AFS_176K = 5, /**< 176.4kHz */
++ TDA_AFS_192K = 6 /**< 192kHz */
++} tda_audio_rate;
++
++typedef enum {
++ TDA_I2SQ_16BITS = 16, /**< 16 bits */
++ TDA_I2SQ_32BITS = 32, /**< 32 bits */
++ TDA_I2SQ_OTHERS = 0 /**< for SPDIF and DSD */
++} tda_audio_I2S_qualifier;
++
++typedef enum {
++ TDA_I2SFOR_PHILIPS_L = 0, /**< Philips like format */
++ TDA_I2SFOR_OTH_L = 2, /**< Other non Philips left justified */
++ TDA_I2SFOR_OTH_R = 3, /**< Other non Philips right justified */
++ TDA_I2SFOR_INVALID = 4 /**< Invalid format */
++} tda_audio_I2S_format;
++
++typedef enum {
++ TDA_DSTRATE_SINGLE = 0, /**< Single transfer rate */
++ TDA_DSTRATE_DOUBLE = 1 /**< Double data rate */
++} tda_dst_rate;
++
++typedef struct {
++ int simplayHd; /**< Enable simplayHD support */
++ int repeaterEnable; /**< Enable repeater mode */
++ unsigned char *pEdidBuffer; /**< Pointer to raw EDID data */
++ unsigned long edidBufferSize; /**< Size of buffer for raw EDID data */
++} tda_instance_setup_info;
++
++typedef enum {
++ TDA_VFMT_NULL = 0, /**< Not a valid format... */
++ TDA_VFMT_NO_CHANGE = 0, /**< ...or no change required */
++ TDA_VFMT_MIN = 1, /**< Lowest valid format */
++ TDA_VFMT_TV_MIN = 1, /**< Lowest valid TV format */
++ TDA_VFMT_01_640x480p_60Hz = 1, /**< Format 01 640 x 480p 60Hz */
++ TDA_VFMT_02_720x480p_60Hz = 2, /**< Format 02 720 x 480p 60Hz */
++ TDA_VFMT_03_720x480p_60Hz = 3, /**< Format 03 720 x 480p 60Hz */
++ TDA_VFMT_04_1280x720p_60Hz = 4, /**< Format 04 1280 x 720p 60Hz */
++ TDA_VFMT_05_1920x1080i_60Hz = 5, /**< Format 05 1920 x 1080i 60Hz */
++ TDA_VFMT_06_720x480i_60Hz = 6, /**< Format 06 720 x 480i 60Hz */
++ TDA_VFMT_07_720x480i_60Hz = 7, /**< Format 07 720 x 480i 60Hz */
++ TDA_VFMT_08_720x240p_60Hz = 8, /**< Format 08 720 x 240p 60Hz */
++ TDA_VFMT_09_720x240p_60Hz = 9, /**< Format 09 720 x 240p 60Hz */
++ TDA_VFMT_10_720x480i_60Hz = 10, /**< Format 10 720 x 480i 60Hz */
++ TDA_VFMT_11_720x480i_60Hz = 11, /**< Format 11 720 x 480i 60Hz */
++ TDA_VFMT_12_720x240p_60Hz = 12, /**< Format 12 720 x 240p 60Hz */
++ TDA_VFMT_13_720x240p_60Hz = 13, /**< Format 13 720 x 240p 60Hz */
++ TDA_VFMT_14_1440x480p_60Hz = 14, /**< Format 14 1440 x 480p 60Hz */
++ TDA_VFMT_15_1440x480p_60Hz = 15, /**< Format 15 1440 x 480p 60Hz */
++ TDA_VFMT_16_1920x1080p_60Hz = 16, /**< Format 16 1920 x 1080p 60Hz */
++ TDA_VFMT_17_720x576p_50Hz = 17, /**< Format 17 720 x 576p 50Hz */
++ TDA_VFMT_18_720x576p_50Hz = 18, /**< Format 18 720 x 576p 50Hz */
++ TDA_VFMT_19_1280x720p_50Hz = 19, /**< Format 19 1280 x 720p 50Hz */
++ TDA_VFMT_20_1920x1080i_50Hz = 20, /**< Format 20 1920 x 1080i 50Hz */
++ TDA_VFMT_21_720x576i_50Hz = 21, /**< Format 21 720 x 576i 50Hz */
++ TDA_VFMT_22_720x576i_50Hz = 22, /**< Format 22 720 x 576i 50Hz */
++ TDA_VFMT_23_720x288p_50Hz = 23, /**< Format 23 720 x 288p 50Hz */
++ TDA_VFMT_24_720x288p_50Hz = 24, /**< Format 24 720 x 288p 50Hz */
++ TDA_VFMT_25_720x576i_50Hz = 25, /**< Format 25 720 x 576i 50Hz */
++ TDA_VFMT_26_720x576i_50Hz = 26, /**< Format 26 720 x 576i 50Hz */
++ TDA_VFMT_27_720x288p_50Hz = 27, /**< Format 27 720 x 288p 50Hz */
++ TDA_VFMT_28_720x288p_50Hz = 28, /**< Format 28 720 x 288p 50Hz */
++ TDA_VFMT_29_1440x576p_50Hz = 29, /**< Format 29 1440 x 576p 50Hz */
++ TDA_VFMT_30_1440x576p_50Hz = 30, /**< Format 30 1440 x 576p 50Hz */
++ TDA_VFMT_31_1920x1080p_50Hz = 31, /**< Format 31 1920 x 1080p 50Hz */
++ TDA_VFMT_32_1920x1080p_24Hz = 32, /**< Format 32 1920 x 1080p 24Hz */
++ TDA_VFMT_33_1920x1080p_25Hz = 33, /**< Format 33 1920 x 1080p 25Hz */
++ TDA_VFMT_34_1920x1080p_30Hz = 34, /**< Format 34 1920 x 1080p 30Hz */
++ TDA_VFMT_TV_MAX = 34, /**< Highest valid TV format */
++ TDA_VFMT_TV_NO_REG_MIN = 32, /**< Lowest TV format without prefetched table */
++ TDA_VFMT_TV_NUM = 35, /**< Number of TV formats & null */
++ TDA_VFMT_PC_MIN = 128, /**< Lowest valid PC format */
++ TDA_VFMT_PC_640x480p_60Hz = 128, /**< PC format 128 */
++ TDA_VFMT_PC_800x600p_60Hz = 129, /**< PC format 129 */
++ TDA_VFMT_PC_1152x960p_60Hz = 130, /**< PC format 130 */
++ TDA_VFMT_PC_1024x768p_60Hz = 131, /**< PC format 131 */
++ TDA_VFMT_PC_1280x768p_60Hz = 132, /**< PC format 132 */
++ TDA_VFMT_PC_1280x1024p_60Hz = 133, /**< PC format 133 */
++ TDA_VFMT_PC_1360x768p_60Hz = 134, /**< PC format 134 */
++ TDA_VFMT_PC_1400x1050p_60Hz = 135, /**< PC format 135 */
++ TDA_VFMT_PC_1600x1200p_60Hz = 136, /**< PC format 136 */
++ TDA_VFMT_PC_1024x768p_70Hz = 137, /**< PC format 137 */
++ TDA_VFMT_PC_640x480p_72Hz = 138, /**< PC format 138 */
++ TDA_VFMT_PC_800x600p_72Hz = 139, /**< PC format 139 */
++ TDA_VFMT_PC_640x480p_75Hz = 140, /**< PC format 140 */
++ TDA_VFMT_PC_1024x768p_75Hz = 141, /**< PC format 141 */
++ TDA_VFMT_PC_800x600p_75Hz = 142, /**< PC format 142 */
++ TDA_VFMT_PC_1024x864p_75Hz = 143, /**< PC format 143 */
++ TDA_VFMT_PC_1280x1024p_75Hz = 144, /**< PC format 144 */
++ TDA_VFMT_PC_640x350p_85Hz = 145, /**< PC format 145 */
++ TDA_VFMT_PC_640x400p_85Hz = 146, /**< PC format 146 */
++ TDA_VFMT_PC_720x400p_85Hz = 147, /**< PC format 147 */
++ TDA_VFMT_PC_640x480p_85Hz = 148, /**< PC format 148 */
++ TDA_VFMT_PC_800x600p_85Hz = 149, /**< PC format 149 */
++ TDA_VFMT_PC_1024x768p_85Hz = 150, /**< PC format 150 */
++ TDA_VFMT_PC_1152x864p_85Hz = 151, /**< PC format 151 */
++ TDA_VFMT_PC_1280x960p_85Hz = 152, /**< PC format 152 */
++ TDA_VFMT_PC_1280x1024p_85Hz = 153, /**< PC format 153 */
++ TDA_VFMT_PC_1024x768i_87Hz = 154, /**< PC format 154 */
++ TDA_VFMT_PC_MAX = 154, /**< Highest valid PC format */
++ TDA_VFMT_PC_NUM = (1+154-128) /**< Number of PC formats */
++} tda_video_fmt_id;
++
++typedef struct {
++ tda_video_fmt_id videoFormat; /**< Video format as defined by EIA/CEA 861-D */
++ int nativeVideoFormat; /**< True if format is the preferred video format */
++} tda_edid_video_desc;
++
++typedef struct {
++ tda_video_fmt_id videoFormat; /**< Video format as defined by EIA/CEA 861-D */
++ int nativeVideoFormat; /**< True if format is the preferred video format */
++} tda_short_video_desc;
++
++typedef enum {
++ TDA_P_ASPECT_RATIO_UNDEFINED = 0, /**< Undefined picture aspect ratio */
++ TDA_P_ASPECT_RATIO_6_5 = 1, /**< 6:5 picture aspect ratio (PAR) */
++ TDA_P_ASPECT_RATIO_5_4 = 2, /**< 5:4 PAR */
++ TDA_P_ASPECT_RATIO_4_3 = 3, /**< 4:3 PAR */
++ TDA_P_ASPECT_RATIO_16_10 = 4, /**< 16:10 PAR */
++ TDA_P_ASPECT_RATIO_5_3 = 5, /**< 5:3 PAR */
++ TDA_P_ASPECT_RATIO_16_9 = 6, /**< 16:9 PAR */
++ TDA_P_ASPECT_RATIO_9_5 = 7 /**< 9:5 PAR */
++} tda_pict_aspect_ratio;
++
++typedef enum {
++ TDA_VFREQ_24Hz = 0, /**< 24Hz */
++ TDA_VFREQ_25Hz = 1, /**< 25Hz */
++ TDA_VFREQ_30Hz = 2, /**< 30Hz */
++ TDA_VFREQ_50Hz = 3, /**< 50Hz */
++ TDA_VFREQ_59Hz = 4, /**< 59.94Hz */
++ TDA_VFREQ_60Hz = 5, /**< 60Hz */
++ TDA_VFREQ_70Hz = 6, /**< 70Hz */
++ TDA_VFREQ_72Hz = 7, /**< 72Hz */
++ TDA_VFREQ_75Hz = 8, /**< 75Hz */
++ TDA_VFREQ_85Hz = 9, /**< 85Hz */
++ TDA_VFREQ_87Hz = 10, /**< 87Hz */
++ TDA_VFREQ_INVALID = 11, /**< Invalid */
++ TDA_VFREQ_NUM = 11 /**< No. of values */
++} tda_vfreq;
++
++typedef struct {
++ unsigned short width; /**< Width of the frame in pixels */
++ unsigned short height; /**< Height of the frame in pixels */
++ int interlaced; /**< Interlaced mode (True/False) */
++ tda_vfreq vfrequency; /**< Vertical frequency in Hz */
++ tda_pict_aspect_ratio aspectRatio; /**< Picture aspect ratio (H:V) */
++} tda_video_fmt_specs;
++
++typedef enum {
++ TDA_VINMODE_CCIR656 = 0, /**< CCIR656 */
++ TDA_VINMODE_RGB444 = 1, /**< RGB444 */
++ TDA_VINMODE_YUV444 = 2, /**< YUV444 */
++ TDA_VINMODE_YUV422 = 3, /**< YUV422 */
++ TDA_VINMODE_NO_CHANGE = 4, /**< No change */
++ TDA_VINMODE_INVALID = 5 /**< Invalid */
++} tda_vinmode;
++
++typedef enum {
++ TDA_SYNCSRC_EMBEDDED = 0, /**< Embedded sync */
++ TDA_SYNCSRC_EXT_VREF = 1, /**< External sync Vref, Href, Fref */
++ TDA_SYNCSRC_EXT_VS = 2 /**< External sync Vs, Hs */
++} tda_sync_source;
++
++typedef enum {
++ TDA_PIXRATE_DOUBLE = 0, /**< Double pixel rate */
++ TDA_PIXRATE_SINGLE = 1, /**< Single pixel rate */
++ TDA_PIXRATE_SINGLE_REPEATED = 2 /**< Single pixel repeated */
++} tda_pix_rate;
++
++typedef struct {
++ tda_video_fmt_id format; /**< Video format as defined by EIA/CEA 861-D */
++ tda_vinmode mode; /**< Video mode (CCIR, RGB, YUV, etc.) */
++ tda_sync_source syncSource; /**< Sync source type */
++ tda_pix_rate pixelRate; /**< Pixel rate */
++} tda_video_in;
++
++typedef enum {
++ TDA_VOUTMODE_RGB444 = 0, /**< RGB444 */
++ TDA_VOUTMODE_YUV422 = 1, /**< YUV422 */
++ TDA_VOUTMODE_YUV444 = 2 /**< YUV444 */
++} tda_vout_mode;
++
++typedef enum {
++ TDA_VQR_DEFAULT = 0, /* Follow HDMI spec. */
++ TDA_RGB_FULL = 1, /* Force RGB FULL , DVI only */
++ TDA_RGB_LIMITED = 2 /* Force RGB LIMITED , DVI only */
++} tda_vqr;
++
++typedef enum {
++ TDA_COLORDEPTH_24 = 0, /**< 8 bits per color */
++ TDA_COLORDEPTH_30 = 1, /**< 10 bits per color */
++ TDA_COLORDEPTH_36 = 2, /**< 12 bits per color */
++ TDA_COLORDEPTH_48 = 3 /**< 16 bits per color */
++} tda_color_depth;
++
++typedef struct {
++ tda_video_fmt_id format; /**< Video format as defined by EIA/CEA 861-D */
++ tda_vout_mode mode; /**< Video mode (CCIR, RGB, YUV, etc.) */
++ tda_color_depth colorDepth; /**< Color depth */
++ tda_vqr dviVqr; /**< VQR applied in DVI mode */
++} tda_video_out;
++
++typedef struct {
++ tda_audio_format format; /**< Audio format (I2S, SPDIF, etc.) */
++ tda_audio_rate rate; /**< Audio sampling rate */
++ tda_audio_I2S_format i2sFormat; /**< I2S format of the audio input */
++ tda_audio_I2S_qualifier i2sQualifier; /**< I2S qualifier of the audio input (8,16,32 bits) */
++ tda_dst_rate dstRate; /**< DST data transfer rate */
++ unsigned char channelAllocation; /**< Ref to CEA-861D p85 */
++} tda_audio_in;
++
++typedef enum {
++ TDA_SINK_DVI = 0, /**< DVI */
++ TDA_SINK_HDMI = 1, /**< HDMI */
++ TDA_SINK_EDID = 2 /**< As currently defined in EDID */
++} tda_sink;
++
++ typedef enum {
++ TDA_DEVICE_UNKNOWN, /**< HW device is unknown */
++ TDA_DEVICE_TDA9984, /**< HW device is IC TDA9984 */
++ TDA_DEVICE_TDA9989, /**< HW device is IC TDA9989 */
++ TDA_DEVICE_TDA9981, /**< HW device is IC TDA9981 */
++ TDA_DEVICE_TDA9983, /**< HW device is IC TDA9983 */
++ TDA_DEVICE_TDA19989 /**< HW device is IC TDA19989 */
++ } tda_device_version;
++
++typedef enum {
++ TDA_HDMI_VERSION_UNKNOWN, /**< Unknown */
++ TDA_HDMI_VERSION_1_1, /**< HDMI 1.1 */
++ TDA_HDMI_VERSION_1_2a, /**< HDMI 1.2a */
++ TDA_HDMI_VERSION_1_3a /**< HDMI 1.3 */
++} tda_hdmi_version;
++
++typedef struct {
++ int HBR; /**< High Bitrate Audio packet */
++ int DST; /**< Direct Stream Transport audio packet */
++ int oneBitAudio; /**< One Bit Audio sample packet */
++} tda_audio_packet;
++
++typedef enum {
++ TDA_COLORDEPTH_24 = 0, /**< 8 bits per color */
++ TDA_COLORDEPTH_30 = 1, /**< 10 bits per color */
++ TDA_COLORDEPTH_36 = 2, /**< 12 bits per color */
++ TDA_COLORDEPTH_48 = 3 /**< 16 bits per color */
++} tda_color_depth;
++
++typedef struct {
++ tda_device_version deviceVersion; /**< HW device version */
++ tda_hdmi_version hdmiVersion; /**< Supported HDMI standard version */
++ tda_audio_packet audioPacket; /**< Supported audio packets */
++ tda_color_depth colorDepth; /**< Supported color depth */
++ int hdcp; /**< Supported Hdcp encryption (True/False) */
++ int scaler; /**< Supported scaler (True/False) */
++} tda_capabilities;
++
++typedef struct {
++ unsigned long compatibilityNr; // Interface compatibility number
++ unsigned long majorVersionNr; // Interface major version number
++ unsigned long minorVersionNr; // Interface minor version number
++} tda_version;
++
++typedef enum
++{
++ PowerOn, // Device powered on (D0 state)
++ PowerStandby, // Device power standby (D1 state)
++ PowerSuspend, // Device power suspended (D2 state)
++ PowerOff // Device powered off (D3 state)
++} tda_powerXXX;
++
++typedef struct {
++ unsigned int simplayHd; /**< Enable simplayHD support */
++ unsigned int repeaterEnable; /**< Enable repeater mode */
++ unsigned char *pEdidBuffer; /**< Pointer to raw EDID data */
++ unsigned long edidBufferSize; /**< Size of buffer for raw EDID data */
++} tda_setup;
++
++typedef struct {
++ tda_video_fmt_id id;
++ tda_video_fmt_specs spec;
++} tda_video_format;
++
++typedef struct {
++ tda_video_in video_in;
++ tda_video_out video_out;
++ tda_audio_in audio_in;
++} tda_set_in_out;
++
++typedef struct {
++ tda_edid_audio_desc desc;
++ unsigned int max;
++ unsigned int written;
++ unsigned char flags;
++} tda_edid_audio_caps;
++
++typedef struct {
++ tda_edid_video_desc desc;
++ unsigned int max;
++ unsigned int written;
++ unsigned char flags;
++} tda_edid_video_caps;
++
++typedef struct {
++ tda_edid_status status;
++ unsigned char block_count;
++} tda_edid;
++
++#endif
++
++#define TDA_IOCTL_BASE 0x40
++#define RELEASE 0xFF
++
++enum {
++ /* driver specific */
++ TDA_VERBOSE_ON_CMD = 0,
++ TDA_VERBOSE_OFF_CMD,
++ TDA_BYEBYE_CMD,
++ /* HDMI Tx */
++ TDA_GET_SW_VERSION_CMD,
++ TDA_SET_POWER_CMD,
++ TDA_GET_POWER_CMD,
++ TDA_SETUP_CMD,
++ TDA_GET_SETUP_CMD,
++ TDA_WAIT_EVENT_CMD,
++ TDA_ENABLE_EVENT_CMD,
++ TDA_DISABLE_EVENT_CMD,
++ TDA_GET_VIDEO_SPEC_CMD,
++ TDA_SET_INPUT_OUTPUT_CMD,
++ TDA_SET_AUDIO_INPUT_CMD,
++ TDA_SET_VIDEO_INFOFRAME_CMD,
++ TDA_SET_AUDIO_INFOFRAME_CMD,
++ TDA_SET_ACP_CMD,
++ TDA_SET_GCP_CMD,
++ TDA_SET_ISRC1_CMD,
++ TDA_SET_ISRC2_CMD,
++ TDA_SET_MPS_INFOFRAME_CMD,
++ TDA_SET_SPD_INFOFRAME_CMD,
++ TDA_SET_VS_INFOFRAME_CMD,
++ TDA_SET_AUDIO_MUTE_CMD,
++ TDA_RESET_AUDIO_CTS_CMD,
++ TDA_GET_EDID_STATUS_CMD,
++ TDA_GET_EDID_AUDIO_CAPS_CMD,
++ TDA_GET_EDID_VIDEO_CAPS_CMD,
++ TDA_GET_EDID_VIDEO_PREF_CMD,
++ TDA_GET_EDID_SINK_TYPE_CMD,
++ TDA_GET_EDID_SOURCE_ADDRESS_CMD,
++ TDA_SET_GAMMUT_CMD,
++ TDA_GET_EDID_DTD_CMD,
++ TDA_GET_EDID_MD_CMD,
++ TDA_GET_EDID_TV_ASPECT_RATIO_CMD,
++ TDA_GET_EDID_LATENCY_CMD,
++ TDA_SET_HDCP_CMD,
++ TDA_GET_HDCP_STATUS_CMD,
++ TDA_GET_HPD_STATUS_CMD,
++};
++
++
++/* driver specific */
++#define TDA_IOCTL_VERBOSE_ON _IO(TDA_IOCTL_BASE, TDA_VERBOSE_ON_CMD)
++#define TDA_IOCTL_VERBOSE_OFF _IO(TDA_IOCTL_BASE, TDA_VERBOSE_OFF_CMD)
++#define TDA_IOCTL_BYEBYE _IO(TDA_IOCTL_BASE, TDA_BYEBYE_CMD)
++/* HDMI Tx */
++#define TDA_IOCTL_GET_SW_VERSION _IOWR(TDA_IOCTL_BASE, TDA_GET_SW_VERSION_CMD,tda_version)
++#define TDA_IOCTL_SET_POWER _IOWR(TDA_IOCTL_BASE, TDA_SET_POWER_CMD,tda_power)
++#define TDA_IOCTL_GET_POWER _IOWR(TDA_IOCTL_BASE, TDA_GET_POWER_CMD,tda_power)
++#define TDA_IOCTL_SETUP _IOWR(TDA_IOCTL_BASE, TDA_SETUP_CMD,tda_setup_info)
++#define TDA_IOCTL_GET_SETUP _IOWR(TDA_IOCTL_BASE, TDA_GET_SETUP_CMD,tda_setup_info)
++#define TDA_IOCTL_WAIT_EVENT _IOWR(TDA_IOCTL_BASE, TDA_WAIT_EVENT_CMD,tda_event)
++#define TDA_IOCTL_ENABLE_EVENT _IOWR(TDA_IOCTL_BASE, TDA_ENABLE_EVENT_CMD,tda_event)
++#define TDA_IOCTL_DISABLE_EVENT _IOWR(TDA_IOCTL_BASE, TDA_DISABLE_EVENT_CMD,tda_event)
++#define TDA_IOCTL_GET_VIDEO_SPEC _IOWR(TDA_IOCTL_BASE, TDA_GET_VIDEO_SPEC_CMD,tda_video_format)
++#define TDA_IOCTL_SET_INPUT_OUTPUT _IOWR(TDA_IOCTL_BASE, TDA_SET_INPUT_OUTPUT_CMD,tda_set_in_out)
++#define TDA_IOCTL_SET_AUDIO_INPUT _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_INPUT_CMD,tda_audio_in)
++#define TDA_IOCTL_SET_VIDEO_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_VIDEO_INFOFRAME_CMD,tda_video_infoframe)
++#define TDA_IOCTL_SET_AUDIO_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_INFOFRAME_CMD,tda_audio_infoframe)
++#define TDA_IOCTL_SET_ACP _IOWR(TDA_IOCTL_BASE, TDA_SET_ACP_CMD,tda_acp)
++#define TDA_IOCTL_SET_GCP _IOWR(TDA_IOCTL_BASE, TDA_SET_GCP_CMD,tda_gcp)
++#define TDA_IOCTL_SET_ISRC1 _IOWR(TDA_IOCTL_BASE, TDA_SET_ISRC1_CMD,tda_isrc1)
++#define TDA_IOCTL_SET_ISRC2 _IOWR(TDA_IOCTL_BASE, TDA_SET_ISRC2_CMD,tda_isrc2)
++#define TDA_IOCTL_SET_MPS_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_MPS_INFOFRAME_CMD,tda_mps_infoframe)
++#define TDA_IOCTL_SET_SPD_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_SPD_INFOFRAME_CMD,tda_spd_infoframe)
++#define TDA_IOCTL_SET_VS_INFOFRAME _IOWR(TDA_IOCTL_BASE, TDA_SET_VS_INFOFRAME_CMD,tda_vs_infoframe)
++#define TDA_IOCTL_SET_AUDIO_MUTE _IOWR(TDA_IOCTL_BASE, TDA_SET_AUDIO_MUTE_CMD,bool)
++#define TDA_IOCTL_RESET_AUDIO_CTS _IO(TDA_IOCTL_BASE, TDA_RESET_AUDIO_CTS_CMD)
++#define TDA_IOCTL_GET_EDID_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_STATUS_CMD,tda_edid)
++#define TDA_IOCTL_GET_EDID_AUDIO_CAPS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_AUDIO_CAPS_CMD,tda_edid_audio_caps)
++#define TDA_IOCTL_GET_EDID_VIDEO_CAPS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_VIDEO_CAPS_CMD,tda_edid_video_caps)
++#define TDA_IOCTL_GET_EDID_VIDEO_PREF _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_VIDEO_PREF_CMD,tda_edid_video_timings)
++#define TDA_IOCTL_GET_EDID_SINK_TYPE _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_SINK_TYPE_CMD,tda_sink)
++#define TDA_IOCTL_GET_EDID_SOURCE_ADDRESS _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_SOURCE_ADDRESS_CMD,unsigned short)
++#define TDA_IOCTL_SET_GAMMUT _IOWR(TDA_IOCTL_BASE, TDA_SET_GAMMUT_CMD,tda_gammut)
++#define TDA_IOCTL_GET_EDID_DTD _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_DTD_CMD,tda_edid_dtd)
++#define TDA_IOCTL_GET_EDID_MD _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_MD_CMD,tda_edid_md)
++#define TDA_IOCTL_GET_EDID_TV_ASPECT_RATIO _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_TV_ASPECT_RATIO_CMD,tda_edid_tv_aspect_ratio)
++#define TDA_IOCTL_GET_HPD_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_HPD_STATUS_CMD, tmdlHdmiTxHotPlug_t)
++#ifdef TMFL_TDA19989
++#define TDA_IOCTL_GET_EDID_LATENCY _IOWR(TDA_IOCTL_BASE, TDA_GET_EDID_LATENCY_CMD,tda_edid_latency)
++#define TDA_IOCTL_SET_HDCP _IOWR(TDA_IOCTL_BASE, TDA_SET_HDCP_CMD,bool)
++#define TDA_IOCTL_GET_HDCP_STATUS _IOWR(TDA_IOCTL_BASE, TDA_GET_HDCP_STATUS_CMD,tda_hdcp_status)
++#endif
++
++
++/* --- Full list --- */
++
++/* legend: */
++/* ------- */
++/* [ ] : not supported */
++/* [x] : IOCTL */
++/* [i] : open, init... */
++
++/* [x] tmdlHdmiTxGetSWVersion */
++/* [ ] tmdlHdmiTxGetNumberOfUnits */
++/* [i] tmdlHdmiTxGetCapabilities */
++/* [ ] tmdlHdmiTxGetCapabilitiesM */
++/* [i] tmdlHdmiTxOpen */
++/* [ ] tmdlHdmiTxOpenM */
++/* [i] tmdlHdmiTxClose */
++/* [x] tmdlHdmiTxSetPowerState */
++/* [x] tmdlHdmiTxGetPowerState */
++/* [ ] tmdlHdmiTxInstanceConfig */
++/* [xi] tmdlHdmiTxInstanceSetup */
++/* [x] tmdlHdmiTxGetInstanceSetup */
++/* [x] tmdlHdmiTxHandleInterrupt see IOCTL_WAIT_EVENT */
++/* [i] tmdlHdmiTxRegisterCallbacks */
++/* [x] tmdlHdmiTxEnableEvent */
++/* [x] tmdlHdmiTxDisableEvent */
++/* [x] tmdlHdmiTxGetVideoFormatSpecs */
++/* [x] tmdlHdmiTxSetInputOutput */
++/* [x] tmdlHdmiTxSetAudioInput */
++/* [x] tmdlHdmiTxSetVideoInfoframe */
++/* [x] tmdlHdmiTxSetAudioInfoframe */
++/* [x] tmdlHdmiTxSetACPPacket */
++/* [x] tmdlHdmiTxSetGeneralControlPacket */
++/* [x] tmdlHdmiTxSetISRC1Packet */
++/* [x] tmdlHdmiTxSetISRC2Packet */
++/* [x] tmdlHdmiTxSetMPSInfoframe */
++/* [x] tmdlHdmiTxSetSpdInfoframe */
++/* [x] tmdlHdmiTxSetVsInfoframe */
++/* [ ] tmdlHdmiTxDebugSetNullPacket */
++/* [ ] tmdlHdmiTxDebugSetSingleNullPacket */
++/* [x] tmdlHdmiTxSetAudioMute */
++/* [x] tmdlHdmiTxResetAudioCts */
++/* [x] tmdlHdmiTxGetEdidStatus */
++/* [x] tmdlHdmiTxGetEdidAudioCaps */
++/* [x] tmdlHdmiTxGetEdidVideoCaps */
++/* [x] tmdlHdmiTxGetEdidVideoPreferred */
++/* [x] tmdlHdmiTxGetEdidSinkType */
++/* [x] tmdlHdmiTxGetEdidSourceAddress */
++/* [ ] tmdlHdmiTxGetKsvList */
++/* [ ] tmdlHdmiTxGetDepth */
++/* [ ] tmdlHdmiTxGeneSHA_1_IT */
++/* [ ] tmdlHdmiTxSetHdcp */
++/* [ ] tmdlHdmiTxGetHdcpState */
++/* [ ] tmdlHdmiTxHdcpCheck */
++/* [x] tmdlHdmiTxSetGamutPacket */
++/* [x] tmdlHdmiTxGetEdidDetailledTimingDescriptors */
++/* [x] tmdlHdmiTxGetEdidMonitorDescriptors */
++/* [x] tmdlHdmiTxGetEdidTVPictureRatio */
++/* [ ] tmdlHdmiTxSetHDCPRevocationList */
++/* [ ] tmdlHdmiTxGetHdcpFailStatus */
++/* [x] tmdlHdmiTxGetEdidLatencyInfo */
++/* [ ] tmdlHdmiTxSetBScreen */
++/* [ ] tmdlHdmiTxRemoveBScreen */
++
++
++#endif /* __tx_h__ */
++#endif /* __tx_ioctl__ */
++
++#ifndef __cec_ioctl__
++#define __cec_ioctl__
++
++#ifdef __cec_h__
++
++typedef struct {
++ UInt8 DayOfMonth;
++ UInt8 MonthOfYear;
++ UInt16 StartTime;
++ tmdlHdmiCECDuration_t Duration;
++ UInt8 RecordingSequence;
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType;
++ UInt16 AnalogueFrequency;
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem;
++} cec_analogue_timer;
++
++typedef struct {
++ UInt8 DayOfMonth;
++ UInt8 MonthOfYear;
++ UInt16 StartTime;
++ tmdlHdmiCECDuration_t Duration;
++ UInt8 RecordingSequence;
++ tmdlHdmiCECDigitalServiceIdentification_t ServiceIdentification;
++} cec_digital_timer;
++
++typedef struct {
++ UInt8 DayOfMonth;
++ UInt8 MonthOfYear;
++ UInt16 StartTime;
++ tmdlHdmiCECDuration_t Duration;
++ UInt8 RecordingSequence;
++ tmdlHdmiCECExternalPlug_t ExternalPlug;
++} cec_ext_timer_with_ext_plug;
++
++typedef struct {
++ UInt8 DayOfMonth;
++ UInt8 MonthOfYear;
++ UInt16 StartTime;
++ tmdlHdmiCECDuration_t Duration;
++ UInt8 RecordingSequence;
++ tmdlHdmiCECExternalPhysicalAddress_t ExternalPhysicalAddress;
++} cec_ext_timer_with_phy_addr;
++
++typedef struct {
++ tmdlHdmiCECFeatureOpcode_t FeatureOpcode;
++ tmdlHdmiCECAbortReason_t AbortReason;
++} cec_feature_abort;
++
++typedef struct {
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType;
++ UInt16 AnalogueFrequency;
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem;
++} cec_analogue_service;
++
++typedef struct {
++ UInt16 OriginalAddress;
++ UInt16 NewAddress;
++} cec_routing_change;
++
++typedef struct {
++ char data[15];
++ unsigned char length;
++} cec_string;
++
++typedef struct {
++ tmdlHdmiCECDisplayControl_t DisplayControl;
++ char data[15];
++ unsigned char length;
++} cec_osd_string;
++
++typedef struct {
++ tmdlHdmiCECRecordingFlag_t RecordingFlag;
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo;
++ tmdlHdmiCECAnalogueBroadcastType_t AnalogueBroadcastType;
++ UInt16 AnalogueFrequency;
++ tmdlHdmiCECBroadcastSystem_t BroadcastSystem;
++} cec_tuner_device_status_analogue;
++
++typedef struct {
++ tmdlHdmiCECRecordingFlag_t RecordingFlag;
++ tmdlHdmiCECTunerDisplayInfo_t TunerDisplayInfo;
++ tmdlHdmiCECDigitalServiceIdentification_t ServiceIdentification;
++} cec_tuner_device_status_digital;
++
++typedef struct {
++ unsigned long VendorID;
++ cec_string cmd;
++} cec_vendor_command_with_id;
++
++/*
++ typedef struct {
++ UInt8 *pData;
++ UInt16 lenData;
++ } cec_send_msg;
++*/
++
++typedef struct
++{
++ unsigned char count;
++ unsigned char service;
++ unsigned char addr;
++ unsigned char data[15];
++} cec_frame;
++/* typedef tmdlHdmiCecFrameFormat_t cec_frame; */
++
++typedef tmSWVersion_t cec_sw_version;
++typedef tmPowerState_t cec_power;
++typedef tmdlHdmiCecInstanceSetup_t cec_setup;
++typedef tmdlHdmiCecEvent_t cec_event;
++typedef tmdlHdmiCecClockSource_t cec_clock;
++typedef tmdlHdmiCECSystemAudioStatus_t cec_sys_audio_status;
++typedef tmdlHdmiCECAudioRate_t cec_audio_rate;
++typedef tmdlHdmiCECDigitalServiceIdentification_t cec_digital_service;
++typedef tmdlHdmiCECVersion_t cec_version;
++typedef tmdlHdmiCECDecControlMode_t cec_deck_ctrl;
++typedef tmdlHdmiCECDecInfo_t cec_deck_status;
++typedef tmdlHdmiCECStatusRequest_t cec_status_request;
++typedef tmdlHdmiCECMenuRequestType_t cec_menu_request;
++typedef tmdlHdmiCECMenuState_t cec_menu_status;
++typedef tmdlHdmiCECPlayMode_t cec_play;
++typedef tmdlHdmiCECExternalPlug_t cec_ext_plug;
++typedef tmdlHdmiCECRecordStatusInfo_t cec_rec_status;
++typedef tmdlHdmiCECAudioStatus_t cec_audio_status;
++typedef tmdlHdmiCECPowerStatus_t cec_power_status;
++typedef tmdlHdmiCECTimerClearedStatusData_t cec_timer_cleared_status;
++typedef tmdlHdmiCECTimerStatusData_t cec_timer_status;
++typedef tmdlHdmiCECUserRemoteControlCommand_t cec_user_ctrl;
++typedef tmdlHdmiCECChannelIdentifier_t cec_user_ctrl_tune;
++typedef tmdlHdmiCECDeviceType_t cec_device_type;
++
++#define CEC_IOCTL_BASE 0x40
++
++/* service */
++enum {
++ CEC_WAITING = 0x80,
++ CEC_RELEASE,
++ CEC_RX_DONE,
++ CEC_TX_DONE
++};
++
++enum {
++ /* driver specific */
++ CEC_VERBOSE_ON_CMD = 0,
++ CEC_VERBOSE_OFF_CMD,
++ CEC_BYEBYE_CMD,
++
++ /* CEC */
++ CEC_IOCTL_RX_ADDR_CMD, /* receiver logical address selector */
++ CEC_IOCTL_PHY_ADDR_CMD, /* physical address selector */
++ CEC_IOCTL_WAIT_FRAME_CMD,
++ CEC_IOCTL_ABORT_MSG_CMD,
++ CEC_IOCTL_ACTIVE_SRC_CMD,
++ CEC_IOCTL_VERSION_CMD,
++ CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD,
++ CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD,
++ CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD,
++ CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD,
++ CEC_IOCTL_DECK_CTRL_CMD,
++ CEC_IOCTL_DECK_STATUS_CMD,
++ CEC_IOCTL_DEVICE_VENDOR_ID_CMD,
++ CEC_IOCTL_FEATURE_ABORT_CMD,
++ CEC_IOCTL_GET_CEC_VERSION_CMD,
++ CEC_IOCTL_GET_MENU_LANGUAGE_CMD,
++ CEC_IOCTL_GIVE_AUDIO_STATUS_CMD,
++ CEC_IOCTL_GIVE_DECK_STATUS_CMD,
++ CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD,
++ CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD,
++ CEC_IOCTL_GIVE_OSD_NAME_CMD,
++ CEC_IOCTL_GIVE_PHY_ADDR_CMD,
++ CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD,
++ CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD,
++ CEC_IOCTL_IMAGE_VIEW_ON_CMD,
++ CEC_IOCTL_INACTIVE_SRC_CMD,
++ CEC_IOCTL_MENU_REQUEST_CMD,
++ CEC_IOCTL_MENU_STATUS_CMD,
++ CEC_IOCTL_PLAY_CMD,
++ CEC_IOCTL_POLLING_MSG_CMD,
++ CEC_IOCTL_REC_OFF_CMD,
++ CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD,
++ CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD,
++ CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD,
++ CEC_IOCTL_REC_ON_EXT_PLUG_CMD,
++ CEC_IOCTL_REC_ON_OWN_SRC_CMD,
++ CEC_IOCTL_REC_STATUS_CMD,
++ CEC_IOCTL_REC_TV_SCREEN_CMD,
++ CEC_IOCTL_REPORT_AUDIO_STATUS_CMD,
++ CEC_IOCTL_REPORT_PHY_ADDR_CMD,
++ CEC_IOCTL_REPORT_POWER_STATUS_CMD,
++ CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD,
++ CEC_IOCTL_ROUTING_CHANGE_CMD,
++ CEC_IOCTL_ROUTING_INFORMATION_CMD,
++ CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD,
++ CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD,
++ CEC_IOCTL_SET_ANALOGUE_TIMER_CMD,
++ CEC_IOCTL_SET_AUDIO_RATE_CMD,
++ CEC_IOCTL_SET_DIGITAL_TIMER_CMD,
++ CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD,
++ CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD,
++ CEC_IOCTL_SET_MENU_LANGUAGE_CMD,
++ CEC_IOCTL_SET_OSD_NAME_CMD,
++ CEC_IOCTL_SET_OSD_STRING_CMD,
++ CEC_IOCTL_SET_STREAM_PATH_CMD,
++ CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD,
++ CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD,
++ CEC_IOCTL_STANDBY_CMD,
++ CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD,
++ CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD,
++ CEC_IOCTL_TEXT_VIEW_ON_CMD,
++ CEC_IOCTL_TIMER_CLEARED_STATUS_CMD,
++ CEC_IOCTL_TIMER_STATUS_CMD,
++ CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD,
++ CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD,
++ CEC_IOCTL_TUNER_STEP_DECREMENT_CMD,
++ CEC_IOCTL_TUNER_STEP_INCREMENT_CMD,
++ CEC_IOCTL_USER_CTRL_CMD,
++ CEC_IOCTL_USER_CTRL_PLAY_CMD,
++ CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD,
++ CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD,
++ CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD,
++ CEC_IOCTL_USER_CTRL_TUNE_CMD,
++ CEC_IOCTL_USER_CTRL_RELEASED_CMD,
++ CEC_IOCTL_VENDOR_COMMAND_CMD,
++ CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD,
++ CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD,
++ CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD,
++ CEC_IOCTL_GET_SW_VERSION_CMD,
++ CEC_IOCTL_SET_POWER_STATE_CMD,
++ CEC_IOCTL_GET_POWER_STATE_CMD,
++ CEC_IOCTL_INSTANCE_CONFIG_CMD,
++ CEC_IOCTL_INSTANCE_SETUP_CMD,
++ CEC_IOCTL_GET_INSTANCE_SETUP_CMD,
++ CEC_IOCTL_ENABLE_EVENT_CMD,
++ CEC_IOCTL_DISABLE_EVENT_CMD,
++ CEC_IOCTL_ENABLE_CALIBRATION_CMD,
++ CEC_IOCTL_DISABLE_CALIBRATION_CMD,
++ CEC_IOCTL_SEND_MSG_CMD,
++ CEC_IOCTL_SET_REGISTER_CMD
++};
++
++
++/* driver specific */
++#define CEC_IOCTL_VERBOSE_ON _IO(CEC_IOCTL_BASE, CEC_VERBOSE_ON_CMD)
++#define CEC_IOCTL_VERBOSE_OFF _IO(CEC_IOCTL_BASE, CEC_VERBOSE_OFF_CMD)
++#define CEC_IOCTL_BYEBYE _IO(CEC_IOCTL_BASE, CEC_BYEBYE_CMD)
++
++/* CEC */
++#define CEC_IOCTL_RX_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_RX_ADDR_CMD,unsigned char)
++#define CEC_IOCTL_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_PHY_ADDR_CMD,unsigned short)
++#define CEC_IOCTL_WAIT_FRAME _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_WAIT_FRAME_CMD,cec_frame)
++#define CEC_IOCTL_ABORT_MSG _IO(CEC_IOCTL_BASE,CEC_IOCTL_ABORT_MSG_CMD)
++#define CEC_IOCTL_ACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_ACTIVE_SRC_CMD)
++#define CEC_IOCTL_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VERSION_CMD,cec_version)
++#define CEC_IOCTL_CLEAR_ANALOGUE_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_ANALOGUE_TIMER_CMD,cec_analogue_timer)
++#define CEC_IOCTL_CLEAR_DIGITAL_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_DIGITAL_TIMER_CMD,cec_digital_timer)
++#define CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_EXT_TIMER_WITH_EXT_PLUG_CMD,cec_ext_timer_with_ext_plug)
++#define CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_CLEAR_EXT_TIMER_WITH_PHY_ADDR_CMD,cec_ext_timer_with_phy_addr)
++#define CEC_IOCTL_DECK_CTRL _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DECK_CTRL_CMD,cec_deck_ctrl)
++#define CEC_IOCTL_DECK_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DECK_STATUS_CMD,cec_deck_status)
++#define CEC_IOCTL_DEVICE_VENDOR_ID _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DEVICE_VENDOR_ID_CMD,unsigned long)
++#define CEC_IOCTL_FEATURE_ABORT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_FEATURE_ABORT_CMD,cec_feature_abort)
++#define CEC_IOCTL_GET_CEC_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_CEC_VERSION_CMD,unsigned char)
++#define CEC_IOCTL_GET_MENU_LANGUAGE _IO(CEC_IOCTL_BASE,CEC_IOCTL_GET_MENU_LANGUAGE_CMD)
++#define CEC_IOCTL_GIVE_AUDIO_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_AUDIO_STATUS_CMD)
++#define CEC_IOCTL_GIVE_DECK_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DECK_STATUS_CMD,cec_status_request)
++#define CEC_IOCTL_GIVE_DEVICE_POWER_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DEVICE_POWER_STATUS_CMD)
++#define CEC_IOCTL_GIVE_DEVICE_VENDOR_ID _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_DEVICE_VENDOR_ID_CMD)
++#define CEC_IOCTL_GIVE_OSD_NAME _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_OSD_NAME_CMD)
++#define CEC_IOCTL_GIVE_PHY_ADDR _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_PHY_ADDR_CMD)
++#define CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS _IO(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_SYS_AUDIO_MODE_STATUS_CMD)
++#define CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GIVE_TUNER_DEVICE_STATUS_CMD,cec_status_request)
++#define CEC_IOCTL_IMAGE_VIEW_ON _IO(CEC_IOCTL_BASE,CEC_IOCTL_IMAGE_VIEW_ON_CMD)
++#define CEC_IOCTL_INACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_INACTIVE_SRC_CMD)
++#define CEC_IOCTL_MENU_REQUEST _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_MENU_REQUEST_CMD,cec_menu_request)
++#define CEC_IOCTL_MENU_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_MENU_STATUS_CMD,cec_menu_status)
++#define CEC_IOCTL_PLAY _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_PLAY_CMD,cec_play)
++#define CEC_IOCTL_POLLING_MSG _IO(CEC_IOCTL_BASE,CEC_IOCTL_POLLING_MSG_CMD)
++#define CEC_IOCTL_REC_OFF _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_OFF_CMD)
++#define CEC_IOCTL_REC_ON_ANALOGUE_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_ANALOGUE_SERVICE_CMD,cec_analogue_service)
++#define CEC_IOCTL_REC_ON_DIGITAL_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_DIGITAL_SERVICE_CMD,cec_digital_service)
++#define CEC_IOCTL_REC_ON_EXT_PHY_ADDR _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_EXT_PHY_ADDR_CMD)
++#define CEC_IOCTL_REC_ON_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_EXT_PLUG_CMD,cec_ext_plug)
++#define CEC_IOCTL_REC_ON_OWN_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_ON_OWN_SRC_CMD)
++#define CEC_IOCTL_REC_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REC_STATUS_CMD,cec_rec_status)
++#define CEC_IOCTL_REC_TV_SCREEN _IO(CEC_IOCTL_BASE,CEC_IOCTL_REC_TV_SCREEN_CMD)
++#define CEC_IOCTL_REPORT_AUDIO_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_AUDIO_STATUS_CMD,cec_audio_status)
++#define CEC_IOCTL_REPORT_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_PHY_ADDR_CMD,cec_device_type)
++#define CEC_IOCTL_REPORT_POWER_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_REPORT_POWER_STATUS_CMD,cec_power_status)
++#define CEC_IOCTL_REQUEST_ACTIVE_SRC _IO(CEC_IOCTL_BASE,CEC_IOCTL_REQUEST_ACTIVE_SRC_CMD)
++#define CEC_IOCTL_ROUTING_CHANGE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ROUTING_CHANGE_CMD,cec_routing_change)
++#define CEC_IOCTL_ROUTING_INFORMATION _IO(CEC_IOCTL_BASE,CEC_IOCTL_ROUTING_INFORMATION_CMD)
++#define CEC_IOCTL_SELECT_ANALOGUE_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SELECT_ANALOGUE_SERVICE_CMD,cec_analogue_service)
++#define CEC_IOCTL_SELECT_DIGITAL_SERVICE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SELECT_DIGITAL_SERVICE_CMD,cec_digital_service)
++#define CEC_IOCTL_SET_ANALOGUE_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_ANALOGUE_TIMER_CMD,cec_analogue_timer)
++#define CEC_IOCTL_SET_AUDIO_RATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_AUDIO_RATE_CMD,cec_audio_rate)
++#define CEC_IOCTL_SET_DIGITAL_TIMER _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_DIGITAL_TIMER_CMD,cec_digital_timer)
++#define CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_EXT_TIMER_WITH_EXT_PLUG_CMD,cec_ext_timer_with_ext_plug)
++#define CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_EXT_TIMER_WITH_PHY_ADDR_CMD,cec_ext_timer_with_phy_addr)
++#define CEC_IOCTL_SET_MENU_LANGUAGE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_MENU_LANGUAGE_CMD,cec_string)
++#define CEC_IOCTL_SET_OSD_NAME _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_OSD_NAME_CMD,cec_string)
++#define CEC_IOCTL_SET_OSD_STRING _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_OSD_STRING_CMD,cec_osd_string)
++#define CEC_IOCTL_SET_STREAM_PATH _IO(CEC_IOCTL_BASE,CEC_IOCTL_SET_STREAM_PATH_CMD)
++#define CEC_IOCTL_SET_SYS_AUDIO_MODE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_SYS_AUDIO_MODE_CMD,cec_sys_audio_status)
++#define CEC_IOCTL_SET_TIMER_PROGRAM_TITLE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_TIMER_PROGRAM_TITLE_CMD,cec_string)
++#define CEC_IOCTL_STANDBY _IO(CEC_IOCTL_BASE,CEC_IOCTL_STANDBY_CMD)
++#define CEC_IOCTL_SYS_AUDIO_MODE_REQUEST _IO(CEC_IOCTL_BASE,CEC_IOCTL_SYS_AUDIO_MODE_REQUEST_CMD)
++#define CEC_IOCTL_SYS_AUDIO_MODE_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SYS_AUDIO_MODE_STATUS_CMD,cec_sys_audio_status)
++#define CEC_IOCTL_TEXT_VIEW_ON _IO(CEC_IOCTL_BASE,CEC_IOCTL_TEXT_VIEW_ON_CMD)
++#define CEC_IOCTL_TIMER_CLEARED_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TIMER_CLEARED_STATUS_CMD,cec_timer_cleared_status)
++#define CEC_IOCTL_TIMER_STATUS _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TIMER_STATUS_CMD,cec_timer_status)
++#define CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_DEVICE_STATUS_ANALOGUE_CMD,cec_tuner_device_status_analogue)
++#define CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_DEVICE_STATUS_DIGITAL_CMD,cec_tuner_device_status_digital)
++#define CEC_IOCTL_TUNER_STEP_DECREMENT _IO(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_STEP_DECREMENT_CMD)
++#define CEC_IOCTL_TUNER_STEP_INCREMENT _IO(CEC_IOCTL_BASE,CEC_IOCTL_TUNER_STEP_INCREMENT_CMD)
++#define CEC_IOCTL_USER_CTRL_PRESSED _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_CMD,cec_user_ctrl)
++#define CEC_IOCTL_USER_CTRL_PLAY _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_PLAY_CMD,cec_play)
++#define CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_AUDIOINPUT_CMD,unsigned char)
++#define CEC_IOCTL_USER_CTRL_SELECT_AVINPUT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_AVINPUT_CMD,unsigned char)
++#define CEC_IOCTL_USER_CTRL_SELECT_MEDIA _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_SELECT_MEDIA_CMD,unsigned char)
++#define CEC_IOCTL_USER_CTRL_TUNE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_TUNE_CMD,cec_user_ctrl_tune)
++#define CEC_IOCTL_USER_CTRL_RELEASED _IO(CEC_IOCTL_BASE,CEC_IOCTL_USER_CTRL_RELEASED_CMD)
++#define CEC_IOCTL_VENDOR_COMMAND _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_COMMAND_CMD,cec_string)
++#define CEC_IOCTL_VENDOR_COMMAND_WITH_ID _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_COMMAND_WITH_ID_CMD,cec_vendor_command_with_id)
++#define CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_REMOTE_BUTTON_DOWN_CMD,cec_string)
++#define CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP _IO(CEC_IOCTL_BASE,CEC_IOCTL_VENDOR_REMOTE_BUTTON_UP_CMD)
++#define CEC_IOCTL_GET_SW_VERSION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_SW_VERSION_CMD,cec_sw_version)
++#define CEC_IOCTL_SET_POWER_STATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SET_POWER_STATE_CMD,cec_power)
++#define CEC_IOCTL_GET_POWER_STATE _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_POWER_STATE_CMD,cec_power)
++#define CEC_IOCTL_INSTANCE_CONFIG _IO(CEC_IOCTL_BASE,CEC_IOCTL_INSTANCE_CONFIG_CMD)
++#define CEC_IOCTL_INSTANCE_SETUP _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_INSTANCE_SETUP_CMD,cec_setup)
++#define CEC_IOCTL_GET_INSTANCE_SETUP _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_GET_INSTANCE_SETUP_CMD,cec_setup)
++#define CEC_IOCTL_ENABLE_EVENT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ENABLE_EVENT_CMD,cec_event)
++#define CEC_IOCTL_DISABLE_EVENT _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_DISABLE_EVENT_CMD,cec_event)
++#define CEC_IOCTL_ENABLE_CALIBRATION _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_ENABLE_CALIBRATION_CMD,cec_clock)
++#define CEC_IOCTL_DISABLE_CALIBRATION _IO(CEC_IOCTL_BASE,CEC_IOCTL_DISABLE_CALIBRATION_CMD)
++//#define CEC_IOCTL_SEND_MSG _IOWR(CEC_IOCTL_BASE,CEC_IOCTL_SEND_MSG_CMD,cec_send_msg)
++
++/* --- Full list --- */
++
++/* legend: */
++/* ------- */
++/* [ ] : not supported */
++/* [x] : IOCTL */
++/* [i] : open, init... */
++
++/* [ ] tmdlHdmiCecAbortMessage */
++/* [ ] tmdlHdmiCecActiveSource */
++/* [ ] tmdlHdmiCecVersion */
++/* [ ] tmdlHdmiCecClearAnalogueTimer */
++/* [ ] tmdlHdmiCecClearDigitalTimer */
++/* [ ] tmdlHdmiCecClearExternalTimerWithExternalPlug */
++/* [ ] tmdlHdmiCecClearExternalTimerWithPhysicalAddress */
++/* [ ] tmdlHdmiCecDeckControl */
++/* [ ] tmdlHdmiCecDeckStatus */
++/* [ ] tmdlHdmiCecDeviceVendorID */
++/* [ ] tmdlHdmiCecFeatureAbort */
++/* [ ] tmdlHdmiCecGetCecVersion */
++/* [ ] tmdlHdmiCecGetMenuLanguage */
++/* [ ] tmdlHdmiCecGiveAudioStatus */
++/* [ ] tmdlHdmiCecGiveDeckStatus */
++/* [ ] tmdlHdmiCecGiveDevicePowerStatus */
++/* [ ] tmdlHdmiCecGiveDeviceVendorID */
++/* [ ] tmdlHdmiCecGiveOsdName */
++/* [ ] tmdlHdmiCecGivePhysicalAddress */
++/* [ ] tmdlHdmiCecGiveSystemAudioModeStatus */
++/* [ ] tmdlHdmiCecGiveTunerDeviceStatus */
++/* [ ] tmdlHdmiCecImageViewOn */
++/* [ ] tmdlHdmiCecInactiveSource */
++/* [ ] tmdlHdmiCecMenuRequest */
++/* [ ] tmdlHdmiCecMenuStatus */
++/* [ ] tmdlHdmiCecPlay */
++/* [ ] tmdlHdmiCecPollingMessage */
++/* [ ] tmdlHdmiCecRecordOff */
++/* [ ] tmdlHdmiCecRecordOnAnalogueService */
++/* [ ] tmdlHdmiCecRecordOnDigitalService */
++/* [ ] tmdlHdmiCecRecordOnExternalPhysicalAddress */
++/* [ ] tmdlHdmiCecRecordOnExternalPlug */
++/* [ ] tmdlHdmiCecRecordOnOwnSource */
++/* [ ] tmdlHdmiCecRecordStatus */
++/* [ ] tmdlHdmiCecRecordTvScreen */
++/* [ ] tmdlHdmiCecReportAudioStatus */
++/* [ ] tmdlHdmiCecReportPhysicalAddress */
++/* [ ] tmdlHdmiCecReportPowerStatus */
++/* [ ] tmdlHdmiCecRequestActiveSource */
++/* [ ] tmdlHdmiCecRoutingChange */
++/* [ ] tmdlHdmiCecRoutingInformation */
++/* [ ] tmdlHdmiCecSelectAnalogueService */
++/* [ ] tmdlHdmiCecSelectDigitalService */
++/* [ ] tmdlHdmiCecSetAnalogueTimer */
++/* [ ] tmdlHdmiCecSetAudioRate */
++/* [ ] tmdlHdmiCecSetDigitalTimer */
++/* [ ] tmdlHdmiCecSetExternalTimerWithExternalPlug */
++/* [ ] tmdlHdmiCecSetExternalTimerWithPhysicalAddress */
++/* [ ] tmdlHdmiCecSetMenuLanguage */
++/* [ ] tmdlHdmiCecSetOsdName */
++/* [ ] tmdlHdmiCecSetOsdString */
++/* [ ] tmdlHdmiCecSetStreamPath */
++/* [ ] tmdlHdmiCecSetSystemAudioMode */
++/* [ ] tmdlHdmiCecSetTimerProgramTitle */
++/* [ ] tmdlHdmiCecStandby */
++/* [ ] tmdlHdmiCecSystemAudioModeRequest */
++/* [ ] tmdlHdmiCecSystemAudioModeStatus */
++/* [ ] tmdlHdmiCecTextViewOn */
++/* [ ] tmdlHdmiCecTimerClearedStatus */
++/* [ ] tmdlHdmiCecTimerStatus */
++/* [ ] tmdlHdmiCecTunerDeviceStatusAnalogue */
++/* [ ] tmdlHdmiCecTunerDeviceStatusDigital */
++/* [ ] tmdlHdmiCecTunerStepDecrement */
++/* [ ] tmdlHdmiCecTunerStepIncrement */
++/* [ ] tmdlHdmiCecUserControlPressed */
++/* [ ] tmdlHdmiCecUserControlPressedPlay */
++/* [ ] tmdlHdmiCecUserControlPressedSelectAudioInput */
++/* [ ] tmdlHdmiCecUserControlPressedSelectAVInput */
++/* [ ] tmdlHdmiCecUserControlPressedSelectMedia */
++/* [ ] tmdlHdmiCecUserControlPressedTune */
++/* [ ] tmdlHdmiCecUserControlReleased */
++/* [ ] tmdlHdmiCecVendorCommand */
++/* [ ] tmdlHdmiCecVendorCommandWithID */
++/* [ ] tmdlHdmiCecVendorRemoteButtonDown */
++/* [ ] tmdlHdmiCecVendorRemoteButtonUp */
++/* [ ] tmdlHdmiCecGetSWVersion */
++/* [ ] tmdlHdmiCecGetNumberOfUnits */
++/* [ ] tmdlHdmiCecGetCapabilities */
++/* [ ] tmdlHdmiCecGetCapabilitiesM */
++/* [ ] tmdlHdmiCecOpen */
++/* [ ] tmdlHdmiCecOpenM */
++/* [ ] tmdlHdmiCecClose */
++/* [ ] tmdlHdmiCecSetPowerState */
++/* [ ] tmdlHdmiCecGetPowerState */
++/* [ ] tmdlHdmiCecInstanceConfig */
++/* [ ] tmdlHdmiCecInstanceSetup */
++/* [ ] tmdlHdmiCecGetInstanceSetup */
++/* [ ] tmdlHdmiCecHandleInterrupt */
++/* [ ] tmdlHdmiCecRegisterCallbacks */
++/* [ ] tmdlHdmiCecSetAutoAnswer */
++/* [ ] tmdlHdmiCecSetLogicalAddress */
++/* [ ] tmdlHdmiCecEnableEvent */
++/* [ ] tmdlHdmiCecDisableEvent */
++/* [ ] tmdlHdmiCecEnableCalibration */
++/* [ ] tmdlHdmiCecDisableCalibration */
++/* [ ] tmdlHdmiCecSendMessage */
++/* [ ] tmdlHdmiCecSetRegister */
++
++
++#endif /* __cec_h__ */
++#endif /* __cec_ioctl__ */
+diff --git a/drivers/video/nxp/tda998x_version.h b/drivers/video/nxp/tda998x_version.h
+new file mode 100755
+index 0000000..11233e0
+--- /dev/null
++++ b/drivers/video/nxp/tda998x_version.h
+@@ -0,0 +1,17 @@
++#ifndef __tda_version__
++#define __tda_version__
++
++/* version */
++#define TDA_VERSION_MAJOR 1
++#define TDA_VERSION_MINOR 3
++#define TDA_VERSION_PATCHLEVEL 0
++#define TDA_VERSION_EXTRA "-ioctl (2009-10-15)"
++
++/* TDA TX chip list */
++#define TDA19989 "tda19989"
++#define TDA19988 "tda19989"
++#define TDA9984 "tda9984"
++#define TDA9983 "tda9983"
++#define TDA9981 "tda9981"
++
++#endif
+diff --git a/drivers/video/nxp/test/Makefile b/drivers/video/nxp/test/Makefile
+new file mode 100755
+index 0000000..fd2fcb8
+--- /dev/null
++++ b/drivers/video/nxp/test/Makefile
+@@ -0,0 +1,28 @@
++PACKAGE_NAME=DEMO_TDA
++
++RULES:=compile
++# ROOT=/home/vadmin/dev/hdmi/omapzoom/nxp-modules
++ROOT=..
++INC=-I${ROOT} -I${ROOT}/inc -I${ROOT}/comps -I${ROOT}/comps/inc -I${ROOT}/comps/tmdlHdmiTx/inc -I${ROOT}/comps/tmdlHdmiCEC/inc
++
++EXTRA_CFLAGS += -DFUNC_PTR=" " -DCONST_DAT="const " -DRAM_DAT=" "
++CFLAGS= ${INC}
++# LDFLAGS= -lpthread
++ACC=agcc
++# ACC=arm-none-linux-gnueabi-gcc
++
++BINARIES=demo_tda
++
++all: $(RULES)
++
++clean:
++ @echo "\t-----> $(PACKAGE_NAME):$@"
++ @rm -f $(BINARIES) *.o
++
++compile:
++ $(ACC) $(CFLAGS) $(LDFLAGS) demo_tda.c -o demo_tda
++
++upload:
++ adb shell rm demo_tda
++ adb push demo_tda demo_tda
++ adb shell ./demo_tda
+diff --git a/drivers/video/nxp/test/demo_tda.c b/drivers/video/nxp/test/demo_tda.c
+new file mode 100755
+index 0000000..0365a6c
+--- /dev/null
++++ b/drivers/video/nxp/test/demo_tda.c
+@@ -0,0 +1,758 @@
++/* *
++ * Filename: tda_demo.c
++ *
++ * Description: bench and stress of CEC
++ * features for TDA19989
++ */
++/* Created: 2009-10-20
++ *
++ * Author: Andre Lepine
++ * Company: NXP Semiconductors Caen
++ *
++ */
++#define TDA_DEMO_VERSION "v0.1"
++
++/* linux */
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <fcntl.h>
++#include <assert.h>
++#include <signal.h>
++#include <string.h>
++#include <pthread.h>
++#include "tmdlHdmiTx_Types.h"
++#include "tmdlHdmiCEC_Types.h"
++#include "tda998x.h"
++#include "tda998x_ioctl.h"
++/* #include "tda998x_cec.h" */
++
++
++/*
++ *
++ * Definitions
++ * -----------
++ * CHAPTER 0
++ *
++ */
++
++#define USERCHECK(x,y) {if (user_request & (x)) {y;}}
++#define _MY_IOCTL(fd,prefix,io,param) {if (ioctl(fd,prefix##io, param) == -1) {oups("ioctl failed",prefix##io);}}
++#define IO_CEC(io,param) _MY_IOCTL(cec,CEC_IOCTL_,io,param)
++#define IO_TX(io,param) _MY_IOCTL(tx,TDA_IOCTL_,io,param)
++#define IO_RX(io,param) _MY_IOCTL(rx,CEC_IOCTL_,io,param)
++#define CEC_DEV "/dev/hdmicec"
++#define TX_DEV "/dev/hdmitx"
++
++typedef struct {
++ unsigned char received;
++ unsigned char service;
++ unsigned char addr;
++ unsigned char data[15];
++} rx_frame;
++
++unsigned int user_request,user_wait;
++const char cec_name[]=CEC_DEV;
++const char tx_name[]=TX_DEV;
++int rx=0,tx=0,cec=0;
++pthread_t rx_thread;
++unsigned short phy_addr;
++cec_string osd_name = {{78,88,80},3}; /* NXP */
++tmdlHdmiCECDeviceType_t device_type = CEC_DEVICE_TYPE_PLAYBACK_DEVICE;
++
++/*
++ *
++ * Internals
++ * ---------
++ * CHAPTER 1
++ *
++ */
++
++char *cec_service(int service)
++{
++ switch (service)
++ {
++ case CEC_WAITING: {return "waiting";break;}
++ case CEC_RELEASE: {return "release";break;}
++ case CEC_RX_DONE: {return "new message";break;}
++ case CEC_TX_DONE: {return "one message sent";break;}
++ default : {return "unknown";break;}
++ }
++}
++
++/*
++ * syntax for dumies
++ */
++void print_usage(char *exename)
++{
++ printf("Usage: %s [test_numer] [loop]\n",exename);
++ printf("0x001: driver open/close\n");
++ printf("0x002: ...\n");
++}
++
++/*
++ * We did it !
++ */
++void my_exit(int signum) {
++
++ printf("bye\n");
++
++ /*
++ .last ioctl for releasing
++ .munmap if needed
++ .free
++ */
++
++ if (tx) close(tx);
++ if (cec) {
++ ioctl(cec,CEC_IOCTL_BYEBYE, NULL);
++ close(cec);
++ }
++ if (rx) close(rx);
++
++ _exit(signum);
++}
++
++/*
++ * Failure
++ */
++void oups(char *s,int io) {
++
++ if (io) {
++ printf("%s (%d)\noups...\n",s,io);
++ }
++ else {
++ }
++
++ /*
++ .specific ioctl for releasing
++ */
++
++ if (tx) close(tx);
++ if (cec) {
++ ioctl(cec,CEC_IOCTL_BYEBYE, NULL);
++ close(cec);
++ }
++ if (rx) close(rx);
++
++ my_exit(EXIT_FAILURE);
++}
++
++
++/*
++ *
++ * Methods
++ * -------
++ * CHAPTER 2
++ *
++ */
++
++/*
++ do some event control here...
++*/
++void read_frame(cec_frame *frame) {
++
++ unsigned char initiator, receiver;
++ int param1,param2,param3;
++ UInt32 vendor_ID;
++ UInt32 vendor_CmdID0, vendor_CmdID1, vendor_CmdID2;
++ char language[3] = {0x65,0x6e,0x67}; /* eng */
++ tmdlHdmiCECAudioStatus_t audio;
++ tmdlHdmiCecInstanceSetup_t setup;
++ cec_feature_abort fa;
++ int i;
++
++ printf("CEC module says:%s\n",cec_service(frame->service));
++
++ /*Give receive data from CEC bus*/
++ if (frame->service == CEC_RX_DONE) {
++
++ //initiator and receiver
++ initiator = (frame->addr >> 4) & 0x0f;
++ receiver = frame->addr & 0x0f;
++ printf("[%x]->[%x] data:%02x%02x%02x%02x...\n", \
++ initiator, \
++ receiver, \
++ frame->data[0], \
++ frame->data[1], \
++ frame->data[2], \
++ frame->data[3]);
++
++
++ // Particular case of Polling Message//
++ if (frame->count == 0x03)
++ {
++ }
++ else
++ {
++ switch(frame->data[0])
++ {
++ // Standby
++ case CEC_OPCODE_STANDBY :
++#ifdef CEC_PW_MGT
++ IO_TX(SET_POWER,tmPowerStandby);
++#endif
++ break;
++
++ // Set Menu Language
++ case CEC_OPCODE_GET_MENU_LANGUAGE :
++ IO_CEC(SET_MENU_LANGUAGE,language);
++ break;
++
++ // Set Menu Language
++ case CEC_OPCODE_SET_MENU_LANGUAGE :
++ param1 = frame->data[1];
++ param2 = frame->data[2];
++ param3 = frame->data[3];
++ printf(" <Language = %c%c%c>\n", param1,param2,param3);
++ break;
++
++ // Active Source
++ case CEC_OPCODE_ACTIVE_SOURCE :
++ param1 = ((int)frame->data[1] << 8) + frame->data[2];
++ printf(" <Physical Address = %.4x>\n", param1);
++ break;
++
++ // Inactive Source
++ case CEC_OPCODE_INACTIVE_SOURCE :
++ param1 = ((int)frame->data[1] << 8) + frame->data[2];
++ printf(" <Physical Address = %.4x>\n", param1);
++ break;
++
++ // CEC Version
++ case CEC_OPCODE_CEC_VERSION :
++ param1 = frame->data[1];
++ printf(" <CEC Version = %x>\n", param1);
++ break;
++
++ // Give OSD Name
++ case CEC_OPCODE_GIVE_OSD_NAME :
++ IO_CEC(SET_OSD_NAME,&osd_name); /* to be check FIXEME */
++ break;
++
++ // Give Device vendor_ ID
++ case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID :
++ IO_CEC(DEVICE_VENDOR_ID,0x000800b7);
++ break;
++
++ // Report Physical Address
++ case CEC_OPCODE_REPORT_PHYSICAL_ADDRESS :
++ param1 = ((int)frame->data[1] << 8) + frame->data[2];
++ param2 = frame->data[3];
++ printf(" <Physical Address = %x> <Device Type = %x> \n", param1, param2);
++ break;
++
++ // Device vendor_ ID
++ case CEC_OPCODE_DEVICE_VENDOR_ID :
++ vendor_ID = ((int)frame->data[1] << 16) + \
++ ((int)frame->data[2] << 8) + \
++ frame->data[3];
++ printf(" <vendor_ ID = 0x%lx>\n", vendor_ID);
++ break;
++
++ case CEC_OPCODE_VENDOR_COMMAND_WITH_ID :
++ vendor_ID = ((int)frame->data[1] << 16) + \
++ ((int)frame->data[2] << 8)+ \
++ frame->data[3];
++ vendor_CmdID0 = ((int)frame->data[4] << 24) + \
++ ((int)frame->data[5] << 16)+ \
++ ((int)frame->data[6] << 8)+ \
++ frame->data[7];
++ vendor_CmdID1 = ((int)frame->data[8] << 24) + \
++ ((int)frame->data[9] << 16)+ \
++ ((int)frame->data[10] << 8)+ \
++ frame->data[11];
++ vendor_CmdID2 = ((int)frame->data[12] << 16) + \
++ ((int)frame->data[13] << 8)+ \
++ frame->data[14];
++ printf(" <vendor_ ID = 0x%lx> <Command ID = 0x%lx%lx%lx>\n", vendor_ID, vendor_CmdID0, vendor_CmdID1, vendor_CmdID2);
++ break;
++
++ // Menu Request
++ case CEC_OPCODE_MENU_REQUEST :
++ param1 = frame->data[1];
++ printf(" <Menu Request Type = %x>\n", param1);
++ break;
++
++ // Report Power Status
++ case CEC_OPCODE_REPORT_POWER_STATUS :
++ param1 =frame->data[1];
++ printf(" <Power Status = %x>\n", param1);
++ break;
++
++ // Set OSD Name
++ case CEC_OPCODE_SET_OSD_NAME :
++ for(i=1; i <= (frame->count-4); i++)
++ printf("%c", frame->data[i]);
++ printf(" >\n ");
++ break;
++
++ // Abort Message
++ case CEC_OPCODE_ABORT_MESSAGE :
++ fa.FeatureOpcode=CEC_OPCODE_ABORT_MESSAGE;
++ fa.AbortReason=CEC_ABORT_REFUSED;
++ printf("ABORT_MESSAGE received\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++
++ // Feature Abort
++ case CEC_OPCODE_FEATURE_ABORT :
++ printf("FEATURE_ABORT");
++ param1 = frame->data[1];
++ param2 = frame->data[2];
++ printf(" <Opcode = %x> <Abort Reason = %x>\n", param1, param2);
++ break;
++
++ // Routing Change
++ case CEC_OPCODE_ROUTING_CHANGE :
++ param1 = ((int)frame->data[1] << 8) + frame->data[2];
++ param2 = frame->data[3];
++ printf(" <Physical Address = %x> <New Address = %x>\n", param1, param2);
++ break;
++
++ //Set Stream Path
++ case CEC_OPCODE_SET_STREAM_PATH :
++ param1 = ((int)frame->data[1] << 8) + frame->data[2];
++ printf(" <Physical Address = %x>\n", param1);
++ if (param1 == phy_addr) {
++ /* IO_CEC(ACTIVE_SRC,0); Done my module itself */
++ }
++ break;
++
++ //Give Device Power Status
++ case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS :
++ IO_CEC(REPORT_POWER_STATUS,CEC_POWER_STATUS_ON);
++ break;
++
++ //Give Audio Status
++ case CEC_OPCODE_GIVE_AUDIO_STATUS :
++ audio.audioMuteSatus = CEC_AUDIO_MUTE_OFF;
++ audio.audioVolumeSatus = 15;
++ IO_CEC(REPORT_AUDIO_STATUS,&audio);
++ break;
++
++ case CEC_OPCODE_PLAY:
++ switch (frame->data[1]) {
++ case CEC_MODE_PLAY_FORWARD:
++ IO_TX(SET_POWER,tmPowerOn);
++ break;
++ case CEC_MODE_PLAY_REVERSE:
++ break;
++ case CEC_MODE_FAST_FORWARD_MIN_SPEED:
++ break;
++ case CEC_MODE_FAST_FORWARD_MEDIUM_SPEED:
++ break;
++ case CEC_MODE_FAST_FORWARD_MAX_SPEED:
++ break;
++ case CEC_MODE_FAST_REVERSE_MIN_SPEED:
++ break;
++ case CEC_MODE_FAST_REVERSE_MEDIUM_SPEED:
++ break;
++ case CEC_MODE_FAST_REVERSE_MAX_SPEED:
++ break;
++ case CEC_MODE_SLOW_FORWARD_MIN_SPEED:
++ break;
++ case CEC_MODE_SLOW_FORWARD_MEDIUM_SPEED:
++ break;
++ case CEC_MODE_SLOW_FORWARD_MAX_SPEED:
++ break;
++ case CEC_MODE_SLOW_REVERSE_MIN_SPEED:
++ break;
++ case CEC_MODE_SLOW_REVERSE_MEDIUM_SPEED:
++ break;
++ case CEC_MODE_SLOW_REVERSE_MAX_SPEED:
++ break;
++ default:
++ fa.FeatureOpcode=frame->data[0];
++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND;
++ printf("Send feature abort::invalid operand in opcode play\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++ }
++ break;
++
++ case CEC_OPCODE_USER_CONTROL_PRESSED:
++ switch (frame->data[1]) {
++ case CEC_REMOTE_BUTTON_SELECT:
++ break;
++ case CEC_REMOTE_BUTTON_UP:
++ break;
++ case CEC_REMOTE_BUTTON_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_LEFT:
++ break;
++ case CEC_REMOTE_BUTTON_RIGHT:
++ break;
++ case CEC_REMOTE_BUTTON_RIGHT_UP:
++ break;
++ case CEC_REMOTE_BUTTON_RIGHT_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_LEFT_UP:
++ break;
++ case CEC_REMOTE_BUTTON_LEFT_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_ROOT_MENU:
++ break;
++ case CEC_REMOTE_BUTTON_SETUP_MENU:
++ break;
++ case CEC_REMOTE_BUTTON_CONTENTS_MENU:
++ break;
++ case CEC_REMOTE_BUTTON_FAVORITE_MENU:
++ break;
++ case CEC_REMOTE_BUTTON_EXIT:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_0:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_1:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_2:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_3:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_4:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_5:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_6:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_7:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_8:
++ break;
++ case CEC_REMOTE_BUTTON_NUMBER_9:
++ break;
++ case CEC_REMOTE_BUTTON_DOT:
++ break;
++ case CEC_REMOTE_BUTTON_ENTER:
++ break;
++ case CEC_REMOTE_BUTTON_CLEAR:
++ break;
++ case CEC_REMOTE_BUTTON_NEXT_FAVORITE:
++ break;
++ case CEC_REMOTE_BUTTON_CHANNEL_UP:
++ break;
++ case CEC_REMOTE_BUTTON_CHANNEL_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_PREVIOUS_CHANNEL:
++ break;
++ case CEC_REMOTE_BUTTON_SOUND_SELECT:
++ break;
++ case CEC_REMOTE_BUTTON_INPUT_SELECT:
++ break;
++ case CEC_REMOTE_BUTTON_DISPLAY_INFORMATION:
++ break;
++ case CEC_REMOTE_BUTTON_HELP:
++ break;
++ case CEC_REMOTE_BUTTON_PAGE_UP:
++ break;
++ case CEC_REMOTE_BUTTON_PAGE_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_POWER:
++ break;
++ case CEC_REMOTE_BUTTON_VOLUME_UP:
++ break;
++ case CEC_REMOTE_BUTTON_VOLUME_DOWN:
++ break;
++ case CEC_REMOTE_BUTTON_MUTE:
++ break;
++ case CEC_REMOTE_BUTTON_PLAY:
++ break;
++ case CEC_REMOTE_BUTTON_STOP:
++ break;
++ case CEC_REMOTE_BUTTON_PAUSE:
++ break;
++ case CEC_REMOTE_BUTTON_RECORD:
++ break;
++ case CEC_REMOTE_BUTTON_REWIND:
++ break;
++ case CEC_REMOTE_BUTTON_FAST_FORWARD:
++ break;
++ case CEC_REMOTE_BUTTON_EJECT:
++ break;
++ case CEC_REMOTE_BUTTON_FORWARD:
++ break;
++ case CEC_REMOTE_BUTTON_BACKWARD:
++ break;
++ case CEC_REMOTE_BUTTON_STOP_RECORD:
++ break;
++ case CEC_REMOTE_BUTTON_PAUSE_RECORD:
++ break;
++ case CEC_REMOTE_BUTTON_ANGLE:
++ break;
++ case CEC_REMOTE_BUTTON_SUB_PICTURE:
++ break;
++ case CEC_REMOTE_BUTTON_VIDEO_ON_DEMAND:
++ break;
++ case CEC_REMOTE_BUTTON_ELECTRONIC_PROGRAM_GUIDE:
++ break;
++ case CEC_REMOTE_BUTTON_TIMER_PROGRAMMING:
++ break;
++ case CEC_REMOTE_BUTTON_INITIAL_CONFIGURATION:
++ break;
++ case CEC_REMOTE_BUTTON_PLAY_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_PAUSE_PLAY_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_RECORD_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_PAUSE_RECORD_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_STOP_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_MUTE_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_RESTORE_VOLUME_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_TUNE_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_SELECT_MEDIA_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_SELECT_AV_INPUT_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_SELECT_AUDIO_INPUT_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_POWER_TOGGLE_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_POWER_OFF_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_POWER_ON_FUNCTION:
++ break;
++ case CEC_REMOTE_BUTTON_F1_BLUE:
++ break;
++ case CEC_REMOTE_BUTTON_F2_RED:
++ break;
++ case CEC_REMOTE_BUTTON_F3_GREEN:
++ break;
++ case CEC_REMOTE_BUTTON_F4_YELLOW:
++ break;
++ case CEC_REMOTE_BUTTON_F5:
++ break;
++ case CEC_REMOTE_BUTTON_DATA:
++ break;
++ default:
++ fa.FeatureOpcode=frame->data[0];
++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND;
++ printf("Send feature abort::invalid operand in user control pressed\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++ }
++ break;
++
++ case CEC_OPCODE_DECK_CONTROL:
++ switch (frame->data[1]) {
++ case CEC_DECK_CONTROL_WIND: /*!< Skip Forward / Wind */
++ break;
++ case CEC_DECK_CONTROL_REWIND: /*!< Skip Reverse / Rewind */
++ break;
++ case CEC_DECK_CONTROL_STOP: /*!< Stop */
++ break;
++ case CEC_DECK_CONTROL_EJECT: /*!< Eject */
++ break;
++ default:
++ fa.FeatureOpcode=frame->data[0];
++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND;
++ printf("Send feature abort::invalid operand in deck control\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++ }
++ break;
++
++ case CEC_OPCODE_DECK_STATUS:
++ switch (frame->data[1]) {
++ case CEC_DECK_INFO_PLAY: /*!< Play */
++ break;
++ case CEC_DECK_INFO_RECORD: /*!< Record */
++ break;
++ case CEC_DECK_INFO_PLAY_REVERSE: /*!< Play Reverse */
++ break;
++ case CEC_DECK_INFO_STILL: /*!< Still */
++ break;
++ case CEC_DECK_INFO_SLOW: /*!< Slow */
++ break;
++ case CEC_DECK_INFO_SLOW_REVERSE: /*!< Slow Reverse */
++ break;
++ case CEC_DECK_INFO_FAST_FORWARD: /*!< Fast Forward */
++ break;
++ case CEC_DECK_INFO_FAST_REVERSE: /*!< Fast Reverse */
++ break;
++ case CEC_DECK_INFO_NO_MEDIA: /*!< No Media */
++ break;
++ case CEC_DECK_INFO_STOP: /*!< Stop */
++ break;
++ case CEC_DECK_INFO_WIND: /*!< Skip Forward / Wind */
++ break;
++ case CEC_DECK_INFO_REWIND: /*!< Skip Reverse / Rewind */
++ break;
++ case CEC_DECK_INFO_ID_SEARCH_FORWARD: /*!< Index Search Forward */
++ break;
++ case CEC_DECK_INFO_ID_SEARCH_REVERSE: /*!< Index Search Forward */
++ break;
++ case CEC_DECK_INFO_OTHER_STATUS: /*!< Other Status */
++ break;
++ default:
++ fa.FeatureOpcode=frame->data[0];
++ fa.AbortReason=CEC_ABORT_INVALID_OPERAND;
++ printf("Send feature abort::invalid operand in deck status\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++ }
++ break;
++
++
++ case CEC_OPCODE_USER_CONTROL_RELEASED:
++ break;
++
++ default:
++ fa.FeatureOpcode=frame->data[0];
++ fa.AbortReason=CEC_ABORT_UNKNOWN_OPCODE;
++ printf("Send feature abort::unknown opcode\n");
++ IO_CEC(FEATURE_ABORT,&fa);
++ break;
++ }
++ }
++ }
++ else if (frame->service == CEC_TX_DONE) {
++ /* ack */
++ }
++}
++
++
++void *rx_main( void *ptr ) {
++
++ cec_frame frame;
++ memset(&frame,0,sizeof(cec_frame));
++
++ printf("%s is alive\n",__func__);
++
++ /* another cec for event */
++ if ((rx = open(cec_name, O_RDWR)) == -1) {
++ perror(cec_name);
++ oups("can not open hdmicec driver\n",0);
++ }
++
++ /* main loop */
++ while(frame.service!=CEC_RELEASE) {
++ IO_RX(WAIT_FRAME,&frame);
++ read_frame(&frame);
++ }
++
++ close(rx);
++ pthread_exit(0);
++
++ return NULL;
++}
++
++/*
++ *
++ * Bench
++ * ---------
++ * CHAPTER 3
++ *
++ */
++
++/* 0x001: driver open/close */
++void bench0001(void) {
++
++ unsigned long /* tda_power */ power;
++
++ printf("%s\n",__func__);
++
++
++ /*
++ * init
++ */
++
++ if ((tx = open(tx_name, O_RDWR)) == -1) {
++ perror(tx_name);
++ oups("can not open hdmicec driver (evt mgr)\n",0);
++ }
++
++ printf("Power on device\n");
++ power = tmPowerOn;
++ IO_TX(SET_POWER,&power);
++
++ if ((cec = open(cec_name, O_RDWR)) == -1) {
++ perror(cec_name);
++ oups("can not open hdmicec driver\n",0);
++ }
++
++ IO_CEC(RX_ADDR,CEC_LOGICAL_ADDRESS_PLAYBACK_DEVICE_1);
++ IO_CEC(POLLING_MSG,NULL);
++
++ /* Create independent threads each of which will execute function */
++ if (pthread_create( &rx_thread, NULL, rx_main, NULL)) {
++ oups("can not create rx_thread\n",0);
++ }
++
++ /*
++ * idle
++ */
++
++ sleep(user_wait);
++ /* IO_CEC(ACTIVE_SRC,0); */
++ /* IO_CEC(IMAGE_VIEW_ON,0); */
++
++
++ /*
++ * deinit
++ */
++
++ /* stop rx_thread */
++ printf("rx_thread release request\n");
++ IO_CEC(BYEBYE,0);
++ pthread_join(rx_thread, NULL);
++
++ /* bye bye */
++ close(cec);
++ close(tx);
++}
++
++/* 0x002: ... */
++void bench0002(void) {
++
++ printf("%s\n",__func__);
++
++}
++
++/*
++ *
++ * Entry point
++ * -----------
++ * CHAPTER 4
++ *
++ */
++
++int main(int argc, char *argv[]) {
++
++ printf("tda_demo, %s, %s %s\n",TDA_DEMO_VERSION,__DATE__,__TIME__);
++ printf("any feedback welcome - andre.lepine@nxp.com\n");
++
++ user_wait = 3;
++ user_request=0xFFFF;
++ /* Check command line parameters and init framebuffer */
++ if (argc > 1) user_request = strtol(argv[1],NULL,16);
++ if (argc > 2) user_wait = strtol(argv[2],NULL,16);
++
++ printf("User request:%x user_wait:%d\n",user_request,user_wait);
++
++ /* hook up our exit handler */
++ signal(SIGINT|SIGTERM|SIGKILL|SIGQUIT, my_exit);
++
++ /*
++ * BENCH
++ */
++ printf("\nSW raster%s", \
++ "\n---------\n");
++ USERCHECK(0x01,bench0001());
++ USERCHECK(0x02,bench0002());
++
++ /*
++ Exit with success
++ */
++ print_usage(argv[0]);
++ raise(SIGTERM);
++ return 0;
++}
diff --git a/patches/linux-3.7/0172-Added-DT-binding-to-NXP-driver.patch b/patches/linux-3.7/0172-Added-DT-binding-to-NXP-driver.patch
new file mode 100644
index 0000000..f612484
--- /dev/null
+++ b/patches/linux-3.7/0172-Added-DT-binding-to-NXP-driver.patch
@@ -0,0 +1,34 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Thu, 15 Nov 2012 16:45:47 -0600
+Subject: [PATCH] Added DT binding to NXP driver
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/nxp/tda998x.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/video/nxp/tda998x.c b/drivers/video/nxp/tda998x.c
+index 4b45e41..2864221 100755
+--- a/drivers/video/nxp/tda998x.c
++++ b/drivers/video/nxp/tda998x.c
+@@ -1911,6 +1911,12 @@ static int this_i2c_remove(struct i2c_client *client)
+ * I2C client driver (backend)
+ * -----------------
+ */
++static const struct of_device_id tda988x_of_match[] = {
++ { .compatible = "nxp,tda988x", },
++ { },
++};
++MODULE_DEVICE_TABLE(of, tda988x_of_match);
++
+ static const struct i2c_device_id this_i2c_id[] = {
+ { TX_NAME, 0 },
+ { },
+@@ -1922,6 +1928,7 @@ static struct i2c_driver this_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = TX_NAME,
++ .of_match_table = tda988x_of_match
+ },
+ .probe = this_i2c_probe,
+ .remove = this_i2c_remove,
diff --git a/patches/linux-3.7/0173-da8xx-fb-Add-timings-for-720x480-60.patch b/patches/linux-3.7/0173-da8xx-fb-Add-timings-for-720x480-60.patch
new file mode 100644
index 0000000..af6c5e3
--- /dev/null
+++ b/patches/linux-3.7/0173-da8xx-fb-Add-timings-for-720x480-60.patch
@@ -0,0 +1,78 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Tue, 20 Nov 2012 11:17:33 -0600
+Subject: [PATCH] da8xx-fb: Add timings for 720x480@60
+
+Also add timings for 1080p, 720p and 480p
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/da8xx-fb.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
+index 6d98184..d6b228f 100644
+--- a/drivers/video/da8xx-fb.c
++++ b/drivers/video/da8xx-fb.c
+@@ -312,6 +312,62 @@ static struct da8xx_panel known_lcd_panels[] = {
+ .pxl_clk = 30000000,
+ .invert_pxl_clk = 0,
+ },
++ [6] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "nxp-720x480@60",
++ .width = 720,
++ .height = 480,
++ .hfp = 15,
++ .hbp = 59,
++ .hsw = 61,
++ .vfp = 9,
++ .vbp = 30,
++ .vsw = 5,
++ .pxl_clk = 27027000,
++ .invert_pxl_clk = 0,
++ },
++ [7] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "nxp-1280x720@60",
++ .width = 1280,
++ .height = 720,
++ .hfp = 109, // 20
++ .hbp = 219, // 54
++ .hsw = 39,
++ .vfp = 5,
++ .vbp = 19,
++ .vsw = 5,
++ .pxl_clk = 74250000,
++ .invert_pxl_clk = 0,
++ },
++ [8] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "nxp-640x480@60",
++ .width = 640,
++ .height = 480,
++ .hfp = 19, // 20 /* Need more changes later */
++ .hbp = 79, // 54
++ .hsw = 59,
++ .vfp = 9,
++ .vbp = 30,
++ .vsw = 6,
++ .pxl_clk = 25200000,
++ .invert_pxl_clk = 0,
++ },
++ [9] = {
++ /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */
++ .name = "nxp-1920x1080@24",
++ .width = 1920,
++ .height = 1080,
++ .hfp = 103, // 20
++ .hbp = 311, // 54
++ .hsw = 31,
++ .vfp = 37,
++ .vbp = 60,
++ .vsw = 8,
++ .pxl_clk = 96000000,
++ .invert_pxl_clk = 0,
++ },
+ };
+
+ /* Enable the Raster Engine of the LCD Controller */
diff --git a/patches/linux-3.7/0174-Add-capebus-override-and-pinmux-for-da8xx-dt.patch b/patches/linux-3.7/0174-Add-capebus-override-and-pinmux-for-da8xx-dt.patch
new file mode 100644
index 0000000..42a16f4
--- /dev/null
+++ b/patches/linux-3.7/0174-Add-capebus-override-and-pinmux-for-da8xx-dt.patch
@@ -0,0 +1,91 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Thu, 6 Dec 2012 02:57:00 -0600
+Subject: [PATCH] Add capebus override and pinmux for da8xx-dt
+
+Config da8xx-fb for 1280x720 with disp-pll settings
+Add commented disp-pll settings for other freqs
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ arch/arm/boot/dts/am335x-bone-common.dtsi | 54 +++++++++++++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
+index 0378046..5bb6a1c 100644
+--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
+@@ -127,6 +127,32 @@
+ >;
+ };
+
++ nxp_hdmi_cape_pins: nxp_hdmi_cape_pins {
++ pinctrl-single,pins = <
++
++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
++ >;
++ };
++
+ bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins {
+ pinctrl-single,pins = <
+ 0xe4 0x07 /* lcd_hsync.gpio2_23, OUTPUT | MODE7 */
+@@ -275,6 +301,10 @@
+ compatible = "bone-generic-cape";
+ };
+
++ nxp_hdmi_capebus: cape@6 {
++ compatible = "bone-generic-cape";
++ };
++
+ /* overrides; no EEPROM (prototyping) */
+ // override@3 {
+ // compatible = "bone-capebus-slot-override";
+@@ -439,6 +469,30 @@
+ slots = <&cape_eeprom_0 &cape_eeprom_1 &cape_eeprom_2 &cape_eeprom_3>;
+ };
+
++/* On-board NXP HDMI Part requires LCDC enabled which is currently
++ only registered using capebus infrastructure */
++&nxp_hdmi_capebus {
++ board-name = "NXP HDMI on capebus";
++ version@00A1 {
++ version = "00A1";
++ dvi {
++ compatible = "da8xx-dt";
++ pinctrl-names = "default";
++ pinctrl-0 = <&nxp_hdmi_cape_pins>;
++
++ ti,hwmods = "lcdc";
++/*
++ 126000000 - 640x480
++ 135000000 - 720x480
++ 371000000 - 1280x720
++ 192000000 - 1920x1080
++*/
++ disp-pll = <371000000>;
++ panel-type = "nxp-1280x720@60";
++ };
++ };
++};
++
+ &bone_dvi_cape {
+ board-name = "BeagleBone DVI-D CAPE";
+
diff --git a/patches/linux-3.7/0175-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch b/patches/linux-3.7/0175-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch
new file mode 100644
index 0000000..c53cedf
--- /dev/null
+++ b/patches/linux-3.7/0175-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch
@@ -0,0 +1,48 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Tue, 20 Nov 2012 14:14:27 -0600
+Subject: [PATCH] video/Kconfig+Makefile: Add new Kconfig for old driver
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/Kconfig | 2 ++
+ drivers/video/Makefile | 2 ++
+ drivers/video/nxp/Kconfig | 7 +++++++
+ 3 files changed, 11 insertions(+)
+ create mode 100644 drivers/video/nxp/Kconfig
+
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index e7868d8..3dc4ae8 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -2433,6 +2433,8 @@ source "drivers/video/omap2/Kconfig"
+ source "drivers/video/exynos/Kconfig"
+ source "drivers/video/backlight/Kconfig"
+
++source "drivers/video/nxp/Kconfig"
++
+ if VT
+ source "drivers/video/console/Kconfig"
+ endif
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 0e13296..10e0642 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -168,3 +168,5 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
+
+ #video output switch sysfs driver
+ obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
++
++obj-$(CONFIG_NXP_TDA998X_OLD) += nxp/
+diff --git a/drivers/video/nxp/Kconfig b/drivers/video/nxp/Kconfig
+new file mode 100644
+index 0000000..1315c5f
+--- /dev/null
++++ b/drivers/video/nxp/Kconfig
+@@ -0,0 +1,7 @@
++config NXP_TDA998X_OLD
++ tristate "NXP TDA998X HDMI video display driver"
++ select REGMAP_I2C
++ depends on I2C
++ help
++ Say Y here if you want to support NXP's TDA998X HDMI driver
++ To compile this driver as a module, choose M here.
diff --git a/patches/linux-3.7/0176-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch b/patches/linux-3.7/0176-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch
new file mode 100644
index 0000000..97a30e2
--- /dev/null
+++ b/patches/linux-3.7/0176-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch
@@ -0,0 +1,34 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Tue, 20 Nov 2012 14:18:08 -0600
+Subject: [PATCH] am335x-bonelt/dts: Add DT node to probe NXP driver
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ arch/arm/boot/dts/am335x-bonelt.dts | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am335x-bonelt.dts b/arch/arm/boot/dts/am335x-bonelt.dts
+index 87257ac..44814b4 100644
+--- a/arch/arm/boot/dts/am335x-bonelt.dts
++++ b/arch/arm/boot/dts/am335x-bonelt.dts
+@@ -30,3 +30,20 @@
+ ti,non-removable;
+ status = "okay";
+ };
++
++&i2c0 {
++ tda998X@34 {
++ compatible = "nxp,tda988x";
++ reg = <0x34>;
++ };
++};
++
++&capebus {
++ override@0 {
++ board-name = "NXP HDMI on CapeBus";
++ compatible = "bone-capebus-slot-override";
++ slot = <1>;
++ version = "00A1";
++ manufacturer = "Beagleboardtoys";
++ };
++};
diff --git a/patches/linux-3.7/0177-tda-driver-enable-1280x720.patch b/patches/linux-3.7/0177-tda-driver-enable-1280x720.patch
new file mode 100644
index 0000000..9a61abe
--- /dev/null
+++ b/patches/linux-3.7/0177-tda-driver-enable-1280x720.patch
@@ -0,0 +1,25 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Mon, 3 Dec 2012 11:08:39 -0600
+Subject: [PATCH] tda driver: enable 1280x720
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/nxp/tda998x.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/video/nxp/tda998x.c b/drivers/video/nxp/tda998x.c
+index 2864221..de9ce6d 100755
+--- a/drivers/video/nxp/tda998x.c
++++ b/drivers/video/nxp/tda998x.c
+@@ -1034,9 +1034,9 @@ static int hdmi_tx_init(tda_instance *this)
+ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_31_1920x1080p_50Hz; */
+ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_60Hz; */
+ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_PC_640x480p_72Hz; */
+- // this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz;
++ this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_04_1280x720p_60Hz;
+ /* this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_19_1280x720p_50Hz; */
+- this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
++ // this->tda.setio.video_out.format = TMDL_HDMITX_VFMT_02_720x480p_60Hz;
+
+ this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_RGB444;
+ /* this->tda.setio.video_in.mode = TMDL_HDMITX_VINMODE_CCIR656; */
diff --git a/patches/linux-3.7/0178-Makefile-Disable-CEC.patch b/patches/linux-3.7/0178-Makefile-Disable-CEC.patch
new file mode 100644
index 0000000..944fc74
--- /dev/null
+++ b/patches/linux-3.7/0178-Makefile-Disable-CEC.patch
@@ -0,0 +1,22 @@
+From: Joel A Fernandes <joelagnel@ti.com>
+Date: Mon, 3 Dec 2012 11:09:29 -0600
+Subject: [PATCH] Makefile: Disable CEC
+
+Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
+---
+ drivers/video/nxp/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/nxp/Makefile b/drivers/video/nxp/Makefile
+index f583226..05dc816 100755
+--- a/drivers/video/nxp/Makefile
++++ b/drivers/video/nxp/Makefile
+@@ -14,7 +14,7 @@ TDA_PLATFORM := ZOOMII
+
+ #TDA_HDCP := 0
+ TDA_HDCP := TMFL_HDCP_SUPPORT
+-TDA_CEC := TDA9950
++#TDA_CEC := TDA9950
+
+ # add this if INTERRUPT is wired, otherwise polling with timer is used
+ #EXTRA_CFLAGS += -DIRQ
diff --git a/patches/linux-3.7/0180-uio-uio_pruss-port-to-AM33xx.patch b/patches/linux-3.7/0180-uio-uio_pruss-port-to-AM33xx.patch
new file mode 100644
index 0000000..056d96d
--- /dev/null
+++ b/patches/linux-3.7/0180-uio-uio_pruss-port-to-AM33xx.patch
@@ -0,0 +1,239 @@
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 21 Sep 2012 12:23:49 -0400
+Subject: [PATCH] uio: uio_pruss: port to AM33xx
+
+Add ifdefery hacks to only use SRAM on Davinci. This
+needs to be cleaned up with a sane generic SRAM allocator
+(like the DT based driver available that can't be used on
+Davinci which is just starting DT conversion) before it
+can go upstream.
+
+Adds DT, pinctrl, and runtime PM support for use on
+AM33xx.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ Documentation/devicetree/bindings/uio/pruss.txt | 17 ++++++
+ .../devicetree/bindings/uio/uio_pruss.txt | 17 ++++++
+ drivers/uio/Kconfig | 4 +-
+ drivers/uio/uio_pruss.c | 63 +++++++++++++++++++-
+ 4 files changed, 98 insertions(+), 3 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/uio/pruss.txt
+ create mode 100644 Documentation/devicetree/bindings/uio/uio_pruss.txt
+
+diff --git a/Documentation/devicetree/bindings/uio/pruss.txt b/Documentation/devicetree/bindings/uio/pruss.txt
+new file mode 100644
+index 0000000..2ac45c5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/uio/pruss.txt
+@@ -0,0 +1,17 @@
++TI PRUSS device
++
++Required properties:
++- compatible :
++ - "ti,pruss-v1" for AM18xx/OMAP-L138/DA850
++ - "ti,pruss-v2" for AM33xx.
++- ti,pintc-offset : Offset of the PINTC from the PRUSS address base
++- ti,hwmods: Name of the hwmod associated to the PRUSS
++
++Example:
++
++pruss: pruss@4a300000 {
++ compatible = "ti,pruss-v2";
++ ti,hwmods = "pruss";
++ reg = <0x4a300000 0x080000>;
++ ti,pintc-offset = <0x20000>;
++};
+diff --git a/Documentation/devicetree/bindings/uio/uio_pruss.txt b/Documentation/devicetree/bindings/uio/uio_pruss.txt
+new file mode 100644
+index 0000000..2ac45c5
+--- /dev/null
++++ b/Documentation/devicetree/bindings/uio/uio_pruss.txt
+@@ -0,0 +1,17 @@
++TI PRUSS device
++
++Required properties:
++- compatible :
++ - "ti,pruss-v1" for AM18xx/OMAP-L138/DA850
++ - "ti,pruss-v2" for AM33xx.
++- ti,pintc-offset : Offset of the PINTC from the PRUSS address base
++- ti,hwmods: Name of the hwmod associated to the PRUSS
++
++Example:
++
++pruss: pruss@4a300000 {
++ compatible = "ti,pruss-v2";
++ ti,hwmods = "pruss";
++ reg = <0x4a300000 0x080000>;
++ ti,pintc-offset = <0x20000>;
++};
+diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
+index 6f3ea9b..8da7d9b 100644
+--- a/drivers/uio/Kconfig
++++ b/drivers/uio/Kconfig
+@@ -96,9 +96,9 @@ config UIO_NETX
+
+ config UIO_PRUSS
+ tristate "Texas Instruments PRUSS driver"
+- depends on ARCH_DAVINCI_DA850
++ depends on ARCH_DAVINCI_DA850 || SOC_AM33XX
+ help
+- PRUSS driver for OMAPL138/DA850/AM18XX devices
++ PRUSS driver for OMAPL138/DA850/AM18XX and AM33XX devices
+ PRUSS driver requires user space components, examples and user space
+ driver is available from below SVN repo - you may use anonymous login
+
+diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
+index 33a7a27..326ce40 100644
+--- a/drivers/uio/uio_pruss.c
++++ b/drivers/uio/uio_pruss.c
+@@ -25,7 +25,15 @@
+ #include <linux/clk.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/slab.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
++#include <linux/pm_runtime.h>
++
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ #include <mach/sram.h>
++#endif
+
+ #define DRV_NAME "pruss_uio"
+ #define DRV_VERSION "1.0"
+@@ -105,8 +113,10 @@ static void pruss_cleanup(struct platform_device *dev,
+ dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
+ gdev->ddr_paddr);
+ }
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ if (gdev->sram_vaddr)
+ sram_free(gdev->sram_vaddr, sram_pool_sz);
++#endif
+ kfree(gdev->info);
+ clk_put(gdev->pruss_clk);
+ kfree(gdev);
+@@ -117,8 +127,10 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ struct uio_info *p;
+ struct uio_pruss_dev *gdev;
+ struct resource *regs_prussio;
++ struct resource res;
+ int ret = -ENODEV, cnt = 0, len;
+ struct uio_pruss_pdata *pdata = dev->dev.platform_data;
++ struct pinctrl *pinctrl;
+
+ gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+ if (!gdev)
+@@ -129,6 +141,7 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ kfree(gdev);
+ return -ENOMEM;
+ }
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ /* Power on PRU in case its not done as part of boot-loader */
+ gdev->pruss_clk = clk_get(&dev->dev, "pruss");
+ if (IS_ERR(gdev->pruss_clk)) {
+@@ -140,6 +153,28 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ } else {
+ clk_enable(gdev->pruss_clk);
+ }
++#endif
++
++ if (dev->dev.of_node) {
++ pm_runtime_enable(&dev->dev);
++ ret = pm_runtime_get_sync(&dev->dev);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(&dev->dev, "pm_runtime_get_sync() failed\n");
++ return ret;
++ }
++
++ ret = of_address_to_resource(dev->dev.of_node, 0, &res);
++ if (IS_ERR_VALUE(ret)) {
++ dev_err(&dev->dev, "failed to parse DT reg\n");
++ return ret;
++ }
++ regs_prussio = &res;
++ }
++
++ pinctrl = devm_pinctrl_get_select_default(&dev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&dev->dev,
++ "pins are not configured from the driver\n");
+
+ regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!regs_prussio) {
+@@ -152,11 +187,13 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ goto out_free;
+ }
+
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
+ if (!gdev->sram_vaddr) {
+ dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+ goto out_free;
+ }
++#endif
+
+ gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
+ &(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA);
+@@ -172,7 +209,17 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ goto out_free;
+ }
+
+- gdev->pintc_base = pdata->pintc_base;
++ if (dev->dev.of_node) {
++ ret = of_property_read_u32(dev->dev.of_node,
++ "ti,pintc-offset",
++ &gdev->pintc_base);
++ if (ret < 0) {
++ dev_err(&dev->dev,
++ "Can't parse ti,pintc-offset property\n");
++ goto out_free;
++ }
++ } else
++ gdev->pintc_base = pdata->pintc_base;
+ gdev->hostirq_start = platform_get_irq(dev, 0);
+
+ for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+@@ -180,6 +227,7 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ p->mem[0].size = resource_size(regs_prussio);
+ p->mem[0].memtype = UIO_MEM_PHYS;
+
++#ifdef CONFIG_ARCH_DAVINCI_DA850
+ p->mem[1].addr = gdev->sram_paddr;
+ p->mem[1].size = sram_pool_sz;
+ p->mem[1].memtype = UIO_MEM_PHYS;
+@@ -187,6 +235,11 @@ static int __devinit pruss_probe(struct platform_device *dev)
+ p->mem[2].addr = gdev->ddr_paddr;
+ p->mem[2].size = extram_pool_sz;
+ p->mem[2].memtype = UIO_MEM_PHYS;
++#else
++ p->mem[1].addr = gdev->ddr_paddr;
++ p->mem[1].size = extram_pool_sz;
++ p->mem[1].memtype = UIO_MEM_PHYS;
++#endif
+
+ p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+ p->version = DRV_VERSION;
+@@ -218,12 +271,20 @@ static int __devexit pruss_remove(struct platform_device *dev)
+ return 0;
+ }
+
++static const struct of_device_id pruss_dt_ids[] = {
++ { .compatible = "ti,pruss-v1", .data = NULL, },
++ { .compatible = "ti,pruss-v2", .data = NULL, },
++ {},
++};
++MODULE_DEVICE_TABLE(of, pruss_dt_ids);
++
+ static struct platform_driver pruss_driver = {
+ .probe = pruss_probe,
+ .remove = __devexit_p(pruss_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
++ .of_match_table = pruss_dt_ids,
+ },
+ };
+
diff --git a/patches/linux-3.7/0181-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch b/patches/linux-3.7/0181-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
new file mode 100644
index 0000000..bc03cce
--- /dev/null
+++ b/patches/linux-3.7/0181-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
@@ -0,0 +1,80 @@
+From: Matt Porter <mporter@ti.com>
+Date: Mon, 24 Sep 2012 09:54:17 -0400
+Subject: [PATCH] ARM: omap: add DT support for deasserting hardware reset
+ lines
+
+This optional binding extension allows specification of a hwmod
+and associate hardware reset line which should be deasserted for
+the device to be functional.
+
+The implementation works for reference as to the problem that
+exists for utilizing uio_pruss on AM33xx but is suboptimal. The
+problem is that this deassertion occurs before clocks are enabled
+and we are warned that the hard reset failed. Ideally the list of
+rst lines requested to be deasserted would be cached and used within
+the hwmod enable sequencing (instead of it just returning if any
+hardware reset line is asserted).
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ .../devicetree/bindings/arm/omap/omap.txt | 2 ++
+ arch/arm/plat-omap/omap_device.c | 25 ++++++++++++++++++--
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
+index d0051a7..3133a4b 100644
+--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
++++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
+@@ -21,6 +21,8 @@ Required properties:
+ Optional properties:
+ - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+ during suspend.
++- ti,deassert-hard-reset: list of hwmod and hardware reset line name pairs
++ (ascii strings) to be deasserted upon device instantiation.
+
+
+ Example:
+diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
+index a15b715..b47161a 100644
+--- a/arch/arm/plat-omap/omap_device.c
++++ b/arch/arm/plat-omap/omap_device.c
+@@ -330,8 +330,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+ struct device_node *node = pdev->dev.of_node;
+- const char *oh_name;
+- int oh_cnt, i, ret = 0;
++ const char *oh_name, *rst_name;
++ int oh_cnt, dstr_cnt, i, ret = 0;
+
+ oh_cnt = of_property_count_strings(node, "ti,hwmods");
+ if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+@@ -376,6 +376,27 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
+ if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
+ omap_device_disable_idle_on_suspend(pdev);
+
++ dstr_cnt =
++ of_property_count_strings(node, "ti,deassert-hard-reset");
++ if (dstr_cnt > 0) {
++ for (i = 0; i < dstr_cnt; i += 2) {
++ of_property_read_string_index(
++ node, "ti,deassert-hard-reset", i,
++ &oh_name);
++ of_property_read_string_index(
++ node, "ti,deassert-hard-reset", i+1,
++ &rst_name);
++ oh = omap_hwmod_lookup(oh_name);
++ if (!oh) {
++ dev_warn(&pdev->dev,
++ "Cannot parse deassert property for '%s'\n",
++ oh_name);
++ break;
++ }
++ omap_hwmod_deassert_hardreset(oh, rst_name);
++ }
++ }
++
+ pdev->dev.pm_domain = &omap_device_pm_domain;
+
+ odbfd_exit1:
diff --git a/patches/linux-3.7/0182-ARM-dts-AM33xx-PRUSS-support.patch b/patches/linux-3.7/0182-ARM-dts-AM33xx-PRUSS-support.patch
new file mode 100644
index 0000000..77b2dae
--- /dev/null
+++ b/patches/linux-3.7/0182-ARM-dts-AM33xx-PRUSS-support.patch
@@ -0,0 +1,33 @@
+From: Matt Porter <mporter@ti.com>
+Date: Fri, 21 Sep 2012 12:33:14 -0400
+Subject: [PATCH] ARM: dts: AM33xx PRUSS support
+
+Adds a pruss node and an example of use on Beaglebone.
+
+Signed-off-by: Matt Porter <mporter@ti.com>
+Signed-off-by: Matt Ranostay <mranostay@gmail.com>
+---
+ arch/arm/boot/dts/am33xx.dtsi | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
+index 5e418c7..8bff718 100644
+--- a/arch/arm/boot/dts/am33xx.dtsi
++++ b/arch/arm/boot/dts/am33xx.dtsi
+@@ -467,6 +467,16 @@
+ interrupt = <61>;
+ ti,hwmods = "ecap2";
+ #pwm-cells = <3>;
++ };
++
++ pruss: pruss@4a300000 {
++ compatible = "ti,pruss-v2";
++ ti,hwmods = "pruss";
++ ti,deassert-hard-reset = "pruss", "pruss";
++ reg = <0x4a300000 0x080000>;
++ ti,pintc-offset = <0x20000>;
++ interrupt-parent = <&intc>;
++ interrupts = <20 21 22 23 24 25 26 27>;
+ status = "disabled";
+ };
+ };
diff --git a/patches/linux-3.7/0184-kbuild-deb-pkg-set-host-machine-after-dpkg-gencontro.patch b/patches/linux-3.7/0184-kbuild-deb-pkg-set-host-machine-after-dpkg-gencontro.patch
new file mode 100644
index 0000000..4e90647
--- /dev/null
+++ b/patches/linux-3.7/0184-kbuild-deb-pkg-set-host-machine-after-dpkg-gencontro.patch
@@ -0,0 +1,110 @@
+From: Robert Gordon <robert@greenroomsoftware.com>
+Date: Wed, 13 Apr 2011 11:32:29 -0500
+Subject: [PATCH] kbuild, deb-pkg: set host machine after dpkg-gencontrol
+
+scripts/package/builddeb script was setting the host machine
+$arch in the KERNEL/debian/control prior to an invocation of
+dpkg-gencontrol. The patch modifies the script to guarantee the correct
+debian arch for the target is written to the control file instead.
+
+Signed-off-by: Robert Gordon <robert@greenroomsoftware.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ scripts/package/builddeb | 70 ++++++++++++++++++++++++----------------------
+ 1 file changed, 36 insertions(+), 34 deletions(-)
+
+diff --git a/scripts/package/builddeb b/scripts/package/builddeb
+index acb8650..72d6255 100644
+--- a/scripts/package/builddeb
++++ b/scripts/package/builddeb
+@@ -26,37 +26,7 @@ create_package() {
+ chmod -R go-w "$pdir"
+
+ # Attempt to find the correct Debian architecture
+- local forcearch="" debarch=""
+- case "$UTS_MACHINE" in
+- i386|ia64|alpha)
+- debarch="$UTS_MACHINE" ;;
+- x86_64)
+- debarch=amd64 ;;
+- sparc*)
+- debarch=sparc ;;
+- s390*)
+- debarch=s390 ;;
+- ppc*)
+- debarch=powerpc ;;
+- parisc*)
+- debarch=hppa ;;
+- mips*)
+- debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
+- arm*)
+- debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
+- *)
+- echo "" >&2
+- echo "** ** ** WARNING ** ** **" >&2
+- echo "" >&2
+- echo "Your architecture doesn't have it's equivalent" >&2
+- echo "Debian userspace architecture defined!" >&2
+- echo "Falling back to using your current userspace instead!" >&2
+- echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
+- echo "" >&2
+- esac
+- if [ -n "$KBUILD_DEBARCH" ] ; then
+- debarch="$KBUILD_DEBARCH"
+- fi
++ local forcearch=""
+ if [ -n "$debarch" ] ; then
+ forcearch="-DArchitecture=$debarch"
+ fi
+@@ -66,6 +36,38 @@ create_package() {
+ dpkg --build "$pdir" ..
+ }
+
++#Set the correct debian arch
++case "$UTS_MACHINE" in
++i386|ia64|alpha)
++ debarch="$UTS_MACHINE" ;;
++x86_64)
++ debarch=amd64 ;;
++sparc*)
++ debarch=sparc ;;
++s390*)
++ debarch=s390 ;;
++ppc*)
++ debarch=powerpc ;;
++parisc*)
++ debarch=hppa ;;
++mips*)
++ debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
++arm*)
++ debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
++*)
++ echo "" >&2
++ echo "** ** ** WARNING ** ** **" >&2
++ echo "" >&2
++ echo "Your architecture doesn't have it's equivalent" >&2
++ echo "Debian userspace architecture defined!" >&2
++ echo "Falling back to using your current userspace instead!" >&2
++ echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
++ echo "" >&2
++esac
++if [ -n "$KBUILD_DEBARCH" ] ; then
++ debarch="$KBUILD_DEBARCH"
++fi
++
+ # Some variables and settings used throughout the script
+ version=$KERNELRELEASE
+ revision=$(cat .version)
+@@ -258,9 +260,9 @@ cat <<EOF >> debian/control
+
+ Package: $kernel_headers_packagename
+ Provides: linux-headers, linux-headers-2.6
+-Architecture: $arch
+-Description: Linux kernel headers for $KERNELRELEASE on $arch
+- This package provides kernel header files for $KERNELRELEASE on $arch
++Architecture: $debarch
++Description: Linux kernel headers for $KERNELRELEASE on $debarch
++ This package provides kernel header files for $KERNELRELEASE on $debarch
+ .
+ This is useful for people who need to build external modules
+ EOF
diff --git a/patches/linux-3.7/0185-arm-add-definition-of-strstr-to-decompress.c.patch b/patches/linux-3.7/0185-arm-add-definition-of-strstr-to-decompress.c.patch
new file mode 100644
index 0000000..0ec6ef4
--- /dev/null
+++ b/patches/linux-3.7/0185-arm-add-definition-of-strstr-to-decompress.c.patch
@@ -0,0 +1,36 @@
+From: Shawn Landden <shawnlandden@gmail.com>
+Date: Wed, 30 May 2012 13:45:08 -0700
+Subject: [PATCH] arm: add definition of strstr() to decompress.c
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+include/linux/dynamic_debug.h uses strstr from <linux/string.h>
+and is included via <linux/kernel.h> from lib/xz/xz_private.h
+when CONFIG_KERNEL_XZ=y.
+
+However arch/arm/boot/compressed/decompress.c defines _LINUX_STRING_H
+preventing the load of <linux/string.h> resulting in:
+
+include/linux/dynamic_debug.h:111:2: error: implicit declaration of function ‘strstr’
+
+Define strstr in arch/arm/boot/compressed/decompress.c, providing the needed
+subset of <linux/string.h>.
+
+Signed-off-by: Shawn Landden <shawnlandden@gmail.com>
+---
+ arch/arm/boot/compressed/decompress.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
+index 9deb56a..0f96125 100644
+--- a/arch/arm/boot/compressed/decompress.c
++++ b/arch/arm/boot/compressed/decompress.c
+@@ -50,6 +50,7 @@ extern char * strstr(const char * s1, const char *s2);
+ #ifdef CONFIG_KERNEL_XZ
+ #define memmove memmove
+ #define memcpy memcpy
++extern char * strstr(const char *, const char *);
+ #include "../../../../lib/decompress_unxz.c"
+ #endif
+
diff --git a/patches/linux-3.7/0187-mach-omap2-board-igep0020.c-Fix-reboot-problem.patch b/patches/linux-3.7/0187-mach-omap2-board-igep0020.c-Fix-reboot-problem.patch
new file mode 100644
index 0000000..0b6bfa7
--- /dev/null
+++ b/patches/linux-3.7/0187-mach-omap2-board-igep0020.c-Fix-reboot-problem.patch
@@ -0,0 +1,65 @@
+From: Matthias Brugger <matthias.bgg@googlemail.com>
+Date: Thu, 15 Nov 2012 17:06:53 +0100
+Subject: [PATCH] mach-omap2/board-igep0020.c: Fix reboot problem
+
+When rebooting an OMAP3530 at 125 MHz, the reboot hangs.
+This patch adds a generic power save script, which resets the TWL4030 when a
+warm reset occures. This way the OMAP3530 does not hang on reboot.
+
+Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
+---
+ arch/arm/mach-omap2/board-igep0020.c | 36 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
+index 3785906..3a7f295 100644
+--- a/arch/arm/mach-omap2/board-igep0020.c
++++ b/arch/arm/mach-omap2/board-igep0020.c
+@@ -487,11 +487,47 @@ static struct twl4030_keypad_data igep2_keypad_pdata = {
+ .rep = 1,
+ };
+
++static struct twl4030_ins wrst_seq[] __initdata = {
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2},
++ {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2},
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2},
++};
++
++static struct twl4030_script wrst_script __initdata = {
++ .script = wrst_seq,
++ .size = ARRAY_SIZE(wrst_seq),
++ .flags = TWL4030_WRST_SCRIPT,
++};
++
++static struct twl4030_script *twl4030_scripts[] __initdata = {
++ &wrst_script,
++};
++
++static struct twl4030_resconfig twl4030_rconfig[] = {
++ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { 0, 0},
++};
++
++static struct twl4030_power_data igep_twl4030_power_data = {
++ .scripts = twl4030_scripts,
++ .num = ARRAY_SIZE(twl4030_scripts),
++ .resource_config = twl4030_rconfig,
++};
++
+ static struct twl4030_platform_data igep_twldata = {
+ /* platform_data for children goes here */
+ .gpio = &igep_twl4030_gpio_pdata,
+ .vmmc1 = &igep_vmmc1,
+ .vio = &igep_vio,
++ .power = &igep_twl4030_power_data,
+ };
+
+ static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
diff --git a/patches/linux-3.7/0188-regulator-core-if-voltage-scaling-fails-restore-orig.patch b/patches/linux-3.7/0188-regulator-core-if-voltage-scaling-fails-restore-orig.patch
new file mode 100644
index 0000000..d811bdf
--- /dev/null
+++ b/patches/linux-3.7/0188-regulator-core-if-voltage-scaling-fails-restore-orig.patch
@@ -0,0 +1,53 @@
+From: Paolo Pisati <paolo.pisati@canonical.com>
+Date: Wed, 12 Dec 2012 12:45:53 +0100
+Subject: [PATCH] regulator: core: if voltage scaling fails, restore original
+ voltage values
+
+Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
+---
+ drivers/regulator/core.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index e872c8b..564ef9f 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -2250,6 +2250,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+ {
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret = 0;
++ int old_min_uV, old_max_uV;
+
+ mutex_lock(&rdev->mutex);
+
+@@ -2271,18 +2272,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
+ ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
+ if (ret < 0)
+ goto out;
++
++ /* restore original values in case of error */
++ old_min_uV = regulator->min_uV;
++ old_max_uV = regulator->max_uV;
+ regulator->min_uV = min_uV;
+ regulator->max_uV = max_uV;
+
+ ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
+ if (ret < 0)
+- goto out;
++ goto out2;
+
+ ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
++ if (ret < 0)
++ goto out2;
+
+ out:
+ mutex_unlock(&rdev->mutex);
+ return ret;
++out2:
++ regulator->min_uV = old_min_uV;
++ regulator->max_uV = old_max_uV;
++ mutex_unlock(&rdev->mutex);
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(regulator_set_voltage);
+
diff --git a/patches/linux-3.7/0190-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch b/patches/linux-3.7/0190-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
new file mode 100644
index 0000000..be7a8d9
--- /dev/null
+++ b/patches/linux-3.7/0190-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
@@ -0,0 +1,74 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Tue, 19 Jan 2010 21:19:15 -0800
+Subject: [PATCH] OMAP: DSS2: add bootarg for selecting svideo
+
+ OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
+ also add pal-16 and ntsc-16 omapfb.mode settings for 16bpp
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/omap2/dss/venc.c | 22 ++++++++++++++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c | 10 +++++++++-
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
+index 56efa3b..d46f7f8 100644
+--- a/drivers/video/omap2/dss/venc.c
++++ b/drivers/video/omap2/dss/venc.c
+@@ -86,6 +86,11 @@
+ #define VENC_OUTPUT_TEST 0xC8
+ #define VENC_DAC_B__DAC_C 0xC8
+
++static char *tv_connection;
++
++module_param_named(tvcable, tv_connection, charp, 0);
++MODULE_PARM_DESC(tvcable, "TV connection type (svideo, composite)");
++
+ struct venc_config {
+ u32 f_control;
+ u32 vidout_ctrl;
+@@ -465,6 +470,23 @@ static int venc_power_on(struct omap_dss_device *dssdev)
+ if (r)
+ goto err2;
+
++ /* Allow the TV output to be overriden */
++ if (tv_connection) {
++ if (strcmp(tv_connection, "svideo") == 0) {
++ printk(KERN_INFO
++ "omapdss: tv output is svideo.\n");
++ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
++ } else if (strcmp(tv_connection, "composite") == 0) {
++ printk(KERN_INFO
++ "omapdss: tv output is composite.\n");
++ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
++ } else {
++ printk(KERN_INFO
++ "omapdss: unsupported output type'%s'.\n",
++ tv_connection);
++ }
++ }
++
+ return 0;
+
+ err2:
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 16db158..dca8650 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -2033,7 +2033,15 @@ static int omapfb_mode_to_timings(const char *mode_str,
+ int r;
+
+ #ifdef CONFIG_OMAP2_DSS_VENC
+- if (strcmp(mode_str, "pal") == 0) {
++ if (strcmp(mode_str, "pal-16") == 0) {
++ *timings = omap_dss_pal_timings;
++ *bpp = 16;
++ return 0;
++ } else if (strcmp(mode_str, "ntsc-16") == 0) {
++ *timings = omap_dss_ntsc_timings;
++ *bpp = 16;
++ return 0;
++ } else if (strcmp(mode_str, "pal") == 0) {
+ *timings = omap_dss_pal_timings;
+ *bpp = 24;
+ return 0;
diff --git a/patches/linux-3.7/0191-video-add-timings-for-hd720.patch b/patches/linux-3.7/0191-video-add-timings-for-hd720.patch
new file mode 100644
index 0000000..9034278
--- /dev/null
+++ b/patches/linux-3.7/0191-video-add-timings-for-hd720.patch
@@ -0,0 +1,24 @@
+From: Steve Sakoman <steve@sakoman.com>
+Date: Sat, 19 Dec 2009 06:52:43 -0800
+Subject: [PATCH] video: add timings for hd720
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/modedb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
+index a9a907c..5b686de 100644
+--- a/drivers/video/modedb.c
++++ b/drivers/video/modedb.c
+@@ -103,6 +103,10 @@ static const struct fb_videomode modedb[] = {
+ { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 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 },
++
+ /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
+ { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
+ FB_VMODE_INTERLACED },
diff --git a/patches/linux-3.7/0193-Beagle-expansion-add-buddy-param-for-expansionboard-.patch b/patches/linux-3.7/0193-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
new file mode 100644
index 0000000..3c26820
--- /dev/null
+++ b/patches/linux-3.7/0193-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
@@ -0,0 +1,58 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:25:27 -0600
+Subject: [PATCH] Beagle: expansion: add buddy param for expansionboard names
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index d41ab98..dd282d5 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>
+ #include <linux/opp.h>
+@@ -159,6 +160,8 @@ static void __init omap3_beagle_init_rev(void)
+ }
+ }
+
++char expansionboard_name[16];
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -445,6 +448,18 @@ static struct omap_board_mux board_mux[] __initdata = {
+ };
+ #endif
+
++static int __init expansionboard_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(expansionboard_name, str, 16);
++ pr_info("Beagle expansionboard: %s\n", expansionboard_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -530,6 +545,8 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+ }
+
++early_param("buddy", expansionboard_setup);
++
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+ .atag_offset = 0x100,
diff --git a/patches/linux-3.7/0194-Beagle-expansion-add-zippy.patch b/patches/linux-3.7/0194-Beagle-expansion-add-zippy.patch
new file mode 100644
index 0000000..e1080ec
--- /dev/null
+++ b/patches/linux-3.7/0194-Beagle-expansion-add-zippy.patch
@@ -0,0 +1,227 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:30:06 -0600
+Subject: [PATCH] Beagle: expansion: add zippy
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 163 +++++++++++++++++++++++++++++--
+ 1 file changed, 157 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index dd282d5..35ad593 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -162,6 +162,86 @@ static void __init omap3_beagle_init_rev(void)
+
+ char expansionboard_name[16];
+
++enum {
++ EXPANSION_MMC_NONE = 0,
++ EXPANSION_MMC_ZIPPY,
++ EXPANSION_MMC_WIFI,
++};
++
++enum {
++ EXPANSION_I2C_NONE = 0,
++ EXPANSION_I2C_ZIPPY,
++};
++
++static struct {
++ int mmc_settings;
++ int i2c_settings;
++} expansion_config = {
++ .mmc_settings = EXPANSION_MMC_NONE,
++ .i2c_settings = EXPANSION_I2C_NONE,
++};
++
++//rcn-ee: this is just a fake regulator, the zippy hardware provides 3.3/1.8 with jumper..
++static struct fixed_voltage_config beagle_vzippy = {
++ .supply_name = "vzippy",
++ .microvolts = 3300000, /* 3.3V */
++ .startup_delay = 70000, /* 70ms */
++ .enable_high = 1,
++ .enabled_at_boot = 0,
++ .init_data = &beagle_vmmc2,
++};
++
++static struct platform_device omap_zippy_device = {
++ .name = "reg-fixed-voltage",
++ .id = 1,
++ .dev = {
++ .platform_data = &beagle_vzippy,
++ },
++};
++
++#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP 141
++#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD 162
++
++#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
++#include <linux/platform_data/spi-omap2-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,
++};
++
++static struct spi_board_info omap3beagle_zippy_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_zippy_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
++ irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ pr_err("Beagle expansionboard: could not obtain gpio for ENC28J60_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_zippy_spi_board_info,
++ ARRAY_SIZE(omap3beagle_zippy_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 */
+ {
+@@ -238,6 +318,23 @@ static struct omap2_hsmmc_info mmc[] = {
+ {} /* Terminator */
+ };
+
++static struct omap2_hsmmc_info mmc_zippy[] = {
++ {
++ .mmc = 1,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = -EINVAL,
++ .deferred = true,
++ },
++ {
++ .mmc = 2,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP,
++ .gpio_cd = OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD,
++ .transceiver = true,
++ .deferred = true,
++ },
++ {} /* Terminator */
++};
+ static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+ };
+@@ -253,10 +350,21 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ {
+ int r;
+
+- mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+- /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+- mmc[0].gpio_cd = gpio + 0;
+- omap_hsmmc_late_init(mmc);
++ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_ZIPPY:
++ mmc_zippy[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmc_zippy[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmc_zippy);
++ break;
++ default:
++ mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmc[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmc);
++ }
+
+ /*
+ * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
+@@ -349,6 +457,14 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+ },
+ };
+
++static struct i2c_board_info __initdata zippy_i2c2_rtc[] = {
++#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
++ {
++ I2C_BOARD_INFO("ds1307", 0x68),
++ },
++#endif
++};
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -359,6 +475,15 @@ static int __init omap3_beagle_i2c_init(void)
+ beagle_twldata.vpll2->constraints.name = "VDVI";
+
+ omap3_pmic_init("twl4030", &beagle_twldata);
++
++ switch (expansion_config.i2c_settings) {
++ case EXPANSION_I2C_ZIPPY:
++ omap_register_i2c_bus(2, 400, zippy_i2c2_rtc, ARRAY_SIZE(zippy_i2c2_rtc));
++ break;
++ default:
++ omap_register_i2c_bus(2, 400, NULL, 0);
++ }
++
+ /* 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, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
+@@ -513,10 +638,30 @@ static void __init omap3_beagle_init(void)
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+ omap3_beagle_init_rev();
+
++ if (!strcmp(expansionboard_name, "zippy"))
++ {
++ pr_info("Beagle expansionboard: initializing zippy mmc\n");
++ platform_device_register(&omap_zippy_device);
++
++ expansion_config.i2c_settings = EXPANSION_I2C_ZIPPY;
++ expansion_config.mmc_settings = EXPANSION_MMC_ZIPPY;
++
++ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP, OMAP_PIN_INPUT);
++ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
++ }
++
+ if (gpio_is_valid(beagle_config.mmc1_gpio_wp))
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+- mmc[0].caps = beagle_config.mmc_caps;
+- omap_hsmmc_init(mmc);
++
++ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_ZIPPY:
++ mmc_zippy[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmc_zippy);
++ break;
++ default:
++ mmc[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmc);
++ }
+
+ omap3_beagle_i2c_init();
+
+@@ -531,6 +676,12 @@ static void __init omap3_beagle_init(void)
+ omap_sdrc_init(mt46h32m32lf6_sdrc_params,
+ mt46h32m32lf6_sdrc_params);
+
++ if (!strcmp(expansionboard_name, "zippy"))
++ {
++ pr_info("Beagle expansionboard: initializing enc28j60\n");
++ omap3beagle_enc28j60_init();
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
diff --git a/patches/linux-3.7/0195-Beagle-expansion-add-zippy2.patch b/patches/linux-3.7/0195-Beagle-expansion-add-zippy2.patch
new file mode 100644
index 0000000..ab4a4ce
--- /dev/null
+++ b/patches/linux-3.7/0195-Beagle-expansion-add-zippy2.patch
@@ -0,0 +1,82 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:32:15 -0600
+Subject: [PATCH] Beagle: expansion: add zippy2
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 48 ++++++++++++++++++++++++++++++-
+ 1 file changed, 47 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 35ad593..c762083 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -242,6 +242,46 @@ static void __init omap3beagle_enc28j60_init(void)
+ static inline void __init omap3beagle_enc28j60_init(void) { return; }
+ #endif
+
++#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
++#include <linux/platform_data/spi-omap2-mcspi.h>
++#include <linux/spi/spi.h>
++
++#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
++
++static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
++ .turbo_mode = 0,
++};
++
++static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
++ {
++ .modalias = "ks8851",
++ .bus_num = 4,
++ .chip_select = 0,
++ .max_speed_hz = 36000000,
++ .controller_data = &ks8851_spi_chip_info,
++ },
++};
++
++static void __init omap3beagle_ks8851_init(void)
++{
++ if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
++ (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
++ gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
++ omap3beagle_zippy2_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_KS8851_IRQ);
++ irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
++ } else {
++ pr_err("Beagle expansionboard: could not obtain gpio for KS8851_IRQ\n");
++ return;
++ }
++
++ spi_register_board_info(omap3beagle_zippy2_spi_board_info,
++ ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
++}
++
++#else
++static inline void __init omap3beagle_ks8851_init(void) { return; }
++#endif
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+@@ -638,7 +678,7 @@ static void __init omap3_beagle_init(void)
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+ omap3_beagle_init_rev();
+
+- if (!strcmp(expansionboard_name, "zippy"))
++ if ((!strcmp(expansionboard_name, "zippy")) || (!strcmp(expansionboard_name, "zippy2")))
+ {
+ pr_info("Beagle expansionboard: initializing zippy mmc\n");
+ platform_device_register(&omap_zippy_device);
+@@ -682,6 +722,12 @@ static void __init omap3_beagle_init(void)
+ omap3beagle_enc28j60_init();
+ }
+
++ if (!strcmp(expansionboard_name, "zippy2"))
++ {
++ pr_info("Beagle expansionboard: initializing ks_8851\n");
++ omap3beagle_ks8851_init();
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
diff --git a/patches/linux-3.7/0196-Beagle-expansion-add-trainer.patch b/patches/linux-3.7/0196-Beagle-expansion-add-trainer.patch
new file mode 100644
index 0000000..d7e75e5
--- /dev/null
+++ b/patches/linux-3.7/0196-Beagle-expansion-add-trainer.patch
@@ -0,0 +1,51 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:33:24 -0600
+Subject: [PATCH] Beagle: expansion: add trainer
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index c762083..c6b33e7 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -728,6 +728,37 @@ static void __init omap3_beagle_init(void)
+ omap3beagle_ks8851_init();
+ }
+
++ if (!strcmp(expansionboard_name, "trainer"))
++ {
++ pr_info("Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
++ gpio_request(130, "sysfs");
++ gpio_export(130, 1);
++ gpio_request(131, "sysfs");
++ gpio_export(131, 1);
++ gpio_request(132, "sysfs");
++ gpio_export(132, 1);
++ gpio_request(133, "sysfs");
++ gpio_export(133, 1);
++ gpio_request(134, "sysfs");
++ gpio_export(134, 1);
++ gpio_request(135, "sysfs");
++ gpio_export(135, 1);
++ gpio_request(136, "sysfs");
++ gpio_export(136, 1);
++ gpio_request(137, "sysfs");
++ gpio_export(137, 1);
++ gpio_request(138, "sysfs");
++ gpio_export(138, 1);
++ gpio_request(139, "sysfs");
++ gpio_export(139, 1);
++ gpio_request(140, "sysfs");
++ gpio_export(140, 1);
++ gpio_request(141, "sysfs");
++ gpio_export(141, 1);
++ gpio_request(162, "sysfs");
++ gpio_export(162, 1);
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
diff --git a/patches/linux-3.7/0197-Beagle-expansion-add-CircuitCo-ulcd-Support.patch b/patches/linux-3.7/0197-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
new file mode 100644
index 0000000..f546eca
--- /dev/null
+++ b/patches/linux-3.7/0197-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
@@ -0,0 +1,290 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:42:03 -0600
+Subject: [PATCH] Beagle: expansion: add CircuitCo ulcd Support
+
+This of a cleanup, squashed both ulcd commits into one:
+
+======================================================================
+
+expansion: add ulcd
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+
+======================================================================
+
+beagleboard: fix uLCD7 support
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+
+======================================================================
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 138 ++++++++++++++++++++++
+ drivers/video/omap2/displays/panel-generic-dpi.c | 27 +++++
+ 2 files changed, 165 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index c6b33e7..6cb7815 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -42,6 +42,7 @@
+
+ #include "common.h"
+ #include <video/omapdss.h>
++#include <video/omap-panel-generic-dpi.h>
+ #include <video/omap-panel-tfp410.h>
+ #include <plat/gpmc.h>
+ #include <linux/platform_data/mtd-nand-omap2.h>
+@@ -84,12 +85,16 @@ static struct {
+ int dvi_pd_gpio;
+ int usr_button_gpio;
+ int mmc_caps;
++ char *lcd_driver_name;
++ int lcd_pwren;
+ } beagle_config = {
+ .mmc1_gpio_wp = -EINVAL,
+ .usb_pwr_level = GPIOF_OUT_INIT_LOW,
+ .dvi_pd_gpio = -EINVAL,
+ .usr_button_gpio = 4,
+ .mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
++ .lcd_driver_name = "",
++ .lcd_pwren = 156,
+ };
+
+ static struct gpio omap3_beagle_rev_gpios[] __initdata = {
+@@ -161,6 +166,7 @@ static void __init omap3_beagle_init_rev(void)
+ }
+
+ char expansionboard_name[16];
++char expansionboard2_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -171,6 +177,7 @@ enum {
+ enum {
+ EXPANSION_I2C_NONE = 0,
+ EXPANSION_I2C_ZIPPY,
++ EXPANSION_I2C_7ULCD,
+ };
+
+ static struct {
+@@ -335,9 +342,53 @@ static struct omap_dss_device beagle_tv_device = {
+ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+ };
+
++static int beagle_enable_lcd(struct omap_dss_device *dssdev)
++{
++ if (gpio_is_valid(beagle_config.lcd_pwren)) {
++ pr_info("%s: Enabling LCD\n", __FUNCTION__);
++ gpio_set_value(beagle_config.lcd_pwren, 0);
++ } else {
++ pr_info("%s: Invalid LCD enable GPIO: %d\n",
++ __FUNCTION__, beagle_config.lcd_pwren);
++ }
++
++ return 0;
++}
++
++static void beagle_disable_lcd(struct omap_dss_device *dssdev)
++{
++ if (gpio_is_valid(beagle_config.lcd_pwren)) {
++ pr_info("%s: Disabling LCD\n", __FUNCTION__);
++ gpio_set_value(beagle_config.lcd_pwren, 1);
++ } else {
++ pr_info("%s: Invalid LCD enable GPIO: %d\n",
++ __FUNCTION__, beagle_config.lcd_pwren);
++ }
++
++ return;
++}
++
++static struct panel_generic_dpi_data lcd_panel = {
++ .name = "tfc_s9700rtwv35tr-01b",
++ .platform_enable = beagle_enable_lcd,
++ .platform_disable = beagle_disable_lcd,
++};
++
++static struct omap_dss_device beagle_lcd_device = {
++ .type = OMAP_DISPLAY_TYPE_DPI,
++ .name = "lcd",
++ .driver_name = "generic_dpi_panel",
++ .phy.dpi.data_lines = 24,
++ .platform_enable = beagle_enable_lcd,
++ .platform_disable = beagle_disable_lcd,
++ .reset_gpio = -EINVAL,
++ .data = &lcd_panel,
++};
++
+ static struct omap_dss_device *beagle_dss_devices[] = {
+ &beagle_dvi_device,
+ &beagle_tv_device,
++ &beagle_lcd_device,
+ };
+
+ static struct omap_dss_board_info beagle_dss_data = {
+@@ -505,6 +556,54 @@ static struct i2c_board_info __initdata zippy_i2c2_rtc[] = {
+ #endif
+ };
+
++#if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
++/* Touchscreen */
++#include <linux/i2c/tsc2007.h>
++
++#define OMAP3BEAGLE_TSC2007_GPIO 157
++
++static int omap3beagle_tsc2007_get_pendown_state(void)
++{
++ return !gpio_get_value(OMAP3BEAGLE_TSC2007_GPIO);
++}
++
++static struct tsc2007_platform_data tsc2007_info = {
++ .model = 2007,
++ .x_plate_ohms = 180,
++ .get_pendown_state = omap3beagle_tsc2007_get_pendown_state,
++};
++
++static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {
++ {
++ I2C_BOARD_INFO("tlc59108", 0x40),
++ },
++ {
++ I2C_BOARD_INFO("tsc2007", 0x48),
++ .platform_data = &tsc2007_info,
++ },
++};
++
++static void __init omap3beagle_tsc2007_init(void)
++{
++ int r;
++
++ omap_mux_init_gpio(OMAP3BEAGLE_TSC2007_GPIO, OMAP_PIN_INPUT_PULLUP);
++
++ r = gpio_request_one(OMAP3BEAGLE_TSC2007_GPIO, GPIOF_IN, "tsc2007_pen_down");
++ if (r < 0) {
++ pr_err("Beagle expansionboard: failed to request GPIO#%d for "
++ "tsc2007 pen down IRQ\n", OMAP3BEAGLE_TSC2007_GPIO);
++ return;
++ }
++
++ beagle_i2c2_bbtoys_ulcd[0].irq = gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO);
++ irq_set_irq_type(gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO), IRQ_TYPE_EDGE_FALLING);
++}
++#else
++static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {};
++static void __init omap3beagle_tsc2007_init(void) { return; }
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -517,6 +616,10 @@ static int __init omap3_beagle_i2c_init(void)
+ omap3_pmic_init("twl4030", &beagle_twldata);
+
+ switch (expansion_config.i2c_settings) {
++ case EXPANSION_I2C_7ULCD:
++ omap_register_i2c_bus(2, 400, beagle_i2c2_bbtoys_ulcd,
++ ARRAY_SIZE(beagle_i2c2_bbtoys_ulcd));
++ break;
+ case EXPANSION_I2C_ZIPPY:
+ omap_register_i2c_bus(2, 400, zippy_i2c2_rtc, ARRAY_SIZE(zippy_i2c2_rtc));
+ break;
+@@ -625,6 +728,18 @@ static int __init expansionboard_setup(char *str)
+ return 0;
+ }
+
++static int __init expansionboard2_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(expansionboard2_name, str, 16);
++ pr_info("Beagle expansionboard2: %s\n", expansionboard2_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -690,6 +805,20 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
++ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
++ {
++ int r;
++ expansion_config.i2c_settings = EXPANSION_I2C_7ULCD;
++
++ /* TODO: set lcd_driver_name by command line or device tree */
++ beagle_config.lcd_driver_name = "tfc_s9700rtwv35tr-01b",
++ lcd_panel.name = beagle_config.lcd_driver_name;
++
++ r = gpio_request_one(beagle_config.lcd_pwren, GPIOF_OUT_INIT_LOW, "LCD power");
++ if (r < 0)
++ pr_err("Beagle expansionboard: Unable to get LCD power enable GPIO\n");
++ }
++
+ if (gpio_is_valid(beagle_config.mmc1_gpio_wp))
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+
+@@ -759,6 +888,14 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
++ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
++ {
++ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
++ pr_info("Beagle expansionboard: initializing touchscreen: tsc2007\n");
++ omap3beagle_tsc2007_init();
++ #endif
++ }
++
+ usb_musb_init(NULL);
+ usbhs_init(&usbhs_bdata);
+ omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
+@@ -774,6 +911,7 @@ static void __init omap3_beagle_init(void)
+ }
+
+ early_param("buddy", expansionboard_setup);
++early_param("buddy2", expansionboard2_setup);
+
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
+diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
+index 88295c5..b7f296b 100644
+--- a/drivers/video/omap2/displays/panel-generic-dpi.c
++++ b/drivers/video/omap2/displays/panel-generic-dpi.c
+@@ -538,6 +538,33 @@ static struct panel_config generic_dpi_panels[] = {
+ },
+ .name = "primeview_pd104slf",
+ },
++
++ /* ThreeFiveCorp S9700RTWV35TR-01B */
++ {
++ {
++ .x_res = 800,
++ .y_res = 480,
++
++ .pixel_clock = 30000,
++
++ .hsw = 49,
++ .hfp = 41,
++ .hbp = 40,
++
++ .vsw = 4,
++ .vfp = 14,
++ .vbp = 29,
++
++ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
++ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
++ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
++ .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
++ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
++ },
++ .power_on_delay = 50,
++ .power_off_delay = 100,
++ .name = "tfc_s9700rtwv35tr-01b",
++ },
+ };
+
+ struct panel_drv_data {
diff --git a/patches/linux-3.7/0198-Beagle-expansion-add-wifi.patch b/patches/linux-3.7/0198-Beagle-expansion-add-wifi.patch
new file mode 100644
index 0000000..f585673
--- /dev/null
+++ b/patches/linux-3.7/0198-Beagle-expansion-add-wifi.patch
@@ -0,0 +1,172 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:48:52 -0600
+Subject: [PATCH] Beagle: expansion: add wifi
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 117 +++++++++++++++++++++++++++++++
+ 1 file changed, 117 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 6cb7815..03773cb 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -188,6 +188,71 @@ static struct {
+ .i2c_settings = EXPANSION_I2C_NONE,
+ };
+
++#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++#include <linux/regulator/fixed.h>
++#include <linux/ti_wilink_st.h>
++#include <linux/wl12xx.h>
++
++#define OMAP_BEAGLE_WLAN_EN_GPIO (139)
++#define OMAP_BEAGLE_BT_EN_GPIO (138)
++#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137)
++#define OMAP_BEAGLE_FM_EN_BT_WU (136)
++
++struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
++ .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
++};
++
++static struct ti_st_plat_data wilink_platform_data = {
++ .nshutdown_gpio = OMAP_BEAGLE_BT_EN_GPIO,
++ .dev_name = "/dev/ttyO1",
++ .flow_cntrl = 1,
++ .baud_rate = 3000000,
++ .chip_enable = NULL,
++ .suspend = NULL,
++ .resume = NULL,
++};
++
++static struct platform_device wl12xx_device = {
++ .name = "kim",
++ .id = -1,
++ .dev.platform_data = &wilink_platform_data,
++};
++
++static struct platform_device btwilink_device = {
++ .name = "btwilink",
++ .id = -1,
++};
++
++static struct regulator_consumer_supply beagle_vmmc2_supply =
++ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
++
++static struct regulator_init_data beagle_vmmc2 = {
++ .constraints = {
++ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
++ },
++ .num_consumer_supplies = 1,
++ .consumer_supplies = &beagle_vmmc2_supply,
++};
++
++static struct fixed_voltage_config beagle_vwlan = {
++ .supply_name = "vwl1271",
++ .microvolts = 1800000, /* 1.8V */
++ .gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
++ .startup_delay = 70000, /* 70ms */
++ .enable_high = 1,
++ .enabled_at_boot = 0,
++ .init_data = &beagle_vmmc2,
++};
++
++static struct platform_device omap_vwlan_device = {
++ .name = "reg-fixed-voltage",
++ .id = 1,
++ .dev = {
++ .platform_data = &beagle_vwlan,
++ },
++};
++#endif
++
+ //rcn-ee: this is just a fake regulator, the zippy hardware provides 3.3/1.8 with jumper..
+ static struct fixed_voltage_config beagle_vzippy = {
+ .supply_name = "vzippy",
+@@ -426,6 +491,26 @@ static struct omap2_hsmmc_info mmc_zippy[] = {
+ },
+ {} /* Terminator */
+ };
++
++static struct omap2_hsmmc_info mmcbbt[] = {
++ {
++ .mmc = 1,
++ .caps = MMC_CAP_4_BIT_DATA,
++ .gpio_wp = -EINVAL,
++ .deferred = true,
++ },
++ {
++ .name = "wl1271",
++ .mmc = 2,
++ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
++ .gpio_wp = -EINVAL,
++ .gpio_cd = -EINVAL,
++ .ocr_mask = MMC_VDD_165_195,
++ .nonremovable = true,
++ },
++ {} /* Terminator */
++};
++
+ static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+ };
+@@ -442,6 +527,13 @@ static int beagle_twl_gpio_setup(struct device *dev,
+ int r;
+
+ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_WIFI:
++ mmcbbt[0].gpio_wp = beagle_config.mmc1_gpio_wp;
++ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
++ mmcbbt[0].gpio_cd = gpio + 0;
++
++ omap_hsmmc_late_init(mmcbbt);
++ break;
+ case EXPANSION_MMC_ZIPPY:
+ mmc_zippy[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+ /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+@@ -805,6 +897,13 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
++ if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ {
++ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ expansion_config.mmc_settings = EXPANSION_MMC_WIFI;
++ #endif
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ int r;
+@@ -823,6 +922,10 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
+
+ switch (expansion_config.mmc_settings) {
++ case EXPANSION_MMC_WIFI:
++ mmcbbt[0].caps = beagle_config.mmc_caps;
++ omap_hsmmc_init(mmcbbt);
++ break;
+ case EXPANSION_MMC_ZIPPY:
+ mmc_zippy[0].caps = beagle_config.mmc_caps;
+ omap_hsmmc_init(mmc_zippy);
+@@ -888,6 +991,20 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
++ if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ {
++ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
++ pr_err("error setting wl12xx data\n");
++ pr_info("Beagle expansionboard: registering wl12xx bt platform device\n");
++ platform_device_register(&wl12xx_device);
++ platform_device_register(&btwilink_device);
++ pr_info("Beagle expansionboard: registering wl12xx wifi platform device\n");
++ platform_device_register(&omap_vwlan_device);
++ #endif
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.7/0199-Beagle-expansion-add-beaglefpga.patch b/patches/linux-3.7/0199-Beagle-expansion-add-beaglefpga.patch
new file mode 100644
index 0000000..2c8efc4
--- /dev/null
+++ b/patches/linux-3.7/0199-Beagle-expansion-add-beaglefpga.patch
@@ -0,0 +1,111 @@
+From: Bas van der Doorn <bas@doornvd.com>
+Date: Tue, 11 Dec 2012 06:52:22 -0600
+Subject: [PATCH] Beagle: expansion: add beaglefpga
+
+Added SPI dev and McBSP 3 mux when FPGA is detected
+
+Signed-off-by: Bas van der Doorn <bas@doornvd.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 74 +++++++++++++++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 03773cb..e6000f4 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -39,6 +39,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/flash.h>
++#include <linux/spi/spi.h>
+
+ #include "common.h"
+ #include <video/omapdss.h>
+@@ -880,6 +881,68 @@ static int __init beagle_opp_init(void)
+ }
+ device_initcall(beagle_opp_init);
+
++static void __init omap3_beagle_config_mcspi3_mux(void)
++{
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("sdmmc2_clk.mcspi3_clk", OMAP_PIN_INPUT);
++ omap_mux_init_signal("sdmmc2_cmd.mcspi3_simo", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("sdmmc2_dat0.mcspi3_somi", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat2.mcspi3_cs1", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("sdmmc2_dat3.mcspi3_cs0", OMAP_PIN_OUTPUT);
++}
++
++static void __init omap3_beagle_config_mcspi4_mux(void)
++{
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("mcbsp1_clkr.mcspi4_clk", OMAP_PIN_INPUT);
++ omap_mux_init_signal("mcbsp1_dx.mcspi4_simo", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("mcbsp1_dr.mcspi4_somi", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("mcbsp1_fsx.mcspi4_cs0", OMAP_PIN_OUTPUT);
++}
++
++static void __init omap3_beagle_config_mcbsp3_mux(void)
++{
++ omap_mux_init_signal("mcbsp3_fsx.uart2_rx", OMAP_PIN_INPUT);
++ omap_mux_init_signal("uart2_cts.mcbsp3_dx", OMAP_PIN_OUTPUT);
++ omap_mux_init_signal("uart2_rts.mcbsp3_dr", OMAP_PIN_INPUT);
++ /* NOTE: Clock pins need to be in input mode */
++ omap_mux_init_signal("uart2_tx.mcbsp3_clkx", OMAP_PIN_INPUT);
++}
++
++static void __init omap3_beagle_config_fpga_mux(void)
++{
++ omap3_beagle_config_mcbsp3_mux();
++ omap3_beagle_config_mcspi3_mux();
++ omap3_beagle_config_mcspi4_mux();
++}
++
++static struct spi_board_info beagle_mcspi_board_info[] = {
++ /* spi 3.0 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 3,
++ .chip_select = 0,
++ .mode = SPI_MODE_1,
++ },
++ /* spi 3.1 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 3,
++ .chip_select = 1,
++ .mode = SPI_MODE_1,
++ },
++ /* spi 4.0 */
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 48000000, //48 Mbps
++ .bus_num = 4,
++ .chip_select = 0,
++ .mode = SPI_MODE_1,
++ },
++};
++
+ static void __init omap3_beagle_init(void)
+ {
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+@@ -1005,6 +1068,17 @@ static void __init omap3_beagle_init(void)
+ #endif
+ }
+
++ if (!strcmp(expansionboard_name, "beaglefpga"))
++ {
++ pr_info("Beagle expansionboard: enabling SPIdev for McSPI3/4 and pin muxing for McBSP3 slave mode\n");
++
++ /* FPGA pin settings configure McSPI 3, McSPI 4 and McBSP 3 */
++ omap3_beagle_config_fpga_mux();
++
++ /* register McSPI 3 and McSPI 4 for FPGA programming and control */
++ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.7/0200-Beagle-expansion-add-spidev.patch b/patches/linux-3.7/0200-Beagle-expansion-add-spidev.patch
new file mode 100644
index 0000000..47b5ae4
--- /dev/null
+++ b/patches/linux-3.7/0200-Beagle-expansion-add-spidev.patch
@@ -0,0 +1,29 @@
+From: Russell Hay <russell.hay@gmail.com>
+Date: Tue, 11 Dec 2012 06:53:58 -0600
+Subject: [PATCH] Beagle: expansion: add spidev
+
+Signed-off-by: Russell Hay <russell.hay@gmail.com>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index e6000f4..64b3444 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -1079,6 +1079,14 @@ static void __init omap3_beagle_init(void)
+ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
+ }
+
++ if (!strcmp(expansionboard_name, "spidev"))
++ {
++ pr_info("Beagle expansionboard: registering spidev\n");
++ omap3_beagle_config_mcspi3_mux();
++ omap3_beagle_config_mcspi4_mux();
++ spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
++ }
++
+ if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+ {
+ #if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
diff --git a/patches/linux-3.7/0201-Beagle-expansion-add-Aptina-li5m03-camera.patch b/patches/linux-3.7/0201-Beagle-expansion-add-Aptina-li5m03-camera.patch
new file mode 100644
index 0000000..9099b3c
--- /dev/null
+++ b/patches/linux-3.7/0201-Beagle-expansion-add-Aptina-li5m03-camera.patch
@@ -0,0 +1,223 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 06:58:15 -0600
+Subject: [PATCH] Beagle: expansion: add Aptina li5m03 camera
+
+Based on:
+https://github.com/Aptina/BeagleBoard-xM/blob/master/tools/0266-Adding-MT9P031-Support-files.patch
+
+And on Max Galemin's patch
+https://github.com/MaxGalemin/buildroot/blob/master/board/beagleboard/xm/kernel-patches/linux-0003-Add-support-for-MT9P031-Aptina-image-sensor-driver.patch
+
+And Koen Kooi Previous work's
+https://github.com/beagleboard/kernel/blob/beagleboard-3.2/patches/camera/0003-beagleboard-fix-i2c2-init.patch
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 152 +++++++++++++++++++++++++++++++
+ 1 file changed, 152 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 64b3444..c64ea55 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -168,6 +168,7 @@ static void __init omap3_beagle_init_rev(void)
+
+ char expansionboard_name[16];
+ char expansionboard2_name[16];
++char camera_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -520,6 +521,14 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
+ REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
+ };
+
++static struct regulator_consumer_supply beagle_vaux3_supply = {
++ .supply = "cam_1v8",
++};
++
++static struct regulator_consumer_supply beagle_vaux4_supply = {
++ .supply = "cam_2v8",
++};
++
+ static struct gpio_led gpio_leds[];
+
+ static int beagle_twl_gpio_setup(struct device *dev,
+@@ -628,11 +637,43 @@ static struct regulator_init_data beagle_vsim = {
+ .consumer_supplies = beagle_vsim_supply,
+ };
+
++/* VAUX3 for CAM_1V8 */
++static struct regulator_init_data beagle_vaux3 = {
++ .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_vaux3_supply,
++};
++
++/* VAUX4 for CAM_2V8 */
++static struct regulator_init_data beagle_vaux4 = {
++ .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_vaux4_supply,
++};
++
+ static struct twl4030_platform_data beagle_twldata = {
+ /* platform_data for children goes here */
+ .gpio = &beagle_gpio_data,
+ .vmmc1 = &beagle_vmmc1,
+ .vsim = &beagle_vsim,
++ .vaux3 = &beagle_vaux3,
++ .vaux4 = &beagle_vaux4,
+ };
+
+ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+@@ -697,6 +738,71 @@ static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {};
+ static void __init omap3beagle_tsc2007_init(void) { return; }
+ #endif
+
++#if defined(CONFIG_VIDEO_MT9P031)
++/* needed for: omap3_beagle_late_initcall */
++#include "devices.h"
++#include <media/omap3isp.h>
++#include <media/mt9p031.h>
++/* needed for: v4l2_dev_to_isp_device */
++#include "../../../drivers/media/platform/omap3isp/isp.h"
++
++#define MT9P031_XCLK ISP_XCLK_A
++
++#define MT9P031_RESET_GPIO 98
++#define MT9P031_EXT_FREQ 21000000
++#define MT9P031_TARGET_FREQ 48000000
++
++#define MT9P031_I2C_ADDR 0x48
++#define MT9P031_I2C_BUS 2
++
++static struct regulator *reg_1v8, *reg_2v8;
++
++static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz)
++{
++ struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
++
++ return isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK);
++}
++
++static struct mt9p031_platform_data beagle_mt9p031_platform_data = {
++ .set_xclk = beagle_cam_set_xclk,
++ .reset = MT9P031_RESET_GPIO,
++ .ext_freq = MT9P031_EXT_FREQ,
++ .target_freq = MT9P031_TARGET_FREQ,
++};
++
++static struct i2c_board_info mt9p031_camera_i2c_device = {
++ I2C_BOARD_INFO("mt9p031", MT9P031_I2C_ADDR),
++ .platform_data = &beagle_mt9p031_platform_data,
++};
++
++static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = {
++ {
++ .board_info = &mt9p031_camera_i2c_device,
++ .i2c_adapter_id = MT9P031_I2C_BUS,
++ },
++ { NULL, 0, },
++};
++
++static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = {
++ {
++ .subdevs = mt9p031_camera_subdevs,
++ .interface = ISP_INTERFACE_PARALLEL,
++ .bus = {
++ .parallel = {
++ .data_lane_shift = 0,
++ .clk_pol = 1,
++ }
++ },
++ },
++ { },
++};
++
++static struct isp_platform_data beagle_isp_platform_data = {
++ .subdevs = beagle_camera_subdevs,
++};
++#endif
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap3_pmic_get_config(&beagle_twldata,
+@@ -833,6 +939,18 @@ static int __init expansionboard2_setup(char *str)
+ return 0;
+ }
+
++static int __init camera_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(camera_name, str, 16);
++ pr_info("Beagle camera: %s\n", camera_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -1109,8 +1227,42 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+ }
+
++static int __init omap3_beagle_late_initcall(void)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!cpu_is_omap3630())
++ return 0;
++
++#if defined(CONFIG_VIDEO_MT9P031)
++ if ((!strcmp(camera_name, "lbcm5m1")) || (!strcmp(camera_name, "li5m03")))
++ {
++ pr_info("Beagle camera: MT9P031 init\n");
++
++ reg_1v8 = regulator_get(NULL, "cam_1v8");
++ if (IS_ERR(reg_1v8))
++ pr_err("%s: cannot get cam_1v8 regulator\n", __func__);
++ else
++ regulator_enable(reg_1v8);
++
++ reg_2v8 = regulator_get(NULL, "cam_2v8");
++ if (IS_ERR(reg_2v8))
++ pr_err("%s: cannot get cam_2v8 regulator\n", __func__);
++ else
++ regulator_enable(reg_2v8);
++
++ omap3_init_camera(&beagle_isp_platform_data);
++ }
++#endif
++ return 0;
++}
++
+ early_param("buddy", expansionboard_setup);
+ early_param("buddy2", expansionboard2_setup);
++early_param("camera", camera_setup);
++
++late_initcall(omap3_beagle_late_initcall);
+
+ MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
+ /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
diff --git a/patches/linux-3.7/0202-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch b/patches/linux-3.7/0202-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
new file mode 100644
index 0000000..419c4dc
--- /dev/null
+++ b/patches/linux-3.7/0202-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
@@ -0,0 +1,119 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 11 Dec 2012 07:02:40 -0600
+Subject: [PATCH] Beagle: expansion: add LSR COM6L Adapter Board
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 60 ++++++++++++++++++++++++++++---
+ 1 file changed, 55 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index c64ea55..4fa880a 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -169,6 +169,7 @@ static void __init omap3_beagle_init_rev(void)
+ char expansionboard_name[16];
+ char expansionboard2_name[16];
+ char camera_name[16];
++char wl12xx_name[16];
+
+ enum {
+ EXPANSION_MMC_NONE = 0,
+@@ -204,6 +205,10 @@ struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
+ .board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
+ };
+
++struct wl12xx_platform_data omap_beagle_wlan_data_26mhz __initdata = {
++ .board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
++};
++
+ static struct ti_st_plat_data wilink_platform_data = {
+ .nshutdown_gpio = OMAP_BEAGLE_BT_EN_GPIO,
+ .dev_name = "/dev/ttyO1",
+@@ -951,6 +956,18 @@ static int __init camera_setup(char *str)
+ return 0;
+ }
+
++static int __init wl12xx_setup(char *str)
++{
++ if (!machine_is_omap3_beagle())
++ return 0;
++
++ if (!str)
++ return -EINVAL;
++ strncpy(wl12xx_name, str, 16);
++ pr_info("Beagle wl12xx clk: %s\n", wl12xx_name);
++ return 0;
++}
++
+ static int __init beagle_opp_init(void)
+ {
+ int r = 0;
+@@ -1078,9 +1095,29 @@ static void __init omap3_beagle_init(void)
+ omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+ }
+
+- if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+ {
+ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
++ pr_info("Beagle expansion: wl12xx: setting up gpio pinmux\n");
++
++ omap_mux_init_gpio(OMAP_BEAGLE_FM_EN_BT_WU, OMAP_PIN_OUTPUT);
++ omap_mux_init_gpio(OMAP_BEAGLE_BT_EN_GPIO, OMAP_PIN_OUTPUT);
++ omap_mux_init_gpio(OMAP_BEAGLE_WLAN_EN_GPIO, OMAP_PIN_OUTPUT);
++
++ omap_mux_init_gpio(OMAP_BEAGLE_WLAN_IRQ_GPIO, OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 CLK */
++ omap_mux_init_signal("sdmmc2_clk.sdmmc2_clk", OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 CMD */
++ omap_mux_init_signal("sdmmc2_cmd.sdmmc2_cmd", OMAP_PIN_INPUT_PULLUP);
++
++ /* WLAN SDIO: MMC2 DAT[0-3] */
++ omap_mux_init_signal("sdmmc2_dat0.sdmmc2_dat0", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat1.sdmmc2_dat1", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat2.sdmmc2_dat2", OMAP_PIN_INPUT_PULLUP);
++ omap_mux_init_signal("sdmmc2_dat3.sdmmc2_dat3", OMAP_PIN_INPUT_PULLUP);
++
+ expansion_config.mmc_settings = EXPANSION_MMC_WIFI;
+ #endif
+ }
+@@ -1172,12 +1209,24 @@ static void __init omap3_beagle_init(void)
+ gpio_export(162, 1);
+ }
+
+- if (!strcmp(expansionboard_name, "bbtoys-wifi"))
++ if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+ {
+ #if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+- omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
+- if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
+- pr_err("error setting wl12xx data\n");
++ pr_info("Beagle expansionboard: initializing wl12xx platform\n");
++
++ if (!strcmp(wl12xx_name, "wl12xx_26mhz")) {
++ pr_info("wl12xx: 26Mhz reference clock (TiWi5)\n");
++ omap_beagle_wlan_data_26mhz.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data_26mhz))
++ pr_err("error setting wl12xx data\n");
++ } else {
++ pr_info("wl12xx: 38.4Mhz reference clock (TiWi2/TiWi-BLE)\n");
++ pr_info("wl12xx: for (TiWi5) support pass kernel [wl12xx_clk=wl12xx_26mhz]\n");
++ omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
++ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
++ pr_err("error setting wl12xx data\n");
++ }
++
+ pr_info("Beagle expansionboard: registering wl12xx bt platform device\n");
+ platform_device_register(&wl12xx_device);
+ platform_device_register(&btwilink_device);
+@@ -1261,6 +1310,7 @@ static int __init omap3_beagle_late_initcall(void)
+ early_param("buddy", expansionboard_setup);
+ early_param("buddy2", expansionboard2_setup);
+ early_param("camera", camera_setup);
++early_param("wl12xx_clk", wl12xx_setup);
+
+ late_initcall(omap3_beagle_late_initcall);
+
diff --git a/patches/linux-3.7/0204-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch b/patches/linux-3.7/0204-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
new file mode 100644
index 0000000..2e4e312
--- /dev/null
+++ b/patches/linux-3.7/0204-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
@@ -0,0 +1,26 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Wed, 23 Mar 2011 08:37:54 -0500
+Subject: [PATCH] meego: modedb add Toshiba LTA070B220F 800x480 support
+
+ from http://wiki.meego.com/ARM/Meego_on_Beagleboard_from_scratch
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/video/modedb.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
+index 5b686de..69ad1ec 100644
+--- a/drivers/video/modedb.c
++++ b/drivers/video/modedb.c
+@@ -293,6 +293,10 @@ static const struct fb_videomode modedb[] = {
+ /* 864x480 @ 60 Hz, 35.15 kHz hsync */
+ { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
+ 0, FB_VMODE_NONINTERLACED },
++
++ /* 800x480 @ 60 Hz, Toshiba LTA070B220F 7 inch LCD */
++ { NULL, 60, 800, 480, 32787, 48, 80, 33, 31, 32, 2,
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
+ };
+
+ #ifdef CONFIG_FB_MODE_HELPERS
diff --git a/patches/linux-3.7/0205-backlight-Add-TLC59108-backlight-control-driver.patch b/patches/linux-3.7/0205-backlight-Add-TLC59108-backlight-control-driver.patch
new file mode 100644
index 0000000..4ae5392
--- /dev/null
+++ b/patches/linux-3.7/0205-backlight-Add-TLC59108-backlight-control-driver.patch
@@ -0,0 +1,212 @@
+From: "Manjunathappa, Prakash" <prakash.pm@ti.com>
+Date: Mon, 1 Aug 2011 18:25:11 +0530
+Subject: [PATCH] backlight: Add TLC59108 backlight control driver
+
+This patch adds support for I2C configurable TLC59108 backlight
+control driver.
+
+Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com>
+Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
+---
+ drivers/video/backlight/Kconfig | 8 ++
+ drivers/video/backlight/Makefile | 1 +
+ drivers/video/backlight/tlc59108.c | 160 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 169 insertions(+)
+ create mode 100644 drivers/video/backlight/tlc59108.c
+
+diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
+index 765a945..50c9e35 100644
+--- a/drivers/video/backlight/Kconfig
++++ b/drivers/video/backlight/Kconfig
+@@ -390,6 +390,14 @@ config BACKLIGHT_TPS65217
+ If you have a Texas Instruments TPS65217 say Y to enable the
+ backlight driver.
+
++config BACKLIGHT_TLC59108
++ tristate "TLC59108 LCD Backlight Driver"
++ depends on I2C && BACKLIGHT_CLASS_DEVICE
++ default n
++ help
++ If you have an LCD Panel with backlight control via TLC59108,
++ say Y to enable its LCD control driver.
++
+ endif # BACKLIGHT_CLASS_DEVICE
+
+ endif # BACKLIGHT_LCD_SUPPORT
+diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
+index e7ce729..2f4711d 100644
+--- a/drivers/video/backlight/Makefile
++++ b/drivers/video/backlight/Makefile
+@@ -43,5 +43,6 @@ obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
+ obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
+ obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o
+ obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
++obj-$(CONFIG_BACKLIGHT_TLC59108) += tlc59108.o
+ obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
+ obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
+diff --git a/drivers/video/backlight/tlc59108.c b/drivers/video/backlight/tlc59108.c
+new file mode 100644
+index 0000000..4f4ea34
+--- /dev/null
++++ b/drivers/video/backlight/tlc59108.c
+@@ -0,0 +1,160 @@
++/*
++ * ti81xxhdmi_tlc59108.c
++ *
++ * Copyright (C) 2011 Texas Instruments
++ * Author: Senthil Natarajan
++ *
++ * tlc59108 HDMI 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/>.
++ * History:
++ *
++ * Senthil Natarajan<senthil.n@ti.com> July 2011 I2C driver for tlc59108
++ * backlight control
++ */
++
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/backlight.h>
++#include <linux/fb.h>
++
++#define tlc59108_MODULE_NAME "tlc59108"
++#define TLC59108_MODE1 0x00
++#define TLC59108_PWM2 0x04
++#define TLC59108_LEDOUT0 0x0c
++#define TLC59108_LEDOUT1 0x0d
++#define TLC59108_MAX_BRIGHTNESS 0xFF
++
++struct tlc59108_bl {
++ struct i2c_client *client;
++ struct backlight_device *bl;
++};
++
++static void tlc59108_bl_set_backlight(struct tlc59108_bl *data, int brightness)
++{
++ /* Set Mode1 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
++
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x21);
++
++ /* Set Backlight Duty Cycle*/
++ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2,
++ brightness & 0xff);
++}
++
++static int tlc59108_bl_get_brightness(struct backlight_device *dev)
++{
++ struct backlight_properties *props = &dev->props;
++
++ return props->brightness;
++}
++
++static int tlc59108_bl_update_status(struct backlight_device *dev)
++{
++ struct backlight_properties *props = &dev->props;
++ struct tlc59108_bl *data = dev_get_drvdata(&dev->dev);
++ int brightness = props->brightness;
++
++ tlc59108_bl_set_backlight(data, brightness);
++
++ return 0;
++}
++
++static const struct backlight_ops bl_ops = {
++ .get_brightness = tlc59108_bl_get_brightness,
++ .update_status = tlc59108_bl_update_status,
++};
++
++static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
++{
++ struct backlight_properties props;
++ struct tlc59108_bl *data = kzalloc(sizeof(struct tlc59108_bl),
++ GFP_KERNEL);
++ int ret = 0;
++
++ if (!data)
++ return -ENOMEM;
++
++ i2c_set_clientdata(c, data);
++ data->client = c;
++
++ memset(&props, 0, sizeof(struct backlight_properties));
++ props.max_brightness = TLC59108_MAX_BRIGHTNESS;
++ props.type = BACKLIGHT_RAW;
++ data->bl = backlight_device_register("tlc59108-bl", &c->dev, data,
++ &bl_ops, &props);
++ if (IS_ERR(data->bl)) {
++ ret = PTR_ERR(data->bl);
++ goto err_reg;
++ }
++
++ data->bl->props.brightness = TLC59108_MAX_BRIGHTNESS;
++
++ backlight_update_status(data->bl);
++
++ return 0;
++
++err_reg:
++ data->bl = NULL;
++ kfree(data);
++ return ret;
++}
++
++static int tlc59108_remove(struct i2c_client *c)
++{
++ struct tlc59108_bl *data = i2c_get_clientdata(c);
++
++ backlight_device_unregister(data->bl);
++ data->bl = NULL;
++
++ kfree(data);
++
++ return 0;
++}
++
++/* I2C Device ID table */
++static const struct i2c_device_id tlc59108_id[] = {
++ { "tlc59108", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, tlc59108_id);
++
++/* I2C driver data */
++static struct i2c_driver tlc59108_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = tlc59108_MODULE_NAME,
++ },
++ .probe = tlc59108_probe,
++ .remove = tlc59108_remove,
++ .id_table = tlc59108_id,
++};
++
++static int __init tlc59108_init(void)
++{
++ return i2c_add_driver(&tlc59108_driver);
++}
++
++static void __exit tlc59108_exit(void)
++{
++ i2c_del_driver(&tlc59108_driver);
++}
++
++module_init(tlc59108_init);
++module_exit(tlc59108_exit);
++
++MODULE_DESCRIPTION("LCD/Backlight control for TLC59108");
++MODULE_AUTHOR("Senthil Natarajan <senthil.n@ti.com>");
++MODULE_LICENSE("GPL v2");
diff --git a/patches/linux-3.7/0206-tlc59108-adjust-for-beagleboard-uLCD7.patch b/patches/linux-3.7/0206-tlc59108-adjust-for-beagleboard-uLCD7.patch
new file mode 100644
index 0000000..2e14b13
--- /dev/null
+++ b/patches/linux-3.7/0206-tlc59108-adjust-for-beagleboard-uLCD7.patch
@@ -0,0 +1,120 @@
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Fri, 27 Apr 2012 21:30:00 +0200
+Subject: [PATCH] tlc59108: adjust for beagleboard+uLCD7
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/video/backlight/tlc59108.c | 46 ++++++++++++++++++++++++------------
+ 1 file changed, 31 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/video/backlight/tlc59108.c b/drivers/video/backlight/tlc59108.c
+index 4f4ea34..40a21e7 100644
+--- a/drivers/video/backlight/tlc59108.c
++++ b/drivers/video/backlight/tlc59108.c
+@@ -29,9 +29,16 @@
+ #include <linux/backlight.h>
+ #include <linux/fb.h>
+
+-#define tlc59108_MODULE_NAME "tlc59108"
+ #define TLC59108_MODE1 0x00
+-#define TLC59108_PWM2 0x04
++#define TLC59108_MODE2 0x01
++#define TLC59108_PWM0 0x02
++#define TLC59108_PWM1 0x03
++#define TLC59108_PWM2 0x04
++#define TLC59108_PWM3 0x05
++#define TLC59108_PWM4 0x06
++#define TLC59108_PWM5 0x07
++#define TLC59108_PWM6 0x08
++#define TLC59108_PWM7 0x09
+ #define TLC59108_LEDOUT0 0x0c
+ #define TLC59108_LEDOUT1 0x0d
+ #define TLC59108_MAX_BRIGHTNESS 0xFF
+@@ -43,15 +50,9 @@ struct tlc59108_bl {
+
+ static void tlc59108_bl_set_backlight(struct tlc59108_bl *data, int brightness)
+ {
+- /* Set Mode1 Register */
+- i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
+-
+- /* Set LEDOUT0 Register */
+- i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x21);
+-
+ /* Set Backlight Duty Cycle*/
+ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2,
+- brightness & 0xff);
++ 0xff - brightness );
+ }
+
+ static int tlc59108_bl_get_brightness(struct backlight_device *dev)
+@@ -65,8 +66,18 @@ static int tlc59108_bl_update_status(struct backlight_device *dev)
+ {
+ struct backlight_properties *props = &dev->props;
+ struct tlc59108_bl *data = dev_get_drvdata(&dev->dev);
++
+ int brightness = props->brightness;
+
++ if (dev->props.state & BL_CORE_FBBLANK) {
++ brightness = 0;
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x10);
++ } else {
++ /* Set LEDOUT0 Register */
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x30);
++ }
++
+ tlc59108_bl_set_backlight(data, brightness);
+
+ return 0;
+@@ -77,7 +88,7 @@ static const struct backlight_ops bl_ops = {
+ .update_status = tlc59108_bl_update_status,
+ };
+
+-static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
++static int __devinit tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
+ {
+ struct backlight_properties props;
+ struct tlc59108_bl *data = kzalloc(sizeof(struct tlc59108_bl),
+@@ -104,6 +115,11 @@ static int tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
+
+ backlight_update_status(data->bl);
+
++ i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
++ i2c_smbus_write_byte_data(data->client, TLC59108_PWM2, 0x80);
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x05);
++ i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x15);
++
+ return 0;
+
+ err_reg:
+@@ -125,7 +141,7 @@ static int tlc59108_remove(struct i2c_client *c)
+ }
+
+ /* I2C Device ID table */
+-static const struct i2c_device_id tlc59108_id[] = {
++static struct i2c_device_id tlc59108_id[] = {
+ { "tlc59108", 0 },
+ { }
+ };
+@@ -134,12 +150,12 @@ MODULE_DEVICE_TABLE(i2c, tlc59108_id);
+ /* I2C driver data */
+ static struct i2c_driver tlc59108_driver = {
+ .driver = {
+- .owner = THIS_MODULE,
+- .name = tlc59108_MODULE_NAME,
++ .owner = THIS_MODULE,
++ .name = "tlc59108"
+ },
++ .id_table = tlc59108_id,
+ .probe = tlc59108_probe,
+ .remove = tlc59108_remove,
+- .id_table = tlc59108_id,
+ };
+
+ static int __init tlc59108_init(void)
+@@ -157,4 +173,4 @@ module_exit(tlc59108_exit);
+
+ MODULE_DESCRIPTION("LCD/Backlight control for TLC59108");
+ MODULE_AUTHOR("Senthil Natarajan <senthil.n@ti.com>");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
diff --git a/patches/linux-3.7/0207-zeroMAP-Open-your-eyes.patch b/patches/linux-3.7/0207-zeroMAP-Open-your-eyes.patch
new file mode 100644
index 0000000..967a1a7
--- /dev/null
+++ b/patches/linux-3.7/0207-zeroMAP-Open-your-eyes.patch
@@ -0,0 +1,27 @@
+From: Alexander Holler <holler@ahsoftware.de>
+Date: Wed, 4 Jul 2012 00:03:04 +0200
+Subject: [PATCH] zeroMAP: Open your eyes!
+
+Signed-off-by: Alexander Holler <holler@ahsoftware.de>
+---
+ kernel/printk.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/kernel/printk.c b/kernel/printk.c
+index 2d607f4..a85e5a4 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -1753,6 +1753,13 @@ static int __init console_setup(char *str)
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
++#ifdef CONFIG_SERIAL_OMAP
++ if (!strncmp(str, "tty0", 4) && '0' <= str[4] && '9' >= str[4]) {
++ str[3] = 'O';
++ pr_warn("We are opening your eyes, assuming you want to use an OMAP based serial driver and not a zeroMAP based one! ;)\n");
++ pr_warn("Which means 'tty0%s' was changed to 'ttyO%s' automagically for your pleasure.\n", str+4, str+4);
++ }
++#endif
+ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+ if (!memcmp(str, "brl,", 4)) {
+ brl_options = "";
diff --git a/patches/linux-3.7/0208-ARM-OMAP-Beagle-C4-fix-reboot-problem.patch b/patches/linux-3.7/0208-ARM-OMAP-Beagle-C4-fix-reboot-problem.patch
new file mode 100644
index 0000000..0bc2f48
--- /dev/null
+++ b/patches/linux-3.7/0208-ARM-OMAP-Beagle-C4-fix-reboot-problem.patch
@@ -0,0 +1,63 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Thu, 15 Nov 2012 13:06:40 -0600
+Subject: [PATCH] ARM: OMAP: Beagle C4: fix reboot problem
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/board-omap3beagle.c | 36 +++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 4fa880a..f5b7f77 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -672,6 +672,41 @@ static struct regulator_init_data beagle_vaux4 = {
+ .consumer_supplies = &beagle_vaux4_supply,
+ };
+
++static struct twl4030_ins wrst_seq[] __initdata = {
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2},
++ {MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60},
++ {MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2},
++ {MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2},
++};
++
++static struct twl4030_script wrst_script __initdata = {
++ .script = wrst_seq,
++ .size = ARRAY_SIZE(wrst_seq),
++ .flags = TWL4030_WRST_SCRIPT,
++};
++
++static struct twl4030_script *twl4030_scripts[] __initdata = {
++ &wrst_script,
++};
++
++static struct twl4030_resconfig twl4030_rconfig[] = {
++ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1, .type = -1,
++ .type2 = -1 },
++ { 0, 0},
++};
++
++static struct twl4030_power_data beagle_twl4030_power_data = {
++ .scripts = twl4030_scripts,
++ .num = ARRAY_SIZE(twl4030_scripts),
++ .resource_config = twl4030_rconfig,
++};
++
+ static struct twl4030_platform_data beagle_twldata = {
+ /* platform_data for children goes here */
+ .gpio = &beagle_gpio_data,
+@@ -679,6 +714,7 @@ static struct twl4030_platform_data beagle_twldata = {
+ .vsim = &beagle_vsim,
+ .vaux3 = &beagle_vaux3,
+ .vaux4 = &beagle_vaux4,
++ .power = &beagle_twl4030_power_data,
+ };
+
+ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
diff --git a/patches/linux-3.7/0210-panda-fix-wl12xx-regulator.patch b/patches/linux-3.7/0210-panda-fix-wl12xx-regulator.patch
new file mode 100644
index 0000000..f1f3959
--- /dev/null
+++ b/patches/linux-3.7/0210-panda-fix-wl12xx-regulator.patch
@@ -0,0 +1,23 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Tue, 2 Aug 2011 21:55:34 -0500
+Subject: [PATCH] panda: fix wl12xx regulator
+
+pulled from: http://elinux.org/Panda_How_to_kernel_3_0_rel
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/mach-omap2/twl-common.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
+index a256135..5b7fdd6 100644
+--- a/arch/arm/mach-omap2/twl-common.c
++++ b/arch/arm/mach-omap2/twl-common.c
+@@ -363,6 +363,7 @@ static struct regulator_init_data omap4_vusb_idata = {
+ static struct regulator_init_data omap4_clk32kg_idata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
++ .always_on = true,
+ },
+ };
+
diff --git a/patches/linux-3.7/0211-ti-st-st-kim-fixing-firmware-path.patch b/patches/linux-3.7/0211-ti-st-st-kim-fixing-firmware-path.patch
new file mode 100644
index 0000000..1100acd
--- /dev/null
+++ b/patches/linux-3.7/0211-ti-st-st-kim-fixing-firmware-path.patch
@@ -0,0 +1,32 @@
+From: Ricardo Salveti de Araujo <ricardo.salveti@linaro.org>
+Date: Tue, 25 Oct 2011 10:06:39 +0200
+Subject: [PATCH] ti-st/st-kim: fixing firmware path
+
+Signed-off-by: Ricardo Salveti de Araujo <ricardo.salveti@linaro.org>
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ drivers/misc/ti-st/st_kim.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
+index 04a8199..43ef2cb 100644
+--- a/drivers/misc/ti-st/st_kim.c
++++ b/drivers/misc/ti-st/st_kim.c
+@@ -244,7 +244,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
+ if (version & 0x8000)
+ maj_ver |= 0x0008;
+
+- sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
++ sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+
+ /* to be accessed later via sysfs entry */
+ kim_gdata->version.full = version;
+@@ -287,7 +287,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
+ long len = 0;
+ unsigned char *ptr = NULL;
+ unsigned char *action_ptr = NULL;
+- unsigned char bts_scr_name[30] = { 0 }; /* 30 char long bts scr name? */
++ unsigned char bts_scr_name[50] = { 0 }; /* 50 char long bts scr name? */
+ int wr_room_space;
+ int cmd_size;
+ unsigned long timeout;
diff --git a/patches/linux-3.7/0213-Revert-drm-kill-drm_sman.patch b/patches/linux-3.7/0213-Revert-drm-kill-drm_sman.patch
new file mode 100644
index 0000000..38aebd5
--- /dev/null
+++ b/patches/linux-3.7/0213-Revert-drm-kill-drm_sman.patch
@@ -0,0 +1,400 @@
+From: Robert Nelson <robertcnelson@gmail.com>
+Date: Thu, 3 May 2012 19:27:52 -0500
+Subject: [PATCH] Revert "drm: kill drm_sman"
+
+This reverts commit 7a6e0daaf4058d1b7dd515bc470ec904454a798c.
+---
+ drivers/gpu/drm/Makefile | 2 +-
+ drivers/gpu/drm/drm_sman.c | 211 ++++++++++++++++++++++++++++++++++++++++++++
+ include/drm/drm_sman.h | 151 +++++++++++++++++++++++++++++++
+ 3 files changed, 363 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/gpu/drm/drm_sman.c
+ create mode 100644 include/drm/drm_sman.h
+
+diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
+index 2ff5cef..2ed0fde 100644
+--- a/drivers/gpu/drm/Makefile
++++ b/drivers/gpu/drm/Makefile
+@@ -9,7 +9,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
+ drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
+ drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
+ drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
+- drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
++ drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
+ drm_crtc.o drm_modes.o drm_edid.o \
+ drm_info.o drm_debugfs.o drm_encoder_slave.o \
+ drm_trace_points.o drm_global.o drm_prime.o
+diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c
+new file mode 100644
+index 0000000..a8ff350
+--- /dev/null
++++ b/drivers/gpu/drm/drm_sman.c
+@@ -0,0 +1,211 @@
++/**************************************************************************
++ *
++ * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA.
++ * All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ *
++ **************************************************************************/
++/*
++ * Simple memory manager interface that keeps track on allocate regions on a
++ * per "owner" basis. All regions associated with an "owner" can be released
++ * with a simple call. Typically if the "owner" exists. The owner is any
++ * "unsigned long" identifier. Can typically be a pointer to a file private
++ * struct or a context identifier.
++ *
++ * Authors:
++ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
++ */
++
++#include <linux/export.h>
++#include "drm_sman.h"
++
++struct drm_owner_item {
++ struct drm_hash_item owner_hash;
++ struct list_head sman_list;
++ struct list_head mem_blocks;
++};
++
++void drm_sman_takedown(struct drm_sman * sman)
++{
++ kfree(sman->mm);
++}
++
++EXPORT_SYMBOL(drm_sman_takedown);
++
++int
++drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
++ unsigned int user_order, unsigned int owner_order)
++{
++ int ret = 0;
++
++ sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL);
++ if (!sman->mm) {
++ ret = -ENOMEM;
++ return ret;
++ }
++ sman->num_managers = num_managers;
++
++ return 0;
++}
++
++EXPORT_SYMBOL(drm_sman_init);
++
++static void *drm_sman_mm_allocate(void *private, unsigned long size,
++ unsigned alignment)
++{
++ struct drm_mm *mm = (struct drm_mm *) private;
++ struct drm_mm_node *tmp;
++
++ tmp = drm_mm_search_free(mm, size, alignment, 1);
++ if (!tmp) {
++ return NULL;
++ }
++ tmp = drm_mm_get_block(tmp, size, alignment);
++ return tmp;
++}
++
++static void drm_sman_mm_free(void *private, void *ref)
++{
++ struct drm_mm_node *node = (struct drm_mm_node *) ref;
++
++ drm_mm_put_block(node);
++}
++
++static void drm_sman_mm_destroy(void *private)
++{
++ struct drm_mm *mm = (struct drm_mm *) private;
++ drm_mm_takedown(mm);
++ kfree(mm);
++}
++
++static unsigned long drm_sman_mm_offset(void *private, void *ref)
++{
++ struct drm_mm_node *node = (struct drm_mm_node *) ref;
++ return node->start;
++}
++
++int
++drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
++ unsigned long start, unsigned long size)
++{
++ struct drm_sman_mm *sman_mm;
++ struct drm_mm *mm;
++ int ret;
++
++ BUG_ON(manager >= sman->num_managers);
++
++ sman_mm = &sman->mm[manager];
++ mm = kzalloc(sizeof(*mm), GFP_KERNEL);
++ if (!mm) {
++ return -ENOMEM;
++ }
++ sman_mm->private = mm;
++ ret = drm_mm_init(mm, start, size);
++
++ if (ret) {
++ kfree(mm);
++ return ret;
++ }
++
++ sman_mm->allocate = drm_sman_mm_allocate;
++ sman_mm->free = drm_sman_mm_free;
++ sman_mm->destroy = drm_sman_mm_destroy;
++ sman_mm->offset = drm_sman_mm_offset;
++
++ return 0;
++}
++
++EXPORT_SYMBOL(drm_sman_set_range);
++
++int
++drm_sman_set_manager(struct drm_sman * sman, unsigned int manager,
++ struct drm_sman_mm * allocator)
++{
++ BUG_ON(manager >= sman->num_managers);
++ sman->mm[manager] = *allocator;
++
++ return 0;
++}
++EXPORT_SYMBOL(drm_sman_set_manager);
++
++struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int manager,
++ unsigned long size, unsigned alignment,
++ unsigned long owner)
++{
++ void *tmp;
++ struct drm_sman_mm *sman_mm;
++ struct drm_memblock_item *memblock;
++
++ BUG_ON(manager >= sman->num_managers);
++
++ sman_mm = &sman->mm[manager];
++ tmp = sman_mm->allocate(sman_mm->private, size, alignment);
++
++ if (!tmp) {
++ return NULL;
++ }
++
++ memblock = kzalloc(sizeof(*memblock), GFP_KERNEL);
++
++ if (!memblock)
++ goto out;
++
++ memblock->mm_info = tmp;
++ memblock->mm = sman_mm;
++ memblock->sman = sman;
++
++ return memblock;
++
++out:
++ sman_mm->free(sman_mm->private, tmp);
++
++ return NULL;
++}
++
++EXPORT_SYMBOL(drm_sman_alloc);
++
++void drm_sman_free(struct drm_memblock_item *item)
++{
++ list_del(&item->owner_list);
++ item->mm->free(item->mm->private, item->mm_info);
++ kfree(item);
++}
++EXPORT_SYMBOL(drm_sman_free);
++
++void drm_sman_cleanup(struct drm_sman *sman)
++{
++ unsigned int i;
++ struct drm_sman_mm *sman_mm;
++
++ if (sman->mm) {
++ for (i = 0; i < sman->num_managers; ++i) {
++ sman_mm = &sman->mm[i];
++ if (sman_mm->private) {
++ sman_mm->destroy(sman_mm->private);
++ sman_mm->private = NULL;
++ }
++ }
++ }
++}
++
++EXPORT_SYMBOL(drm_sman_cleanup);
+diff --git a/include/drm/drm_sman.h b/include/drm/drm_sman.h
+new file mode 100644
+index 0000000..031e521
+--- /dev/null
++++ b/include/drm/drm_sman.h
+@@ -0,0 +1,151 @@
++/**************************************************************************
++ *
++ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
++ * All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
++ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
++ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
++ * USE OR OTHER DEALINGS IN THE SOFTWARE.
++ *
++ *
++ **************************************************************************/
++/*
++ * Simple memory MANager interface that keeps track on allocate regions on a
++ * per "owner" basis. All regions associated with an "owner" can be released
++ * with a simple call. Typically if the "owner" exists. The owner is any
++ * "unsigned long" identifier. Can typically be a pointer to a file private
++ * struct or a context identifier.
++ *
++ * Authors:
++ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
++ */
++
++#ifndef DRM_SMAN_H
++#define DRM_SMAN_H
++
++#include "drmP.h"
++#include "drm_hashtab.h"
++
++/*
++ * A class that is an abstration of a simple memory allocator.
++ * The sman implementation provides a default such allocator
++ * using the drm_mm.c implementation. But the user can replace it.
++ * See the SiS implementation, which may use the SiS FB kernel module
++ * for memory management.
++ */
++
++struct drm_sman_mm {
++ /* private info. If allocated, needs to be destroyed by the destroy
++ function */
++ void *private;
++
++ /* Allocate a memory block with given size and alignment.
++ Return an opaque reference to the memory block */
++
++ void *(*allocate) (void *private, unsigned long size,
++ unsigned alignment);
++
++ /* Free a memory block. "ref" is the opaque reference that we got from
++ the "alloc" function */
++
++ void (*free) (void *private, void *ref);
++
++ /* Free all resources associated with this allocator */
++
++ void (*destroy) (void *private);
++
++ /* Return a memory offset from the opaque reference returned from the
++ "alloc" function */
++
++ unsigned long (*offset) (void *private, void *ref);
++};
++
++struct drm_memblock_item {
++ struct list_head owner_list;
++ struct drm_hash_item user_hash;
++ void *mm_info;
++ struct drm_sman_mm *mm;
++ struct drm_sman *sman;
++};
++
++struct drm_sman {
++ struct drm_sman_mm *mm;
++ int num_managers;
++};
++
++/*
++ * Take down a memory manager. This function should only be called after a
++ * successful init and after a call to drm_sman_cleanup.
++ */
++
++extern void drm_sman_takedown(struct drm_sman * sman);
++
++/*
++ * Allocate structures for a manager.
++ * num_managers are the number of memory pools to manage. (VRAM, AGP, ....)
++ * user_order is the log2 of the number of buckets in the user hash table.
++ * set this to approximately log2 of the max number of memory regions
++ * that will be allocated for _all_ pools together.
++ * owner_order is the log2 of the number of buckets in the owner hash table.
++ * set this to approximately log2 of
++ * the number of client file connections that will
++ * be using the manager.
++ *
++ */
++
++extern int drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
++ unsigned int user_order, unsigned int owner_order);
++
++/*
++ * Initialize a drm_mm.c allocator. Should be called only once for each
++ * manager unless a customized allogator is used.
++ */
++
++extern int drm_sman_set_range(struct drm_sman * sman, unsigned int manager,
++ unsigned long start, unsigned long size);
++
++/*
++ * Initialize a customized allocator for one of the managers.
++ * (See the SiS module). The object pointed to by "allocator" is copied,
++ * so it can be destroyed after this call.
++ */
++
++extern int drm_sman_set_manager(struct drm_sman * sman, unsigned int mananger,
++ struct drm_sman_mm * allocator);
++
++/*
++ * Allocate a memory block. Aligment is not implemented yet.
++ */
++
++extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman,
++ unsigned int manager,
++ unsigned long size,
++ unsigned alignment,
++ unsigned long owner);
++
++extern void drm_sman_free(struct drm_memblock_item *item);
++
++/*
++ * Frees all stale memory blocks associated with the memory manager.
++ * See idling above.
++ */
++
++extern void drm_sman_cleanup(struct drm_sman * sman);
++
++#endif
diff --git a/patches/linux-3.7/0215-omap3-Increase-limit-on-bootarg-mpurate.patch b/patches/linux-3.7/0215-omap3-Increase-limit-on-bootarg-mpurate.patch
new file mode 100644
index 0000000..8f3d0cf
--- /dev/null
+++ b/patches/linux-3.7/0215-omap3-Increase-limit-on-bootarg-mpurate.patch
@@ -0,0 +1,29 @@
+From: Sanjeev Premi <premi@ti.com>
+Date: Thu, 29 Apr 2010 14:09:42 +0530
+Subject: [PATCH] omap3: Increase limit on bootarg 'mpurate'
+
+The value of mpurate is currently expected to be less
+than 1000 when specified in MHz.
+
+This patch raises this limit to 2000 to support 1GHz
+capable processors. The new limit should be reasonable
+for quite some time.
+
+Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
+---
+ arch/arm/plat-omap/clock.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index 9d7ac20..20b2de8 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -185,7 +185,7 @@ static int __init omap_clk_setup(char *str)
+ if (!mpurate)
+ return 1;
+
+- if (mpurate < 1000)
++ if (mpurate < 2000)
+ mpurate *= 1000000;
+
+ return 1;
diff --git a/patches/linux-3.7/0217-staging-omap-thermal-fix-compilation.patch b/patches/linux-3.7/0217-staging-omap-thermal-fix-compilation.patch
new file mode 100644
index 0000000..a4bdf2e
--- /dev/null
+++ b/patches/linux-3.7/0217-staging-omap-thermal-fix-compilation.patch
@@ -0,0 +1,24 @@
+From: Eduardo Valentin <eduardo.valentin@ti.com>
+Date: Tue, 13 Nov 2012 14:10:00 -0400
+Subject: [PATCH] staging: omap-thermal: fix compilation
+
+Because we are not including linux/io.h, the driver is not compiling.
+This patch adds the missing header.
+
+Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
+---
+ drivers/staging/omap-thermal/omap-bandgap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
+index 368a2e1..1cae5ed 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.c
++++ b/drivers/staging/omap-thermal/omap-bandgap.c
+@@ -38,6 +38,7 @@
+ #include <linux/of_device.h>
+ #include <linux/of_platform.h>
+ #include <linux/of_irq.h>
++#include <linux/io.h>
+
+ #include "omap-bandgap.h"
+
diff --git a/patches/linux-3.7/0218-staging-omap-thermal-remove-platform-data-nomenclatu.patch b/patches/linux-3.7/0218-staging-omap-thermal-remove-platform-data-nomenclatu.patch
new file mode 100644
index 0000000..ffcab5f
--- /dev/null
+++ b/patches/linux-3.7/0218-staging-omap-thermal-remove-platform-data-nomenclatu.patch
@@ -0,0 +1,40 @@
+From: Eduardo Valentin <eduardo.valentin@ti.com>
+Date: Tue, 13 Nov 2012 14:10:01 -0400
+Subject: [PATCH] staging: omap-thermal: remove platform data nomenclature
+
+Because the driver is not really using platform data, this patch
+removes the pdata nomenclature from this driver.
+
+Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
+---
+ drivers/staging/omap-thermal/omap-thermal-common.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
+index 5c0c203b..5be66d7 100644
+--- a/drivers/staging/omap-thermal/omap-thermal-common.c
++++ b/drivers/staging/omap-thermal/omap-thermal-common.c
+@@ -256,12 +256,12 @@ static struct omap_thermal_data
+ int omap_thermal_expose_sensor(struct omap_bandgap *bg_ptr, int id,
+ char *domain)
+ {
+- struct omap_thermal_pdata pdata;
++ struct omap_thermal_data *data;
+
+ data = omap_bandgap_get_sensor_data(bg_ptr, id);
+
+ if (!data)
+- data = omap_thermal_build_pdata(bg_ptr, id);
++ data = omap_thermal_build_data(bg_ptr, id);
+
+ if (!data)
+ return -EINVAL;
+@@ -359,7 +359,7 @@ int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
+
+ data = omap_bandgap_get_sensor_data(bg_ptr, id);
+ if (!data)
+- data = omap_thermal_build_pdata(bg_ptr, id);
++ data = omap_thermal_build_data(bg_ptr, id);
+
+ if (!data)
+ return -EINVAL;
diff --git a/patches/linux-3.7/0219-staging-omap-thermal-remove-freq_clip-table.patch b/patches/linux-3.7/0219-staging-omap-thermal-remove-freq_clip-table.patch
new file mode 100644
index 0000000..7b52eb8
--- /dev/null
+++ b/patches/linux-3.7/0219-staging-omap-thermal-remove-freq_clip-table.patch
@@ -0,0 +1,156 @@
+From: Eduardo Valentin <eduardo.valentin@ti.com>
+Date: Tue, 13 Nov 2012 14:10:02 -0400
+Subject: [PATCH] staging: omap-thermal: remove freq_clip table
+
+The API exposed by cpu cooling does not need any freq clip
+table anymore. Now the cpu cooling device is smart enough
+to build its own table.
+
+For this reason, this patch removes all the code that is
+generating a freq clip table and also removes all references
+in data structures regarding freq clip table.
+
+Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
+---
+ drivers/staging/omap-thermal/omap-bandgap.h | 9 ---
+ drivers/staging/omap-thermal/omap-thermal-common.c | 63 +-------------------
+ 2 files changed, 3 insertions(+), 69 deletions(-)
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.h b/drivers/staging/omap-thermal/omap-bandgap.h
+index 78aed75..2bb14bd 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.h
++++ b/drivers/staging/omap-thermal/omap-bandgap.h
+@@ -336,14 +336,6 @@ struct temp_sensor_regval {
+ };
+
+ /**
+- * struct thermal_cooling_conf - description on how to cool a thermal zone
+- * @freq_clip_count: size of freq_data
+- */
+-struct thermal_cooling_conf {
+- int freq_clip_count;
+-};
+-
+-/**
+ * struct omap_temp_sensor - bandgap temperature sensor platform data
+ * @ts_data: pointer to struct with thresholds, limits of temperature sensor
+ * @registers: pointer to the list of register offsets and bitfields
+@@ -365,7 +357,6 @@ struct omap_temp_sensor {
+ struct temp_sensor_registers *registers;
+ struct temp_sensor_regval regval;
+ char *domain;
+- struct thermal_cooling_conf cooling_data;
+ /* for hotspot extrapolation */
+ const int slope;
+ const int constant;
+diff --git a/drivers/staging/omap-thermal/omap-thermal-common.c b/drivers/staging/omap-thermal/omap-thermal-common.c
+index 5be66d7..15e9723 100644
+--- a/drivers/staging/omap-thermal/omap-thermal-common.c
++++ b/drivers/staging/omap-thermal/omap-thermal-common.c
+@@ -29,6 +29,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/thermal.h>
+ #include <linux/cpufreq.h>
++#include <linux/cpumask.h>
+ #include <linux/cpu_cooling.h>
+
+ #include "omap-thermal.h"
+@@ -112,7 +113,7 @@ static int omap_thermal_bind(struct thermal_zone_device *thermal,
+ struct thermal_cooling_device *cdev)
+ {
+ struct omap_thermal_data *data = thermal->devdata;
+- int max, id;
++ int id;
+
+ if (IS_ERR_OR_NULL(data))
+ return -ENODEV;
+@@ -122,7 +123,6 @@ static int omap_thermal_bind(struct thermal_zone_device *thermal,
+ return 0;
+
+ id = data->sensor_id;
+- max = data->bg_ptr->conf->sensors[id].cooling_data.freq_clip_count;
+
+ /* TODO: bind with min and max states */
+ /* Simple thing, two trips, one passive another critical */
+@@ -304,58 +304,9 @@ int omap_thermal_report_sensor_temperature(struct omap_bandgap *bg_ptr, int id)
+ return 0;
+ }
+
+-static int omap_thermal_build_cpufreq_clip(struct omap_bandgap *bg_ptr,
+- struct freq_clip_table **tab_ptr,
+- int *tab_size)
+-{
+- struct cpufreq_frequency_table *freq_table;
+- struct freq_clip_table *tab;
+- int i, count = 0;
+-
+- freq_table = cpufreq_frequency_get_table(0);
+- if (IS_ERR_OR_NULL(freq_table)) {
+- dev_err(bg_ptr->dev,
+- "%s: failed to get cpufreq table (%p)\n",
+- __func__, freq_table);
+- return -EINVAL;
+- }
+-
+- for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- unsigned int freq = freq_table[i].frequency;
+- if (freq == CPUFREQ_ENTRY_INVALID)
+- continue;
+- count++;
+- }
+-
+- tab = devm_kzalloc(bg_ptr->dev, sizeof(*tab) * count, GFP_KERNEL);
+- if (!tab) {
+- dev_err(bg_ptr->dev,
+- "%s: no memory available\n", __func__);
+- return -ENOMEM;
+- }
+-
+- for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- unsigned int freq = freq_table[i].frequency;
+-
+- if (freq == CPUFREQ_ENTRY_INVALID)
+- continue;
+-
+- tab[count - i - 1].freq_clip_max = freq;
+- tab[count - i - 1].temp_level = OMAP_TRIP_HOT;
+- tab[count - i - 1].mask_val = cpumask_of(0);
+- }
+-
+- *tab_ptr = tab;
+- *tab_size = count;
+-
+- return 0;
+-}
+-
+ int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
+ {
+ struct omap_thermal_data *data;
+- struct freq_clip_table *tab_ptr;
+- int tab_size, ret;
+
+ data = omap_bandgap_get_sensor_data(bg_ptr, id);
+ if (!data)
+@@ -364,21 +315,13 @@ int omap_thermal_register_cpu_cooling(struct omap_bandgap *bg_ptr, int id)
+ if (!data)
+ return -EINVAL;
+
+- ret = omap_thermal_build_cpufreq_clip(bg_ptr, &tab_ptr, &tab_size);
+- if (ret < 0) {
+- dev_err(bg_ptr->dev,
+- "%s: failed to build cpufreq clip table\n", __func__);
+- return ret;
+- }
+-
+ /* Register cooling device */
+- data->cool_dev = cpufreq_cooling_register(tab_ptr, tab_size);
++ data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
+ if (IS_ERR_OR_NULL(data->cool_dev)) {
+ dev_err(bg_ptr->dev,
+ "Failed to register cpufreq cooling device\n");
+ return PTR_ERR(data->cool_dev);
+ }
+- bg_ptr->conf->sensors[id].cooling_data.freq_clip_count = tab_size;
+ omap_bandgap_set_sensor_data(bg_ptr, id, data);
+
+ return 0;
diff --git a/patches/linux-3.7/0220-staging-omap-thermal-add-IRQ-debugging-messaging.patch b/patches/linux-3.7/0220-staging-omap-thermal-add-IRQ-debugging-messaging.patch
new file mode 100644
index 0000000..ee44bfb
--- /dev/null
+++ b/patches/linux-3.7/0220-staging-omap-thermal-add-IRQ-debugging-messaging.patch
@@ -0,0 +1,28 @@
+From: Eduardo Valentin <eduardo.valentin@ti.com>
+Date: Tue, 13 Nov 2012 14:10:03 -0400
+Subject: [PATCH] staging: omap-thermal: add IRQ debugging messaging
+
+For debugging purposes, print the IRQ event for the domain being processed.
+
+Signed-off-by: Enric Balletbo i Serra <eballetbo@gmail.com>
+Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
+---
+ drivers/staging/omap-thermal/omap-bandgap.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
+index 1cae5ed..3eb726f 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.c
++++ b/drivers/staging/omap-thermal/omap-bandgap.c
+@@ -113,6 +113,11 @@ static irqreturn_t talert_irq_handler(int irq, void *data)
+
+ omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
+
++ dev_dbg(bg_ptr->dev,
++ "%s: IRQ from %s sensor: hotevent %d coldevent %d\n",
++ __func__, bg_ptr->conf->sensors[i].domain,
++ t_hot, t_cold);
++
+ /* read temperature */
+ temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
+ temp &= tsr->bgap_dtemp_mask;
diff --git a/patches/linux-3.7/0221-staging-omap-thermal-fix-context-restore-function.patch b/patches/linux-3.7/0221-staging-omap-thermal-fix-context-restore-function.patch
new file mode 100644
index 0000000..08eb5c8
--- /dev/null
+++ b/patches/linux-3.7/0221-staging-omap-thermal-fix-context-restore-function.patch
@@ -0,0 +1,93 @@
+From: Radhesh Fadnis <radhesh.fadnis@ti.com>
+Date: Tue, 13 Nov 2012 14:10:04 -0400
+Subject: [PATCH] staging: omap-thermal: fix context restore function
+
+In the context restore function, if the context is lost or
+not is being checked by the contents of the counter register.
+But this is logic hold good as long as counter reset value is
+zero, if the reset value is non-zero then above logic doesn't
+hold good. Hence removed checking of the register value and
+restoring the context.
+
+Signed-off-by: Radhesh Fadnis <radhesh.fadnis@ti.com>
+Signed-off-by: Enric Balletbo i Serra <eballetbo@gmail.com>
+Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
+---
+ drivers/staging/omap-thermal/omap-bandgap.c | 57 ++++++++++-----------------
+ 1 file changed, 21 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/staging/omap-thermal/omap-bandgap.c b/drivers/staging/omap-thermal/omap-bandgap.c
+index 3eb726f..c17bc95 100644
+--- a/drivers/staging/omap-thermal/omap-bandgap.c
++++ b/drivers/staging/omap-thermal/omap-bandgap.c
+@@ -1065,7 +1065,6 @@ static int omap_bandgap_save_ctxt(struct omap_bandgap *bg_ptr)
+ static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+ {
+ int i;
+- u32 temp = 0;
+
+ for (i = 0; i < bg_ptr->conf->sensor_count; i++) {
+ struct temp_sensor_registers *tsr;
+@@ -1078,41 +1077,27 @@ static int omap_bandgap_restore_ctxt(struct omap_bandgap *bg_ptr)
+ if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
+ val = omap_bandgap_readl(bg_ptr, tsr->bgap_counter);
+
+- if (val == 0) {
+- if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
+- omap_bandgap_writel(bg_ptr,
+- rval->tshut_threshold,
+- tsr->tshut_threshold);
+- /* Force immediate temperature measurement and update
+- * of the DTEMP field
+- */
+- omap_bandgap_force_single_read(bg_ptr, i);
+-
+- if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
+- omap_bandgap_writel(bg_ptr, rval->bg_counter,
+- tsr->bgap_counter);
+- if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
+- omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
+- tsr->bgap_mode_ctrl);
+- if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
+- omap_bandgap_writel(bg_ptr,
+- rval->bg_threshold,
+- tsr->bgap_threshold);
+- omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
+- tsr->bgap_mask_ctrl);
+- }
+- } else {
+- temp = omap_bandgap_readl(bg_ptr,
+- tsr->temp_sensor_ctrl);
+- temp &= (tsr->bgap_dtemp_mask);
+- omap_bandgap_force_single_read(bg_ptr, i);
+- if (temp == 0 && OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
+- temp = omap_bandgap_readl(bg_ptr,
+- tsr->bgap_mask_ctrl);
+- temp |= 1 << __ffs(tsr->mode_ctrl_mask);
+- omap_bandgap_writel(bg_ptr, temp,
+- tsr->bgap_mask_ctrl);
+- }
++ if (OMAP_BANDGAP_HAS(bg_ptr, TSHUT_CONFIG))
++ omap_bandgap_writel(bg_ptr,
++ rval->tshut_threshold,
++ tsr->tshut_threshold);
++ /* Force immediate temperature measurement and update
++ * of the DTEMP field
++ */
++ omap_bandgap_force_single_read(bg_ptr, i);
++
++ if (OMAP_BANDGAP_HAS(bg_ptr, COUNTER))
++ omap_bandgap_writel(bg_ptr, rval->bg_counter,
++ tsr->bgap_counter);
++ if (OMAP_BANDGAP_HAS(bg_ptr, MODE_CONFIG))
++ omap_bandgap_writel(bg_ptr, rval->bg_mode_ctrl,
++ tsr->bgap_mode_ctrl);
++ if (OMAP_BANDGAP_HAS(bg_ptr, TALERT)) {
++ omap_bandgap_writel(bg_ptr,
++ rval->bg_threshold,
++ tsr->bgap_threshold);
++ omap_bandgap_writel(bg_ptr, rval->bg_ctrl,
++ tsr->bgap_mask_ctrl);
+ }
+ }
+
diff --git a/patches/linux-3.7/0223-Attempted-SMC911x-BQL-patch.patch b/patches/linux-3.7/0223-Attempted-SMC911x-BQL-patch.patch
new file mode 100644
index 0000000..74b2a84
--- /dev/null
+++ b/patches/linux-3.7/0223-Attempted-SMC911x-BQL-patch.patch
@@ -0,0 +1,56 @@
+From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Date: Thu, 29 Nov 2012 11:17:05 +0100
+Subject: [PATCH] Attempted SMC911x BQL patch
+
+First attempt at BQL on smsc911x.
+
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+---
+ drivers/net/ethernet/smsc/smsc911x.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
+index c53c0f4..f5bedac 100644
+--- a/drivers/net/ethernet/smsc/smsc911x.c
++++ b/drivers/net/ethernet/smsc/smsc911x.c
+@@ -1107,6 +1107,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ {
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int tx_stat;
++ unsigned int bytes_compl = 0, pkts_compl = 0;
+
+ while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
+ if (unlikely(tx_stat & 0x80000000)) {
+@@ -1124,6 +1125,8 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += (tx_stat >> 16);
++ pkts_compl++;
++ bytes_compl += (tx_stat >> 16);
+ }
+ if (unlikely(tx_stat & TX_STS_EXCESS_COL_)) {
+ dev->stats.collisions += 16;
+@@ -1140,6 +1143,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
+ }
+ }
+ }
++ netdev_completed_queue(dev, pkts_compl, bytes_compl);
+ }
+
+ /* Increments the Rx error counters */
+@@ -1607,6 +1611,7 @@ static int smsc911x_stop(struct net_device *dev)
+ /* At this point all Rx and Tx activity is stopped */
+ dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+ smsc911x_tx_update_txcounters(dev);
++ netdev_reset_queue(dev);
+
+ /* Bring the PHY down */
+ if (pdata->phy_dev)
+@@ -1650,6 +1655,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ wrsz >>= 2;
+
+ pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
++ netdev_sent_queue(dev, skb->len);
+ freespace -= (skb->len + 32);
+ skb_tx_timestamp(skb);
+ dev_kfree_skb(skb);
diff --git a/patches/linux-3.7/0225-spi-spidev-Add-device-tree-bindings.patch b/patches/linux-3.7/0225-spi-spidev-Add-device-tree-bindings.patch
new file mode 100644
index 0000000..aceab2a
--- /dev/null
+++ b/patches/linux-3.7/0225-spi-spidev-Add-device-tree-bindings.patch
@@ -0,0 +1,43 @@
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Fri, 28 Sep 2012 12:50:15 +0000
+Subject: [PATCH] spi: spidev: Add device tree bindings
+
+This will allow to probe spidev from device tree
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+---
+ drivers/spi/spidev.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
+index 830adbe..8ae0660 100644
+--- a/drivers/spi/spidev.c
++++ b/drivers/spi/spidev.c
+@@ -31,6 +31,8 @@
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
+ #include <linux/compat.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
+
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spidev.h>
+@@ -642,10 +644,18 @@ static int __devexit spidev_remove(struct spi_device *spi)
+ return 0;
+ }
+
++static const struct of_device_id spidev_dt_ids[] = {
++ { .compatible = "linux,spidev" },
++ {},
++};
++
++MODULE_DEVICE_TABLE(of, spidev_dt_ids);
++
+ static struct spi_driver spidev_spi_driver = {
+ .driver = {
+ .name = "spidev",
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(spidev_dt_ids),
+ },
+ .probe = spidev_probe,
+ .remove = __devexit_p(spidev_remove),
diff --git a/patches/linux-3.7/0301-Release-distrokit-beaglebone-20121218.patch b/patches/linux-3.7/0301-Release-distrokit-beaglebone-20121218.patch
new file mode 100644
index 0000000..472f2b2
--- /dev/null
+++ b/patches/linux-3.7/0301-Release-distrokit-beaglebone-20121218.patch
@@ -0,0 +1,22 @@
+From: Jan Luebbe <jlu@pengutronix.de>
+Date: Tue, 18 Dec 2012 14:55:28 +0100
+Subject: [PATCH] Release distrokit/beaglebone/20121218
+
+Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 540f7b2..5fb3b62 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ VERSION = 3
+ PATCHLEVEL = 7
+ SUBLEVEL = 0
+-EXTRAVERSION =
++EXTRAVERSION =-20121218
+ NAME = Terrified Chipmunk
+
+ # *DOCUMENTATION*
diff --git a/patches/linux-3.7/series b/patches/linux-3.7/series
new file mode 100644
index 0000000..b189567
--- /dev/null
+++ b/patches/linux-3.7/series
@@ -0,0 +1,209 @@
+# umpf-base: v3.7
+# umpf-name: distrokit/beaglebone
+# umpf-version: distrokit/beaglebone/20121218
+# umpf-topic: topic/distrokit/beaglebone/board
+# umpf-hashinfo: 1008c9cfa5d53ee128edacdc6608aafb4946f4be
+# umpf-topic-range: 29594404d7fe73cd80eaa4ee8c43dcc53970c60e..1008c9cfa5d53ee128edacdc6608aafb4946f4be
+0001-video-st7735fb-add-st7735-framebuffer-driver.patch
+0002-regulator-tps65910-fix-BUG_ON-shown-with-vrtc-regula.patch
+0003-dmaengine-add-helper-function-to-request-a-slave-DMA.patch
+0004-of-Add-generic-device-tree-DMA-helpers.patch
+0005-of-dma-fix-build-break-for-CONFIG_OF.patch
+0006-of-dma-fix-typos-in-generic-dma-binding-definition.patch
+0007-dmaengine-fix-build-failure-due-to-missing-semi-colo.patch
+0008-dmaengine-edma-fix-slave-config-dependency-on-direct.patch
+0009-ARM-davinci-move-private-EDMA-API-to-arm-common.patch
+0010-ARM-edma-remove-unused-transfer-controller-handlers.patch
+0011-ARM-edma-add-DT-and-runtime-PM-support-for-AM33XX.patch
+0012-ARM-edma-add-AM33XX-crossbar-event-support.patch
+0013-dmaengine-edma-enable-build-for-AM33XX.patch
+0014-dmaengine-edma-Add-TI-EDMA-device-tree-binding.patch
+0015-ARM-dts-add-AM33XX-EDMA-support.patch
+0016-dmaengine-add-dma_request_slave_channel_compat.patch
+0017-mmc-omap_hsmmc-convert-to-dma_request_slave_channel_.patch
+0018-mmc-omap_hsmmc-limit-max_segs-with-the-EDMA-DMAC.patch
+0019-mmc-omap_hsmmc-add-generic-DMA-request-support-to-th.patch
+0020-ARM-dts-add-AM33XX-MMC-support.patch
+0021-spi-omap2-mcspi-convert-to-dma_request_slave_channel.patch
+0022-spi-omap2-mcspi-add-generic-DMA-request-support-to-t.patch
+0023-ARM-dts-add-AM33XX-SPI-support.patch
+0024-Documentation-bindings-add-spansion.patch
+0025-ARM-dts-add-BeagleBone-Adafruit-1.8-LCD-support.patch
+0026-misc-add-gpevt-driver.patch
+0027-ARM-dts-add-BeagleBone-gpevt-support.patch
+0028-ARM-configs-working-AM33XX-edma-dmaengine-defconfig.patch
+0029-ARM-configs-working-da850-edma-dmaengine-defconfig.patch
+0030-misc-gpevt-null-terminate-the-of_match_table.patch
+0031-proposed-probe-fix-works-for-me-on-evm.patch
+0033-ARM-OMAP3-hwmod-Add-AM33XX-HWMOD-data-for-davinci_md.patch
+0034-net-davinci_mdio-Fix-type-mistake-in-calling-runtime.patch
+0035-net-cpsw-Add-parent-child-relation-support-between-c.patch
+0036-arm-dts-am33xx-Add-cpsw-and-mdio-module-nodes-for-AM.patch
+0038-i2c-pinctrl-ify-i2c-omap.c.patch
+0039-arm-dts-AM33XX-Configure-pinmuxs-for-user-leds-contr.patch
+0040-beaglebone-DT-set-default-triggers-for-LEDS.patch
+0041-beaglebone-add-a-cpu-led-trigger.patch
+0043-arm-dts-AM33XX-Add-device-tree-OPP-table.patch
+0044-am33xx-DT-add-commented-out-OPP-values-for-ES2.0.patch
+0046-input-TSC-ti_tscadc-Correct-register-usage.patch
+0047-input-TSC-ti_tscadc-Add-Step-configuration-as-platfo.patch
+0048-input-TSC-ti_tscadc-set-FIFO0-threshold-Interrupt.patch
+0049-input-TSC-ti_tscadc-Remove-definition-of-End-Of-Inte.patch
+0050-input-TSC-ti_tscadc-Rename-the-existing-touchscreen-.patch
+0051-MFD-ti_tscadc-Add-support-for-TI-s-TSC-ADC-MFDevice.patch
+0052-input-TSC-ti_tsc-Convert-TSC-into-a-MFDevice.patch
+0053-IIO-ADC-tiadc-Add-support-of-TI-s-ADC-driver.patch
+0054-input-ti_am335x_tsc-Make-steps-enable-configurable.patch
+0055-input-ti_am335x_tsc-Order-of-TSC-wires-connect-made-.patch
+0056-input-ti_am335x_tsc-Add-variance-filters.patch
+0057-ti_tscadc-Update-with-IIO-map-interface-deal-with-pa.patch
+0058-ti_tscadc-Match-mfd-sub-devices-to-regmap-interface.patch
+0060-ARM-OMAP3-hwmod-Corrects-resource-data-for-PWM-devic.patch
+0061-pwm_backlight-Add-device-tree-support-for-Low-Thresh.patch
+0062-pwm-pwm-tiecap-Add-device-tree-binding-support-in-AP.patch
+0063-Control-module-EHRPWM-clk-enabling.patch
+0064-pwm-pwm-tiecap-Enable-clock-gating.patch
+0065-PWM-ti-ehrpwm-fix-up-merge-conflict.patch
+0066-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch
+0067-arm-dts-DT-support-for-EHRPWM-and-ECAP-device.patch
+0068-pwm-pwm-tiehrpwm-Add-device-tree-binding-support-EHR.patch
+0069-ARM-OMAP2-PWM-limit-am33xx_register_ehrpwm-to-soc_is.patch
+0071-pinctrl-pinctrl-single-must-be-initialized-early.patch
+0072-Bone-DTS-working-i2c2-i2c3-in-the-tree.patch
+0073-am33xx-Convert-I2C-from-omap-to-am33xx-names.patch
+0074-beaglebone-fix-backlight-entry-in-DT.patch
+0076-Shut-up-musb.patch
+0077-musb-Fix-crashes-and-other-weirdness.patch
+0078-musb-revert-parts-of-032ec49f.patch
+0079-usb-musb-dsps-get-the-PHY-using-phandle-api.patch
+0080-drivers-usb-otg-add-device-tree-support-to-otg-libra.patch
+0081-usb-otg-nop-add-dt-support.patch
+0082-usb-musb-dsps-add-phy-control-logic-to-glue.patch
+0083-usb-musb-dsps-enable-phy-control-for-am335x.patch
+0084-ARM-am33xx-fix-mem-regions-in-USB-hwmod.patch
+0086-omap2-clk-Add-missing-lcdc-clock-definition.patch
+0087-da8xx-Allow-use-by-am33xx-based-devices.patch
+0088-da8xx-Fix-revision-check-on-the-da8xx-driver.patch
+0089-da8xx-De-constify-members-in-the-platform-config.patch
+0090-da8xx-Add-standard-panel-definition.patch
+0091-da8xx-Add-CDTech_S035Q01-panel-used-by-LCD3-bone-cap.patch
+0092-da8xx-fb-add-panel-definition-for-beaglebone-LCD7-ca.patch
+0094-mmc-omap_hsmmc-Enable-HSPE-bit-for-high-speed-cards.patch
+0095-am33xx.dtsi-enable-MMC-HSPE-bit-for-all-3-controller.patch
+0096-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch
+0098-ARM-AM33XX-hwmod-Remove-wrong-INIT_NO_RESET-IDLE-fla.patch
+0100-f2fs-add-document.patch
+0101-f2fs-add-on-disk-layout.patch
+0102-f2fs-add-superblock-and-major-in-memory-structure.patch
+0103-f2fs-add-super-block-operations.patch
+0104-f2fs-add-checkpoint-operations.patch
+0105-f2fs-add-node-operations.patch
+0106-f2fs-add-segment-operations.patch
+0107-f2fs-add-file-operations.patch
+0108-f2fs-add-address-space-operations-for-data.patch
+0109-f2fs-add-core-inode-operations.patch
+0110-f2fs-add-inode-operations-for-special-inodes.patch
+0111-f2fs-add-core-directory-operations.patch
+0112-f2fs-add-xattr-and-acl-functionalities.patch
+0113-f2fs-add-garbage-collection-functions.patch
+0114-f2fs-add-recovery-routines-for-roll-forward.patch
+0115-f2fs-update-Kconfig-and-Makefile.patch
+0116-f2fs-gc.h-make-should_do_checkpoint-inline.patch
+0117-f2fs-move-statistics-code-into-one-file.patch
+0118-f2fs-move-proc-files-to-debugfs.patch
+0119-f2fs-compile-fix.patch
+0121-6lowpan-lowpan_is_iid_16_bit_compressable-does-not-d.patch
+0122-6lowpan-next-header-is-not-properly-set-upon-decompr.patch
+0123-6lowpan-always-enable-link-layer-acknowledgments.patch
+0124-mac802154-turn-on-ACK-when-enabled-by-the-upper-laye.patch
+0125-6lowpan-use-short-IEEE-802.15.4-addresses-for-broadc.patch
+0126-6lowpan-fix-first-fragment-FRAG1-handling.patch
+0127-6lowpan-store-fragment-tag-values-per-device-instead.patch
+0128-6lowpan-obtain-IEEE802.15.4-sequence-number-from-the.patch
+0129-6lowpan-add-a-new-parameter-in-sysfs-to-turn-on-off-.patch
+0130-6lowpan-use-the-PANID-provided-by-the-device-instead.patch
+0131-6lowpan-modify-udp-compression-uncompression-to-matc.patch
+0132-6lowpan-make-memory-allocation-atomic-during-6lowpan.patch
+0133-mac802154-make-mem-alloc-ATOMIC-to-prevent-schedulin.patch
+0134-mac802154-remove-unnecessary-spinlocks.patch
+0135-mac802154-re-introduce-MAC-primitives-required-to-se.patch
+0136-serial-initial-import-of-the-IEEE-802.15.4-serial-dr.patch
+0138-i2c-EEPROM-Export-memory-accessor.patch
+0139-omap-Export-omap_hwmod_lookup-omap_device_build-omap.patch
+0140-gpio-keys-Pinctrl-fy.patch
+0141-tps65217-Allow-placement-elsewhere-than-parent-mfd-d.patch
+0142-pwm-export-of_pwm_request.patch
+0143-i2c-Export-capability-to-probe-devices.patch
+0144-pwm-backlight-Pinctrl-fy.patch
+0145-spi-Export-OF-interfaces-for-capebus-use.patch
+0146-w1-gpio-Pinctrl-fy.patch
+0147-w1-gpio-Simplify-get-rid-of-defines.patch
+0148-arm-dt-Enable-DT-proc-updates.patch
+0149-ARM-CUSTOM-Build-a-uImage-with-dtb-already-appended.patch
+0150-beaglebone-create-a-shared-dtsi-for-beaglebone-based.patch
+0151-beaglebone-enable-emmc-for-bonelt.patch
+0152-da8xx-dt-Create-da8xx-DT-adapter-device.patch
+0153-ti-tscadc-dt-Create-ti-tscadc-dt-DT-adapter-device.patch
+0154-capebus-Core-capebus-support.patch
+0155-capebus-Add-beaglebone-board-support.patch
+0156-capebus-Beaglebone-generic-cape-support.patch
+0157-capebus-Beaglebone-geiger-cape-support.patch
+0158-capebus-Beaglebone-capebus-DT-update.patch
+0159-capebus-Document-DT-bindings.patch
+0160-capebus-Documentation-capebus-summary.patch
+0161-beaglebone-Update-default-config-for-capebus.patch
+0162-capebus-Geiger-Cape-config-bugfixs.patch
+0163-am335x-bone-Add-spi0-pins-defines.patch
+0164-Allow-more-than-one-instance-of-generic-devices.patch
+0165-Mark-the-device-as-PRIVATE.patch
+0166-DT-overlay.patch
+0167-Bug-fixes-pinctl-gpio-reset.patch
+0168-ARM-HSMMC-fix-error-path-when-no-gpio_reset.patch
+0169-capebus-Add-PRUSS-DT-bindings.patch
+0171-Import-working-HDMI-driver-from-3.2-kernel.patch
+0172-Added-DT-binding-to-NXP-driver.patch
+0173-da8xx-fb-Add-timings-for-720x480-60.patch
+0174-Add-capebus-override-and-pinmux-for-da8xx-dt.patch
+0175-video-Kconfig-Makefile-Add-new-Kconfig-for-old-drive.patch
+0176-am335x-bonelt-dts-Add-DT-node-to-probe-NXP-driver.patch
+0177-tda-driver-enable-1280x720.patch
+0178-Makefile-Disable-CEC.patch
+0180-uio-uio_pruss-port-to-AM33xx.patch
+0181-ARM-omap-add-DT-support-for-deasserting-hardware-res.patch
+0182-ARM-dts-AM33xx-PRUSS-support.patch
+0184-kbuild-deb-pkg-set-host-machine-after-dpkg-gencontro.patch
+0185-arm-add-definition-of-strstr-to-decompress.c.patch
+0187-mach-omap2-board-igep0020.c-Fix-reboot-problem.patch
+0188-regulator-core-if-voltage-scaling-fails-restore-orig.patch
+0190-OMAP-DSS2-add-bootarg-for-selecting-svideo.patch
+0191-video-add-timings-for-hd720.patch
+0193-Beagle-expansion-add-buddy-param-for-expansionboard-.patch
+0194-Beagle-expansion-add-zippy.patch
+0195-Beagle-expansion-add-zippy2.patch
+0196-Beagle-expansion-add-trainer.patch
+0197-Beagle-expansion-add-CircuitCo-ulcd-Support.patch
+0198-Beagle-expansion-add-wifi.patch
+0199-Beagle-expansion-add-beaglefpga.patch
+0200-Beagle-expansion-add-spidev.patch
+0201-Beagle-expansion-add-Aptina-li5m03-camera.patch
+0202-Beagle-expansion-add-LSR-COM6L-Adapter-Board.patch
+0204-meego-modedb-add-Toshiba-LTA070B220F-800x480-support.patch
+0205-backlight-Add-TLC59108-backlight-control-driver.patch
+0206-tlc59108-adjust-for-beagleboard-uLCD7.patch
+0207-zeroMAP-Open-your-eyes.patch
+0208-ARM-OMAP-Beagle-C4-fix-reboot-problem.patch
+0210-panda-fix-wl12xx-regulator.patch
+0211-ti-st-st-kim-fixing-firmware-path.patch
+0213-Revert-drm-kill-drm_sman.patch
+0215-omap3-Increase-limit-on-bootarg-mpurate.patch
+0217-staging-omap-thermal-fix-compilation.patch
+0218-staging-omap-thermal-remove-platform-data-nomenclatu.patch
+0219-staging-omap-thermal-remove-freq_clip-table.patch
+0220-staging-omap-thermal-add-IRQ-debugging-messaging.patch
+0221-staging-omap-thermal-fix-context-restore-function.patch
+0223-Attempted-SMC911x-BQL-patch.patch
+0225-spi-spidev-Add-device-tree-bindings.patch
+# umpf-release: distrokit/beaglebone/20121218
+# umpf-topic-range: 1008c9cfa5d53ee128edacdc6608aafb4946f4be..6e88807ad901e9a028fef46f76d7f6e8c40975eb
+0301-Release-distrokit-beaglebone-20121218.patch
+# umpf-end