aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDrew Moseley <drew_moseley@mentor.com>2014-05-21 16:34:03 -0400
committerDrew Moseley <drew_moseley@mentor.com>2014-05-21 16:34:03 -0400
commitba547e52f4da4d47f887f2c71ddd7498442ffb5e (patch)
tree1ce2ef7d0d0a25489d05ce034edb14022019f49f
parentbdb3ec51589d96ba63e2d01bc8d2e8deb7e984d4 (diff)
downloadmeta-amd-ba547e52f4da4d47f887f2c71ddd7498442ffb5e.tar.gz
meta-amd-ba547e52f4da4d47f887f2c71ddd7498442ffb5e.tar.bz2
meta-amd-ba547e52f4da4d47f887f2c71ddd7498442ffb5e.zip
steppeeagle: Initial commit
Signed-off-by: Drew Moseley <drew_moseley@mentor.com>
-rw-r--r--meta-steppeeagle/.gitignore0
-rw-r--r--meta-steppeeagle/COPYING.MIT17
-rw-r--r--meta-steppeeagle/binary/.gitignore0
-rw-r--r--meta-steppeeagle/conf/layer.conf12
-rw-r--r--meta-steppeeagle/conf/machine/include/tune-steppeeagle.inc18
-rw-r--r--meta-steppeeagle/conf/machine/steppeeagle.conf50
-rw-r--r--meta-steppeeagle/post-setup-environment4
-rw-r--r--meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.c575
-rw-r--r--meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.h17
-rw-r--r--meta-steppeeagle/recipes-applications/gpio-test/gpio-test_1.0.bb27
-rw-r--r--meta-steppeeagle/recipes-applications/rtc-test/files/rtc-test.c505
-rw-r--r--meta-steppeeagle/recipes-applications/rtc-test/rtc-test_1.0.bb23
-rw-r--r--meta-steppeeagle/recipes-applications/smbus-test/files/LICENSE339
-rw-r--r--meta-steppeeagle/recipes-applications/smbus-test/files/i2c-dev.h335
-rw-r--r--meta-steppeeagle/recipes-applications/smbus-test/files/smbus-test.c632
-rw-r--r--meta-steppeeagle/recipes-applications/smbus-test/smbus-test_1.0.bb27
-rw-r--r--meta-steppeeagle/recipes-applications/spi-test/files/spirom-test.c641
-rw-r--r--meta-steppeeagle/recipes-applications/spi-test/files/spirom.h43
-rw-r--r--meta-steppeeagle/recipes-applications/spi-test/spi-test_1.0.bb27
-rw-r--r--meta-steppeeagle/recipes-applications/watchdog-test/files/watchdog-test.c288
-rw-r--r--meta-steppeeagle/recipes-applications/watchdog-test/watchdog-test_1.0.bb23
-rw-r--r--meta-steppeeagle/recipes-bsp/formfactor/formfactor/steppeeagle/machconfig3
-rw-r--r--meta-steppeeagle/recipes-bsp/formfactor/formfactor_0.0.bbappend2
-rw-r--r--meta-steppeeagle/recipes-core/llvm/llvm3.4.inc49
-rw-r--r--meta-steppeeagle/recipes-core/llvm/llvm3.4/0001-R600-SI-Add-processor-type-for-Mullins.patch12
-rw-r--r--meta-steppeeagle/recipes-core/llvm/llvm3.4/arm_fenv_uclibc.patch14
-rw-r--r--meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bb19
-rw-r--r--meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bbappend1
-rw-r--r--meta-steppeeagle/recipes-graphics/drm/libdrm/0001-radeon-add-Mullins-chip-family.patch26
-rw-r--r--meta-steppeeagle/recipes-graphics/drm/libdrm/0002-radeon-add-Mullins-pci-ids.patch42
-rw-r--r--meta-steppeeagle/recipes-graphics/drm/libdrm_git.bbappend18
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Add-missing-data-files.patch623
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Use-DEMOS_DATA_DIR-to-locate-data-files.patch234
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos_8.1.0.bbappend19
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa/mesa/0001-radeonsi-add-support-for-Mullins-asics.patch74
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa/mesa/0002-radeonsi-add-Mullins-pci-ids.patch42
-rw-r--r--meta-steppeeagle/recipes-graphics/mesa/mesa_git.bbappend60
-rw-r--r--meta-steppeeagle/recipes-graphics/vdpauinfo/vdpauinfo_0.1.bb15
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-driver/glamor-egl_0.6.0.bb18
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0001-radeon-add-support-for-Mullins.patch41
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0002-radeon-kms-add-Mullins-pci-ids.patch181
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati_git.bb38
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-lib/libvdpau_0.7.bb39
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config/steppeeagle/xorg.conf113
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend1
-rw-r--r--meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xorg_1.15.0.bbappend5
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb28
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile14
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c886
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h85
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/amd-spi_1.0.bb33
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/files/Makefile14
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.c492
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.h28
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.c516
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.h43
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-wdt/amd-wdt_1.0.bb28
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-wdt/files/Makefile14
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.c518
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.h49
-rw-r--r--meta-steppeeagle/recipes-kernel/gpio-load/amd-gpio-load_1.0.bb17
-rw-r--r--meta-steppeeagle/recipes-kernel/gpio-load/files/modprobe.d/gpio-amd.conf0
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware.bb26
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_ce.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mc.binbin0 -> 31464 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_me.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mec.binbin0 -> 16768 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_pfp.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_rlc.binbin0 -> 8192 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_sdma.binbin0 -> 4200 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_smc.binbin0 -> 130540 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_uvd.binbin0 -> 224408 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_vce.binbin0 -> 78248 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_ce.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_mc.binbin0 -> 31452 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_me.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_pfp.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_rlc.binbin0 -> 8192 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_smc.binbin0 -> 59004 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_vce.binbin0 -> 78248 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_ce.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_me.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_mec.binbin0 -> 16768 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_pfp.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_rlc.binbin0 -> 10240 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_sdma.binbin0 -> 4200 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/LICENSE.radeon51
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_ce.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_me.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_mec.binbin0 -> 16768 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_pfp.binbin0 -> 8576 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_rlc.binbin0 -> 10240 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_sdma.binbin0 -> 4200 bytes
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/files/steppeeagle-user-features.scc0
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch780
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0001-yocto-amd-drm-radeon-add-vm_set_page-tracepoint.patch118
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0002-yocto-amd-drm-radeon-cleanup-flushing-on-CIK-v3.patch96
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0003-yocto-amd-drm-radeon-cleanup-DMA-HDP-flush-on-CIK-v2.patch100
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0004-yocto-amd-drm-radeon-allow-semaphore-emission-to-fail.patch754
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0005-yocto-amd-drm-radeon-improve-ring-debugfs-a-bit.patch93
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0006-yocto-amd-drm-radeon-report-the-real-offset-in-radeon_sa_bo_du.patch39
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0007-yocto-amd-drm-radeon-update-fence-values-in-before-reporting-t.patch30
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0008-yocto-amd-drm-radeon-cleanup-radeon_ttm-debugfs-handling.patch109
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0009-yocto-amd-drm-radeon-add-VRAM-debugfs-access-v3.patch168
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0010-yocto-amd-drm-radeon-add-GART-debugfs-access-v3.patch119
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0011-yocto-amd-drm-radeon-fix-VMID-use-tracking.patch71
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0012-yocto-amd-drm-radeon-add-missing-trace-point.patch28
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0013-yocto-amd-drm-radeon-add-semaphore-trace-point.patch95
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0014-yocto-amd-drm-radeon-add-VMID-allocation-trace-point.patch64
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0015-yocto-amd-drm-radeon-add-uvd-debugfs-support.patch99
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0016-yocto-amd-drm-radeon-add-radeon_vm_bo_update-trace-point.patch138
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0017-yocto-amd-drm-radeon-drop-CP-page-table-updates-cleanup-v2.patch676
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0018-yocto-amd-drm-radeon-add-large-PTE-support-for-NI-SI-and-CIK-v.patch237
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0019-yocto-amd-drm-radeon-add-proper-support-for-RADEON_VM_BLOCK_SI.patch133
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0020-yocto-amd-drm-radeon-WIP-add-copy-trace-point.patch59
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0021-yocto-amd-drm-radeon-cik-Return-backend-map-information-to-use.patch34
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0022-yocto-amd-drm-radeon-cik-Add-macrotile-mode-array-query.patch113
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0023-yocto-amd-drm-radeon-set-correct-number-of-banks-for-CIK-chips.patch102
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0024-yocto-amd-drm-radeon-don-t-power-gate-paused-UVD-streams.patch45
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0025-yocto-amd-drm-radeon-dpm-retain-user-selected-performance-leve.patch45
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0026-yocto-amd-drm-radeon-remove-generic-rptr-wptr-functions-v2.patch1049
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch1434
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0028-yocto-amd-drm-radeon-add-VCE-ring-query.patch30
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0029-yocto-amd-drm-radeon-add-VCE-version-parsing-and-checking.patch147
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0030-yocto-amd-drm-radeon-add-callback-for-setting-vce-clocks.patch35
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0031-yocto-amd-drm-radeon-dpm-move-platform-caps-fetching-to-a-sepa.patch330
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0032-yocto-amd-drm-radeon-dpm-fill-in-some-initial-vce-infrastructu.patch84
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0033-yocto-amd-drm-radeon-dpm-fetch-vce-states-from-the-vbios.patch110
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0034-yocto-amd-drm-radeon-fill-in-set_vce_clocks-for-CIK-asics.patch111
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0035-yocto-amd-drm-radeon-add-vce-dpm-support-for-CI.patch149
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0036-yocto-amd-drm-radeon-enable-vce-dpm-on-CI.patch28
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0037-yocto-amd-drm-radeon-add-vce-dpm-support-for-KV-KB.patch169
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0038-yocto-amd-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch195
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0039-yocto-amd-drm-radeon-dpm-properly-enable-disable-vce-when-vce-.patch56
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0040-yocto-amd-drm-radeon-add-vce-debugfs-support.patch98
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0041-yocto-amd-drm-radeon-add-support-for-vce-2.0-clock-gating.patch165
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0042-yocto-amd-drm-radeon-cik-enable-disable-vce-cg-when-encoding.patch90
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0043-yocto-amd-drm-radeon-fix-CP-semaphores-on-CIK.patch117
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0044-yocto-amd-drm-radeon-disable-dynamic-powering-vce.patch30
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0045-yocto-amd-drm-radeon-add-Mullins-chip-family.patch39
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0046-yocto-amd-drm-radeon-update-cik-init-for-Mullins.patch140
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0047-yocto-amd-drm-radeon-add-Mullins-UVD-support.patch17
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0048-yocto-amd-drm-radeon-add-Mullins-dpm-support.patch111
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0049-yocto-amd-drm-radeon-modesetting-updates-for-Mullins.patch21
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0050-yocto-amd-drm-radeon-add-pci-ids-for-Mullins.patch30
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0051-yocto-amd-drm-radeon-add-Mulins-VCE-support.patch17
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0052-yocto-amd-clear-exceptions-in-AMD-FXSAVE-workaround.patch34
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0053-yocto-amd-i2c-piix4-add-support-for-AMD-ML-and-CZ-SMBus-changes.patch87
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0054-yocto-amd-i2c-piix4-use-different-message-for-AMD-auxiliary-SMBus-controller.patch24
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/0055-yocto-amd-change-acpi-enforce-resources-to-lax.patch19
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto/defconfig4181
-rw-r--r--meta-steppeeagle/recipes-kernel/linux/linux-yocto_3.12.bb71
-rw-r--r--meta-steppeeagle/recipes-kernel/wdt-load/amd-wdt-load_1.0.bb18
-rw-r--r--meta-steppeeagle/recipes-kernel/wdt-load/files/modprobe.d/amd-wdt.conf0
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0001-gstomxvideodec-fix-multithreads-negotiation-problem-.patch36
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0002-gstomxvideodec-remove-dead-code.patch99
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0003-gstomxvideodec-simplify-_find_nearest_frame.patch125
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0004-gstomxvideoenc-simplify-_find_nearest_frame.patch175
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0005-omx-improve-tunneling-support.patch77
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-omx-add-tunneling-support-between-decoder-and-encode.patch328
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0007-gstomxvideoenc-implement-scaling-configuration-suppo.patch155
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0008-configure-fix-first-run-of-autogen-automake.patch29
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0009-omxvideodec-fix-startup-race-condition.patch33
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0010-omxvideoenc-fix-startup-race-condition.patch33
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx/0011-omx-fix-two-serious-message-handling-bugs.patch40
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-omx_git.bbappend32
-rw-r--r--meta-steppeeagle/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.2.3.bbappend1
-rw-r--r--meta-steppeeagle/recipes-multimedia/libomxil/libomxil_0.9.3.bbappend8
168 files changed, 22886 insertions, 0 deletions
diff --git a/meta-steppeeagle/.gitignore b/meta-steppeeagle/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/meta-steppeeagle/.gitignore
diff --git a/meta-steppeeagle/COPYING.MIT b/meta-steppeeagle/COPYING.MIT
new file mode 100644
index 00000000..89de3547
--- /dev/null
+++ b/meta-steppeeagle/COPYING.MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/meta-steppeeagle/binary/.gitignore b/meta-steppeeagle/binary/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/meta-steppeeagle/binary/.gitignore
diff --git a/meta-steppeeagle/conf/layer.conf b/meta-steppeeagle/conf/layer.conf
new file mode 100644
index 00000000..dab62903
--- /dev/null
+++ b/meta-steppeeagle/conf/layer.conf
@@ -0,0 +1,12 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+# We have a recipes-* directories, add to BBFILES
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+ ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "steppeeagle"
+BBFILE_PATTERN_steppeeagle = "^${LAYERDIR}/"
+BBFILE_PRIORITY_steppeeagle = "6"
+
+LAYERDEPENDS_steppeeagle = "amd openembedded-layer"
diff --git a/meta-steppeeagle/conf/machine/include/tune-steppeeagle.inc b/meta-steppeeagle/conf/machine/include/tune-steppeeagle.inc
new file mode 100644
index 00000000..0c142a70
--- /dev/null
+++ b/meta-steppeeagle/conf/machine/include/tune-steppeeagle.inc
@@ -0,0 +1,18 @@
+DEFAULTTUNE ?= "dbft3b"
+
+require conf/machine/include/x86/arch-x86.inc
+require conf/machine/include/x86-base.inc
+
+
+# AMD DB-FT3b 64bit (SteppeEagle)
+TUNEVALID[dbft3b] = "Enable AMD DB-FT3b (64 bit) specific processor optimizations"
+TUNECONFLICTS[dbft3b] = "m32 mx32"
+TUNE_ARCH .= "${@bb.utils.contains("TUNE_FEATURES", "dbft3b", "${X86ARCH64}", "" ,d)}"
+TUNE_CCARGS .= "${@bb.utils.contains("TUNE_FEATURES", "dbft3b", " -march=btver2", "", d)}"
+
+# Extra tune selections
+AVAILTUNES += "dbft3b"
+TUNE_FEATURES_tune-dbft3b = "dbft3b"
+BASE_LIB_tune-dbft3b = "lib64"
+TUNE_PKGARCH_tune-dbft3b = "dbft3b"
+PACKAGE_EXTRA_ARCHS_tune-dbft3b = "${TUNE_PKGARCH_tune-dbft3b}"
diff --git a/meta-steppeeagle/conf/machine/steppeeagle.conf b/meta-steppeeagle/conf/machine/steppeeagle.conf
new file mode 100644
index 00000000..96a80129
--- /dev/null
+++ b/meta-steppeeagle/conf/machine/steppeeagle.conf
@@ -0,0 +1,50 @@
+#@TYPE: Machine
+#@NAME: steppeeagle
+
+#@DESCRIPTION: Machine configuration for steppeeagle systems
+
+
+PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
+PREFERRED_PROVIDER_jpeg ?= "jpeg"
+PREFERRED_PROVIDER_jpeg-native ?= "jpeg-native"
+PREFERRED_VERSION_linux-yocto = "3.12%"
+PREFERRED_VERSION_mesa = "10.2.0+git%"
+PREFERRED_VERSION_xf86-video-ati = "7.3.99+git%"
+PREFERRED_VERSION_gstreamer1.0-omx = "git+git%"
+PREFERRED_VERSION_llvm = "3.4"
+PREFERRED_VERSION_libdrm = "2.4.53+git%"
+
+require conf/machine/include/tune-steppeeagle.inc
+
+MACHINE_FEATURES += "wifi efi pcbios"
+
+XSERVER_X86_RADEON = "xf86-video-ati \
+ ${@base_contains('DISTRO_FEATURES', 'opengl', 'mesa-driver-radeon', '', d)} \
+ "
+XSERVER ?= "${XSERVER_X86_BASE} \
+ ${XSERVER_X86_EXT} \
+ ${XSERVER_X86_FBDEV} \
+ ${XSERVER_X86_MODESETTING} \
+ ${XSERVER_X86_RADEON} \
+ "
+
+MACHINE_EXTRA_RRECOMMENDS += "v86d kernel-modules radeon-firmware alsa-utils"
+MACHINE_EXTRA_RRECOMMENDS += "vdpauinfo grub"
+MACHINE_EXTRA_RRECOMMENDS += "rtc-test watchdog-test spi-test smbus-test gpio-test"
+MACHINE_ESSENTIAL_EXTRA_RDEPENDS += "amd-gpio amd-spi amd-wdt amd-gpio-load amd-wdt-load"
+
+GLIBC_ADDONS = "nptl"
+
+EXTRA_OECONF_append_pn-matchbox-panel-2 = " --with-battery=acpi"
+
+# Setup a gettys on all serial ports
+SERIAL_CONSOLES = "115200;ttyUSB0"
+
+# Make sure the kernel messages go to the VGA console and to the serial ports.
+APPEND += "console=tty0 console=ttyUSB0,115200"
+
+RELEASE_IMAGE ?= "core-image-sato"
+
+APPEND += "radeon.dpm=1"
+
+SYSLINUX_LABELS = "boot"
diff --git a/meta-steppeeagle/post-setup-environment b/meta-steppeeagle/post-setup-environment
new file mode 100644
index 00000000..6807d5f6
--- /dev/null
+++ b/meta-steppeeagle/post-setup-environment
@@ -0,0 +1,4 @@
+if [ -e conf/local.conf ]; then
+ sed -i -e 's@\(CORE_IMAGE_EXTRA_INSTALL.*\)oprofile\(.*\)@\1\2@' \
+ -e 's@\(EXTRA_IMAGE_FEATURES.*\)tools-profile\(.*\)@\1\2@' conf/local.conf
+fi
diff --git a/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.c b/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.c
new file mode 100644
index 00000000..38c43276
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.c
@@ -0,0 +1,575 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+
+#include <readline/readline.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#include "gpio-test.h"
+
+#define GPIO_APP_VERSION "0.1"
+#define AMD_GPIO_NUM_PINS 184
+static int gpio_in_use[AMD_GPIO_NUM_PINS];
+
+char *show_prompt(void)
+{
+ return "$ ";
+}
+
+void sighandler(int sig)
+{
+ printf("\n%s", show_prompt());
+}
+
+void show_license(void)
+{
+ printf("/*****************************************************************************\n"
+ "*\n"
+ "* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "* All rights reserved.\n"
+ "*\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
+ "* modification, are permitted provided that the following conditions are met:\n"
+ "* * Redistributions of source code must retain the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer.\n"
+ "* * Redistributions in binary form must reproduce the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer in the\n"
+ "* documentation and/or other materials provided with the distribution.\n"
+ "* * Neither the name of Advanced Micro Devices, Inc. nor the names of\n"
+ "* its contributors may be used to endorse or promote products derived\n"
+ "* from this software without specific prior written permission.\n"
+ "*\n"
+ "* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n"
+ "* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
+ "* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
+ "* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY\n"
+ "* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
+ "* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+ "* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"
+ "* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+ "* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*\n"
+ "*\n"
+ "***************************************************************************/\n");
+}
+
+void print_usage()
+{
+ printf("\nCommands Supported ->\n");
+ printf(" getgpiomode <gpio> : Gets the mode of GPIO pin\n");
+ printf(" setgpiomode <gpio> <in/out/high/low> : Sets the mode of GPIO pin to input or output(high/low)\n");
+ printf(" getgpiovalue <gpio> : Gets the value of GPIO pin\n");
+ printf(" setgpiovalue <gpio> <high/low> : Sets the value of GPO pin to high or low\n");
+ printf(" getnumgpio : Gets the number of GPIO pins supported\n");
+ printf(" getgpiobase : Gets the number of first GPIO pin\n");
+ printf(" getgpioname : Gets the name of GPIO driver currently in use\n");
+ printf(" dmesg : Displays the kernel log messages related to GPIO\n");
+ printf(" license : Displays the terms of LICENSE for this application\n");
+ printf(" help : Displays help text\n");
+ printf(" exit : Exits the application\n\n");
+}
+
+void parse_cmd(const char *cmdline)
+{
+ int fd;
+
+ if (strncmp(cmdline, "help", 4) == 0)
+ print_usage();
+ else if (strncmp(cmdline, "getnumgpio", 10) == 0) {
+ int fd;
+ char ngpio[3 + 1];
+
+ memset(ngpio, '\0', (3 + 1));
+ fd = open("/sys/class/gpio/gpiochip0/ngpio", O_RDONLY);
+ if (fd < 0) {
+ printf("\nPlease make sure AMD GPIO driver is loaded\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Value read from the file is ASCII text */
+ if(read(fd, ngpio, 3) < 0)
+ perror("Cannot read number of GPIO pins");
+
+ printf("\nThe maximum number of GPIO pins supported is %d\n", atoi(ngpio));
+ close(fd);
+ } else if (strncmp(cmdline, "getgpiobase", 11) == 0) {
+ int fd;
+ char gpiobase[3 + 1];
+
+ memset(gpiobase, '\0', (3 + 1));
+ fd = open("/sys/class/gpio/gpiochip0/base", O_RDONLY);
+ if (fd < 0) {
+ printf("\nPlease make sure AMD GPIO driver is loaded\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(read(fd, gpiobase, 3) < 0)
+ perror("Cannot read GPIO base");
+
+ printf("\nGPIO pin numbering starts from %d\n", atoi(gpiobase));
+ close(fd);
+ } else if (strncmp(cmdline, "getgpioname", 11) == 0) {
+ int fd;
+ char gpioname[10 + 1]; /* Max 10 characters + NULL character */
+
+ /* Zero initialize gpioname array */
+ memset(gpioname, '\0', sizeof(gpioname));
+
+ fd = open("/sys/class/gpio/gpiochip0/label", O_RDONLY);
+ if (fd < 0) {
+ printf("\nPlease make sure AMD GPIO driver is loaded\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(read(fd, gpioname, 10) < 0)
+ perror("Cannot read GPIO driver name");
+
+ printf("\nGPIO driver loaded is %s\n", gpioname);
+ close(fd);
+ } else if (strncmp(cmdline, "getgpiovalue", 12) == 0) {
+ int fd;
+ int gpio;
+ const char *charp = cmdline;
+ char pathname[80];
+ int ret = 0;
+
+ /* Lets point to the end of first token */
+ charp += strlen("getgpiovalue");
+ /* Skip blank characters */
+ while (*charp == ' ' || *charp == '\t' || *charp == '\n')
+ charp++;
+
+ /* Now we should be pointing to the first 'digit' character */
+ gpio = atoi(charp);
+
+ fd = open("/sys/class/gpio/export", O_WRONLY);
+ if (fd < 0) {
+ if (errno == EACCES)
+ printf("\nYou do not have correct permission, please run as root\n");
+ else
+ perror("Eror opening /sys/class/gpio/export");
+
+ exit(EXIT_FAILURE);
+ }
+
+ ret = write(fd, charp, strlen(charp));
+ /*
+ * There can be two situations ->
+ * 1) The GPIO is being exported for the first time.
+ * 2) The GPIO is being exported again.
+ * In the first case, the write to file descriptor should
+ * succeed, and we should still fall into the if clause.
+ *
+ * In the second case, write will fail and errno will be
+ * set to EBUSY, since the GPIO pin is already exported.
+ * Rest all is error.
+ */
+ if((ret >= 0) || ((ret < 0) && (errno == EBUSY))) {
+ /* Close the last file descriptor */
+ close(fd);
+
+ memset(pathname, '\0', sizeof(pathname));
+ sprintf(pathname, "/sys/class/gpio/gpio%d/value", gpio);
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0)
+ perror("GPIO read error");
+ else {
+ char value[1 + 1];
+
+ memset(value, '\0', 2);
+ ret = read(fd, value, 1);
+ if (ret < 0)
+ perror("Cannot read GPIO pin");
+
+ printf("\nGPIO pin %s is at \"%s\"\n", charp,
+ (strncmp(value, "1", 1) == 0) ? "high" : "low");
+
+ close(fd);
+
+ /*
+ * Mark the GPIO as already exported, so that we can use
+ * unexport them during exit.
+ */
+ gpio_in_use[gpio] = 1;
+ }
+ } else {
+ if (errno == EINVAL)
+ printf("\nInvalid GPIO number\n");
+ else
+ perror("Error exporting GPIO number");
+
+ close(fd);
+ }
+ } else if (strncmp(cmdline, "getgpiomode", 11) == 0) {
+ int fd;
+ int gpio;
+ const char *charp = cmdline;
+ char pathname[80];
+ int ret = 0;
+
+ /* Lets point to the end of first token */
+ charp += strlen("getgpiomode");
+ /* Skip blank characters */
+ while (*charp == ' ' || *charp == '\t' || *charp == '\n')
+ charp++;
+
+ /* Now we should be pointing to the first 'digit' character */
+ gpio = atoi(charp);
+
+ fd = open("/sys/class/gpio/export", O_WRONLY);
+ if (fd < 0) {
+ if (errno == EACCES)
+ printf("\nYou do not have correct permission, please run as root\n");
+ else
+ perror("Eror opening /sys/class/gpio/export");
+
+ exit(EXIT_FAILURE);
+ }
+
+ ret = write(fd, charp, strlen(charp));
+ /*
+ * There can be two situations ->
+ * 1) The GPIO is being exported for the first time.
+ * 2) The GPIO is being exported again.
+ * In the first case, the write to file descriptor should
+ * succeed, and we should still fall into the if clause.
+ *
+ * In the second case, write will fail and errno will be
+ * set to EBUSY, since the GPIO pin is already exported.
+ * Rest all is error.
+ */
+ if((ret >= 0) || ((ret < 0) && (errno == EBUSY))) {
+ FILE *fp;
+
+ /* Close the last file descriptor */
+ close(fd);
+
+ memset(pathname, '\0', sizeof(pathname));
+ sprintf(pathname, "/sys/class/gpio/gpio%d/direction", gpio);
+
+ fp = fopen(pathname, "r");
+ if (fp == NULL)
+ perror("GPIO read error");
+ else {
+ char mode[3 + 1];
+ int c, i = 0;
+
+ memset(mode, '\0', (3 + 1));
+ /*
+ * Since we do not exactly know whether the
+ * direction will be 'in' or 'out', we need to
+ * use fgetc() so that we read the input till
+ * we find terminating '\n', at which point
+ * we stop reading any further.
+ */
+ while ((c = fgetc(fp)) != '\n')
+ mode[i++] = c;
+
+ printf("\nGPIO pin %s is in \"%s\" mode\n", charp,
+ (strncmp(mode, "in", 2) == 0) ? "input" : "output");
+
+ fclose(fp);
+
+ /*
+ * Mark the GPIO as already exported, so that we can use
+ * unexport them during exit.
+ */
+ gpio_in_use[gpio] = 1;
+ }
+ } else {
+ if (errno == EINVAL)
+ printf("\nInvalid GPIO number\n");
+ else
+ perror("Error exporting GPIO number");
+
+ close(fd);
+ }
+ } else if (strncmp(cmdline, "setgpiomode", 11) == 0) {
+ int fd;
+ const char *charp = cmdline;
+ int i = 0;
+ char gpio[3 + 1];
+ int ngpio;
+ int ret;
+
+ charp += strlen("setgpiomode");
+ while (*charp == ' ' || *charp == '\t' || *charp == '\n')
+ charp++;
+
+ memset(gpio, '\0', (3 + 1));
+ /*
+ * We are at the start of string which contains the GPIO
+ * number. We look for the end of this string, copying
+ * byte by byte into array. We also make sure that we
+ * do not store more than 3 bytes into the array, since
+ * a GPIO can have a maximum value of 183, that is, not
+ * exceeding 3 characters.
+ */
+ while (*charp != ' ' && *charp != '\t' && (i < 3)) {
+ gpio[i++] = *charp;
+ charp++;
+ }
+
+ ngpio = atoi(gpio);
+
+ fd = open("/sys/class/gpio/export", O_WRONLY);
+ if (fd < 0) {
+ if (errno == EACCES)
+ printf("\nYou do not have correct permission, please run as root\n");
+ else
+ perror("Eror opening /sys/class/gpio/export");
+
+ exit(EXIT_FAILURE);
+ }
+
+ ret = write(fd, gpio, strlen(gpio));
+ if((ret >= 0) || ((ret < 0) && (errno == EBUSY))) {
+ char pathname[80];
+
+ /* Close the last file descriptor */
+ close(fd);
+
+ memset(pathname, '\0', sizeof(pathname));
+ sprintf(pathname, "/sys/class/gpio/gpio%d/direction", ngpio);
+
+ fd = open(pathname, O_WRONLY);
+ if (fd < 0)
+ perror("GPIO read error");
+ else {
+ char mode[4 + 1];
+
+ memset(mode, '\0', (4 + 1));
+
+ /* Lets skip the blanks till we find a character */
+ while (*charp == ' ' || *charp == '\t')
+ charp++;
+
+ i = 0;
+ /*
+ * Mode can be 'in', 'out', 'high' or 'low',
+ * again a maximum of 4 characters.
+ */
+ while (*charp != ' ' && *charp != '\t' && (i < 4)) {
+ mode[i++] = *charp;
+ charp++;
+ }
+
+ /* Sanity check */
+ if ((strncmp(mode, "in", 2) == 0) ||
+ (strncmp(mode, "out", 3) == 0) ||
+ (strncmp(mode, "high", 4) == 0) ||
+ (strncmp(mode, "low", 3) == 0)) {
+ /* Write mode into /sys/.../direction file */
+ ret = write(fd, mode, strlen(mode));
+ if (ret < 0)
+ perror("Error writing GPIO mode");
+ } else
+ printf("\nInvalid GPIO mode, please try again\n");
+
+ close(fd);
+
+ /*
+ * Mark the GPIO as exported, so that we can use
+ * unexport them during exit.
+ */
+ gpio_in_use[ngpio] = 1;
+ }
+ } else {
+ if (errno == EINVAL)
+ printf("\nInvalid GPIO number\n");
+ else
+ perror("Error exporting GPIO number");
+
+ close(fd);
+ }
+ } else if (strncmp(cmdline, "setgpiovalue", 12) == 0) {
+ int fd;
+ const char *charp = cmdline;
+ int i = 0;
+ char gpio[3 + 1];
+ int ngpio;
+ int ret;
+
+ charp += strlen("setgpiovalue");
+ while (*charp == ' ' || *charp == '\t' || *charp == '\n')
+ charp++;
+
+ memset(gpio, '\0', (3 + 1));
+ /*
+ * We are at the start of string which contains the GPIO
+ * number. We look for the end of this string, copying
+ * byte by byte into array. We also make sure that we
+ * do not store more than 3 bytes into the array, since
+ * a GPIO can have a maximum value of 183, that is, not
+ * exceeding 3 characters.
+ */
+ while (*charp != ' ' && *charp != '\t' && (i < 3)) {
+ gpio[i++] = *charp;
+ charp++;
+ }
+
+ ngpio = atoi(gpio);
+
+ fd = open("/sys/class/gpio/export", O_WRONLY);
+ if (fd < 0) {
+ if (errno == EACCES)
+ printf("\nYou do not have correct permission, please run as root\n");
+ else
+ perror("Eror opening /sys/class/gpio/export");
+
+ exit(EXIT_FAILURE);
+ }
+
+ ret = write(fd, gpio, strlen(gpio));
+ if((ret >= 0) || ((ret < 0) && (errno == EBUSY))) {
+ char pathname[80];
+
+ /* Close the last file descriptor */
+ close(fd);
+
+ memset(pathname, '\0', sizeof(pathname));
+ sprintf(pathname, "/sys/class/gpio/gpio%d/value", ngpio);
+
+ fd = open(pathname, O_WRONLY);
+ if (fd < 0)
+ perror("GPIO read error");
+ else {
+ char value[1 + 1];
+
+ memset(value, '\0', (1 + 1));
+
+ /* Lets skip the blanks till we find a character */
+ while (*charp == ' ' || *charp == '\t')
+ charp++;
+
+ i = 0;
+
+ if (strncmp(charp, "high", 4) == 0)
+ value[0] = '1';
+ else if (strncmp(charp, "low", 3) == 0)
+ value[0] = '0';
+ else {
+ printf("\nInvalid input, please try again...\n");
+ goto out;
+ }
+
+ /* Write mode into /sys/.../direction file */
+ ret = write(fd, value, 1);
+ if (ret < 0)
+ perror("Error writing GPIO mode");
+
+out:
+ close(fd);
+
+ /*
+ * Mark the GPIO as exported, so that we can use
+ * unexport them during exit.
+ */
+ gpio_in_use[ngpio] = 1;
+ }
+ } else {
+ if (errno == EINVAL)
+ printf("\nInvalid GPIO number\n");
+ else
+ perror("Error exporting GPIO number");
+
+ close(fd);
+ }
+ } else if (strncmp(cmdline, "dmesg", 5) == 0) {
+ if (system("dmesg | grep GPIO") < 0)
+ perror("Error executing \'dmesg | grep GPIO\'");
+ } else if (strncmp(cmdline, "license", 7) == 0) {
+ show_license();
+ } else if (strncmp(cmdline, "exit", 4) == 0) {
+ int i;
+ int ret;
+ char gpio[3 + 1];
+
+ printf("\nExiting...\n");
+
+ /* We need to unexport all the GPIO pins exported earlier */
+ for (i = 0; i < AMD_GPIO_NUM_PINS; i++) {
+ if (gpio_in_use[i]) {
+ int fd;
+
+ fd = open("/sys/class/gpio/unexport", O_WRONLY);
+ if (fd < 0) {
+ printf("\nPlease make sure AMD GPIO driver is loaded\n");
+ exit(EXIT_FAILURE);
+ }
+ memset(gpio, '\0', (3 + 1));
+ snprintf(gpio, 4, "%d", i);
+
+ ret = write(fd, gpio, strlen(gpio));
+ if (ret < 0)
+ perror("Error writing to /sys/class/gpio/unexport");
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+ } else {
+ printf("\nUnknown command\n");
+ print_usage();
+ }
+}
+
+int main(void)
+{
+ char *cmdline= NULL;
+
+ printf("GPIO sample application version: %s\n", GPIO_APP_VERSION);
+ printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "This sample application comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; type `license' for details.\n\n");
+
+ /* Handler for Ctrl+C */
+ signal(SIGINT, sighandler);
+
+ while (1) {
+ cmdline = readline(show_prompt());
+ parse_cmd(cmdline);
+ /* Free the memory malloc'ed by readline */
+ free(cmdline);
+ }
+
+ /* Should never reach here */
+ return 0;
+}
diff --git a/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.h b/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.h
new file mode 100644
index 00000000..af9c3b68
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/gpio-test/files/gpio-test.h
@@ -0,0 +1,17 @@
+#ifndef _GPIO_TEST_H_
+#define _GPIO_TEST_H_
+
+
+
+/* IOCTL numbers */
+
+typedef struct {
+ int offset;
+ int value;
+}debug_data;
+
+#define GPIO_TEST_IOC_MAGIC 'k'
+#define GPIO_IOC_SWCTRLIN _IOW(GPIO_TEST_IOC_MAGIC, 1, debug_data)
+#define GPIO_IOC_SWCTRLEN _IOW(GPIO_TEST_IOC_MAGIC, 2, debug_data)
+
+#endif /* _GPIO_TEST_H_ */
diff --git a/meta-steppeeagle/recipes-applications/gpio-test/gpio-test_1.0.bb b/meta-steppeeagle/recipes-applications/gpio-test/gpio-test_1.0.bb
new file mode 100644
index 00000000..246a1c97
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/gpio-test/gpio-test_1.0.bb
@@ -0,0 +1,27 @@
+DESCRIPTION = "Sample application for AMD GPIO driver"
+SECTION = "applications"
+LICENSE = "BSD"
+DEPENDS = "readline"
+LIC_FILES_CHKSUM = "file://gpio-test.c;md5=cd7d02789bf5b4795b385ad4f2938469 \
+ file://gpio-test.h;md5=c7aaa743b172cf584032f9bfc5e85044 \
+ "
+
+PR = "r1"
+PV = "1.0"
+
+SRC_URI = "file://gpio-test.c \
+ file://gpio-test.h \
+ "
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+S = "${WORKDIR}"
+
+do_compile() {
+ ${CC} gpio-test.c -o gpio-test -lreadline
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 gpio-test ${D}${bindir}
+}
diff --git a/meta-steppeeagle/recipes-applications/rtc-test/files/rtc-test.c b/meta-steppeeagle/recipes-applications/rtc-test/files/rtc-test.c
new file mode 100644
index 00000000..08088544
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/rtc-test/files/rtc-test.c
@@ -0,0 +1,505 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <linux/rtc.h>
+
+#include <readline/readline.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+
+#define RTC_APP_VERSION "0.1"
+static const char *rtc = "/dev/rtc0";
+static int rtc_fd;
+static int signal_recvd;
+static volatile int loop;
+
+char *show_prompt(void)
+{
+ return "$ ";
+}
+
+void sighandler(int sig)
+{
+ printf("\n%s", show_prompt());
+}
+
+void periodicinthandler(int sig)
+{
+ int ret;
+
+ fprintf(stderr, "\nAborting...\n");
+ fflush(stderr);
+
+ loop = 0;
+
+ /* Turn off periodic interrupts */
+ ret = ioctl(rtc_fd, RTC_PIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_PIE_OFF ioctl");
+
+ /* Restore original handler for SIGINT */
+ signal(SIGINT, sighandler);
+}
+
+void updateinthandler(int sig)
+{
+ int ret;
+
+ fprintf(stderr, "\nAborting...\n");
+ fflush(stderr);
+
+ loop = 0;
+
+ /* Turn off update interrupt */
+ ret = ioctl(rtc_fd, RTC_UIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_UIE_OFF ioctl");
+
+ /* Restore original handler for SIGINT */
+ signal(SIGINT, sighandler);
+}
+
+void alarminthandler(int sig)
+{
+ struct rtc_wkalrm rtc_wakealarm;
+ int ret;
+
+ signal_recvd = 1;
+
+ ret = ioctl(rtc_fd, RTC_WKALM_RD, &rtc_wakealarm);
+ if (ret == -1) {
+ perror("RTC_WKALM_RD ioctl");
+ return;
+ }
+
+ /* disable alarm and set pending to 0 */
+ rtc_wakealarm.enabled = 0;
+ rtc_wakealarm.pending = 0;
+
+ ret = ioctl(rtc_fd, RTC_WKALM_SET, &rtc_wakealarm);
+ if (ret == -1) {
+ perror("RTC_WKALM_SET ioctl");
+ return;
+ }
+
+ /* Restore original handler for SIGINT */
+ signal(SIGINT, sighandler);
+}
+
+void show_license(void)
+{
+ printf("/*****************************************************************************\n"
+ "*\n"
+ "* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "* All rights reserved.\n"
+ "*\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
+ "* modification, are permitted provided that the following conditions are met:\n"
+ "* * Redistributions of source code must retain the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer.\n"
+ "* * Redistributions in binary form must reproduce the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer in the\n"
+ "* documentation and/or other materials provided with the distribution.\n"
+ "* * Neither the name of Advanced Micro Devices, Inc. nor the names of\n"
+ "* its contributors may be used to endorse or promote products derived\n"
+ "* from this software without specific prior written permission.\n"
+ "*\n"
+ "* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n"
+ "* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
+ "* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
+ "* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY\n"
+ "* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
+ "* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+ "* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"
+ "* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+ "* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*\n"
+ "*\n"
+ "***************************************************************************/\n");
+}
+
+void print_usage(void)
+{
+ printf("\nCommands Supported ->\n");
+ printf(" updateinton : Turns on update interrupt\n");
+ printf(" updateintoff : Turns off update interrupt\n");
+ printf(" getrtctime : Reads the current RTC time\n");
+ printf(" setrtctime <date>, <time> : Sets RTC date and time. Both date and time are mandatory\n");
+ printf(" getwakealarm : Reads the current alarm setting\n");
+ printf(" setwakealarm <date>, <time> : Sets the alarm date and time. Both date and time are mandatory\n");
+ printf(" wakealarmoff : Turn off wakeup alarm set previously\n");
+ printf(" getperiodicrate : Reads the current periodic interrupt rate\n");
+ printf(" setperiodicrate <rate> : Sets the periodic interrupt rate\n");
+ printf(" : The rate can take values from 2 to 8192 in steps of "
+ "power of 2\n");
+ printf(" : 2, 4, 8, ..., 8192\n");
+ printf(" periodicinton : Turns on periodic interrupt\n");
+ printf(" periodicintoff : Turns off periodic interrupt\n");
+ printf(" license : Displays the terms of LICENSE for this application\n");
+ printf(" help : Displays help text\n");
+ printf(" exit : Exits the application\n\n");
+}
+
+void parse_cmd(const char *cmdline)
+{
+ int ret, irqcount = 0;
+ unsigned long data;
+ struct rtc_time rtc_time;
+ struct rtc_wkalrm rtc_wakealarm;
+
+ if (strncmp(cmdline, "help", 4) == 0)
+ print_usage();
+ else if (strncmp(cmdline, "updateinton", 11) == 0) {
+ int i;
+
+ ret = ioctl(rtc_fd, RTC_UIE_ON, 0);
+ if (ret == -1) {
+ if (errno == ENOTTY)
+ fprintf(stderr, "\n..Update interrupt not supported.\n");
+
+ perror("RTC_UIE_ON ioctl");
+ return;
+ }
+
+ fprintf(stderr, "Counting update interrupts by reading %s...Press Ctrl+C to abort\n", rtc);
+ fflush(stderr);
+
+ /* Set default handler for SIGINT */
+ signal(SIGINT, updateinthandler);
+
+ i = loop = 1;
+ while (loop) {
+ struct timeval tv = {5, 0};
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(rtc_fd, &readfds);
+
+ ret = select(rtc_fd + 1, &readfds, NULL, NULL, &tv);
+ if (ret == -1) {
+ if (errno != EINTR)
+ perror("select");
+
+ /* Break the loop */
+ loop = 0;
+ } else {
+ /* Non blocking read */
+ ret = read(rtc_fd, &data, sizeof(unsigned long));
+ if (ret == -1) {
+ perror("read");
+ loop = 0;
+ } else {
+ fprintf(stderr, " %d", i++);
+ irqcount++;
+ }
+ }
+ }
+
+ /* Turn off update interrupt */
+ ret = ioctl(rtc_fd, RTC_UIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_UIE_OFF ioctl");
+ } else if (strncmp(cmdline, "updateintoff", 12) == 0) {
+ fprintf(stderr, "Turning update interrupt off\n");
+ fflush(stderr);
+
+ ret = ioctl(rtc_fd, RTC_UIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_UIE_OFF ioctl");
+ } else if (strncmp(cmdline, "getrtctime", 10) == 0) {
+ ret = ioctl(rtc_fd, RTC_RD_TIME, &rtc_time);
+ if (ret == -1)
+ perror("RTC_RD_TIME ioctl");
+ else
+ fprintf(stderr, "\nCurrent RTC date and time is %02d/%02d/%04d, %02d:%02d:%02d\n",
+ rtc_time.tm_mon + 1, rtc_time.tm_mday, rtc_time.tm_year + 1900,
+ rtc_time.tm_hour, rtc_time.tm_min, rtc_time.tm_sec);
+ } else if (strncmp(cmdline, "setrtctime", 10) == 0) {
+ /* Point past the string and one whitespace */
+ cmdline += 11;
+ ret = sscanf(cmdline, "%02d/%02d/%04d, %02d:%02d:%02d", &rtc_time.tm_mon, &rtc_time.tm_mday,
+ &rtc_time.tm_year, &rtc_time.tm_hour, &rtc_time.tm_min, &rtc_time.tm_sec);
+
+ if (ret < 6) {
+ fprintf(stderr, "\nPlease check your input\n");
+ return;
+ }
+
+ /* months should be in the range 0 to 11 */
+ rtc_time.tm_mon -= 1;
+ /* years should be number of years since 1900 */
+ rtc_time.tm_year -= 1900;
+ ret = ioctl(rtc_fd, RTC_SET_TIME, &rtc_time);
+ if (ret == -1)
+ perror("RTC_SET_TIME ioctl");
+ } else if (strncmp(cmdline, "getwakealarm", 12) == 0) {
+ ret = ioctl(rtc_fd, RTC_WKALM_RD, &rtc_wakealarm);
+ if (ret == -1)
+ perror("RTC_WKALM_RD ioctl");
+ else {
+ fprintf(stderr, "\nRTC alarm is %s and %s\n",
+ rtc_wakealarm.enabled ? "enabled" : "disabled",
+ rtc_wakealarm.pending ? "pending": "not pending");
+ fprintf(stderr, "\nCurrent alarm date and time is %02d/%02d/%04d, %02d:%02d:%02d\n",
+ rtc_wakealarm.time.tm_mon + 1, rtc_wakealarm.time.tm_mday,
+ rtc_wakealarm.time.tm_year + 1900, rtc_wakealarm.time.tm_hour,
+ rtc_wakealarm.time.tm_min, rtc_wakealarm.time.tm_sec);
+ }
+ } else if (strncmp(cmdline, "setwakealarm", 12) == 0) {
+ fprintf(stderr, "\nSetting alarm interrupt...Press Ctrl+C to abort\n\n");
+ fflush(stderr);
+
+ /* Point past the string and one whitespace */
+ cmdline += 13;
+ ret = sscanf(cmdline, "%02d/%02d/%04d, %02d:%02d:%02d",
+ &rtc_wakealarm.time.tm_mon, &rtc_wakealarm.time.tm_mday,
+ &rtc_wakealarm.time.tm_year, &rtc_wakealarm.time.tm_hour,
+ &rtc_wakealarm.time.tm_min, &rtc_wakealarm.time.tm_sec);
+
+ if (ret < 6) {
+ fprintf(stderr, "\nPlease check your input\n");
+ return;
+ }
+
+ /* months should be in the range 0 to 11 */
+ rtc_wakealarm.time.tm_mon -= 1;
+ /* years should be number of years since 1900 */
+ rtc_wakealarm.time.tm_year -= 1900;
+
+ /* Enable wake alarm interrupt */
+ rtc_wakealarm.enabled = 1;
+
+ /* Set pending to 0 */
+ rtc_wakealarm.pending = 1;
+
+ /* Set handler for SIGINT */
+ signal(SIGINT, alarminthandler);
+
+ ret = ioctl(rtc_fd, RTC_WKALM_SET, &rtc_wakealarm);
+ if (ret == -1) {
+ perror("RTC_WKALM_SET ioctl");
+ return;
+ }
+
+ while (1) {
+ ret = ioctl(rtc_fd, RTC_WKALM_RD, &rtc_wakealarm);
+ if (ret == -1) {
+ perror("RTC_WKALM_RD ioctl");
+ return;
+ }
+
+ if (!rtc_wakealarm.enabled) {
+ /* We could be here either because we received the alarm
+ * interrupt, or the SIGINT handler was executed. To
+ * differentiate between the two cases, we use the flag.
+ */
+ if (!signal_recvd)
+ fprintf(stderr, "\nReceived alarm interrupt\n");
+ else
+ fprintf(stderr, "\nAborting...\n");
+
+ fflush(stderr);
+ break;
+ }
+ }
+
+ /* In case we did not receive a signal, and we fall through */
+ alarminthandler(SIGINT);
+ signal_recvd = 0;
+ } else if (strncmp(cmdline, "wakealarmoff", 12) == 0) {
+ fprintf(stderr, "Turning wake alarm interrupt off\n");
+ fflush(stderr);
+
+ ret = ioctl(rtc_fd, RTC_WKALM_RD, &rtc_wakealarm);
+ if (ret == -1) {
+ perror("RTC_WKALM_RD ioctl");
+ return;
+ }
+
+ /* Disable wake alarm */
+ rtc_wakealarm.enabled = 0;
+ rtc_wakealarm.pending = 0;
+ ret = ioctl(rtc_fd, RTC_WKALM_SET, &rtc_wakealarm);
+
+ if (ret == -1)
+ perror("RTC_WKALM_SET ioctl");
+ } else if (strncmp(cmdline, "getperiodicrate", 15) == 0) {
+ unsigned long rate;
+
+ ret = ioctl(rtc_fd, RTC_IRQP_READ, &rate);
+ if (ret == -1) {
+ if (errno == ENOTTY)
+ fprintf(stderr, "\nNo periodic interrupt support\n");
+ else
+ perror("RTC_IRQP_READ ioctl");
+
+ return;
+ }
+
+ fprintf(stderr, "\nPeriodic interrupt rate is %luHz\n", rate);
+ } else if (strncmp(cmdline, "setperiodicrate", 15) == 0) {
+ unsigned long rate;
+
+ cmdline += 16;
+
+ sscanf(cmdline, "%lu", &rate);
+ /* bounds check */
+ if (rate < 2 || rate > 8192) {
+ fprintf(stderr, "\nInvalid rate specified\n");
+ return;
+ }
+
+ /* the rate should be a power of 2 */
+ if (rate & (rate - 1)) {
+ fprintf(stderr, "\nInvalid rate. Only power of 2 allowed\n");
+ return;
+ }
+
+ ret = ioctl(rtc_fd, RTC_IRQP_SET, rate);
+ if (ret == -1) {
+ if (errno == ENOTTY)
+ fprintf(stderr, "\nCannot change periodic interrupt rate\n");
+ else
+ perror("RTC_IRQP_SET ioctl");
+
+ return;
+ }
+ } else if (strncmp(cmdline, "periodicinton", 13) == 0) {
+ /* Set default handler for SIGINT */
+ signal(SIGINT, periodicinthandler);
+
+ ret = ioctl(rtc_fd, RTC_PIE_ON, 0);
+ if (ret == -1) {
+ perror("RTC_PIE_ON ioctl");
+ return;
+ }
+
+ fprintf(stderr, "\nChecking periodic interrupt rate...Press Ctrl+C to abort\n\n");
+ fflush(stderr);
+
+ loop = 1;
+ while (loop) {
+ struct timeval tv = {5, 0};
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ FD_SET(rtc_fd, &readfds);
+
+ ret = select(rtc_fd + 1, &readfds, NULL, NULL, &tv);
+ if (ret == -1) {
+ if (errno != EINTR)
+ perror("select");
+
+ /* Break the loop */
+ loop = 0;
+ } else {
+ /* Non blocking read */
+ ret = read(rtc_fd, &data, sizeof(unsigned long));
+ if (ret == -1) {
+ perror("read");
+ loop = 0;
+ } else {
+ fprintf(stderr, ".");
+ irqcount++;
+ }
+ }
+ }
+
+ /* Turn off periodic interrupts */
+ ret = ioctl(rtc_fd, RTC_PIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_PIE_OFF ioctl");
+ } else if (strncmp(cmdline, "periodicintoff", 14) == 0) {
+ fprintf(stderr, "Turning periodic interrupt off\n");
+ fflush(stderr);
+
+ ret = ioctl(rtc_fd, RTC_PIE_OFF, 0);
+ if (ret == -1)
+ perror("RTC_PIE_OFF ioctl");
+ } else if (strncmp(cmdline, "license", 7) == 0) {
+ show_license();
+ } else if (strncmp(cmdline, "exit", 4) == 0) {
+ close(rtc_fd);
+ printf("\nExiting...\n");
+ exit(EXIT_SUCCESS);
+ } else {
+ printf("\nUnknown command\n");
+ print_usage();
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char *cmdline= NULL;
+
+ printf("RTC sample application version: %s\n", RTC_APP_VERSION);
+ printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "This sample application comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; type `license' for details.\n\n");
+
+ /* Handler for Ctrl+C */
+ signal(SIGINT, sighandler);
+
+ switch(argc) {
+ case 2:
+ rtc = argv[1];
+ /* FALL THROUGH */
+ case 1:
+ break;
+ default:
+ fprintf(stderr, "usage: rtc_test [rtcdev]\n");
+ return 1;
+ }
+
+ rtc_fd = open(rtc, O_RDONLY);
+ if (rtc_fd == -1) {
+ perror(rtc);
+ exit(errno);
+ }
+
+ while (1) {
+ cmdline = readline(show_prompt());
+ parse_cmd(cmdline);
+ /* Free the memory malloc'ed by readline */
+ free(cmdline);
+ }
+
+ /* Should never reach here */
+ return 0;
+}
diff --git a/meta-steppeeagle/recipes-applications/rtc-test/rtc-test_1.0.bb b/meta-steppeeagle/recipes-applications/rtc-test/rtc-test_1.0.bb
new file mode 100644
index 00000000..868c63c9
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/rtc-test/rtc-test_1.0.bb
@@ -0,0 +1,23 @@
+DESCRIPTION = "Sample application for AMD RTC driver"
+SECTION = "applications"
+LICENSE = "BSD"
+DEPENDS = "readline"
+LIC_FILES_CHKSUM = "file://rtc-test.c;md5=cdf9bfd59714d20025056dbfaaf31134"
+
+PR = "r1"
+PV = "1.0"
+
+SRC_URI = "file://rtc-test.c"
+
+S = "${WORKDIR}"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_compile() {
+ ${CC} rtc-test.c -o rtc-test -lreadline
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 rtc-test ${D}${bindir}
+}
diff --git a/meta-steppeeagle/recipes-applications/smbus-test/files/LICENSE b/meta-steppeeagle/recipes-applications/smbus-test/files/LICENSE
new file mode 100644
index 00000000..d159169d
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/smbus-test/files/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/meta-steppeeagle/recipes-applications/smbus-test/files/i2c-dev.h b/meta-steppeeagle/recipes-applications/smbus-test/files/i2c-dev.h
new file mode 100644
index 00000000..b9358174
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/smbus-test/files/i2c-dev.h
@@ -0,0 +1,335 @@
+/*
+ i2c-dev.h - i2c-bus driver, char device interface
+
+ Copyright (C) 1995-97 Simon G. Vogl
+ Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301 USA.
+*/
+
+/* $Id: i2c-dev.h 5894 2010-12-12 13:22:29Z khali $ */
+
+#ifndef LIB_I2CDEV_H
+#define LIB_I2CDEV_H
+
+#include <linux/types.h>
+#include <sys/ioctl.h>
+
+
+/* -- i2c.h -- */
+
+
+/*
+ * I2C Message - used for pure i2c transaction, also from /dev interface
+ */
+struct i2c_msg {
+ __u16 addr; /* slave address */
+ unsigned short flags;
+#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
+#define I2C_M_RD 0x01
+#define I2C_M_NOSTART 0x4000
+#define I2C_M_REV_DIR_ADDR 0x2000
+#define I2C_M_IGNORE_NAK 0x1000
+#define I2C_M_NO_RD_ACK 0x0800
+ short len; /* msg length */
+ char *buf; /* pointer to msg data */
+};
+
+/* To determine what functionality is present */
+
+#define I2C_FUNC_I2C 0x00000001
+#define I2C_FUNC_10BIT_ADDR 0x00000002
+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */
+#define I2C_FUNC_SMBUS_PEC 0x00000008
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_SMBUS_QUICK 0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
+
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+ I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+
+/* Old name, for compatibility */
+#define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for PEC */
+};
+
+/* smbus_access read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+
+/* ----- commands for the ioctl like i2c_command call:
+ * note that additional calls are defined in the algorithm and hw
+ * dependent layers - these can be listed here, or see the
+ * corresponding header files.
+ */
+ /* -> bit-adapter specific ioctls */
+#define I2C_RETRIES 0x0701 /* number of times a device address */
+ /* should be polled when not */
+ /* acknowledging */
+#define I2C_TIMEOUT 0x0702 /* set timeout - call with int */
+
+
+/* this is for i2c-dev.c */
+#define I2C_SLAVE 0x0703 /* Change slave address */
+ /* Attn.: Slave address is 7 or 10 bits */
+#define I2C_SLAVE_FORCE 0x0706 /* Change slave address */
+ /* Attn.: Slave address is 7 or 10 bits */
+ /* This changes the address, even if it */
+ /* is already taken! */
+#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
+
+#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
+#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
+#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
+
+#define I2C_SMBUS 0x0720 /* SMBus-level access */
+
+/* -- i2c.h -- */
+
+
+/* Note: 10-bit addresses are NOT supported! */
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+ char read_write;
+ __u8 command;
+ int size;
+ union i2c_smbus_data *data;
+};
+
+/* This is the structure as used in the I2C_RDWR ioctl call */
+struct i2c_rdwr_ioctl_data {
+ struct i2c_msg *msgs; /* pointers to i2c_msgs */
+ int nmsgs; /* number of i2c_msgs */
+};
+
+
+static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ struct i2c_smbus_ioctl_data args;
+
+ args.read_write = read_write;
+ args.command = command;
+ args.size = size;
+ args.data = data;
+ return ioctl(file,I2C_SMBUS,&args);
+}
+
+
+static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
+{
+ return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte(int file)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
+{
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
+ I2C_SMBUS_BYTE,NULL);
+}
+
+static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BYTE_DATA,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
+}
+
+static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
+ __u8 value)
+{
+ union i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BYTE_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
+{
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_WORD_DATA,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+static inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
+ __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WORD_DATA, &data);
+}
+
+static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_PROC_CALL,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
+}
+
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
+ __u8 *values)
+{
+ union i2c_smbus_data data;
+ int i;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BLOCK_DATA,&data))
+ return -1;
+ else {
+ for (i = 1; i <= data.block[0]; i++)
+ values[i-1] = data.block[i];
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
+ __u8 length, const __u8 *values)
+{
+ union i2c_smbus_data data;
+ int i;
+ if (length > 32)
+ length = 32;
+ for (i = 1; i <= length; i++)
+ data.block[i] = values[i-1];
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+/* Returns the number of read bytes */
+/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
+ ask for less than 32 bytes, your code will only work with kernels
+ 2.6.23 and later. */
+static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+ int i;
+
+ if (length > 32)
+ length = 32;
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
+ I2C_SMBUS_I2C_BLOCK_DATA,&data))
+ return -1;
+ else {
+ for (i = 1; i <= data.block[0]; i++)
+ values[i-1] = data.block[i];
+ return data.block[0];
+ }
+}
+
+static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
+ __u8 length,
+ const __u8 *values)
+{
+ union i2c_smbus_data data;
+ int i;
+ if (length > 32)
+ length = 32;
+ for (i = 1; i <= length; i++)
+ data.block[i] = values[i-1];
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
+}
+
+/* Returns the number of read bytes */
+static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
+ __u8 length, __u8 *values)
+{
+ union i2c_smbus_data data;
+ int i;
+ if (length > 32)
+ length = 32;
+ for (i = 1; i <= length; i++)
+ data.block[i] = values[i-1];
+ data.block[0] = length;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_PROC_CALL,&data))
+ return -1;
+ else {
+ for (i = 1; i <= data.block[0]; i++)
+ values[i-1] = data.block[i];
+ return data.block[0];
+ }
+}
+
+
+#endif /* LIB_I2CDEV_H */
diff --git a/meta-steppeeagle/recipes-applications/smbus-test/files/smbus-test.c b/meta-steppeeagle/recipes-applications/smbus-test/files/smbus-test.c
new file mode 100644
index 00000000..128c5391
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/smbus-test/files/smbus-test.c
@@ -0,0 +1,632 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <dirent.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include <readline/readline.h>
+
+#include "i2c-dev.h"
+
+#define SMBUS_APP_VERSION "0.1"
+
+static int adapter_nr = -1;
+static int slave_addr = 0xFF;
+static char filename[20];
+static int fd = -1;
+
+char *show_prompt(void)
+{
+ return "$ ";
+}
+
+void sighandler(int sig)
+{
+ printf("\n%s", show_prompt());
+}
+
+void show_license(void)
+{
+ printf("/*****************************************************************************\n"
+ "*\n"
+ "* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "* All rights reserved.\n"
+ "*\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
+ "* modification, are permitted provided that the following conditions are met:\n"
+ "* * Redistributions of source code must retain the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer.\n"
+ "* * Redistributions in binary form must reproduce the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer in the\n"
+ "* documentation and/or other materials provided with the distribution.\n"
+ "* * Neither the name of Advanced Micro Devices, Inc. nor the names of\n"
+ "* its contributors may be used to endorse or promote products derived\n"
+ "* from this software without specific prior written permission.\n"
+ "*\n"
+ "* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n"
+ "* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
+ "* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
+ "* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY\n"
+ "* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
+ "* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+ "* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"
+ "* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+ "* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*\n"
+ "*\n"
+ "***************************************************************************/\n");
+}
+
+void print_usage(void)
+{
+ printf("\nCommands Supported ->\n");
+ printf(" enumerate : List all adapters available\n");
+ printf(" setadapternum <num> : Set the adapter number\n");
+ printf(" getadapternum : Get the current adapter number\n");
+ printf(" setslaveaddr <addr> : Set the slave device address\n");
+ printf(" getslaveaddr : Get the current slave device address\n");
+ printf(" getadapterfunc : Displays the functionalities supported by the adapter\n");
+ printf(" quicksend <bit> : Sends a single bit (0 or 1) to the device\n");
+ printf(" receivebyte : Receive a single byte from the slave device\n");
+ printf(" sendbyte <byte> : Sends a single byte to the slave device\n");
+ printf(" readbyte <register> : Reads a byte at register of the slave device\n");
+ printf(" writebyte <register> <byte> : Writes a byte at register of the slave device\n");
+ printf(" readword <register> : Reads a word at register of the slave device\n");
+ printf(" writeword <register> <word> : Writes a word at register of the slave device\n");
+ printf(" readblock <register> : Reads a block of data from register of the slave device\n");
+ printf(" writeblock <register> <filename> : Writes a block of data read from filename to register\n"
+ " of the slave device\n");
+ printf(" license : Displays the terms of LICENSE for this application\n");
+ printf(" help : Displays help text\n");
+ printf(" exit : Exits the application\n\n");
+}
+
+void parse_cmd(const char *cmdline)
+{
+ struct i2c_smbus_ioctl_data param;
+ union i2c_smbus_data smbus_data;
+ unsigned long funcs;
+
+ if (strncmp(cmdline, "enumerate", 9) == 0) {
+ DIR *dir;
+ struct dirent *dir_entry;
+ int adapter_found = 0;
+
+ /* Get the directory handle */
+ if ((dir = opendir("/dev")) == NULL) {
+ printf("Failed to open directory /dev. Probably you "
+ "do not have right privilege!\n\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Iterate over all the directory entries */
+ while ((dir_entry = readdir(dir)) != NULL) {
+ /*
+ * If the file is a character device, and its signature
+ * matches i2c-x, then we print the corresponding file.
+ */
+ if ((dir_entry->d_type == DT_CHR) &&
+ (strncmp(dir_entry->d_name, "i2c-", 4) == 0)) {
+ printf("%s\n", dir_entry->d_name);
+ adapter_found = 1;
+ }
+ }
+
+ printf("\n");
+
+ /*
+ * In case we did not find even a single adapter, we print a
+ * message and exit.
+ */
+ if (!adapter_found) {
+ printf("No adapters found, load i2c-dev kernel module and try again\n\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (strncmp(cmdline, "setadapternum", 13) == 0) {
+ int input;
+ int file_desc;
+
+ cmdline += 14;
+ if (sscanf(cmdline, "%d", &input) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ snprintf(filename, 19, "/dev/i2c-%d", input);
+ file_desc = open(filename, O_RDWR);
+ if (file_desc < 0) {
+ printf("Error opening file %s\n\n", filename);
+ return;
+ }
+
+ /* Once we have validated inputs, we store them into the global
+ * variables used at other places in the program.
+ */
+ fd = file_desc;
+ adapter_nr = input;
+ printf("Adapter Number set to %d\n\n", adapter_nr);
+ } else if (strncmp(cmdline, "getadapternum", 13) == 0) {
+ if (adapter_nr == -1)
+ printf("Adapter Number not set\n\n");
+ else
+ printf("Adapter Number set to %d\n\n", adapter_nr);
+ } else if (strncmp(cmdline, "setslaveaddr", 12) == 0) {
+ int addr;
+
+ cmdline += 13;
+ if (sscanf(cmdline, "0x%x", &addr) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ /* Set the slave address */
+ if (ioctl(fd, I2C_SLAVE, addr) < 0) {
+ printf("Error setting slave address. Please make sure "
+ "to provide 7-bit slave address\n\n");
+ return;
+ }
+
+ slave_addr = addr;
+ printf("Slave Address set to 0x%x\n\n", slave_addr);
+ } else if (strncmp(cmdline, "getslaveaddr", 12) == 0) {
+ if (slave_addr == 0xFF)
+ printf("Slave Address not set\n\n");
+ else
+ printf("Slave Address set to 0x%x\n\n", slave_addr);
+ } else if (strncmp(cmdline, "getadapterfunc", 14) == 0) {
+ if (adapter_nr == -1) {
+ printf("Please set adapter first\n\n");
+ return;
+ }
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (funcs & I2C_FUNC_I2C)
+ printf("I2C_FUNC_I2C\n");
+ if (funcs & I2C_FUNC_10BIT_ADDR)
+ printf("I2C_FUNC_10BIT_ADDR\n");
+ if (funcs & I2C_FUNC_PROTOCOL_MANGLING)
+ printf("I2C_FUNC_PROTOCOL_MANGLING\n");
+ if (funcs & I2C_FUNC_SMBUS_PEC)
+ printf("I2C_FUNC_SMBUS_PEC\n");
+ if (funcs & I2C_FUNC_SMBUS_BLOCK_PROC_CALL)
+ printf("I2C_FUNC_SMBUS_BLOCK_PROC_CALL\n");
+ if (funcs & I2C_FUNC_SMBUS_QUICK)
+ printf("I2C_FUNC_SMBUS_QUICK\n");
+ if (funcs & I2C_FUNC_SMBUS_READ_BYTE)
+ printf("I2C_FUNC_SMBUS_READ_BYTE\n");
+ if (funcs & I2C_FUNC_SMBUS_WRITE_BYTE)
+ printf("I2C_FUNC_SMBUS_WRITE_BYTE\n");
+ if (funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)
+ printf("I2C_FUNC_SMBUS_READ_BYTE_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+ printf("I2C_FUNC_SMBUS_WRITE_BYTE_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)
+ printf("I2C_FUNC_SMBUS_READ_WORD_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+ printf("I2C_FUNC_SMBUS_WRITE_WORD_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_PROC_CALL)
+ printf("I2C_FUNC_SMBUS_PROC_CALL\n");
+ if (funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA)
+ printf("I2C_FUNC_SMBUS_READ_BLOCK_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+ printf("I2C_FUNC_SMBUS_WRITE_BLOCK_DATA\n");
+ if (funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK)
+ printf("I2C_FUNC_SMBUS_READ_I2C_BLOCK\n");
+ if (funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+ printf("I2C_FUNC_SMBUS_WRITE_I2C_BLOCK\n");
+
+ printf("\n");
+ } else if (strncmp(cmdline, "quicksend", 9) == 0) {
+ int bit;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
+ printf("SMBus Quick command not supported by the adapter\n\n");
+ return;
+ }
+
+ cmdline += 10;
+ if (sscanf(cmdline, "%d", &bit) < 1) {
+ printf("Invalid input, please try again\n\n");
+ return;
+ }
+
+ /* Sanity check */
+ if ((bit != 0) && (bit != 1)) {
+ printf("Only 0 or 1 is allowed\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ param.data = NULL;
+
+ if (bit)
+ param.read_write = I2C_SMBUS_READ;
+ else
+ param.read_write = I2C_SMBUS_WRITE;
+
+ param.size = I2C_SMBUS_QUICK;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Quick command failed\n\n");
+ return;
+ }
+
+ printf("Quick Send %d successfull\n\n", bit);
+ } else if (strncmp(cmdline, "receivebyte", 11) == 0) {
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BYTE)) {
+ printf("SMBus receivebyte command not supported by adapter\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.read_write = I2C_SMBUS_READ;
+ param.size = I2C_SMBUS_BYTE;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Receive Byte command failed\n\n");
+ return;
+ }
+
+ printf("Byte Received 0x%x\n\n", param.data->byte);
+ } else if (strncmp(cmdline, "sendbyte", 8) == 0) {
+ int byte;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BYTE)) {
+ printf("SMBus sendbyte command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 9;
+ if (sscanf(cmdline, "0x%x", &byte) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ param.data = NULL;
+
+ param.read_write = I2C_SMBUS_WRITE;
+ param.command = byte;
+ param.size = I2C_SMBUS_BYTE;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Send Byte command failed\n\n");
+ return;
+ }
+
+ printf("Sent 0x%x to slave\n\n", byte);
+ } else if (strncmp(cmdline, "readbyte", 8) == 0) {
+ int reg;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BYTE_DATA)) {
+ printf("SMBus readbyte command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 9;
+ if (sscanf(cmdline, "0x%x", &reg) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_READ;
+ param.size = I2C_SMBUS_BYTE_DATA;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Read Byte Data command failed\n\n");
+ return;
+ }
+
+ printf("Read 0x%x at register 0x%x of the slave\n\n", param.data->byte, reg);
+ } else if (strncmp(cmdline, "writebyte", 9) == 0) {
+ int reg, byte;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BYTE_DATA)) {
+ printf("SMBus writebyte command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 10;
+ if (sscanf(cmdline, "0x%x 0x%x", &reg, &byte) < 2) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_WRITE;
+ param.size = I2C_SMBUS_BYTE_DATA;
+ param.data->byte = byte;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Write Byte Data command failed\n\n");
+ return;
+ }
+
+ printf("Written 0x%x to register 0x%x of the slave\n\n", byte, reg);
+ } else if (strncmp(cmdline, "readword", 8) == 0) {
+ int reg;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_WORD_DATA)) {
+ printf("SMBus readword command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 9;
+ if (sscanf(cmdline, "0x%x", &reg) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_READ;
+ param.size = I2C_SMBUS_WORD_DATA;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Read Word Data command failed\n\n");
+ return;
+ }
+
+ printf("Read 0x%.4x at register 0x%x of the slave\n\n", param.data->word, reg);
+ } else if (strncmp(cmdline, "writeword", 9) == 0) {
+ int reg, word;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_WORD_DATA)) {
+ printf("SMBus writeword command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 10;
+ if (sscanf(cmdline, "0x%x 0x%x", &reg, &word) < 2) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_WRITE;
+ param.size = I2C_SMBUS_WORD_DATA;
+ param.data->word = word;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Write Word Data command failed\n\n");
+ return;
+ }
+
+ printf("Written 0x%x to register 0x%x of the slave\n\n", word, reg);
+ } else if (strncmp(cmdline, "readblock", 9) == 0) {
+ int reg;
+ int i;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BLOCK_DATA)) {
+ printf("SMBus readblock command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 10;
+ if (sscanf(cmdline, "0x%x", &reg) < 1) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_READ;
+ param.size = I2C_SMBUS_BLOCK_DATA;
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Read Block Data command failed\n\n");
+ return;
+ }
+
+ printf("Reading %d bytes from register 0x%x:\n", param.data->block[0], reg);
+ for (i = 1; i <= param.data->block[0]; i++)
+ printf("0x%.2x ", param.data->block[i]);
+ printf("\n\n");
+ } else if (strncmp(cmdline, "writeblock", 10) == 0) {
+ int reg;
+ char infile[256];
+ FILE *file;
+ int data;
+ int num_bytes = 0;
+ int i;
+
+ /* Get the adapter functionality */
+ if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
+ printf("Error getting adapter functionalities\n\n");
+ return;
+ }
+
+ if (!(funcs & I2C_FUNC_SMBUS_BLOCK_DATA)) {
+ printf("SMBus writeblock command not supported by adapter\n");
+ return;
+ }
+
+ cmdline += 11;
+ if (sscanf(cmdline, "0x%x %s", &reg, infile) < 2) {
+ printf("Invalid inputs, please try again\n\n");
+ return;
+ }
+
+ /* open infile for reading */
+ if ((file = fopen(infile, "r")) == NULL) {
+ printf("Failed to open file %s\n\n", infile);
+ return;
+ }
+
+ /* setup parameters to the IOCTL call */
+ memset(&param, 0, sizeof(struct i2c_smbus_ioctl_data));
+ memset(&smbus_data, 0, sizeof(union i2c_smbus_data));
+ param.data = &smbus_data;
+
+ param.command = reg;
+ param.read_write = I2C_SMBUS_WRITE;
+ param.size = I2C_SMBUS_BLOCK_DATA;
+
+ /*
+ * populate block data to be sent to the device. SMBus sets a
+ * limit of 32 bytes to be sent or received in a block.
+ */
+ for (i = 1; i <= 32; i++) {
+ if (fscanf(file, "0x%x ", &data) == EOF)
+ break;
+
+ param.data->block[i] = data;
+ num_bytes++;
+ }
+
+ /* The very first block data should be the number of bytes
+ * in the block.
+ */
+ param.data->block[0] = num_bytes;
+
+ printf("Writing %d bytes to register 0x%.2x of device\n\n",
+ param.data->block[0], reg);
+
+ /* Execute block write command */
+ if (ioctl(fd, I2C_SMBUS, &param) == -1) {
+ printf("SMBus Write Block Data command failed\n\n");
+ return;
+ }
+
+ fclose(file);
+ } else if (strncmp(cmdline, "license", 7) == 0) {
+ show_license();
+ } else if (strncmp(cmdline, "exit", 4) == 0) {
+ printf("\nExiting...\n");
+ if((fd != -1) && (close(fd) < 0))
+ printf("Error closing device\n\n");
+
+ exit(EXIT_SUCCESS);
+ } else if (strncmp(cmdline, "help", 4) == 0) {
+ print_usage();
+ } else {
+ printf("\nUnknown command\n");
+ print_usage();
+ }
+}
+
+int main(void)
+{
+ char *cmdline= NULL;
+
+ printf("SMBus sample application version: %s\n", SMBUS_APP_VERSION);
+ printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "This sample application comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; type `license` for details.\n\n");
+
+ /* Handler for Ctrl+C */
+ signal(SIGINT, sighandler);
+
+ while (1) {
+ cmdline = readline(show_prompt());
+ parse_cmd(cmdline);
+ /* Free the memory malloc'ed by readline */
+ free(cmdline);
+ }
+
+ /* Should never reach here */
+ return 0;
+}
diff --git a/meta-steppeeagle/recipes-applications/smbus-test/smbus-test_1.0.bb b/meta-steppeeagle/recipes-applications/smbus-test/smbus-test_1.0.bb
new file mode 100644
index 00000000..2347b74d
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/smbus-test/smbus-test_1.0.bb
@@ -0,0 +1,27 @@
+DESCRIPTION = "Sample application for AMD SMBUS driver"
+SECTION = "applications"
+LICENSE = "BSD | GPLv2"
+DEPENDS = "readline"
+LIC_FILES_CHKSUM = "file://smbus-test.c;md5=51840771157718d4d562329e476d6917 \
+ file://i2c-dev.h;md5=11afa8583cd78137a63feb1a8b24cc51 \
+ "
+
+PR = "r1"
+PV = "1.0"
+
+SRC_URI = "file://smbus-test.c \
+ file://i2c-dev.h \
+ "
+
+S = "${WORKDIR}"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_compile() {
+ ${CC} smbus-test.c -o smbus-test -lreadline
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 smbus-test ${D}${bindir}
+}
diff --git a/meta-steppeeagle/recipes-applications/spi-test/files/spirom-test.c b/meta-steppeeagle/recipes-applications/spi-test/files/spirom-test.c
new file mode 100644
index 00000000..1c48f7c4
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/spi-test/files/spirom-test.c
@@ -0,0 +1,641 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+
+#include "spirom.h"
+
+#define SPI_APP_VERSION "0.1"
+
+#define WREN 0x06
+#define WRDI 0x04
+#define RDSR 0x05
+#define RDID 0x9F
+#define CHIP_ERASE 0x60
+#define SECTOR_ERASE 0x20
+#define BLOCK_ERASE 0xD8
+#define READ 0x03
+#define WRITE 0x02
+
+static void pabort(const char *s)
+{
+ perror(s);
+ abort();
+}
+
+static const char *device = "/dev/spirom0.0";
+static char command[20];
+static int inputfile_fd;
+static int outfile_fd;;
+static unsigned long address;
+static unsigned int num_bytes;
+
+void show_license(void)
+{
+ printf("/*****************************************************************************\n"
+ "*\n"
+ "* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "* All rights reserved.\n"
+ "*\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
+ "* modification, are permitted provided that the following conditions are met:\n"
+ "* * Redistributions of source code must retain the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer.\n"
+ "* * Redistributions in binary form must reproduce the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer in the\n"
+ "* documentation and/or other materials provided with the distribution.\n"
+ "* * Neither the name of Advanced Micro Devices, Inc. nor the names of\n"
+ "* its contributors may be used to endorse or promote products derived\n"
+ "* from this software without specific prior written permission.\n"
+ "*\n"
+ "* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n"
+ "* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
+ "* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
+ "* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY\n"
+ "* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
+ "* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+ "* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"
+ "* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+ "* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*\n"
+ "*\n"
+ "***************************************************************************/\n");
+}
+
+void parse_command(int fd)
+{
+ uint8_t cmd_byte;
+ struct spi_ioc_transfer tr;
+ unsigned int bytes_chunks;
+ unsigned int remaining_bytes;
+ int ret;
+
+ /* Zero initialize spi_ioc_transfer */
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ if ((strncmp(command, "WREN", 4) == 0) ||
+ (strncmp(command, "wren", 4) == 0)) {
+ /* Command without data */
+ tr.buf[0] = WREN;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ } else if ((strncmp(command, "WRDI", 4) == 0) ||
+ (strncmp(command, "wrdi", 4) == 0)) {
+ /* Command without data */
+ tr.buf[0] = WRDI;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ } else if ((strncmp(command, "CHIPERASE", 4) == 0) ||
+ (strncmp(command, "chiperase", 4) == 0)) {
+
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("cannot execute command, write is disabled\n");
+ exit(1);
+ }
+
+ /* Command without data */
+ tr.buf[0] = CHIP_ERASE;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* Make sure WIP has been reset */
+ while (1) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if ((tr.buf[1] & 0x01) == 0x00)
+ break;
+ }
+ } else if ((strncmp(command, "RDSR", 4) == 0) ||
+ (strncmp(command, "rdsr", 4) == 0)) {
+ /* Command with response */
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /*
+ * The 1-byte response will be stored in tr.buf,
+ * so print it out
+ */
+ printf("command: 0x%.2x response: 0x%.2x\n", tr.buf[0],
+ tr.buf[1]);
+ } else if ((strncmp(command, "RDID", 4) == 0) ||
+ (strncmp(command, "rdid", 4) == 0)) {
+ /* Command with response */
+ tr.buf[0] = RDID;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 3;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /*
+ * The 3-bytes response will be stored in tr.buf,
+ * so print it out
+ */
+ printf("command: 0x%.2x response: 0x%.2x%.2x%.2x\n", tr.buf[0],
+ tr.buf[1], tr.buf[2], tr.buf[3]);
+ } else if ((strncmp(command, "SECTORERASE", 6) ==0) ||
+ (strncmp(command, "sectorerase", 6) ==0)) {
+ int i;
+
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("cannot execute command, write is disabled\n");
+ exit(1);
+ }
+
+ /*
+ * num_bytes here is a little bit of misnomer, it indicates the
+ * number of sectors to be erased, rather than the number of
+ * bytes to be erased.
+ */
+ for (i = 0; i < num_bytes; i++) {
+ /* Write Enable before Sector Erase */
+ tr.buf[0] = WREN;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* Command with address but no data */
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = SECTOR_ERASE;
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.addr_present = 1;
+ tr.direction = 0;
+ tr.len = 0;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* point to the next 4k block */
+ address += 4 * 1024;
+
+ /*
+ * Before the next loop, we need to make sure that WIP
+ * bit in the output of RDSR has been reset.
+ */
+ while (1) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if ((tr.buf[1] & 0x01) == 0x00)
+ break;
+ }
+ }
+ } else if ((strncmp(command, "BLOCKERASE", 5) == 0) ||
+ (strncmp(command, "blockerase", 5) == 0)) {
+ int i;
+
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("cannot execute command, write is disabled\n");
+ exit(1);
+ }
+
+ /*
+ * num_bytes indicates the number of blocks to be erased,
+ * rather than the number of bytes to be erased.
+ */
+ for (i = 0; i < num_bytes; i++) {
+ /* Write Enable before Block Erase */
+ tr.buf[0] = WREN;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* Command with address but no data */
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = BLOCK_ERASE;
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.addr_present = 1;
+ tr.direction = 0;
+ tr.len = 0;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* point to the next 64k block */
+ address += 64 * 1024;
+
+ /*
+ * Before the next loop, we need to make sure that WIP
+ * bit in the output of RDSR has been reset.
+ */
+ while (1) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if ((tr.buf[1] & 0x01) == 0x00)
+ break;
+ }
+ }
+ } else if ((strncmp(command, "READ", 4) == 0) ||
+ (strncmp(command, "read", 4) ==0)) {
+ int i;
+
+ /*
+ * We will break down the bytes to be received in chunks of
+ * of 64-bytes. Data might not be a even multiple of 64. So
+ * in that case, we will have some remaining bytes <64. We
+ * handle that separately.
+ */
+ bytes_chunks = num_bytes / 64;
+ remaining_bytes = num_bytes % 64;
+
+ for (i = 0; i < bytes_chunks; i++) {
+ /* Command with address and data */
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = READ;
+ tr.direction = RECEIVE;
+ /*
+ * We will store the address into the buffer in little
+ * endian order.
+ */
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.len = 64;
+ tr.addr_present = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* Write the data read to output file */
+ if (write(outfile_fd, &tr.buf[4], tr.len) < 0) {
+ perror("write error");
+ exit(1);
+ }
+ address += 64;
+ }
+
+ if (remaining_bytes) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = READ;
+ tr.direction = RECEIVE;
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.len = remaining_bytes;
+ tr.addr_present = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if (write(outfile_fd, &tr.buf[4], tr.len) < 0) {
+ perror("write error");
+ exit(1);
+ }
+ }
+ } else if ((strncmp(command, "WRITE", 5) == 0) ||
+ (strncmp(command, "write", 5) ==0)) {
+ int i;
+
+ /*
+ * We will break down the bytes to be transmitted in chunks of
+ * of 64-bytes. Like for read, we might not have data in an
+ * even multiple of 64 bytes. So we will handle the remaining
+ * bytes in the end.
+ */
+
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+ else if ((tr.buf[1] & 0x02) == 0x00) {
+ printf("cannot execute command, write is disabled\n");
+ exit(1);
+ }
+
+ bytes_chunks = num_bytes / 64;
+ remaining_bytes = num_bytes % 64;
+
+ for (i = 0; i < bytes_chunks; i++) {
+ tr.buf[0] = WREN;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ /* Command with data and address */
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = WRITE;
+ tr.direction = TRANSMIT;
+ /*
+ * We will store the address into the buffer in little
+ * endian order.
+ */
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.len = 64;
+ tr.addr_present = 1;
+
+ /* Read 64 bytes from inputfile to buffer */
+ if (read(inputfile_fd, &tr.buf[4], tr.len) < 0) {
+ perror("read error");
+ exit(1);
+ }
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ address += 64;
+
+ /*
+ * Before the next loop, we need to make sure that WIP
+ * bit in the output of RDSR has been reset.
+ */
+ while (1) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if ((tr.buf[1] & 0x01) == 0x00)
+ break;
+ }
+ }
+
+ if (remaining_bytes) {
+ tr.buf[0] = WREN;
+ tr.direction = 0;
+ tr.len = 0;
+ tr.addr_present = 0;
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = WRITE;
+ tr.direction = TRANSMIT;
+ tr.buf[3] = address & 0xff;
+ tr.buf[2] = (address >> 8) & 0xff;
+ tr.buf[1] = (address >> 16) & 0xff;
+ tr.len = remaining_bytes;
+ tr.addr_present = 1;
+
+ if (read(inputfile_fd, &tr.buf[4], tr.len) < 0) {
+ perror("read error");
+ exit(1);
+ }
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ while (1) {
+ memset(&tr, 0, sizeof(struct spi_ioc_transfer));
+ tr.buf[0] = RDSR;
+ tr.direction = RECEIVE;
+ tr.addr_present = 0;
+ tr.len = 1;
+
+ ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ if (ret < 1)
+ pabort("can't send spi message");
+
+ if ((tr.buf[1] & 0x01) == 0x00)
+ break;
+ }
+ }
+ } else
+ pabort("Unrecognized command, please try again.\n");
+}
+
+static void print_usage(const char *prog)
+{
+ printf("\nUsage: sudo %s [-DCAnio] [arguments]\n\n", prog);
+ puts(" -D --device SPI ROM device to use\n"
+ " (default /dev/spirom0.0)\n\n"
+ " -C --command command to send to the device\n"
+ " (WREN/WRDI/RDSR/RDID/CHIPERASE/SECTORERASE/\n"
+ " BLOCKERASE/READ/WRITE)\n\n"
+ " -A --address offset in decimal, into the device to read\n"
+ " from or write to. For a ROM size of 8MB,\n"
+ " address can go from 0 to 8388608. Negative\n"
+ " offsets are not valid, but the program\n"
+ " won't complain and convert it to its\n"
+ " unsigned equivalent.\n\n"
+ " -n --num-bytes number of bytes to be read from or written\n"
+ " to. Depending on the address, this can\n"
+ " take values from 0 to 8388608 for a ROM\n"
+ " size of 8MB.\n\n"
+ " In case of SECTORERASE and BLOCKERASE\n"
+ " commands, num-bytes actually takes the\n"
+ " number of sectors and blocks to be erased\n"
+ " respectively, rather than the number of\n"
+ " bytes.\n\n"
+ " -i --input-file file to be used as input.\n\n"
+ " -o --output-file file to be used for output. Remember that if\n"
+ " an existing filename is given, its contents\n"
+ " will be overwritten.\n"
+ " -l --license displays the terms of LICENSE for this application\n\n");
+ exit(1);
+}
+
+static void parse_opts(int argc, char *argv[])
+{
+ if (argc == 1)
+ print_usage(argv[0]);
+
+ while (1) {
+ static const struct option lopts[] = {
+ { "device", 1, 0, 'D' },
+ { "command", 1, 0, 'C' },
+ { "address", 1, 0, 'A' },
+ { "num-bytes", 1, 0, 'n' },
+ { "input-file", 1, 0, 'i' },
+ { "output-file", 1, 0, 'o' },
+ { "license", 0, 0, 'l' },
+ { NULL, 0, 0, 0 },
+ };
+ int c;
+
+ c = getopt_long(argc, argv, "D:C:A:n:i:o:l", lopts, NULL);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'D':
+ device = optarg;
+ break;
+ case 'C':
+ memset(command, sizeof(command), 0);
+ strncpy(command, optarg, sizeof(command));
+ break;
+ case 'A':
+ address = atol(optarg);
+ break;
+ case 'n':
+ num_bytes = atoi(optarg);
+ break;
+ case 'i':
+ inputfile_fd = open(optarg, O_RDONLY);
+ if (inputfile_fd < 0) {
+ printf("Error opening %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'o':
+ outfile_fd = open(optarg, O_WRONLY | O_CREAT |
+ O_TRUNC, 0644);
+ if(outfile_fd < 0) {
+ printf("Error opening %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'l':
+ show_license();
+ exit(0);;
+ default:
+ print_usage(argv[0]);
+ break;
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ int fd;
+
+ printf("SPI sample application version: %s\n", SPI_APP_VERSION);
+ printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "This sample application comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; type `license' for details.\n\n");
+
+ parse_opts(argc, argv);
+
+ fd = open(device, O_RDWR);
+ if (fd < 0)
+ pabort("can't open device");
+
+ parse_command(fd);
+
+ return ret;
+}
diff --git a/meta-steppeeagle/recipes-applications/spi-test/files/spirom.h b/meta-steppeeagle/recipes-applications/spi-test/files/spirom.h
new file mode 100644
index 00000000..750719a6
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/spi-test/files/spirom.h
@@ -0,0 +1,43 @@
+#ifndef SPIROM_H
+#define SPIROM_H
+
+#include <linux/types.h>
+
+/*---------------------------------------------------------------------------*/
+
+/* IOCTL commands */
+
+#define SPI_IOC_MAGIC 'k'
+
+#define TRANSMIT 1
+#define RECEIVE 2
+
+/*
+ * struct spi_ioc_transfer - interface structure between application and ioctl
+ *
+ * @buf: Buffer to hold 1-byte command, 3-bytes address, and 64-byte data for
+ * transmit or receive. The internal FIFO of our controller can hold a
+ * maximum of 70 bytes, including the address. But here we assume the
+ * maximum data excluding address to be 64-bytes long.
+ *
+ * @direction: Direction of data transfer, either TRANSMIT or RECEIVE.
+ *
+ * @len: Length of data excluding command and address.
+ *
+ * @addr_present: Flag to indicate whether 'buf' above contains an address.
+ */
+struct spi_ioc_transfer {
+ __u8 buf[64 + 1 + 3];
+ __u8 direction;
+ __u8 len;
+ __u8 addr_present;
+};
+
+/* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
+#define SPI_MSGSIZE(N) \
+ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
+ ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
+#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
+
+
+#endif /* SPIROM_H */
diff --git a/meta-steppeeagle/recipes-applications/spi-test/spi-test_1.0.bb b/meta-steppeeagle/recipes-applications/spi-test/spi-test_1.0.bb
new file mode 100644
index 00000000..83593cb4
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/spi-test/spi-test_1.0.bb
@@ -0,0 +1,27 @@
+DESCRIPTION = "Sample application for AMD SPI driver"
+SECTION = "applications"
+LICENSE = "BSD"
+DEPENDS = "readline"
+LIC_FILES_CHKSUM = "file://spirom-test.c;md5=c6d80587d583668ffbfb5828abd58878 \
+ file://spirom.h;md5=56f117ed31b82b02182c7a491364d112 \
+ "
+
+PR = "r1"
+PV = "1.0"
+
+SRC_URI = "file://spirom-test.c \
+ file://spirom.h \
+ "
+
+S = "${WORKDIR}"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_compile() {
+ ${CC} spirom-test.c -o spirom-test -lreadline
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 spirom-test ${D}${bindir}
+}
diff --git a/meta-steppeeagle/recipes-applications/watchdog-test/files/watchdog-test.c b/meta-steppeeagle/recipes-applications/watchdog-test/files/watchdog-test.c
new file mode 100644
index 00000000..77124784
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/watchdog-test/files/watchdog-test.c
@@ -0,0 +1,288 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <readline/readline.h>
+#include <linux/watchdog.h>
+
+#define WATCHDOG_APP_VERSION "0.1"
+
+int fd; /* /dev/watchdog file descriptor */
+volatile int ping;
+
+char *show_prompt(void)
+{
+ return "$ ";
+}
+
+void sighandler(int sig)
+{
+ printf("\n%s", show_prompt());
+}
+
+void pinghandler(int sig)
+{
+ ping = 0;
+ printf("\n");
+ /* Set the signal handler back to the original */
+ signal(SIGINT, sighandler);
+}
+
+void show_license(void)
+{
+ printf("/*****************************************************************************\n"
+ "*\n"
+ "* Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "* All rights reserved.\n"
+ "*\n"
+ "* Redistribution and use in source and binary forms, with or without\n"
+ "* modification, are permitted provided that the following conditions are met:\n"
+ "* * Redistributions of source code must retain the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer.\n"
+ "* * Redistributions in binary form must reproduce the above copyright\n"
+ "* notice, this list of conditions and the following disclaimer in the\n"
+ "* documentation and/or other materials provided with the distribution.\n"
+ "* * Neither the name of Advanced Micro Devices, Inc. nor the names of\n"
+ "* its contributors may be used to endorse or promote products derived\n"
+ "* from this software without specific prior written permission.\n"
+ "*\n"
+ "* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n"
+ "* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
+ "* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
+ "* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY\n"
+ "* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n"
+ "* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n"
+ "* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n"
+ "* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+ "* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+ "*\n"
+ "*\n"
+ "***************************************************************************/\n");
+}
+
+void print_usage()
+{
+ printf("\nCommands Supported ->\n");
+ printf(" disablewatchdog : Disables the Watchdog Timer\n");
+ printf(" enablewatchdog : Enables the Watchdog Timer\n");
+ printf(" getfeatures : Shows the features supported by the Watchdog implementation\n");
+ printf(" getstatus : Gives the current status of Watchdog Timer\n");
+ printf(" getbootstatus : Displays the status of Watchdog Hardware after reboot or fresh boot\n");
+ printf(" ping : Resets Watchdog Timer at regular intervals\n");
+ printf(" gettimeout : Gives the value of Watchdog timeout (in frequency units)\n");
+ printf(" gettimeleft : Gives the current value of Watchdog Timer (in frequency units)\n");
+ printf(" sendmagicchar : Sends the magic character 'V' to the Watchdog device\n");
+ printf(" settimeout <timeout> : Sets the new value for Watchdog timeout (in frequency units)\n");
+ printf(" license : Displays the terms of LICENSE for this application\n");
+ printf(" help : Displays help text\n");
+ printf(" exit : Exits the application\n\n");
+}
+
+void parse_cmd(const char *cmdline)
+{
+ if (strncmp(cmdline, "help", 4) == 0)
+ print_usage();
+ else if (strncmp(cmdline, "disablewatchdog", 7) == 0) {
+ int flags;
+
+ printf("\nDisabling watchdog timer...\n");
+ flags = WDIOS_DISABLECARD;
+ if (ioctl(fd, WDIOC_SETOPTIONS, &flags) < 0)
+ perror("Could not disable watchdog");
+ } else if (strncmp(cmdline, "enablewatchdog", 6) == 0) {
+ int flags;
+
+ printf("\nEnabling watchdog timer...\n");
+ flags = WDIOS_ENABLECARD;
+ if (ioctl(fd, WDIOC_SETOPTIONS, &flags) < 0)
+ printf("Could not enable watchdog");
+ } else if (strncmp(cmdline, "getfeatures", 10) == 0) {
+ struct watchdog_info info;
+
+ if(ioctl(fd, WDIOC_GETSUPPORT, &info) < 0)
+ perror("Could not get watchdog features");
+
+ printf("\nIdentity:\t\t%s\n", info.identity);
+ printf("Firmware Version:\t%u\n", info.firmware_version);
+ printf("Options Set: \n"
+ "%s%s%s%s%s%s%s%s%s%s%s\n",
+ info.options & WDIOF_OVERHEAT ? "\t\t\tReset due to CPU overheat\n": "",
+ info.options & WDIOF_FANFAULT ? "\t\t\tFan failed\n": "",
+ info.options & WDIOF_EXTERN1 ? "\t\t\tExternal relay 1\n": "",
+ info.options & WDIOF_EXTERN2 ? "\t\t\tExternal relay 2\n": "",
+ info.options & WDIOF_POWERUNDER ? "\t\t\tPower bad/power fault\n": "",
+ info.options & WDIOF_CARDRESET ? "\t\t\tCard previously reset the CPU\n": "",
+ info.options & WDIOF_POWEROVER ? "\t\t\tPower over voltage\n": "",
+ info.options & WDIOF_SETTIMEOUT ? "\t\t\tSet timeout (in frequency units)\n": "",
+ info.options & WDIOF_MAGICCLOSE ? "\t\t\tSupports magic close character\n": "",
+ info.options & WDIOF_PRETIMEOUT ? "\t\t\tPretimeout (in frequency units)\n": "",
+ info.options & WDIOF_KEEPALIVEPING ? "\t\t\tKeep alive ping reply\n": "");
+ } else if (strncmp(cmdline, "getstatus", 9) == 0) {
+ int status;
+
+ printf("\n");
+ if(ioctl(fd, WDIOC_GETSTATUS, &status) < 0)
+ perror("Could not get watchdog status");
+
+ if (status & (1 << 0))
+ printf("\nWatchdog device is active\n");
+ if (status & (1 << 1))
+ printf("Watchdog device opened via /dev/watchdog\n");
+ if (status & (1 << 2))
+ printf("Received magic char\n");
+ if (status & (1 << 3))
+ printf("nowayout set\n");
+ if (status & (1 << 4))
+ printf("Watchdog device unregistered\n");
+ } else if (strncmp(cmdline, "getbootstatus", 7) == 0) {
+ int bootstatus;
+
+ if(ioctl(fd, WDIOC_GETBOOTSTATUS, &bootstatus) < 0)
+ perror("Could not get bootstatus");
+
+ printf("\nbootstatus: \n"
+ "%s%s%s%s%s%s%s%s%s%s%s\n",
+ bootstatus & WDIOF_OVERHEAT ? "\t\t\tReset due to CPU overheat\n": "",
+ bootstatus & WDIOF_FANFAULT ? "\t\t\tFan failed\n": "",
+ bootstatus & WDIOF_EXTERN1 ? "\t\t\tExternal relay 1\n": "",
+ bootstatus & WDIOF_EXTERN2 ? "\t\t\tExternal relay 2\n": "",
+ bootstatus & WDIOF_POWERUNDER ? "\t\t\tPower bad/power fault\n": "",
+ bootstatus & WDIOF_CARDRESET ? "\t\t\tCard previously reset the CPU\n": "",
+ bootstatus & WDIOF_POWEROVER ? "\t\t\tPower over voltage\n": "",
+ bootstatus & WDIOF_SETTIMEOUT ? "\t\t\tSet timeout (in frequency units)\n": "",
+ bootstatus & WDIOF_MAGICCLOSE ? "\t\t\tSupports magic close character\n": "",
+ bootstatus & WDIOF_PRETIMEOUT ? "\t\t\tPretimeout (in frequency units)\n": "",
+ bootstatus & WDIOF_KEEPALIVEPING ? "\t\t\tKeep alive ping reply\n": "");
+ } else if (strncmp(cmdline, "ping", 4) == 0) {
+ int dummy;
+
+ printf("\nContinuosly resetting Watchdog...press Ctrl+C to stop\n");
+ printf("\nOnce you stop pinging, Watchog Timer will start counting down...\n");
+ printf("...If the Watchdog Timer was enabled\n");
+
+ /* Lets set a different handler for Ctrl+C */
+ signal(SIGINT, pinghandler);
+
+ ping = 1;
+ while (ping) {
+ if(ioctl(fd, WDIOC_KEEPALIVE, &dummy) < 0) {
+ perror("Error sending ping");
+ break;
+ }
+ sleep(1);
+ }
+ } else if (strncmp(cmdline, "gettimeout", 10) == 0) {
+ int timeout;
+
+ if(ioctl(fd, WDIOC_GETTIMEOUT, &timeout) < 0)
+ perror("Error getting watchdog timeout");
+
+ printf("\nCurrent setting of timeout is %d frequency units\n", timeout);
+ } else if (strncmp(cmdline, "gettimeleft", 11) == 0) {
+ int timeleft;
+
+ if(ioctl(fd, WDIOC_GETTIMELEFT, &timeleft) < 0)
+ perror("Error getting watchdog timeleft");
+
+ printf("\nTime left for system reboot/shutdown is %d frequency units\n", timeleft);
+ } else if (strncmp(cmdline, "sendmagicchar", 9) == 0) {
+ printf("\nSending magic character to Watchdog device...\n");
+ printf("\nWatchdog Timer will be stopped once you exit the application\n");
+ if(write(fd, "V", 1) < 0)
+ perror("Could not send magic character");
+ } else if (strncmp(cmdline, "settimeout", 10) == 0) {
+ const char *charp = cmdline;
+ int timeout;
+
+ /* Lets point to the end of first token */
+ charp += strlen("settimeout");
+ /* Skip blank characters */
+ while (*charp == ' ' || *charp == '\t' || *charp == '\n')
+ charp++;
+
+ /* Now we should be pointing to the first 'digit' character */
+ timeout = atoi(charp);
+
+ if(ioctl(fd, WDIOC_SETTIMEOUT, &timeout) < 0) {
+ perror("Could not set watchdog timeout");
+ return;
+ }
+
+ printf("\nSetting timeout to %d frequency units\n", timeout);
+ printf("Watchdog Timer will start counting down with the new timeout value\n");
+ } else if (strncmp(cmdline, "license", 7) == 0) {
+ show_license();
+ } else if (strncmp(cmdline, "exit", 4) == 0) {
+ printf("\nExiting...\n");
+ printf("\nIf the Watchdog Timer was not disabled, and you did not send the magic character,\n"
+ "Watchdog Timer is still ticking, and your system will reboot soon\n");
+
+ if(close(fd) < 0)
+ perror("Error closing /dev/watchdog");
+ exit(EXIT_SUCCESS);
+ } else {
+ printf("\nUnknown command\n");
+ print_usage();
+ }
+}
+
+int main(void)
+{
+ char *cmdline= NULL;
+
+ printf("Watchdog sample application version: %s\n", WATCHDOG_APP_VERSION);
+ printf("Copyright (c) 2014, Advanced Micro Devices, Inc.\n"
+ "This sample application comes with ABSOLUTELY NO WARRANTY;\n"
+ "This is free software, and you are welcome to redistribute it\n"
+ "under certain conditions; type `license' for details.\n\n");
+
+
+ if ((fd = open("/dev/watchdog", O_WRONLY)) < 0) {
+ perror("Could not open /dev/watchdog");
+ exit(1);
+ }
+
+ /* Handler for Ctrl+C */
+ signal(SIGINT, sighandler);
+
+ while (1) {
+ cmdline = readline(show_prompt());
+ parse_cmd(cmdline);
+ /* Free the memory malloc'ed by readline */
+ free(cmdline);
+ }
+
+ /* Should never reach here */
+ return 0;
+}
diff --git a/meta-steppeeagle/recipes-applications/watchdog-test/watchdog-test_1.0.bb b/meta-steppeeagle/recipes-applications/watchdog-test/watchdog-test_1.0.bb
new file mode 100644
index 00000000..43d511d0
--- /dev/null
+++ b/meta-steppeeagle/recipes-applications/watchdog-test/watchdog-test_1.0.bb
@@ -0,0 +1,23 @@
+DESCRIPTION = "Sample application for AMD Watchdog driver"
+SECTION = "applications"
+LICENSE = "BSD"
+DEPENDS = "readline"
+LIC_FILES_CHKSUM = "file://watchdog-test.c;md5=47ff70acbf47e0bf894330dee1143414"
+
+PR = "r1"
+PV = "1.0"
+
+SRC_URI = "file://watchdog-test.c"
+
+S = "${WORKDIR}"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+do_compile() {
+ ${CC} watchdog-test.c -o watchdog-test -lreadline
+}
+
+do_install() {
+ install -d ${D}${bindir}
+ install -m 0755 watchdog-test ${D}${bindir}
+}
diff --git a/meta-steppeeagle/recipes-bsp/formfactor/formfactor/steppeeagle/machconfig b/meta-steppeeagle/recipes-bsp/formfactor/formfactor/steppeeagle/machconfig
new file mode 100644
index 00000000..28ca080e
--- /dev/null
+++ b/meta-steppeeagle/recipes-bsp/formfactor/formfactor/steppeeagle/machconfig
@@ -0,0 +1,3 @@
+# Assume a USB mouse and keyboard are connected
+HAVE_TOUCHSCREEN=n
+HAVE_KEYBOARD=y
diff --git a/meta-steppeeagle/recipes-bsp/formfactor/formfactor_0.0.bbappend b/meta-steppeeagle/recipes-bsp/formfactor/formfactor_0.0.bbappend
new file mode 100644
index 00000000..6d4804d1
--- /dev/null
+++ b/meta-steppeeagle/recipes-bsp/formfactor/formfactor_0.0.bbappend
@@ -0,0 +1,2 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
diff --git a/meta-steppeeagle/recipes-core/llvm/llvm3.4.inc b/meta-steppeeagle/recipes-core/llvm/llvm3.4.inc
new file mode 100644
index 00000000..a416dfd8
--- /dev/null
+++ b/meta-steppeeagle/recipes-core/llvm/llvm3.4.inc
@@ -0,0 +1,49 @@
+#
+# Since we need LLVM 3.4 but meta-oe currently only supports
+# 3.3, override the minimum bits needed to get it to work.
+# Eventually this will need to be reconciled with upstream
+#
+
+# Ideally this would be done as a patch but since llvm3.inc already
+# manipulates this file with sed we have to do similar. We also need
+# to do this as an append to ensure proper sequencing.
+do_configure_append_x86-64() {
+ # Fix paths in llvm-config
+ sed -ri "s#lib/${LLVM_DIR}#lib64/${LLVM_DIR}#g" ${S}/tools/llvm-config/llvm-config.cpp
+}
+
+#
+# Override the do_install() provided by llvm3.inc to use the lib64
+# directory naming.
+#
+# This should probably be cleaned up at some point in the stock LLVM
+# sources but at the moment they do not appear to handle lib64 very well.
+#
+do_install() {
+ cd ${LLVM_BUILD_DIR}
+ oe_runmake DESTDIR=${LLVM_INSTALL_DIR} install
+
+ mv ${LLVM_INSTALL_DIR}${bindir}/${HOST_SYS}-llvm-config-host ${LLVM_INSTALL_DIR}/llvm-config-host
+
+ install -d ${D}${bindir}/${LLVM_DIR}
+ mv ${LLVM_INSTALL_DIR}${bindir}/* ${D}${bindir}/${LLVM_DIR}/
+
+ install -d ${D}${includedir}/${LLVM_DIR}
+ mv ${LLVM_INSTALL_DIR}${includedir}/* ${D}${includedir}/${LLVM_DIR}/
+
+ install -d ${D}${libdir}/${LLVM_DIR}
+
+ # The LLVM sources have "/lib" embedded and so we cannot completely rely on the ${libdir} variable
+ if [ -d ${LLVM_INSTALL_DIR}${libdir}/ ]; then
+ mv ${LLVM_INSTALL_DIR}${libdir}/* ${D}${libdir}/${LLVM_DIR}/
+ elif [ -d ${LLVM_INSTALL_DIR}${prefix}/lib ]; then
+ mv ${LLVM_INSTALL_DIR}${prefix}/lib/* ${D}${libdir}/${LLVM_DIR}/
+ elif [ -d ${LLVM_INSTALL_DIR}${prefix}/lib64 ]; then
+ mv ${LLVM_INSTALL_DIR}${prefix}/lib64/* ${D}${libdir}/${LLVM_DIR}/
+ fi
+
+ ln -s ${LLVM_DIR}/libLLVM-${PV}.so ${D}${libdir}/libLLVM-${PV}.so
+
+ install -d ${D}${docdir}/${LLVM_DIR}
+ mv ${LLVM_INSTALL_DIR}${prefix}/docs/llvm/* ${D}${docdir}/${LLVM_DIR}
+}
diff --git a/meta-steppeeagle/recipes-core/llvm/llvm3.4/0001-R600-SI-Add-processor-type-for-Mullins.patch b/meta-steppeeagle/recipes-core/llvm/llvm3.4/0001-R600-SI-Add-processor-type-for-Mullins.patch
new file mode 100644
index 00000000..d267c29a
--- /dev/null
+++ b/meta-steppeeagle/recipes-core/llvm/llvm3.4/0001-R600-SI-Add-processor-type-for-Mullins.patch
@@ -0,0 +1,12 @@
+R600/SI: Add processor type for Mullins.
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+diff -Naur a/lib/Target/R600/Processors.td b/lib/Target/R600/Processors.td
+--- a/lib/Target/R600/Processors.td 2013-11-15 05:16:00.000000000 +0530
++++ b/lib/Target/R600/Processors.td 2014-04-26 01:22:39.105011843 +0530
+@@ -52,3 +52,4 @@
+ def : Proc<"kabini", SI_Itin, [FeatureSeaIslands]>;
+ def : Proc<"kaveri", SI_Itin, [FeatureSeaIslands]>;
+ def : Proc<"hawaii", SI_Itin, [FeatureSeaIslands]>;
++def : Proc<"mullins", SI_Itin, [FeatureSeaIslands]>;
diff --git a/meta-steppeeagle/recipes-core/llvm/llvm3.4/arm_fenv_uclibc.patch b/meta-steppeeagle/recipes-core/llvm/llvm3.4/arm_fenv_uclibc.patch
new file mode 100644
index 00000000..c3ae4946
--- /dev/null
+++ b/meta-steppeeagle/recipes-core/llvm/llvm3.4/arm_fenv_uclibc.patch
@@ -0,0 +1,14 @@
+Index: llvm-2.9/include/llvm/Support/FEnv.h
+===================================================================
+--- llvm-2.9.orig/include/llvm/Support/FEnv.h 2010-11-29 20:44:50.000000000 +0100
++++ llvm-2.9/include/llvm/Support/FEnv.h 2011-11-18 18:42:22.580161297 +0100
+@@ -17,6 +17,9 @@
+
+ #include "llvm/Config/config.h"
+ #include <cerrno>
++
++#undef HAVE_FENV_H
++
+ #ifdef HAVE_FENV_H
+ #include <fenv.h>
+ #endif
diff --git a/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bb b/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bb
new file mode 100644
index 00000000..e59f508a
--- /dev/null
+++ b/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bb
@@ -0,0 +1,19 @@
+require recipes-core/llvm/llvm.inc
+require recipes-core/llvm/llvm3.inc
+require llvm3.4.inc
+
+LIC_FILES_CHKSUM = "file://LICENSE.TXT;md5=71df953c321b5b31ae94316a7fb6a7f3"
+
+DEPENDS += "zlib"
+EXTRA_OECONF += "--enable-zlib"
+
+S = "${WORKDIR}/llvm-${PV}"
+
+SRC_URI += "file://0001-R600-SI-Add-processor-type-for-Mullins.patch"
+
+SRC_URI_append_libc-uclibc = " file://arm_fenv_uclibc.patch "
+SRC_URI[md5sum] = "46ed668a1ce38985120dbf6344cf6116"
+SRC_URI[sha256sum] = "25a5612d692c48481b9b397e2b55f4870e447966d66c96d655241702d44a2628"
+
+PACKAGECONFIG ??= ""
+PACKAGECONFIG[r600] = "--enable-experimental-targets=R600,,,"
diff --git a/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bbappend b/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bbappend
new file mode 100644
index 00000000..e648dcab
--- /dev/null
+++ b/meta-steppeeagle/recipes-core/llvm/llvm3.4_3.4.bbappend
@@ -0,0 +1 @@
+PACKAGECONFIG_append_steppeeagle = "r600"
diff --git a/meta-steppeeagle/recipes-graphics/drm/libdrm/0001-radeon-add-Mullins-chip-family.patch b/meta-steppeeagle/recipes-graphics/drm/libdrm/0001-radeon-add-Mullins-chip-family.patch
new file mode 100644
index 00000000..97f9c354
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/drm/libdrm/0001-radeon-add-Mullins-chip-family.patch
@@ -0,0 +1,26 @@
+From 0ca3b79c21c1db04d442b09654e4cc2d7d956276 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Thu, 17 Apr 2014 14:30:08 -0400
+Subject: [PATCH 1/2] radeon: add Mullins chip family
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ radeon/radeon_surface.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
+index 15127d4..109bd6b 100644
+--- a/radeon/radeon_surface.c
++++ b/radeon/radeon_surface.c
+@@ -80,6 +80,7 @@ enum radeon_family {
+ CHIP_KAVERI,
+ CHIP_KABINI,
+ CHIP_HAWAII,
++ CHIP_MULLINS,
+ CHIP_LAST,
+ };
+
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/drm/libdrm/0002-radeon-add-Mullins-pci-ids.patch b/meta-steppeeagle/recipes-graphics/drm/libdrm/0002-radeon-add-Mullins-pci-ids.patch
new file mode 100644
index 00000000..c5a22269
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/drm/libdrm/0002-radeon-add-Mullins-pci-ids.patch
@@ -0,0 +1,42 @@
+From 532a41b72641791df14f3a7b49f6b9ebd9fe5022 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Tue, 12 Nov 2013 15:39:31 -0500
+Subject: [PATCH 2/2] radeon: add Mullins pci ids
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ radeon/r600_pci_ids.h | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/radeon/r600_pci_ids.h b/radeon/r600_pci_ids.h
+index 37fb61c..de25f16 100644
+--- a/radeon/r600_pci_ids.h
++++ b/radeon/r600_pci_ids.h
+@@ -425,6 +425,23 @@ CHIPSET(0x983D, KABINI_983D, KABINI)
+ CHIPSET(0x983E, KABINI_983E, KABINI)
+ CHIPSET(0x983F, KABINI_983F, KABINI)
+
++CHIPSET(0x9850, MULLINS_9850, MULLINS)
++CHIPSET(0x9851, MULLINS_9851, MULLINS)
++CHIPSET(0x9852, MULLINS_9852, MULLINS)
++CHIPSET(0x9853, MULLINS_9853, MULLINS)
++CHIPSET(0x9854, MULLINS_9854, MULLINS)
++CHIPSET(0x9855, MULLINS_9855, MULLINS)
++CHIPSET(0x9856, MULLINS_9856, MULLINS)
++CHIPSET(0x9857, MULLINS_9857, MULLINS)
++CHIPSET(0x9858, MULLINS_9858, MULLINS)
++CHIPSET(0x9859, MULLINS_9859, MULLINS)
++CHIPSET(0x985A, MULLINS_985A, MULLINS)
++CHIPSET(0x985B, MULLINS_985B, MULLINS)
++CHIPSET(0x985C, MULLINS_985C, MULLINS)
++CHIPSET(0x985D, MULLINS_985D, MULLINS)
++CHIPSET(0x985E, MULLINS_985E, MULLINS)
++CHIPSET(0x985F, MULLINS_985F, MULLINS)
++
+ CHIPSET(0x1304, KAVERI_1304, KAVERI)
+ CHIPSET(0x1305, KAVERI_1305, KAVERI)
+ CHIPSET(0x1306, KAVERI_1306, KAVERI)
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/drm/libdrm_git.bbappend b/meta-steppeeagle/recipes-graphics/drm/libdrm_git.bbappend
new file mode 100644
index 00000000..cb5ebffd
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/drm/libdrm_git.bbappend
@@ -0,0 +1,18 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRCREV = "e6ec4c88519da05eccc05ed2ae7ff20277e3672a"
+PV = "2.4.53+git${SRCPV}"
+
+SRC_URI += " \
+ file://0001-radeon-add-Mullins-chip-family.patch \
+ file://0002-radeon-add-Mullins-pci-ids.patch \
+ "
+
+PATCHTOOL = "git"
+
+EXTRA_OECONF += "--enable-optimized \
+ --disable-assertions \
+ --enable-shared \
+ --enable-targets=x86_64 \
+ --enable-experimental-targets=R600 \
+ --enable-bindings=none"
diff --git a/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Add-missing-data-files.patch b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Add-missing-data-files.patch
new file mode 100644
index 00000000..c7851035
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Add-missing-data-files.patch
@@ -0,0 +1,623 @@
+From 87f9a62329d7c5f4d351fbb63a41f2a1935fb2f1 Mon Sep 17 00:00:00 2001
+From: Drew Moseley <drew_moseley@mentor.com>
+Date: Mon, 12 May 2014 15:22:32 -0400
+Subject: [PATCH] mesa-demos: Add missing data files.
+
+Add some data files that are present in the git repository:
+ http://cgit.freedesktop.org/mesa/demos/tree/?id=mesa-demos-8.1.0
+but not in the release tarball
+ ftp://ftp.freedesktop.org/pub/mesa/demos/8.1.0/mesa-demos-8.1.0.tar.bz2
+
+Upstream-Status: Backport
+Signed-off-by: Drew Moseley <drew_moseley@mentor.com>
+---
+ src/fpglsl/depth-read.glsl | 4 +
+ src/fpglsl/infinite-loop.glsl | 7 +
+ src/glsl/CH11-bumpmaptex.frag | 47 +++++++
+ src/glsl/blinking-teapot.frag | 31 +++++
+ src/glsl/blinking-teapot.vert | 16 +++
+ src/glsl/convolution.frag | 21 +++
+ src/glsl/simplex-noise.glsl | 279 +++++++++++++++++++++++++++++++++++++++
+ src/glsl/skinning.vert | 24 ++++
+ src/perf/glslstateschange1.frag | 19 +++
+ src/perf/glslstateschange1.vert | 14 ++
+ src/perf/glslstateschange2.frag | 17 +++
+ src/perf/glslstateschange2.vert | 14 ++
+ src/vpglsl/infinite-loop.glsl | 8 ++
+ 13 files changed, 501 insertions(+)
+ create mode 100644 src/fpglsl/depth-read.glsl
+ create mode 100644 src/fpglsl/infinite-loop.glsl
+ create mode 100644 src/glsl/CH11-bumpmaptex.frag
+ create mode 100644 src/glsl/blinking-teapot.frag
+ create mode 100644 src/glsl/blinking-teapot.vert
+ create mode 100644 src/glsl/convolution.frag
+ create mode 100644 src/glsl/simplex-noise.glsl
+ create mode 100644 src/glsl/skinning.vert
+ create mode 100644 src/perf/glslstateschange1.frag
+ create mode 100644 src/perf/glslstateschange1.vert
+ create mode 100644 src/perf/glslstateschange2.frag
+ create mode 100644 src/perf/glslstateschange2.vert
+ create mode 100644 src/vpglsl/infinite-loop.glsl
+
+diff --git a/src/fpglsl/depth-read.glsl b/src/fpglsl/depth-read.glsl
+new file mode 100644
+index 0000000..86d298e
+--- /dev/null
++++ b/src/fpglsl/depth-read.glsl
+@@ -0,0 +1,4 @@
++void main()
++{
++ gl_FragColor = gl_FragCoord.zzzz;
++}
+diff --git a/src/fpglsl/infinite-loop.glsl b/src/fpglsl/infinite-loop.glsl
+new file mode 100644
+index 0000000..c6dc6ee
+--- /dev/null
++++ b/src/fpglsl/infinite-loop.glsl
+@@ -0,0 +1,7 @@
++void main() {
++ vec4 sum = vec4(0);
++ for (int i = 1; i != 2; i += 2) {
++ sum += vec4(0.1, 0.1, 0.1, 0.1);
++ }
++ gl_FragColor = sum;
++}
+diff --git a/src/glsl/CH11-bumpmaptex.frag b/src/glsl/CH11-bumpmaptex.frag
+new file mode 100644
+index 0000000..b5dabb4
+--- /dev/null
++++ b/src/glsl/CH11-bumpmaptex.frag
+@@ -0,0 +1,47 @@
++//
++// Fragment shader for procedural bumps
++//
++// Authors: John Kessenich, Randi Rost
++//
++// Copyright (c) 2002-2006 3Dlabs Inc. Ltd.
++//
++// See 3Dlabs-License.txt for license information
++//
++// Texture mapping/modulation added by Brian Paul
++//
++
++varying vec3 LightDir;
++varying vec3 EyeDir;
++
++uniform float BumpDensity; // = 16.0
++uniform float BumpSize; // = 0.15
++uniform float SpecularFactor; // = 0.5
++
++uniform sampler2D Tex;
++
++void main()
++{
++ vec3 ambient = vec3(0.25);
++ vec3 litColor;
++ vec2 c = BumpDensity * gl_TexCoord[0].st;
++ vec2 p = fract(c) - vec2(0.5);
++
++ float d, f;
++ d = p.x * p.x + p.y * p.y;
++ f = inversesqrt(d + 1.0);
++
++ if (d >= BumpSize)
++ { p = vec2(0.0); f = 1.0; }
++
++ vec3 SurfaceColor = texture2D(Tex, gl_TexCoord[0].st).xyz;
++
++ vec3 normDelta = vec3(p.x, p.y, 1.0) * f;
++ litColor = SurfaceColor * (ambient + max(dot(normDelta, LightDir), 0.0));
++ vec3 reflectDir = reflect(LightDir, normDelta);
++
++ float spec = max(dot(EyeDir, reflectDir), 0.0);
++ spec *= SpecularFactor;
++ litColor = min(litColor + spec, vec3(1.0));
++
++ gl_FragColor = vec4(litColor, 1.0);
++}
+diff --git a/src/glsl/blinking-teapot.frag b/src/glsl/blinking-teapot.frag
+new file mode 100644
+index 0000000..0db060b
+--- /dev/null
++++ b/src/glsl/blinking-teapot.frag
+@@ -0,0 +1,31 @@
++#extension GL_ARB_uniform_buffer_object : enable
++
++layout(std140) uniform colors0
++{
++ float DiffuseCool;
++ float DiffuseWarm;
++ vec3 SurfaceColor;
++ vec3 WarmColor;
++ vec3 CoolColor;
++ vec4 some[8];
++};
++
++varying float NdotL;
++varying vec3 ReflectVec;
++varying vec3 ViewVec;
++
++void main (void)
++{
++
++ vec3 kcool = min(CoolColor + DiffuseCool * SurfaceColor, 1.0);
++ vec3 kwarm = min(WarmColor + DiffuseWarm * SurfaceColor, 1.0);
++ vec3 kfinal = mix(kcool, kwarm, NdotL);
++
++ vec3 nreflect = normalize(ReflectVec);
++ vec3 nview = normalize(ViewVec);
++
++ float spec = max(dot(nreflect, nview), 0.0);
++ spec = pow(spec, 32.0);
++
++ gl_FragColor = vec4 (min(kfinal + spec, 1.0), 1.0);
++}
+diff --git a/src/glsl/blinking-teapot.vert b/src/glsl/blinking-teapot.vert
+new file mode 100644
+index 0000000..397d733
+--- /dev/null
++++ b/src/glsl/blinking-teapot.vert
+@@ -0,0 +1,16 @@
++vec3 LightPosition = vec3(0.0, 10.0, 4.0);
++
++varying float NdotL;
++varying vec3 ReflectVec;
++varying vec3 ViewVec;
++
++void main(void)
++{
++ vec3 ecPos = vec3 (gl_ModelViewMatrix * gl_Vertex);
++ vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
++ vec3 lightVec = normalize(LightPosition - ecPos);
++ ReflectVec = normalize(reflect(-lightVec, tnorm));
++ ViewVec = normalize(-ecPos);
++ NdotL = (dot(lightVec, tnorm) + 1.0) * 0.5;
++ gl_Position = ftransform();
++}
+diff --git a/src/glsl/convolution.frag b/src/glsl/convolution.frag
+new file mode 100644
+index 0000000..e49b8ac
+--- /dev/null
++++ b/src/glsl/convolution.frag
+@@ -0,0 +1,21 @@
++
++const int KernelSize = 9;
++
++//texture offsets
++uniform vec2 Offset[KernelSize];
++//convolution kernel
++uniform vec4 KernelValue[KernelSize];
++uniform sampler2D srcTex;
++uniform vec4 ScaleFactor;
++uniform vec4 BaseColor;
++
++void main(void)
++{
++ int i;
++ vec4 sum = vec4(0.0);
++ for (i = 0; i < KernelSize; ++i) {
++ vec4 tmp = texture2D(srcTex, gl_TexCoord[0].st + Offset[i]);
++ sum += tmp * KernelValue[i];
++ }
++ gl_FragColor = sum * ScaleFactor + BaseColor;
++}
+diff --git a/src/glsl/simplex-noise.glsl b/src/glsl/simplex-noise.glsl
+new file mode 100644
+index 0000000..b6833cb
+--- /dev/null
++++ b/src/glsl/simplex-noise.glsl
+@@ -0,0 +1,279 @@
++//
++// Description : Array and textureless GLSL 2D/3D/4D simplex
++// noise functions.
++// Author : Ian McEwan, Ashima Arts.
++// Maintainer : ijm
++// Lastmod : 20110223
++// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
++// Distributed under the Artistic License 2.0; See LICENCE file.
++//
++
++#define NORMALIZE_GRADIENTS
++#undef USE_CIRCLE
++#define COLLAPSE_SORTNET
++
++float permute(float x0,vec3 p) {
++ float x1 = mod(x0 * p.y, p.x);
++ return floor( mod( (x1 + p.z) *x0, p.x ));
++ }
++vec2 permute(vec2 x0,vec3 p) {
++ vec2 x1 = mod(x0 * p.y, p.x);
++ return floor( mod( (x1 + p.z) *x0, p.x ));
++ }
++vec3 permute(vec3 x0,vec3 p) {
++ vec3 x1 = mod(x0 * p.y, p.x);
++ return floor( mod( (x1 + p.z) *x0, p.x ));
++ }
++vec4 permute(vec4 x0,vec3 p) {
++ vec4 x1 = mod(x0 * p.y, p.x);
++ return floor( mod( (x1 + p.z) *x0, p.x ));
++ }
++
++uniform vec4 pParam;
++// Example
++// const vec4 pParam = vec4( 17.* 17., 34., 1., 7.);
++
++float taylorInvSqrt(float r)
++ {
++ return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r );
++ }
++
++float simplexNoise2(vec2 v)
++ {
++ const vec2 C = vec2(0.211324865405187134, // (3.0-sqrt(3.0))/6.;
++ 0.366025403784438597); // 0.5*(sqrt(3.0)-1.);
++ const vec3 D = vec3( 0., 0.5, 2.0) * 3.14159265358979312;
++// First corner
++ vec2 i = floor(v + dot(v, C.yy) );
++ vec2 x0 = v - i + dot(i, C.xx);
++
++// Other corners
++ vec2 i1 = (x0.x > x0.y) ? vec2(1.,0.) : vec2(0.,1.) ;
++
++ // x0 = x0 - 0. + 0. * C
++ vec2 x1 = x0 - i1 + 1. * C.xx ;
++ vec2 x2 = x0 - 1. + 2. * C.xx ;
++
++// Permutations
++ i = mod(i, pParam.x);
++ vec3 p = permute( permute(
++ i.y + vec3(0., i1.y, 1. ), pParam.xyz)
++ + i.x + vec3(0., i1.x, 1. ), pParam.xyz);
++
++#ifndef USE_CIRCLE
++// ( N points uniformly over a line, mapped onto a diamond.)
++ vec3 x = fract(p / pParam.w) ;
++ vec3 h = 0.5 - abs(x) ;
++
++ vec3 sx = vec3(lessThan(x,D.xxx)) *2. -1.;
++ vec3 sh = vec3(lessThan(h,D.xxx));
++
++ vec3 a0 = x + sx*sh;
++ vec2 p0 = vec2(a0.x,h.x);
++ vec2 p1 = vec2(a0.y,h.y);
++ vec2 p2 = vec2(a0.z,h.z);
++
++#ifdef NORMALISE_GRADIENTS
++ p0 *= taylorInvSqrt(dot(p0,p0));
++ p1 *= taylorInvSqrt(dot(p1,p1));
++ p2 *= taylorInvSqrt(dot(p2,p2));
++#endif
++
++ vec3 g = 2.0 * vec3( dot(p0, x0), dot(p1, x1), dot(p2, x2) );
++#else
++// N points around a unit circle.
++ vec3 phi = D.z * mod(p,pParam.w) /pParam.w ;
++ vec4 a0 = sin(phi.xxyy+D.xyxy);
++ vec2 a1 = sin(phi.zz +D.xy);
++ vec3 g = vec3( dot(a0.xy, x0), dot(a0.zw, x1), dot(a1.xy, x2) );
++#endif
++// mix
++ vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.);
++ m = m*m ;
++ return 1.66666* 70.*dot(m*m, g);
++ }
++
++float simplexNoise3(vec3 v)
++ {
++ const vec2 C = vec2(1./6. , 1./3. ) ;
++ const vec4 D = vec4(0., 0.5, 1.0, 2.0);
++
++// First corner
++ vec3 i = floor(v + dot(v, C.yyy) );
++ vec3 x0 = v - i + dot(i, C.xxx) ;
++
++// Other corners
++#ifdef COLLAPSE_SORTNET
++ vec3 g = vec3( greaterThan( x0.xyz, x0.yzx) );
++ vec3 l = vec3( lessThanEqual( x0.xyz, x0.yzx) );
++
++ vec3 i1 = g.xyz * l.zxy;
++ vec3 i2 = max( g.xyz, l.zxy);
++#else
++// Keeping this clean - let the compiler optimize.
++ vec3 q1;
++ q1.x = max(x0.x, x0.y);
++ q1.y = min(x0.x, x0.y);
++ q1.z = x0.z;
++
++ vec3 q2;
++ q2.x = max(q1.x,q1.z);
++ q2.z = min(q1.x,q1.z);
++ q2.y = q1.y;
++
++ vec3 q3;
++ q3.y = max(q2.y, q2.z);
++ q3.z = min(q2.y, q2.z);
++ q3.x = q2.x;
++
++ vec3 i1 = vec3(equal(q3.xxx, x0));
++ vec3 i2 = i1 + vec3(equal(q3.yyy, x0));
++#endif
++
++ // x0 = x0 - 0. + 0. * C
++ vec3 x1 = x0 - i1 + 1. * C.xxx;
++ vec3 x2 = x0 - i2 + 2. * C.xxx;
++ vec3 x3 = x0 - 1. + 3. * C.xxx;
++
++// Permutations
++ i = mod(i, pParam.x );
++ vec4 p = permute( permute( permute(
++ i.z + vec4(0., i1.z, i2.z, 1. ), pParam.xyz)
++ + i.y + vec4(0., i1.y, i2.y, 1. ), pParam.xyz)
++ + i.x + vec4(0., i1.x, i2.x, 1. ), pParam.xyz);
++
++// Gradients
++// ( N*N points uniformly over a square, mapped onto a octohedron.)
++ float n_ = 1.0/pParam.w ;
++ vec3 ns = n_ * D.wyz - D.xzx ;
++
++ vec4 j = p - pParam.w*pParam.w*floor(p * ns.z *ns.z); // mod(p,N*N)
++
++ vec4 x_ = floor(j * ns.z) ;
++ vec4 y_ = floor(j - pParam.w * x_ ) ; // mod(j,N)
++
++ vec4 x = x_ *ns.x + ns.yyyy;
++ vec4 y = y_ *ns.x + ns.yyyy;
++ vec4 h = 1. - abs(x) - abs(y);
++
++ vec4 b0 = vec4( x.xy, y.xy );
++ vec4 b1 = vec4( x.zw, y.zw );
++
++ vec4 s0 = vec4(lessThan(b0,D.xxxx)) *2. -1.;
++ vec4 s1 = vec4(lessThan(b1,D.xxxx)) *2. -1.;
++ vec4 sh = vec4(lessThan(h, D.xxxx));
++
++ vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
++ vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
++
++ vec3 p0 = vec3(a0.xy,h.x);
++ vec3 p1 = vec3(a0.zw,h.y);
++ vec3 p2 = vec3(a1.xy,h.z);
++ vec3 p3 = vec3(a1.zw,h.w);
++
++#ifdef NORMALISE_GRADIENTS
++ p0 *= taylorInvSqrt(dot(p0,p0));
++ p1 *= taylorInvSqrt(dot(p1,p1));
++ p2 *= taylorInvSqrt(dot(p2,p2));
++ p3 *= taylorInvSqrt(dot(p3,p3));
++#endif
++
++// Mix
++ vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.);
++ m = m * m;
++//used to be 64.
++ return 48.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
++ dot(p2,x2), dot(p3,x3) ) );
++ }
++
++vec4 grad4(float j, vec4 ip)
++ {
++ const vec4 ones = vec4(1.,1.,1.,-1.);
++ vec4 p,s;
++
++ p.xyz = floor( fract (vec3(j) * ip.xyz) *pParam.w) * ip.z -1.0;
++ p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
++ s = vec4(lessThan(p,vec4(0.)));
++ p.xyz = p.xyz + (s.xyz*2.-1.) * s.www;
++
++ return p;
++ }
++
++float simplexNoise4(vec4 v)
++ {
++ const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4
++ 0.309016994374947451); // (sqrt(5) - 1)/4 F4
++// First corner
++ vec4 i = floor(v + dot(v, C.yyyy) );
++ vec4 x0 = v - i + dot(i, C.xxxx);
++
++// Other corners
++
++// Force existance of strict total ordering in sort.
++ vec4 q0 = floor(x0 * 1024.0) + vec4( 0., 1./4., 2./4. , 3./4.);
++ vec4 q1;
++ q1.xy = max(q0.xy,q0.zw); // x:z y:w
++ q1.zw = min(q0.xy,q0.zw);
++
++ vec4 q2;
++ q2.xz = max(q1.xz,q1.yw); // x:y z:w
++ q2.yw = min(q1.xz,q1.yw);
++
++ vec4 q3;
++ q3.y = max(q2.y,q2.z); // y:z
++ q3.z = min(q2.y,q2.z);
++ q3.xw = q2.xw;
++
++ vec4 i1 = vec4(lessThanEqual(q3.xxxx, q0));
++ vec4 i2 = vec4(lessThanEqual(q3.yyyy, q0));
++ vec4 i3 = vec4(lessThanEqual(q3.zzzz, q0));
++
++ // x0 = x0 - 0. + 0. * C
++ vec4 x1 = x0 - i1 + 1. * C.xxxx;
++ vec4 x2 = x0 - i2 + 2. * C.xxxx;
++ vec4 x3 = x0 - i3 + 3. * C.xxxx;
++ vec4 x4 = x0 - 1. + 4. * C.xxxx;
++
++// Permutations
++ i = mod(i, pParam.x );
++ float j0 = permute( permute( permute( permute (
++ i.w, pParam.xyz) + i.z, pParam.xyz)
++ + i.y, pParam.xyz) + i.x, pParam.xyz);
++ vec4 j1 = permute( permute( permute( permute (
++ i.w + vec4(i1.w, i2.w, i3.w, 1. ), pParam.xyz)
++ + i.z + vec4(i1.z, i2.z, i3.z, 1. ), pParam.xyz)
++ + i.y + vec4(i1.y, i2.y, i3.y, 1. ), pParam.xyz)
++ + i.x + vec4(i1.x, i2.x, i3.x, 1. ), pParam.xyz);
++// Gradients
++// ( N*N*N points uniformly over a cube, mapped onto a 4-octohedron.)
++ vec4 ip = pParam ;
++ ip.xy *= pParam.w ;
++ ip.x *= pParam.w ;
++ ip = vec4(1.,1.,1.,2.) / ip ;
++
++ vec4 p0 = grad4(j0, ip);
++ vec4 p1 = grad4(j1.x, ip);
++ vec4 p2 = grad4(j1.y, ip);
++ vec4 p3 = grad4(j1.z, ip);
++ vec4 p4 = grad4(j1.w, ip);
++
++#ifdef NORMALISE_GRADIENTS
++ p0 *= taylorInvSqrt(dot(p0,p0));
++ p1 *= taylorInvSqrt(dot(p1,p1));
++ p2 *= taylorInvSqrt(dot(p2,p2));
++ p3 *= taylorInvSqrt(dot(p3,p3));
++ p4 *= taylorInvSqrt(dot(p4,p4));
++#endif
++
++// Mix
++ vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.);
++ vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.);
++ m0 = m0 * m0;
++ m1 = m1 * m1;
++ return 32. * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
++ + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;
++
++ }
++
++
++
+diff --git a/src/glsl/skinning.vert b/src/glsl/skinning.vert
+new file mode 100644
+index 0000000..28970ee
+--- /dev/null
++++ b/src/glsl/skinning.vert
+@@ -0,0 +1,24 @@
++// Vertex weighting/blendin shader
++// Brian Paul
++// 4 Nov 2008
++
++uniform mat4 mat0, mat1;
++attribute float weight;
++
++void main()
++{
++ // simple diffuse shading
++ // Note that we should really transform the normal vector along with
++ // the postion below... someday.
++ vec3 lightVec = vec3(0, 0, 1);
++ vec3 norm = gl_NormalMatrix * gl_Normal;
++ float dot = 0.2 + max(0.0, dot(norm, lightVec));
++ gl_FrontColor = vec4(dot);
++
++ // compute sum of weighted transformations
++ vec4 pos0 = mat0 * gl_Vertex;
++ vec4 pos1 = mat1 * gl_Vertex;
++ vec4 pos = mix(pos0, pos1, weight);
++
++ gl_Position = gl_ModelViewProjectionMatrix * pos;
++}
+diff --git a/src/perf/glslstateschange1.frag b/src/perf/glslstateschange1.frag
+new file mode 100644
+index 0000000..0839436
+--- /dev/null
++++ b/src/perf/glslstateschange1.frag
+@@ -0,0 +1,19 @@
++// Multi-texture fragment shader
++// Brian Paul
++
++// Composite second texture over first.
++// We're assuming the 2nd texture has a meaningful alpha channel.
++
++uniform sampler2D tex1;
++uniform sampler2D tex2;
++uniform vec4 UniV1;
++uniform vec4 UniV2;
++
++void main()
++{
++ vec4 t3;
++ vec4 t1 = texture2D(tex1, gl_TexCoord[0].xy);
++ vec4 t2 = texture2D(tex2, gl_TexCoord[1].xy);
++ t3 = mix(t1, t2, t2.w);
++ gl_FragColor = t3 + UniV1 + UniV2;
++}
+diff --git a/src/perf/glslstateschange1.vert b/src/perf/glslstateschange1.vert
+new file mode 100644
+index 0000000..cef50db
+--- /dev/null
++++ b/src/perf/glslstateschange1.vert
+@@ -0,0 +1,14 @@
++// Multi-texture vertex shader
++// Brian Paul
++
++
++attribute vec4 TexCoord0, TexCoord1;
++attribute vec4 VertCoord;
++
++void main()
++{
++ gl_TexCoord[0] = TexCoord0;
++ gl_TexCoord[1] = TexCoord1;
++ // note: may use gl_Vertex or VertCoord here for testing:
++ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
++}
+diff --git a/src/perf/glslstateschange2.frag b/src/perf/glslstateschange2.frag
+new file mode 100644
+index 0000000..0df0319
+--- /dev/null
++++ b/src/perf/glslstateschange2.frag
+@@ -0,0 +1,17 @@
++// Multi-texture fragment shader
++// Brian Paul
++
++// Composite second texture over first.
++// We're assuming the 2nd texture has a meaningful alpha channel.
++
++uniform sampler2D tex1;
++uniform sampler2D tex2;
++uniform vec4 UniV1;
++uniform vec4 UniV2;
++
++void main()
++{
++ vec4 t1 = texture2D(tex1, gl_TexCoord[0].xy);
++ vec4 t2 = texture2D(tex2, gl_TexCoord[1].xy);
++ gl_FragColor = t1 + t2 + UniV1 + UniV2;
++}
+diff --git a/src/perf/glslstateschange2.vert b/src/perf/glslstateschange2.vert
+new file mode 100644
+index 0000000..cef50db
+--- /dev/null
++++ b/src/perf/glslstateschange2.vert
+@@ -0,0 +1,14 @@
++// Multi-texture vertex shader
++// Brian Paul
++
++
++attribute vec4 TexCoord0, TexCoord1;
++attribute vec4 VertCoord;
++
++void main()
++{
++ gl_TexCoord[0] = TexCoord0;
++ gl_TexCoord[1] = TexCoord1;
++ // note: may use gl_Vertex or VertCoord here for testing:
++ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
++}
+diff --git a/src/vpglsl/infinite-loop.glsl b/src/vpglsl/infinite-loop.glsl
+new file mode 100644
+index 0000000..bc7ae4b
+--- /dev/null
++++ b/src/vpglsl/infinite-loop.glsl
+@@ -0,0 +1,8 @@
++void main() {
++ gl_Position = gl_Vertex;
++ vec4 sum = vec4(0);
++ for (int i = 1; i != 2; i += 2) {
++ sum += vec4(0.1, 0.1, 0.1, 0.1);
++ }
++ gl_FrontColor = sum;
++}
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Use-DEMOS_DATA_DIR-to-locate-data-files.patch b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Use-DEMOS_DATA_DIR-to-locate-data-files.patch
new file mode 100644
index 00000000..c89f8789
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos/0001-mesa-demos-Use-DEMOS_DATA_DIR-to-locate-data-files.patch
@@ -0,0 +1,234 @@
+From bc7fa67d13e8032601df5cf04e15c53a7204dcd7 Mon Sep 17 00:00:00 2001
+From: Drew Moseley <drew_moseley@mentor.com>
+Date: Fri, 9 May 2014 11:50:24 -0400
+Subject: [PATCH] mesa-demos: Use DEMOS_DATA_DIR to locate data files
+
+Upstream-Status: Submitted [https://bugs.freedesktop.org/show_bug.cgi?id=78496]
+Signed-off-by: Drew Moseley <drew_moseley@mentor.com>
+---
+ src/glsl/bezier.c | 2 +-
+ src/glsl/blinking-teapot.c | 4 ++--
+ src/glsl/brick.c | 4 ++--
+ src/glsl/bump.c | 6 +++---
+ src/glsl/convolutions.c | 2 +-
+ src/glsl/mandelbrot.c | 4 ++--
+ src/glsl/multitex.c | 4 ++--
+ src/glsl/simplex-noise.c | 2 +-
+ src/glsl/skinning.c | 4 ++--
+ src/glsl/texdemo1.c | 8 ++++----
+ src/glsl/toyball.c | 4 ++--
+ src/objviewer/objview.c | 12 ++++++------
+ src/perf/glslstateschange.c | 8 ++++----
+ 13 files changed, 32 insertions(+), 32 deletions(-)
+
+diff --git a/src/glsl/bezier.c b/src/glsl/bezier.c
+index 0b56bc1..e01603d 100644
+--- a/src/glsl/bezier.c
++++ b/src/glsl/bezier.c
+@@ -13,7 +13,7 @@
+ #include "glut_wrap.h"
+ #include "shaderutil.h"
+
+-static const char *filename = "bezier.geom";
++static const char *filename = DEMOS_DATA_DIR "bezier.geom";
+
+ static GLuint fragShader;
+ static GLuint vertShader;
+diff --git a/src/glsl/blinking-teapot.c b/src/glsl/blinking-teapot.c
+index e3bf24d..7662b1f 100644
+--- a/src/glsl/blinking-teapot.c
++++ b/src/glsl/blinking-teapot.c
+@@ -63,8 +63,8 @@ init_opengl (void)
+ exit(1);
+ }
+
+- vshad_id = CompileShaderFile (GL_VERTEX_SHADER, "blinking-teapot.vert");
+- fshad_id = CompileShaderFile (GL_FRAGMENT_SHADER, "blinking-teapot.frag");
++ vshad_id = CompileShaderFile (GL_VERTEX_SHADER, DEMOS_DATA_DIR "blinking-teapot.vert");
++ fshad_id = CompileShaderFile (GL_FRAGMENT_SHADER, DEMOS_DATA_DIR "blinking-teapot.frag");
+ prog_id = LinkShaders (vshad_id, fshad_id);
+
+ UseProgram (prog_id);
+diff --git a/src/glsl/brick.c b/src/glsl/brick.c
+index 3021856..fe5f190 100644
+--- a/src/glsl/brick.c
++++ b/src/glsl/brick.c
+@@ -14,8 +14,8 @@
+ #include "shaderutil.h"
+
+
+-static char *FragProgFile = "CH06-brick.frag";
+-static char *VertProgFile = "CH06-brick.vert";
++static char *FragProgFile = DEMOS_DATA_DIR "CH06-brick.frag";
++static char *VertProgFile = DEMOS_DATA_DIR "CH06-brick.vert";
+
+ /* program/shader objects */
+ static GLuint fragShader;
+diff --git a/src/glsl/bump.c b/src/glsl/bump.c
+index 59f62cd..3a1b20a 100644
+--- a/src/glsl/bump.c
++++ b/src/glsl/bump.c
+@@ -15,9 +15,9 @@
+ #include "readtex.h"
+
+
+-static char *FragProgFile = "CH11-bumpmap.frag";
+-static char *FragTexProgFile = "CH11-bumpmaptex.frag";
+-static char *VertProgFile = "CH11-bumpmap.vert";
++static char *FragProgFile = DEMOS_DATA_DIR "CH11-bumpmap.frag";
++static char *FragTexProgFile = DEMOS_DATA_DIR "CH11-bumpmaptex.frag";
++static char *VertProgFile = DEMOS_DATA_DIR "CH11-bumpmap.vert";
+ static char *TextureFile = DEMOS_DATA_DIR "tile.rgb";
+
+ /* program/shader objects */
+diff --git a/src/glsl/convolutions.c b/src/glsl/convolutions.c
+index a120cfe..9312f00 100644
+--- a/src/glsl/convolutions.c
++++ b/src/glsl/convolutions.c
+@@ -340,7 +340,7 @@ static void init(void)
+
+ menuInit();
+ readTexture(textureLocation);
+- createProgram("convolution.vert", "convolution.frag");
++ createProgram(DEMOS_DATA_DIR "convolution.vert", DEMOS_DATA_DIR "convolution.frag");
+
+ glEnable(GL_TEXTURE_2D);
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+diff --git a/src/glsl/mandelbrot.c b/src/glsl/mandelbrot.c
+index 31ede1d..ab34a0f 100644
+--- a/src/glsl/mandelbrot.c
++++ b/src/glsl/mandelbrot.c
+@@ -14,8 +14,8 @@
+ #include "shaderutil.h"
+
+
+-static char *FragProgFile = "CH18-mandel.frag";
+-static char *VertProgFile = "CH18-mandel.vert";
++static char *FragProgFile = DEMOS_DATA_DIR "CH18-mandel.frag";
++static char *VertProgFile = DEMOS_DATA_DIR "CH18-mandel.vert";
+
+ /* program/shader objects */
+ static GLuint fragShader;
+diff --git a/src/glsl/multitex.c b/src/glsl/multitex.c
+index 262ea50..546bd27 100644
+--- a/src/glsl/multitex.c
++++ b/src/glsl/multitex.c
+@@ -35,8 +35,8 @@
+
+ static const char *Demo = "multitex";
+
+-static const char *VertFile = "multitex.vert";
+-static const char *FragFile = "multitex.frag";
++static const char *VertFile = DEMOS_DATA_DIR "multitex.vert";
++static const char *FragFile = DEMOS_DATA_DIR "multitex.frag";
+
+ static const char *TexFiles[2] =
+ {
+diff --git a/src/glsl/simplex-noise.c b/src/glsl/simplex-noise.c
+index 13fdd5d..885f01e 100644
+--- a/src/glsl/simplex-noise.c
++++ b/src/glsl/simplex-noise.c
+@@ -169,7 +169,7 @@ SpecialKey(int key, int x, int y)
+ static void
+ Init(void)
+ {
+- const char *filename = "simplex-noise.glsl";
++ const char *filename = DEMOS_DATA_DIR "simplex-noise.glsl";
+ char noiseText[10000];
+ FILE *f;
+ int len;
+diff --git a/src/glsl/skinning.c b/src/glsl/skinning.c
+index bf38d77..536d475 100644
+--- a/src/glsl/skinning.c
++++ b/src/glsl/skinning.c
+@@ -20,8 +20,8 @@
+ #define M_PI 3.1415926535
+ #endif
+
+-static char *FragProgFile = "skinning.frag";
+-static char *VertProgFile = "skinning.vert";
++static char *FragProgFile = DEMOS_DATA_DIR "skinning.frag";
++static char *VertProgFile = DEMOS_DATA_DIR "skinning.vert";
+
+ /* program/shader objects */
+ static GLuint fragShader;
+diff --git a/src/glsl/texdemo1.c b/src/glsl/texdemo1.c
+index 6cde239..a082342 100644
+--- a/src/glsl/texdemo1.c
++++ b/src/glsl/texdemo1.c
+@@ -35,11 +35,11 @@
+
+ static const char *Demo = "texdemo1";
+
+-static const char *ReflectVertFile = "reflect.vert";
+-static const char *CubeFragFile = "cubemap.frag";
++static const char *ReflectVertFile = DEMOS_DATA_DIR "reflect.vert";
++static const char *CubeFragFile = DEMOS_DATA_DIR "cubemap.frag";
+
+-static const char *SimpleVertFile = "simple.vert";
+-static const char *SimpleTexFragFile = "shadowtex.frag";
++static const char *SimpleVertFile = DEMOS_DATA_DIR "simple.vert";
++static const char *SimpleTexFragFile = DEMOS_DATA_DIR "shadowtex.frag";
+
+ static const char *GroundImage = DEMOS_DATA_DIR "tile.rgb";
+
+diff --git a/src/glsl/toyball.c b/src/glsl/toyball.c
+index 5f27951..4e7e832 100644
+--- a/src/glsl/toyball.c
++++ b/src/glsl/toyball.c
+@@ -14,8 +14,8 @@
+ #include "shaderutil.h"
+
+
+-static char *FragProgFile = "CH11-toyball.frag";
+-static char *VertProgFile = "CH11-toyball.vert";
++static char *FragProgFile = DEMOS_DATA_DIR "CH11-toyball.frag";
++static char *VertProgFile = DEMOS_DATA_DIR "CH11-toyball.vert";
+
+ /* program/shader objects */
+ static GLuint fragShader;
+diff --git a/src/objviewer/objview.c b/src/objviewer/objview.c
+index 6def726..78a6acf 100644
+--- a/src/objviewer/objview.c
++++ b/src/objviewer/objview.c
+@@ -162,12 +162,12 @@ init_model(void)
+ static void
+ init_skybox(void)
+ {
+- SkyboxTex = LoadSkyBoxCubeTexture("alpine_east.rgb",
+- "alpine_west.rgb",
+- "alpine_up.rgb",
+- "alpine_down.rgb",
+- "alpine_south.rgb",
+- "alpine_north.rgb");
++ SkyboxTex = LoadSkyBoxCubeTexture(DEMOS_DATA_DIR "alpine_east.rgb",
++ DEMOS_DATA_DIR "alpine_west.rgb",
++ DEMOS_DATA_DIR "alpine_up.rgb",
++ DEMOS_DATA_DIR "alpine_down.rgb",
++ DEMOS_DATA_DIR "alpine_south.rgb",
++ DEMOS_DATA_DIR "alpine_north.rgb");
+ glmSpecularTexture(Model, SkyboxTex);
+ }
+
+diff --git a/src/perf/glslstateschange.c b/src/perf/glslstateschange.c
+index 7422b78..dbf8332 100644
+--- a/src/perf/glslstateschange.c
++++ b/src/perf/glslstateschange.c
+@@ -33,10 +33,10 @@
+ #include "glmain.h"
+ #include "common.h"
+
+-static const char *VertFile1 = "glslstateschange1.vert";
+-static const char *FragFile1 = "glslstateschange1.frag";
+-static const char *VertFile2 = "glslstateschange2.vert";
+-static const char *FragFile2 = "glslstateschange2.frag";
++static const char *VertFile1 = DEMOS_DATA_DIR "glslstateschange1.vert";
++static const char *FragFile1 = DEMOS_DATA_DIR "glslstateschange1.frag";
++static const char *VertFile2 = DEMOS_DATA_DIR "glslstateschange2.vert";
++static const char *FragFile2 = DEMOS_DATA_DIR "glslstateschange2.frag";
+ static struct uniform_info Uniforms1[] = {
+ { "tex1", 1, GL_SAMPLER_2D, { 0, 0, 0, 0 }, -1 },
+ { "tex2", 1, GL_SAMPLER_2D, { 1, 0, 0, 0 }, -1 },
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos_8.1.0.bbappend b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos_8.1.0.bbappend
new file mode 100644
index 00000000..b7e42908
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa-demos/mesa-demos_8.1.0.bbappend
@@ -0,0 +1,19 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+EXTRA_OECONF += "--with-system-data-files"
+PACKAGECONFIG[glut] = "--with-glut=${STAGING_EXECPREFIXDIR},--without-glut,"
+DEPENDS_steppeeagle += "mesa-glut glew"
+PACKAGECONFIG_append_steppeeagle = " glut"
+
+SRC_URI += " \
+ file://0001-mesa-demos-Use-DEMOS_DATA_DIR-to-locate-data-files.patch \
+ file://0001-mesa-demos-Add-missing-data-files.patch \
+"
+
+do_install_append () {
+ install -m 0644 ${S}/src/perf/*.frag \
+ ${S}/src/perf/*.vert \
+ ${S}/src/glsl/*.frag \
+ ${S}/src/glsl/*.vert \
+ ${S}/src/glsl/*.geom \
+ ${S}/src/glsl/*.glsl ${D}${datadir}/${BPN}
+}
diff --git a/meta-steppeeagle/recipes-graphics/mesa/mesa/0001-radeonsi-add-support-for-Mullins-asics.patch b/meta-steppeeagle/recipes-graphics/mesa/mesa/0001-radeonsi-add-support-for-Mullins-asics.patch
new file mode 100644
index 00000000..51b1d070
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa/mesa/0001-radeonsi-add-support-for-Mullins-asics.patch
@@ -0,0 +1,74 @@
+From 5dfd2c48a8d4b362a6119a2dcbfe66e163e3af35 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Thu, 17 Apr 2014 15:49:52 -0400
+Subject: [PATCH 1/2] radeonsi: add support for Mullins asics.
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ src/gallium/drivers/radeon/r600_pipe_common.c | 2 ++
+ src/gallium/drivers/radeonsi/si_state.c | 2 ++
+ src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 1 +
+ src/gallium/winsys/radeon/drm/radeon_winsys.h | 1 +
+ 4 files changed, 6 insertions(+)
+
+diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
+index 7508865..db6709a 100644
+--- a/src/gallium/drivers/radeon/r600_pipe_common.c
++++ b/src/gallium/drivers/radeon/r600_pipe_common.c
+@@ -293,6 +293,7 @@ static const char* r600_get_name(struct pipe_screen* pscreen)
+ case CHIP_KAVERI: return "AMD KAVERI";
+ case CHIP_KABINI: return "AMD KABINI";
+ case CHIP_HAWAII: return "AMD HAWAII";
++ case CHIP_MULLINS: return "AMD MULLINS";
+ default: return "AMD unknown";
+ }
+ }
+@@ -410,6 +411,7 @@ const char *r600_get_llvm_processor_name(enum radeon_family family)
+ case CHIP_KABINI: return "kabini";
+ case CHIP_KAVERI: return "kaveri";
+ case CHIP_HAWAII: return "hawaii";
++ case CHIP_MULLINS: return "mullins";
+ default: return "";
+ #endif
+ }
+diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
+index ab9c4cc..85ef5ae 100644
+--- a/src/gallium/drivers/radeonsi/si_state.c
++++ b/src/gallium/drivers/radeonsi/si_state.c
+@@ -3086,6 +3086,8 @@ void si_init_config(struct si_context *sctx)
+ /* XXX todo */
+ case CHIP_KABINI:
+ /* XXX todo */
++ case CHIP_MULLINS:
++ /* XXX todo */
+ default:
+ si_pm4_set_reg(pm4, R_028350_PA_SC_RASTER_CONFIG, 0x00000000);
+ si_pm4_set_reg(pm4, R_028354_PA_SC_RASTER_CONFIG_1, 0x00000000);
+diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+index 0eb0c6a..602c406 100644
+--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
++++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+@@ -276,6 +276,7 @@ static boolean do_winsys_init(struct radeon_drm_winsys *ws)
+ case CHIP_KAVERI:
+ case CHIP_KABINI:
+ case CHIP_HAWAII:
++ case CHIP_MULLINS:
+ ws->info.chip_class = CIK;
+ break;
+ }
+diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
+index fe0617b..1c0c825 100644
+--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
++++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
+@@ -130,6 +130,7 @@ enum radeon_family {
+ CHIP_KAVERI,
+ CHIP_KABINI,
+ CHIP_HAWAII,
++ CHIP_MULLINS,
+ CHIP_LAST,
+ };
+
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/mesa/mesa/0002-radeonsi-add-Mullins-pci-ids.patch b/meta-steppeeagle/recipes-graphics/mesa/mesa/0002-radeonsi-add-Mullins-pci-ids.patch
new file mode 100644
index 00000000..264fd958
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa/mesa/0002-radeonsi-add-Mullins-pci-ids.patch
@@ -0,0 +1,42 @@
+From 5b54f9dac924f9b469105bc664f6bf2b3234f691 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Tue, 12 Nov 2013 15:49:55 -0500
+Subject: [PATCH 2/2] radeonsi: add Mullins pci ids.
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ include/pci_ids/radeonsi_pci_ids.h | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/include/pci_ids/radeonsi_pci_ids.h b/include/pci_ids/radeonsi_pci_ids.h
+index 7b42d5e..5099c74 100644
+--- a/include/pci_ids/radeonsi_pci_ids.h
++++ b/include/pci_ids/radeonsi_pci_ids.h
+@@ -97,6 +97,23 @@ CHIPSET(0x983D, KABINI_983D, KABINI)
+ CHIPSET(0x983E, KABINI_983E, KABINI)
+ CHIPSET(0x983F, KABINI_983F, KABINI)
+
++CHIPSET(0x9850, MULLINS_9850, MULLINS)
++CHIPSET(0x9851, MULLINS_9851, MULLINS)
++CHIPSET(0x9852, MULLINS_9852, MULLINS)
++CHIPSET(0x9853, MULLINS_9853, MULLINS)
++CHIPSET(0x9854, MULLINS_9854, MULLINS)
++CHIPSET(0x9855, MULLINS_9855, MULLINS)
++CHIPSET(0x9856, MULLINS_9856, MULLINS)
++CHIPSET(0x9857, MULLINS_9857, MULLINS)
++CHIPSET(0x9858, MULLINS_9858, MULLINS)
++CHIPSET(0x9859, MULLINS_9859, MULLINS)
++CHIPSET(0x985A, MULLINS_985A, MULLINS)
++CHIPSET(0x985B, MULLINS_985B, MULLINS)
++CHIPSET(0x985C, MULLINS_985C, MULLINS)
++CHIPSET(0x985D, MULLINS_985D, MULLINS)
++CHIPSET(0x985E, MULLINS_985E, MULLINS)
++CHIPSET(0x985F, MULLINS_985F, MULLINS)
++
+ CHIPSET(0x1304, KAVERI_1304, KAVERI)
+ CHIPSET(0x1305, KAVERI_1305, KAVERI)
+ CHIPSET(0x1306, KAVERI_1306, KAVERI)
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/mesa/mesa_git.bbappend b/meta-steppeeagle/recipes-graphics/mesa/mesa_git.bbappend
new file mode 100644
index 00000000..7f85de14
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/mesa/mesa_git.bbappend
@@ -0,0 +1,60 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRCREV = "d4e5ea65089af05b5891293d8947b0ee0e9dd429"
+LIC_FILES_CHKSUM = "file://docs/license.html;md5=6a23445982a7a972ac198e93cc1cb3de"
+PV = "10.2.0+git${SRCPV}"
+DEPENDS += "libvdpau"
+PACKAGECONFIG_append = " xvmc openvg gallium gallium-egl gallium-gbm r600"
+PACKAGECONFIG_append += " gallium-llvm"
+MESA_LLVM_RELEASE = "3.4"
+
+# Install the demos onto the target
+RRECOMMENDS_libgl-mesa += "mesa-demos"
+
+SRC_URI = " \
+ git://people.freedesktop.org/~deathsimple/mesa;branch=vce-release \
+ file://0001-radeonsi-add-support-for-Mullins-asics.patch \
+ file://0002-radeonsi-add-Mullins-pci-ids.patch \
+ "
+
+PATCHTOOL = "git"
+
+DEPENDS += "libomxil"
+EXTRA_OECONF += "--disable-dri3 \
+ --enable-vdpau \
+ --enable-osmesa \
+ --enable-xa \
+ --enable-glx \
+ --enable-omx \
+ --with-omx-libdir=${libdir}/bellagio \
+ "
+
+PACKAGES += "libxvmcr600-${PN}-dev"
+FILES_libxvmcr600-${PN}-dev += "${libdir}/libXvMCr600.so \
+ ${libdir}/libXvMCr600.la"
+
+PACKAGES += "libxvmcnouveau-${PN}-dev"
+FILES_libxvmcnouveau-${PN}-dev += "${libdir}/libXvMCnouveau.so \
+ ${libdir}/libXvMCnouveau.la"
+
+PACKAGES += "libvdpau-${PN} libvdpau-${PN}-dev"
+FILES_libvdpau-${PN} += "${libdir}/vdpau/libvdpau*.so.*"
+FILES_libvdpau-${PN}-dev += "${libdir}/vdpau/libvdpau*.so \
+ ${libdir}/vdpau/libvdpau*.la"
+FILES_${PN}-dbg += "${libdir}/vdpau/.debug"
+
+PACKAGES += "libxatracker-${PN} libxatracker-${PN}-dev"
+FILES_libxatracker-${PN} += "${libdir}/libxatracker.so.*"
+FILES_libxatracker-${PN}-dev += "${includedir}/xa_tracker.h \
+ ${includedir}/xa_composite.h \
+ ${includedir}/xa_context.h \
+ ${libdir}/pkgconfig/xatracker.pc \
+ ${libdir}/libxatracker.so \
+ ${libdir}/libxatracker.la \
+ "
+
+PACKAGES += "libomx-${PN} libomx-${PN}-dev libomx-${PN}-dbg"
+FILES_libomx-${PN} += "${libdir}/bellagio/libomx_*.so.*"
+FILES_libomx-${PN}-dev += "${libdir}/bellagio/libomx_*.so \
+ ${libdir}/bellagio/libomx_*.la"
+FILES_libomx-${PN}-dbg += "${libdir}/bellagio/.debug"
diff --git a/meta-steppeeagle/recipes-graphics/vdpauinfo/vdpauinfo_0.1.bb b/meta-steppeeagle/recipes-graphics/vdpauinfo/vdpauinfo_0.1.bb
new file mode 100644
index 00000000..aa726b2b
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/vdpauinfo/vdpauinfo_0.1.bb
@@ -0,0 +1,15 @@
+DESCRIPTION = "VDPAU info tool"
+HOMEPAGE = "http://people.freedesktop.org"
+LICENSE = "MIT"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=5b6e110c362fe46168199f3490e52c3c"
+
+SRC_URI = "http://cgit.freedesktop.org/~aplattner/vdpauinfo/snapshot/vdpauinfo-${PV}.zip"
+SRC_URI[md5sum] = "62902c9d5d4417885aa70d05521b8280"
+SRC_URI[sha256sum] = "b87dd48b2b3b4fc7e886c6963d8dfe8d4dffa3f7b91768a1376ba3e295c28db7"
+
+inherit autotools pkgconfig
+
+DEPENDS += "virtual/libx11 libvdpau"
+
+RDEPENDS_${PN} += "libvdpau-mesa"
diff --git a/meta-steppeeagle/recipes-graphics/xorg-driver/glamor-egl_0.6.0.bb b/meta-steppeeagle/recipes-graphics/xorg-driver/glamor-egl_0.6.0.bb
new file mode 100644
index 00000000..2628adbe
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-driver/glamor-egl_0.6.0.bb
@@ -0,0 +1,18 @@
+require recipes-graphics/xorg-driver/xorg-driver-common.inc
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=c7f5e33031114ad132cb03949d73a8a8"
+
+SRC_URI[md5sum] = "b3668594675f71a75153ee52dbd35535"
+SRC_URI[sha256sum] = "66531b56e6054eb53daa7bd57eb6358a7ead1b84f63419606e69d1092365e5c9"
+
+S = "${WORKDIR}/${PN}-${PV}"
+
+inherit autotools pkgconfig
+
+EXTRA_OECONF += "--prefix=${prefix} \
+ --sysconfdir=${sysconfdir} \
+ --localstatedir=${localstatedir} \
+ --enable-glx-tls"
+
+FILES_${PN} += "${datadir}/X11/xorg.conf.d ${libdir}/xorg/modules/lib*.so"
+FILES_${PN}-dbg += "${libdir}/xorg/modules/.debug"
diff --git a/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0001-radeon-add-support-for-Mullins.patch b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0001-radeon-add-support-for-Mullins.patch
new file mode 100644
index 00000000..29c1c714
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0001-radeon-add-support-for-Mullins.patch
@@ -0,0 +1,41 @@
+From 5cf5f62f912c3cd178561ad164f1f51f980e96a9 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Thu, 17 Apr 2014 15:17:28 -0400
+Subject: [PATCH 1/2] radeon: add support for Mullins.
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ man/radeon.man | 3 +++
+ src/radeon_probe.h | 1 +
+ 2 files changed, 4 insertions(+)
+
+diff --git a/man/radeon.man b/man/radeon.man
+index f6a825d..65b880c 100644
+--- a/man/radeon.man
++++ b/man/radeon.man
+@@ -208,6 +208,9 @@ KABINI APUs
+ .TP 12
+ .B HAWAII
+ Radeon R9 series
++.TP 12
++.B MULLINS
++MULLINS APUs
+ .PD
+ .SH CONFIGURATION DETAILS
+ Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+diff --git a/src/radeon_probe.h b/src/radeon_probe.h
+index 9500189..3fe4644 100644
+--- a/src/radeon_probe.h
++++ b/src/radeon_probe.h
+@@ -116,6 +116,7 @@ typedef enum {
+ CHIP_FAMILY_KAVERI,
+ CHIP_FAMILY_KABINI,
+ CHIP_FAMILY_HAWAII,
++ CHIP_FAMILY_MULLINS,
+ CHIP_FAMILY_LAST
+ } RADEONChipFamily;
+
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0002-radeon-kms-add-Mullins-pci-ids.patch b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0002-radeon-kms-add-Mullins-pci-ids.patch
new file mode 100644
index 00000000..d3cd5502
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati/0002-radeon-kms-add-Mullins-pci-ids.patch
@@ -0,0 +1,181 @@
+From e1484dfd7336aa71ad020968615b1acc0d34fb89 Mon Sep 17 00:00:00 2001
+From: Samuel Li <samuel.li@amd.com>
+Date: Tue, 12 Nov 2013 15:30:42 -0500
+Subject: [PATCH 2/2] radeon/kms: add Mullins pci ids.
+
+Signed-off-by: Samuel Li <samuel.li@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ src/ati_pciids_gen.h | 16 ++++++++++++++++
+ src/pcidb/ati_pciids.csv | 16 ++++++++++++++++
+ src/radeon_chipinfo_gen.h | 16 ++++++++++++++++
+ src/radeon_chipset_gen.h | 16 ++++++++++++++++
+ src/radeon_pci_chipset_gen.h | 16 ++++++++++++++++
+ src/radeon_pci_device_match_gen.h | 16 ++++++++++++++++
+ 6 files changed, 96 insertions(+)
+
+diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
+index eb57992..94c8fc8 100644
+--- a/src/ati_pciids_gen.h
++++ b/src/ati_pciids_gen.h
+@@ -722,6 +722,22 @@
+ #define PCI_CHIP_KABINI_983D 0x983D
+ #define PCI_CHIP_KABINI_983E 0x983E
+ #define PCI_CHIP_KABINI_983F 0x983F
++#define PCI_CHIP_MULLINS_9850 0x9850
++#define PCI_CHIP_MULLINS_9851 0x9851
++#define PCI_CHIP_MULLINS_9852 0x9852
++#define PCI_CHIP_MULLINS_9853 0x9853
++#define PCI_CHIP_MULLINS_9854 0x9854
++#define PCI_CHIP_MULLINS_9855 0x9855
++#define PCI_CHIP_MULLINS_9856 0x9856
++#define PCI_CHIP_MULLINS_9857 0x9857
++#define PCI_CHIP_MULLINS_9858 0x9858
++#define PCI_CHIP_MULLINS_9859 0x9859
++#define PCI_CHIP_MULLINS_985A 0x985A
++#define PCI_CHIP_MULLINS_985B 0x985B
++#define PCI_CHIP_MULLINS_985C 0x985C
++#define PCI_CHIP_MULLINS_985D 0x985D
++#define PCI_CHIP_MULLINS_985E 0x985E
++#define PCI_CHIP_MULLINS_985F 0x985F
+ #define PCI_CHIP_KAVERI_1304 0x1304
+ #define PCI_CHIP_KAVERI_1305 0x1305
+ #define PCI_CHIP_KAVERI_1306 0x1306
+diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
+index 8469a2a..e334230 100644
+--- a/src/pcidb/ati_pciids.csv
++++ b/src/pcidb/ati_pciids.csv
+@@ -723,6 +723,22 @@
+ "0x983D","KABINI_983D","KABINI",,1,,,1,"KABINI"
+ "0x983E","KABINI_983E","KABINI",,1,,,1,"KABINI"
+ "0x983F","KABINI_983F","KABINI",,1,,,1,"KABINI"
++"0x9850","MULLINS_9850","MULLINS",1,1,,,1,"MULLINS"
++"0x9851","MULLINS_9851","MULLINS",1,1,,,1,"MULLINS"
++"0x9852","MULLINS_9852","MULLINS",1,1,,,1,"MULLINS"
++"0x9853","MULLINS_9853","MULLINS",1,1,,,1,"MULLINS"
++"0x9854","MULLINS_9854","MULLINS",1,1,,,1,"MULLINS"
++"0x9845","MULLINS_9855","MULLINS",1,1,,,1,"MULLINS"
++"0x9856","MULLINS_9856","MULLINS",1,1,,,1,"MULLINS"
++"0x9857","MULLINS_9857","MULLINS",1,1,,,1,"MULLINS"
++"0x9858","MULLINS_9858","MULLINS",1,1,,,1,"MULLINS"
++"0x9859","MULLINS_9859","MULLINS",1,1,,,1,"MULLINS"
++"0x985A","MULLINS_985A","MULLINS",1,1,,,1,"MULLINS"
++"0x985B","MULLINS_985B","MULLINS",1,1,,,1,"MULLINS"
++"0x985C","MULLINS_985C","MULLINS",1,1,,,1,"MULLINS"
++"0x985D","MULLINS_985D","MULLINS",1,1,,,1,"MULLINS"
++"0x985E","MULLINS_985E","MULLINS",1,1,,,1,"MULLINS"
++"0x985F","MULLINS_985F","MULLINS",1,1,,,1,"MULLINS"
+ "0x1304","KAVERI_1304","KAVERI",1,1,,,1,"KAVERI"
+ "0x1305","KAVERI_1305","KAVERI",,1,,,1,"KAVERI"
+ "0x1306","KAVERI_1306","KAVERI",1,1,,,1,"KAVERI"
+diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
+index fc9474b..4f6e3bc 100644
+--- a/src/radeon_chipinfo_gen.h
++++ b/src/radeon_chipinfo_gen.h
+@@ -642,6 +642,22 @@ static RADEONCardInfo RADEONCards[] = {
+ { 0x983D, CHIP_FAMILY_KABINI, 0, 1, 0, 0, 1 },
+ { 0x983E, CHIP_FAMILY_KABINI, 0, 1, 0, 0, 1 },
+ { 0x983F, CHIP_FAMILY_KABINI, 0, 1, 0, 0, 1 },
++ { 0x9850, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9851, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9852, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9853, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9854, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9855, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9856, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9857, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9858, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x9859, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985A, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985B, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985C, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985D, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985E, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
++ { 0x985F, CHIP_FAMILY_MULLINS, 1, 1, 0, 0, 1 },
+ { 0x1304, CHIP_FAMILY_KAVERI, 1, 1, 0, 0, 1 },
+ { 0x1305, CHIP_FAMILY_KAVERI, 0, 1, 0, 0, 1 },
+ { 0x1306, CHIP_FAMILY_KAVERI, 1, 1, 0, 0, 1 },
+diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
+index afab6b0..03a413e 100644
+--- a/src/radeon_chipset_gen.h
++++ b/src/radeon_chipset_gen.h
+@@ -642,6 +642,22 @@ SymTabRec RADEONChipsets[] = {
+ { PCI_CHIP_KABINI_983D, "KABINI" },
+ { PCI_CHIP_KABINI_983E, "KABINI" },
+ { PCI_CHIP_KABINI_983F, "KABINI" },
++ { PCI_CHIP_MULLINS_9850, "MULLINS" },
++ { PCI_CHIP_MULLINS_9851, "MULLINS" },
++ { PCI_CHIP_MULLINS_9852, "MULLINS" },
++ { PCI_CHIP_MULLINS_9853, "MULLINS" },
++ { PCI_CHIP_MULLINS_9854, "MULLINS" },
++ { PCI_CHIP_MULLINS_9855, "MULLINS" },
++ { PCI_CHIP_MULLINS_9856, "MULLINS" },
++ { PCI_CHIP_MULLINS_9857, "MULLINS" },
++ { PCI_CHIP_MULLINS_9858, "MULLINS" },
++ { PCI_CHIP_MULLINS_9859, "MULLINS" },
++ { PCI_CHIP_MULLINS_985A, "MULLINS" },
++ { PCI_CHIP_MULLINS_985B, "MULLINS" },
++ { PCI_CHIP_MULLINS_985C, "MULLINS" },
++ { PCI_CHIP_MULLINS_985D, "MULLINS" },
++ { PCI_CHIP_MULLINS_985E, "MULLINS" },
++ { PCI_CHIP_MULLINS_985F, "MULLINS" },
+ { PCI_CHIP_KAVERI_1304, "KAVERI" },
+ { PCI_CHIP_KAVERI_1305, "KAVERI" },
+ { PCI_CHIP_KAVERI_1306, "KAVERI" },
+diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
+index da4440b..a9b186c 100644
+--- a/src/radeon_pci_chipset_gen.h
++++ b/src/radeon_pci_chipset_gen.h
+@@ -642,6 +642,22 @@ static PciChipsets RADEONPciChipsets[] = {
+ { PCI_CHIP_KABINI_983D, PCI_CHIP_KABINI_983D, RES_SHARED_VGA },
+ { PCI_CHIP_KABINI_983E, PCI_CHIP_KABINI_983E, RES_SHARED_VGA },
+ { PCI_CHIP_KABINI_983F, PCI_CHIP_KABINI_983F, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9850, PCI_CHIP_MULLINS_9850, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9851, PCI_CHIP_MULLINS_9851, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9852, PCI_CHIP_MULLINS_9852, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9853, PCI_CHIP_MULLINS_9853, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9854, PCI_CHIP_MULLINS_9854, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9855, PCI_CHIP_MULLINS_9855, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9856, PCI_CHIP_MULLINS_9856, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9857, PCI_CHIP_MULLINS_9857, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9858, PCI_CHIP_MULLINS_9858, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_9859, PCI_CHIP_MULLINS_9859, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985A, PCI_CHIP_MULLINS_985A, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985B, PCI_CHIP_MULLINS_985B, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985C, PCI_CHIP_MULLINS_985C, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985D, PCI_CHIP_MULLINS_985D, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985E, PCI_CHIP_MULLINS_985E, RES_SHARED_VGA },
++ { PCI_CHIP_MULLINS_985F, PCI_CHIP_MULLINS_985F, RES_SHARED_VGA },
+ { PCI_CHIP_KAVERI_1304, PCI_CHIP_KAVERI_1304, RES_SHARED_VGA },
+ { PCI_CHIP_KAVERI_1305, PCI_CHIP_KAVERI_1305, RES_SHARED_VGA },
+ { PCI_CHIP_KAVERI_1306, PCI_CHIP_KAVERI_1306, RES_SHARED_VGA },
+diff --git a/src/radeon_pci_device_match_gen.h b/src/radeon_pci_device_match_gen.h
+index d4b3763..a73d9c1 100644
+--- a/src/radeon_pci_device_match_gen.h
++++ b/src/radeon_pci_device_match_gen.h
+@@ -642,6 +642,22 @@ static const struct pci_id_match radeon_device_match[] = {
+ ATI_DEVICE_MATCH( PCI_CHIP_KABINI_983D, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_KABINI_983E, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_KABINI_983F, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9850, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9851, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9852, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9853, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9854, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9855, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9856, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9857, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9858, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_9859, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985A, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985B, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985C, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985D, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985E, 0 ),
++ ATI_DEVICE_MATCH( PCI_CHIP_MULLINS_985F, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_KAVERI_1304, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_KAVERI_1305, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_KAVERI_1306, 0 ),
+--
+1.8.3.1
+
diff --git a/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati_git.bb b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati_git.bb
new file mode 100644
index 00000000..70676d0b
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-driver/xf86-video-ati_git.bb
@@ -0,0 +1,38 @@
+require recipes-graphics/xorg-driver/xorg-driver-video.inc
+
+SUMMARY = "X.Org X server -- ATI integrated graphics chipsets driver"
+
+DESCRIPTION = "xf86-video-ati is an Xorg driver for Intel integrated \
+graphics chipsets. The driver supports depths 8, 15, 16 and 24. On \
+some chipsets, the driver supports hardware accelerated 3D via the \
+Direct Rendering Infrastructure (DRI)."
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=aabff1606551f9461ccf567739af63dc"
+
+DEPENDS += "virtual/libx11 drm dri2proto glproto \
+ virtual/libgl xineramaproto libpciaccess \
+ udev glamor-egl"
+
+SRCREV = "48d3dbc8a0d3bfde88f46e402e530438f9317715"
+PV = "7.3.99+git${SRCPV}"
+PR = "${INC_PR}.1"
+
+EXTRA_OECONF += "--enable-udev --enable-glamor"
+
+SRC_URI = " \
+ git://anongit.freedesktop.org/git/xorg/driver/xf86-video-ati \
+ file://0001-radeon-add-support-for-Mullins.patch \
+ file://0002-radeon-kms-add-Mullins-pci-ids.patch \
+ "
+
+PATCHTOOL = "git"
+
+S = "${WORKDIR}/git"
+
+RDEPENDS_${PN} += "libgbm-gallium \
+ mesa-driver-radeon \
+ mesa-driver-radeonsi \
+ mesa-driver-swrast \
+ "
+
+COMPATIBLE_HOST = '(i.86|x86_64).*-linux'
diff --git a/meta-steppeeagle/recipes-graphics/xorg-lib/libvdpau_0.7.bb b/meta-steppeeagle/recipes-graphics/xorg-lib/libvdpau_0.7.bb
new file mode 100644
index 00000000..f6b9afe2
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-lib/libvdpau_0.7.bb
@@ -0,0 +1,39 @@
+DESCRIPTION = "Implements VDPAU library"
+HOMEPAGE = "http://people.freedesktop.org"
+LICENSE = "MIT"
+DEPENDS = "xtrans libx11 libxext libice libsm libxscrnsaver libxt \
+ libxmu libxpm libxau libxfixes libxcomposite libxrender \
+ libxcursor libxdamage libfontenc libxfont libxft libxi \
+ libxinerama libxrandr libxres libxtst libxv libxvmc \
+ libxxf86dga libxxf86vm libdmx libpciaccess libxkbfile \
+ dri2proto \
+ "
+LIC_FILES_CHKSUM = "file://COPYING;md5=83af8811a28727a13f04132cc33b7f58"
+
+SRC_URI = "http://people.freedesktop.org/~aplattner/vdpau/libvdpau-${PV}.tar.gz"
+SRC_URI[md5sum] = "cb81b0c3b7d32b2b2a51894ef05b95ce"
+SRC_URI[sha256sum] = "24dc08467ce8c59d6cfbf0d34d2dd1f86b4ff62e90777e0a8f513c5c9de9bce0"
+
+inherit autotools pkgconfig
+
+S = "${WORKDIR}/libvdpau-${PV}"
+
+FILES_${PN} += "${libdir}/vdpau/libvdpau_nouveau.so.* \
+ ${libdir}/vdpau/libvdpau_r600.so.* \
+ ${libdir}/vdpau/libvdpau_radeonsi.so.* \
+ ${libdir}/vdpau/libvdpau_trace.so.* \
+ "
+
+FILES_${PN}-dev += "${libdir}/vdpau/libvdpau_nouveau.so \
+ ${libdir}/vdpau/libvdpau_nouveau.la \
+ ${libdir}/vdpau/libvdpau_r600.so \
+ ${libdir}/vdpau/libvdpau_r600.la \
+ ${libdir}/vdpau/libvdpau_radeonsi.so \
+ ${libdir}/vdpau/libvdpau_radeonsi.la \
+ ${libdir}/vdpau/libvdpau_trace.so \
+ ${libdir}/vdpau/libvdpau_trace.la \
+ "
+
+FILES_${PN}-dbg += "${libdir}/vdpau/.debug"
+
+EXTRA_OECONF += "--enable-dri2"
diff --git a/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config/steppeeagle/xorg.conf b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config/steppeeagle/xorg.conf
new file mode 100644
index 00000000..17363bc6
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config/steppeeagle/xorg.conf
@@ -0,0 +1,113 @@
+# TODO: imported from /usr/local/xorg/share/X11/conf.d/glamor.conf
+Section "Module"
+ Load "dri2"
+ Load "glamoregl"
+EndSection
+
+Section "Monitor"
+ Identifier "Monitor0"
+ VendorName "Monitor Vendor"
+ ModelName "Monitor Model"
+EndSection
+
+Section "Device"
+ ### Available Driver options are:-
+ ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
+ ### <string>: "String", <freq>: "<f> Hz/kHz/MHz",
+ ### <percent>: "<f>%"
+ ### [arg]: arg optional
+ #Option "NoAccel" # [<bool>]
+ #Option "SWcursor" # [<bool>]
+ #Option "Dac6Bit" # [<bool>]
+ #Option "Dac8Bit" # [<bool>]
+ #Option "BusType" # [<str>]
+ #Option "CPPIOMode" # [<bool>]
+ #Option "CPusecTimeout" # <i>
+ #Option "AGPMode" # <i>
+ #Option "AGPFastWrite" # [<bool>]
+ #Option "AGPSize" # <i>
+ #Option "GARTSize" # <i>
+ #Option "RingSize" # <i>
+ #Option "BufferSize" # <i>
+ #Option "EnableDepthMoves" # [<bool>]
+ #Option "EnablePageFlip" # [<bool>]
+ #Option "NoBackBuffer" # [<bool>]
+ #Option "DMAForXv" # [<bool>]
+ #Option "FBTexPercent" # <i>
+ #Option "DepthBits" # <i>
+ #Option "PCIAPERSize" # <i>
+ #Option "AccelDFS" # [<bool>]
+ #Option "IgnoreEDID" # [<bool>]
+ #Option "CustomEDID" # [<str>]
+ #Option "DisplayPriority" # [<str>]
+ #Option "PanelSize" # [<str>]
+ #Option "ForceMinDotClock" # <freq>
+ #Option "ColorTiling" # [<bool>]
+ #Option "VideoKey" # <i>
+ #Option "RageTheatreCrystal" # <i>
+ #Option "RageTheatreTunerPort" # <i>
+ #Option "RageTheatreCompositePort" # <i>
+ #Option "RageTheatreSVideoPort" # <i>
+ #Option "TunerType" # <i>
+ #Option "RageTheatreMicrocPath" # <str>
+ #Option "RageTheatreMicrocType" # <str>
+ #Option "ScalerWidth" # <i>
+ #Option "RenderAccel" # [<bool>]
+ #Option "SubPixelOrder" # [<str>]
+ #Option "ClockGating" # [<bool>]
+ #Option "VGAAccess" # [<bool>]
+ #Option "ReverseDDC" # [<bool>]
+ #Option "LVDSProbePLL" # [<bool>]
+ Option "AccelMethod" "glamor"
+ #Option "DRI" # [<bool>]
+ #Option "ConnectorTable" # <str>
+ #Option "DefaultConnectorTable" # [<bool>]
+ #Option "DefaultTMDSPLL" # [<bool>]
+ #Option "TVDACLoadDetect" # [<bool>]
+ #Option "ForceTVOut" # [<bool>]
+ #Option "TVStandard" # <str>
+ #Option "IgnoreLidStatus" # [<bool>]
+ #Option "DefaultTVDACAdj" # [<bool>]
+ #Option "Int10" # [<bool>]
+ #Option "EXAVSync" # [<bool>]
+ #Option "ATOMTVOut" # [<bool>]
+ #Option "R4xxATOM" # [<bool>]
+ #Option "ForceLowPowerMode" # [<bool>]
+ #Option "DynamicPM" # [<bool>]
+ #Option "NewPLL" # [<bool>]
+ #Option "ZaphodHeads" # <str>
+ Identifier "Card0"
+ Driver "radeon"
+ BusID "PCI:0:1:0"
+EndSection
+
+Section "Screen"
+ Identifier "Screen0"
+ Device "Card0"
+ Monitor "Monitor0"
+ SubSection "Display"
+ Viewport 0 0
+ Depth 1
+ EndSubSection
+ SubSection "Display"
+ Viewport 0 0
+ Depth 4
+ EndSubSection
+ SubSection "Display"
+ Viewport 0 0
+ Depth 8
+ EndSubSection
+ SubSection "Display"
+ Viewport 0 0
+ Depth 15
+ EndSubSection
+ SubSection "Display"
+ Viewport 0 0
+ Depth 16
+ EndSubSection
+ SubSection "Display"
+ Viewport 0 0
+ Depth 24
+ EndSubSection
+EndSection
+
diff --git a/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend
new file mode 100644
index 00000000..72d991c7
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend
@@ -0,0 +1 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
diff --git a/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xorg_1.15.0.bbappend b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xorg_1.15.0.bbappend
new file mode 100644
index 00000000..aa1ecd66
--- /dev/null
+++ b/meta-steppeeagle/recipes-graphics/xorg-xserver/xserver-xorg_1.15.0.bbappend
@@ -0,0 +1,5 @@
+PR = "${INC_PR}.1"
+EXTRA_OECONF += "--enable-aiglx \
+ --enable-xvmc \
+ --enable-libdrm \
+ "
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb b/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb
new file mode 100644
index 00000000..c003fe43
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "This kernel module provides support for AMD GPIO driver"
+LICENSE = "BSD | GPLv2"
+LIC_FILES_CHKSUM = "file://gpio-amd.c;md5=a48cb57d6711b1801a62ea03a87e2e76 \
+ file://gpio-amd.h;md5=90e0a4a5923224a946619ee72f0f7522 \
+ file://Makefile;md5=1bede035509502b1669f098efbd904f3 \
+ "
+
+inherit module
+
+PR = "r0"
+PV = "1.0"
+
+SRC_URI = "file://Makefile \
+ file://gpio-amd.c \
+ file://gpio-amd.h \
+ "
+
+S = "${WORKDIR}"
+
+# Kernel module packages MUST begin with 'kernel-module-', otherwise
+# multilib image generation can fail.
+#
+# The following line is only necessary if the recipe name does not begin
+# with kernel-module-.
+#
+PKG_${PN} = "kernel-module-${PN}"
+
+FILES_${PN} += "${sysconfdir}"
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile b/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile
new file mode 100644
index 00000000..b9348759
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile
@@ -0,0 +1,14 @@
+obj-m := gpio-amd.o
+
+SRC := $(shell pwd)
+
+all:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
+
+clean:
+ rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
+ rm -f Module.markers Module.symvers modules.order
+ rm -rf .tmp_versions Modules.symvers
+
+modules_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install \ No newline at end of file
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c
new file mode 100644
index 00000000..6c790c11
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c
@@ -0,0 +1,886 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/fs.h> /* everything... */
+#include <asm/io.h>
+#include <linux/ioctl.h>
+#include <linux/device.h>
+
+#include "gpio-amd.h"
+
+static u32 gpiobase_phys;
+static u32 iomuxbase_phys;
+static struct pci_dev *amd_gpio_pci;
+static struct platform_device *amd_gpio_platform_device;
+
+
+static int dev_major;
+static int dev_minor = 0;
+
+static struct gpio_test_dev{
+ struct cdev cdev;
+ struct class *gpio_class;
+}gpio_test_dev;
+
+
+/* The following GPIO pins are reserved as per the specification. 184 max */
+static u8 mask[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+
+
+static int gpio_mask[AMD_GPIO_NUM_PINS];
+static unsigned int num_mask;
+module_param_array(gpio_mask, int, &num_mask, 0);
+MODULE_PARM_DESC(gpio_mask, "GPIO mask which marks them as reserved");
+
+static int gpio_mode[AMD_GPIO_NUM_PINS];
+static unsigned int num_modes;
+module_param_array(gpio_mode, int, &num_modes, 0);
+MODULE_PARM_DESC(gpio_mode, "Specifies whether the GPIO mentioned "
+ "in gpio_mask is 0-reserved, 1-available, 2-GPI only, "
+ "3-GPO only");
+
+static struct amd_gpio_chip {
+ struct gpio_chip gpio;
+
+ void __iomem *gpiobase;
+ void __iomem *iomuxbase;
+
+ struct platform_device *pdev;
+ spinlock_t lock;
+} amd_gpio_chip;
+
+static int amd_gpio_request(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u8 iomux_reg;
+ u32 gpio_reg = 0;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* check if this pin is available */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ spin_unlock_irqrestore(&chip->lock, flags);
+ pr_info("GPIO pin %u not available\n", offset);
+ return -EINVAL;
+ }
+
+ /* Program the GPIO Wake/Interrupt Switch offset is AMD_GPIO_MSWITCH */
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + AMD_GPIO_MSWITCH);
+ /* to disable all GPIO wake and interrupt*/
+ gpio_reg &= (~AMD_GPIO_WAKE_EN & ~AMD_GPIO_INTERRUPT_EN);
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + AMD_GPIO_MSWITCH));
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* clear wake status and interrupt status */
+ gpio_reg |= (AMD_GPIO_INTERPT_STATUS | AMD_GPIO_WAKE_STATUS);
+
+ /* Set disable both Pull Up and Pull Down and disable output */
+ gpio_reg &= (~AMD_GPIO_PULLUP_ENABLE & ~AMD_GPIO_PULLDN_ENABLE
+ & ~AMD_GPIO_DEB_CTRL & ~AMD_GPIO_SWCTRL_IN
+ & ~AMD_GPIO_WAKECTRL & ~AMD_GPIO_INTERPT_ENABLE);
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ /* Enable GPIO by writing to the corresponding IOMUX register */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + offset);
+ iomux_reg &= ~AMD_IOMUX_GPIO_MASK;
+
+ if(offset == 10 || offset == 72 || offset == 73 ||offset == 76)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC0;
+ else if(offset == 35 || offset == 64 || offset == 65 ||offset == 66 ||
+ offset == 71 || offset == 93 ||offset == 115 ||offset == 116)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC2;
+ else if(offset == 67 || offset == 70)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC3;
+ else
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC1;
+
+ iowrite8(iomux_reg, ((u8 *)amd_gpio_chip.iomuxbase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+
+static int amd_gpio_get(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* Read the GPIO register */
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return (gpio_reg & AMD_GPIO_GET_INPUT) ? 1 : 0;
+}
+
+static void amd_gpio_set(struct gpio_chip *c, unsigned offset, int val)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+ /* Set GPIO Output depending on 'val' */
+ if (val)
+ gpio_reg |= AMD_GPIO_SET_OUTPUT;
+ else
+ gpio_reg &= ~AMD_GPIO_SET_OUTPUT;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int amd_gpio_direction_input(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in output mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int amd_gpio_direction_output(struct gpio_chip *c, unsigned offset,
+ int val)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPI, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_INPUT) {
+ pr_info("GPIO %u can only be set in input mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+
+ gpio_reg |= AMD_GPIO_DRV_STRENGTH(2);
+ /* Set disable both Pull Up and Pull Down */
+ gpio_reg &= (~AMD_GPIO_PULLUP_ENABLE & ~AMD_GPIO_PULLDN_ENABLE
+ & ~AMD_GPIO_DEB_CTRL & ~AMD_GPIO_SWCTRL_IN
+ & ~AMD_GPIO_WAKECTRL & ~AMD_GPIO_INTERPT_ENABLE);
+ /* Enable output */
+ gpio_reg |= AMD_GPIO_OUTPUT_ENABLE;
+
+ /* Set GPIO Output depending on 'val' */
+ if (val)
+ gpio_reg |= AMD_GPIO_SET_OUTPUT;
+ else
+ gpio_reg &= ~AMD_GPIO_SET_OUTPUT;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static struct amd_gpio_chip amd_gpio_chip = {
+ .gpio = {
+ .owner = THIS_MODULE,
+ .label = DRV_NAME,
+
+ .base = 0,
+ .ngpio = AMD_GPIO_NUM_PINS,
+ .names = NULL,
+ .request = amd_gpio_request,
+ .get = amd_gpio_get,
+ .set = amd_gpio_set,
+ .direction_input = amd_gpio_direction_input,
+ .direction_output = amd_gpio_direction_output,
+ },
+};
+
+/*
+* The PCI Device ID table below is used to identify the platform
+* the driver is supposed to work for. Since this is a platform
+* driver, we need a way for us to be able to find the correct
+* platform when the driver gets loaded, otherwise we should
+* bail out.
+*/
+static DEFINE_PCI_DEVICE_TABLE(amd_gpio_pci_tbl) = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID,
+ PCI_ANY_ID, },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, amd_gpio_pci_tbl);
+
+static void amd_update_gpio_mask(void)
+{
+ u8 iomux_reg;
+
+ /*
+ * Some of the GPIO pins have an alternate function assigned to
+ * them. That will be reflected in the corresponding IOMUX
+ * registers. If so, we mark these GPIO pins as reserved.
+ */
+
+ /* AGPIO10 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x0A);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[10] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO19 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x13);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[19] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO20 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x14);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[20] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO26 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1A);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[26] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO27 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1B);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[27] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO28 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1C);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[28] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO29 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[29] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO30 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1E);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[30] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO31 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1F);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[31] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO35 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x23);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[35] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO64 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x40);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[64] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO65 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x41);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[65] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO66 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x42);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[66] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO67 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x43);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2))
+ mask[67] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO68 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x44);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[68] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO69 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x45);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[68] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO70 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x46);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2))
+ mask[70] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO71 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x47);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[71] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO72 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x48);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[72] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO73 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x49);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[73] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO76 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x4C);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[76] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO77 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x4D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[77] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO84 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x54);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[84] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO85 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x55);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[85] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO87 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x57);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[87] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO88 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x58);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[88] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO91 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x5B);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[91] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO93 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x5D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[93] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO115 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x73);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[115] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO116 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x74);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[116] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO130 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x82);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[86] = AMD_GPIO_MODE_RESV;
+}
+
+static int amd_gpio_init(struct platform_device *pdev)
+{
+ struct pci_dev *dev = NULL;
+ int i;
+ int err;
+
+ /* Match the PCI device */
+ for_each_pci_dev(dev) {
+ if (pci_match_id(amd_gpio_pci_tbl, dev) != NULL) {
+ amd_gpio_pci = dev;
+ break;
+ }
+ }
+
+ if (!amd_gpio_pci)
+ return -ENODEV;
+
+ /* GPIO registers range from AMD_GPIO_ACPIMMIO_BASE+1500h to
+ AMD_GPIO_ACPIMMIO_BASE+17FFh. */
+ if (!request_mem_region_exclusive(AMD_GPIO_ACPIMMIO_BASE
+ + AMD_GPIO_BANK_OFFSET, AMD_GPIO_MEM_MAP_SIZE, "AMD GPIO")) {
+ pr_err("mmio address 0x%04x already in use\n",
+ AMD_GPIO_ACPIMMIO_BASE + AMD_GPIO_BANK_OFFSET );
+ goto exit;
+ }
+ gpiobase_phys = AMD_GPIO_ACPIMMIO_BASE + AMD_GPIO_BANK_OFFSET;
+
+ amd_gpio_chip.gpiobase = ioremap(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+ if (!amd_gpio_chip.gpiobase) {
+ pr_err("failed to get gpiobase address\n");
+ goto unreg_gpio_region;
+ }
+
+ /* IOMUX Base Address starts from ACPI MMIO Base Address + 0xD00 */
+ if (!request_mem_region_exclusive(AMD_GPIO_ACPIMMIO_BASE
+ + AMD_IOMUX_MEM_MAP_OFFSET,
+ AMD_IOMUX_MEM_MAP_SIZE, "AMD IOMUX")) {
+ pr_err("mmio address 0x%04x already in use\n",
+ AMD_GPIO_ACPIMMIO_BASE + AMD_IOMUX_MEM_MAP_OFFSET);
+ goto unmap_gpio_region;
+ }
+ iomuxbase_phys = AMD_GPIO_ACPIMMIO_BASE + AMD_IOMUX_MEM_MAP_OFFSET;
+
+ amd_gpio_chip.iomuxbase = ioremap(iomuxbase_phys,
+ AMD_IOMUX_MEM_MAP_SIZE);
+ if (!amd_gpio_chip.iomuxbase) {
+ pr_err("failed to get iomuxbase address\n");
+ goto unreg_iomux_region;
+ }
+
+ /* Set up driver specific struct */
+ amd_gpio_chip.pdev = pdev;
+ spin_lock_init(&amd_gpio_chip.lock);
+
+ /* Register ourself with the GPIO core */
+ err = gpiochip_add(&amd_gpio_chip.gpio);
+ if (err)
+ goto unmap_iomux_region;
+
+ /*
+ * Lets take care of special GPIO pins, and mark them as reserved
+ * as appropriate.
+ */
+ amd_update_gpio_mask();
+
+ /*
+ * If the number of GPIO pins provided during module loading does
+ * not match the number of GPIO modes, we fall back to the default
+ * mask.
+ */
+ if (num_mask == num_modes) {
+ /*
+ * If the number of masks or the number of modes specified
+ * is more than the maximum number of GPIO pins supported
+ * by the driver, we set the limit to the one supported
+ * driver.
+ */
+ if (num_mask > AMD_GPIO_NUM_PINS)
+ num_mask = num_modes = AMD_GPIO_NUM_PINS;
+
+ /*
+ * The default mask is our de facto standard. The GPIO
+ * pins marked reserved in the default mask stay reserved
+ * no matter what the module load parameter says. Also, we
+ * set the mode of the GPIO pins depending on the value
+ * of gpio_mode provided.
+ */
+ for (i = 0; i < num_mask; i++) {
+ if (mask[gpio_mask[i]] != AMD_GPIO_MODE_RESV) {
+ mask[gpio_mask[i]] = gpio_mode[i];
+
+ /*
+ * gpio_request() can fail, in which case we
+ * won't set the GPIO modes.
+ */
+ if(!gpio_request(gpio_mask[i], DRV_NAME)) {
+ if (gpio_mode[i] ==
+ AMD_GPIO_MODE_INPUT)
+ gpio_direction_input(gpio_mask[i]);
+ else if (gpio_mode[i] ==
+ AMD_GPIO_MODE_OUTPUT)
+ gpio_direction_output(gpio_mask[i],
+ 0);
+
+ gpio_free(gpio_mask[i]);
+ }
+ }
+ }
+ }
+
+ return 0;
+
+unmap_iomux_region:
+ iounmap(amd_gpio_chip.iomuxbase);
+unreg_iomux_region:
+ release_mem_region(iomuxbase_phys, AMD_IOMUX_MEM_MAP_SIZE);
+unmap_gpio_region:
+ iounmap(amd_gpio_chip.gpiobase);
+unreg_gpio_region:
+ release_mem_region(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+exit:
+ return -ENODEV;
+}
+
+static int amd_gpio_remove(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpiochip_remove(&amd_gpio_chip.gpio);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to remove gpio chip\n");
+ return err;
+ }
+
+ iounmap(amd_gpio_chip.iomuxbase);
+ release_mem_region(iomuxbase_phys, AMD_IOMUX_MEM_MAP_SIZE);
+ iounmap(amd_gpio_chip.gpiobase);
+ release_mem_region(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+
+ return 0;
+}
+
+static struct platform_driver amd_gpio_driver = {
+ .probe = amd_gpio_init,
+ .remove = amd_gpio_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = GPIO_MODULE_NAME,
+ },
+};
+
+/* interface to debug driver for gpio */
+
+static int amd_gpio_swctrlen(int offset, int value)
+{
+ struct amd_gpio_chip *chip = &amd_gpio_chip;
+ u32 gpio_reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ pr_info("GPIO %u is reserved\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in output mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ /* enable or disable sw input */
+ if(value)
+ gpio_reg |= AMD_GPIO_SWCTRL_EN;
+ else
+ gpio_reg &= ~AMD_GPIO_SWCTRL_EN;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int amd_gpio_swctrlin(int offset, int value)
+{
+ struct amd_gpio_chip *chip = &amd_gpio_chip;
+ u32 gpio_reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ pr_info("GPIO %u is reserved\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in input mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ /* enable or disable sw input */
+ if(value)
+ gpio_reg |= AMD_GPIO_SWCTRL_IN;
+ else
+ gpio_reg &= ~AMD_GPIO_SWCTRL_IN;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+
+static int gpio_test_open(struct inode *inode, struct file *filp)
+{
+ struct gpio_test_dev *dev; /* device information */
+
+ dev = container_of(inode->i_cdev, struct gpio_test_dev, cdev);
+ filp->private_data = dev; /* for other methods */
+
+ return 0; /* success */
+}
+
+static int gpio_test_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long gpio_test_ioctl(struct file *filp,
+ unsigned cmd, unsigned long arg)
+{
+
+ debug_data tmp;
+ unsigned long retval = 0;
+
+ /* Check type and command number */
+ if (_IOC_TYPE(cmd) != GPIO_TEST_IOC_MAGIC)
+ return -ENOTTY;
+
+ retval = copy_from_user(&tmp, (void __user *)arg, sizeof(debug_data));
+ if(retval != 0)
+ return 0;
+
+ switch(cmd) {
+ case GPIO_IOC_SWCTRLIN:
+ retval = amd_gpio_swctrlin(tmp.offset,tmp.value);
+ break;
+ case GPIO_IOC_SWCTRLEN:
+ retval = amd_gpio_swctrlen(tmp.offset,tmp.value);
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ return retval;
+}
+
+struct file_operations gpio_test_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = gpio_test_ioctl,
+ .open = gpio_test_open,
+ .release = gpio_test_release,
+};
+
+
+static int __init amd_gpio_init_module(void)
+{
+ int err;
+ dev_t dev = 0;
+ struct device *gpio_device = 0;
+
+ pr_info("AMD GPIO Driver v%s\n", GPIO_VERSION);
+
+ err = platform_driver_register(&amd_gpio_driver);
+ if (err)
+ return err;
+
+ err = alloc_chrdev_region(&dev, dev_minor, 1,"gpio_test_driver");
+ if (err < 0) {
+ printk(KERN_WARNING " can't get major %d\n", dev_major);
+ goto unreg_platform_driver;
+ }
+
+ gpio_test_dev.gpio_class = class_create(THIS_MODULE, "gpio_test_driver");
+ if (IS_ERR(gpio_test_dev.gpio_class)) {
+ printk(" error in class create \n");
+ goto unregister_test_driver;
+ }
+
+ dev_major = MAJOR(dev);
+
+ gpio_device = device_create(gpio_test_dev.gpio_class, NULL, dev, NULL,
+ "gpio_test_driver");
+ if (IS_ERR(gpio_device)) {
+ printk(" error in device create \n");
+ goto destroy_class;
+ }
+
+ cdev_init(&gpio_test_dev.cdev, &gpio_test_fops);
+ err = cdev_add (&gpio_test_dev.cdev, dev, 1);
+ if(err)
+ goto destroy_device;
+
+ amd_gpio_platform_device = platform_device_register_simple(
+ GPIO_MODULE_NAME, -1, NULL, 0);
+ if (IS_ERR(amd_gpio_platform_device)) {
+ err = PTR_ERR(amd_gpio_platform_device);
+ goto cdev_delete;
+ }
+
+ return 0;
+
+cdev_delete:
+ cdev_del(&gpio_test_dev.cdev);
+destroy_device:
+ device_destroy(gpio_test_dev.gpio_class, dev);
+destroy_class:
+ class_destroy(gpio_test_dev.gpio_class);
+unregister_test_driver:
+ unregister_chrdev_region(dev, 1);
+unreg_platform_driver:
+ platform_driver_unregister(&amd_gpio_driver);
+ return err;
+}
+
+static void __exit amd_gpio_cleanup_module(void)
+{
+ dev_t dev = MKDEV(dev_major, dev_minor);
+
+ device_destroy(gpio_test_dev.gpio_class, dev);
+ class_destroy(gpio_test_dev.gpio_class);
+ cdev_del(&gpio_test_dev.cdev);
+ unregister_chrdev_region(dev, 1);
+ platform_device_unregister(amd_gpio_platform_device);
+ platform_driver_unregister(&amd_gpio_driver);
+ pr_info("AMD GPIO Module Unloaded\n");
+}
+
+module_init(amd_gpio_init_module);
+module_exit(amd_gpio_cleanup_module);
+
+
+
+MODULE_AUTHOR("Sudheesh Mavila <sudheesh.mavila@amd.com>");
+MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h
new file mode 100644
index 00000000..5574ef53
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h
@@ -0,0 +1,85 @@
+#ifndef _AMD_GPIO_H_
+#define _AMD_GPIO_H_
+
+#include <linux/types.h>
+
+/* Module and version information */
+#define GPIO_VERSION "0.1"
+#define GPIO_MODULE_NAME "AMD GPIO"
+#define GPIO_DRIVER_NAME GPIO_MODULE_NAME ", v" GPIO_VERSION
+
+#define DRV_NAME "amd-gpio"
+
+/* GPIO register definitions */
+#define AMD_GPIO_ACPIMMIO_BASE 0xFED80000
+#define AMD_GPIO_BANK_OFFSET 0x1500
+#define AMD_GPIO_MEM_MAP_SIZE 0x300
+#define AMD_GPIO_MSWITCH 63
+
+#define AMD_IOMUX_MEM_MAP_OFFSET 0x0D00
+#define AMD_IOMUX_MEM_MAP_SIZE 0x100
+
+#define AMD_PM_IOPORTS_SIZE 0x02
+
+/* IO port address for indirect access using the ACPI PM registers */
+#define AMD_IO_PM_INDEX_REG 0xCD6
+#define AMD_IO_PM_DATA_REG 0xCD7
+
+#define AMD_GPIO_NUM_PINS 184
+
+#define AMD_GPIO_DEB_TIMEOUT0 (0) /* debouncing logic disabled */
+#define AMD_GPIO_DEB_TIMEOUT1 (1)
+#define AMD_GPIO_DEB_TIMEOUT_MASK (7)
+#define AMD_GPIO_DEB_TIMEOUTUNIT (1 << 4)
+#define AMD_GPIO_DEB_CTRL (3 << 5)
+#define AMD_GPIO_LEVL_TRG (1 << 8) /* 0 - edge , 1 level */
+#define AMD_GPIO_ACTIVE_LEVEL (3 << 9)
+#define AMD_GPIO_INTERPT_ENABLE (3 << 11)
+#define AMD_GPIO_WAKECTRL (7 << 13)
+#define AMD_GPIO_GET_INPUT (1 << 16)
+#define AMD_GPIO_DRV_STRENGTH(x) (((x) & 3) << 17)
+#define AMD_GPIO_PULLUP_SEL (1 << 19)
+#define AMD_GPIO_PULLUP_ENABLE (1 << 20)
+#define AMD_GPIO_PULLDN_ENABLE (1 << 21)
+#define AMD_GPIO_SET_OUTPUT (1 << 22)
+#define AMD_GPIO_OUTPUT_ENABLE (1 << 23)
+#define AMD_GPIO_SWCTRL_IN (1 << 24)
+#define AMD_GPIO_SWCTRL_EN (1 << 25)
+#define AMD_GPIO_INTERPT_STATUS (1 << 28)
+#define AMD_GPIO_WAKE_STATUS (1 << 29)
+
+#define AMD_GPIO_WAKE_EN (1 << 31)
+#define AMD_GPIO_INTERRUPT_EN (1 << 30)
+
+#define AMD_IOMUX_ENABLE_FUNC0 0x0
+#define AMD_IOMUX_ENABLE_FUNC1 0x1
+#define AMD_IOMUX_ENABLE_FUNC2 0x2
+#define AMD_IOMUX_ENABLE_FUNC3 0x3
+#define AMD_IOMUX_GPIO_MASK 0x03
+
+#define AMD_PM_GPIO_BASE0 0x24
+#define AMD_PM_GPIO_BASE1 0x25
+#define AMD_PM_GPIO_BASE2 0x26
+#define AMD_PM_GPIO_BASE3 0x27
+
+
+
+
+/* GPIO pin mode definitions */
+#define AMD_GPIO_MODE_RESV 0 /* Reserved */
+#define AMD_GPIO_MODE_ANY 1 /* Either input or output */
+#define AMD_GPIO_MODE_INPUT 2 /* GPI */
+#define AMD_GPIO_MODE_OUTPUT 3 /* GPO */
+
+/* IOCTL numbers */
+
+typedef struct {
+ int offset;
+ int value;
+}debug_data;
+
+#define GPIO_TEST_IOC_MAGIC 'k'
+#define GPIO_IOC_SWCTRLIN _IOW(GPIO_TEST_IOC_MAGIC, 1, debug_data)
+#define GPIO_IOC_SWCTRLEN _IOW(GPIO_TEST_IOC_MAGIC, 2, debug_data)
+
+#endif /* _AMD_GPIO_H_ */
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/amd-spi_1.0.bb b/meta-steppeeagle/recipes-kernel/amd-spi/amd-spi_1.0.bb
new file mode 100644
index 00000000..f4304d4d
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/amd-spi_1.0.bb
@@ -0,0 +1,33 @@
+DESCRIPTION = "This kernel module provides support for AMD SPI controller driver"
+LICENSE = "BSD | GPLv2"
+LIC_FILES_CHKSUM = "file://spi_amd.c;md5=3cbc6410f1e2b6009f1a74731f6fc557 \
+ file://spi_amd.h;md5=2233c2a926f120b07153e3ea0ba7474f \
+ file://spirom.c;md5=1f5bba5ab39fb0759286aab09b55bc84 \
+ file://spirom.h;md5=56f117ed31b82b02182c7a491364d112 \
+ file://Makefile;md5=8ea80a6d4ae15bcf922d090df6cfdd4c \
+ "
+
+inherit module
+
+PR = "r0"
+PV = "1.0"
+
+SRC_URI = "file://Makefile \
+ file://spi_amd.c \
+ file://spi_amd.h \
+ file://spirom.c \
+ file://spirom.h \
+ "
+
+S = "${WORKDIR}"
+
+
+# Kernel module packages MUST begin with 'kernel-module-', otherwise
+# multilib image generation can fail.
+#
+# The following line is only necessary if the recipe name does not begin
+# with kernel-module-.
+#
+PKG_${PN} = "kernel-module-${PN}"
+
+FILES_${PN} += "${sysconfdir}"
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/files/Makefile b/meta-steppeeagle/recipes-kernel/amd-spi/files/Makefile
new file mode 100644
index 00000000..f778a69a
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/files/Makefile
@@ -0,0 +1,14 @@
+obj-m := spi_amd.o spirom.o
+
+SRC := $(shell pwd)
+
+all:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
+
+modules_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
+
+clean:
+ rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
+ rm -f Module.markers Module.symvers modules.order
+ rm -rf .tmp_versions Modules.symvers
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.c b/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.c
new file mode 100644
index 00000000..554bd352
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.c
@@ -0,0 +1,492 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spi/spi.h>
+#include <linux/kthread.h>
+
+#include "spi_amd.h"
+
+struct amd_platform_data {
+ u8 chip_select;
+};
+
+struct amd_spi {
+ void __iomem *io_remap_addr;
+ unsigned long io_base_addr;
+ u32 rom_addr;
+ struct spi_master *master;
+ struct amd_platform_data controller_data;
+ spinlock_t lock;
+ struct task_struct *kthread_spi;
+ struct list_head msg_queue;
+};
+
+static struct pci_device_id amd_spi_pci_device_id[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LPC_BRIDGE) },
+ {}
+};
+MODULE_DEVICE_TABLE(pci, amd_spi_pci_device_id);
+
+static inline u8 amd_spi_readreg8(struct spi_master *master, int idx)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ return ioread8((u8 *)amd_spi->io_remap_addr + idx);
+}
+
+static inline void amd_spi_writereg8(struct spi_master *master, int idx,
+ u8 val)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ iowrite8(val, ((u8 *)amd_spi->io_remap_addr + idx));
+}
+
+static inline void amd_spi_setclear_reg8(struct spi_master *master, int idx,
+ u8 set, u8 clear)
+{
+ u8 tmp = amd_spi_readreg8(master, idx);
+ tmp = (tmp & ~clear) | set;
+ amd_spi_writereg8(master, idx, tmp);
+}
+
+static inline u32 amd_spi_readreg32(struct spi_master *master, int idx)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ return ioread32((u8 *)amd_spi->io_remap_addr + idx);
+}
+
+static inline void amd_spi_writereg32(struct spi_master *master, int idx,
+ u32 val)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ iowrite32(val, ((u8 *)amd_spi->io_remap_addr + idx));
+}
+
+static inline void amd_spi_setclear_reg32(struct spi_master *master, int idx,
+ u32 set, u32 clear)
+{
+ u32 tmp = amd_spi_readreg32(master, idx);
+ tmp = (tmp & ~clear) | set;
+ amd_spi_writereg32(master, idx, tmp);
+}
+
+static void amd_spi_select_chip(struct spi_master *master)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+ u8 chip_select = amd_spi->controller_data.chip_select;
+
+ amd_spi_setclear_reg8(master, AMD_SPI_ALT_CS_REG, chip_select,
+ AMD_SPI_ALT_CS_MASK);
+}
+
+
+static void amd_spi_clear_fifo_ptr(struct spi_master *master)
+{
+ amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR,
+ AMD_SPI_FIFO_CLEAR);
+}
+
+static void amd_spi_set_opcode(struct spi_master *master, u8 cmd_opcode)
+{
+ amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, cmd_opcode,
+ AMD_SPI_OPCODE_MASK);
+}
+
+static inline void amd_spi_set_rx_count(struct spi_master *master,
+ u8 rx_count)
+{
+ amd_spi_setclear_reg8(master, AMD_SPI_RX_COUNT_REG, rx_count, 0xff);
+}
+
+static inline void amd_spi_set_tx_count(struct spi_master *master,
+ u8 tx_count)
+{
+ amd_spi_setclear_reg8(master, AMD_SPI_TX_COUNT_REG, tx_count, 0xff);
+}
+
+static void amd_spi_execute_opcode(struct spi_master *master)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+ bool spi_busy;
+
+ /* Set ExecuteOpCode bit in the CTRL0 register */
+ amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD,
+ AMD_SPI_EXEC_CMD);
+
+ /* poll for SPI bus to become idle */
+ spi_busy = (ioread32((u8 *)amd_spi->io_remap_addr +
+ AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY;
+ while (spi_busy) {
+ schedule();
+ spi_busy = (ioread32((u8 *)amd_spi->io_remap_addr +
+ AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY;
+ }
+}
+
+/* Helper function */
+#ifdef CONFIG_SPI_DEBUG
+static void amd_spi_dump_reg(struct spi_master *master)
+{
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ printk(KERN_DEBUG DRIVER_NAME ": SPI CTRL 0 registers: 0x%.8x\n",
+ ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG));
+ /*
+ * We cannot read CTRL1 register, because reading it would
+ * inadvertently increment the FIFO pointer.
+ */
+ printk(KERN_DEBUG DRIVER_NAME ": SPI ALT CS registers: 0x%.2x\n",
+ ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_ALT_CS_REG));
+ printk(KERN_DEBUG DRIVER_NAME ": SPI Tx Byte Count: 0x%.2x\n",
+ ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_TX_COUNT_REG));
+ printk(KERN_DEBUG DRIVER_NAME ": SPI Rx Byte Count: 0x%.2x\n",
+ ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_RX_COUNT_REG));
+ printk(KERN_DEBUG DRIVER_NAME ": SPI Status registers: 0x%.8x\n",
+ ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_STATUS_REG));
+}
+#else
+static void amd_spi_dump_reg(struct spi_master *master) {}
+#endif
+
+
+static int amd_spi_master_setup(struct spi_device *spi)
+{
+ struct spi_master *master = spi->master;
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ amd_spi->controller_data.chip_select = spi->chip_select;
+
+ amd_spi_select_chip(master);
+
+ return 0;
+}
+
+static int amd_spi_master_transfer(struct spi_device *spi,
+ struct spi_message *msg)
+{
+ struct spi_master *master = spi->master;
+ struct amd_spi *amd_spi = spi_master_get_devdata(master);
+
+ /*
+ * We will just add this message to the message queue set up by
+ * the controller, and let the kernel thread handle it later.
+ */
+ msg->status = -EINPROGRESS;
+ msg->actual_length = 0;
+ msg->spi = spi;
+ /*
+ * There could be a situation when we are running on this processor
+ * and trying to add element to the end of the message queue, but
+ * at the same time the kernel thread is running on another processor
+ * and trying to find out if the list is empty or not. So protect
+ * against such contention. Simple spin_lock() should do.
+ */
+ spin_lock(&amd_spi->lock);
+ list_add_tail(&msg->queue, &amd_spi->msg_queue);
+ spin_unlock(&amd_spi->lock);
+
+ return 0;
+}
+static int amd_spi_thread(void *t)
+{
+ struct amd_spi *amd_spi = t;
+ struct spi_master *master = amd_spi->master;
+ struct spi_transfer *transfer = NULL;
+ struct spi_message *message = NULL;
+ int direction = 0,i = 0,saved_index = 0;
+ int opcode_found = 0,recv_flag = 0,tx_len = 0,rx_len = 0;
+ u8 cmd_opcode = 0;
+ u8 *buffer = NULL;
+
+ /*
+ * What we do here is actually pretty simple. We pick one message
+ * at a time from the message queue set up by the controller, and
+ * then process all the spi_transfers of that spi_message in one go.
+ * We then remove the message from the queue, and complete the
+ * transaction. This might not be the best approach, but this is how
+ * we chose to implement this. Note that out SPI controller has FIFO
+ * size of 70 bytes, but we consider it to contain a maximum of
+ * 64-bytes of data and 3-bytes of address.
+ */
+ while (1) {
+ /* break condition */
+ if (kthread_should_stop()) {
+ set_current_state(TASK_RUNNING);
+ break;
+ }
+
+ /*
+ * If the message queue is empty, then there is no need to waste
+ * CPU cycles. So we let other processes execute, and continue
+ * from the beginning of the loop when we next get to run.
+ */
+ spin_lock(&amd_spi->lock);
+ if (list_empty(&amd_spi->msg_queue)) {
+ spin_unlock(&amd_spi->lock);
+ schedule();
+ continue;
+ }
+
+ /*
+ * Else, pull the very first message from the queue and process
+ * all transfers within that message. And process the messages
+ * in a pure linear fashion. We also remove the spi_message
+ * from the queue.
+ */
+ message = list_entry(amd_spi->msg_queue.next,
+ struct spi_message, queue);
+ list_del_init(&message->queue);
+ spin_unlock(&amd_spi->lock);
+
+ /* We store the CS# line to be used for this spi_message */
+ amd_spi->controller_data.chip_select =
+ message->spi->chip_select;
+
+ /* Setting all variables to default value. */
+ direction = i = 0;
+ opcode_found = 0;
+ recv_flag = tx_len = rx_len = 0;
+ cmd_opcode = 0;
+ buffer = NULL;
+ saved_index = 0;
+
+ amd_spi_select_chip(master);
+
+ /*
+ * This loop extracts spi_transfers from the spi message,
+ * programs the command into command register. Pointer variable
+ * *buffer* points to either tx_buf or rx_buf of spi_transfer
+ * depending on direction of transfer. Also programs FIFO of
+ * controller if data has to be transmitted.
+ */
+ list_for_each_entry(transfer, &message->transfers,
+ transfer_list)
+ {
+ if(transfer->rx_buf != NULL)
+ direction = RECEIVE;
+ else if(transfer->tx_buf != NULL)
+ direction = TRANSMIT;
+
+ switch (direction) {
+ case TRANSMIT:
+ buffer = (u8 *)transfer->tx_buf;
+
+ if(opcode_found != 1) {
+ /* Store no. of bytes to be sent into
+ * FIFO */
+ tx_len = transfer->len - 1;
+ /* Store opcode */
+ cmd_opcode = *(u8 *)transfer->tx_buf;
+ /* Pointing to start of TX data */
+ buffer++;
+ /* Program the command register*/
+ amd_spi_set_opcode(master, cmd_opcode);
+ opcode_found = 1;
+ } else {
+ /* Store no. of bytes to be sent into
+ * FIFO */
+ tx_len = transfer->len;
+ }
+
+ /* Write data into the FIFO. */
+ for (i = 0; i < tx_len; i++) {
+ iowrite8(buffer[i],
+ ((u8 *)amd_spi->io_remap_addr +
+ AMD_SPI_FIFO_BASE +
+ i + saved_index));
+ }
+
+ /* Set no. of bytes to be transmitted */
+ amd_spi_set_tx_count(master,
+ tx_len + saved_index);
+
+ /*
+ * Saving the index, from where next
+ * spi_transfer's data will be stored in FIFO.
+ */
+ saved_index = i;
+ break;
+ case RECEIVE:
+ /* Store no. of bytes to be received from
+ * FIFO */
+ rx_len = transfer->len;
+ buffer = (u8 *)transfer->rx_buf;
+ recv_flag=1;
+ break;
+ }
+ }
+
+ /* Set the RX count to the number of bytes to expect in
+ * response */
+ amd_spi_set_rx_count(master, rx_len );
+ amd_spi_clear_fifo_ptr(master);
+ amd_spi_dump_reg(master);
+ /* Executing command */
+ amd_spi_execute_opcode(master);
+ amd_spi_dump_reg(master);
+
+ if(recv_flag == 1) {
+ /* Read data from FIFO to receive buffer */
+ for (i = 0; i < rx_len; i++) {
+ buffer[i] = ioread8((u8 *)amd_spi->io_remap_addr
+ + AMD_SPI_FIFO_BASE
+ + tx_len + i);
+ }
+
+ recv_flag = 0;
+ }
+
+ /* Update statistics */
+ message->actual_length = tx_len + rx_len + 1 ;
+ /* complete the transaction */
+ message->status = 0;
+ message->complete(message->context);
+ }
+
+ return 0;
+}
+
+static int amd_spi_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct device *dev = &pdev->dev;
+ struct spi_master *master;
+ struct amd_spi *amd_spi;
+ u32 io_base_addr;
+ int err = 0;
+
+ /* Allocate storage for spi_master and driver private data */
+ master = spi_alloc_master(dev, sizeof(struct amd_spi));
+ if (master == NULL) {
+ dev_err(dev, "Error allocating SPI master\n");
+ return -ENOMEM;
+ }
+
+ amd_spi = spi_master_get_devdata(master);
+ amd_spi->master = master;
+
+ /*
+ * Lets first get the base address of SPI registers. The SPI Base
+ * Address is stored at offset 0xA0 into the LPC PCI configuration
+ * space. As per the specification, it is stored at bits 6:31 of the
+ * register. The address is aligned at 64-byte boundary,
+ * so we should just mask the lower 6 bits and get the address.
+ */
+ pci_read_config_dword(pdev, AMD_PCI_LPC_SPI_BASE_ADDR_REG,
+ &io_base_addr);
+ amd_spi->io_base_addr = io_base_addr & AMD_SPI_BASE_ADDR_MASK;
+ amd_spi->io_remap_addr = ioremap_nocache(amd_spi->io_base_addr,
+ AMD_SPI_MEM_SIZE);
+ if (amd_spi->io_remap_addr == NULL) {
+ dev_err(dev, "ioremap of SPI registers failed\n");
+ err = -ENOMEM;
+ goto err_free_master;
+ }
+ dev_dbg(dev, "io_base_addr: 0x%.8lx, io_remap_address: %p\n",
+ amd_spi->io_base_addr, amd_spi->io_remap_addr);
+ spin_lock_init(&amd_spi->lock);
+ INIT_LIST_HEAD(&amd_spi->msg_queue);
+ amd_spi->kthread_spi = kthread_run(amd_spi_thread, amd_spi,
+ "amd_spi_thread");
+
+ /* Now lets initialize the fields of spi_master */
+ master->bus_num = 0; /*
+ * This should be the same as passed in
+ * spi_board_info structure
+ */
+ master->num_chipselect = 4; /* Can be overwritten later during setup */
+ master->mode_bits = 0;
+ master->flags = 0;
+ master->setup = amd_spi_master_setup;
+ master->transfer = amd_spi_master_transfer;
+ /* Register the controller with SPI framework */
+ err = spi_register_master(master);
+ if (err) {
+ dev_err(dev, "error registering SPI controller\n");
+ goto err_iounmap;
+ }
+ pci_set_drvdata(pdev, amd_spi);
+
+ return 0;
+
+err_iounmap:
+ iounmap(amd_spi->io_remap_addr);
+err_free_master:
+ spi_master_put(master);
+
+ return 0;
+}
+
+static void amd_spi_pci_remove(struct pci_dev *pdev)
+{
+ struct amd_spi *amd_spi = pci_get_drvdata(pdev);
+
+ kthread_stop(amd_spi->kthread_spi);
+ iounmap(amd_spi->io_remap_addr);
+ spi_unregister_master(amd_spi->master);
+ spi_master_put(amd_spi->master);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_driver amd_spi_pci_driver = {
+ .name = "amd_spi",
+ .id_table = amd_spi_pci_device_id,
+ .probe = amd_spi_pci_probe,
+ .remove = amd_spi_pci_remove,
+};
+
+static int __init amd_spi_init(void)
+{
+ int ret;
+
+ pr_info("AMD SPI Driver v%s\n", SPI_VERSION);
+
+ ret = pci_register_driver(&amd_spi_pci_driver);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+module_init(amd_spi_init);
+
+static void __exit amd_spi_exit(void)
+{
+ pci_unregister_driver(&amd_spi_pci_driver);
+}
+module_exit(amd_spi_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Arindam Nath <arindam.nath@amd.com>");
+MODULE_DESCRIPTION("AMD SPI Master Controller Driver");
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.h b/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.h
new file mode 100644
index 00000000..ea5181d7
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/files/spi_amd.h
@@ -0,0 +1,28 @@
+#ifndef SPI_AMD_H
+#define SPI_AMD_H
+
+#define DRIVER_NAME "spi_amd"
+#define SPI_VERSION "0.1"
+
+#define AMD_SPI_CTRL0_REG 0x00
+ #define AMD_SPI_EXEC_CMD (0x1 << 16)
+ #define AMD_SPI_OPCODE_MASK 0xFF
+ #define AMD_SPI_FIFO_CLEAR (0x1 << 20)
+ #define AMD_SPI_BUSY (0x1 << 31)
+#define AMD_SPI_ALT_CS_REG 0x1D
+ #define AMD_SPI_ALT_CS_MASK 0x3
+#define AMD_SPI_FIFO_BASE 0x80
+#define AMD_SPI_TX_COUNT_REG 0x48
+#define AMD_SPI_RX_COUNT_REG 0x4B
+#define AMD_SPI_STATUS_REG 0x4C
+
+#define AMD_PCI_LPC_SPI_BASE_ADDR_REG 0xA0
+#define AMD_SPI_BASE_ADDR_MASK ~0x3F
+#define AMD_SPI_MEM_SIZE 200
+
+#define PCI_DEVICE_ID_AMD_LPC_BRIDGE 0x780E
+
+#define TRANSMIT 1
+#define RECEIVE 2
+
+#endif /* SPI_AMD_H */
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.c b/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.c
new file mode 100644
index 00000000..439961bc
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.c
@@ -0,0 +1,516 @@
+/*****************************************************************************
+*
+* spirom.c - SPI ROM client driver
+*
+* Copyright (c) 2014, Advanced Micro Devices, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*
+***************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <asm/uaccess.h>
+
+#include "spirom.h"
+
+#define SPIROM_VERSION "0.1"
+
+/*
+ * SPI has a character major number assigned. We allocate minor numbers
+ * dynamically using a bitmask. You must use hotplug tools, such as udev
+ * (or mdev with busybox) to create and destroy the /dev/spiromB.C device
+ * nodes, since there is no fixed association of minor numbers with any
+ * particular SPI bus or device.
+ */
+#define SPIROM_MAJOR 153 /* assigned */
+#define N_SPI_MINORS 32 /* ... up to 256 */
+
+#define SPI_BUS 0
+#define SPI_BUS_CS1 0
+
+static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG];
+
+
+struct spirom_data {
+ dev_t devt;
+ spinlock_t spi_lock;
+ struct spi_device *spi;
+ struct list_head device_entry;
+ struct completion done;
+
+ struct mutex buf_lock;
+ unsigned users;
+};
+
+static LIST_HEAD(device_list);
+static DEFINE_MUTEX(device_list_lock);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * We can't use the standard synchronous wrappers for file I/O; we
+ * need to protect against async removal of the underlying spi_device.
+ */
+static void spirom_complete(void *arg)
+{
+ complete(arg);
+}
+
+static ssize_t
+spirom_sync(struct spirom_data *spirom, struct spi_message *message)
+{
+ int status;
+
+ message->complete = spirom_complete;
+ message->context = &spirom->done;
+
+ spin_lock_irq(&spirom->spi_lock);
+ if (spirom->spi == NULL)
+ status = -ESHUTDOWN;
+ else
+ status = spi_async(spirom->spi, message);
+ spin_unlock_irq(&spirom->spi_lock);
+
+ if (status == 0) {
+ /*
+ * There might be cases where the controller driver has been
+ * unloaded in the middle of a transaction. So we might end up
+ * in a situation where we will be waiting for an event which
+ * will never happen. So we provide a timeout of 1 second for
+ * situations like this.
+ */
+ wait_for_completion_timeout(&spirom->done, HZ);
+ status = message->status;
+ if (status == 0)
+ status = message->actual_length;
+ }
+ return status;
+}
+
+static int spirom_message(struct spirom_data *spirom,
+ struct spi_ioc_transfer *u_trans, unsigned long arg)
+{
+ struct spi_message msg;
+ struct spi_transfer *transfer;
+ u8 *buffer;
+ int status = u_trans->len;
+
+ buffer = u_trans->buf;
+ spi_message_init(&msg);
+
+ /* The very first spi_transfer will contain the command only */
+ transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!transfer)
+ return -ENOMEM;
+
+ transfer->tx_buf = buffer;
+ transfer->len = 1;
+ buffer += transfer->len;
+ spi_message_add_tail(transfer, &msg);
+
+ /*
+ * If the command expects an address as its argument, we populate
+ * it in the very next spi_transfer.
+ */
+ if (u_trans->addr_present) {
+ transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!transfer)
+ return -ENOMEM;
+
+ transfer->tx_buf = buffer;
+ transfer->len = 3; // 3-byte address
+ buffer += transfer->len;
+ spi_message_add_tail(transfer, &msg);
+ }
+
+ /*
+ * Next is data, which can have a maximum of 64-bytes, the size limited
+ * by the number of bytes that can stored in the controller FIFO.
+ */
+ if (u_trans->len) {
+ transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!transfer)
+ return -ENOMEM;
+
+ if (u_trans->direction == TRANSMIT)
+ transfer->tx_buf = buffer;
+ else if (u_trans->direction == RECEIVE)
+ transfer->rx_buf = buffer;
+
+ transfer->len = u_trans->len;
+ /* No need to increment buffer pointer */
+ spi_message_add_tail(transfer, &msg);
+ }
+
+ status = spirom_sync(spirom, &msg);
+
+ if (u_trans->direction == RECEIVE) {
+ /*
+ * The received data should have been populated in
+ * u_trans->buf, so we just need to copy it into the
+ * user-space buffer.
+ */
+ buffer = u_trans->buf;
+ if (u_trans->addr_present) {
+ buffer += 4; // 1-byte command and 3-byte address
+ if(__copy_to_user((u8 __user *)
+ (((struct spi_ioc_transfer *)arg)->buf) + 4,
+ buffer, u_trans->len)) {
+ status = -EFAULT;
+ }
+ } else {
+ buffer += 1; // 1-byte command only
+ if(__copy_to_user((u8 __user *)
+ (((struct spi_ioc_transfer *)arg)->buf) + 1,
+ buffer, u_trans->len)) {
+ status = -EFAULT;
+ }
+ }
+ }
+
+ /* Done with everything, free the memory taken by spi_transfer */
+ while (msg.transfers.next != &msg.transfers) {
+ transfer = list_entry(msg.transfers.next, struct spi_transfer,
+ transfer_list);
+ msg.transfers.next = transfer->transfer_list.next;
+ transfer->transfer_list.next->prev = &msg.transfers;
+ kfree(transfer);
+ }
+
+ return status;
+}
+
+static long
+spirom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ int retval = 0;
+ struct spirom_data *spirom;
+ struct spi_device *spi;
+ u32 tmp;
+ struct spi_ioc_transfer *ioc;
+
+ /* Check type and command number */
+ if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
+ return -ENOTTY;
+
+ /* Check access direction once here; don't repeat below.
+ * IOC_DIR is from the user perspective, while access_ok is
+ * from the kernel perspective; so they look reversed.
+ */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE,
+ (void __user *)arg, _IOC_SIZE(cmd));
+ if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ,
+ (void __user *)arg, _IOC_SIZE(cmd));
+ if (err)
+ return -EFAULT;
+
+ /* guard against device removal before, or while,
+ * we issue this ioctl.
+ */
+ spirom = filp->private_data;
+ spin_lock_irq(&spirom->spi_lock);
+ spi = spi_dev_get(spirom->spi);
+ spin_unlock_irq(&spirom->spi_lock);
+
+ if (spi == NULL)
+ return -ESHUTDOWN;
+
+ /* use the buffer lock here for triple duty:
+ * - prevent I/O (from us) so calling spi_setup() is safe;
+ * - prevent concurrent SPI_IOC_WR_* from morphing
+ * data fields while SPI_IOC_RD_* reads them;
+ * - SPI_IOC_MESSAGE needs the buffer locked "normally".
+ */
+ mutex_lock(&spirom->buf_lock);
+
+ /* segmented and/or full-duplex I/O request */
+ if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) ||
+ _IOC_DIR(cmd) !=_IOC_WRITE) {
+ retval = -ENOTTY;
+ goto out;
+ }
+
+ tmp = sizeof(struct spi_ioc_transfer);
+
+ /* copy into scratch area */
+ ioc = kzalloc(tmp, GFP_KERNEL);
+ if (!ioc) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ if (__copy_from_user(ioc, (struct spi_ioc_transfer __user *)arg,
+ tmp)) {
+ kfree(ioc);
+ retval = -EFAULT;
+ goto out;
+ }
+
+ /* translate to spi_message, execute */
+ retval = spirom_message(spirom, ioc, arg);
+ kfree(ioc);
+
+out:
+ mutex_unlock(&spirom->buf_lock);
+ spi_dev_put(spi);
+ return retval;
+}
+
+static int spirom_open(struct inode *inode, struct file *filp)
+{
+ struct spirom_data *spirom;
+ int status = -ENXIO;
+
+ mutex_lock(&device_list_lock);
+
+ list_for_each_entry(spirom, &device_list, device_entry) {
+ if (spirom->devt == inode->i_rdev) {
+ status = 0;
+ break;
+ }
+ }
+ if (status == 0) {
+ if (status == 0) {
+ spirom->users++;
+ filp->private_data = spirom;
+ nonseekable_open(inode, filp);
+ }
+ } else
+ pr_debug("spirom: nothing for minor %d\n", iminor(inode));
+
+ mutex_unlock(&device_list_lock);
+ return status;
+}
+
+static int spirom_release(struct inode *inode, struct file *filp)
+{
+ struct spirom_data *spirom;
+ int status = 0;
+
+ mutex_lock(&device_list_lock);
+ spirom = filp->private_data;
+ filp->private_data = NULL;
+
+ /* last close? */
+ spirom->users--;
+ if (!spirom->users) {
+ int dofree;
+
+ /* ... after we unbound from the underlying device? */
+ spin_lock_irq(&spirom->spi_lock);
+ dofree = (spirom->spi == NULL);
+ spin_unlock_irq(&spirom->spi_lock);
+
+ if (dofree)
+ kfree(spirom);
+ }
+ mutex_unlock(&device_list_lock);
+
+ return status;
+}
+
+static const struct file_operations spirom_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = spirom_ioctl,
+ .open = spirom_open,
+ .release = spirom_release,
+};
+
+static int __init add_spi_device_to_bus(void)
+{
+ struct spi_master *spi_master;
+ struct spi_device *spi_device;
+ struct spi_board_info spi_info;
+
+ spi_master = spi_busnum_to_master(SPI_BUS);
+ if (!spi_master) {
+ printk(KERN_ALERT "Please make sure to \'modprobe "
+ "spi_amd\' driver first\n");
+ return -1;
+ }
+ memset(&spi_info, 0, sizeof(struct spi_board_info));
+
+ strlcpy(spi_info.modalias, "spirom", SPI_NAME_SIZE);
+ spi_info.bus_num = SPI_BUS; //Bus number of SPI master
+ spi_info.chip_select = SPI_BUS_CS1; //CS on which SPI device is connected
+
+ spi_device = spi_new_device(spi_master, &spi_info);
+ if (!spi_device)
+ return -ENODEV;
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* The main reason to have this class is to make mdev/udev create the
+ * /dev/spiromB.C character device nodes exposing our userspace API.
+ * It also simplifies memory management.
+ */
+
+static struct class *spirom_class;
+
+/*-------------------------------------------------------------------------*/
+
+static int spirom_probe(struct spi_device *spi)
+{
+ struct spirom_data *spirom;
+ int status;
+ unsigned long minor;
+
+ /* Allocate driver data */
+ spirom = kzalloc(sizeof(*spirom), GFP_KERNEL);
+ if (!spirom)
+ return -ENOMEM;
+
+ /* Initialize the driver data */
+ spirom->spi = spi;
+ spin_lock_init(&spirom->spi_lock);
+ mutex_init(&spirom->buf_lock);
+
+ INIT_LIST_HEAD(&spirom->device_entry);
+ init_completion(&spirom->done);
+
+ /* If we can allocate a minor number, hook up this device.
+ * Reusing minors is fine so long as udev or mdev is working.
+ */
+ mutex_lock(&device_list_lock);
+ minor = find_first_zero_bit(minors, N_SPI_MINORS);
+ if (minor < N_SPI_MINORS) {
+ struct device *dev;
+
+ spirom->devt = MKDEV(SPIROM_MAJOR, minor);
+ dev = device_create(spirom_class, &spi->dev, spirom->devt,
+ spirom, "spirom%d.%d",
+ spi->master->bus_num, spi->chip_select);
+ status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
+ } else {
+ dev_dbg(&spi->dev, "no minor number available!\n");
+ status = -ENODEV;
+ }
+ if (status == 0) {
+ set_bit(minor, minors);
+ list_add(&spirom->device_entry, &device_list);
+ }
+ mutex_unlock(&device_list_lock);
+
+ if (status == 0)
+ spi_set_drvdata(spi, spirom);
+ else
+ kfree(spirom);
+
+ return status;
+}
+
+static int spirom_remove(struct spi_device *spi)
+{
+ struct spirom_data *spirom = spi_get_drvdata(spi);
+
+ /* make sure ops on existing fds can abort cleanly */
+ spin_lock_irq(&spirom->spi_lock);
+ spirom->spi = NULL;
+ spi_set_drvdata(spi, NULL);
+ spin_unlock_irq(&spirom->spi_lock);
+
+ /* prevent new opens */
+ mutex_lock(&device_list_lock);
+ list_del(&spirom->device_entry);
+ clear_bit(MINOR(spirom->devt), minors);
+ device_destroy(spirom_class, spirom->devt);
+ if (spirom->users == 0)
+ kfree(spirom);
+ mutex_unlock(&device_list_lock);
+
+ return 0;
+}
+
+static struct spi_driver spirom_spi = {
+ .driver = {
+ .name = "spirom",
+ .owner = THIS_MODULE,
+ },
+ .probe = spirom_probe,
+ .remove = spirom_remove,
+
+ /* NOTE: suspend/resume methods are not necessary here.
+ * We don't do anything except pass the requests to/from
+ * the underlying controller. The refrigerator handles
+ * most issues; the controller driver handles the rest.
+ */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init spirom_init(void)
+{
+ int status;
+
+ pr_info("AMD SPIROM Driver v%s\n", SPIROM_VERSION);
+
+ /* Claim our 256 reserved device numbers. Then register a class
+ * that will key udev/mdev to add/remove /dev nodes. Last, register
+ * the driver which manages those device numbers.
+ */
+ BUILD_BUG_ON(N_SPI_MINORS > 256);
+ status = register_chrdev(SPIROM_MAJOR, "spi", &spirom_fops);
+ if (status < 0)
+ return status;
+
+ spirom_class = class_create(THIS_MODULE, "spirom");
+ if (IS_ERR(spirom_class)) {
+ unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
+ return PTR_ERR(spirom_class);
+ }
+
+ status = spi_register_driver(&spirom_spi);
+ if (status < 0) {
+ class_destroy(spirom_class);
+ unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
+ }
+
+ status = add_spi_device_to_bus();
+ if (status < 0) {
+ spi_unregister_driver(&spirom_spi);
+ class_destroy(spirom_class);
+ unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
+ }
+
+ return status;
+}
+module_init(spirom_init);
+
+static void __exit spirom_exit(void)
+{
+ spi_unregister_driver(&spirom_spi);
+ class_destroy(spirom_class);
+ unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
+}
+module_exit(spirom_exit);
+
+MODULE_AUTHOR("Arindam Nath <arindam.nath@amd.com>");
+MODULE_DESCRIPTION("User mode SPI ROM interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:spirom");
diff --git a/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.h b/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.h
new file mode 100644
index 00000000..750719a6
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-spi/files/spirom.h
@@ -0,0 +1,43 @@
+#ifndef SPIROM_H
+#define SPIROM_H
+
+#include <linux/types.h>
+
+/*---------------------------------------------------------------------------*/
+
+/* IOCTL commands */
+
+#define SPI_IOC_MAGIC 'k'
+
+#define TRANSMIT 1
+#define RECEIVE 2
+
+/*
+ * struct spi_ioc_transfer - interface structure between application and ioctl
+ *
+ * @buf: Buffer to hold 1-byte command, 3-bytes address, and 64-byte data for
+ * transmit or receive. The internal FIFO of our controller can hold a
+ * maximum of 70 bytes, including the address. But here we assume the
+ * maximum data excluding address to be 64-bytes long.
+ *
+ * @direction: Direction of data transfer, either TRANSMIT or RECEIVE.
+ *
+ * @len: Length of data excluding command and address.
+ *
+ * @addr_present: Flag to indicate whether 'buf' above contains an address.
+ */
+struct spi_ioc_transfer {
+ __u8 buf[64 + 1 + 3];
+ __u8 direction;
+ __u8 len;
+ __u8 addr_present;
+};
+
+/* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
+#define SPI_MSGSIZE(N) \
+ ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
+ ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
+#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
+
+
+#endif /* SPIROM_H */
diff --git a/meta-steppeeagle/recipes-kernel/amd-wdt/amd-wdt_1.0.bb b/meta-steppeeagle/recipes-kernel/amd-wdt/amd-wdt_1.0.bb
new file mode 100644
index 00000000..22324c38
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-wdt/amd-wdt_1.0.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "This kernel module provides support for AMD Watchdog driver"
+LICENSE = "BSD | GPLv2"
+LIC_FILES_CHKSUM = "file://amd_wdt.c;md5=8b8efe83eff938c6f17592973d38e70d \
+ file://amd_wdt.h;md5=29c5be1a55c35b14a9bde439b9de839e \
+ file://Makefile;md5=111ec65dfed99f6cd330ccb4957fb924 \
+ "
+
+inherit module
+
+PR = "r0"
+PV = "1.0"
+
+SRC_URI = "file://Makefile \
+ file://amd_wdt.c \
+ file://amd_wdt.h \
+ "
+
+S = "${WORKDIR}"
+
+# Kernel module packages MUST begin with 'kernel-module-', otherwise
+# multilib image generation can fail.
+#
+# The following line is only necessary if the recipe name does not begin
+# with kernel-module-.
+#
+PKG_${PN} = "kernel-module-${PN}"
+
+FILES_${PN} += "${sysconfdir}"
diff --git a/meta-steppeeagle/recipes-kernel/amd-wdt/files/Makefile b/meta-steppeeagle/recipes-kernel/amd-wdt/files/Makefile
new file mode 100644
index 00000000..36b32f87
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-wdt/files/Makefile
@@ -0,0 +1,14 @@
+obj-m := amd_wdt.o
+
+SRC := $(shell pwd)
+
+all:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
+
+modules_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
+
+clean:
+ rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
+ rm -f Module.markers Module.symvers modules.order
+ rm -rf .tmp_versions Modules.symvers
diff --git a/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.c b/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.c
new file mode 100644
index 00000000..26da1736
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.c
@@ -0,0 +1,518 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include "amd_wdt.h"
+
+/* internal variables */
+static u32 wdtbase_phys;
+static void __iomem *wdtbase;
+static DEFINE_SPINLOCK(wdt_lock);
+static unsigned int bootstatus;
+static unsigned long status;
+static struct pci_dev *amd_wdt_pci;
+
+/* watchdog platform device */
+static struct platform_device *amd_wdt_platform_device;
+
+/* module parameters */
+static int heartbeat = WATCHDOG_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in frequency units. "
+ "(default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static char frequency[MAX_LENGTH] = "1s";
+module_param_string(frequency, frequency, MAX_LENGTH, 0);
+MODULE_PARM_DESC(frequency, "Watchdog timer frequency units (32us, "
+ "10ms, 100ms, 1s). (default=1s)");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
+ " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static char action[MAX_LENGTH] = "reboot";
+module_param_string(action, action, MAX_LENGTH, 0);
+MODULE_PARM_DESC(action, "Watchdog action (reboot/shutdown). (default=reboot) ");
+
+/*
+ * Watchdog specific functions
+ */
+static int amd_wdt_timer_set_heartbeat(unsigned int t)
+{
+ unsigned long flags;
+
+ /*
+ * In case the user inputs out of range timeout, we set it to the
+ * maximum timeout possible.
+ */
+ if ((t == 0) || (t > 0xffff))
+ heartbeat = t = 0xffff;
+
+ /* Write new timeout value to watchdog */
+ spin_lock_irqsave(&wdt_lock, flags);
+ writel(t, AMD_WDT_COUNT(wdtbase));
+ spin_unlock_irqrestore(&wdt_lock, flags);
+
+ heartbeat = t;
+
+ return 0;
+}
+
+static void amd_wdt_timer_activate(void)
+{
+ u32 val;
+ unsigned long flags;
+
+ /* Enable the watchdog timer */
+ spin_lock_irqsave(&wdt_lock, flags);
+
+ val = readl(AMD_WDT_CONTROL(wdtbase));
+ val |= AMD_WDT_START_STOP_BIT;
+ writel(val, AMD_WDT_CONTROL(wdtbase));
+
+ set_bit(AMD_WDOG_ACTIVE, &status);
+
+ spin_unlock_irqrestore(&wdt_lock, flags);
+}
+
+static void amd_wdt_timer_deactivate(void)
+{
+ u32 val;
+ unsigned long flags;
+
+ /* Disable the watchdog timer */
+ spin_lock_irqsave(&wdt_lock, flags);
+
+ val = readl(AMD_WDT_CONTROL(wdtbase));
+ val &= ~AMD_WDT_START_STOP_BIT;
+ writel(val, AMD_WDT_CONTROL(wdtbase));
+
+ clear_bit(AMD_WDOG_ACTIVE, &status);
+
+ spin_unlock_irqrestore(&wdt_lock, flags);
+}
+
+static void amd_wdt_timer_keepalive(void)
+{
+ u32 val;
+ unsigned long flags;
+
+ /* Trigger watchdog */
+ spin_lock_irqsave(&wdt_lock, flags);
+
+ val = readl(AMD_WDT_CONTROL(wdtbase));
+ val |= AMD_WDT_TRIGGER_BIT;
+ writel(val, AMD_WDT_CONTROL(wdtbase));
+
+ spin_unlock_irqrestore(&wdt_lock, flags);
+}
+
+static unsigned int amd_wdt_timer_get_timeleft(void)
+{
+ u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdt_lock, flags);
+ val = readl(AMD_WDT_COUNT(wdtbase));
+ spin_unlock_irqrestore(&wdt_lock, flags);
+
+ /* Mask out the upper 16-bits and return */
+ return val & AMD_WDT_COUNT_MASK;
+}
+
+static int amd_wdt_timer_open(struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(AMD_WDOG_DEV_OPEN, &status))
+ return -EBUSY;
+
+ /* Start the watchdog timer and ping it once */
+ amd_wdt_timer_activate();
+ amd_wdt_timer_keepalive();
+
+ return nonseekable_open(inode, file);
+}
+
+static int amd_wdt_timer_release(struct inode *inode, struct file *file)
+{
+ if (test_and_clear_bit(AMD_WDOG_ALLOW_RELEASE, &status)) {
+ amd_wdt_timer_deactivate();
+ } else {
+ pr_crit("Unexpected close, not stopping watchdog!\n");
+ amd_wdt_timer_keepalive();
+ }
+
+ clear_bit(AMD_WDOG_DEV_OPEN, &status);
+
+ return 0;
+}
+
+static ssize_t amd_wdt_timer_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(AMD_WDOG_ALLOW_RELEASE, &status);
+
+ /*
+ * parse user buffer to see if we received magic
+ * character 'V'.
+ */
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ set_bit(AMD_WDOG_ALLOW_RELEASE, &status);
+ }
+ }
+
+ /* Reload the timer */
+ amd_wdt_timer_keepalive();
+ }
+
+ return len;
+}
+
+static long amd_wdt_timer_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int new_options, retval = -EINVAL;
+ int new_heartbeat;
+ int timeleft;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static const struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = WDT_MODULE_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ case WDIOC_GETSTATUS:
+ return put_user(status, p);
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(bootstatus, p);
+ case WDIOC_SETOPTIONS:
+ if (get_user(new_options, p))
+ return -EFAULT;
+ if (new_options & WDIOS_DISABLECARD) {
+ amd_wdt_timer_deactivate();
+ retval = 0;
+ }
+ if (new_options & WDIOS_ENABLECARD) {
+ amd_wdt_timer_activate();
+ amd_wdt_timer_keepalive();
+ retval = 0;
+ }
+ return retval;
+ case WDIOC_KEEPALIVE:
+ amd_wdt_timer_keepalive();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_heartbeat, p))
+ return -EFAULT;
+ if (amd_wdt_timer_set_heartbeat(new_heartbeat))
+ return -EINVAL;
+ amd_wdt_timer_keepalive();
+ /* Fall through */
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+ case WDIOC_GETTIMELEFT:
+ timeleft = amd_wdt_timer_get_timeleft();
+ return put_user(timeleft, p);
+ default:
+ return -ENOTTY;
+ }
+}
+
+/* Watchdog timer file operations structure */
+static const struct file_operations amd_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = amd_wdt_timer_write,
+ .unlocked_ioctl = amd_wdt_timer_ioctl,
+ .open = amd_wdt_timer_open,
+ .release = amd_wdt_timer_release,
+};
+
+static struct miscdevice amd_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &amd_wdt_fops,
+};
+
+/*
+ * The PCI Device ID table below is used to identify the platform
+ * the driver is supposed to work for. Since this is a platform
+ * device, we need a way for us to be able to find the correct
+ * platform when the driver gets loaded, otherwise we should
+ * bail out.
+ */
+static DEFINE_PCI_DEVICE_TABLE(amd_wdt_pci_tbl) = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID,
+ PCI_ANY_ID, },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, amd_wdt_pci_tbl);
+
+static unsigned char amd_wdt_setupdevice(void)
+{
+ struct pci_dev *dev = NULL;
+ u32 val;
+
+ /* Match the PCI device */
+ for_each_pci_dev(dev) {
+ if (pci_match_id(amd_wdt_pci_tbl, dev) != NULL) {
+ amd_wdt_pci = dev;
+ break;
+ }
+ }
+
+ if (!amd_wdt_pci)
+ return 0;
+
+ /* Watchdog Base Address starts from ACPI MMIO Base Address + 0xB00 */
+ wdtbase_phys = AMD_ACPI_MMIO_BASE + AMD_WDT_MEM_MAP_OFFSET;
+ if (!request_mem_region_exclusive(wdtbase_phys, AMD_WDT_MEM_MAP_SIZE,
+ "AMD Watchdog")) {
+ pr_err("mmio address 0x%04x already in use\n", wdtbase_phys);
+ goto exit;
+ }
+
+ wdtbase = ioremap(wdtbase_phys, AMD_WDT_MEM_MAP_SIZE);
+ if (!wdtbase) {
+ pr_err("failed to get wdtbase address\n");
+ goto unreg_mem_region;
+ }
+
+ /* Enable watchdog timer and decode bit */
+ outb(AMD_PM_WATCHDOG_EN_REG, AMD_IO_PM_INDEX_REG);
+ val = inb(AMD_IO_PM_DATA_REG);
+ val |= AMD_PM_WATCHDOG_TIMER_EN;
+ outb(val, AMD_IO_PM_DATA_REG);
+
+ /* Set the watchdog timer resolution */
+ outb(AMD_PM_WATCHDOG_CONFIG_REG, AMD_IO_PM_INDEX_REG);
+ val = inb(AMD_IO_PM_DATA_REG);
+ /* Clear the previous frequency setting, if any */
+ val &= ~AMD_PM_WATCHDOG_CONFIG_MASK;
+
+ /*
+ * Now set the frequency depending on the module load parameter.
+ * In case the user passes an invalid argument, we consider the
+ * frequency to be of 1 second resolution.
+ */
+ if (strncmp(frequency, "32us", 4) == 0)
+ val |= AMD_PM_WATCHDOG_32USEC_RES;
+ else if (strncmp(frequency, "10ms", 4) == 0)
+ val |= AMD_PM_WATCHDOG_10MSEC_RES;
+ else if (strncmp(frequency, "100ms", 5) == 0)
+ val |= AMD_PM_WATCHDOG_100MSEC_RES;
+ else {
+ val |= AMD_PM_WATCHDOG_1SEC_RES;
+ if (strncmp(frequency, "1s", 2) != 0)
+ strncpy(frequency, "1s", 2);
+ }
+
+ outb(val, AMD_IO_PM_DATA_REG);
+
+ /* Set the watchdog action depending on module load parameter. */
+ val = readl(AMD_WDT_CONTROL(wdtbase));
+
+ /*
+ * If action is specified anything other than reboot or shutdown,
+ * we default it to reboot.
+ */
+ if (strncmp(action, "shutdown", 8) == 0)
+ val |= AMD_WDT_ACTION_RESET_BIT;
+ else {
+ val &= ~AMD_WDT_ACTION_RESET_BIT;
+ /* The statement below is required for when the action
+ * is set anything other than reboot.
+ */
+ if (strncmp(action, "reboot", 6) != 0)
+ strncpy(action, "reboot", 6);
+ }
+
+ writel(val, AMD_WDT_CONTROL(wdtbase));
+
+ return 1;
+
+unreg_mem_region:
+ release_mem_region(wdtbase_phys, AMD_WDT_MEM_MAP_SIZE);
+exit:
+ return 0;
+}
+
+static int amd_wdt_init(struct platform_device *dev)
+{
+ int ret;
+ u32 val;
+
+ /* Identify our device and initialize watchdog hardware */
+ if (!amd_wdt_setupdevice())
+ return -ENODEV;
+
+ /* Check to see if last reboot was due to watchdog timeout */
+ val = readl(AMD_WDT_CONTROL(wdtbase));
+ if (val & AMD_WDT_FIRED_BIT)
+ bootstatus |= WDIOF_CARDRESET;
+ else
+ bootstatus &= ~WDIOF_CARDRESET;
+
+ pr_info("Watchdog reboot %sdetected\n",
+ (val & AMD_WDT_FIRED_BIT) ? "" : "not ");
+
+ /* Clear out the old status */
+ val |= AMD_WDT_FIRED_BIT;
+ writel(val, AMD_WDT_CONTROL(wdtbase));
+
+ /* Set Watchdog timeout */
+ amd_wdt_timer_set_heartbeat(heartbeat);
+
+ ret = misc_register(&amd_wdt_miscdev);
+ if (ret != 0) {
+ pr_err("Watchdog timer: cannot register miscdevice on minor="
+ "%d (err=%d)\n", WATCHDOG_MINOR, ret);
+ goto exit;
+ }
+
+ clear_bit(AMD_WDOG_DEV_OPEN, &status);
+ if (nowayout)
+ set_bit(AMD_WDOG_NO_WAY_OUT, &status);
+
+ pr_info("initialized (0x%p). (heartbeat=%d units) (frequency=%s) "
+ "(nowayout=%d) (action=%s)\n", wdtbase, heartbeat, frequency,
+ nowayout, action);
+
+ return 0;
+
+exit:
+ iounmap(wdtbase);
+ release_mem_region(wdtbase_phys, AMD_WDT_MEM_MAP_SIZE);
+ return ret;
+}
+
+static void amd_wdt_cleanup(void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ amd_wdt_timer_deactivate();
+
+ misc_deregister(&amd_wdt_miscdev);
+ iounmap(wdtbase);
+ release_mem_region(wdtbase_phys, AMD_WDT_MEM_MAP_SIZE);
+}
+
+static int amd_wdt_remove(struct platform_device *dev)
+{
+ if (wdtbase)
+ amd_wdt_cleanup();
+
+ return 0;
+}
+
+static void amd_wdt_shutdown(struct platform_device *dev)
+{
+ amd_wdt_timer_deactivate();
+}
+
+static struct platform_driver amd_wdt_driver = {
+ .probe = amd_wdt_init,
+ .remove = amd_wdt_remove,
+ .shutdown = amd_wdt_shutdown,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = WDT_MODULE_NAME,
+ },
+};
+
+static int __init amd_wdt_init_module(void)
+{
+ int err;
+
+ pr_info("AMD WatchDog Timer Driver v%s\n", WDT_VERSION);
+
+ err = platform_driver_register(&amd_wdt_driver);
+ if (err)
+ return err;
+
+ amd_wdt_platform_device = platform_device_register_simple(
+ WDT_MODULE_NAME, -1, NULL, 0);
+ if (IS_ERR(amd_wdt_platform_device)) {
+ err = PTR_ERR(amd_wdt_platform_device);
+ goto unreg_platform_driver;
+ }
+
+ return 0;
+
+unreg_platform_driver:
+ platform_driver_unregister(&amd_wdt_driver);
+ return err;
+}
+
+static void __exit amd_wdt_cleanup_module(void)
+{
+ platform_device_unregister(amd_wdt_platform_device);
+ platform_driver_unregister(&amd_wdt_driver);
+ pr_info("AMD Watchdog Module Unloaded\n");
+}
+
+module_init(amd_wdt_init_module);
+module_exit(amd_wdt_cleanup_module);
+
+MODULE_AUTHOR("Arindam Nath <arindam.nath@amd.com>");
+MODULE_DESCRIPTION("Watchdog timer driver for AMD chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.h b/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.h
new file mode 100644
index 00000000..116f370a
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-wdt/files/amd_wdt.h
@@ -0,0 +1,49 @@
+#ifndef _AMD_WDT_H_
+#define _AMD_WDT_H_
+
+/* Module and version information */
+#define WDT_VERSION "0.1"
+#define WDT_MODULE_NAME "AMD watchdog timer"
+#define WDT_DRIVER_NAME WDT_MODULE_NAME ", v" WDT_VERSION
+
+#define WATCHDOG_HEARTBEAT 60 /* 60 units default heartbeat. */
+#define MAX_LENGTH (8 + 1) /* shutdown has 8 characters + NULL character */
+
+/* Watchdog register definitions */
+#define AMD_ACPI_MMIO_BASE 0xFED80000
+#define AMD_WDT_MEM_MAP_OFFSET 0xB00
+#define AMD_WDT_MEM_MAP_SIZE 0x100
+
+#define AMD_WDT_CONTROL(base) ((base) + 0x00) /* Watchdog Control */
+ #define AMD_WDT_START_STOP_BIT (1 << 0)
+ #define AMD_WDT_FIRED_BIT (1 << 1)
+ #define AMD_WDT_ACTION_RESET_BIT (1 << 2)
+ #define AMD_WDT_DISABLE_BIT (1 << 3)
+ /* 6:4 bits Reserved */
+ #define AMD_WDT_TRIGGER_BIT (1 << 7)
+#define AMD_WDT_COUNT(base) ((base) + 0x04) /* Watchdog Count */
+ #define AMD_WDT_COUNT_MASK 0xFFFF
+
+#define AMD_PM_WATCHDOG_EN_REG 0x00
+ #define AMD_PM_WATCHDOG_TIMER_EN (0x01 << 7)
+
+#define AMD_PM_WATCHDOG_CONFIG_REG 0x03
+ #define AMD_PM_WATCHDOG_32USEC_RES 0x0
+ #define AMD_PM_WATCHDOG_10MSEC_RES 0x1
+ #define AMD_PM_WATCHDOG_100MSEC_RES 0x2
+ #define AMD_PM_WATCHDOG_1SEC_RES 0x3
+#define AMD_PM_WATCHDOG_CONFIG_MASK 0x3
+
+/* IO port address for indirect access using ACPI PM registers */
+#define AMD_IO_PM_INDEX_REG 0xCD6
+#define AMD_IO_PM_DATA_REG 0xCD7
+
+#define AMD_ACPI_MMIO_ADDR_MASK ~0x1FFF
+
+/* Watchdog device status */
+#define AMD_WDOG_ACTIVE 0 /* Is the watchdog running/active */
+#define AMD_WDOG_DEV_OPEN 1 /* Opended via /dev/watchdog */
+#define AMD_WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char? */
+#define AMD_WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set? */
+
+#endif /* _AMD_WDT_H_ */
diff --git a/meta-steppeeagle/recipes-kernel/gpio-load/amd-gpio-load_1.0.bb b/meta-steppeeagle/recipes-kernel/gpio-load/amd-gpio-load_1.0.bb
new file mode 100644
index 00000000..eba925e4
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/gpio-load/amd-gpio-load_1.0.bb
@@ -0,0 +1,17 @@
+DESCRIPTION = "Configuration file to pass module load parameters to AMD GPIO driver"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
+
+SRC_URI = "file://modprobe.d/gpio-amd.conf"
+
+PR = "r0"
+PV = "1.0"
+
+S = "${WORKDIR}"
+
+do_install() {
+ install -d ${D}/${sysconfdir}/modprobe.d/
+ install -m 0644 modprobe.d/gpio-amd.conf ${D}${sysconfdir}/modprobe.d/
+}
+
+FILES_${PN} = "${sysconfdir}/modprobe.d"
diff --git a/meta-steppeeagle/recipes-kernel/gpio-load/files/modprobe.d/gpio-amd.conf b/meta-steppeeagle/recipes-kernel/gpio-load/files/modprobe.d/gpio-amd.conf
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/gpio-load/files/modprobe.d/gpio-amd.conf
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware.bb b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware.bb
new file mode 100644
index 00000000..e0e0999d
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware.bb
@@ -0,0 +1,26 @@
+DESCRIPTION = "These binaries provide kernel support for AMD radeon GPUs"
+SECTION = "kernel"
+LICENSE = "Proprietary"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"
+
+SRC_URI = "file://*.bin"
+
+LIC_FILES_CHKSUM = "file://LICENSE.radeon;md5=07b0c31777bd686d8e1609c6940b5e74"
+
+S = "${WORKDIR}"
+
+# Since, no binaries are generated for a specific target,
+# inherit allarch to simply populate prebuilt binaries
+inherit allarch
+
+do_compile() {
+ :
+}
+
+do_install() {
+ install -v -m 444 -D ${S}/LICENSE.radeon ${D}/lib/firmware/radeon/LICENSE.radeon
+ install -v -m 0644 ${S}/*.bin ${D}/lib/firmware/radeon/
+}
+
+FILES_${PN} = "/lib/firmware/*"
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_ce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_ce.bin
new file mode 100644
index 00000000..7d40fbf1
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_ce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mc.bin
new file mode 100644
index 00000000..a3c70472
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_me.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_me.bin
new file mode 100644
index 00000000..75bff897
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_me.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mec.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mec.bin
new file mode 100644
index 00000000..65fd6fb8
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_mec.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_pfp.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_pfp.bin
new file mode 100644
index 00000000..e12a1af2
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_pfp.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_rlc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_rlc.bin
new file mode 100644
index 00000000..7e322354
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_rlc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_sdma.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_sdma.bin
new file mode 100644
index 00000000..4766a2a9
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_sdma.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_smc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_smc.bin
new file mode 100644
index 00000000..c735c6f4
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_smc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_uvd.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_uvd.bin
new file mode 100644
index 00000000..0876de9e
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_uvd.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_vce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_vce.bin
new file mode 100644
index 00000000..2fcf2696
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/BONAIRE_vce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_ce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_ce.bin
new file mode 100644
index 00000000..497e1321
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_ce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_mc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_mc.bin
new file mode 100644
index 00000000..a7b80c3d
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_mc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_me.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_me.bin
new file mode 100644
index 00000000..6dc895ba
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_me.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_pfp.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_pfp.bin
new file mode 100644
index 00000000..1918d64a
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_pfp.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_rlc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_rlc.bin
new file mode 100644
index 00000000..df07678f
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_rlc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_smc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_smc.bin
new file mode 100644
index 00000000..6bf5b369
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_smc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_vce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_vce.bin
new file mode 100644
index 00000000..2fcf2696
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/HAINAN_vce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_ce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_ce.bin
new file mode 100644
index 00000000..06d92de4
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_ce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_me.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_me.bin
new file mode 100644
index 00000000..543dc671
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_me.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_mec.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_mec.bin
new file mode 100644
index 00000000..002ac5c0
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_mec.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_pfp.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_pfp.bin
new file mode 100644
index 00000000..77590a14
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_pfp.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_rlc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_rlc.bin
new file mode 100644
index 00000000..ba84d86b
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_rlc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_sdma.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_sdma.bin
new file mode 100644
index 00000000..4766a2a9
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/KAVERI_sdma.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/LICENSE.radeon b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/LICENSE.radeon
new file mode 100644
index 00000000..fe3780b3
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/LICENSE.radeon
@@ -0,0 +1,51 @@
+Copyright (C) 2009-2014 Advanced Micro Devices, Inc. All rights reserved.
+
+REDISTRIBUTION: Permission is hereby granted, free of any license fees,
+to any person obtaining a copy of this microcode (the "Software"), to
+install, reproduce, copy and distribute copies, in binary form only, of
+the Software and to permit persons to whom the Software is provided to
+do the same, provided that the following conditions are met:
+
+No reverse engineering, decompilation, or disassembly of this Software
+is permitted.
+
+Redistributions must reproduce the above copyright notice, this
+permission notice, and the following disclaimers and notices in the
+Software documentation and/or other materials provided with the
+Software.
+
+DISCLAIMER: THE USE OF THE SOFTWARE IS AT YOUR SOLE RISK. THE SOFTWARE
+IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND AND COPYRIGHT
+HOLDER AND ITS LICENSORS EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS AND
+IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+COPYRIGHT HOLDER AND ITS LICENSORS DO NOT WARRANT THAT THE SOFTWARE WILL
+MEET YOUR REQUIREMENTS, OR THAT THE OPERATION OF THE SOFTWARE WILL BE
+UNINTERRUPTED OR ERROR-FREE. THE ENTIRE RISK ASSOCIATED WITH THE USE OF
+THE SOFTWARE IS ASSUMED BY YOU. FURTHERMORE, COPYRIGHT HOLDER AND ITS
+LICENSORS DO NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE
+OR THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS,
+ACCURACY, RELIABILITY, CURRENTNESS, OR OTHERWISE.
+
+DISCLAIMER: UNDER NO CIRCUMSTANCES INCLUDING NEGLIGENCE, SHALL COPYRIGHT
+HOLDER AND ITS LICENSORS OR ITS DIRECTORS, OFFICERS, EMPLOYEES OR AGENTS
+("AUTHORIZED REPRESENTATIVES") BE LIABLE FOR ANY INCIDENTAL, INDIRECT,
+SPECIAL OR CONSEQUENTIAL DAMAGES (INCLUDING DAMAGES FOR LOSS OF BUSINESS
+PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, AND THE
+LIKE) ARISING OUT OF THE USE, MISUSE OR INABILITY TO USE THE SOFTWARE,
+BREACH OR DEFAULT, INCLUDING THOSE ARISING FROM INFRINGEMENT OR ALLEGED
+INFRINGEMENT OF ANY PATENT, TRADEMARK, COPYRIGHT OR OTHER INTELLECTUAL
+PROPERTY RIGHT EVEN IF COPYRIGHT HOLDER AND ITS AUTHORIZED
+REPRESENTATIVES HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN
+NO EVENT SHALL COPYRIGHT HOLDER OR ITS AUTHORIZED REPRESENTATIVES TOTAL
+LIABILITY FOR ALL DAMAGES, LOSSES, AND CAUSES OF ACTION (WHETHER IN
+CONTRACT, TORT (INCLUDING NEGLIGENCE) OR OTHERWISE) EXCEED THE AMOUNT OF
+US$10.
+
+Notice: The Software is subject to United States export laws and
+regulations. You agree to comply with all domestic and international
+export laws and regulations that apply to the Software, including but
+not limited to the Export Administration Regulations administered by the
+U.S. Department of Commerce and International Traffic in Arm Regulations
+administered by the U.S. Department of State. These laws include
+restrictions on destinations, end users and end use.
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_ce.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_ce.bin
new file mode 100644
index 00000000..06d92de4
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_ce.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_me.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_me.bin
new file mode 100644
index 00000000..543dc671
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_me.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_mec.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_mec.bin
new file mode 100644
index 00000000..5ae6b387
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_mec.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_pfp.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_pfp.bin
new file mode 100644
index 00000000..abe62fbc
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_pfp.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_rlc.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_rlc.bin
new file mode 100644
index 00000000..8c24a03b
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_rlc.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_sdma.bin b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_sdma.bin
new file mode 100644
index 00000000..4766a2a9
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux-firmware/radeon-firmware/MULLINS_sdma.bin
Binary files differ
diff --git a/meta-steppeeagle/recipes-kernel/linux/files/steppeeagle-user-features.scc b/meta-steppeeagle/recipes-kernel/linux/files/steppeeagle-user-features.scc
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/files/steppeeagle-user-features.scc
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch
new file mode 100644
index 00000000..8540cbf0
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0000-yocto-amd-drm-radeon-backport-support-from-kernel-version-3.12.10.patch
@@ -0,0 +1,780 @@
+This single patch is a backport from kernel version 3.12.10 to kernel version
+3.12. This lays the ground for the next set of patches which had been created
+on top of 3.12.10.
+
+Signed-off-by: Arindam Nath <arindam.nath@amd.com>
+diff -Naur a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+--- a/drivers/acpi/bus.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/acpi/bus.c 2014-04-03 02:38:06.049166833 +0530
+@@ -156,6 +156,16 @@
+ }
+ EXPORT_SYMBOL(acpi_bus_get_private_data);
+
++void acpi_bus_no_hotplug(acpi_handle handle)
++{
++ struct acpi_device *adev = NULL;
++
++ acpi_bus_get_device(handle, &adev);
++ if (adev)
++ adev->flags.no_hotplug = true;
++}
++EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug);
++
+ static void acpi_print_osc_error(acpi_handle handle,
+ struct acpi_osc_context *context, char *error)
+ {
+diff -Naur a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c 2014-04-03 01:45:50.161111970 +0530
+@@ -1180,23 +1180,18 @@
+ fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
+
+ if (rdev->family >= CHIP_BONAIRE) {
+- u32 num_pipe_configs = rdev->config.cik.max_tile_pipes;
+- u32 num_rb = rdev->config.cik.max_backends_per_se;
+- if (num_pipe_configs > 8)
+- num_pipe_configs = 8;
+- if (num_pipe_configs == 8)
+- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P8_32x32_16x16);
+- else if (num_pipe_configs == 4) {
+- if (num_rb == 4)
+- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_16x16);
+- else if (num_rb < 4)
+- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P4_8x16);
+- } else if (num_pipe_configs == 2)
+- fb_format |= CIK_GRPH_PIPE_CONFIG(CIK_ADDR_SURF_P2);
++ /* Read the pipe config from the 2D TILED SCANOUT mode.
++ * It should be the same for the other modes too, but not all
++ * modes set the pipe config field. */
++ u32 pipe_config = (rdev->config.cik.tile_mode_array[10] >> 6) & 0x1f;
++
++ fb_format |= CIK_GRPH_PIPE_CONFIG(pipe_config);
+ } else if ((rdev->family == CHIP_TAHITI) ||
+ (rdev->family == CHIP_PITCAIRN))
+ fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16);
+- else if (rdev->family == CHIP_VERDE)
++ else if ((rdev->family == CHIP_VERDE) ||
++ (rdev->family == CHIP_OLAND) ||
++ (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */
+ fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16);
+
+ switch (radeon_crtc->crtc_id) {
+@@ -1753,7 +1748,7 @@
+ if (pll != ATOM_PPLL_INVALID)
+ return pll;
+ }
+- } else {
++ } else if (!ASIC_IS_DCE41(rdev)) { /* Don't share PLLs on DCE4.1 chips */
+ /* use the same PPLL for all monitors with the same clock */
+ pll = radeon_get_shared_nondp_ppll(crtc);
+ if (pll != ATOM_PPLL_INVALID)
+diff -Naur a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c
+--- a/drivers/gpu/drm/radeon/atombios_i2c.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/atombios_i2c.c 2014-04-03 01:45:50.161111970 +0530
+@@ -44,7 +44,7 @@
+ PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
+ int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
+ unsigned char *base;
+- u16 out;
++ u16 out = cpu_to_le16(0);
+
+ memset(&args, 0, sizeof(args));
+
+@@ -55,9 +55,14 @@
+ DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
+ return -EINVAL;
+ }
+- args.ucRegIndex = buf[0];
+- if (num > 1)
+- memcpy(&out, &buf[1], num - 1);
++ if (buf == NULL)
++ args.ucRegIndex = 0;
++ else
++ args.ucRegIndex = buf[0];
++ if (num)
++ num--;
++ if (num)
++ memcpy(&out, &buf[1], num);
+ args.lpI2CDataOut = cpu_to_le16(out);
+ } else {
+ if (num > ATOM_MAX_HW_I2C_READ) {
+@@ -94,14 +99,14 @@
+ struct radeon_i2c_chan *i2c = i2c_get_adapdata(i2c_adap);
+ struct i2c_msg *p;
+ int i, remaining, current_count, buffer_offset, max_bytes, ret;
+- u8 buf = 0, flags;
++ u8 flags;
+
+ /* check for bus probe */
+ p = &msgs[0];
+ if ((num == 1) && (p->len == 0)) {
+ ret = radeon_process_i2c_ch(i2c,
+ p->addr, HW_I2C_WRITE,
+- &buf, 1);
++ NULL, 0);
+ if (ret)
+ return ret;
+ else
+diff -Naur a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+--- a/drivers/gpu/drm/radeon/cik.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/cik.c 2014-04-03 01:45:50.165111971 +0530
+@@ -2608,7 +2608,7 @@
+ * Returns the disabled RB bitmask.
+ */
+ static u32 cik_get_rb_disabled(struct radeon_device *rdev,
+- u32 max_rb_num, u32 se_num,
++ u32 max_rb_num_per_se,
+ u32 sh_per_se)
+ {
+ u32 data, mask;
+@@ -2622,7 +2622,7 @@
+
+ data >>= BACKEND_DISABLE_SHIFT;
+
+- mask = cik_create_bitmask(max_rb_num / se_num / sh_per_se);
++ mask = cik_create_bitmask(max_rb_num_per_se / sh_per_se);
+
+ return data & mask;
+ }
+@@ -2639,7 +2639,7 @@
+ */
+ static void cik_setup_rb(struct radeon_device *rdev,
+ u32 se_num, u32 sh_per_se,
+- u32 max_rb_num)
++ u32 max_rb_num_per_se)
+ {
+ int i, j;
+ u32 data, mask;
+@@ -2649,19 +2649,21 @@
+ for (i = 0; i < se_num; i++) {
+ for (j = 0; j < sh_per_se; j++) {
+ cik_select_se_sh(rdev, i, j);
+- data = cik_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
++ data = cik_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
+ disabled_rbs |= data << ((i * sh_per_se + j) * CIK_RB_BITMAP_WIDTH_PER_SH);
+ }
+ }
+ cik_select_se_sh(rdev, 0xffffffff, 0xffffffff);
+
+ mask = 1;
+- for (i = 0; i < max_rb_num; i++) {
++ for (i = 0; i < max_rb_num_per_se * se_num; i++) {
+ if (!(disabled_rbs & mask))
+ enabled_rbs |= mask;
+ mask <<= 1;
+ }
+
++ rdev->config.cik.backend_enable_mask = enabled_rbs;
++
+ for (i = 0; i < se_num; i++) {
+ cik_select_se_sh(rdev, i, 0xffffffff);
+ data = 0;
+diff -Naur a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+--- a/drivers/gpu/drm/radeon/cik_sdma.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/cik_sdma.c 2014-04-03 01:45:50.169111972 +0530
+@@ -468,7 +468,7 @@
+ radeon_ring_write(ring, 0); /* src/dst endian swap */
+ radeon_ring_write(ring, src_offset & 0xffffffff);
+ radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff);
+- radeon_ring_write(ring, dst_offset & 0xfffffffc);
++ radeon_ring_write(ring, dst_offset & 0xffffffff);
+ radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff);
+ src_offset += cur_size_in_bytes;
+ dst_offset += cur_size_in_bytes;
+diff -Naur a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
+--- a/drivers/gpu/drm/radeon/dce6_afmt.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-03 01:45:50.169111972 +0530
+@@ -132,7 +132,7 @@
+ }
+
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+- if (sad_count < 0) {
++ if (sad_count <= 0) {
+ DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+ return;
+ }
+@@ -193,7 +193,7 @@
+ }
+
+ sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+- if (sad_count < 0) {
++ if (sad_count <= 0) {
+ DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+ return;
+ }
+diff -Naur a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
+--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-03 01:45:50.169111972 +0530
+@@ -81,7 +81,7 @@
+ }
+
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+- if (sad_count < 0) {
++ if (sad_count <= 0) {
+ DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
+ return;
+ }
+@@ -134,7 +134,7 @@
+ }
+
+ sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+- if (sad_count < 0) {
++ if (sad_count <= 0) {
+ DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
+ return;
+ }
+diff -Naur a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+--- a/drivers/gpu/drm/radeon/ni.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/ni.c 2014-04-03 01:45:50.169111972 +0530
+@@ -900,6 +900,10 @@
+ (rdev->pdev->device == 0x999C)) {
+ rdev->config.cayman.max_simds_per_se = 6;
+ rdev->config.cayman.max_backends_per_se = 2;
++ rdev->config.cayman.max_hw_contexts = 8;
++ rdev->config.cayman.sx_max_export_size = 256;
++ rdev->config.cayman.sx_max_export_pos_size = 64;
++ rdev->config.cayman.sx_max_export_smx_size = 192;
+ } else if ((rdev->pdev->device == 0x9903) ||
+ (rdev->pdev->device == 0x9904) ||
+ (rdev->pdev->device == 0x990A) ||
+@@ -910,6 +914,10 @@
+ (rdev->pdev->device == 0x999D)) {
+ rdev->config.cayman.max_simds_per_se = 4;
+ rdev->config.cayman.max_backends_per_se = 2;
++ rdev->config.cayman.max_hw_contexts = 8;
++ rdev->config.cayman.sx_max_export_size = 256;
++ rdev->config.cayman.sx_max_export_pos_size = 64;
++ rdev->config.cayman.sx_max_export_smx_size = 192;
+ } else if ((rdev->pdev->device == 0x9919) ||
+ (rdev->pdev->device == 0x9990) ||
+ (rdev->pdev->device == 0x9991) ||
+@@ -920,9 +928,17 @@
+ (rdev->pdev->device == 0x99A0)) {
+ rdev->config.cayman.max_simds_per_se = 3;
+ rdev->config.cayman.max_backends_per_se = 1;
++ rdev->config.cayman.max_hw_contexts = 4;
++ rdev->config.cayman.sx_max_export_size = 128;
++ rdev->config.cayman.sx_max_export_pos_size = 32;
++ rdev->config.cayman.sx_max_export_smx_size = 96;
+ } else {
+ rdev->config.cayman.max_simds_per_se = 2;
+ rdev->config.cayman.max_backends_per_se = 1;
++ rdev->config.cayman.max_hw_contexts = 4;
++ rdev->config.cayman.sx_max_export_size = 128;
++ rdev->config.cayman.sx_max_export_pos_size = 32;
++ rdev->config.cayman.sx_max_export_smx_size = 96;
+ }
+ rdev->config.cayman.max_texture_channel_caches = 2;
+ rdev->config.cayman.max_gprs = 256;
+@@ -930,10 +946,6 @@
+ rdev->config.cayman.max_gs_threads = 32;
+ rdev->config.cayman.max_stack_entries = 512;
+ rdev->config.cayman.sx_num_of_sets = 8;
+- rdev->config.cayman.sx_max_export_size = 256;
+- rdev->config.cayman.sx_max_export_pos_size = 64;
+- rdev->config.cayman.sx_max_export_smx_size = 192;
+- rdev->config.cayman.max_hw_contexts = 8;
+ rdev->config.cayman.sq_num_cf_insts = 2;
+
+ rdev->config.cayman.sc_prim_fifo_size = 0x40;
+diff -Naur a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
+--- a/drivers/gpu/drm/radeon/r600_hdmi.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-03 01:45:50.169111972 +0530
+@@ -24,6 +24,7 @@
+ * Authors: Christian König
+ */
+ #include <linux/hdmi.h>
++#include <linux/gcd.h>
+ #include <drm/drmP.h>
+ #include <drm/radeon_drm.h>
+ #include "radeon.h"
+@@ -57,35 +58,57 @@
+ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
+ /* 32kHz 44.1kHz 48kHz */
+ /* Clock N CTS N CTS N CTS */
+- { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */
++ { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */
+ { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */
+ { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */
+ { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */
+ { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */
+ { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */
+- { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */
++ { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */
+ { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */
+- { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */
++ { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */
+ { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */
+- { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */
+ };
+
++
+ /*
+- * calculate CTS value if it's not found in the table
++ * calculate CTS and N values if they are not found in the table
+ */
+-static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
++static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
+ {
+- u64 n;
+- u32 d;
++ int n, cts;
++ unsigned long div, mul;
+
+- if (*CTS == 0) {
+- n = (u64)clock * (u64)N * 1000ULL;
+- d = 128 * freq;
+- do_div(n, d);
+- *CTS = n;
+- }
+- DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
+- N, *CTS, freq);
++ /* Safe, but overly large values */
++ n = 128 * freq;
++ cts = clock * 1000;
++
++ /* Smallest valid fraction */
++ div = gcd(n, cts);
++
++ n /= div;
++ cts /= div;
++
++ /*
++ * The optimal N is 128*freq/1000. Calculate the closest larger
++ * value that doesn't truncate any bits.
++ */
++ mul = ((128*freq/1000) + (n-1))/n;
++
++ n *= mul;
++ cts *= mul;
++
++ /* Check that we are in spec (not always possible) */
++ if (n < (128*freq/1500))
++ printk(KERN_WARNING "Calculated ACR N value is too small. You may experience audio problems.\n");
++ if (n > (128*freq/300))
++ printk(KERN_WARNING "Calculated ACR N value is too large. You may experience audio problems.\n");
++
++ *N = n;
++ *CTS = cts;
++
++ DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
++ *N, *CTS, freq);
+ }
+
+ struct radeon_hdmi_acr r600_hdmi_acr(uint32_t clock)
+@@ -93,15 +116,16 @@
+ struct radeon_hdmi_acr res;
+ u8 i;
+
+- for (i = 0; r600_hdmi_predefined_acr[i].clock != clock &&
+- r600_hdmi_predefined_acr[i].clock != 0; i++)
+- ;
+- res = r600_hdmi_predefined_acr[i];
+-
+- /* In case some CTS are missing */
+- r600_hdmi_calc_cts(clock, &res.cts_32khz, res.n_32khz, 32000);
+- r600_hdmi_calc_cts(clock, &res.cts_44_1khz, res.n_44_1khz, 44100);
+- r600_hdmi_calc_cts(clock, &res.cts_48khz, res.n_48khz, 48000);
++ /* Precalculated values for common clocks */
++ for (i = 0; i < ARRAY_SIZE(r600_hdmi_predefined_acr); i++) {
++ if (r600_hdmi_predefined_acr[i].clock == clock)
++ return r600_hdmi_predefined_acr[i];
++ }
++
++ /* And odd clocks get manually calculated */
++ r600_hdmi_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
++ r600_hdmi_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
++ r600_hdmi_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
+
+ return res;
+ }
+@@ -280,9 +304,9 @@
+ WREG32(DCCG_AUDIO_DTO1_MODULE, dto_modulo);
+ WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+ }
+- } else if (ASIC_IS_DCE3(rdev)) {
++ } else {
+ /* according to the reg specs, this should DCE3.2 only, but in
+- * practice it seems to cover DCE3.0/3.1 as well.
++ * practice it seems to cover DCE2.0/3.0/3.1 as well.
+ */
+ if (dig->dig_encoder == 0) {
+ WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 100);
+@@ -293,10 +317,6 @@
+ WREG32(DCCG_AUDIO_DTO1_MODULE, clock * 100);
+ WREG32(DCCG_AUDIO_DTO_SELECT, 1); /* select DTO1 */
+ }
+- } else {
+- /* according to the reg specs, this should be DCE2.0 and DCE3.0/3.1 */
+- WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate / 10) |
+- AUDIO_DTO_MODULE(clock / 10));
+ }
+ }
+
+diff -Naur a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
+--- a/drivers/gpu/drm/radeon/radeon_asic.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_asic.c 2014-04-03 01:45:50.173111972 +0530
+@@ -2019,6 +2019,8 @@
+ .bandwidth_update = &dce8_bandwidth_update,
+ .get_vblank_counter = &evergreen_get_vblank_counter,
+ .wait_for_vblank = &dce4_wait_for_vblank,
++ .set_backlight_level = &atombios_set_backlight_level,
++ .get_backlight_level = &atombios_get_backlight_level,
+ .hdmi_enable = &evergreen_hdmi_enable,
+ .hdmi_setmode = &evergreen_hdmi_setmode,
+ },
+@@ -2119,6 +2121,8 @@
+ .bandwidth_update = &dce8_bandwidth_update,
+ .get_vblank_counter = &evergreen_get_vblank_counter,
+ .wait_for_vblank = &dce4_wait_for_vblank,
++ .set_backlight_level = &atombios_set_backlight_level,
++ .get_backlight_level = &atombios_get_backlight_level,
+ .hdmi_enable = &evergreen_hdmi_enable,
+ .hdmi_setmode = &evergreen_hdmi_setmode,
+ },
+diff -Naur a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
+--- a/drivers/gpu/drm/radeon/radeon_atombios.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_atombios.c 2014-04-03 01:45:50.173111972 +0530
+@@ -2918,7 +2918,7 @@
+ mpll_param->dll_speed = args.ucDllSpeed;
+ mpll_param->bwcntl = args.ucBWCntl;
+ mpll_param->vco_mode =
+- (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0;
++ (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK);
+ mpll_param->yclk_sel =
+ (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0;
+ mpll_param->qdr =
+diff -Naur a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c 2014-04-03 01:45:50.173111972 +0530
+@@ -34,6 +34,7 @@
+ bool atpx_detected;
+ /* handle for device - and atpx */
+ acpi_handle dhandle;
++ acpi_handle other_handle;
+ struct radeon_atpx atpx;
+ } radeon_atpx_priv;
+
+@@ -448,9 +449,10 @@
+ return false;
+
+ status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+- if (ACPI_FAILURE(status))
++ if (ACPI_FAILURE(status)) {
++ radeon_atpx_priv.other_handle = dhandle;
+ return false;
+-
++ }
+ radeon_atpx_priv.dhandle = dhandle;
+ radeon_atpx_priv.atpx.handle = atpx_handle;
+ return true;
+@@ -527,6 +529,16 @@
+ printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
+ acpi_method_name);
+ radeon_atpx_priv.atpx_detected = true;
++ /*
++ * On some systems hotplug events are generated for the device
++ * being switched off when ATPX is executed. They cause ACPI
++ * hotplug to trigger and attempt to remove the device from
++ * the system, which causes it to break down. Prevent that from
++ * happening by setting the no_hotplug flag for the involved
++ * ACPI device objects.
++ */
++ acpi_bus_no_hotplug(radeon_atpx_priv.dhandle);
++ acpi_bus_no_hotplug(radeon_atpx_priv.other_handle);
+ return true;
+ }
+ return false;
+diff -Naur a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+--- a/drivers/gpu/drm/radeon/radeon_gart.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_gart.c 2014-04-03 01:45:50.173111972 +0530
+@@ -1156,6 +1156,8 @@
+ return -ENOMEM;
+
+ r = radeon_ib_get(rdev, ridx, &ib, NULL, ndw * 4);
++ if (r)
++ return r;
+ ib.length_dw = 0;
+
+ r = radeon_vm_update_pdes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset);
+diff -Naur a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+--- a/drivers/gpu/drm/radeon/radeon.h 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon.h 2014-04-03 01:45:50.177111972 +0530
+@@ -1930,7 +1930,7 @@
+ unsigned sc_earlyz_tile_fifo_size;
+
+ unsigned num_tile_pipes;
+- unsigned num_backends_per_se;
++ unsigned backend_enable_mask;
+ unsigned backend_disable_mask_per_asic;
+ unsigned backend_map;
+ unsigned num_texture_channel_caches;
+@@ -1960,7 +1960,7 @@
+ unsigned sc_earlyz_tile_fifo_size;
+
+ unsigned num_tile_pipes;
+- unsigned num_backends_per_se;
++ unsigned backend_enable_mask;
+ unsigned backend_disable_mask_per_asic;
+ unsigned backend_map;
+ unsigned num_texture_channel_caches;
+diff -Naur a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+--- a/drivers/gpu/drm/radeon/radeon_kms.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_kms.c 2014-04-03 01:45:50.177111972 +0530
+@@ -436,6 +436,15 @@
+ case RADEON_INFO_SI_CP_DMA_COMPUTE:
+ *value = 1;
+ break;
++ case RADEON_INFO_SI_BACKEND_ENABLED_MASK:
++ if (rdev->family >= CHIP_BONAIRE) {
++ *value = rdev->config.cik.backend_enable_mask;
++ } else if (rdev->family >= CHIP_TAHITI) {
++ *value = rdev->config.si.backend_enable_mask;
++ } else {
++ DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
++ }
++ break;
+ default:
+ DRM_DEBUG_KMS("Invalid request %d\n", info->request);
+ return -EINVAL;
+diff -Naur a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 2014-04-03 01:45:50.181111972 +0530
+@@ -422,6 +422,7 @@
+ /* Pin framebuffer & get tilling informations */
+ obj = radeon_fb->obj;
+ rbo = gem_to_radeon_bo(obj);
++retry:
+ r = radeon_bo_reserve(rbo, false);
+ if (unlikely(r != 0))
+ return r;
+@@ -430,6 +431,33 @@
+ &base);
+ if (unlikely(r != 0)) {
+ radeon_bo_unreserve(rbo);
++
++ /* On old GPU like RN50 with little vram pining can fails because
++ * current fb is taking all space needed. So instead of unpining
++ * the old buffer after pining the new one, first unpin old one
++ * and then retry pining new one.
++ *
++ * As only master can set mode only master can pin and it is
++ * unlikely the master client will race with itself especialy
++ * on those old gpu with single crtc.
++ *
++ * We don't shutdown the display controller because new buffer
++ * will end up in same spot.
++ */
++ if (!atomic && fb && fb != crtc->fb) {
++ struct radeon_bo *old_rbo;
++ unsigned long nsize, osize;
++
++ old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj);
++ osize = radeon_bo_size(old_rbo);
++ nsize = radeon_bo_size(rbo);
++ if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) {
++ radeon_bo_unpin(old_rbo);
++ radeon_bo_unreserve(old_rbo);
++ fb = NULL;
++ goto retry;
++ }
++ }
+ return -EINVAL;
+ }
+ radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
+diff -Naur a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
+--- a/drivers/gpu/drm/radeon/radeon_uvd.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/radeon_uvd.c 2014-04-03 01:45:50.181111972 +0530
+@@ -240,6 +240,8 @@
+ if (handle != 0 && rdev->uvd.filp[i] == filp) {
+ struct radeon_fence *fence;
+
++ radeon_uvd_note_usage(rdev);
++
+ r = radeon_uvd_get_destroy_msg(rdev,
+ R600_RING_TYPE_UVD_INDEX, handle, &fence);
+ if (r) {
+@@ -470,7 +472,7 @@
+ return -EINVAL;
+ }
+
+- if ((start >> 28) != (end >> 28)) {
++ if ((start >> 28) != ((end - 1) >> 28)) {
+ DRM_ERROR("reloc %LX-%LX crossing 256MB boundary!\n",
+ start, end);
+ return -EINVAL;
+@@ -620,7 +622,7 @@
+ if (r)
+ goto err;
+
+- r = radeon_ib_get(rdev, ring, &ib, NULL, 16);
++ r = radeon_ib_get(rdev, ring, &ib, NULL, 64);
+ if (r)
+ goto err;
+
+diff -Naur a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
+--- a/drivers/gpu/drm/radeon/rs690.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/rs690.c 2014-04-03 01:45:50.181111972 +0530
+@@ -162,6 +162,16 @@
+ base = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
+ base = G_000100_MC_FB_START(base) << 16;
+ rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev);
++ /* Some boards seem to be configured for 128MB of sideport memory,
++ * but really only have 64MB. Just skip the sideport and use
++ * UMA memory.
++ */
++ if (rdev->mc.igp_sideport_enabled &&
++ (rdev->mc.real_vram_size == (384 * 1024 * 1024))) {
++ base += 128 * 1024 * 1024;
++ rdev->mc.real_vram_size -= 128 * 1024 * 1024;
++ rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
++ }
+
+ /* Use K8 direct mapping for fast fb access. */
+ rdev->fastfb_working = false;
+diff -Naur a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
+--- a/drivers/gpu/drm/radeon/rv770_dpm.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/rv770_dpm.c 2014-04-03 01:45:50.185111972 +0530
+@@ -2328,6 +2328,12 @@
+ pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
+ ASIC_INTERNAL_MEMORY_SS, 0);
+
++ /* disable ss, causes hangs on some cayman boards */
++ if (rdev->family == CHIP_CAYMAN) {
++ pi->sclk_ss = false;
++ pi->mclk_ss = false;
++ }
++
+ if (pi->sclk_ss || pi->mclk_ss)
+ pi->dynamic_ss = true;
+ else
+diff -Naur a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
+--- a/drivers/gpu/drm/radeon/si.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/si.c 2014-04-03 01:45:50.189111972 +0530
+@@ -2816,7 +2816,7 @@
+ }
+
+ static u32 si_get_rb_disabled(struct radeon_device *rdev,
+- u32 max_rb_num, u32 se_num,
++ u32 max_rb_num_per_se,
+ u32 sh_per_se)
+ {
+ u32 data, mask;
+@@ -2830,14 +2830,14 @@
+
+ data >>= BACKEND_DISABLE_SHIFT;
+
+- mask = si_create_bitmask(max_rb_num / se_num / sh_per_se);
++ mask = si_create_bitmask(max_rb_num_per_se / sh_per_se);
+
+ return data & mask;
+ }
+
+ static void si_setup_rb(struct radeon_device *rdev,
+ u32 se_num, u32 sh_per_se,
+- u32 max_rb_num)
++ u32 max_rb_num_per_se)
+ {
+ int i, j;
+ u32 data, mask;
+@@ -2847,19 +2847,21 @@
+ for (i = 0; i < se_num; i++) {
+ for (j = 0; j < sh_per_se; j++) {
+ si_select_se_sh(rdev, i, j);
+- data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se);
++ data = si_get_rb_disabled(rdev, max_rb_num_per_se, sh_per_se);
+ disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
+ }
+ }
+ si_select_se_sh(rdev, 0xffffffff, 0xffffffff);
+
+ mask = 1;
+- for (i = 0; i < max_rb_num; i++) {
++ for (i = 0; i < max_rb_num_per_se * se_num; i++) {
+ if (!(disabled_rbs & mask))
+ enabled_rbs |= mask;
+ mask <<= 1;
+ }
+
++ rdev->config.si.backend_enable_mask = enabled_rbs;
++
+ for (i = 0; i < se_num; i++) {
+ si_select_se_sh(rdev, i, 0xffffffff);
+ data = 0;
+@@ -3887,8 +3889,15 @@
+ rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0);
+ rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0);
+ /* size in MB on si */
+- rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+- rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
++ tmp = RREG32(CONFIG_MEMSIZE);
++ /* some boards may have garbage in the upper 16 bits */
++ if (tmp & 0xffff0000) {
++ DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
++ if (tmp & 0xffff)
++ tmp &= 0xffff;
++ }
++ rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL;
++ rdev->mc.real_vram_size = rdev->mc.mc_vram_size;
+ rdev->mc.visible_vram_size = rdev->mc.aper_size;
+ si_vram_gtt_location(rdev, &rdev->mc);
+ radeon_update_bandwidth_info(rdev);
+diff -Naur a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
+--- a/drivers/gpu/drm/radeon/sid.h 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/sid.h 2014-04-03 01:45:50.189111972 +0530
+@@ -478,7 +478,7 @@
+ #define STATE3_MASK (0x1f << 15)
+ #define STATE3_SHIFT 15
+
+-#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808
++#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8
+ #define TRAIN_DONE_D0 (1 << 30)
+ #define TRAIN_DONE_D1 (1 << 31)
+
+diff -Naur a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
+--- a/drivers/gpu/drm/radeon/trinity_dpm.c 2013-11-04 05:11:51.000000000 +0530
++++ b/drivers/gpu/drm/radeon/trinity_dpm.c 2014-04-03 01:45:50.193111972 +0530
+@@ -1873,9 +1873,9 @@
+ pi->enable_sclk_ds = true;
+ pi->enable_gfx_power_gating = true;
+ pi->enable_gfx_clock_gating = true;
+- pi->enable_mg_clock_gating = true;
+- pi->enable_gfx_dynamic_mgpg = true; /* ??? */
+- pi->override_dynamic_mgpg = true;
++ pi->enable_mg_clock_gating = false;
++ pi->enable_gfx_dynamic_mgpg = false;
++ pi->override_dynamic_mgpg = false;
+ pi->enable_auto_thermal_throttling = true;
+ pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
+ pi->uvd_dpm = true; /* ??? */
+diff -Naur a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+--- a/include/acpi/acpi_bus.h 2013-11-04 05:11:51.000000000 +0530
++++ b/include/acpi/acpi_bus.h 2014-04-03 02:41:15.381170177 +0530
+@@ -168,6 +168,7 @@
+ u32 ejectable:1;
+ u32 power_manageable:1;
+ u32 match_driver:1;
++ u32 no_hotplug:1;
+ u32 reserved:27;
+ };
+
+@@ -356,6 +357,7 @@
+ extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
+ void acpi_bus_private_data_handler(acpi_handle, void *);
+ int acpi_bus_get_private_data(acpi_handle, void **);
++void acpi_bus_no_hotplug(acpi_handle handle);
+ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
+ extern int register_acpi_notifier(struct notifier_block *);
+ extern int unregister_acpi_notifier(struct notifier_block *);
+diff -Naur a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
+--- a/include/uapi/drm/radeon_drm.h 2013-11-04 05:11:51.000000000 +0530
++++ b/include/uapi/drm/radeon_drm.h 2014-04-03 02:30:27.125158815 +0530
+@@ -981,6 +981,8 @@
+ #define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16
+ /* query if CP DMA is supported on the compute ring */
+ #define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17
++/* query the number of render backends */
++#define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19
+
+
+ struct drm_radeon_info {
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0001-yocto-amd-drm-radeon-add-vm_set_page-tracepoint.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0001-yocto-amd-drm-radeon-add-vm_set_page-tracepoint.patch
new file mode 100644
index 00000000..7374ddfe
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0001-yocto-amd-drm-radeon-add-vm_set_page-tracepoint.patch
@@ -0,0 +1,118 @@
+From c97f6a9d11c7350c40e84ae85851e46f546e9ace Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 29 Oct 2013 20:14:48 +0100
+Subject: [PATCH 01/44] drm/radeon: add vm_set_page tracepoint
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/cik_sdma.c | 3 +++
+ drivers/gpu/drm/radeon/ni_dma.c | 3 +++
+ drivers/gpu/drm/radeon/radeon_trace.h | 24 ++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/si_dma.c | 3 +++
+ 4 files changed, 33 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index aaf7ffc..ed65b6e 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -25,6 +25,7 @@
+ #include <drm/drmP.h>
+ #include "radeon.h"
+ #include "radeon_asic.h"
++#include "radeon_trace.h"
+ #include "cikd.h"
+
+ /* sdma */
+@@ -657,6 +658,8 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ uint64_t value;
+ unsigned ndw;
+
++ trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++
+ if (flags & RADEON_VM_PAGE_SYSTEM) {
+ while (count) {
+ ndw = count * 2;
+diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
+index dd6e968..e9cfe8a 100644
+--- a/drivers/gpu/drm/radeon/ni_dma.c
++++ b/drivers/gpu/drm/radeon/ni_dma.c
+@@ -24,6 +24,7 @@
+ #include <drm/drmP.h>
+ #include "radeon.h"
+ #include "radeon_asic.h"
++#include "radeon_trace.h"
+ #include "nid.h"
+
+ u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev);
+@@ -260,6 +261,8 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+ uint64_t value;
+ unsigned ndw;
+
++ trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++
+ if ((flags & RADEON_VM_PAGE_SYSTEM) || (count == 1)) {
+ while (count) {
+ ndw = count * 2;
+diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
+index f7e3678..811bca6 100644
+--- a/drivers/gpu/drm/radeon/radeon_trace.h
++++ b/drivers/gpu/drm/radeon/radeon_trace.h
+@@ -47,6 +47,30 @@ TRACE_EVENT(radeon_cs,
+ __entry->fences)
+ );
+
++TRACE_EVENT(radeon_vm_set_page,
++ TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
++ uint32_t incr, uint32_t flags),
++ TP_ARGS(pe, addr, count, incr, flags),
++ TP_STRUCT__entry(
++ __field(u64, pe)
++ __field(u64, addr)
++ __field(u32, count)
++ __field(u32, incr)
++ __field(u32, flags)
++ ),
++
++ TP_fast_assign(
++ __entry->pe = pe;
++ __entry->addr = addr;
++ __entry->count = count;
++ __entry->incr = incr;
++ __entry->flags = flags;
++ ),
++ TP_printk("pe=%010Lx, addr=%010Lx, incr=%u, flags=%08x, count=%u",
++ __entry->pe, __entry->addr, __entry->incr,
++ __entry->flags, __entry->count)
++);
++
+ DECLARE_EVENT_CLASS(radeon_fence_request,
+
+ TP_PROTO(struct drm_device *dev, u32 seqno),
+diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
+index 49909d2..17205fd 100644
+--- a/drivers/gpu/drm/radeon/si_dma.c
++++ b/drivers/gpu/drm/radeon/si_dma.c
+@@ -24,6 +24,7 @@
+ #include <drm/drmP.h>
+ #include "radeon.h"
+ #include "radeon_asic.h"
++#include "radeon_trace.h"
+ #include "sid.h"
+
+ u32 si_gpu_check_soft_reset(struct radeon_device *rdev);
+@@ -79,6 +80,8 @@ void si_dma_vm_set_page(struct radeon_device *rdev,
+ uint64_t value;
+ unsigned ndw;
+
++ trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++
+ if (flags & RADEON_VM_PAGE_SYSTEM) {
+ while (count) {
+ ndw = count * 2;
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0002-yocto-amd-drm-radeon-cleanup-flushing-on-CIK-v3.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0002-yocto-amd-drm-radeon-cleanup-flushing-on-CIK-v3.patch
new file mode 100644
index 00000000..986489c2
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0002-yocto-amd-drm-radeon-cleanup-flushing-on-CIK-v3.patch
@@ -0,0 +1,96 @@
+From eee59eb01ab5dcbf99d6c11d5467f933e76ba99f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <marek.olsak@amd.com>
+Date: Sat, 19 Oct 2013 22:06:43 +0200
+Subject: [PATCH 02/44] drm/radeon: cleanup flushing on CIK (v3)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+v2: fix compute handling.
+v3: use HDP_MEM_COHERENCY_FLUSH_CNTL again
+
+Signed-off-by: Marek Olšák <marek.olsak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 43 +++++++++++++++---------------------------
+ 1 file changed, 15 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 31f5f0e..2277a59 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -3011,6 +3011,18 @@ int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
+ return r;
+ }
+
++static void cik_cp_hdp_flush(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ /* Request an HDP flush */
++ radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
++ radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
++ WRITE_DATA_DST_SEL(0)));
++ radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
++ radeon_ring_write(ring, 0);
++ radeon_ring_write(ring, 0);
++}
++
+ /**
+ * cik_fence_gfx_ring_emit - emit a fence on the gfx ring
+ *
+@@ -3037,15 +3049,7 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, fence->seq);
+ radeon_ring_write(ring, 0);
+ /* HDP flush */
+- /* We should be using the new WAIT_REG_MEM special op packet here
+- * but it causes the CP to hang
+- */
+- radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+- WRITE_DATA_DST_SEL(0)));
+- radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
+- radeon_ring_write(ring, 0);
+- radeon_ring_write(ring, 0);
++ cik_cp_hdp_flush(rdev, ring);
+ }
+
+ /**
+@@ -3075,15 +3079,7 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, fence->seq);
+ radeon_ring_write(ring, 0);
+ /* HDP flush */
+- /* We should be using the new WAIT_REG_MEM special op packet here
+- * but it causes the CP to hang
+- */
+- radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+- WRITE_DATA_DST_SEL(0)));
+- radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
+- radeon_ring_write(ring, 0);
+- radeon_ring_write(ring, 0);
++ cik_cp_hdp_flush(rdev, ring);
+ }
+
+ void cik_semaphore_ring_emit(struct radeon_device *rdev,
+@@ -4809,16 +4805,7 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
+ radeon_ring_write(ring, VMID(0));
+
+ /* HDP flush */
+- /* We should be using the WAIT_REG_MEM packet here like in
+- * cik_fence_ring_emit(), but it causes the CP to hang in this
+- * context...
+- */
+- radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+- radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+- WRITE_DATA_DST_SEL(0)));
+- radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
+- radeon_ring_write(ring, 0);
+- radeon_ring_write(ring, 0);
++ cik_cp_hdp_flush(rdev, ring);
+
+ /* bits 0-15 are the VM contexts0-15 */
+ radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0003-yocto-amd-drm-radeon-cleanup-DMA-HDP-flush-on-CIK-v2.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0003-yocto-amd-drm-radeon-cleanup-DMA-HDP-flush-on-CIK-v2.patch
new file mode 100644
index 00000000..8fe9e087
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0003-yocto-amd-drm-radeon-cleanup-DMA-HDP-flush-on-CIK-v2.patch
@@ -0,0 +1,100 @@
+From 9c318cd900e41358c7507cb144f0ef8f5c0bbb19 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 5 Nov 2013 18:12:13 -0500
+Subject: [PATCH 03/44] drm/radeon: cleanup DMA HDP flush on CIK (v2)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+v2: use HDP_MEM_COHERENCY_FLUSH_CNTL again
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik_sdma.c | 38 ++++++++++---------------------------
+ 1 file changed, 10 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index ed65b6e..56ede52 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -51,6 +51,14 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev);
+ * buffers.
+ */
+
++static void cik_sdma_hdp_flush(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
++ radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2);
++ radeon_ring_write(ring, 0x0);
++}
++
+ /**
+ * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine
+ *
+@@ -102,14 +110,6 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
+ {
+ struct radeon_ring *ring = &rdev->ring[fence->ring];
+ u64 addr = rdev->fence_drv[fence->ring].gpu_addr;
+- u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) |
+- SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
+- u32 ref_and_mask;
+-
+- if (fence->ring == R600_RING_TYPE_DMA_INDEX)
+- ref_and_mask = SDMA0;
+- else
+- ref_and_mask = SDMA1;
+
+ /* write the fence */
+ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_FENCE, 0, 0));
+@@ -119,12 +119,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
+ /* generate an interrupt */
+ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0));
+ /* flush HDP */
+- radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits));
+- radeon_ring_write(ring, GPU_HDP_FLUSH_DONE);
+- radeon_ring_write(ring, GPU_HDP_FLUSH_REQ);
+- radeon_ring_write(ring, ref_and_mask); /* REFERENCE */
+- radeon_ring_write(ring, ref_and_mask); /* MASK */
+- radeon_ring_write(ring, (4 << 16) | 10); /* RETRY_COUNT, POLL_INTERVAL */
++ cik_sdma_hdp_flush(rdev, ring);
+ }
+
+ /**
+@@ -727,18 +722,10 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
+ {
+ struct radeon_ring *ring = &rdev->ring[ridx];
+- u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) |
+- SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */
+- u32 ref_and_mask;
+
+ if (vm == NULL)
+ return;
+
+- if (ridx == R600_RING_TYPE_DMA_INDEX)
+- ref_and_mask = SDMA0;
+- else
+- ref_and_mask = SDMA1;
+-
+ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
+ if (vm->id < 8) {
+ radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2)) >> 2);
+@@ -773,12 +760,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm
+ radeon_ring_write(ring, VMID(0));
+
+ /* flush HDP */
+- radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits));
+- radeon_ring_write(ring, GPU_HDP_FLUSH_DONE);
+- radeon_ring_write(ring, GPU_HDP_FLUSH_REQ);
+- radeon_ring_write(ring, ref_and_mask); /* REFERENCE */
+- radeon_ring_write(ring, ref_and_mask); /* MASK */
+- radeon_ring_write(ring, (4 << 16) | 10); /* RETRY_COUNT, POLL_INTERVAL */
++ cik_sdma_hdp_flush(rdev, ring);
+
+ /* flush TLB */
+ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000));
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0004-yocto-amd-drm-radeon-allow-semaphore-emission-to-fail.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0004-yocto-amd-drm-radeon-allow-semaphore-emission-to-fail.patch
new file mode 100644
index 00000000..f8d0e106
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0004-yocto-amd-drm-radeon-allow-semaphore-emission-to-fail.patch
@@ -0,0 +1,754 @@
+From 26046527719672da3148501129151ccbceaf8339 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 8 Jul 2013 05:11:52 -0600
+Subject: [PATCH 04/44] drm/radeon: allow semaphore emission to fail
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Some rings can only use semaphore in certain states, take that into account
+and fall back to waiting for a fence when a ring currently can't emit a
+semaphore.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 4 +-
+ drivers/gpu/drm/radeon/cik_sdma.c | 13 ++-
+ drivers/gpu/drm/radeon/evergreen_dma.c | 9 +--
+ drivers/gpu/drm/radeon/r100.c | 3 +-
+ drivers/gpu/drm/radeon/r600.c | 13 ++-
+ drivers/gpu/drm/radeon/r600_dma.c | 13 ++-
+ drivers/gpu/drm/radeon/radeon.h | 14 ++--
+ drivers/gpu/drm/radeon/radeon_asic.h | 18 ++---
+ drivers/gpu/drm/radeon/radeon_cs.c | 9 ++-
+ drivers/gpu/drm/radeon/radeon_fence.c | 26 ++++++
+ drivers/gpu/drm/radeon/radeon_gart.c | 2 +-
+ drivers/gpu/drm/radeon/radeon_ring.c | 46 +++--------
+ drivers/gpu/drm/radeon/radeon_semaphore.c | 123 ++++++++++++++++++++++-------
+ drivers/gpu/drm/radeon/rv770_dma.c | 9 +--
+ drivers/gpu/drm/radeon/si_dma.c | 9 +--
+ drivers/gpu/drm/radeon/uvd_v1_0.c | 4 +-
+ drivers/gpu/drm/radeon/uvd_v3_1.c | 4 +-
+ 17 files changed, 182 insertions(+), 137 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 2277a59..0608446 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -3082,7 +3082,7 @@ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
+ cik_cp_hdp_flush(rdev, ring);
+ }
+
+-void cik_semaphore_ring_emit(struct radeon_device *rdev,
++bool cik_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -3093,6 +3093,8 @@ void cik_semaphore_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1));
+ radeon_ring_write(ring, addr & 0xffffffff);
+ radeon_ring_write(ring, (upper_32_bits(addr) & 0xffff) | sel);
++
++ return true;
+ }
+
+ /*
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index 56ede52..ace0bc6 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -133,7 +133,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
+ * Add a DMA semaphore packet to the ring wait on or signal
+ * other rings (CIK).
+ */
+-void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
++bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -144,6 +144,8 @@ void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SEMAPHORE, 0, extra_bits));
+ radeon_ring_write(ring, addr & 0xfffffff8);
+ radeon_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
++
++ return true;
+ }
+
+ /**
+@@ -446,13 +448,8 @@ int cik_copy_dma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ for (i = 0; i < num_loops; i++) {
+ cur_size_in_bytes = size_in_bytes;
+diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c
+index 6a0656d..a37b544 100644
+--- a/drivers/gpu/drm/radeon/evergreen_dma.c
++++ b/drivers/gpu/drm/radeon/evergreen_dma.c
+@@ -131,13 +131,8 @@ int evergreen_copy_dma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ for (i = 0; i < num_loops; i++) {
+ cur_size_in_dw = size_in_dw;
+diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
+index d713330..aa015a5 100644
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -869,13 +869,14 @@ void r100_fence_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, RADEON_SW_INT_FIRE);
+ }
+
+-void r100_semaphore_ring_emit(struct radeon_device *rdev,
++bool r100_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+ {
+ /* Unused on older asics, since we don't have semaphores or multiple rings */
+ BUG();
++ return false;
+ }
+
+ int r100_copy_blit(struct radeon_device *rdev,
+diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
+index f9be220..a5de2cf 100644
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -2597,7 +2597,7 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
+ }
+ }
+
+-void r600_semaphore_ring_emit(struct radeon_device *rdev,
++bool r600_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -2611,6 +2611,8 @@ void r600_semaphore_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1));
+ radeon_ring_write(ring, addr & 0xffffffff);
+ radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel);
++
++ return true;
+ }
+
+ /**
+@@ -2653,13 +2655,8 @@ int r600_copy_cpdma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
+ radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
+diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c
+index 3b31745..7844d15 100644
+--- a/drivers/gpu/drm/radeon/r600_dma.c
++++ b/drivers/gpu/drm/radeon/r600_dma.c
+@@ -311,7 +311,7 @@ void r600_dma_fence_ring_emit(struct radeon_device *rdev,
+ * Add a DMA semaphore packet to the ring wait on or signal
+ * other rings (r6xx-SI).
+ */
+-void r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
++bool r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -322,6 +322,8 @@ void r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
+ radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SEMAPHORE, 0, s, 0));
+ radeon_ring_write(ring, addr & 0xfffffffc);
+ radeon_ring_write(ring, upper_32_bits(addr) & 0xff);
++
++ return true;
+ }
+
+ /**
+@@ -462,13 +464,8 @@ int r600_copy_dma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ for (i = 0; i < num_loops; i++) {
+ cur_size_in_dw = size_in_dw;
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index f44ca58..c0d4230 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -348,6 +348,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, i
+ void radeon_fence_process(struct radeon_device *rdev, int ring);
+ bool radeon_fence_signaled(struct radeon_fence *fence);
+ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible);
++int radeon_fence_wait_locked(struct radeon_fence *fence);
+ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring);
+ int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring);
+ int radeon_fence_wait_any(struct radeon_device *rdev,
+@@ -548,17 +549,20 @@ struct radeon_semaphore {
+ struct radeon_sa_bo *sa_bo;
+ signed waiters;
+ uint64_t gpu_addr;
++ struct radeon_fence *sync_to[RADEON_NUM_RINGS];
+ };
+
+ int radeon_semaphore_create(struct radeon_device *rdev,
+ struct radeon_semaphore **semaphore);
+-void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
++bool radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
+ struct radeon_semaphore *semaphore);
+-void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
++bool radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
+ struct radeon_semaphore *semaphore);
++void radeon_semaphore_sync_to(struct radeon_semaphore *semaphore,
++ struct radeon_fence *fence);
+ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+ struct radeon_semaphore *semaphore,
+- int signaler, int waiter);
++ int waiting_ring);
+ void radeon_semaphore_free(struct radeon_device *rdev,
+ struct radeon_semaphore **semaphore,
+ struct radeon_fence *fence);
+@@ -765,7 +769,6 @@ struct radeon_ib {
+ struct radeon_fence *fence;
+ struct radeon_vm *vm;
+ bool is_const_ib;
+- struct radeon_fence *sync_to[RADEON_NUM_RINGS];
+ struct radeon_semaphore *semaphore;
+ };
+
+@@ -915,7 +918,6 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
+ struct radeon_ib *ib, struct radeon_vm *vm,
+ unsigned size);
+ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib);
+-void radeon_ib_sync_to(struct radeon_ib *ib, struct radeon_fence *fence);
+ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
+ struct radeon_ib *const_ib);
+ int radeon_ib_pool_init(struct radeon_device *rdev);
+@@ -1629,7 +1631,7 @@ struct radeon_asic_ring {
+ /* command emmit functions */
+ void (*ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
+ void (*emit_fence)(struct radeon_device *rdev, struct radeon_fence *fence);
+- void (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp,
++ bool (*emit_semaphore)(struct radeon_device *rdev, struct radeon_ring *cp,
+ struct radeon_semaphore *semaphore, bool emit_wait);
+ void (*vm_flush)(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
+index 70c29d5..8588670 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.h
++++ b/drivers/gpu/drm/radeon/radeon_asic.h
+@@ -80,7 +80,7 @@ int r100_irq_set(struct radeon_device *rdev);
+ int r100_irq_process(struct radeon_device *rdev);
+ void r100_fence_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void r100_semaphore_ring_emit(struct radeon_device *rdev,
++bool r100_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *cp,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+@@ -313,13 +313,13 @@ int r600_cs_parse(struct radeon_cs_parser *p);
+ int r600_dma_cs_parse(struct radeon_cs_parser *p);
+ void r600_fence_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void r600_semaphore_ring_emit(struct radeon_device *rdev,
++bool r600_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *cp,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+ void r600_dma_fence_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
++bool r600_dma_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+@@ -566,10 +566,6 @@ int sumo_dpm_force_performance_level(struct radeon_device *rdev,
+ */
+ void cayman_fence_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void cayman_uvd_semaphore_emit(struct radeon_device *rdev,
+- struct radeon_ring *ring,
+- struct radeon_semaphore *semaphore,
+- bool emit_wait);
+ void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev);
+ int cayman_init(struct radeon_device *rdev);
+ void cayman_fini(struct radeon_device *rdev);
+@@ -696,7 +692,7 @@ void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
+ void cik_sdma_fence_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
++bool cik_sdma_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+@@ -712,7 +708,7 @@ void cik_fence_gfx_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+ void cik_fence_compute_ring_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+-void cik_semaphore_ring_emit(struct radeon_device *rdev,
++bool cik_semaphore_ring_emit(struct radeon_device *rdev,
+ struct radeon_ring *cp,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+@@ -802,7 +798,7 @@ void uvd_v1_0_stop(struct radeon_device *rdev);
+
+ int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
+ int uvd_v1_0_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
+-void uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
++bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+@@ -814,7 +810,7 @@ void uvd_v2_2_fence_emit(struct radeon_device *rdev,
+ struct radeon_fence *fence);
+
+ /* uvd v3.1 */
+-void uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
++bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
+diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
+index 80285e3..eb5cd94 100644
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -159,7 +159,8 @@ static void radeon_cs_sync_rings(struct radeon_cs_parser *p)
+ if (!p->relocs[i].robj)
+ continue;
+
+- radeon_ib_sync_to(&p->ib, p->relocs[i].robj->tbo.sync_obj);
++ radeon_semaphore_sync_to(p->ib.semaphore,
++ p->relocs[i].robj->tbo.sync_obj);
+ }
+ }
+
+@@ -495,9 +496,9 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
+ goto out;
+ }
+ radeon_cs_sync_rings(parser);
+- radeon_ib_sync_to(&parser->ib, vm->fence);
+- radeon_ib_sync_to(&parser->ib, radeon_vm_grab_id(
+- rdev, vm, parser->ring));
++ radeon_semaphore_sync_to(parser->ib.semaphore, vm->fence);
++ radeon_semaphore_sync_to(parser->ib.semaphore,
++ radeon_vm_grab_id(rdev, vm, parser->ring));
+
+ if ((rdev->family >= CHIP_TAHITI) &&
+ (parser->chunk_const_ib_idx != -1)) {
+diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
+index ddb8f8e..8aea16e 100644
+--- a/drivers/gpu/drm/radeon/radeon_fence.c
++++ b/drivers/gpu/drm/radeon/radeon_fence.c
+@@ -404,6 +404,32 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
+ return 0;
+ }
+
++/**
++ * radeon_fence_wait_locked - wait for a fence to signal
++ *
++ * @fence: radeon fence object
++ *
++ * Wait for the requested fence to signal (all asics).
++ * Returns 0 if the fence has passed, error for all other cases.
++ */
++int radeon_fence_wait_locked(struct radeon_fence *fence)
++{
++ int r;
++
++ if (fence == NULL) {
++ WARN(1, "Querying an invalid fence : %p !\n", fence);
++ return -EINVAL;
++ }
++
++ r = radeon_fence_wait_seq(fence->rdev, fence->seq,
++ fence->ring, false, false);
++ if (r) {
++ return r;
++ }
++ fence->seq = RADEON_FENCE_SIGNALED_SEQ;
++ return 0;
++}
++
+ static bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq)
+ {
+ unsigned i;
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index 3b1de72..f8d7b16 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -1169,7 +1169,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
+ radeon_vm_update_ptes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset,
+ addr, bo_va->flags);
+
+- radeon_ib_sync_to(&ib, vm->fence);
++ radeon_semaphore_sync_to(ib.semaphore, vm->fence);
+ r = radeon_ib_schedule(rdev, &ib, NULL);
+ if (r) {
+ radeon_ib_free(rdev, &ib);
+diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
+index 18254e1..9214403 100644
+--- a/drivers/gpu/drm/radeon/radeon_ring.c
++++ b/drivers/gpu/drm/radeon/radeon_ring.c
+@@ -61,7 +61,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
+ struct radeon_ib *ib, struct radeon_vm *vm,
+ unsigned size)
+ {
+- int i, r;
++ int r;
+
+ r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &ib->sa_bo, size, 256, true);
+ if (r) {
+@@ -87,8 +87,6 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
+ ib->gpu_addr = radeon_sa_bo_gpu_addr(ib->sa_bo);
+ }
+ ib->is_const_ib = false;
+- for (i = 0; i < RADEON_NUM_RINGS; ++i)
+- ib->sync_to[i] = NULL;
+
+ return 0;
+ }
+@@ -109,25 +107,6 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib)
+ }
+
+ /**
+- * radeon_ib_sync_to - sync to fence before executing the IB
+- *
+- * @ib: IB object to add fence to
+- * @fence: fence to sync to
+- *
+- * Sync to the fence before executing the IB
+- */
+-void radeon_ib_sync_to(struct radeon_ib *ib, struct radeon_fence *fence)
+-{
+- struct radeon_fence *other;
+-
+- if (!fence)
+- return;
+-
+- other = ib->sync_to[fence->ring];
+- ib->sync_to[fence->ring] = radeon_fence_later(fence, other);
+-}
+-
+-/**
+ * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring
+ *
+ * @rdev: radeon_device pointer
+@@ -151,8 +130,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
+ struct radeon_ib *const_ib)
+ {
+ struct radeon_ring *ring = &rdev->ring[ib->ring];
+- bool need_sync = false;
+- int i, r = 0;
++ int r = 0;
+
+ if (!ib->length_dw || !ring->ready) {
+ /* TODO: Nothings in the ib we should report. */
+@@ -166,19 +144,15 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
+ dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
+ return r;
+ }
+- for (i = 0; i < RADEON_NUM_RINGS; ++i) {
+- struct radeon_fence *fence = ib->sync_to[i];
+- if (radeon_fence_need_sync(fence, ib->ring)) {
+- need_sync = true;
+- radeon_semaphore_sync_rings(rdev, ib->semaphore,
+- fence->ring, ib->ring);
+- radeon_fence_note_sync(fence, ib->ring);
+- }
+- }
+- /* immediately free semaphore when we don't need to sync */
+- if (!need_sync) {
+- radeon_semaphore_free(rdev, &ib->semaphore, NULL);
++
++ /* sync with other rings */
++ r = radeon_semaphore_sync_rings(rdev, ib->semaphore, ib->ring);
++ if (r) {
++ dev_err(rdev->dev, "failed to sync rings (%d)\n", r);
++ radeon_ring_unlock_undo(rdev, ring);
++ return r;
+ }
++
+ /* if we can't remember our last VM flush then flush now! */
+ /* XXX figure out why we have to flush for every IB */
+ if (ib->vm /*&& !ib->vm->last_flush*/) {
+diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
+index 8dcc20f..34ea889 100644
+--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
++++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
+@@ -34,7 +34,7 @@
+ int radeon_semaphore_create(struct radeon_device *rdev,
+ struct radeon_semaphore **semaphore)
+ {
+- int r;
++ int i, r;
+
+ *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
+ if (*semaphore == NULL) {
+@@ -50,54 +50,117 @@ int radeon_semaphore_create(struct radeon_device *rdev,
+ (*semaphore)->waiters = 0;
+ (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
+ *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;
++
++ for (i = 0; i < RADEON_NUM_RINGS; ++i)
++ (*semaphore)->sync_to[i] = NULL;
++
+ return 0;
+ }
+
+-void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring,
++bool radeon_semaphore_emit_signal(struct radeon_device *rdev, int ridx,
+ struct radeon_semaphore *semaphore)
+ {
+- --semaphore->waiters;
+- radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false);
++ struct radeon_ring *ring = &rdev->ring[ridx];
++
++ if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, false)) {
++ --semaphore->waiters;
++
++ /* for debugging lockup only, used by sysfs debug files */
++ ring->last_semaphore_signal_addr = semaphore->gpu_addr;
++ return true;
++ }
++ return false;
+ }
+
+-void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring,
++bool radeon_semaphore_emit_wait(struct radeon_device *rdev, int ridx,
+ struct radeon_semaphore *semaphore)
+ {
+- ++semaphore->waiters;
+- radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true);
++ struct radeon_ring *ring = &rdev->ring[ridx];
++
++ if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, true)) {
++ ++semaphore->waiters;
++
++ /* for debugging lockup only, used by sysfs debug files */
++ ring->last_semaphore_wait_addr = semaphore->gpu_addr;
++ return true;
++ }
++ return false;
+ }
+
+-/* caller must hold ring lock */
++/**
++ * radeon_semaphore_sync_to - use the semaphore to sync to a fence
++ *
++ * @semaphore: semaphore object to add fence to
++ * @fence: fence to sync to
++ *
++ * Sync to the fence using this semaphore object
++ */
++void radeon_semaphore_sync_to(struct radeon_semaphore *semaphore,
++ struct radeon_fence *fence)
++{
++ struct radeon_fence *other;
++
++ if (!fence)
++ return;
++
++ other = semaphore->sync_to[fence->ring];
++ semaphore->sync_to[fence->ring] = radeon_fence_later(fence, other);
++}
++
++/**
++ * radeon_semaphore_sync_rings - sync ring to all registered fences
++ *
++ * @rdev: radeon_device pointer
++ * @semaphore: semaphore object to use for sync
++ * @ring: ring that needs sync
++ *
++ * Ensure that all registered fences are signaled before letting
++ * the ring continue. The caller must hold the ring lock.
++ */
+ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
+ struct radeon_semaphore *semaphore,
+- int signaler, int waiter)
++ int ring)
+ {
+- int r;
++ int i, r;
+
+- /* no need to signal and wait on the same ring */
+- if (signaler == waiter) {
+- return 0;
+- }
++ for (i = 0; i < RADEON_NUM_RINGS; ++i) {
++ struct radeon_fence *fence = semaphore->sync_to[i];
+
+- /* prevent GPU deadlocks */
+- if (!rdev->ring[signaler].ready) {
+- dev_err(rdev->dev, "Trying to sync to a disabled ring!");
+- return -EINVAL;
+- }
++ /* check if we really need to sync */
++ if (!radeon_fence_need_sync(fence, ring))
++ continue;
+
+- r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8);
+- if (r) {
+- return r;
+- }
+- radeon_semaphore_emit_signal(rdev, signaler, semaphore);
+- radeon_ring_commit(rdev, &rdev->ring[signaler]);
++ /* prevent GPU deadlocks */
++ if (!rdev->ring[i].ready) {
++ dev_err(rdev->dev, "Syncing to a disabled ring!");
++ return -EINVAL;
++ }
+
+- /* we assume caller has already allocated space on waiters ring */
+- radeon_semaphore_emit_wait(rdev, waiter, semaphore);
++ /* allocate enough space for sync command */
++ r = radeon_ring_alloc(rdev, &rdev->ring[i], 16);
++ if (r) {
++ return r;
++ }
+
+- /* for debugging lockup only, used by sysfs debug files */
+- rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr;
+- rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr;
++ /* emit the signal semaphore */
++ if (!radeon_semaphore_emit_signal(rdev, i, semaphore)) {
++ /* signaling wasn't successful wait manually */
++ radeon_ring_undo(&rdev->ring[i]);
++ radeon_fence_wait_locked(fence);
++ continue;
++ }
++
++ /* we assume caller has already allocated space on waiters ring */
++ if (!radeon_semaphore_emit_wait(rdev, ring, semaphore)) {
++ /* waiting wasn't successful wait manually */
++ radeon_ring_undo(&rdev->ring[i]);
++ radeon_fence_wait_locked(fence);
++ continue;
++ }
++
++ radeon_ring_commit(rdev, &rdev->ring[i]);
++ radeon_fence_note_sync(fence, ring);
++ }
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c
+index f9b02e3..aca8cbe 100644
+--- a/drivers/gpu/drm/radeon/rv770_dma.c
++++ b/drivers/gpu/drm/radeon/rv770_dma.c
+@@ -66,13 +66,8 @@ int rv770_copy_dma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ for (i = 0; i < num_loops; i++) {
+ cur_size_in_dw = size_in_dw;
+diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
+index 17205fd..97af34c 100644
+--- a/drivers/gpu/drm/radeon/si_dma.c
++++ b/drivers/gpu/drm/radeon/si_dma.c
+@@ -202,13 +202,8 @@ int si_copy_dma(struct radeon_device *rdev,
+ return r;
+ }
+
+- if (radeon_fence_need_sync(*fence, ring->idx)) {
+- radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
+- ring->idx);
+- radeon_fence_note_sync(*fence, ring->idx);
+- } else {
+- radeon_semaphore_free(rdev, &sem, NULL);
+- }
++ radeon_semaphore_sync_to(sem, *fence);
++ radeon_semaphore_sync_rings(rdev, sem, ring->idx);
+
+ for (i = 0; i < num_loops; i++) {
+ cur_size_in_bytes = size_in_bytes;
+diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
+index 7266805..d4a68af 100644
+--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
++++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
+@@ -357,7 +357,7 @@ int uvd_v1_0_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+-void uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
++bool uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -372,6 +372,8 @@ void uvd_v1_0_semaphore_emit(struct radeon_device *rdev,
+
+ radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+ radeon_ring_write(ring, emit_wait ? 1 : 0);
++
++ return true;
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/radeon/uvd_v3_1.c b/drivers/gpu/drm/radeon/uvd_v3_1.c
+index 5b6fa1f..d722db2 100644
+--- a/drivers/gpu/drm/radeon/uvd_v3_1.c
++++ b/drivers/gpu/drm/radeon/uvd_v3_1.c
+@@ -37,7 +37,7 @@
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+-void uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
++bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+@@ -52,4 +52,6 @@ void uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+
+ radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+ radeon_ring_write(ring, 0x80 | (emit_wait ? 1 : 0));
++
++ return true;
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0005-yocto-amd-drm-radeon-improve-ring-debugfs-a-bit.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0005-yocto-amd-drm-radeon-improve-ring-debugfs-a-bit.patch
new file mode 100644
index 00000000..b46ce725
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0005-yocto-amd-drm-radeon-improve-ring-debugfs-a-bit.patch
@@ -0,0 +1,93 @@
+From e628d1bcf988fe77d8b040d00c97eb20645758ab Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 12 Nov 2013 10:55:12 -0700
+Subject: [PATCH 05/44] drm/radeon: improve ring debugfs a bit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_ring.c | 56 +++++++++++++++++++++++-----------
+ 1 file changed, 38 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
+index 9214403..f1cec22 100644
+--- a/drivers/gpu/drm/radeon/radeon_ring.c
++++ b/drivers/gpu/drm/radeon/radeon_ring.c
+@@ -790,34 +790,54 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
+ struct radeon_device *rdev = dev->dev_private;
+ int ridx = *(int*)node->info_ent->data;
+ struct radeon_ring *ring = &rdev->ring[ridx];
++
++ uint32_t rptr, wptr, rptr_next;
+ unsigned count, i, j;
+- u32 tmp;
+
+ radeon_ring_free_size(rdev, ring);
+ count = (ring->ring_size / 4) - ring->ring_free_dw;
+- tmp = radeon_ring_get_wptr(rdev, ring);
+- seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n", ring->wptr_reg, tmp, tmp);
+- tmp = radeon_ring_get_rptr(rdev, ring);
+- seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n", ring->rptr_reg, tmp, tmp);
++
++ wptr = radeon_ring_get_wptr(rdev, ring);
++ seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n",
++ ring->wptr_reg, wptr, wptr);
++
++ rptr = radeon_ring_get_rptr(rdev, ring);
++ seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n",
++ ring->rptr_reg, rptr, rptr);
++
+ if (ring->rptr_save_reg) {
+- seq_printf(m, "rptr next(0x%04x): 0x%08x\n", ring->rptr_save_reg,
+- RREG32(ring->rptr_save_reg));
+- }
+- seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
+- seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
+- seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
+- seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr);
++ rptr_next = RREG32(ring->rptr_save_reg);
++ seq_printf(m, "rptr next(0x%04x): 0x%08x [%5d]\n",
++ ring->rptr_save_reg, rptr_next, rptr_next);
++ } else
++ rptr_next = ~0;
++
++ seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n",
++ ring->wptr, ring->wptr);
++ seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n",
++ ring->rptr, ring->rptr);
++ seq_printf(m, "last semaphore signal addr : 0x%016llx\n",
++ ring->last_semaphore_signal_addr);
++ seq_printf(m, "last semaphore wait addr : 0x%016llx\n",
++ ring->last_semaphore_wait_addr);
+ seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
+ seq_printf(m, "%u dwords in ring\n", count);
++
++ if (!ring->ready)
++ return 0;
++
+ /* print 8 dw before current rptr as often it's the last executed
+ * packet that is the root issue
+ */
+- i = (ring->rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
+- if (ring->ready) {
+- for (j = 0; j <= (count + 32); j++) {
+- seq_printf(m, "r[%5d]=0x%08x\n", i, ring->ring[i]);
+- i = (i + 1) & ring->ptr_mask;
+- }
++ i = (rptr + ring->ptr_mask + 1 - 32) & ring->ptr_mask;
++ for (j = 0; j <= (count + 32); j++) {
++ seq_printf(m, "r[%5d]=0x%08x", i, ring->ring[i]);
++ if (rptr == i)
++ seq_puts(m, " *");
++ if (rptr_next == i)
++ seq_puts(m, " #");
++ seq_puts(m, "\n");
++ i = (i + 1) & ring->ptr_mask;
+ }
+ return 0;
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0006-yocto-amd-drm-radeon-report-the-real-offset-in-radeon_sa_bo_du.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0006-yocto-amd-drm-radeon-report-the-real-offset-in-radeon_sa_bo_du.patch
new file mode 100644
index 00000000..7ddaa18f
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0006-yocto-amd-drm-radeon-report-the-real-offset-in-radeon_sa_bo_du.patch
@@ -0,0 +1,39 @@
+From cf27c1b111dd09e7f55feb28de6d8f80fd28fd67 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 10 Dec 2013 12:46:23 -0700
+Subject: [PATCH 06/44] drm/radeon: report the real offset in
+ radeon_sa_bo_dump_debug_info
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_sa.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
+index f0bac68..c062580 100644
+--- a/drivers/gpu/drm/radeon/radeon_sa.c
++++ b/drivers/gpu/drm/radeon/radeon_sa.c
+@@ -402,13 +402,15 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
+
+ spin_lock(&sa_manager->wq.lock);
+ list_for_each_entry(i, &sa_manager->olist, olist) {
++ uint64_t soffset = i->soffset + sa_manager->gpu_addr;
++ uint64_t eoffset = i->eoffset + sa_manager->gpu_addr;
+ if (&i->olist == sa_manager->hole) {
+ seq_printf(m, ">");
+ } else {
+ seq_printf(m, " ");
+ }
+- seq_printf(m, "[0x%08x 0x%08x] size %8d",
+- i->soffset, i->eoffset, i->eoffset - i->soffset);
++ seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
++ soffset, eoffset, eoffset - soffset);
+ if (i->fence) {
+ seq_printf(m, " protected by 0x%016llx on ring %d",
+ i->fence->seq, i->fence->ring);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0007-yocto-amd-drm-radeon-update-fence-values-in-before-reporting-t.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0007-yocto-amd-drm-radeon-update-fence-values-in-before-reporting-t.patch
new file mode 100644
index 00000000..ebc32a16
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0007-yocto-amd-drm-radeon-update-fence-values-in-before-reporting-t.patch
@@ -0,0 +1,30 @@
+From c6c27a74ed822d853de89e5d1360b983906e35aa Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 10 Dec 2013 12:48:45 -0700
+Subject: [PATCH 07/44] drm/radeon: update fence values in before reporting
+ them
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_fence.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
+index 8aea16e..51760b7 100644
+--- a/drivers/gpu/drm/radeon/radeon_fence.c
++++ b/drivers/gpu/drm/radeon/radeon_fence.c
+@@ -945,6 +945,8 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
+ if (!rdev->fence_drv[i].initialized)
+ continue;
+
++ radeon_fence_process(rdev, i);
++
+ seq_printf(m, "--- ring %d ---\n", i);
+ seq_printf(m, "Last signaled fence 0x%016llx\n",
+ (unsigned long long)atomic64_read(&rdev->fence_drv[i].last_seq));
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0008-yocto-amd-drm-radeon-cleanup-radeon_ttm-debugfs-handling.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0008-yocto-amd-drm-radeon-cleanup-radeon_ttm-debugfs-handling.patch
new file mode 100644
index 00000000..bb62cdb6
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0008-yocto-amd-drm-radeon-cleanup-radeon_ttm-debugfs-handling.patch
@@ -0,0 +1,109 @@
+From d1ed06d2f21d3e7b407e4b32739472b7210c95ed Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 9 Dec 2013 06:50:21 -0700
+Subject: [PATCH 08/44] drm/radeon: cleanup radeon_ttm debugfs handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise we not necessary export the right information.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_ttm.c | 59 ++++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
+index 71245d6..a2d6c4f 100644
+--- a/drivers/gpu/drm/radeon/radeon_ttm.c
++++ b/drivers/gpu/drm/radeon/radeon_ttm.c
+@@ -832,16 +832,15 @@ int radeon_mmap(struct file *filp, struct vm_area_struct *vma)
+ return 0;
+ }
+
+-
+-#define RADEON_DEBUGFS_MEM_TYPES 2
+-
+ #if defined(CONFIG_DEBUG_FS)
++
+ static int radeon_mm_dump_table(struct seq_file *m, void *data)
+ {
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+- struct drm_mm *mm = (struct drm_mm *)node->info_ent->data;
++ unsigned ttm_pl = *(int *)node->info_ent->data;
+ struct drm_device *dev = node->minor->dev;
+ struct radeon_device *rdev = dev->dev_private;
++ struct drm_mm *mm = (struct drm_mm *)rdev->mman.bdev.man[ttm_pl].priv;
+ int ret;
+ struct ttm_bo_global *glob = rdev->mman.bdev.glob;
+
+@@ -850,46 +849,34 @@ static int radeon_mm_dump_table(struct seq_file *m, void *data)
+ spin_unlock(&glob->lru_lock);
+ return ret;
+ }
++
++static int ttm_pl_vram = TTM_PL_VRAM;
++static int ttm_pl_tt = TTM_PL_TT;
++
++static struct drm_info_list radeon_ttm_debugfs_list[] = {
++ {"radeon_vram_mm", radeon_mm_dump_table, 0, &ttm_pl_vram},
++ {"radeon_gtt_mm", radeon_mm_dump_table, 0, &ttm_pl_tt},
++ {"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL},
++#ifdef CONFIG_SWIOTLB
++ {"ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL}
++#endif
++};
++
+ #endif
+
+ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+ {
+ #if defined(CONFIG_DEBUG_FS)
+- static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES+2];
+- static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES+2][32];
+- unsigned i;
++ unsigned count = ARRAY_SIZE(radeon_ttm_debugfs_list);
+
+- for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
+- if (i == 0)
+- sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
+- else
+- sprintf(radeon_mem_types_names[i], "radeon_gtt_mm");
+- radeon_mem_types_list[i].name = radeon_mem_types_names[i];
+- radeon_mem_types_list[i].show = &radeon_mm_dump_table;
+- radeon_mem_types_list[i].driver_features = 0;
+- if (i == 0)
+- radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_VRAM].priv;
+- else
+- radeon_mem_types_list[i].data = rdev->mman.bdev.man[TTM_PL_TT].priv;
+-
+- }
+- /* Add ttm page pool to debugfs */
+- sprintf(radeon_mem_types_names[i], "ttm_page_pool");
+- radeon_mem_types_list[i].name = radeon_mem_types_names[i];
+- radeon_mem_types_list[i].show = &ttm_page_alloc_debugfs;
+- radeon_mem_types_list[i].driver_features = 0;
+- radeon_mem_types_list[i++].data = NULL;
+ #ifdef CONFIG_SWIOTLB
+- if (swiotlb_nr_tbl()) {
+- sprintf(radeon_mem_types_names[i], "ttm_dma_page_pool");
+- radeon_mem_types_list[i].name = radeon_mem_types_names[i];
+- radeon_mem_types_list[i].show = &ttm_dma_page_alloc_debugfs;
+- radeon_mem_types_list[i].driver_features = 0;
+- radeon_mem_types_list[i++].data = NULL;
+- }
++ if (!swiotlb_nr_tbl())
++ --count;
+ #endif
+- return radeon_debugfs_add_files(rdev, radeon_mem_types_list, i);
+
+-#endif
++ return radeon_debugfs_add_files(rdev, radeon_ttm_debugfs_list, count);
++#else
++
+ return 0;
++#endif
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0009-yocto-amd-drm-radeon-add-VRAM-debugfs-access-v3.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0009-yocto-amd-drm-radeon-add-VRAM-debugfs-access-v3.patch
new file mode 100644
index 00000000..c8788bd6
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0009-yocto-amd-drm-radeon-add-VRAM-debugfs-access-v3.patch
@@ -0,0 +1,168 @@
+From c100632a7a63c7cc03b7c4ad391477c919c61666 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 10 Dec 2013 07:45:24 -0700
+Subject: [PATCH 09/44] drm/radeon: add VRAM debugfs access v3
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Not very fast, but makes it possible to access even the
+normally inaccessible parts of VRAM from userspace.
+
+v2: use MM_INDEX_HI for >2GB mem access, add default_llseek
+v3: set inode size in the open callback
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/evergreen_reg.h | 1 +
+ drivers/gpu/drm/radeon/radeon.h | 4 ++
+ drivers/gpu/drm/radeon/radeon_ttm.c | 77 +++++++++++++++++++++++++++++++-
+ 3 files changed, 81 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h
+index 8a4e641..a0f63ff 100644
+--- a/drivers/gpu/drm/radeon/evergreen_reg.h
++++ b/drivers/gpu/drm/radeon/evergreen_reg.h
+@@ -33,6 +33,7 @@
+ #define EVERGREEN_PIF_PHY0_DATA 0xc
+ #define EVERGREEN_PIF_PHY1_INDEX 0x10
+ #define EVERGREEN_PIF_PHY1_DATA 0x14
++#define EVERGREEN_MM_INDEX_HI 0x18
+
+ #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS 0x310
+ #define EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH 0x324
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index c0d4230..14df551 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -413,6 +413,10 @@ struct radeon_mman {
+ struct ttm_bo_device bdev;
+ bool mem_global_referenced;
+ bool initialized;
++
++#if defined(CONFIG_DEBUG_FS)
++ struct dentry *vram;
++#endif
+ };
+
+ /* bo virtual address in a specific vm */
+diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
+index a2d6c4f..83ef24d 100644
+--- a/drivers/gpu/drm/radeon/radeon_ttm.c
++++ b/drivers/gpu/drm/radeon/radeon_ttm.c
+@@ -39,12 +39,14 @@
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/swiotlb.h>
++#include <linux/debugfs.h>
+ #include "radeon_reg.h"
+ #include "radeon.h"
+
+ #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+ static int radeon_ttm_debugfs_init(struct radeon_device *rdev);
++static void radeon_ttm_debugfs_fini(struct radeon_device *rdev);
+
+ static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev)
+ {
+@@ -753,6 +755,7 @@ void radeon_ttm_fini(struct radeon_device *rdev)
+
+ if (!rdev->mman.initialized)
+ return;
++ radeon_ttm_debugfs_fini(rdev);
+ if (rdev->stollen_vga_memory) {
+ r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
+ if (r == 0) {
+@@ -862,12 +865,75 @@ static struct drm_info_list radeon_ttm_debugfs_list[] = {
+ #endif
+ };
+
++static int radeon_ttm_vram_open(struct inode *inode, struct file *filep)
++{
++ struct radeon_device *rdev = inode->i_private;
++ i_size_write(inode, rdev->mc.mc_vram_size);
++ filep->private_data = inode->i_private;
++ return 0;
++}
++
++static ssize_t radeon_ttm_vram_read(struct file *f, char __user *buf,
++ size_t size, loff_t *pos)
++{
++ struct radeon_device *rdev = f->private_data;
++ ssize_t result = 0;
++ int r;
++
++ if (size & 0x3 || *pos & 0x3)
++ return -EINVAL;
++
++ while (size) {
++ unsigned long flags;
++ uint32_t value;
++
++ if (*pos >= rdev->mc.mc_vram_size)
++ return result;
++
++ spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
++ WREG32(RADEON_MM_INDEX, ((uint32_t)*pos) | 0x80000000);
++ if (rdev->family >= CHIP_CEDAR)
++ WREG32(EVERGREEN_MM_INDEX_HI, *pos >> 31);
++ value = RREG32(RADEON_MM_DATA);
++ spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
++
++ r = put_user(value, (uint32_t *)buf);
++ if (r)
++ return r;
++
++ result += 4;
++ buf += 4;
++ *pos += 4;
++ size -= 4;
++ }
++
++ return result;
++}
++
++static const struct file_operations radeon_ttm_vram_fops = {
++ .owner = THIS_MODULE,
++ .open = radeon_ttm_vram_open,
++ .read = radeon_ttm_vram_read,
++ .llseek = default_llseek
++};
++
+ #endif
+
+ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+ {
+ #if defined(CONFIG_DEBUG_FS)
+- unsigned count = ARRAY_SIZE(radeon_ttm_debugfs_list);
++ unsigned count;
++
++ struct drm_minor *minor = rdev->ddev->primary;
++ struct dentry *ent, *root = minor->debugfs_root;
++
++ ent = debugfs_create_file("radeon_vram", S_IFREG | S_IRUGO, root,
++ rdev, &radeon_ttm_vram_fops);
++ if (IS_ERR(ent))
++ return PTR_ERR(ent);
++ rdev->mman.vram = ent;
++
++ count = ARRAY_SIZE(radeon_ttm_debugfs_list);
+
+ #ifdef CONFIG_SWIOTLB
+ if (!swiotlb_nr_tbl())
+@@ -880,3 +946,12 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+ return 0;
+ #endif
+ }
++
++static void radeon_ttm_debugfs_fini(struct radeon_device *rdev)
++{
++#if defined(CONFIG_DEBUG_FS)
++
++ debugfs_remove(rdev->mman.vram);
++ rdev->mman.vram = NULL;
++#endif
++}
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0010-yocto-amd-drm-radeon-add-GART-debugfs-access-v3.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0010-yocto-amd-drm-radeon-add-GART-debugfs-access-v3.patch
new file mode 100644
index 00000000..5cabdf25
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0010-yocto-amd-drm-radeon-add-GART-debugfs-access-v3.patch
@@ -0,0 +1,119 @@
+From ee6e4aae828077d7503a2baf5acb54df222fa922 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Wed, 11 Dec 2013 06:13:22 -0700
+Subject: [PATCH 10/44] drm/radeon: add GART debugfs access v3
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+v2: add default_llseek
+v3: set inode size in the open callback
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 1 +
+ drivers/gpu/drm/radeon/radeon_ttm.c | 63 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 64 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 14df551..7a483c9 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -416,6 +416,7 @@ struct radeon_mman {
+
+ #if defined(CONFIG_DEBUG_FS)
+ struct dentry *vram;
++ struct dentry *gtt;
+ #endif
+ };
+
+diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
+index 83ef24d..381782d 100644
+--- a/drivers/gpu/drm/radeon/radeon_ttm.c
++++ b/drivers/gpu/drm/radeon/radeon_ttm.c
+@@ -917,6 +917,60 @@ static const struct file_operations radeon_ttm_vram_fops = {
+ .llseek = default_llseek
+ };
+
++static int radeon_ttm_gtt_open(struct inode *inode, struct file *filep)
++{
++ struct radeon_device *rdev = inode->i_private;
++ i_size_write(inode, rdev->mc.gtt_size);
++ filep->private_data = inode->i_private;
++ return 0;
++}
++
++static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf,
++ size_t size, loff_t *pos)
++{
++ struct radeon_device *rdev = f->private_data;
++ ssize_t result = 0;
++ int r;
++
++ while (size) {
++ loff_t p = *pos / PAGE_SIZE;
++ unsigned off = *pos & ~PAGE_MASK;
++ ssize_t cur_size = min(size, PAGE_SIZE - off);
++ struct page *page;
++ void *ptr;
++
++ if (p >= rdev->gart.num_cpu_pages)
++ return result;
++
++ page = rdev->gart.pages[p];
++ if (page) {
++ ptr = kmap(page);
++ ptr += off;
++
++ r = copy_to_user(buf, ptr, cur_size);
++ kunmap(rdev->gart.pages[p]);
++ } else
++ r = clear_user(buf, cur_size);
++
++ if (r)
++ return -EFAULT;
++
++ result += cur_size;
++ buf += cur_size;
++ *pos += cur_size;
++ size -= cur_size;
++ }
++
++ return result;
++}
++
++static const struct file_operations radeon_ttm_gtt_fops = {
++ .owner = THIS_MODULE,
++ .open = radeon_ttm_gtt_open,
++ .read = radeon_ttm_gtt_read,
++ .llseek = default_llseek
++};
++
+ #endif
+
+ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+@@ -933,6 +987,12 @@ static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
+ return PTR_ERR(ent);
+ rdev->mman.vram = ent;
+
++ ent = debugfs_create_file("radeon_gtt", S_IFREG | S_IRUGO, root,
++ rdev, &radeon_ttm_gtt_fops);
++ if (IS_ERR(ent))
++ return PTR_ERR(ent);
++ rdev->mman.gtt = ent;
++
+ count = ARRAY_SIZE(radeon_ttm_debugfs_list);
+
+ #ifdef CONFIG_SWIOTLB
+@@ -953,5 +1013,8 @@ static void radeon_ttm_debugfs_fini(struct radeon_device *rdev)
+
+ debugfs_remove(rdev->mman.vram);
+ rdev->mman.vram = NULL;
++
++ debugfs_remove(rdev->mman.gtt);
++ rdev->mman.gtt = NULL;
+ #endif
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0011-yocto-amd-drm-radeon-fix-VMID-use-tracking.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0011-yocto-amd-drm-radeon-fix-VMID-use-tracking.patch
new file mode 100644
index 00000000..40486c39
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0011-yocto-amd-drm-radeon-fix-VMID-use-tracking.patch
@@ -0,0 +1,71 @@
+From cdf069ae98745bb458f38ec7267fe80a544ddee1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Sat, 14 Dec 2013 10:02:57 -0700
+Subject: [PATCH 11/44] drm/radeon: fix VMID use tracking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise we allocate a new VMID on nearly every submit.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 2 ++
+ drivers/gpu/drm/radeon/radeon_gart.c | 8 +++++++-
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 7a483c9..a21b1d4 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -857,6 +857,8 @@ struct radeon_vm {
+ struct radeon_fence *fence;
+ /* last flush or NULL if we still need to flush */
+ struct radeon_fence *last_flush;
++ /* last use of vmid */
++ struct radeon_fence *last_id_use;
+ };
+
+ struct radeon_vm_manager {
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index f8d7b16..cdab083 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -688,7 +688,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
+ unsigned i;
+
+ /* check if the id is still valid */
+- if (vm->fence && vm->fence == rdev->vm_manager.active[vm->id])
++ if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id])
+ return NULL;
+
+ /* we definately need to flush */
+@@ -743,6 +743,9 @@ void radeon_vm_fence(struct radeon_device *rdev,
+
+ radeon_fence_unref(&vm->fence);
+ vm->fence = radeon_fence_ref(fence);
++
++ radeon_fence_unref(&vm->last_id_use);
++ vm->last_id_use = radeon_fence_ref(fence);
+ }
+
+ /**
+@@ -1246,6 +1249,8 @@ void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
+ {
+ vm->id = 0;
+ vm->fence = NULL;
++ vm->last_flush = NULL;
++ vm->last_id_use = NULL;
+ mutex_init(&vm->mutex);
+ INIT_LIST_HEAD(&vm->list);
+ INIT_LIST_HEAD(&vm->va);
+@@ -1284,5 +1289,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
+ }
+ radeon_fence_unref(&vm->fence);
+ radeon_fence_unref(&vm->last_flush);
++ radeon_fence_unref(&vm->last_id_use);
+ mutex_unlock(&vm->mutex);
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0012-yocto-amd-drm-radeon-add-missing-trace-point.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0012-yocto-amd-drm-radeon-add-missing-trace-point.patch
new file mode 100644
index 00000000..f6f82bba
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0012-yocto-amd-drm-radeon-add-missing-trace-point.patch
@@ -0,0 +1,28 @@
+From 6674c82f2a3cb9da12768e3670a814e84f9e54cc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Sat, 14 Dec 2013 04:11:08 -0700
+Subject: [PATCH 12/44] drm/radeon: add missing trace point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_gart.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index cdab083..d1077f6 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -701,6 +701,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
+ if (fence == NULL) {
+ /* found a free one */
+ vm->id = i;
++ trace_radeon_vm_grab_id(vm->id, ring);
+ return NULL;
+ }
+
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0013-yocto-amd-drm-radeon-add-semaphore-trace-point.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0013-yocto-amd-drm-radeon-add-semaphore-trace-point.patch
new file mode 100644
index 00000000..b63f8c9a
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0013-yocto-amd-drm-radeon-add-semaphore-trace-point.patch
@@ -0,0 +1,95 @@
+From e5798e4519e07f3f0c6077a6f5dd2e9223d01f85 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Thu, 7 Nov 2013 05:32:33 -0700
+Subject: [PATCH 13/44] drm/radeon: add semaphore trace point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_semaphore.c | 6 ++++-
+ drivers/gpu/drm/radeon/radeon_trace.h | 36 +++++++++++++++++++++++++++++
+ 2 files changed, 41 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
+index 34ea889..2b42aa1 100644
+--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
++++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
+@@ -29,7 +29,7 @@
+ */
+ #include <drm/drmP.h>
+ #include "radeon.h"
+-
++#include "radeon_trace.h"
+
+ int radeon_semaphore_create(struct radeon_device *rdev,
+ struct radeon_semaphore **semaphore)
+@@ -62,6 +62,8 @@ bool radeon_semaphore_emit_signal(struct radeon_device *rdev, int ridx,
+ {
+ struct radeon_ring *ring = &rdev->ring[ridx];
+
++ trace_radeon_semaphore_signale(ridx, semaphore);
++
+ if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, false)) {
+ --semaphore->waiters;
+
+@@ -77,6 +79,8 @@ bool radeon_semaphore_emit_wait(struct radeon_device *rdev, int ridx,
+ {
+ struct radeon_ring *ring = &rdev->ring[ridx];
+
++ trace_radeon_semaphore_wait(ridx, semaphore);
++
+ if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, true)) {
+ ++semaphore->waiters;
+
+diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
+index 811bca6..9f0e181 100644
+--- a/drivers/gpu/drm/radeon/radeon_trace.h
++++ b/drivers/gpu/drm/radeon/radeon_trace.h
+@@ -111,6 +111,42 @@ DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end,
+ TP_ARGS(dev, seqno)
+ );
+
++DECLARE_EVENT_CLASS(radeon_semaphore_request,
++
++ TP_PROTO(int ring, struct radeon_semaphore *sem),
++
++ TP_ARGS(ring, sem),
++
++ TP_STRUCT__entry(
++ __field(int, ring)
++ __field(signed, waiters)
++ __field(uint64_t, gpu_addr)
++ ),
++
++ TP_fast_assign(
++ __entry->ring = ring;
++ __entry->waiters = sem->waiters;
++ __entry->gpu_addr = sem->gpu_addr;
++ ),
++
++ TP_printk("ring=%u, waiters=%d, addr=%010Lx", __entry->ring,
++ __entry->waiters, __entry->gpu_addr)
++);
++
++DEFINE_EVENT(radeon_semaphore_request, radeon_semaphore_signale,
++
++ TP_PROTO(int ring, struct radeon_semaphore *sem),
++
++ TP_ARGS(ring, sem)
++);
++
++DEFINE_EVENT(radeon_semaphore_request, radeon_semaphore_wait,
++
++ TP_PROTO(int ring, struct radeon_semaphore *sem),
++
++ TP_ARGS(ring, sem)
++);
++
+ #endif
+
+ /* This part must be outside protection */
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0014-yocto-amd-drm-radeon-add-VMID-allocation-trace-point.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0014-yocto-amd-drm-radeon-add-VMID-allocation-trace-point.patch
new file mode 100644
index 00000000..4e230031
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0014-yocto-amd-drm-radeon-add-VMID-allocation-trace-point.patch
@@ -0,0 +1,64 @@
+From 0a4a2069686234528f3e2c876a97bdd499062c2c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 25 Nov 2013 15:42:10 +0100
+Subject: [PATCH 14/44] drm/radeon: add VMID allocation trace point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_gart.c | 2 ++
+ drivers/gpu/drm/radeon/radeon_trace.h | 15 +++++++++++++++
+ 2 files changed, 17 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index d1077f6..f7c0b64 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -29,6 +29,7 @@
+ #include <drm/radeon_drm.h>
+ #include "radeon.h"
+ #include "radeon_reg.h"
++#include "radeon_trace.h"
+
+ /*
+ * GART
+@@ -714,6 +715,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
+ for (i = 0; i < 2; ++i) {
+ if (choices[i]) {
+ vm->id = choices[i];
++ trace_radeon_vm_grab_id(vm->id, ring);
+ return rdev->vm_manager.active[choices[i]];
+ }
+ }
+diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
+index 9f0e181..8c13aec 100644
+--- a/drivers/gpu/drm/radeon/radeon_trace.h
++++ b/drivers/gpu/drm/radeon/radeon_trace.h
+@@ -47,6 +47,21 @@ TRACE_EVENT(radeon_cs,
+ __entry->fences)
+ );
+
++TRACE_EVENT(radeon_vm_grab_id,
++ TP_PROTO(unsigned vmid, int ring),
++ TP_ARGS(vmid, ring),
++ TP_STRUCT__entry(
++ __field(u32, vmid)
++ __field(u32, ring)
++ ),
++
++ TP_fast_assign(
++ __entry->vmid = vmid;
++ __entry->ring = ring;
++ ),
++ TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring)
++);
++
+ TRACE_EVENT(radeon_vm_set_page,
+ TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags),
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0015-yocto-amd-drm-radeon-add-uvd-debugfs-support.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0015-yocto-amd-drm-radeon-add-uvd-debugfs-support.patch
new file mode 100644
index 00000000..fd312353
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0015-yocto-amd-drm-radeon-add-uvd-debugfs-support.patch
@@ -0,0 +1,99 @@
+From 627d32e67d83a65294cb9da1e7ef796009b0e5d8 Mon Sep 17 00:00:00 2001
+From: Leo Liu <leo.liu@amd.com>
+Date: Mon, 25 Nov 2013 17:25:41 -0500
+Subject: [PATCH 15/44] drm/radeon: add uvd debugfs support
+
+Signed-off-by: Leo Liu <leo.liu@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 1 +
+ drivers/gpu/drm/radeon/radeon_uvd.c | 37 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index a21b1d4..b212569 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1549,6 +1549,7 @@ struct radeon_uvd {
+ struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
+ unsigned img_size[RADEON_MAX_UVD_HANDLES];
+ struct delayed_work idle_work;
++ bool status;
+ };
+
+ int radeon_uvd_init(struct radeon_device *rdev);
+diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
+index 1d029cc..2b502b4 100644
+--- a/drivers/gpu/drm/radeon/radeon_uvd.c
++++ b/drivers/gpu/drm/radeon/radeon_uvd.c
+@@ -53,6 +53,7 @@ MODULE_FIRMWARE(FIRMWARE_TAHITI);
+ MODULE_FIRMWARE(FIRMWARE_BONAIRE);
+
+ static void radeon_uvd_idle_work_handler(struct work_struct *work);
++static int radeon_debugfs_uvd_init(struct radeon_device *rdev);
+
+ int radeon_uvd_init(struct radeon_device *rdev)
+ {
+@@ -142,6 +143,10 @@ int radeon_uvd_init(struct radeon_device *rdev)
+ return r;
+ }
+
++ r = radeon_debugfs_uvd_init(rdev);
++ if (r)
++ dev_err(rdev->dev, "(%d) Register debugfs file for uvd failed\n", r);
++
+ radeon_bo_unreserve(rdev->uvd.vcpu_bo);
+
+ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+@@ -785,6 +790,7 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
+ schedule_delayed_work(&rdev->uvd.idle_work,
+ msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
+ }
++ rdev->uvd.status = false;
+ }
+
+ void radeon_uvd_note_usage(struct radeon_device *rdev)
+@@ -812,6 +818,7 @@ void radeon_uvd_note_usage(struct radeon_device *rdev)
+ } else {
+ radeon_set_uvd_clocks(rdev, 53300, 40000);
+ }
++ rdev->uvd.status = true;
+ }
+ }
+
+@@ -951,3 +958,33 @@ int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
+
+ return 0;
+ }
++
++/*
++ * Debugfs info
++ */
++#if defined(CONFIG_DEBUG_FS)
++
++static int radeon_debugfs_uvd_info(struct seq_file *m, void *data)
++{
++ struct drm_info_node *node = (struct drm_info_node *) m->private;
++ struct drm_device *dev = node->minor->dev;
++ struct radeon_device *rdev = dev->dev_private;
++
++ seq_printf(m, "UVD Status: %s\n", ((rdev->uvd.status) ? "Busy" : "Idle"));
++
++ return 0;
++}
++
++static struct drm_info_list radeon_uvd_info_list[] = {
++ {"radeon_uvd_info", radeon_debugfs_uvd_info, 0, NULL},
++};
++#endif
++
++static int radeon_debugfs_uvd_init(struct radeon_device *rdev)
++{
++#if defined(CONFIG_DEBUG_FS)
++ return radeon_debugfs_add_files(rdev, radeon_uvd_info_list, ARRAY_SIZE(radeon_uvd_info_list));
++#else
++ return 0;
++#endif
++}
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0016-yocto-amd-drm-radeon-add-radeon_vm_bo_update-trace-point.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0016-yocto-amd-drm-radeon-add-radeon_vm_bo_update-trace-point.patch
new file mode 100644
index 00000000..190b7b16
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0016-yocto-amd-drm-radeon-add-radeon_vm_bo_update-trace-point.patch
@@ -0,0 +1,138 @@
+From b72be939a9ff7a33b0aa3ff3bd196ea016b8dce1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 25 Nov 2013 15:42:11 +0100
+Subject: [PATCH 16/44] drm/radeon: add radeon_vm_bo_update trace point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Also rename the function to better reflect what it is doing.
+
+agd5f: fix argument size warning
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 8 ++++----
+ drivers/gpu/drm/radeon/radeon_cs.c | 4 ++--
+ drivers/gpu/drm/radeon/radeon_gart.c | 14 ++++++++------
+ drivers/gpu/drm/radeon/radeon_trace.h | 18 ++++++++++++++++++
+ 4 files changed, 32 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index b212569..37e619c 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -2705,10 +2705,10 @@ void radeon_vm_fence(struct radeon_device *rdev,
+ struct radeon_vm *vm,
+ struct radeon_fence *fence);
+ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr);
+-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
+- struct radeon_vm *vm,
+- struct radeon_bo *bo,
+- struct ttm_mem_reg *mem);
++int radeon_vm_bo_update(struct radeon_device *rdev,
++ struct radeon_vm *vm,
++ struct radeon_bo *bo,
++ struct ttm_mem_reg *mem);
+ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
+ struct radeon_bo *bo);
+ struct radeon_bo_va *radeon_vm_bo_find(struct radeon_vm *vm,
+diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
+index eb5cd94..83731ff 100644
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -407,13 +407,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser,
+ struct radeon_bo *bo;
+ int r;
+
+- r = radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
++ r = radeon_vm_bo_update(rdev, vm, rdev->ring_tmp_bo.bo, &rdev->ring_tmp_bo.bo->tbo.mem);
+ if (r) {
+ return r;
+ }
+ list_for_each_entry(lobj, &parser->validated, tv.head) {
+ bo = lobj->bo;
+- r = radeon_vm_bo_update_pte(parser->rdev, vm, bo, &bo->tbo.mem);
++ r = radeon_vm_bo_update(parser->rdev, vm, bo, &bo->tbo.mem);
+ if (r) {
+ return r;
+ }
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index f7c0b64..33bd02e 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -1071,7 +1071,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
+ }
+
+ /**
+- * radeon_vm_bo_update_pte - map a bo into the vm page table
++ * radeon_vm_bo_update - map a bo into the vm page table
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+@@ -1083,10 +1083,10 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
+ *
+ * Object have to be reserved & global and local mutex must be locked!
+ */
+-int radeon_vm_bo_update_pte(struct radeon_device *rdev,
+- struct radeon_vm *vm,
+- struct radeon_bo *bo,
+- struct ttm_mem_reg *mem)
++int radeon_vm_bo_update(struct radeon_device *rdev,
++ struct radeon_vm *vm,
++ struct radeon_bo *bo,
++ struct ttm_mem_reg *mem)
+ {
+ unsigned ridx = rdev->asic->vm.pt_ring_index;
+ struct radeon_ib ib;
+@@ -1132,6 +1132,8 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
+ bo_va->valid = false;
+ }
+
++ trace_radeon_vm_bo_update(bo_va);
++
+ nptes = radeon_bo_ngpu_pages(bo);
+
+ /* assume two extra pdes in case the mapping overlaps the borders */
+@@ -1210,7 +1212,7 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,
+ mutex_lock(&rdev->vm_manager.lock);
+ mutex_lock(&bo_va->vm->mutex);
+ if (bo_va->soffset) {
+- r = radeon_vm_bo_update_pte(rdev, bo_va->vm, bo_va->bo, NULL);
++ r = radeon_vm_bo_update(rdev, bo_va->vm, bo_va->bo, NULL);
+ }
+ mutex_unlock(&rdev->vm_manager.lock);
+ list_del(&bo_va->vm_list);
+diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
+index 8c13aec..0473257 100644
+--- a/drivers/gpu/drm/radeon/radeon_trace.h
++++ b/drivers/gpu/drm/radeon/radeon_trace.h
+@@ -62,6 +62,24 @@ TRACE_EVENT(radeon_vm_grab_id,
+ TP_printk("vmid=%u, ring=%u", __entry->vmid, __entry->ring)
+ );
+
++TRACE_EVENT(radeon_vm_bo_update,
++ TP_PROTO(struct radeon_bo_va *bo_va),
++ TP_ARGS(bo_va),
++ TP_STRUCT__entry(
++ __field(u64, soffset)
++ __field(u64, eoffset)
++ __field(u32, flags)
++ ),
++
++ TP_fast_assign(
++ __entry->soffset = bo_va->soffset;
++ __entry->eoffset = bo_va->eoffset;
++ __entry->flags = bo_va->flags;
++ ),
++ TP_printk("soffs=%010llx, eoffs=%010llx, flags=%08x",
++ __entry->soffset, __entry->eoffset, __entry->flags)
++);
++
+ TRACE_EVENT(radeon_vm_set_page,
+ TP_PROTO(uint64_t pe, uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags),
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0017-yocto-amd-drm-radeon-drop-CP-page-table-updates-cleanup-v2.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0017-yocto-amd-drm-radeon-drop-CP-page-table-updates-cleanup-v2.patch
new file mode 100644
index 00000000..0f88bc76
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0017-yocto-amd-drm-radeon-drop-CP-page-table-updates-cleanup-v2.patch
@@ -0,0 +1,676 @@
+From 6a98674d6cb42c43b6a5e9dd2719b52a50b9e489 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Wed, 30 Oct 2013 11:51:09 -0400
+Subject: [PATCH 17/44] drm/radeon: drop CP page table updates & cleanup v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The DMA ring seems to be stable now.
+
+v2: remove pt_ring_index as well
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 56 -------------------------
+ drivers/gpu/drm/radeon/cik_sdma.c | 21 ++++------
+ drivers/gpu/drm/radeon/ni.c | 76 ----------------------------------
+ drivers/gpu/drm/radeon/ni_dma.c | 18 ++++----
+ drivers/gpu/drm/radeon/radeon.h | 8 +++-
+ drivers/gpu/drm/radeon/radeon_asic.c | 15 +++----
+ drivers/gpu/drm/radeon/radeon_asic.h | 31 +++++++-------
+ drivers/gpu/drm/radeon/radeon_gart.c | 29 ++++++++++---
+ drivers/gpu/drm/radeon/si.c | 60 ---------------------------
+ drivers/gpu/drm/radeon/si_dma.c | 21 ++++------
+ 10 files changed, 73 insertions(+), 262 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 0608446..d7e86ef3 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -4825,62 +4825,6 @@ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
+ }
+ }
+
+-/**
+- * cik_vm_set_page - update the page tables using sDMA
+- *
+- * @rdev: radeon_device pointer
+- * @ib: indirect buffer to fill with commands
+- * @pe: addr of the page entry
+- * @addr: dst addr to write into pe
+- * @count: number of page entries to update
+- * @incr: increase next addr by incr bytes
+- * @flags: access flags
+- *
+- * Update the page tables using CP or sDMA (CIK).
+- */
+-void cik_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags)
+-{
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+- uint64_t value;
+- unsigned ndw;
+-
+- if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) {
+- /* CP */
+- while (count) {
+- ndw = 2 + count * 2;
+- if (ndw > 0x3FFE)
+- ndw = 0x3FFE;
+-
+- ib->ptr[ib->length_dw++] = PACKET3(PACKET3_WRITE_DATA, ndw);
+- ib->ptr[ib->length_dw++] = (WRITE_DATA_ENGINE_SEL(0) |
+- WRITE_DATA_DST_SEL(1));
+- ib->ptr[ib->length_dw++] = pe;
+- ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+- for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- value = radeon_vm_map_gart(rdev, addr);
+- value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
+- value = addr;
+- } else {
+- value = 0;
+- }
+- addr += incr;
+- value |= r600_flags;
+- ib->ptr[ib->length_dw++] = value;
+- ib->ptr[ib->length_dw++] = upper_32_bits(value);
+- }
+- }
+- } else {
+- /* DMA */
+- cik_sdma_vm_set_page(rdev, ib, pe, addr, count, incr, flags);
+- }
+-}
+-
+ /*
+ * RLC
+ * The RLC is a multi-purpose microengine that handles a
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index ace0bc6..8517a62 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -646,13 +646,12 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+ {
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+ uint64_t value;
+ unsigned ndw;
+
+- trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++ trace_radeon_vm_set_page(pe, addr, count, incr, flags);
+
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
++ if (flags & R600_PTE_SYSTEM) {
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+@@ -664,16 +663,10 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+ ib->ptr[ib->length_dw++] = ndw;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- value = radeon_vm_map_gart(rdev, addr);
+- value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
+- value = addr;
+- } else {
+- value = 0;
+- }
++ value = radeon_vm_map_gart(rdev, addr);
++ value &= 0xFFFFFFFFFFFFF000ULL;
+ addr += incr;
+- value |= r600_flags;
++ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ }
+@@ -684,7 +677,7 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ if (ndw > 0x7FFFF)
+ ndw = 0x7FFFF;
+
+- if (flags & RADEON_VM_PAGE_VALID)
++ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+@@ -692,7 +685,7 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_GENERATE_PTE_PDE, 0, 0);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+- ib->ptr[ib->length_dw++] = r600_flags; /* mask */
++ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index 954eb9a..f59a9e9 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -174,11 +174,6 @@ extern void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
+ extern void evergreen_program_aspm(struct radeon_device *rdev);
+ extern void sumo_rlc_fini(struct radeon_device *rdev);
+ extern int sumo_rlc_init(struct radeon_device *rdev);
+-extern void cayman_dma_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags);
+
+ /* Firmware Names */
+ MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
+@@ -2412,77 +2407,6 @@ void cayman_vm_decode_fault(struct radeon_device *rdev,
+ block, mc_id);
+ }
+
+-#define R600_ENTRY_VALID (1 << 0)
+-#define R600_PTE_SYSTEM (1 << 1)
+-#define R600_PTE_SNOOPED (1 << 2)
+-#define R600_PTE_READABLE (1 << 5)
+-#define R600_PTE_WRITEABLE (1 << 6)
+-
+-uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags)
+-{
+- uint32_t r600_flags = 0;
+- r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_ENTRY_VALID : 0;
+- r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0;
+- r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0;
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- r600_flags |= R600_PTE_SYSTEM;
+- r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0;
+- }
+- return r600_flags;
+-}
+-
+-/**
+- * cayman_vm_set_page - update the page tables using the CP
+- *
+- * @rdev: radeon_device pointer
+- * @ib: indirect buffer to fill with commands
+- * @pe: addr of the page entry
+- * @addr: dst addr to write into pe
+- * @count: number of page entries to update
+- * @incr: increase next addr by incr bytes
+- * @flags: access flags
+- *
+- * Update the page tables using the CP (cayman/TN).
+- */
+-void cayman_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags)
+-{
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+- uint64_t value;
+- unsigned ndw;
+-
+- if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) {
+- while (count) {
+- ndw = 1 + count * 2;
+- if (ndw > 0x3FFF)
+- ndw = 0x3FFF;
+-
+- ib->ptr[ib->length_dw++] = PACKET3(PACKET3_ME_WRITE, ndw);
+- ib->ptr[ib->length_dw++] = pe;
+- ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+- for (; ndw > 1; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- value = radeon_vm_map_gart(rdev, addr);
+- value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
+- value = addr;
+- } else {
+- value = 0;
+- }
+- addr += incr;
+- value |= r600_flags;
+- ib->ptr[ib->length_dw++] = value;
+- ib->ptr[ib->length_dw++] = upper_32_bits(value);
+- }
+- }
+- } else {
+- cayman_dma_vm_set_page(rdev, ib, pe, addr, count, incr, flags);
+- }
+-}
+-
+ /**
+ * cayman_vm_flush - vm flush using the CP
+ *
+diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
+index e9cfe8a..bdeb65e 100644
+--- a/drivers/gpu/drm/radeon/ni_dma.c
++++ b/drivers/gpu/drm/radeon/ni_dma.c
+@@ -246,8 +246,7 @@ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
+ * @addr: dst addr to write into pe
+ * @count: number of page entries to update
+ * @incr: increase next addr by incr bytes
+- * @flags: access flags
+- * @r600_flags: hw access flags
++ * @flags: hw access flags
+ *
+ * Update the page tables using the DMA (cayman/TN).
+ */
+@@ -257,13 +256,12 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+ {
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+ uint64_t value;
+ unsigned ndw;
+
+- trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++ trace_radeon_vm_set_page(pe, addr, count, incr, flags);
+
+- if ((flags & RADEON_VM_PAGE_SYSTEM) || (count == 1)) {
++ if ((flags & R600_PTE_SYSTEM) || (count == 1)) {
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+@@ -274,16 +272,16 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = pe;
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
++ if (flags & R600_PTE_SYSTEM) {
+ value = radeon_vm_map_gart(rdev, addr);
+ value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
++ } else if (flags & R600_PTE_VALID) {
+ value = addr;
+ } else {
+ value = 0;
+ }
+ addr += incr;
+- value |= r600_flags;
++ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ }
+@@ -294,7 +292,7 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+- if (flags & RADEON_VM_PAGE_VALID)
++ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+@@ -302,7 +300,7 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+- ib->ptr[ib->length_dw++] = r600_flags; /* mask */
++ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 37e619c..b987f01 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -840,6 +840,12 @@ struct radeon_mec {
+ #define RADEON_VM_PTB_ALIGN_MASK (RADEON_VM_PTB_ALIGN_SIZE - 1)
+ #define RADEON_VM_PTB_ALIGN(a) (((a) + RADEON_VM_PTB_ALIGN_MASK) & ~RADEON_VM_PTB_ALIGN_MASK)
+
++#define R600_PTE_VALID (1 << 0)
++#define R600_PTE_SYSTEM (1 << 1)
++#define R600_PTE_SNOOPED (1 << 2)
++#define R600_PTE_READABLE (1 << 5)
++#define R600_PTE_WRITEABLE (1 << 6)
++
+ struct radeon_vm {
+ struct list_head list;
+ struct list_head va;
+@@ -1685,8 +1691,6 @@ struct radeon_asic {
+ struct {
+ int (*init)(struct radeon_device *rdev);
+ void (*fini)(struct radeon_device *rdev);
+-
+- u32 pt_ring_index;
+ void (*set_page)(struct radeon_device *rdev,
+ struct radeon_ib *ib,
+ uint64_t pe,
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
+index 5720e66..123adfe 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.c
++++ b/drivers/gpu/drm/radeon/radeon_asic.c
+@@ -1622,8 +1622,7 @@ static struct radeon_asic cayman_asic = {
+ .vm = {
+ .init = &cayman_vm_init,
+ .fini = &cayman_vm_fini,
+- .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+- .set_page = &cayman_vm_set_page,
++ .set_page = &cayman_dma_vm_set_page,
+ },
+ .ring = {
+ [RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
+@@ -1723,8 +1722,7 @@ static struct radeon_asic trinity_asic = {
+ .vm = {
+ .init = &cayman_vm_init,
+ .fini = &cayman_vm_fini,
+- .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+- .set_page = &cayman_vm_set_page,
++ .set_page = &cayman_dma_vm_set_page,
+ },
+ .ring = {
+ [RADEON_RING_TYPE_GFX_INDEX] = &cayman_gfx_ring,
+@@ -1854,8 +1852,7 @@ static struct radeon_asic si_asic = {
+ .vm = {
+ .init = &si_vm_init,
+ .fini = &si_vm_fini,
+- .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+- .set_page = &si_vm_set_page,
++ .set_page = &si_dma_vm_set_page,
+ },
+ .ring = {
+ [RADEON_RING_TYPE_GFX_INDEX] = &si_gfx_ring,
+@@ -2000,8 +1997,7 @@ static struct radeon_asic ci_asic = {
+ .vm = {
+ .init = &cik_vm_init,
+ .fini = &cik_vm_fini,
+- .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+- .set_page = &cik_vm_set_page,
++ .set_page = &cik_sdma_vm_set_page,
+ },
+ .ring = {
+ [RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
+@@ -2102,8 +2098,7 @@ static struct radeon_asic kv_asic = {
+ .vm = {
+ .init = &cik_vm_init,
+ .fini = &cik_vm_fini,
+- .pt_ring_index = R600_RING_TYPE_DMA_INDEX,
+- .set_page = &cik_vm_set_page,
++ .set_page = &cik_sdma_vm_set_page,
+ },
+ .ring = {
+ [RADEON_RING_TYPE_GFX_INDEX] = &ci_gfx_ring,
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
+index 8588670..8939cb3 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.h
++++ b/drivers/gpu/drm/radeon/radeon_asic.h
+@@ -577,17 +577,18 @@ int cayman_vm_init(struct radeon_device *rdev);
+ void cayman_vm_fini(struct radeon_device *rdev);
+ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+ uint32_t cayman_vm_page_flags(struct radeon_device *rdev, uint32_t flags);
+-void cayman_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags);
+ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+ int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+ void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
+ struct radeon_ib *ib);
+ bool cayman_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
+ bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
++void cayman_dma_vm_set_page(struct radeon_device *rdev,
++ struct radeon_ib *ib,
++ uint64_t pe,
++ uint64_t addr, unsigned count,
++ uint32_t incr, uint32_t flags);
++
+ void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+
+ int ni_dpm_init(struct radeon_device *rdev);
+@@ -649,17 +650,17 @@ int si_irq_set(struct radeon_device *rdev);
+ int si_irq_process(struct radeon_device *rdev);
+ int si_vm_init(struct radeon_device *rdev);
+ void si_vm_fini(struct radeon_device *rdev);
+-void si_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags);
+ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+ int si_copy_dma(struct radeon_device *rdev,
+ uint64_t src_offset, uint64_t dst_offset,
+ unsigned num_gpu_pages,
+ struct radeon_fence **fence);
++void si_dma_vm_set_page(struct radeon_device *rdev,
++ struct radeon_ib *ib,
++ uint64_t pe,
++ uint64_t addr, unsigned count,
++ uint32_t incr, uint32_t flags);
+ void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+ u32 si_get_xclk(struct radeon_device *rdev);
+ uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev);
+@@ -727,11 +728,11 @@ int cik_irq_process(struct radeon_device *rdev);
+ int cik_vm_init(struct radeon_device *rdev);
+ void cik_vm_fini(struct radeon_device *rdev);
+ void cik_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+-void cik_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags);
++void cik_sdma_vm_set_page(struct radeon_device *rdev,
++ struct radeon_ib *ib,
++ uint64_t pe,
++ uint64_t addr, unsigned count,
++ uint32_t incr, uint32_t flags);
+ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+ int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index 33bd02e..9ceabdf 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -920,6 +920,26 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr)
+ }
+
+ /**
++ * radeon_vm_page_flags - translate page flags to what the hw uses
++ *
++ * @flags: flags comming from userspace
++ *
++ * Translate the flags the userspace ABI uses to hw flags.
++ */
++static uint32_t radeon_vm_page_flags(uint32_t flags)
++{
++ uint32_t hw_flags = 0;
++ hw_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_PTE_VALID : 0;
++ hw_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0;
++ hw_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0;
++ if (flags & RADEON_VM_PAGE_SYSTEM) {
++ hw_flags |= R600_PTE_SYSTEM;
++ hw_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0;
++ }
++ return hw_flags;
++}
++
++/**
+ * radeon_vm_update_pdes - make sure that page directory is valid
+ *
+ * @rdev: radeon_device pointer
+@@ -980,7 +1000,7 @@ retry:
+ if (count) {
+ radeon_asic_vm_set_page(rdev, ib, last_pde,
+ last_pt, count, incr,
+- RADEON_VM_PAGE_VALID);
++ R600_PTE_VALID);
+ }
+
+ count = 1;
+@@ -993,7 +1013,7 @@ retry:
+
+ if (count) {
+ radeon_asic_vm_set_page(rdev, ib, last_pde, last_pt, count,
+- incr, RADEON_VM_PAGE_VALID);
++ incr, R600_PTE_VALID);
+
+ }
+
+@@ -1088,7 +1108,6 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
+ struct radeon_bo *bo,
+ struct ttm_mem_reg *mem)
+ {
+- unsigned ridx = rdev->asic->vm.pt_ring_index;
+ struct radeon_ib ib;
+ struct radeon_bo_va *bo_va;
+ unsigned nptes, npdes, ndw;
+@@ -1163,7 +1182,7 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
+ if (ndw > 0xfffff)
+ return -ENOMEM;
+
+- r = radeon_ib_get(rdev, ridx, &ib, NULL, ndw * 4);
++ r = radeon_ib_get(rdev, R600_RING_TYPE_DMA_INDEX, &ib, NULL, ndw * 4);
+ if (r)
+ return r;
+ ib.length_dw = 0;
+@@ -1175,7 +1194,7 @@ int radeon_vm_bo_update(struct radeon_device *rdev,
+ }
+
+ radeon_vm_update_ptes(rdev, vm, &ib, bo_va->soffset, bo_va->eoffset,
+- addr, bo_va->flags);
++ addr, radeon_vm_page_flags(bo_va->flags));
+
+ radeon_semaphore_sync_to(ib.semaphore, vm->fence);
+ r = radeon_ib_schedule(rdev, &ib, NULL);
+diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
+index 37acf93..0334f3e 100644
+--- a/drivers/gpu/drm/radeon/si.c
++++ b/drivers/gpu/drm/radeon/si.c
+@@ -78,11 +78,6 @@ extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_
+ extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev);
+ extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
+ extern bool evergreen_is_display_hung(struct radeon_device *rdev);
+-extern void si_dma_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags);
+ static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
+ bool enable);
+ static void si_fini_pg(struct radeon_device *rdev);
+@@ -4682,61 +4677,6 @@ static void si_vm_decode_fault(struct radeon_device *rdev,
+ block, mc_id);
+ }
+
+-/**
+- * si_vm_set_page - update the page tables using the CP
+- *
+- * @rdev: radeon_device pointer
+- * @ib: indirect buffer to fill with commands
+- * @pe: addr of the page entry
+- * @addr: dst addr to write into pe
+- * @count: number of page entries to update
+- * @incr: increase next addr by incr bytes
+- * @flags: access flags
+- *
+- * Update the page tables using the CP (SI).
+- */
+-void si_vm_set_page(struct radeon_device *rdev,
+- struct radeon_ib *ib,
+- uint64_t pe,
+- uint64_t addr, unsigned count,
+- uint32_t incr, uint32_t flags)
+-{
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+- uint64_t value;
+- unsigned ndw;
+-
+- if (rdev->asic->vm.pt_ring_index == RADEON_RING_TYPE_GFX_INDEX) {
+- while (count) {
+- ndw = 2 + count * 2;
+- if (ndw > 0x3FFE)
+- ndw = 0x3FFE;
+-
+- ib->ptr[ib->length_dw++] = PACKET3(PACKET3_WRITE_DATA, ndw);
+- ib->ptr[ib->length_dw++] = (WRITE_DATA_ENGINE_SEL(0) |
+- WRITE_DATA_DST_SEL(1));
+- ib->ptr[ib->length_dw++] = pe;
+- ib->ptr[ib->length_dw++] = upper_32_bits(pe);
+- for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- value = radeon_vm_map_gart(rdev, addr);
+- value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
+- value = addr;
+- } else {
+- value = 0;
+- }
+- addr += incr;
+- value |= r600_flags;
+- ib->ptr[ib->length_dw++] = value;
+- ib->ptr[ib->length_dw++] = upper_32_bits(value);
+- }
+- }
+- } else {
+- /* DMA */
+- si_dma_vm_set_page(rdev, ib, pe, addr, count, incr, flags);
+- }
+-}
+-
+ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
+ {
+ struct radeon_ring *ring = &rdev->ring[ridx];
+diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c
+index 97af34c..59be2cf 100644
+--- a/drivers/gpu/drm/radeon/si_dma.c
++++ b/drivers/gpu/drm/radeon/si_dma.c
+@@ -76,13 +76,12 @@ void si_dma_vm_set_page(struct radeon_device *rdev,
+ uint64_t addr, unsigned count,
+ uint32_t incr, uint32_t flags)
+ {
+- uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
+ uint64_t value;
+ unsigned ndw;
+
+- trace_radeon_vm_set_page(pe, addr, count, incr, r600_flags);
++ trace_radeon_vm_set_page(pe, addr, count, incr, flags);
+
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
++ if (flags & R600_PTE_SYSTEM) {
+ while (count) {
+ ndw = count * 2;
+ if (ndw > 0xFFFFE)
+@@ -93,16 +92,10 @@ void si_dma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = pe;
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+ for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+- if (flags & RADEON_VM_PAGE_SYSTEM) {
+- value = radeon_vm_map_gart(rdev, addr);
+- value &= 0xFFFFFFFFFFFFF000ULL;
+- } else if (flags & RADEON_VM_PAGE_VALID) {
+- value = addr;
+- } else {
+- value = 0;
+- }
++ value = radeon_vm_map_gart(rdev, addr);
++ value &= 0xFFFFFFFFFFFFF000ULL;
+ addr += incr;
+- value |= r600_flags;
++ value |= flags;
+ ib->ptr[ib->length_dw++] = value;
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+ }
+@@ -113,7 +106,7 @@ void si_dma_vm_set_page(struct radeon_device *rdev,
+ if (ndw > 0xFFFFE)
+ ndw = 0xFFFFE;
+
+- if (flags & RADEON_VM_PAGE_VALID)
++ if (flags & R600_PTE_VALID)
+ value = addr;
+ else
+ value = 0;
+@@ -121,7 +114,7 @@ void si_dma_vm_set_page(struct radeon_device *rdev,
+ ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw);
+ ib->ptr[ib->length_dw++] = pe; /* dst addr */
+ ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff;
+- ib->ptr[ib->length_dw++] = r600_flags; /* mask */
++ ib->ptr[ib->length_dw++] = flags; /* mask */
+ ib->ptr[ib->length_dw++] = 0;
+ ib->ptr[ib->length_dw++] = value; /* value */
+ ib->ptr[ib->length_dw++] = upper_32_bits(value);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0018-yocto-amd-drm-radeon-add-large-PTE-support-for-NI-SI-and-CIK-v.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0018-yocto-amd-drm-radeon-add-large-PTE-support-for-NI-SI-and-CIK-v.patch
new file mode 100644
index 00000000..6498c071
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0018-yocto-amd-drm-radeon-add-large-PTE-support-for-NI-SI-and-CIK-v.patch
@@ -0,0 +1,237 @@
+From a2bc39a6394bb8e11060df3da33d603a66ccf9f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 25 Oct 2013 18:07:55 +0200
+Subject: [PATCH 18/44] drm/radeon: add large PTE support for NI, SI and CIK
+ v3
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch implements support for VRAM page table entry compression.
+PTE construction is enhanced to identify physically contiguous page
+ranges and mark them in the PTE fragment field. L1 TLB and L2 cache
+support is enabled for 64KB (SI/CIK) and 256KB (NI) PTE fragments,
+significantly improving TLB utilization for VRAM allocations.
+
+Linear store bandwidth is improved from 60GB/s to 125GB/s on Pitcairn.
+Unigine Heaven 3.0 sees an average improvement from 24.7 to 27.7 FPS
+on default settings at 1920x1200 resolution with vsync disabled.
+
+See main comment in radeon_gart.c gives a technical description.
+
+v2 (chk): rebased and simplified.
+v3 (chk): add missing hw setup
+
+Signed-off-by: Jay Cornwall <jay@jcornwall.me>
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 4 +-
+ drivers/gpu/drm/radeon/ni.c | 2 +
+ drivers/gpu/drm/radeon/radeon.h | 5 ++
+ drivers/gpu/drm/radeon/radeon_gart.c | 91 +++++++++++++++++++++++++++++++---
+ drivers/gpu/drm/radeon/si.c | 5 +-
+ 5 files changed, 98 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index d7e86ef3..27fa479 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -4522,6 +4522,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
+ WREG32(MC_VM_MX_L1_TLB_CNTL,
+ (0xA << 7) |
+ ENABLE_L1_TLB |
++ ENABLE_L1_FRAGMENT_PROCESSING |
+ SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+ ENABLE_ADVANCED_DRIVER_MODEL |
+ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+@@ -4534,7 +4535,8 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
+ CONTEXT1_IDENTITY_ACCESS_MODE(1));
+ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
+ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+- L2_CACHE_BIGK_FRAGMENT_SIZE(6));
++ BANK_SELECT(4) |
++ L2_CACHE_BIGK_FRAGMENT_SIZE(4));
+ /* setup context0 */
+ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index f59a9e9..9291982 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -1227,12 +1227,14 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
+ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+ /* Setup L2 cache */
+ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
++ ENABLE_L2_FRAGMENT_PROCESSING |
+ ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+ EFFECTIVE_L2_QUEUE_SIZE(7) |
+ CONTEXT1_IDENTITY_ACCESS_MODE(1));
+ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
+ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
++ BANK_SELECT(6) |
+ L2_CACHE_BIGK_FRAGMENT_SIZE(6));
+ /* setup context0 */
+ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index b987f01..06b3375 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -846,6 +846,11 @@ struct radeon_mec {
+ #define R600_PTE_READABLE (1 << 5)
+ #define R600_PTE_WRITEABLE (1 << 6)
+
++/* PTE (Page Table Entry) fragment field for different page sizes */
++#define R600_PTE_FRAG_4KB (0 << 7)
++#define R600_PTE_FRAG_64KB (4 << 7)
++#define R600_PTE_FRAG_256KB (6 << 7)
++
+ struct radeon_vm {
+ struct list_head list;
+ struct list_head va;
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index 9ceabdf..f960ce6 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -1021,6 +1021,84 @@ retry:
+ }
+
+ /**
++ * radeon_vm_frag_ptes - add fragment information to PTEs
++ *
++ * @rdev: radeon_device pointer
++ * @ib: IB for the update
++ * @pe_start: first PTE to handle
++ * @pe_end: last PTE to handle
++ * @addr: addr those PTEs should point to
++ * @flags: hw mapping flags
++ *
++ * Global and local mutex must be locked!
++ */
++static void radeon_vm_frag_ptes(struct radeon_device *rdev,
++ struct radeon_ib *ib,
++ uint64_t pe_start, uint64_t pe_end,
++ uint64_t addr, uint32_t flags)
++{
++ /**
++ * The MC L1 TLB supports variable sized pages, based on a fragment
++ * field in the PTE. When this field is set to a non-zero value, page
++ * granularity is increased from 4KB to (1 << (12 + frag)). The PTE
++ * flags are considered valid for all PTEs within the fragment range
++ * and corresponding mappings are assumed to be physically contiguous.
++ *
++ * The L1 TLB can store a single PTE for the whole fragment,
++ * significantly increasing the space available for translation
++ * caching. This leads to large improvements in throughput when the
++ * TLB is under pressure.
++ *
++ * The L2 cache distributes small and large fragments into two
++ * asymmetric partitions. The large fragment cache is significantly
++ * larger. Thus, we try to use large fragments wherever possible.
++ * Userspace can support this by aligning virtual base address and
++ * allocation size to the fragment size.
++ */
++
++ /* NI is optimized for 256KB fragments, SI and newer for 64KB */
++ uint64_t frag_flags = rdev->family == CHIP_CAYMAN ?
++ R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB;
++ uint64_t frag_align = rdev->family == CHIP_CAYMAN ? 0x200 : 0x80;
++
++ uint64_t frag_start = ALIGN(pe_start, frag_align);
++ uint64_t frag_end = pe_end & ~(frag_align - 1);
++
++ unsigned count;
++
++ /* system pages are non continuously */
++ if ((flags & R600_PTE_SYSTEM) || !(flags & R600_PTE_VALID) ||
++ (frag_start >= frag_end)) {
++
++ count = (pe_end - pe_start) / 8;
++ radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
++ RADEON_GPU_PAGE_SIZE, flags);
++ return;
++ }
++
++ /* handle the 4K area at the beginning */
++ if (pe_start != frag_start) {
++ count = (frag_start - pe_start) / 8;
++ radeon_asic_vm_set_page(rdev, ib, pe_start, addr, count,
++ RADEON_GPU_PAGE_SIZE, flags);
++ addr += RADEON_GPU_PAGE_SIZE * count;
++ }
++
++ /* handle the area in the middle */
++ count = (frag_end - frag_start) / 8;
++ radeon_asic_vm_set_page(rdev, ib, frag_start, addr, count,
++ RADEON_GPU_PAGE_SIZE, flags | frag_flags);
++
++ /* handle the 4K area at the end */
++ if (frag_end != pe_end) {
++ addr += RADEON_GPU_PAGE_SIZE * count;
++ count = (pe_end - frag_end) / 8;
++ radeon_asic_vm_set_page(rdev, ib, frag_end, addr, count,
++ RADEON_GPU_PAGE_SIZE, flags);
++ }
++}
++
++/**
+ * radeon_vm_update_ptes - make sure that page tables are valid
+ *
+ * @rdev: radeon_device pointer
+@@ -1066,10 +1144,9 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
+ if ((last_pte + 8 * count) != pte) {
+
+ if (count) {
+- radeon_asic_vm_set_page(rdev, ib, last_pte,
+- last_dst, count,
+- RADEON_GPU_PAGE_SIZE,
+- flags);
++ radeon_vm_frag_ptes(rdev, ib, last_pte,
++ last_pte + 8 * count,
++ last_dst, flags);
+ }
+
+ count = nptes;
+@@ -1084,9 +1161,9 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
+ }
+
+ if (count) {
+- radeon_asic_vm_set_page(rdev, ib, last_pte,
+- last_dst, count,
+- RADEON_GPU_PAGE_SIZE, flags);
++ radeon_vm_frag_ptes(rdev, ib, last_pte,
++ last_pte + 8 * count,
++ last_dst, flags);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
+index 0334f3e..d9173ef 100644
+--- a/drivers/gpu/drm/radeon/si.c
++++ b/drivers/gpu/drm/radeon/si.c
+@@ -3928,18 +3928,21 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
+ WREG32(MC_VM_MX_L1_TLB_CNTL,
+ (0xA << 7) |
+ ENABLE_L1_TLB |
++ ENABLE_L1_FRAGMENT_PROCESSING |
+ SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+ ENABLE_ADVANCED_DRIVER_MODEL |
+ SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+ /* Setup L2 cache */
+ WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
++ ENABLE_L2_FRAGMENT_PROCESSING |
+ ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+ ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+ EFFECTIVE_L2_QUEUE_SIZE(7) |
+ CONTEXT1_IDENTITY_ACCESS_MODE(1));
+ WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
+ WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+- L2_CACHE_BIGK_FRAGMENT_SIZE(0));
++ BANK_SELECT(4) |
++ L2_CACHE_BIGK_FRAGMENT_SIZE(4));
+ /* setup context0 */
+ WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0019-yocto-amd-drm-radeon-add-proper-support-for-RADEON_VM_BLOCK_SI.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0019-yocto-amd-drm-radeon-add-proper-support-for-RADEON_VM_BLOCK_SI.patch
new file mode 100644
index 00000000..8061d7ba
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0019-yocto-amd-drm-radeon-add-proper-support-for-RADEON_VM_BLOCK_SI.patch
@@ -0,0 +1,133 @@
+From 7ef7e2da03959058588c4f0bc68e32b1bf17e1d9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 29 Oct 2013 09:30:16 +0100
+Subject: [PATCH 19/44] drm/radeon: add proper support for
+ RADEON_VM_BLOCK_SIZE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch makes it possible to decide how many address
+bits are spend on the page directory vs the page tables.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 1 +
+ drivers/gpu/drm/radeon/cikd.h | 1 +
+ drivers/gpu/drm/radeon/ni.c | 1 +
+ drivers/gpu/drm/radeon/nid.h | 1 +
+ drivers/gpu/drm/radeon/radeon.h | 2 +-
+ drivers/gpu/drm/radeon/radeon_gart.c | 3 ++-
+ drivers/gpu/drm/radeon/si.c | 1 +
+ drivers/gpu/drm/radeon/sid.h | 1 +
+ 8 files changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 27fa479..cd5f85e 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -4572,6 +4572,7 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
+ (u32)(rdev->dummy_page.addr >> 12));
+ WREG32(VM_CONTEXT1_CNTL2, 4);
+ WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
++ PAGE_TABLE_BLOCK_SIZE(RADEON_VM_BLOCK_SIZE - 9) |
+ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
+index 203d2a0..7a0a0d2 100644
+--- a/drivers/gpu/drm/radeon/cikd.h
++++ b/drivers/gpu/drm/radeon/cikd.h
+@@ -474,6 +474,7 @@
+ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16)
+ #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18)
+ #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19)
++#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24)
+ #define VM_CONTEXT1_CNTL 0x1414
+ #define VM_CONTEXT0_CNTL2 0x1430
+ #define VM_CONTEXT1_CNTL2 0x1434
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index 9291982..ce87221 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -1267,6 +1267,7 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
+ (u32)(rdev->dummy_page.addr >> 12));
+ WREG32(VM_CONTEXT1_CNTL2, 4);
+ WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
++ PAGE_TABLE_BLOCK_SIZE(RADEON_VM_BLOCK_SIZE - 9) |
+ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
+index 22421bc..ef7ba2d 100644
+--- a/drivers/gpu/drm/radeon/nid.h
++++ b/drivers/gpu/drm/radeon/nid.h
+@@ -128,6 +128,7 @@
+ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16)
+ #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18)
+ #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19)
++#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24)
+ #define VM_CONTEXT1_CNTL 0x1414
+ #define VM_CONTEXT0_CNTL2 0x1430
+ #define VM_CONTEXT1_CNTL2 0x1434
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 06b3375..c639a58 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -830,7 +830,7 @@ struct radeon_mec {
+ /* defines number of bits in page table versus page directory,
+ * a page is 4KB so we have 12 bits offset, 9 bits in the page
+ * table and the remaining 19 bits are in the page directory */
+-#define RADEON_VM_BLOCK_SIZE 9
++#define RADEON_VM_BLOCK_SIZE 12
+
+ /* number of entries in page table */
+ #define RADEON_VM_PTE_COUNT (1 << RADEON_VM_BLOCK_SIZE)
+diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
+index f960ce6..34b09ac 100644
+--- a/drivers/gpu/drm/radeon/radeon_gart.c
++++ b/drivers/gpu/drm/radeon/radeon_gart.c
+@@ -959,6 +959,7 @@ static int radeon_vm_update_pdes(struct radeon_device *rdev,
+ uint64_t start, uint64_t end)
+ {
+ static const uint32_t incr = RADEON_VM_PTE_COUNT * 8;
++ const unsigned align = min((uint32_t)RADEON_VM_PTB_ALIGN_SIZE, incr);
+
+ uint64_t last_pde = ~0, last_pt = ~0;
+ unsigned count = 0;
+@@ -979,7 +980,7 @@ retry:
+ r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
+ &vm->page_tables[pt_idx],
+ RADEON_VM_PTE_COUNT * 8,
+- RADEON_GPU_PAGE_SIZE, false);
++ align, false);
+
+ if (r == -ENOMEM) {
+ r = radeon_vm_evict(rdev, vm);
+diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
+index d9173ef..a7c53b7 100644
+--- a/drivers/gpu/drm/radeon/si.c
++++ b/drivers/gpu/drm/radeon/si.c
+@@ -3979,6 +3979,7 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
+ (u32)(rdev->dummy_page.addr >> 12));
+ WREG32(VM_CONTEXT1_CNTL2, 4);
+ WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
++ PAGE_TABLE_BLOCK_SIZE(RADEON_VM_BLOCK_SIZE - 9) |
+ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
+ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
+diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
+index 6e23019..db3dd87 100644
+--- a/drivers/gpu/drm/radeon/sid.h
++++ b/drivers/gpu/drm/radeon/sid.h
+@@ -357,6 +357,7 @@
+ #define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16)
+ #define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18)
+ #define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19)
++#define PAGE_TABLE_BLOCK_SIZE(x) (((x) & 0xF) << 24)
+ #define VM_CONTEXT1_CNTL 0x1414
+ #define VM_CONTEXT0_CNTL2 0x1430
+ #define VM_CONTEXT1_CNTL2 0x1434
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0020-yocto-amd-drm-radeon-WIP-add-copy-trace-point.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0020-yocto-amd-drm-radeon-WIP-add-copy-trace-point.patch
new file mode 100644
index 00000000..95662197
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0020-yocto-amd-drm-radeon-WIP-add-copy-trace-point.patch
@@ -0,0 +1,59 @@
+From fd743f086a3079b5fab5f05809a5998200f5201d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Tue, 17 Dec 2013 11:43:21 -0700
+Subject: [PATCH 20/44] drm/radeon: WIP add copy trace point
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/cik_sdma.c | 2 ++
+ drivers/gpu/drm/radeon/radeon_trace.h | 18 ++++++++++++++++++
+ 2 files changed, 20 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index 8517a62..a589d79 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -433,6 +433,8 @@ int cik_copy_dma(struct radeon_device *rdev,
+ int i, num_loops;
+ int r = 0;
+
++ trace_radeon_copy(src_offset, dst_offset, num_gpu_pages);
++
+ r = radeon_semaphore_create(rdev, &sem);
+ if (r) {
+ DRM_ERROR("radeon: moving bo (%d).\n", r);
+diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
+index 0473257..6e966bb 100644
+--- a/drivers/gpu/drm/radeon/radeon_trace.h
++++ b/drivers/gpu/drm/radeon/radeon_trace.h
+@@ -27,6 +27,24 @@ TRACE_EVENT(radeon_bo_create,
+ TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages)
+ );
+
++TRACE_EVENT(radeon_copy,
++ TP_PROTO(u64 src, u64 dst, u32 pages),
++ TP_ARGS(src, dst, pages),
++ TP_STRUCT__entry(
++ __field(u64, src)
++ __field(u64, dst)
++ __field(u32, pages)
++ ),
++
++ TP_fast_assign(
++ __entry->src = src;
++ __entry->dst = dst;
++ __entry->pages = pages;
++ ),
++ TP_printk("src=%010llx, dst=%010llx, pages=%u",
++ __entry->src, __entry->dst, __entry->pages)
++);
++
+ TRACE_EVENT(radeon_cs,
+ TP_PROTO(struct radeon_cs_parser *p),
+ TP_ARGS(p),
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0021-yocto-amd-drm-radeon-cik-Return-backend-map-information-to-use.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0021-yocto-amd-drm-radeon-cik-Return-backend-map-information-to-use.patch
new file mode 100644
index 00000000..d082f22c
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0021-yocto-amd-drm-radeon-cik-Return-backend-map-information-to-use.patch
@@ -0,0 +1,34 @@
+From 72285aebc730c0b21532a0c5c83aa3f7d075e5ce Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel.daenzer@amd.com>
+Date: Mon, 18 Nov 2013 18:25:59 +0900
+Subject: [PATCH 21/44] drm/radeon/cik: Return backend map information to
+ userspace
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is required to properly calculate the tiling parameters
+in userspace.
+
+Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_kms.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 4a3b3c5..405b0d4 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -324,7 +324,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+ break;
+ case RADEON_INFO_BACKEND_MAP:
+ if (rdev->family >= CHIP_BONAIRE)
+- return -EINVAL;
++ *value = rdev->config.cik.backend_map;
+ else if (rdev->family >= CHIP_TAHITI)
+ *value = rdev->config.si.backend_map;
+ else if (rdev->family >= CHIP_CAYMAN)
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0022-yocto-amd-drm-radeon-cik-Add-macrotile-mode-array-query.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0022-yocto-amd-drm-radeon-cik-Add-macrotile-mode-array-query.patch
new file mode 100644
index 00000000..63d826e6
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0022-yocto-amd-drm-radeon-cik-Add-macrotile-mode-array-query.patch
@@ -0,0 +1,113 @@
+From 93ebc5801cab1c47f426da110d19b77f71a51b4f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <michel.daenzer@amd.com>
+Date: Mon, 18 Nov 2013 18:26:00 +0900
+Subject: [PATCH 22/44] drm/radeon/cik: Add macrotile mode array query
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is required to properly calculate the tiling parameters
+in userspace.
+
+Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 3 +++
+ drivers/gpu/drm/radeon/radeon.h | 1 +
+ drivers/gpu/drm/radeon/radeon_drv.c | 3 ++-
+ drivers/gpu/drm/radeon/radeon_kms.c | 9 +++++++++
+ include/uapi/drm/radeon_drm.h | 2 ++
+ 5 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index cd5f85e..5419abe 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -1981,6 +1981,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
+ gb_tile_moden = 0;
+ break;
+ }
++ rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
+ }
+ } else if (num_pipe_configs == 4) {
+@@ -2327,6 +2328,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
+ gb_tile_moden = 0;
+ break;
+ }
++ rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
+ }
+ } else if (num_pipe_configs == 2) {
+@@ -2544,6 +2546,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
+ gb_tile_moden = 0;
+ break;
+ }
++ rdev->config.cik.macrotile_mode_array[reg_offset] = gb_tile_moden;
+ WREG32(GB_MACROTILE_MODE0 + (reg_offset * 4), gb_tile_moden);
+ }
+ } else
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index c639a58..5331fc2 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1991,6 +1991,7 @@ struct cik_asic {
+
+ unsigned tile_config;
+ uint32_t tile_mode_array[32];
++ uint32_t macrotile_mode_array[16];
+ };
+
+ union radeon_asic_config {
+diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
+index 9c14a1b..51b3214 100644
+--- a/drivers/gpu/drm/radeon/radeon_drv.c
++++ b/drivers/gpu/drm/radeon/radeon_drv.c
+@@ -75,9 +75,10 @@
+ * 2.32.0 - new info request for rings working
+ * 2.33.0 - Add SI tiling mode array query
+ * 2.34.0 - Add CIK tiling mode array query
++ * 2.35.0 - Add CIK macrotile mode array query
+ */
+ #define KMS_DRIVER_MAJOR 2
+-#define KMS_DRIVER_MINOR 34
++#define KMS_DRIVER_MINOR 35
+ #define KMS_DRIVER_PATCHLEVEL 0
+ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
+ int radeon_driver_unload_kms(struct drm_device *dev);
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 405b0d4..5d67422 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -433,6 +433,15 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+ return -EINVAL;
+ }
+ break;
++ case RADEON_INFO_CIK_MACROTILE_MODE_ARRAY:
++ if (rdev->family >= CHIP_BONAIRE) {
++ value = rdev->config.cik.macrotile_mode_array;
++ value_size = sizeof(uint32_t)*16;
++ } else {
++ DRM_DEBUG_KMS("macrotile mode array is cik+ only!\n");
++ return -EINVAL;
++ }
++ break;
+ case RADEON_INFO_SI_CP_DMA_COMPUTE:
+ *value = 1;
+ break;
+diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
+index a71442b..fe421e8 100644
+--- a/include/uapi/drm/radeon_drm.h
++++ b/include/uapi/drm/radeon_drm.h
+@@ -981,6 +981,8 @@ struct drm_radeon_cs {
+ #define RADEON_INFO_SI_TILE_MODE_ARRAY 0x16
+ /* query if CP DMA is supported on the compute ring */
+ #define RADEON_INFO_SI_CP_DMA_COMPUTE 0x17
++/* CIK macrotile mode array */
++#define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18
+ /* query the number of render backends */
+ #define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19
+
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0023-yocto-amd-drm-radeon-set-correct-number-of-banks-for-CIK-chips.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0023-yocto-amd-drm-radeon-set-correct-number-of-banks-for-CIK-chips.patch
new file mode 100644
index 00000000..def7d8fc
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0023-yocto-amd-drm-radeon-set-correct-number-of-banks-for-CIK-chips.patch
@@ -0,0 +1,102 @@
+From 037690c12dcf3c3c2843f8db082ad2f5d49b7757 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <marek.olsak@amd.com>
+Date: Mon, 23 Dec 2013 17:11:36 +0100
+Subject: [PATCH 23/44] drm/radeon: set correct number of banks for CIK chips
+ in DCE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We don't have the NUM_BANKS parameter, so we have to calculate it
+from the other parameters. NUM_BANKS is not constant on CIK.
+
+This fixes 2D tiling for the display engine on CIK.
+
+Signed-off-by: Marek Olšák <marek.olsak@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c | 64 +++++++++++++++++++++-----------
+ 1 file changed, 43 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
+index 368e1b8..09b35c3 100644
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -1143,31 +1143,53 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
+ }
+
+ if (tiling_flags & RADEON_TILING_MACRO) {
+- if (rdev->family >= CHIP_BONAIRE)
+- tmp = rdev->config.cik.tile_config;
+- else if (rdev->family >= CHIP_TAHITI)
+- tmp = rdev->config.si.tile_config;
+- else if (rdev->family >= CHIP_CAYMAN)
+- tmp = rdev->config.cayman.tile_config;
+- else
+- tmp = rdev->config.evergreen.tile_config;
++ evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
+
+- switch ((tmp & 0xf0) >> 4) {
+- case 0: /* 4 banks */
+- fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
+- break;
+- case 1: /* 8 banks */
+- default:
+- fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
+- break;
+- case 2: /* 16 banks */
+- fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
+- break;
++ /* Set NUM_BANKS. */
++ if (rdev->family >= CHIP_BONAIRE) {
++ unsigned tileb, index, num_banks, tile_split_bytes;
++
++ /* Calculate the macrotile mode index. */
++ tile_split_bytes = 64 << tile_split;
++ tileb = 8 * 8 * target_fb->bits_per_pixel / 8;
++ tileb = min(tile_split_bytes, tileb);
++
++ for (index = 0; tileb > 64; index++) {
++ tileb >>= 1;
++ }
++
++ if (index >= 16) {
++ DRM_ERROR("Wrong screen bpp (%u) or tile split (%u)\n",
++ target_fb->bits_per_pixel, tile_split);
++ return -EINVAL;
++ }
++
++ num_banks = (rdev->config.cik.macrotile_mode_array[index] >> 6) & 0x3;
++ fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
++ } else {
++ /* SI and older. */
++ if (rdev->family >= CHIP_TAHITI)
++ tmp = rdev->config.si.tile_config;
++ else if (rdev->family >= CHIP_CAYMAN)
++ tmp = rdev->config.cayman.tile_config;
++ else
++ tmp = rdev->config.evergreen.tile_config;
++
++ switch ((tmp & 0xf0) >> 4) {
++ case 0: /* 4 banks */
++ fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK);
++ break;
++ case 1: /* 8 banks */
++ default:
++ fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK);
++ break;
++ case 2: /* 16 banks */
++ fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK);
++ break;
++ }
+ }
+
+ fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
+-
+- evergreen_tiling_fields(tiling_flags, &bankw, &bankh, &mtaspect, &tile_split);
+ fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
+ fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
+ fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0024-yocto-amd-drm-radeon-don-t-power-gate-paused-UVD-streams.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0024-yocto-amd-drm-radeon-don-t-power-gate-paused-UVD-streams.patch
new file mode 100644
index 00000000..8beb11e7
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0024-yocto-amd-drm-radeon-don-t-power-gate-paused-UVD-streams.patch
@@ -0,0 +1,45 @@
+From e273f124b346f1fcbf3c363ae3224344988d07de Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 10 Jan 2014 06:59:40 -0700
+Subject: [PATCH 24/44] drm/radeon: don't power gate paused UVD streams
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_pm.c | 4 ++++
+ drivers/gpu/drm/radeon/radeon_uvd.c | 2 ++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
+index 4f6b7fc..41ca652 100644
+--- a/drivers/gpu/drm/radeon/radeon_pm.c
++++ b/drivers/gpu/drm/radeon/radeon_pm.c
+@@ -938,6 +938,10 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
+
+ if (rdev->asic->dpm.powergate_uvd) {
+ mutex_lock(&rdev->pm.mutex);
++ /* don't powergate anything if we
++ have active but pause streams */
++ enable |= rdev->pm.dpm.sd > 0;
++ enable |= rdev->pm.dpm.hd > 0;
+ /* enable/disable UVD */
+ radeon_dpm_powergate_uvd(rdev, !enable);
+ mutex_unlock(&rdev->pm.mutex);
+diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
+index 2b502b4..1b5970a 100644
+--- a/drivers/gpu/drm/radeon/radeon_uvd.c
++++ b/drivers/gpu/drm/radeon/radeon_uvd.c
+@@ -782,6 +782,8 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work)
+
+ if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) {
+ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
++ radeon_uvd_count_handles(rdev, &rdev->pm.dpm.sd,
++ &rdev->pm.dpm.hd);
+ radeon_dpm_enable_uvd(rdev, false);
+ } else {
+ radeon_set_uvd_clocks(rdev, 0, 0);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0025-yocto-amd-drm-radeon-dpm-retain-user-selected-performance-leve.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0025-yocto-amd-drm-radeon-dpm-retain-user-selected-performance-leve.patch
new file mode 100644
index 00000000..abec682c
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0025-yocto-amd-drm-radeon-dpm-retain-user-selected-performance-leve.patch
@@ -0,0 +1,45 @@
+From b2773506c602407fc15219c75ec673d4bd0c2d82 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 23 Oct 2013 21:31:42 +0000
+Subject: [PATCH 25/44] drm/radeon/dpm: retain user selected performance level
+ across state changes
+
+If the user has forced the state high or low, retain that preference
+even when we switch power states.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=70654
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_pm.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
+index 41ca652..5febb25 100644
+--- a/drivers/gpu/drm/radeon/radeon_pm.c
++++ b/drivers/gpu/drm/radeon/radeon_pm.c
+@@ -918,12 +918,16 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
+ radeon_dpm_post_set_power_state(rdev);
+
+ if (rdev->asic->dpm.force_performance_level) {
+- if (rdev->pm.dpm.thermal_active)
++ if (rdev->pm.dpm.thermal_active) {
++ enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
+ /* force low perf level for thermal */
+ radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW);
+- else
+- /* otherwise, enable auto */
+- radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
++ /* save the user's level */
++ rdev->pm.dpm.forced_level = level;
++ } else {
++ /* otherwise, user selected level */
++ radeon_dpm_force_performance_level(rdev, rdev->pm.dpm.forced_level);
++ }
+ }
+
+ done:
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0026-yocto-amd-drm-radeon-remove-generic-rptr-wptr-functions-v2.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0026-yocto-amd-drm-radeon-remove-generic-rptr-wptr-functions-v2.patch
new file mode 100644
index 00000000..628a3230
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0026-yocto-amd-drm-radeon-remove-generic-rptr-wptr-functions-v2.patch
@@ -0,0 +1,1049 @@
+From 3f033c032e0fd56dd58707405c037800f0f6fe90 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 10 Dec 2013 00:44:30 +0000
+Subject: [PATCH 26/44] drm/radeon: remove generic rptr/wptr functions (v2)
+
+Fill in asic family specific versions rather than
+using the generic version. This lets us handle asic
+specific differences more easily. In this case, we
+disable sw swapping of the rtpr writeback value on
+r6xx+ since the hw does it for us. Fixes bogus
+rptr readback on BE systems.
+
+v2: remove missed cpu_to_le32(), add comments
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/cik.c | 58 +++++++++++++++++++---------
+ drivers/gpu/drm/radeon/cik_sdma.c | 69 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/evergreen.c | 3 --
+ drivers/gpu/drm/radeon/ni.c | 69 ++++++++++++++++++++++++++++++----
+ drivers/gpu/drm/radeon/ni_dma.c | 69 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/r100.c | 31 ++++++++++++++-
+ drivers/gpu/drm/radeon/r600.c | 32 +++++++++++++++-
+ drivers/gpu/drm/radeon/r600_dma.c | 13 +++++--
+ drivers/gpu/drm/radeon/radeon.h | 4 +-
+ drivers/gpu/drm/radeon/radeon_asic.c | 66 ++++++++++++++++----------------
+ drivers/gpu/drm/radeon/radeon_asic.h | 57 +++++++++++++++++++++-------
+ drivers/gpu/drm/radeon/radeon_ring.c | 44 +++-------------------
+ drivers/gpu/drm/radeon/rv770.c | 3 --
+ drivers/gpu/drm/radeon/si.c | 8 ----
+ 14 files changed, 392 insertions(+), 134 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 5419abe..4a89b5c 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -3461,15 +3461,43 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
+ return 0;
+ }
+
+-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
++u32 cik_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
+ {
+ u32 rptr;
+
++ if (rdev->wb.enabled)
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ else
++ rptr = RREG32(CP_RB0_RPTR);
++
++ return rptr;
++}
+
++u32 cik_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 wptr;
++
++ wptr = RREG32(CP_RB0_WPTR);
++
++ return wptr;
++}
++
++void cik_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ WREG32(CP_RB0_WPTR, ring->wptr);
++ (void)RREG32(CP_RB0_WPTR);
++}
++
++u32 cik_compute_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr;
+
+ if (rdev->wb.enabled) {
+- rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
+ } else {
+ mutex_lock(&rdev->srbm_mutex);
+ cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
+@@ -3481,13 +3509,14 @@ u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
+ return rptr;
+ }
+
+-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
++u32 cik_compute_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
+ {
+ u32 wptr;
+
+ if (rdev->wb.enabled) {
+- wptr = le32_to_cpu(rdev->wb.wb[ring->wptr_offs/4]);
++ /* XXX check if swapping is necessary on BE */
++ wptr = rdev->wb.wb[ring->wptr_offs/4];
+ } else {
+ mutex_lock(&rdev->srbm_mutex);
+ cik_srbm_select(rdev, ring->me, ring->pipe, ring->queue, 0);
+@@ -3499,10 +3528,11 @@ u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
+ return wptr;
+ }
+
+-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
++void cik_compute_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
+ {
+- rdev->wb.wb[ring->wptr_offs/4] = cpu_to_le32(ring->wptr);
++ /* XXX check if swapping is necessary on BE */
++ rdev->wb.wb[ring->wptr_offs/4] = ring->wptr;
+ WDOORBELL32(ring->doorbell_offset, ring->wptr);
+ }
+
+@@ -7058,8 +7088,7 @@ static int cik_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- CP_RB0_RPTR, CP_RB0_WPTR,
+- RADEON_CP_PACKET2);
++ PACKET3(PACKET3_NOP, 0x3FFF));
+ if (r)
+ return r;
+
+@@ -7067,7 +7096,6 @@ static int cik_startup(struct radeon_device *rdev)
+ /* type-2 packets are deprecated on MEC, use type-3 instead */
+ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
+- CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
+ PACKET3(PACKET3_NOP, 0x3FFF));
+ if (r)
+ return r;
+@@ -7079,7 +7107,6 @@ static int cik_startup(struct radeon_device *rdev)
+ /* type-2 packets are deprecated on MEC, use type-3 instead */
+ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
+- CP_HQD_PQ_RPTR, CP_HQD_PQ_WPTR,
+ PACKET3(PACKET3_NOP, 0x3FFF));
+ if (r)
+ return r;
+@@ -7091,16 +7118,12 @@ static int cik_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET,
+- SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET,
+ SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
+ if (r)
+ return r;
+
+ ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
+- SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET,
+- SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET,
+ SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0));
+ if (r)
+ return r;
+@@ -7116,7 +7139,6 @@ static int cik_startup(struct radeon_device *rdev)
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ if (ring->ring_size) {
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+- UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (!r)
+ r = uvd_v1_0_init(rdev);
+diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c
+index a589d79..f7c0b47 100644
+--- a/drivers/gpu/drm/radeon/cik_sdma.c
++++ b/drivers/gpu/drm/radeon/cik_sdma.c
+@@ -60,6 +60,75 @@ static void cik_sdma_hdp_flush(struct radeon_device *rdev,
+ }
+
+ /**
++ * cik_sdma_get_rptr - get the current read pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Get the current rptr from the hardware (CIK+).
++ */
++uint32_t cik_sdma_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr, reg;
++
++ if (rdev->wb.enabled) {
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ } else {
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET;
++ else
++ reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET;
++
++ rptr = RREG32(reg);
++ }
++
++ return (rptr & 0x3fffc) >> 2;
++}
++
++/**
++ * cik_sdma_get_wptr - get the current write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Get the current wptr from the hardware (CIK+).
++ */
++uint32_t cik_sdma_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 reg;
++
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
++ else
++ reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
++
++ return (RREG32(reg) & 0x3fffc) >> 2;
++}
++
++/**
++ * cik_sdma_set_wptr - commit the write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Write the wptr back to the hardware (CIK+).
++ */
++void cik_sdma_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 reg;
++
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET;
++ else
++ reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET;
++
++ WREG32(reg, (ring->wptr << 2) & 0x3fffc);
++}
++
++/**
+ * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine
+ *
+ * @rdev: radeon_device pointer
+diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
+index b5c67a9..491d048 100644
+--- a/drivers/gpu/drm/radeon/evergreen.c
++++ b/drivers/gpu/drm/radeon/evergreen.c
+@@ -5150,14 +5150,12 @@ static int evergreen_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- DMA_RB_RPTR, DMA_RB_WPTR,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0));
+ if (r)
+ return r;
+@@ -5175,7 +5173,6 @@ static int evergreen_startup(struct radeon_device *rdev)
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ if (ring->ring_size) {
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+- UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (!r)
+ r = uvd_v1_0_init(rdev);
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index ce87221..b684fd0 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -1401,6 +1401,55 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
+ }
+ }
+
++u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr;
++
++ if (rdev->wb.enabled)
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ else {
++ if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
++ rptr = RREG32(CP_RB0_RPTR);
++ else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
++ rptr = RREG32(CP_RB1_RPTR);
++ else
++ rptr = RREG32(CP_RB2_RPTR);
++ }
++
++ return rptr;
++}
++
++u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 wptr;
++
++ if (ring->idx == RADEON_RING_TYPE_GFX_INDEX)
++ wptr = RREG32(CP_RB0_WPTR);
++ else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX)
++ wptr = RREG32(CP_RB1_WPTR);
++ else
++ wptr = RREG32(CP_RB2_WPTR);
++
++ return wptr;
++}
++
++void cayman_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ if (ring->idx == RADEON_RING_TYPE_GFX_INDEX) {
++ WREG32(CP_RB0_WPTR, ring->wptr);
++ (void)RREG32(CP_RB0_WPTR);
++ } else if (ring->idx == CAYMAN_RING_TYPE_CP1_INDEX) {
++ WREG32(CP_RB1_WPTR, ring->wptr);
++ (void)RREG32(CP_RB1_WPTR);
++ } else {
++ WREG32(CP_RB2_WPTR, ring->wptr);
++ (void)RREG32(CP_RB2_WPTR);
++ }
++}
++
+ static int cayman_cp_load_microcode(struct radeon_device *rdev)
+ {
+ const __be32 *fw_data;
+@@ -1529,6 +1578,16 @@ static int cayman_cp_resume(struct radeon_device *rdev)
+ CP_RB1_BASE,
+ CP_RB2_BASE
+ };
++ static const unsigned cp_rb_rptr[] = {
++ CP_RB0_RPTR,
++ CP_RB1_RPTR,
++ CP_RB2_RPTR
++ };
++ static const unsigned cp_rb_wptr[] = {
++ CP_RB0_WPTR,
++ CP_RB1_WPTR,
++ CP_RB2_WPTR
++ };
+ struct radeon_ring *ring;
+ int i, r;
+
+@@ -1587,8 +1646,8 @@ static int cayman_cp_resume(struct radeon_device *rdev)
+ WREG32_P(cp_rb_cntl[i], RB_RPTR_WR_ENA, ~RB_RPTR_WR_ENA);
+
+ ring->rptr = ring->wptr = 0;
+- WREG32(ring->rptr_reg, ring->rptr);
+- WREG32(ring->wptr_reg, ring->wptr);
++ WREG32(cp_rb_rptr[i], ring->rptr);
++ WREG32(cp_rb_wptr[i], ring->wptr);
+
+ mdelay(1);
+ WREG32_P(cp_rb_cntl[i], 0, ~RB_RPTR_WR_ENA);
+@@ -1984,23 +2043,18 @@ static int cayman_startup(struct radeon_device *rdev)
+ evergreen_irq_set(rdev);
+
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- CP_RB0_RPTR, CP_RB0_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
+- DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
+ if (r)
+ return r;
+
+ ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
+- DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
+- DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
+ if (r)
+ return r;
+@@ -2019,7 +2073,6 @@ static int cayman_startup(struct radeon_device *rdev)
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ if (ring->ring_size) {
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+- UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (!r)
+ r = uvd_v1_0_init(rdev);
+diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c
+index bdeb65e..51424ab 100644
+--- a/drivers/gpu/drm/radeon/ni_dma.c
++++ b/drivers/gpu/drm/radeon/ni_dma.c
+@@ -43,6 +43,75 @@ u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev);
+ */
+
+ /**
++ * cayman_dma_get_rptr - get the current read pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Get the current rptr from the hardware (cayman+).
++ */
++uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr, reg;
++
++ if (rdev->wb.enabled) {
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ } else {
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = DMA_RB_RPTR + DMA0_REGISTER_OFFSET;
++ else
++ reg = DMA_RB_RPTR + DMA1_REGISTER_OFFSET;
++
++ rptr = RREG32(reg);
++ }
++
++ return (rptr & 0x3fffc) >> 2;
++}
++
++/**
++ * cayman_dma_get_wptr - get the current write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Get the current wptr from the hardware (cayman+).
++ */
++uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 reg;
++
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
++ else
++ reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
++
++ return (RREG32(reg) & 0x3fffc) >> 2;
++}
++
++/**
++ * cayman_dma_set_wptr - commit the write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon ring pointer
++ *
++ * Write the wptr back to the hardware (cayman+).
++ */
++void cayman_dma_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 reg;
++
++ if (ring->idx == R600_RING_TYPE_DMA_INDEX)
++ reg = DMA_RB_WPTR + DMA0_REGISTER_OFFSET;
++ else
++ reg = DMA_RB_WPTR + DMA1_REGISTER_OFFSET;
++
++ WREG32(reg, (ring->wptr << 2) & 0x3fffc);
++}
++
++/**
+ * cayman_dma_ring_ib_execute - Schedule an IB on the DMA engine
+ *
+ * @rdev: radeon_device pointer
+diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
+index aa015a5..39f6984 100644
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -1050,6 +1050,36 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
+ return err;
+ }
+
++u32 r100_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr;
++
++ if (rdev->wb.enabled)
++ rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
++ else
++ rptr = RREG32(RADEON_CP_RB_RPTR);
++
++ return rptr;
++}
++
++u32 r100_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 wptr;
++
++ wptr = RREG32(RADEON_CP_RB_WPTR);
++
++ return wptr;
++}
++
++void r100_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ WREG32(RADEON_CP_RB_WPTR, ring->wptr);
++ (void)RREG32(RADEON_CP_RB_WPTR);
++}
++
+ static void r100_cp_load_microcode(struct radeon_device *rdev)
+ {
+ const __be32 *fw_data;
+@@ -1102,7 +1132,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
+ ring_size = (1 << (rb_bufsz + 1)) * 4;
+ r100_cp_load_microcode(rdev);
+ r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (r) {
+ return r;
+diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
+index a5de2cf..5f52b50 100644
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -2329,6 +2329,36 @@ out:
+ return err;
+ }
+
++u32 r600_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 rptr;
++
++ if (rdev->wb.enabled)
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ else
++ rptr = RREG32(R600_CP_RB_RPTR);
++
++ return rptr;
++}
++
++u32 r600_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ u32 wptr;
++
++ wptr = RREG32(R600_CP_RB_WPTR);
++
++ return wptr;
++}
++
++void r600_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ WREG32(R600_CP_RB_WPTR, ring->wptr);
++ (void)RREG32(R600_CP_RB_WPTR);
++}
++
+ static int r600_cp_load_microcode(struct radeon_device *rdev)
+ {
+ const __be32 *fw_data;
+@@ -2773,14 +2803,12 @@ static int r600_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- DMA_RB_RPTR, DMA_RB_WPTR,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
+ if (r)
+ return r;
+diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c
+index 7844d15..3452c84 100644
+--- a/drivers/gpu/drm/radeon/r600_dma.c
++++ b/drivers/gpu/drm/radeon/r600_dma.c
+@@ -51,7 +51,14 @@ u32 r600_gpu_check_soft_reset(struct radeon_device *rdev);
+ uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
+ struct radeon_ring *ring)
+ {
+- return (radeon_ring_generic_get_rptr(rdev, ring) & 0x3fffc) >> 2;
++ u32 rptr;
++
++ if (rdev->wb.enabled)
++ rptr = rdev->wb.wb[ring->rptr_offs/4];
++ else
++ rptr = RREG32(DMA_RB_RPTR);
++
++ return (rptr & 0x3fffc) >> 2;
+ }
+
+ /**
+@@ -65,7 +72,7 @@ uint32_t r600_dma_get_rptr(struct radeon_device *rdev,
+ uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
+ struct radeon_ring *ring)
+ {
+- return (RREG32(ring->wptr_reg) & 0x3fffc) >> 2;
++ return (RREG32(DMA_RB_WPTR) & 0x3fffc) >> 2;
+ }
+
+ /**
+@@ -79,7 +86,7 @@ uint32_t r600_dma_get_wptr(struct radeon_device *rdev,
+ void r600_dma_set_wptr(struct radeon_device *rdev,
+ struct radeon_ring *ring)
+ {
+- WREG32(ring->wptr_reg, (ring->wptr << 2) & 0x3fffc);
++ WREG32(DMA_RB_WPTR, (ring->wptr << 2) & 0x3fffc);
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 5331fc2..fb7323d 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -782,13 +782,11 @@ struct radeon_ring {
+ volatile uint32_t *ring;
+ unsigned rptr;
+ unsigned rptr_offs;
+- unsigned rptr_reg;
+ unsigned rptr_save_reg;
+ u64 next_rptr_gpu_addr;
+ volatile u32 *next_rptr_cpu_addr;
+ unsigned wptr;
+ unsigned wptr_old;
+- unsigned wptr_reg;
+ unsigned ring_size;
+ unsigned ring_free_dw;
+ int count_dw;
+@@ -960,7 +958,7 @@ unsigned radeon_ring_backup(struct radeon_device *rdev, struct radeon_ring *ring
+ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
+ unsigned size, uint32_t *data);
+ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ring_size,
+- unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop);
++ unsigned rptr_offs, u32 nop);
+ void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *cp);
+
+
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
+index 123adfe..a539869 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.c
++++ b/drivers/gpu/drm/radeon/radeon_asic.c
+@@ -182,9 +182,9 @@ static struct radeon_asic_ring r100_gfx_ring = {
+ .ring_test = &r100_ring_test,
+ .ib_test = &r100_ib_test,
+ .is_lockup = &r100_gpu_is_lockup,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &r100_gfx_get_rptr,
++ .get_wptr = &r100_gfx_get_wptr,
++ .set_wptr = &r100_gfx_set_wptr,
+ };
+
+ static struct radeon_asic r100_asic = {
+@@ -330,9 +330,9 @@ static struct radeon_asic_ring r300_gfx_ring = {
+ .ring_test = &r100_ring_test,
+ .ib_test = &r100_ib_test,
+ .is_lockup = &r100_gpu_is_lockup,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &r100_gfx_get_rptr,
++ .get_wptr = &r100_gfx_get_wptr,
++ .set_wptr = &r100_gfx_set_wptr,
+ };
+
+ static struct radeon_asic r300_asic = {
+@@ -883,9 +883,9 @@ static struct radeon_asic_ring r600_gfx_ring = {
+ .ring_test = &r600_ring_test,
+ .ib_test = &r600_ib_test,
+ .is_lockup = &r600_gfx_is_lockup,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &r600_gfx_get_rptr,
++ .get_wptr = &r600_gfx_get_wptr,
++ .set_wptr = &r600_gfx_set_wptr,
+ };
+
+ static struct radeon_asic_ring r600_dma_ring = {
+@@ -1267,9 +1267,9 @@ static struct radeon_asic_ring evergreen_gfx_ring = {
+ .ring_test = &r600_ring_test,
+ .ib_test = &r600_ib_test,
+ .is_lockup = &evergreen_gfx_is_lockup,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &r600_gfx_get_rptr,
++ .get_wptr = &r600_gfx_get_wptr,
++ .set_wptr = &r600_gfx_set_wptr,
+ };
+
+ static struct radeon_asic_ring evergreen_dma_ring = {
+@@ -1570,9 +1570,9 @@ static struct radeon_asic_ring cayman_gfx_ring = {
+ .ib_test = &r600_ib_test,
+ .is_lockup = &cayman_gfx_is_lockup,
+ .vm_flush = &cayman_vm_flush,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &cayman_gfx_get_rptr,
++ .get_wptr = &cayman_gfx_get_wptr,
++ .set_wptr = &cayman_gfx_set_wptr,
+ };
+
+ static struct radeon_asic_ring cayman_dma_ring = {
+@@ -1585,9 +1585,9 @@ static struct radeon_asic_ring cayman_dma_ring = {
+ .ib_test = &r600_dma_ib_test,
+ .is_lockup = &cayman_dma_is_lockup,
+ .vm_flush = &cayman_dma_vm_flush,
+- .get_rptr = &r600_dma_get_rptr,
+- .get_wptr = &r600_dma_get_wptr,
+- .set_wptr = &r600_dma_set_wptr
++ .get_rptr = &cayman_dma_get_rptr,
++ .get_wptr = &cayman_dma_get_wptr,
++ .set_wptr = &cayman_dma_set_wptr
+ };
+
+ static struct radeon_asic_ring cayman_uvd_ring = {
+@@ -1813,9 +1813,9 @@ static struct radeon_asic_ring si_gfx_ring = {
+ .ib_test = &r600_ib_test,
+ .is_lockup = &si_gfx_is_lockup,
+ .vm_flush = &si_vm_flush,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &cayman_gfx_get_rptr,
++ .get_wptr = &cayman_gfx_get_wptr,
++ .set_wptr = &cayman_gfx_set_wptr,
+ };
+
+ static struct radeon_asic_ring si_dma_ring = {
+@@ -1828,9 +1828,9 @@ static struct radeon_asic_ring si_dma_ring = {
+ .ib_test = &r600_dma_ib_test,
+ .is_lockup = &si_dma_is_lockup,
+ .vm_flush = &si_dma_vm_flush,
+- .get_rptr = &r600_dma_get_rptr,
+- .get_wptr = &r600_dma_get_wptr,
+- .set_wptr = &r600_dma_set_wptr,
++ .get_rptr = &cayman_dma_get_rptr,
++ .get_wptr = &cayman_dma_get_wptr,
++ .set_wptr = &cayman_dma_set_wptr,
+ };
+
+ static struct radeon_asic si_asic = {
+@@ -1943,9 +1943,9 @@ static struct radeon_asic_ring ci_gfx_ring = {
+ .ib_test = &cik_ib_test,
+ .is_lockup = &cik_gfx_is_lockup,
+ .vm_flush = &cik_vm_flush,
+- .get_rptr = &radeon_ring_generic_get_rptr,
+- .get_wptr = &radeon_ring_generic_get_wptr,
+- .set_wptr = &radeon_ring_generic_set_wptr,
++ .get_rptr = &cik_gfx_get_rptr,
++ .get_wptr = &cik_gfx_get_wptr,
++ .set_wptr = &cik_gfx_set_wptr,
+ };
+
+ static struct radeon_asic_ring ci_cp_ring = {
+@@ -1958,9 +1958,9 @@ static struct radeon_asic_ring ci_cp_ring = {
+ .ib_test = &cik_ib_test,
+ .is_lockup = &cik_gfx_is_lockup,
+ .vm_flush = &cik_vm_flush,
+- .get_rptr = &cik_compute_ring_get_rptr,
+- .get_wptr = &cik_compute_ring_get_wptr,
+- .set_wptr = &cik_compute_ring_set_wptr,
++ .get_rptr = &cik_compute_get_rptr,
++ .get_wptr = &cik_compute_get_wptr,
++ .set_wptr = &cik_compute_set_wptr,
+ };
+
+ static struct radeon_asic_ring ci_dma_ring = {
+@@ -1973,9 +1973,9 @@ static struct radeon_asic_ring ci_dma_ring = {
+ .ib_test = &cik_sdma_ib_test,
+ .is_lockup = &cik_sdma_is_lockup,
+ .vm_flush = &cik_dma_vm_flush,
+- .get_rptr = &r600_dma_get_rptr,
+- .get_wptr = &r600_dma_get_wptr,
+- .set_wptr = &r600_dma_set_wptr,
++ .get_rptr = &cik_sdma_get_rptr,
++ .get_wptr = &cik_sdma_get_wptr,
++ .set_wptr = &cik_sdma_set_wptr,
+ };
+
+ static struct radeon_asic ci_asic = {
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
+index 8939cb3..998042e 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.h
++++ b/drivers/gpu/drm/radeon/radeon_asic.h
+@@ -47,13 +47,6 @@ u8 atombios_get_backlight_level(struct radeon_encoder *radeon_encoder);
+ void radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level);
+ u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder);
+
+-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
+-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
+-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
+-
+ /*
+ * r100,rv100,rs100,rv200,rs200
+ */
+@@ -148,6 +141,13 @@ extern void r100_post_page_flip(struct radeon_device *rdev, int crtc);
+ extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
+ extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
+
++u32 r100_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 r100_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void r100_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++
+ /*
+ * r200,rv250,rs300,rv280
+ */
+@@ -368,6 +368,12 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev);
+ int r600_pcie_gart_init(struct radeon_device *rdev);
+ void r600_scratch_init(struct radeon_device *rdev);
+ int r600_init_microcode(struct radeon_device *rdev);
++u32 r600_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 r600_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void r600_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
+ /* r600 irq */
+ int r600_irq_process(struct radeon_device *rdev);
+ int r600_irq_init(struct radeon_device *rdev);
+@@ -591,6 +597,19 @@ void cayman_dma_vm_set_page(struct radeon_device *rdev,
+
+ void cayman_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+
++u32 cayman_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cayman_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void cayman_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++uint32_t cayman_dma_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++uint32_t cayman_dma_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void cayman_dma_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++
+ int ni_dpm_init(struct radeon_device *rdev);
+ void ni_dpm_setup_asic(struct radeon_device *rdev);
+ int ni_dpm_enable(struct radeon_device *rdev);
+@@ -735,12 +754,24 @@ void cik_sdma_vm_set_page(struct radeon_device *rdev,
+ uint32_t incr, uint32_t flags);
+ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm);
+ int cik_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+-u32 cik_compute_ring_get_rptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
+-u32 cik_compute_ring_get_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
+-void cik_compute_ring_set_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring);
++u32 cik_gfx_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cik_gfx_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void cik_gfx_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cik_compute_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cik_compute_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void cik_compute_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cik_sdma_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++u32 cik_sdma_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void cik_sdma_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
+ int ci_get_temp(struct radeon_device *rdev);
+ int kv_get_temp(struct radeon_device *rdev);
+
+diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
+index f1cec22..65f1cea 100644
+--- a/drivers/gpu/drm/radeon/radeon_ring.c
++++ b/drivers/gpu/drm/radeon/radeon_ring.c
+@@ -332,36 +332,6 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
+ }
+ }
+
+-u32 radeon_ring_generic_get_rptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
+-{
+- u32 rptr;
+-
+- if (rdev->wb.enabled)
+- rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]);
+- else
+- rptr = RREG32(ring->rptr_reg);
+-
+- return rptr;
+-}
+-
+-u32 radeon_ring_generic_get_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
+-{
+- u32 wptr;
+-
+- wptr = RREG32(ring->wptr_reg);
+-
+- return wptr;
+-}
+-
+-void radeon_ring_generic_set_wptr(struct radeon_device *rdev,
+- struct radeon_ring *ring)
+-{
+- WREG32(ring->wptr_reg, ring->wptr);
+- (void)RREG32(ring->wptr_reg);
+-}
+-
+ /**
+ * radeon_ring_free_size - update the free size
+ *
+@@ -689,22 +659,18 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring,
+ * @ring: radeon_ring structure holding ring information
+ * @ring_size: size of the ring
+ * @rptr_offs: offset of the rptr writeback location in the WB buffer
+- * @rptr_reg: MMIO offset of the rptr register
+- * @wptr_reg: MMIO offset of the wptr register
+ * @nop: nop packet for this ring
+ *
+ * Initialize the driver information for the selected ring (all asics).
+ * Returns 0 on success, error on failure.
+ */
+ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size,
+- unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, u32 nop)
++ unsigned rptr_offs, u32 nop)
+ {
+ int r;
+
+ ring->ring_size = ring_size;
+ ring->rptr_offs = rptr_offs;
+- ring->rptr_reg = rptr_reg;
+- ring->wptr_reg = wptr_reg;
+ ring->nop = nop;
+ /* Allocate ring buffer */
+ if (ring->ring_obj == NULL) {
+@@ -798,12 +764,12 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data)
+ count = (ring->ring_size / 4) - ring->ring_free_dw;
+
+ wptr = radeon_ring_get_wptr(rdev, ring);
+- seq_printf(m, "wptr(0x%04x): 0x%08x [%5d]\n",
+- ring->wptr_reg, wptr, wptr);
++ seq_printf(m, "wptr: 0x%08x [%5d]\n",
++ wptr, wptr);
+
+ rptr = radeon_ring_get_rptr(rdev, ring);
+- seq_printf(m, "rptr(0x%04x): 0x%08x [%5d]\n",
+- ring->rptr_reg, rptr, rptr);
++ seq_printf(m, "rptr: 0x%08x [%5d]\n",
++ rptr, rptr);
+
+ if (ring->rptr_save_reg) {
+ rptr_next = RREG32(ring->rptr_save_reg);
+diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
+index 9f58467..6cce0de 100644
+--- a/drivers/gpu/drm/radeon/rv770.c
++++ b/drivers/gpu/drm/radeon/rv770.c
+@@ -1728,14 +1728,12 @@ static int rv770_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- R600_CP_RB_RPTR, R600_CP_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- DMA_RB_RPTR, DMA_RB_WPTR,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
+ if (r)
+ return r;
+@@ -1754,7 +1752,6 @@ static int rv770_startup(struct radeon_device *rdev)
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ if (ring->ring_size) {
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+- UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (!r)
+ r = uvd_v1_0_init(rdev);
+diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
+index a7c53b7..8576a6f 100644
+--- a/drivers/gpu/drm/radeon/si.c
++++ b/drivers/gpu/drm/radeon/si.c
+@@ -6424,37 +6424,30 @@ static int si_startup(struct radeon_device *rdev)
+
+ ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
+- CP_RB0_RPTR, CP_RB0_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[CAYMAN_RING_TYPE_CP1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP1_RPTR_OFFSET,
+- CP_RB1_RPTR, CP_RB1_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP2_RPTR_OFFSET,
+- CP_RB2_RPTR, CP_RB2_WPTR,
+ RADEON_CP_PACKET2);
+ if (r)
+ return r;
+
+ ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
+- DMA_RB_RPTR + DMA0_REGISTER_OFFSET,
+- DMA_RB_WPTR + DMA0_REGISTER_OFFSET,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
+ if (r)
+ return r;
+
+ ring = &rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX];
+ r = radeon_ring_init(rdev, ring, ring->ring_size, CAYMAN_WB_DMA1_RPTR_OFFSET,
+- DMA_RB_RPTR + DMA1_REGISTER_OFFSET,
+- DMA_RB_WPTR + DMA1_REGISTER_OFFSET,
+ DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0));
+ if (r)
+ return r;
+@@ -6474,7 +6467,6 @@ static int si_startup(struct radeon_device *rdev)
+ ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+ if (ring->ring_size) {
+ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
+- UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
+ RADEON_CP_PACKET2);
+ if (!r)
+ r = uvd_v1_0_init(rdev);
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch
new file mode 100644
index 00000000..e64abef2
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch
@@ -0,0 +1,1434 @@
+From 5890ab59e66a268c7910a7a5ad939107fa1b8a1d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Thu, 23 May 2013 12:10:04 +0200
+Subject: [PATCH 27/44] drm/radeon: initial VCE support v4
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Only VCE 2.0 support so far.
+
+v2: squashing multiple patches into this one
+v3: add IRQ support for CIK, major cleanups,
+ basic code documentation
+v4: remove HAINAN from chipset list
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/Makefile | 6 +
+ drivers/gpu/drm/radeon/cik.c | 60 ++++
+ drivers/gpu/drm/radeon/cikd.h | 33 ++
+ drivers/gpu/drm/radeon/radeon.h | 56 +++-
+ drivers/gpu/drm/radeon/radeon_asic.c | 17 +
+ drivers/gpu/drm/radeon/radeon_asic.h | 13 +
+ drivers/gpu/drm/radeon/radeon_cs.c | 4 +
+ drivers/gpu/drm/radeon/radeon_kms.c | 1 +
+ drivers/gpu/drm/radeon/radeon_ring.c | 4 +
+ drivers/gpu/drm/radeon/radeon_test.c | 39 ++-
+ drivers/gpu/drm/radeon/radeon_vce.c | 588 ++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/sid.h | 47 +++
+ drivers/gpu/drm/radeon/vce_v1_0.c | 187 +++++++++++
+ drivers/gpu/drm/radeon/vce_v2_0.c | 70 ++++
+ include/uapi/drm/radeon_drm.h | 1 +
+ 15 files changed, 1117 insertions(+), 9 deletions(-)
+ create mode 100644 drivers/gpu/drm/radeon/radeon_vce.c
+ create mode 100644 drivers/gpu/drm/radeon/vce_v1_0.c
+ create mode 100644 drivers/gpu/drm/radeon/vce_v2_0.c
+
+diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
+index 306364a..ed60caa 100644
+--- a/drivers/gpu/drm/radeon/Makefile
++++ b/drivers/gpu/drm/radeon/Makefile
+@@ -99,6 +99,12 @@ radeon-y += \
+ uvd_v3_1.o \
+ uvd_v4_2.o
+
++# add VCE block
++radeon-y += \
++ radeon_vce.o \
++ vce_v1_0.o \
++ vce_v2_0.o \
++
+ radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
+ radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
+ radeon-$(CONFIG_ACPI) += radeon_acpi.o
+diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
+index 4a89b5c..872b146 100644
+--- a/drivers/gpu/drm/radeon/cik.c
++++ b/drivers/gpu/drm/radeon/cik.c
+@@ -6753,6 +6753,20 @@ restart_ih:
+ /* reset addr and status */
+ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
+ break;
++ case 167: /* VCE */
++ DRM_DEBUG("IH: VCE int: 0x%08x\n", src_data);
++ switch (src_data) {
++ case 0:
++ radeon_fence_process(rdev, TN_RING_TYPE_VCE1_INDEX);
++ break;
++ case 1:
++ radeon_fence_process(rdev, TN_RING_TYPE_VCE2_INDEX);
++ break;
++ default:
++ DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
++ break;
++ }
++ break;
+ case 176: /* GFX RB CP_INT */
+ case 177: /* GFX IB CP_INT */
+ radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
+@@ -7071,6 +7085,22 @@ static int cik_startup(struct radeon_device *rdev)
+ if (r)
+ rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+
++ r = radeon_vce_resume(rdev);
++ if (!r) {
++ r = vce_v2_0_resume(rdev);
++ if (!r)
++ r = radeon_fence_driver_start_ring(rdev,
++ TN_RING_TYPE_VCE1_INDEX);
++ if (!r)
++ r = radeon_fence_driver_start_ring(rdev,
++ TN_RING_TYPE_VCE2_INDEX);
++ }
++ if (r) {
++ dev_err(rdev->dev, "VCE init error (%d).\n", r);
++ rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
++ rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
++ }
++
+ /* Enable IRQ */
+ if (!rdev->irq.installed) {
+ r = radeon_irq_kms_init(rdev);
+@@ -7146,6 +7176,23 @@ static int cik_startup(struct radeon_device *rdev)
+ DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
+ }
+
++ r = -ENOENT;
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
++ if (ring->ring_size)
++ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
++ VCE_CMD_NO_OP);
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
++ if (ring->ring_size)
++ r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
++ VCE_CMD_NO_OP);
++
++ if (!r)
++ r = vce_v1_0_init(rdev);
++ else if (r != -ENOENT)
++ DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
++
+ r = radeon_ib_pool_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
+@@ -7213,6 +7260,7 @@ int cik_suspend(struct radeon_device *rdev)
+ cik_sdma_enable(rdev, false);
+ uvd_v1_0_fini(rdev);
+ radeon_uvd_suspend(rdev);
++ radeon_vce_suspend(rdev);
+ cik_fini_pg(rdev);
+ cik_fini_cg(rdev);
+ cik_irq_suspend(rdev);
+@@ -7321,6 +7369,17 @@ int cik_init(struct radeon_device *rdev)
+ r600_ring_init(rdev, ring, 4096);
+ }
+
++ r = radeon_vce_init(rdev);
++ if (!r) {
++ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
++ ring->ring_obj = NULL;
++ r600_ring_init(rdev, ring, 4096);
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
++ ring->ring_obj = NULL;
++ r600_ring_init(rdev, ring, 4096);
++ }
++
+ rdev->ih.ring_obj = NULL;
+ r600_ih_ring_init(rdev, 64 * 1024);
+
+@@ -7381,6 +7440,7 @@ void cik_fini(struct radeon_device *rdev)
+ radeon_irq_kms_fini(rdev);
+ uvd_v1_0_fini(rdev);
+ radeon_uvd_fini(rdev);
++ radeon_vce_fini(rdev);
+ cik_pcie_gart_fini(rdev);
+ r600_vram_scratch_fini(rdev);
+ radeon_gem_fini(rdev);
+diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
+index 7a0a0d2..b296d50 100644
+--- a/drivers/gpu/drm/radeon/cikd.h
++++ b/drivers/gpu/drm/radeon/cikd.h
+@@ -1899,4 +1899,37 @@
+ /* UVD CTX indirect */
+ #define UVD_CGC_MEM_CTRL 0xC0
+
++/* VCE */
++
++#define VCE_VCPU_CACHE_OFFSET0 0x20024
++#define VCE_VCPU_CACHE_SIZE0 0x20028
++#define VCE_VCPU_CACHE_OFFSET1 0x2002c
++#define VCE_VCPU_CACHE_SIZE1 0x20030
++#define VCE_VCPU_CACHE_OFFSET2 0x20034
++#define VCE_VCPU_CACHE_SIZE2 0x20038
++#define VCE_RB_RPTR2 0x20178
++#define VCE_RB_WPTR2 0x2017c
++#define VCE_RB_RPTR 0x2018c
++#define VCE_RB_WPTR 0x20190
++#define VCE_CLOCK_GATING_A 0x202f8
++#define VCE_CLOCK_GATING_B 0x202fc
++#define VCE_UENC_CLOCK_GATING 0x207bc
++#define VCE_UENC_REG_CLOCK_GATING 0x207c0
++#define VCE_SYS_INT_EN 0x21300
++# define VCE_SYS_INT_TRAP_INTERRUPT_EN (1 << 3)
++#define VCE_LMI_CTRL2 0x21474
++#define VCE_LMI_CTRL 0x21498
++#define VCE_LMI_VM_CTRL 0x214a0
++#define VCE_LMI_SWAP_CNTL 0x214b4
++#define VCE_LMI_SWAP_CNTL1 0x214b8
++#define VCE_LMI_CACHE_CTRL 0x214f4
++
++#define VCE_CMD_NO_OP 0x00000000
++#define VCE_CMD_END 0x00000001
++#define VCE_CMD_IB 0x00000002
++#define VCE_CMD_FENCE 0x00000003
++#define VCE_CMD_TRAP 0x00000004
++#define VCE_CMD_IB_AUTO 0x00000005
++#define VCE_CMD_SEMAPHORE 0x00000006
++
+ #endif
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index fb7323d..094e5f5 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -111,19 +111,16 @@ extern int radeon_aspm;
+ #define RADEONFB_CONN_LIMIT 4
+ #define RADEON_BIOS_NUM_SCRATCH 8
+
+-/* max number of rings */
+-#define RADEON_NUM_RINGS 6
+-
+ /* fence seq are set to this number when signaled */
+ #define RADEON_FENCE_SIGNALED_SEQ 0LL
+
+ /* internal ring indices */
+ /* r1xx+ has gfx CP ring */
+-#define RADEON_RING_TYPE_GFX_INDEX 0
++#define RADEON_RING_TYPE_GFX_INDEX 0
+
+ /* cayman has 2 compute CP rings */
+-#define CAYMAN_RING_TYPE_CP1_INDEX 1
+-#define CAYMAN_RING_TYPE_CP2_INDEX 2
++#define CAYMAN_RING_TYPE_CP1_INDEX 1
++#define CAYMAN_RING_TYPE_CP2_INDEX 2
+
+ /* R600+ has an async dma ring */
+ #define R600_RING_TYPE_DMA_INDEX 3
+@@ -131,7 +128,14 @@ extern int radeon_aspm;
+ #define CAYMAN_RING_TYPE_DMA1_INDEX 4
+
+ /* R600+ */
+-#define R600_RING_TYPE_UVD_INDEX 5
++#define R600_RING_TYPE_UVD_INDEX 5
++
++/* TN+ */
++#define TN_RING_TYPE_VCE1_INDEX 6
++#define TN_RING_TYPE_VCE2_INDEX 7
++
++/* max number of rings */
++#define RADEON_NUM_RINGS 8
+
+ /* hardcode those limit for now */
+ #define RADEON_VA_IB_OFFSET (1 << 20)
+@@ -1586,6 +1590,42 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
+ int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
+ unsigned cg_upll_func_cntl);
+
++/*
++ * VCE
++ */
++#define RADEON_MAX_VCE_HANDLES 16
++#define RADEON_VCE_STACK_SIZE (1024*1024)
++#define RADEON_VCE_HEAP_SIZE (4*1024*1024)
++
++struct radeon_vce {
++ struct radeon_bo *vcpu_bo;
++ void *cpu_addr;
++ uint64_t gpu_addr;
++ atomic_t handles[RADEON_MAX_VCE_HANDLES];
++ struct drm_file *filp[RADEON_MAX_VCE_HANDLES];
++};
++
++int radeon_vce_init(struct radeon_device *rdev);
++void radeon_vce_fini(struct radeon_device *rdev);
++int radeon_vce_suspend(struct radeon_device *rdev);
++int radeon_vce_resume(struct radeon_device *rdev);
++int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
++ uint32_t handle, struct radeon_fence **fence);
++int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
++ uint32_t handle, struct radeon_fence **fence);
++void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
++int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
++int radeon_vce_cs_parse(struct radeon_cs_parser *p);
++bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
++ struct radeon_ring *ring,
++ struct radeon_semaphore *semaphore,
++ bool emit_wait);
++void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
++void radeon_vce_fence_emit(struct radeon_device *rdev,
++ struct radeon_fence *fence);
++int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
++int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
++
+ struct r600_audio_pin {
+ int channels;
+ int rate;
+@@ -2180,6 +2220,7 @@ struct radeon_device {
+ struct radeon_gem gem;
+ struct radeon_pm pm;
+ struct radeon_uvd uvd;
++ struct radeon_vce vce;
+ uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH];
+ struct radeon_wb wb;
+ struct radeon_dummy_page dummy_page;
+@@ -2198,6 +2239,7 @@ struct radeon_device {
+ const struct firmware *sdma_fw; /* CIK SDMA firmware */
+ const struct firmware *smc_fw; /* SMC firmware */
+ const struct firmware *uvd_fw; /* UVD firmware */
++ const struct firmware *vce_fw; /* VCE firmware */
+ struct r600_vram_scratch vram_scratch;
+ int msi_enabled; /* msi enabled */
+ struct r600_ih ih; /* r6/700 interrupt ring */
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
+index a539869..763280b 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.c
++++ b/drivers/gpu/drm/radeon/radeon_asic.c
+@@ -1978,6 +1978,19 @@ static struct radeon_asic_ring ci_dma_ring = {
+ .set_wptr = &cik_sdma_set_wptr,
+ };
+
++static struct radeon_asic_ring ci_vce_ring = {
++ .ib_execute = &radeon_vce_ib_execute,
++ .emit_fence = &radeon_vce_fence_emit,
++ .emit_semaphore = &radeon_vce_semaphore_emit,
++ .cs_parse = &radeon_vce_cs_parse,
++ .ring_test = &radeon_vce_ring_test,
++ .ib_test = &radeon_vce_ib_test,
++ .is_lockup = &radeon_ring_test_lockup,
++ .get_rptr = &vce_v1_0_get_rptr,
++ .get_wptr = &vce_v1_0_get_wptr,
++ .set_wptr = &vce_v1_0_set_wptr,
++};
++
+ static struct radeon_asic ci_asic = {
+ .init = &cik_init,
+ .fini = &cik_fini,
+@@ -2006,6 +2019,8 @@ static struct radeon_asic ci_asic = {
+ [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
+ [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
+ [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
++ [TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
++ [TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
+ },
+ .irq = {
+ .set = &cik_irq_set,
+@@ -2107,6 +2122,8 @@ static struct radeon_asic kv_asic = {
+ [R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
+ [CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
+ [R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
++ [TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
++ [TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
+ },
+ .irq = {
+ .set = &cik_irq_set,
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
+index 998042e..a6c3eeb 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.h
++++ b/drivers/gpu/drm/radeon/radeon_asic.h
+@@ -850,4 +850,17 @@ bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
+ /* uvd v4.2 */
+ int uvd_v4_2_resume(struct radeon_device *rdev);
+
++/* vce v1.0 */
++uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++void vce_v1_0_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring);
++int vce_v1_0_init(struct radeon_device *rdev);
++int vce_v1_0_start(struct radeon_device *rdev);
++
++/* vce v2.0 */
++int vce_v2_0_resume(struct radeon_device *rdev);
++
+ #endif
+diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
+index 83731ff..2f8e92b 100644
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -147,6 +147,10 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority
+ case RADEON_CS_RING_UVD:
+ p->ring = R600_RING_TYPE_UVD_INDEX;
+ break;
++ case RADEON_CS_RING_VCE:
++ /* TODO: only use the low priority ring for now */
++ p->ring = TN_RING_TYPE_VCE1_INDEX;
++ break;
+ }
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 5d67422..07da88f 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -579,6 +579,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
+ if (rdev->cmask_filp == file_priv)
+ rdev->cmask_filp = NULL;
+ radeon_uvd_free_handles(rdev, file_priv);
++ radeon_vce_free_handles(rdev, file_priv);
+ }
+
+ /*
+diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
+index 65f1cea..91457f8 100644
+--- a/drivers/gpu/drm/radeon/radeon_ring.c
++++ b/drivers/gpu/drm/radeon/radeon_ring.c
+@@ -814,6 +814,8 @@ static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX;
+ static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX;
+ static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX;
+ static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX;
++static int si_vce1_index = TN_RING_TYPE_VCE1_INDEX;
++static int si_vce2_index = TN_RING_TYPE_VCE2_INDEX;
+
+ static struct drm_info_list radeon_debugfs_ring_info_list[] = {
+ {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index},
+@@ -822,6 +824,8 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = {
+ {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index},
+ {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index},
+ {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index},
++ {"radeon_ring_vce1", radeon_debugfs_ring_info, 0, &si_vce1_index},
++ {"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index},
+ };
+
+ static int radeon_debugfs_sa_info(struct seq_file *m, void *data)
+diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
+index 12e8099..3a13e0d 100644
+--- a/drivers/gpu/drm/radeon/radeon_test.c
++++ b/drivers/gpu/drm/radeon/radeon_test.c
+@@ -257,20 +257,36 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_fence **fence)
+ {
++ uint32_t handle = ring->idx ^ 0xdeafbeef;
+ int r;
+
+ if (ring->idx == R600_RING_TYPE_UVD_INDEX) {
+- r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL);
++ r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL);
+ if (r) {
+ DRM_ERROR("Failed to get dummy create msg\n");
+ return r;
+ }
+
+- r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence);
++ r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence);
+ if (r) {
+ DRM_ERROR("Failed to get dummy destroy msg\n");
+ return r;
+ }
++
++ } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX ||
++ ring->idx == TN_RING_TYPE_VCE2_INDEX) {
++ r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL);
++ if (r) {
++ DRM_ERROR("Failed to get dummy create msg\n");
++ return r;
++ }
++
++ r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence);
++ if (r) {
++ DRM_ERROR("Failed to get dummy destroy msg\n");
++ return r;
++ }
++
+ } else {
+ r = radeon_ring_lock(rdev, ring, 64);
+ if (r) {
+@@ -486,6 +502,16 @@ out_cleanup:
+ printk(KERN_WARNING "Error while testing ring sync (%d).\n", r);
+ }
+
++static bool radeon_test_sync_possible(struct radeon_ring *ringA,
++ struct radeon_ring *ringB)
++{
++ if (ringA->idx == TN_RING_TYPE_VCE2_INDEX &&
++ ringB->idx == TN_RING_TYPE_VCE1_INDEX)
++ return false;
++
++ return true;
++}
++
+ void radeon_test_syncing(struct radeon_device *rdev)
+ {
+ int i, j, k;
+@@ -500,6 +526,9 @@ void radeon_test_syncing(struct radeon_device *rdev)
+ if (!ringB->ready)
+ continue;
+
++ if (!radeon_test_sync_possible(ringA, ringB))
++ continue;
++
+ DRM_INFO("Testing syncing between rings %d and %d...\n", i, j);
+ radeon_test_ring_sync(rdev, ringA, ringB);
+
+@@ -511,6 +540,12 @@ void radeon_test_syncing(struct radeon_device *rdev)
+ if (!ringC->ready)
+ continue;
+
++ if (!radeon_test_sync_possible(ringA, ringC))
++ continue;
++
++ if (!radeon_test_sync_possible(ringB, ringC))
++ continue;
++
+ DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k);
+ radeon_test_ring_sync2(rdev, ringA, ringB, ringC);
+
+diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
+new file mode 100644
+index 0000000..2547d8e
+--- /dev/null
++++ b/drivers/gpu/drm/radeon/radeon_vce.c
+@@ -0,0 +1,588 @@
++/*
++ * Copyright 2013 Advanced Micro Devices, Inc.
++ * 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.
++ *
++ * Authors: Christian König <christian.koenig@amd.com>
++ */
++
++#include <linux/firmware.h>
++#include <linux/module.h>
++#include <drm/drmP.h>
++#include <drm/drm.h>
++
++#include "radeon.h"
++#include "radeon_asic.h"
++#include "sid.h"
++
++/* Firmware Names */
++#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin"
++
++MODULE_FIRMWARE(FIRMWARE_BONAIRE);
++
++/**
++ * radeon_vce_init - allocate memory, load vce firmware
++ *
++ * @rdev: radeon_device pointer
++ *
++ * First step to get VCE online, allocate memory and load the firmware
++ */
++int radeon_vce_init(struct radeon_device *rdev)
++{
++ unsigned long bo_size;
++ const char *fw_name;
++ int i, r;
++
++ switch (rdev->family) {
++ case CHIP_BONAIRE:
++ case CHIP_KAVERI:
++ case CHIP_KABINI:
++ fw_name = FIRMWARE_BONAIRE;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ r = request_firmware(&rdev->vce_fw, fw_name, rdev->dev);
++ if (r) {
++ dev_err(rdev->dev, "radeon_vce: Can't load firmware \"%s\"\n",
++ fw_name);
++ return r;
++ }
++
++ bo_size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
++ RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
++ r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
++ RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
++ if (r) {
++ dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
++ return r;
++ }
++
++ r = radeon_vce_resume(rdev);
++ if (r)
++ return r;
++
++ memset(rdev->vce.cpu_addr, 0, bo_size);
++ memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
++
++ r = radeon_vce_suspend(rdev);
++ if (r)
++ return r;
++
++ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
++ atomic_set(&rdev->vce.handles[i], 0);
++ rdev->vce.filp[i] = NULL;
++ }
++
++ return 0;
++}
++
++/**
++ * radeon_vce_fini - free memory
++ *
++ * @rdev: radeon_device pointer
++ *
++ * Last step on VCE teardown, free firmware memory
++ */
++void radeon_vce_fini(struct radeon_device *rdev)
++{
++ radeon_vce_suspend(rdev);
++ radeon_bo_unref(&rdev->vce.vcpu_bo);
++}
++
++/**
++ * radeon_vce_suspend - unpin VCE fw memory
++ *
++ * @rdev: radeon_device pointer
++ *
++ * TODO: Test VCE suspend/resume
++ */
++int radeon_vce_suspend(struct radeon_device *rdev)
++{
++ int r;
++
++ if (rdev->vce.vcpu_bo == NULL)
++ return 0;
++
++ r = radeon_bo_reserve(rdev->vce.vcpu_bo, false);
++ if (!r) {
++ radeon_bo_kunmap(rdev->vce.vcpu_bo);
++ radeon_bo_unpin(rdev->vce.vcpu_bo);
++ radeon_bo_unreserve(rdev->vce.vcpu_bo);
++ }
++ return r;
++}
++
++/**
++ * radeon_vce_resume - pin VCE fw memory
++ *
++ * @rdev: radeon_device pointer
++ *
++ * TODO: Test VCE suspend/resume
++ */
++int radeon_vce_resume(struct radeon_device *rdev)
++{
++ int r;
++
++ if (rdev->vce.vcpu_bo == NULL)
++ return -EINVAL;
++
++ r = radeon_bo_reserve(rdev->vce.vcpu_bo, false);
++ if (r) {
++ radeon_bo_unref(&rdev->vce.vcpu_bo);
++ dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r);
++ return r;
++ }
++
++ r = radeon_bo_pin(rdev->vce.vcpu_bo, RADEON_GEM_DOMAIN_VRAM,
++ &rdev->vce.gpu_addr);
++ if (r) {
++ radeon_bo_unreserve(rdev->vce.vcpu_bo);
++ radeon_bo_unref(&rdev->vce.vcpu_bo);
++ dev_err(rdev->dev, "(%d) VCE bo pin failed\n", r);
++ return r;
++ }
++
++ r = radeon_bo_kmap(rdev->vce.vcpu_bo, &rdev->vce.cpu_addr);
++ if (r) {
++ dev_err(rdev->dev, "(%d) VCE map failed\n", r);
++ return r;
++ }
++
++ radeon_bo_unreserve(rdev->vce.vcpu_bo);
++
++ return 0;
++}
++
++/**
++ * radeon_vce_free_handles - free still open VCE handles
++ *
++ * @rdev: radeon_device pointer
++ * @filp: drm file pointer
++ *
++ * Close all VCE handles still open by this file pointer
++ */
++void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp)
++{
++ int i, r;
++ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
++ uint32_t handle = atomic_read(&rdev->vce.handles[i]);
++ if (!handle || rdev->vce.filp[i] != filp)
++ continue;
++
++ r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX,
++ handle, NULL);
++ if (r)
++ DRM_ERROR("Error destroying VCE handle (%d)!\n", r);
++
++ rdev->vce.filp[i] = NULL;
++ atomic_set(&rdev->vce.handles[i], 0);
++ }
++}
++
++/**
++ * radeon_vce_get_create_msg - generate a VCE create msg
++ *
++ * @rdev: radeon_device pointer
++ * @ring: ring we should submit the msg to
++ * @handle: VCE session handle to use
++ * @fence: optional fence to return
++ *
++ * Open up a stream for HW test
++ */
++int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
++ uint32_t handle, struct radeon_fence **fence)
++{
++ const unsigned ib_size_dw = 1024;
++ struct radeon_ib ib;
++ uint64_t dummy;
++ int i, r;
++
++ r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4);
++ if (r) {
++ DRM_ERROR("radeon: failed to get ib (%d).\n", r);
++ return r;
++ }
++
++ dummy = ib.gpu_addr + 1024;
++
++ /* stitch together an VCE create msg */
++ ib.length_dw = 0;
++ ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
++ ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
++ ib.ptr[ib.length_dw++] = handle;
++
++ ib.ptr[ib.length_dw++] = 0x00000030; /* len */
++ ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */
++ ib.ptr[ib.length_dw++] = 0x00000000;
++ ib.ptr[ib.length_dw++] = 0x00000042;
++ ib.ptr[ib.length_dw++] = 0x0000000a;
++ ib.ptr[ib.length_dw++] = 0x00000001;
++ ib.ptr[ib.length_dw++] = 0x00000080;
++ ib.ptr[ib.length_dw++] = 0x00000060;
++ ib.ptr[ib.length_dw++] = 0x00000100;
++ ib.ptr[ib.length_dw++] = 0x00000100;
++ ib.ptr[ib.length_dw++] = 0x0000000c;
++ ib.ptr[ib.length_dw++] = 0x00000000;
++
++ ib.ptr[ib.length_dw++] = 0x00000014; /* len */
++ ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
++ ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
++ ib.ptr[ib.length_dw++] = dummy;
++ ib.ptr[ib.length_dw++] = 0x00000001;
++
++ for (i = ib.length_dw; i < ib_size_dw; ++i)
++ ib.ptr[i] = 0x0;
++
++ r = radeon_ib_schedule(rdev, &ib, NULL);
++ if (r) {
++ DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
++ }
++
++ if (fence)
++ *fence = radeon_fence_ref(ib.fence);
++
++ radeon_ib_free(rdev, &ib);
++
++ return r;
++}
++
++/**
++ * radeon_vce_get_destroy_msg - generate a VCE destroy msg
++ *
++ * @rdev: radeon_device pointer
++ * @ring: ring we should submit the msg to
++ * @handle: VCE session handle to use
++ * @fence: optional fence to return
++ *
++ * Close up a stream for HW test or if userspace failed to do so
++ */
++int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
++ uint32_t handle, struct radeon_fence **fence)
++{
++ const unsigned ib_size_dw = 1024;
++ struct radeon_ib ib;
++ uint64_t dummy;
++ int i, r;
++
++ r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4);
++ if (r) {
++ DRM_ERROR("radeon: failed to get ib (%d).\n", r);
++ return r;
++ }
++
++ dummy = ib.gpu_addr + 1024;
++
++ /* stitch together an VCE destroy msg */
++ ib.length_dw = 0;
++ ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
++ ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
++ ib.ptr[ib.length_dw++] = handle;
++
++ ib.ptr[ib.length_dw++] = 0x00000014; /* len */
++ ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
++ ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
++ ib.ptr[ib.length_dw++] = dummy;
++ ib.ptr[ib.length_dw++] = 0x00000001;
++
++ ib.ptr[ib.length_dw++] = 0x00000008; /* len */
++ ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */
++
++ for (i = ib.length_dw; i < ib_size_dw; ++i)
++ ib.ptr[i] = 0x0;
++
++ r = radeon_ib_schedule(rdev, &ib, NULL);
++ if (r) {
++ DRM_ERROR("radeon: failed to schedule ib (%d).\n", r);
++ }
++
++ if (fence)
++ *fence = radeon_fence_ref(ib.fence);
++
++ radeon_ib_free(rdev, &ib);
++
++ return r;
++}
++
++/**
++ * radeon_vce_cs_reloc - command submission relocation
++ *
++ * @p: parser context
++ * @lo: address of lower dword
++ * @hi: address of higher dword
++ *
++ * Patch relocation inside command stream with real buffer address
++ */
++int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi)
++{
++ struct radeon_cs_chunk *relocs_chunk;
++ uint64_t offset;
++ unsigned idx;
++
++ relocs_chunk = &p->chunks[p->chunk_relocs_idx];
++ offset = radeon_get_ib_value(p, lo);
++ idx = radeon_get_ib_value(p, hi);
++
++ if (idx >= relocs_chunk->length_dw) {
++ DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
++ idx, relocs_chunk->length_dw);
++ return -EINVAL;
++ }
++
++ offset += p->relocs_ptr[(idx / 4)]->lobj.gpu_offset;
++
++ p->ib.ptr[lo] = offset & 0xFFFFFFFF;
++ p->ib.ptr[hi] = offset >> 32;
++
++ return 0;
++}
++
++/**
++ * radeon_vce_cs_parse - parse and validate the command stream
++ *
++ * @p: parser context
++ *
++ */
++int radeon_vce_cs_parse(struct radeon_cs_parser *p)
++{
++ uint32_t handle = 0;
++ bool destroy = false;
++ int i, r;
++
++ while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) {
++ uint32_t len = radeon_get_ib_value(p, p->idx);
++ uint32_t cmd = radeon_get_ib_value(p, p->idx + 1);
++
++ if ((len < 8) || (len & 3)) {
++ DRM_ERROR("invalid VCE command length (%d)!\n", len);
++ return -EINVAL;
++ }
++
++ switch (cmd) {
++ case 0x00000001: // session
++ handle = radeon_get_ib_value(p, p->idx + 2);
++ break;
++
++ case 0x00000002: // task info
++ case 0x01000001: // create
++ case 0x04000001: // config extension
++ case 0x04000002: // pic control
++ case 0x04000005: // rate control
++ case 0x04000007: // motion estimation
++ case 0x04000008: // rdo
++ break;
++
++ case 0x03000001: // encode
++ r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9);
++ if (r)
++ return r;
++
++ r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11);
++ if (r)
++ return r;
++ break;
++
++ case 0x02000001: // destroy
++ destroy = true;
++ break;
++
++ case 0x05000001: // context buffer
++ case 0x05000004: // video bitstream buffer
++ case 0x05000005: // feedback buffer
++ r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2);
++ if (r)
++ return r;
++ break;
++
++ default:
++ DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
++ return -EINVAL;
++ }
++
++ p->idx += len / 4;
++ }
++
++ if (destroy) {
++ /* IB contains a destroy msg, free the handle */
++ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
++ atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
++
++ return 0;
++ }
++
++ /* create or encode, validate the handle */
++ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
++ if (atomic_read(&p->rdev->vce.handles[i]) == handle)
++ return 0;
++ }
++
++ /* handle not found try to alloc a new one */
++ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
++ if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
++ p->rdev->vce.filp[i] = p->filp;
++ return 0;
++ }
++ }
++
++ DRM_ERROR("No more free VCE handles!\n");
++ return -EINVAL;
++}
++
++/**
++ * radeon_vce_semaphore_emit - emit a semaphore command
++ *
++ * @rdev: radeon_device pointer
++ * @ring: engine to use
++ * @semaphore: address of semaphore
++ * @emit_wait: true=emit wait, false=emit signal
++ *
++ */
++bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
++ struct radeon_ring *ring,
++ struct radeon_semaphore *semaphore,
++ bool emit_wait)
++{
++ uint64_t addr = semaphore->gpu_addr;
++
++ radeon_ring_write(ring, VCE_CMD_SEMAPHORE);
++ radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
++ radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
++ radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0));
++ if (!emit_wait)
++ radeon_ring_write(ring, VCE_CMD_END);
++
++ return true;
++}
++
++/**
++ * radeon_vce_ib_execute - execute indirect buffer
++ *
++ * @rdev: radeon_device pointer
++ * @ib: the IB to execute
++ *
++ */
++void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
++{
++ struct radeon_ring *ring = &rdev->ring[ib->ring];
++ radeon_ring_write(ring, VCE_CMD_IB);
++ radeon_ring_write(ring, ib->gpu_addr);
++ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr));
++ radeon_ring_write(ring, ib->length_dw);
++}
++
++/**
++ * radeon_vce_fence_emit - add a fence command to the ring
++ *
++ * @rdev: radeon_device pointer
++ * @fence: the fence
++ *
++ */
++void radeon_vce_fence_emit(struct radeon_device *rdev,
++ struct radeon_fence *fence)
++{
++ struct radeon_ring *ring = &rdev->ring[fence->ring];
++ uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr;
++
++ radeon_ring_write(ring, VCE_CMD_FENCE);
++ radeon_ring_write(ring, addr);
++ radeon_ring_write(ring, upper_32_bits(addr));
++ radeon_ring_write(ring, fence->seq);
++ radeon_ring_write(ring, VCE_CMD_TRAP);
++ radeon_ring_write(ring, VCE_CMD_END);
++}
++
++/**
++ * radeon_vce_ring_test - test if VCE ring is working
++ *
++ * @rdev: radeon_device pointer
++ * @ring: the engine to test on
++ *
++ */
++int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
++{
++ uint32_t rptr = vce_v1_0_get_rptr(rdev, ring);
++ unsigned i;
++ int r;
++
++ r = radeon_ring_lock(rdev, ring, 16);
++ if (r) {
++ DRM_ERROR("radeon: vce failed to lock ring %d (%d).\n",
++ ring->idx, r);
++ return r;
++ }
++ radeon_ring_write(ring, VCE_CMD_END);
++ radeon_ring_unlock_commit(rdev, ring);
++
++ for (i = 0; i < rdev->usec_timeout; i++) {
++ if (vce_v1_0_get_rptr(rdev, ring) != rptr)
++ break;
++ DRM_UDELAY(1);
++ }
++
++ if (i < rdev->usec_timeout) {
++ DRM_INFO("ring test on %d succeeded in %d usecs\n",
++ ring->idx, i);
++ } else {
++ DRM_ERROR("radeon: ring %d test failed\n",
++ ring->idx);
++ r = -ETIMEDOUT;
++ }
++
++ return r;
++}
++
++/**
++ * radeon_vce_ib_test - test if VCE IBs are working
++ *
++ * @rdev: radeon_device pointer
++ * @ring: the engine to test on
++ *
++ */
++int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
++{
++ struct radeon_fence *fence = NULL;
++ int r;
++
++ r = radeon_vce_get_create_msg(rdev, ring->idx, 1, NULL);
++ if (r) {
++ DRM_ERROR("radeon: failed to get create msg (%d).\n", r);
++ goto error;
++ }
++
++ r = radeon_vce_get_destroy_msg(rdev, ring->idx, 1, &fence);
++ if (r) {
++ DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r);
++ goto error;
++ }
++
++ r = radeon_fence_wait(fence, false);
++ if (r) {
++ DRM_ERROR("radeon: fence wait failed (%d).\n", r);
++ } else {
++ DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
++ }
++error:
++ radeon_fence_unref(&fence);
++ return r;
++}
+diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
+index db3dd87..1da5a7a 100644
+--- a/drivers/gpu/drm/radeon/sid.h
++++ b/drivers/gpu/drm/radeon/sid.h
+@@ -1747,4 +1747,51 @@
+ #define DMA_PACKET_CONSTANT_FILL 0xd
+ #define DMA_PACKET_NOP 0xf
+
++#define VCE_STATUS 0x20004
++#define VCE_VCPU_CNTL 0x20014
++#define VCE_CLK_EN (1 << 0)
++#define VCE_VCPU_CACHE_OFFSET0 0x20024
++#define VCE_VCPU_CACHE_SIZE0 0x20028
++#define VCE_VCPU_CACHE_OFFSET1 0x2002c
++#define VCE_VCPU_CACHE_SIZE1 0x20030
++#define VCE_VCPU_CACHE_OFFSET2 0x20034
++#define VCE_VCPU_CACHE_SIZE2 0x20038
++#define VCE_SOFT_RESET 0x20120
++#define VCE_ECPU_SOFT_RESET (1 << 0)
++#define VCE_FME_SOFT_RESET (1 << 2)
++#define VCE_RB_BASE_LO2 0x2016c
++#define VCE_RB_BASE_HI2 0x20170
++#define VCE_RB_SIZE2 0x20174
++#define VCE_RB_RPTR2 0x20178
++#define VCE_RB_WPTR2 0x2017c
++#define VCE_RB_BASE_LO 0x20180
++#define VCE_RB_BASE_HI 0x20184
++#define VCE_RB_SIZE 0x20188
++#define VCE_RB_RPTR 0x2018c
++#define VCE_RB_WPTR 0x20190
++#define VCE_CLOCK_GATING_A 0x202f8
++#define VCE_CLOCK_GATING_B 0x202fc
++#define VCE_UENC_CLOCK_GATING 0x205bc
++#define VCE_UENC_REG_CLOCK_GATING 0x205c0
++#define VCE_FW_REG_STATUS 0x20e10
++# define VCE_FW_REG_STATUS_BUSY (1 << 0)
++# define VCE_FW_REG_STATUS_PASS (1 << 3)
++# define VCE_FW_REG_STATUS_DONE (1 << 11)
++#define VCE_LMI_FW_START_KEYSEL 0x20e18
++#define VCE_LMI_FW_PERIODIC_CTRL 0x20e20
++#define VCE_LMI_CTRL2 0x20e74
++#define VCE_LMI_CTRL 0x20e98
++#define VCE_LMI_VM_CTRL 0x20ea0
++#define VCE_LMI_SWAP_CNTL 0x20eb4
++#define VCE_LMI_SWAP_CNTL1 0x20eb8
++#define VCE_LMI_CACHE_CTRL 0x20ef4
++
++#define VCE_CMD_NO_OP 0x00000000
++#define VCE_CMD_END 0x00000001
++#define VCE_CMD_IB 0x00000002
++#define VCE_CMD_FENCE 0x00000003
++#define VCE_CMD_TRAP 0x00000004
++#define VCE_CMD_IB_AUTO 0x00000005
++#define VCE_CMD_SEMAPHORE 0x00000006
++
+ #endif
+diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c
+new file mode 100644
+index 0000000..e0c3534
+--- /dev/null
++++ b/drivers/gpu/drm/radeon/vce_v1_0.c
+@@ -0,0 +1,187 @@
++/*
++ * Copyright 2013 Advanced Micro Devices, Inc.
++ * 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.
++ *
++ * Authors: Christian König <christian.koenig@amd.com>
++ */
++
++#include <linux/firmware.h>
++#include <drm/drmP.h>
++#include "radeon.h"
++#include "radeon_asic.h"
++#include "sid.h"
++
++/**
++ * vce_v1_0_get_rptr - get read pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon_ring pointer
++ *
++ * Returns the current hardware read pointer
++ */
++uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
++ return RREG32(VCE_RB_RPTR);
++ else
++ return RREG32(VCE_RB_RPTR2);
++}
++
++/**
++ * vce_v1_0_get_wptr - get write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon_ring pointer
++ *
++ * Returns the current hardware write pointer
++ */
++uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
++ return RREG32(VCE_RB_WPTR);
++ else
++ return RREG32(VCE_RB_WPTR2);
++}
++
++/**
++ * vce_v1_0_set_wptr - set write pointer
++ *
++ * @rdev: radeon_device pointer
++ * @ring: radeon_ring pointer
++ *
++ * Commits the write pointer to the hardware
++ */
++void vce_v1_0_set_wptr(struct radeon_device *rdev,
++ struct radeon_ring *ring)
++{
++ if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
++ WREG32(VCE_RB_WPTR, ring->wptr);
++ else
++ WREG32(VCE_RB_WPTR2, ring->wptr);
++}
++
++/**
++ * vce_v1_0_start - start VCE block
++ *
++ * @rdev: radeon_device pointer
++ *
++ * Setup and start the VCE block
++ */
++int vce_v1_0_start(struct radeon_device *rdev)
++{
++ struct radeon_ring *ring;
++ int i, j, r;
++
++ /* set BUSY flag */
++ WREG32_P(VCE_STATUS, 1, ~1);
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
++ WREG32(VCE_RB_RPTR, ring->rptr);
++ WREG32(VCE_RB_WPTR, ring->wptr);
++ WREG32(VCE_RB_BASE_LO, ring->gpu_addr);
++ WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
++ WREG32(VCE_RB_SIZE, ring->ring_size / 4);
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
++ WREG32(VCE_RB_RPTR2, ring->rptr);
++ WREG32(VCE_RB_WPTR2, ring->wptr);
++ WREG32(VCE_RB_BASE_LO2, ring->gpu_addr);
++ WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
++ WREG32(VCE_RB_SIZE2, ring->ring_size / 4);
++
++ WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN);
++
++ WREG32_P(VCE_SOFT_RESET,
++ VCE_ECPU_SOFT_RESET |
++ VCE_FME_SOFT_RESET, ~(
++ VCE_ECPU_SOFT_RESET |
++ VCE_FME_SOFT_RESET));
++
++ mdelay(100);
++
++ WREG32_P(VCE_SOFT_RESET, 0, ~(
++ VCE_ECPU_SOFT_RESET |
++ VCE_FME_SOFT_RESET));
++
++ for (i = 0; i < 10; ++i) {
++ uint32_t status;
++ for (j = 0; j < 100; ++j) {
++ status = RREG32(VCE_STATUS);
++ if (status & 2)
++ break;
++ mdelay(10);
++ }
++ r = 0;
++ if (status & 2)
++ break;
++
++ DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
++ WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET);
++ mdelay(10);
++ WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET);
++ mdelay(10);
++ r = -1;
++ }
++
++ /* clear BUSY flag */
++ WREG32_P(VCE_STATUS, 0, ~1);
++
++ if (r) {
++ DRM_ERROR("VCE not responding, giving up!!!\n");
++ return r;
++ }
++
++ return 0;
++}
++
++int vce_v1_0_init(struct radeon_device *rdev)
++{
++ struct radeon_ring *ring;
++ int r;
++
++ r = vce_v1_0_start(rdev);
++ if (r)
++ return r;
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
++ ring->ready = true;
++ r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring);
++ if (r) {
++ ring->ready = false;
++ return r;
++ }
++
++ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
++ ring->ready = true;
++ r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring);
++ if (r) {
++ ring->ready = false;
++ return r;
++ }
++
++ DRM_INFO("VCE initialized successfully.\n");
++
++ return 0;
++}
+diff --git a/drivers/gpu/drm/radeon/vce_v2_0.c b/drivers/gpu/drm/radeon/vce_v2_0.c
+new file mode 100644
+index 0000000..4911d1b
+--- /dev/null
++++ b/drivers/gpu/drm/radeon/vce_v2_0.c
+@@ -0,0 +1,70 @@
++/*
++ * Copyright 2013 Advanced Micro Devices, Inc.
++ * 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.
++ *
++ * Authors: Christian König <christian.koenig@amd.com>
++ */
++
++#include <linux/firmware.h>
++#include <drm/drmP.h>
++#include "radeon.h"
++#include "radeon_asic.h"
++#include "cikd.h"
++
++int vce_v2_0_resume(struct radeon_device *rdev)
++{
++ uint64_t addr = rdev->vce.gpu_addr;
++ uint32_t size;
++
++ WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16));
++ WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
++ WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
++ WREG32(VCE_CLOCK_GATING_B, 0xf7);
++
++ WREG32(VCE_LMI_CTRL, 0x00398000);
++ WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1);
++ WREG32(VCE_LMI_SWAP_CNTL, 0);
++ WREG32(VCE_LMI_SWAP_CNTL1, 0);
++ WREG32(VCE_LMI_VM_CTRL, 0);
++
++ size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size);
++ WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
++ WREG32(VCE_VCPU_CACHE_SIZE0, size);
++
++ addr += size;
++ size = RADEON_VCE_STACK_SIZE;
++ WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
++ WREG32(VCE_VCPU_CACHE_SIZE1, size);
++
++ addr += size;
++ size = RADEON_VCE_HEAP_SIZE;
++ WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
++ WREG32(VCE_VCPU_CACHE_SIZE2, size);
++
++ WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100);
++
++ WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN,
++ ~VCE_SYS_INT_TRAP_INTERRUPT_EN);
++
++ return 0;
++}
+diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
+index fe421e8..b93c92a 100644
+--- a/include/uapi/drm/radeon_drm.h
++++ b/include/uapi/drm/radeon_drm.h
+@@ -919,6 +919,7 @@ struct drm_radeon_gem_va {
+ #define RADEON_CS_RING_COMPUTE 1
+ #define RADEON_CS_RING_DMA 2
+ #define RADEON_CS_RING_UVD 3
++#define RADEON_CS_RING_VCE 4
+ /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */
+ /* 0 = normal, + = higher priority, - = lower priority */
+
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0028-yocto-amd-drm-radeon-add-VCE-ring-query.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0028-yocto-amd-drm-radeon-add-VCE-ring-query.patch
new file mode 100644
index 00000000..f68e0058
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0028-yocto-amd-drm-radeon-add-VCE-ring-query.patch
@@ -0,0 +1,30 @@
+From dbc2d98551a2f32b8e7ad375ccc6b18bb8ef9709 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Mon, 27 Jan 2014 10:16:06 -0700
+Subject: [PATCH 28/44] drm/radeon: add VCE ring query
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon_kms.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index 07da88f..c9dd7ef 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -417,6 +417,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+ case RADEON_CS_RING_UVD:
+ *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
+ break;
++ case RADEON_CS_RING_VCE:
++ *value = rdev->ring[TN_RING_TYPE_VCE1_INDEX].ready;
++ break;
+ default:
+ return -EINVAL;
+ }
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0029-yocto-amd-drm-radeon-add-VCE-version-parsing-and-checking.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0029-yocto-amd-drm-radeon-add-VCE-version-parsing-and-checking.patch
new file mode 100644
index 00000000..1f11b462
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0029-yocto-amd-drm-radeon-add-VCE-version-parsing-and-checking.patch
@@ -0,0 +1,147 @@
+From 511a68ce32e94aa20be2ed70b3eccb059aef87bb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Thu, 23 Jan 2014 09:50:49 -0700
+Subject: [PATCH 29/44] drm/radeon: add VCE version parsing and checking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Also make the result available to userspace.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 2 ++
+ drivers/gpu/drm/radeon/radeon_kms.c | 6 ++++
+ drivers/gpu/drm/radeon/radeon_vce.c | 56 +++++++++++++++++++++++++++++++----
+ include/uapi/drm/radeon_drm.h | 4 +++
+ 4 files changed, 62 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 094e5f5..6abe303 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1601,6 +1601,8 @@ struct radeon_vce {
+ struct radeon_bo *vcpu_bo;
+ void *cpu_addr;
+ uint64_t gpu_addr;
++ unsigned fw_version;
++ unsigned fb_version;
+ atomic_t handles[RADEON_MAX_VCE_HANDLES];
+ struct drm_file *filp[RADEON_MAX_VCE_HANDLES];
+ };
+diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
+index c9dd7ef..cc2d29d 100644
+--- a/drivers/gpu/drm/radeon/radeon_kms.c
++++ b/drivers/gpu/drm/radeon/radeon_kms.c
+@@ -457,6 +457,12 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+ DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+ }
+ break;
++ case RADEON_INFO_VCE_FW_VERSION:
++ *value = rdev->vce.fw_version;
++ break;
++ case RADEON_INFO_VCE_FB_VERSION:
++ *value = rdev->vce.fb_version;
++ break;
+ default:
+ DRM_DEBUG_KMS("Invalid request %d\n", info->request);
+ return -EINVAL;
+diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
+index 2547d8e..f46563b 100644
+--- a/drivers/gpu/drm/radeon/radeon_vce.c
++++ b/drivers/gpu/drm/radeon/radeon_vce.c
+@@ -48,8 +48,11 @@ MODULE_FIRMWARE(FIRMWARE_BONAIRE);
+ */
+ int radeon_vce_init(struct radeon_device *rdev)
+ {
+- unsigned long bo_size;
+- const char *fw_name;
++ static const char *fw_version = "[ATI LIB=VCEFW,";
++ static const char *fb_version = "[ATI LIB=VCEFWSTATS,";
++ unsigned long size;
++ const char *fw_name, *c;
++ uint8_t start, mid, end;
+ int i, r;
+
+ switch (rdev->family) {
+@@ -70,9 +73,50 @@ int radeon_vce_init(struct radeon_device *rdev)
+ return r;
+ }
+
+- bo_size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
+- RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
+- r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
++ /* search for firmware version */
++
++ size = rdev->vce_fw->size - strlen(fw_version) - 9;
++ c = rdev->vce_fw->data;
++ for (;size > 0; --size, ++c)
++ if (strncmp(c, fw_version, strlen(fw_version)) == 0)
++ break;
++
++ if (size == 0)
++ return -EINVAL;
++
++ c += strlen(fw_version);
++ if (sscanf(c, "%2hhd.%2hhd.%2hhd]", &start, &mid, &end) != 3)
++ return -EINVAL;
++
++ /* search for feedback version */
++
++ size = rdev->vce_fw->size - strlen(fb_version) - 3;
++ c = rdev->vce_fw->data;
++ for (;size > 0; --size, ++c)
++ if (strncmp(c, fb_version, strlen(fb_version)) == 0)
++ break;
++
++ if (size == 0)
++ return -EINVAL;
++
++ c += strlen(fb_version);
++ if (sscanf(c, "%2u]", &rdev->vce.fb_version) != 1)
++ return -EINVAL;
++
++ DRM_INFO("Found VCE firmware/feedback version %hhd.%hhd.%hhd / %d!\n",
++ start, mid, end, rdev->vce.fb_version);
++
++ rdev->vce.fw_version = (start << 24) | (mid << 16) | (end << 8);
++
++ /* we can only work with this fw version for now */
++ if (rdev->vce.fw_version != ((40 << 24) | (2 << 16) | (2 << 8)))
++ return -EINVAL;
++
++ /* load firmware into VRAM */
++
++ size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) +
++ RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE;
++ r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
+ RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo);
+ if (r) {
+ dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r);
+@@ -83,7 +127,7 @@ int radeon_vce_init(struct radeon_device *rdev)
+ if (r)
+ return r;
+
+- memset(rdev->vce.cpu_addr, 0, bo_size);
++ memset(rdev->vce.cpu_addr, 0, size);
+ memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size);
+
+ r = radeon_vce_suspend(rdev);
+diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
+index b93c92a..2ff6e71 100644
+--- a/include/uapi/drm/radeon_drm.h
++++ b/include/uapi/drm/radeon_drm.h
+@@ -986,6 +986,10 @@ struct drm_radeon_cs {
+ #define RADEON_INFO_CIK_MACROTILE_MODE_ARRAY 0x18
+ /* query the number of render backends */
+ #define RADEON_INFO_SI_BACKEND_ENABLED_MASK 0x19
++/* version of VCE firmware */
++#define RADEON_INFO_VCE_FW_VERSION 0x1b
++/* version of VCE feedback */
++#define RADEON_INFO_VCE_FB_VERSION 0x1c
+
+
+ struct drm_radeon_info {
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0030-yocto-amd-drm-radeon-add-callback-for-setting-vce-clocks.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0030-yocto-amd-drm-radeon-add-callback-for-setting-vce-clocks.patch
new file mode 100644
index 00000000..26edee67
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0030-yocto-amd-drm-radeon-add-callback-for-setting-vce-clocks.patch
@@ -0,0 +1,35 @@
+From f6b00233428f66b0a57d6d9943c05eff10169f6b Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 20 Aug 2013 20:01:18 -0400
+Subject: [PATCH 30/44] drm/radeon: add callback for setting vce clocks
+
+Similar to uvd clock setting.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index 6abe303..f0ad724 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1817,6 +1817,7 @@ struct radeon_asic {
+ void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
+ void (*set_clock_gating)(struct radeon_device *rdev, int enable);
+ int (*set_uvd_clocks)(struct radeon_device *rdev, u32 vclk, u32 dclk);
++ int (*set_vce_clocks)(struct radeon_device *rdev, u32 evclk, u32 ecclk);
+ int (*get_temperature)(struct radeon_device *rdev);
+ } pm;
+ /* dynamic power management */
+@@ -2673,6 +2674,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
+ #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->pm.set_pcie_lanes((rdev), (l))
+ #define radeon_set_clock_gating(rdev, e) (rdev)->asic->pm.set_clock_gating((rdev), (e))
+ #define radeon_set_uvd_clocks(rdev, v, d) (rdev)->asic->pm.set_uvd_clocks((rdev), (v), (d))
++#define radeon_set_vce_clocks(rdev, ev, ec) (rdev)->asic->pm.set_vce_clocks((rdev), (ev), (ec))
+ #define radeon_get_temperature(rdev) (rdev)->asic->pm.get_temperature((rdev))
+ #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->surface.set_reg((rdev), (r), (f), (p), (o), (s)))
+ #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->surface.clear_reg((rdev), (r)))
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0031-yocto-amd-drm-radeon-dpm-move-platform-caps-fetching-to-a-sepa.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0031-yocto-amd-drm-radeon-dpm-move-platform-caps-fetching-to-a-sepa.patch
new file mode 100644
index 00000000..9dab9dcc
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0031-yocto-amd-drm-radeon-dpm-move-platform-caps-fetching-to-a-sepa.patch
@@ -0,0 +1,330 @@
+From d57ea9870d87db49132b6cd8067d512fb2810e24 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Wed, 21 Aug 2013 10:02:32 -0400
+Subject: [PATCH 31/44] drm/radeon/dpm: move platform caps fetching to a
+ separate function
+
+It's needed by by both the asic specific functions and the
+extended table parser.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/btc_dpm.c | 4 ++++
+ drivers/gpu/drm/radeon/ci_dpm.c | 9 ++++++---
+ drivers/gpu/drm/radeon/cypress_dpm.c | 4 ++++
+ drivers/gpu/drm/radeon/kv_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/ni_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/r600_dpm.c | 20 ++++++++++++++++++++
+ drivers/gpu/drm/radeon/r600_dpm.h | 2 ++
+ drivers/gpu/drm/radeon/rs780_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/rv6xx_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/rv770_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/si_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/sumo_dpm.c | 7 ++++---
+ drivers/gpu/drm/radeon/trinity_dpm.c | 7 ++++---
+ 13 files changed, 68 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
+index 9b6950d..e910299 100644
+--- a/drivers/gpu/drm/radeon/btc_dpm.c
++++ b/drivers/gpu/drm/radeon/btc_dpm.c
+@@ -2610,6 +2610,10 @@ int btc_dpm_init(struct radeon_device *rdev)
+ pi->min_vddc_in_table = 0;
+ pi->max_vddc_in_table = 0;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = rv7xx_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
+index 51e947a..b90834a 100644
+--- a/drivers/gpu/drm/radeon/ci_dpm.c
++++ b/drivers/gpu/drm/radeon/ci_dpm.c
+@@ -4951,9 +4951,6 @@ static int ci_parse_power_table(struct radeon_device *rdev)
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+ power_state_offset = (u8 *)state_array->states;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+ for (i = 0; i < state_array->ucNumEntries; i++) {
+ u8 *idx;
+ power_state = (union pplib_power_state *)power_state_offset;
+@@ -5069,6 +5066,12 @@ int ci_dpm_init(struct radeon_device *rdev)
+ ci_dpm_fini(rdev);
+ return ret;
+ }
++
++ ret = r600_get_platform_caps(rdev);
++ if (ret) {
++ ci_dpm_fini(rdev);
++ return ret;
++ }
+ ret = ci_parse_power_table(rdev);
+ if (ret) {
+ ci_dpm_fini(rdev);
+diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c
+index 91bb470..db1f391 100644
+--- a/drivers/gpu/drm/radeon/cypress_dpm.c
++++ b/drivers/gpu/drm/radeon/cypress_dpm.c
+@@ -2049,6 +2049,10 @@ int cypress_dpm_init(struct radeon_device *rdev)
+ pi->min_vddc_in_table = 0;
+ pi->max_vddc_in_table = 0;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = rv7xx_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
+index b419055..58b5a5d 100644
+--- a/drivers/gpu/drm/radeon/kv_dpm.c
++++ b/drivers/gpu/drm/radeon/kv_dpm.c
+@@ -2556,9 +2556,6 @@ static int kv_parse_power_table(struct radeon_device *rdev)
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+ power_state_offset = (u8 *)state_array->states;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+ for (i = 0; i < state_array->ucNumEntries; i++) {
+ u8 *idx;
+ power_state = (union pplib_power_state *)power_state_offset;
+@@ -2608,6 +2605,10 @@ int kv_dpm_init(struct radeon_device *rdev)
+ return -ENOMEM;
+ rdev->pm.dpm.priv = pi;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = r600_parse_extended_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
+index f263390..76bcc1e 100644
+--- a/drivers/gpu/drm/radeon/ni_dpm.c
++++ b/drivers/gpu/drm/radeon/ni_dpm.c
+@@ -4041,9 +4041,6 @@ static int ni_parse_power_table(struct radeon_device *rdev)
+ power_info->pplib.ucNumStates, GFP_KERNEL);
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+
+ for (i = 0; i < power_info->pplib.ucNumStates; i++) {
+ power_state = (union pplib_power_state *)
+@@ -4105,6 +4102,10 @@ int ni_dpm_init(struct radeon_device *rdev)
+ pi->min_vddc_in_table = 0;
+ pi->max_vddc_in_table = 0;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = ni_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
+index 5513d8f..d57cde7 100644
+--- a/drivers/gpu/drm/radeon/r600_dpm.c
++++ b/drivers/gpu/drm/radeon/r600_dpm.c
+@@ -818,6 +818,26 @@ static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependen
+ return 0;
+ }
+
++int r600_get_platform_caps(struct radeon_device *rdev)
++{
++ struct radeon_mode_info *mode_info = &rdev->mode_info;
++ union power_info *power_info;
++ int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
++ u16 data_offset;
++ u8 frev, crev;
++
++ if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
++ &frev, &crev, &data_offset))
++ return -EINVAL;
++ power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
++
++ rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
++ rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
++ rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
++
++ return 0;
++}
++
+ /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
+ #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
+ #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
+diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h
+index 1000bf9..7e5d2c2 100644
+--- a/drivers/gpu/drm/radeon/r600_dpm.h
++++ b/drivers/gpu/drm/radeon/r600_dpm.h
+@@ -217,6 +217,8 @@ int r600_set_thermal_temperature_range(struct radeon_device *rdev,
+ int min_temp, int max_temp);
+ bool r600_is_internal_thermal_sensor(enum radeon_int_thermal_type sensor);
+
++int r600_get_platform_caps(struct radeon_device *rdev);
++
+ int r600_parse_extended_power_table(struct radeon_device *rdev);
+ void r600_free_extended_power_table(struct radeon_device *rdev);
+
+diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c
+index 6af8505..f3143c0 100644
+--- a/drivers/gpu/drm/radeon/rs780_dpm.c
++++ b/drivers/gpu/drm/radeon/rs780_dpm.c
+@@ -815,9 +815,6 @@ static int rs780_parse_power_table(struct radeon_device *rdev)
+ power_info->pplib.ucNumStates, GFP_KERNEL);
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+
+ for (i = 0; i < power_info->pplib.ucNumStates; i++) {
+ power_state = (union pplib_power_state *)
+@@ -867,6 +864,10 @@ int rs780_dpm_init(struct radeon_device *rdev)
+ return -ENOMEM;
+ rdev->pm.dpm.priv = pi;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = rs780_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c
+index 5811d27..3aa0a8c 100644
+--- a/drivers/gpu/drm/radeon/rv6xx_dpm.c
++++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c
+@@ -1901,9 +1901,6 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev)
+ power_info->pplib.ucNumStates, GFP_KERNEL);
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+
+ for (i = 0; i < power_info->pplib.ucNumStates; i++) {
+ power_state = (union pplib_power_state *)
+@@ -1953,6 +1950,10 @@ int rv6xx_dpm_init(struct radeon_device *rdev)
+ return -ENOMEM;
+ rdev->pm.dpm.priv = pi;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = rv6xx_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
+index 374499d..4bcbacb 100644
+--- a/drivers/gpu/drm/radeon/rv770_dpm.c
++++ b/drivers/gpu/drm/radeon/rv770_dpm.c
+@@ -2277,9 +2277,6 @@ int rv7xx_parse_power_table(struct radeon_device *rdev)
+ power_info->pplib.ucNumStates, GFP_KERNEL);
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+
+ for (i = 0; i < power_info->pplib.ucNumStates; i++) {
+ power_state = (union pplib_power_state *)
+@@ -2357,6 +2354,10 @@ int rv770_dpm_init(struct radeon_device *rdev)
+ pi->min_vddc_in_table = 0;
+ pi->max_vddc_in_table = 0;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = rv7xx_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
+index 2332aa1..749c45c 100644
+--- a/drivers/gpu/drm/radeon/si_dpm.c
++++ b/drivers/gpu/drm/radeon/si_dpm.c
+@@ -6291,9 +6291,6 @@ static int si_parse_power_table(struct radeon_device *rdev)
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+ power_state_offset = (u8 *)state_array->states;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+ for (i = 0; i < state_array->ucNumEntries; i++) {
+ u8 *idx;
+ power_state = (union pplib_power_state *)power_state_offset;
+@@ -6370,6 +6367,10 @@ int si_dpm_init(struct radeon_device *rdev)
+ pi->min_vddc_in_table = 0;
+ pi->max_vddc_in_table = 0;
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = si_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
+index 96ea6db8..485d006 100644
+--- a/drivers/gpu/drm/radeon/sumo_dpm.c
++++ b/drivers/gpu/drm/radeon/sumo_dpm.c
+@@ -1477,9 +1477,6 @@ static int sumo_parse_power_table(struct radeon_device *rdev)
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+ power_state_offset = (u8 *)state_array->states;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+ for (i = 0; i < state_array->ucNumEntries; i++) {
+ u8 *idx;
+ power_state = (union pplib_power_state *)power_state_offset;
+@@ -1765,6 +1762,10 @@ int sumo_dpm_init(struct radeon_device *rdev)
+
+ sumo_construct_boot_and_acpi_state(rdev);
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = sumo_parse_power_table(rdev);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
+index d700698..ab32576 100644
+--- a/drivers/gpu/drm/radeon/trinity_dpm.c
++++ b/drivers/gpu/drm/radeon/trinity_dpm.c
+@@ -1685,9 +1685,6 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
+ if (!rdev->pm.dpm.ps)
+ return -ENOMEM;
+ power_state_offset = (u8 *)state_array->states;
+- rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
+- rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
+- rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
+ for (i = 0; i < state_array->ucNumEntries; i++) {
+ u8 *idx;
+ power_state = (union pplib_power_state *)power_state_offset;
+@@ -1886,6 +1883,10 @@ int trinity_dpm_init(struct radeon_device *rdev)
+
+ trinity_construct_boot_state(rdev);
+
++ ret = r600_get_platform_caps(rdev);
++ if (ret)
++ return ret;
++
+ ret = trinity_parse_power_table(rdev);
+ if (ret)
+ return ret;
+--
+1.7.9.5
+
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0032-yocto-amd-drm-radeon-dpm-fill-in-some-initial-vce-infrastructu.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0032-yocto-amd-drm-radeon-dpm-fill-in-some-initial-vce-infrastructu.patch
new file mode 100644
index 00000000..00f558dc
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0032-yocto-amd-drm-radeon-dpm-fill-in-some-initial-vce-infrastructu.patch
@@ -0,0 +1,84 @@
+From e539bcfbb6e46e51b7a463078e3bf3a7ae4c28d7 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 20 Aug 2013 20:29:05 -0400
+Subject: [PATCH 32/44] drm/radeon/dpm: fill in some initial vce
+ infrastructure
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/radeon/radeon.h | 12 ++++++++++++
+ drivers/gpu/drm/radeon/radeon_pm.c | 7 +++++++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index f0ad724..7846289 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1253,6 +1253,15 @@ enum radeon_dpm_event_src {
+ RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
+ };
+
++enum radeon_vce_level {
++ RADEON_VCE_LEVEL_AC_ALL = 0, /* AC, All cases */
++ RADEON_VCE_LEVEL_DC_EE = 1, /* DC, entropy encoding */
++ RADEON_VCE_LEVEL_DC_LL_LOW = 2, /* DC, low latency queue, res <= 720 */
++ RADEON_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
++ RADEON_VCE_LEVEL_DC_GP_LOW = 4, /* DC, general purpose queue, res <= 720 */
++ RADEON_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
++};
++
+ struct radeon_ps {
+ u32 caps; /* vbios flags */
+ u32 class; /* vbios flags */
+@@ -1263,6 +1272,8 @@ struct radeon_ps {
+ /* VCE clocks */
+ u32 evclk;
+ u32 ecclk;
++ bool vce_active;
++ enum radeon_vce_level vce_level;
+ /* asic priv */
+ void *ps_priv;
+ };
+@@ -1474,6 +1485,7 @@ struct radeon_dpm {
+ /* special states active */
+ bool thermal_active;
+ bool uvd_active;
++ bool vce_active;
+ /* thermal handling */
+