diff --git a/packages/addons/service/slice/changelog.txt b/packages/addons/service/slice/changelog.txt
new file mode 100644
index 0000000000..fe01f1b4fe
--- /dev/null
+++ b/packages/addons/service/slice/changelog.txt
@@ -0,0 +1,2 @@
+100
+- Initial release
diff --git a/packages/addons/service/slice/icon/icon.png b/packages/addons/service/slice/icon/icon.png
new file mode 100644
index 0000000000..d669c45ed6
Binary files /dev/null and b/packages/addons/service/slice/icon/icon.png differ
diff --git a/packages/addons/service/slice/package.mk b/packages/addons/service/slice/package.mk
new file mode 100644
index 0000000000..111cc562ff
--- /dev/null
+++ b/packages/addons/service/slice/package.mk
@@ -0,0 +1,46 @@
+################################################################################
+# This file is part of LibreELEC - https://libreelec.tv
+# Copyright (C) 2016-present Team LibreELEC
+#
+# LibreELEC 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.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT 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 LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="slice"
+PKG_VERSION="0"
+PKG_REV="100"
+PKG_ARCH="any"
+PKG_LICENSE="GPL"
+PKG_SITE=""
+PKG_URL=""
+PKG_DEPENDS_TARGET="toolchain"
+PKG_SECTION="service"
+PKG_SHORTDESC="Provides the ability to change the led lights on the Slice box via Kodi actions"
+PKG_LONGDESC="Provides the ability to change the led lights on the Slice box via Kodi actions"
+PKG_AUTORECONF="no"
+
+PKG_IS_ADDON="yes"
+PKG_ADDON_NAME="Slice"
+PKG_ADDON_TYPE="xbmc.service"
+
+make_target() {
+ :
+}
+
+makeinstall_target() {
+ :
+}
+
+addon() {
+ :
+}
diff --git a/packages/addons/service/slice/source/default.py b/packages/addons/service/slice/source/default.py
new file mode 100644
index 0000000000..214b03a18a
--- /dev/null
+++ b/packages/addons/service/slice/source/default.py
@@ -0,0 +1,237 @@
+################################################################################
+# This file is part of LibreELEC - https://libreelec.tv
+# Copyright (C) 2016-present Team LibreELEC
+#
+# LibreELEC 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.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT 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 LibreELEC. If not, see .
+################################################################################
+
+from PIL import Image
+
+import os
+import threading
+import time
+import Queue
+import xbmc
+import xbmcaddon
+
+'''
+ffwd.png
+pause.png
+play.png
+quit.png
+rew.png
+shutdown.png
+skipf.png
+skipr.png
+sleep.png
+startup.png
+stop.png
+wake.png
+'''
+
+__addon__ = xbmcaddon.Addon()
+__path__ = __addon__.getAddonInfo('path')
+
+class PNGPatternPlayer(threading.Thread):
+
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self.path = __path__ + "/resources/media/ledpatterns"
+ self.patterns = Queue.Queue()
+ self.responses = Queue.Queue()
+ self.stopped = False
+ self.memo = {}
+ self.start()
+
+ def setPath(self, path):
+ if self.path != path:
+ self.path = path
+ self.memo = {}
+
+ def clearPattern(self):
+ with open('/dev/ws2812', 'wb') as f:
+ f.write(bytearray(25))
+
+ def playPattern(self, file, delay):
+ xbmc.log('playing pattern: %s' % file, xbmc.LOGNOTICE)
+
+ 'get pixel data from a cache if available, otherwise load and calculate'
+ if file not in self.memo:
+ image = Image.open(file)
+ pixels = image.load()
+ width, height = image.size
+ data = []
+
+ for y in range(height):
+ x_pixels = []
+ for x in range(width):
+ pixel = []
+ r, g, b, a = pixels[x, y]
+ pixel.append(hex(r)[2:].zfill(2))
+ pixel.append(hex(g)[2:].zfill(2))
+ pixel.append(hex(b)[2:].zfill(2))
+ pixel.append(hex(a)[2:].zfill(2))
+ x_pixels.append(''.join(str(e) for e in pixel))
+ data.append(' '.join(str(e) for e in x_pixels))
+
+ self.memo[file] = data
+
+ for hexline in self.memo[file]:
+ if not self.stopped:
+ with open('/dev/ws2812', 'wb') as f:
+ f.write(bytearray.fromhex(hexline))
+ time.sleep(delay)
+ else:
+ break
+
+ def play(self, file, repeat=False, delay=0.030, wait=None):
+ self.stopped = True
+
+ if wait is not None:
+ # wait up to specified time if this pattern is to be processed synchronously
+ self.patterns.put((file, repeat, delay, True))
+ try:
+ result = self.responses.get(block=True, timeout=wait)
+ except Queue.Empty:
+ pass
+ else:
+ self.patterns.put((file, repeat, delay, False))
+
+ def stop(wait=None):
+ self.play(None, wait=wait)
+
+ def run(self):
+ repeat = False
+
+ while True:
+ try:
+ (file, repeat, delay, wait) = self.patterns.get(block=True, timeout=0 if repeat and not self.stopped else None)
+
+ self.stopped = False
+
+ if file is not None:
+ self.playPattern("%s/%s.png" % (self.path, file), delay)
+ else:
+ self.clearPattern()
+
+ if wait:
+ self.responses.put(True)
+
+ # Queue will be empty if we're repeating the last pattern and there is no new work
+ except Queue.Empty:
+ self.playPattern("%s/%s.png" % (self.path, file), delay)
+
+class SlicePlayer(xbmc.Player):
+
+ def __init__(self, *args, **kwargs):
+ xbmc.Player.__init__(self)
+
+ 'maps kodi player speed to delay in seconds'
+ self.speed_map = { 1: 0.060,
+ 2: 0.040,
+ 4: 0.035,
+ 8: 0.030,
+ 16: 0.025,
+ 32: 0.015,
+ }
+
+ self.speed = 1
+ patterns.play('startup', False, 0.02)
+
+ def onPlayBackEnded(self):
+ 'Will be called when Kodi stops playing a file'
+
+ patterns.play('stop')
+
+ def onPlayBackPaused(self):
+ 'Will be called when user pauses a playing file'
+
+ patterns.play('pause')
+
+ def onPlayBackResumed(self):
+ 'Will be called when user resumes a paused file'
+
+ patterns.play('play')
+
+ def onPlayBackSeek(self, iTime, seekOffset):
+ 'Will be called when user seeks to a time'
+
+ # todo: not working
+
+ xbmc.log('time offset: %d' % iTime, xbmc.LOGNOTICE)
+ xbmc.log('seek offset: %d' % seekOffset, xbmc.LOGNOTICE)
+
+ if seekOffset > 0:
+ patterns.play('skipf')
+ else:
+ patterns.play('skipr')
+
+ def onPlayBackSeekChapter(self, chapter):
+ 'Will be called when user performs a chapter seek'
+ pass
+
+ def onPlayBackSpeedChanged(self, speed):
+ 'Will be called when players speed changes. (eg. user FF/RW)'
+
+ xbmc.log('seek speed: %d' % speed, xbmc.LOGNOTICE)
+
+ self.speed = speed
+
+ if self.speed != 1:
+ patterns.play('ffwd' if self.speed > 0 else 'rew', True, self.speed_map[self.speed])
+ else:
+ patterns.stop()
+ #OR: patterns.play('play') ???
+
+ def onPlayBackStarted(self):
+ 'Will be called when Kodi starts playing a file'
+
+ patterns.play('play')
+
+ def onPlayBackStopped(self):
+ 'Will be called when user stops Kodi playing a file'
+
+ patterns.play('stop')
+
+class SliceMonitor(xbmc.Monitor):
+
+ def __init__(self, *args, **kwargs):
+ xbmc.Monitor.__init__(self)
+
+ def onScreensaverActivated(self):
+ 'Will be called when screensaver kicks in'
+
+ patterns.play('sleep')
+
+ def onScreensaverDeactivated(self):
+ 'Will be called when screensaver goes off'
+
+ patterns.play('wake')
+
+ def onSettingsChanged(self):
+ 'Will be called when addon settings are changed'
+
+ # meh
+
+if (__name__ == "__main__"):
+ patterns = PNGPatternPlayer()
+ player = SlicePlayer()
+ monitor = SliceMonitor()
+
+ monitor.waitForAbort()
+ patterns.play('shutdown', wait=5.0)
+
+ del SliceMonitor
+ del SlicePlayer
+ del PNGPatternPlayer
\ No newline at end of file
diff --git a/packages/tools/led_tools/media/ledpatterns/ffwd.png b/packages/addons/service/slice/source/resources/media/ledpatterns/ffwd.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/ffwd.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/ffwd.png
diff --git a/packages/tools/led_tools/media/ledpatterns/pause.png b/packages/addons/service/slice/source/resources/media/ledpatterns/pause.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/pause.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/pause.png
diff --git a/packages/tools/led_tools/media/ledpatterns/play.png b/packages/addons/service/slice/source/resources/media/ledpatterns/play.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/play.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/play.png
diff --git a/packages/tools/led_tools/media/ledpatterns/quit.png b/packages/addons/service/slice/source/resources/media/ledpatterns/quit.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/quit.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/quit.png
diff --git a/packages/tools/led_tools/media/ledpatterns/rew.png b/packages/addons/service/slice/source/resources/media/ledpatterns/rew.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/rew.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/rew.png
diff --git a/packages/tools/led_tools/media/ledpatterns/shutdown.png b/packages/addons/service/slice/source/resources/media/ledpatterns/shutdown.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/shutdown.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/shutdown.png
diff --git a/packages/tools/led_tools/media/ledpatterns/skipf.png b/packages/addons/service/slice/source/resources/media/ledpatterns/skipf.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/skipf.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/skipf.png
diff --git a/packages/tools/led_tools/media/ledpatterns/skipr.png b/packages/addons/service/slice/source/resources/media/ledpatterns/skipr.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/skipr.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/skipr.png
diff --git a/packages/tools/led_tools/media/ledpatterns/sleep.png b/packages/addons/service/slice/source/resources/media/ledpatterns/sleep.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/sleep.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/sleep.png
diff --git a/packages/tools/led_tools/media/ledpatterns/startup.png b/packages/addons/service/slice/source/resources/media/ledpatterns/startup.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/startup.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/startup.png
diff --git a/packages/tools/led_tools/media/ledpatterns/stop.png b/packages/addons/service/slice/source/resources/media/ledpatterns/stop.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/stop.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/stop.png
diff --git a/packages/tools/led_tools/media/ledpatterns/wake.png b/packages/addons/service/slice/source/resources/media/ledpatterns/wake.png
similarity index 100%
rename from packages/tools/led_tools/media/ledpatterns/wake.png
rename to packages/addons/service/slice/source/resources/media/ledpatterns/wake.png
diff --git a/packages/linux-drivers/slice-drivers/package.mk b/packages/linux-drivers/slice-drivers/package.mk
new file mode 100644
index 0000000000..5c9e366231
--- /dev/null
+++ b/packages/linux-drivers/slice-drivers/package.mk
@@ -0,0 +1,45 @@
+################################################################################
+# This file is part of LibreELEC - https://libreelec.tv
+# Copyright (C) 2016-present Team LibreELEC
+#
+# LibreELEC 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.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT 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 LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="slice-drivers"
+PKG_VERSION="d02f3e7"
+PKG_ARCH="arm"
+PKG_LICENSE="GPL"
+PKG_SITE="https://github.com/LibreELEC/slice-drivers"
+PKG_URL="https://github.com/LibreELEC/slice-drivers/archive/$PKG_VERSION.tar.gz"
+PKG_DEPENDS_TARGET="toolchain linux"
+PKG_NEED_UNPACK="$LINUX_DEPENDS"
+PKG_SECTION="driver"
+PKG_SHORTDESC="linux kernel modules for the Slice box"
+PKG_LONGDESC="linux kernel modules for the Slice box"
+
+PKG_IS_ADDON="no"
+PKG_AUTORECONF="no"
+
+pre_make_target() {
+ unset LDFLAGS
+}
+
+make_target() {
+ make KDIR=$(kernel_path)
+}
+
+makeinstall_target() {
+ mkdir -p $INSTALL/usr/lib/modules/$(get_module_dir)/$PKG_NAME
+ cp *.ko $INSTALL/usr/lib/modules/$(get_module_dir)/$PKG_NAME
+}
diff --git a/packages/linux-firmware/slice-firmware/package.mk b/packages/linux-firmware/slice-firmware/package.mk
new file mode 100644
index 0000000000..1e8554709c
--- /dev/null
+++ b/packages/linux-firmware/slice-firmware/package.mk
@@ -0,0 +1,44 @@
+################################################################################
+# This file is part of LibreELEC - https://libreelec.tv
+# Copyright (C) 2016-present Team LibreELEC
+#
+# LibreELEC 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.
+#
+# LibreELEC is distributed in the hope that it will be useful,
+# but WITHOUT 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 LibreELEC. If not, see .
+################################################################################
+
+PKG_NAME="slice-firmware"
+PKG_VERSION="0f463cc"
+PKG_ARCH="arm"
+PKG_LICENSE="GPL"
+PKG_SITE="https://github.com/FiveNinjas/slice-firmware"
+PKG_URL="https://github.com/libreelec/slice-firmware/archive/$PKG_VERSION.tar.gz"
+PKG_DEPENDS_TARGET="toolchain dtc:host"
+PKG_SECTION="linux-firmware"
+PKG_SHORTDESC="BCM270x firmware related stuff for Slice"
+PKG_LONGDESC="BCM270x firmware related stuff for Slice"
+
+PKG_IS_ADDON="no"
+PKG_AUTORECONF="no"
+
+make_target() {
+ if [ "$DEVICE" = "Slice3" ]; then
+ dtc -O dtb -I dts -o dt-blob.bin slice3-dt-blob.dts
+ elif [ "$DEVICE" = "Slice" ]; then
+ dtc -O dtb -I dts -o dt-blob.bin slice-dt-blob.dts
+ fi
+}
+
+makeinstall_target() {
+ mkdir -p $INSTALL/usr/share/bootloader/
+ cp -a dt-blob.bin $INSTALL/usr/share/bootloader/
+}
diff --git a/packages/linux/package.mk b/packages/linux/package.mk
index c41b37e4c6..5ff874a8fd 100644
--- a/packages/linux/package.mk
+++ b/packages/linux/package.mk
@@ -135,16 +135,10 @@ post_patch() {
for f in $PROJECT_DIR/$PROJECT/config/*-overlay.dts; do
[ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays
done
- if [ -f $PROJECT_DIR/$PROJECT/config/dt-blob.dts ]; then
- cp -v $PROJECT_DIR/$PROJECT/config/dt-blob.dts $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts
- fi
if [ -n "$DEVICE" ]; then
for f in $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/*-overlay.dts; do
[ -f "$f" ] && cp -v $f $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts/overlays
done
- if [ -f $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.dts ]; then
- cp -v $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.dts $PKG_BUILD/arch/$TARGET_KERNEL_ARCH/boot/dts
- fi
fi
}
diff --git a/packages/tools/bcm2835-bootloader/release b/packages/tools/bcm2835-bootloader/release
index 5170fa409f..7a0071624d 100755
--- a/packages/tools/bcm2835-bootloader/release
+++ b/packages/tools/bcm2835-bootloader/release
@@ -25,8 +25,8 @@ mkdir -p $RELEASE_DIR/3rdparty/bootloader
cp -PR $BUILD/bcm2835-bootloader-*/bootcode.bin $RELEASE_DIR/3rdparty/bootloader/
cp -PR $BUILD/bcm2835-bootloader-*/fixup_x.dat $RELEASE_DIR/3rdparty/bootloader/fixup.dat
cp -PR $BUILD/bcm2835-bootloader-*/start_x.elf $RELEASE_DIR/3rdparty/bootloader/start.elf
- if [ -f $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.bin ]; then
- cp -PR $PROJECT_DIR/$PROJECT/devices/$DEVICE/config/dt-blob.bin $RELEASE_DIR/3rdparty/bootloader/
+ if [ -f $(get_build_dir slice-firmware)/dt-blob.bin ]; then
+ cp -PR $(get_build_dir slice-firmware)/dt-blob.bin $RELEASE_DIR/3rdparty/bootloader/
fi
cp -PR $INSTALL/usr/share/bootloader/*.dtb $RELEASE_DIR/3rdparty/bootloader/
cp -PR $INSTALL/usr/share/bootloader/overlays $RELEASE_DIR/3rdparty/bootloader/
diff --git a/packages/tools/dtc/package.mk b/packages/tools/dtc/package.mk
index 72b105cf02..cedcbebb69 100644
--- a/packages/tools/dtc/package.mk
+++ b/packages/tools/dtc/package.mk
@@ -37,6 +37,6 @@ makeinstall_target() {
}
makeinstall_host() {
- mkdir -p $INSTALL/usr/bin
- cp -P $PKG_BUILD/dtc $INSTALL/usr/bin
+ mkdir -p $TOOLCHAIN/bin
+ cp -P $PKG_BUILD/dtc $TOOLCHAIN/bin
}
diff --git a/packages/tools/led_tools/package.mk b/packages/tools/led_tools/package.mk
index 6b786ed52f..ef6da64b01 100644
--- a/packages/tools/led_tools/package.mk
+++ b/packages/tools/led_tools/package.mk
@@ -40,7 +40,4 @@ make_target() {
makeinstall_target() {
mkdir -p $INSTALL/usr/bin
cp led_png $INSTALL/usr/bin
-
- mkdir -p $INSTALL/usr/share/kodi/
- cp -r $PKG_DIR/media $INSTALL/usr/share/kodi/
}
diff --git a/projects/RPi/devices/Slice/config/dt-blob.bin b/projects/RPi/devices/Slice/config/dt-blob.bin
deleted file mode 100644
index f4f373db20..0000000000
Binary files a/projects/RPi/devices/Slice/config/dt-blob.bin and /dev/null differ
diff --git a/projects/RPi/devices/Slice/config/dt-blob.dts b/projects/RPi/devices/Slice/config/dt-blob.dts
deleted file mode 100644
index 443b31b7c8..0000000000
--- a/projects/RPi/devices/Slice/config/dt-blob.dts
+++ /dev/null
@@ -1,92 +0,0 @@
-/dts-v1/;
-
-/ {
- videocore {
-
- pins_cm {
-
- pin_config {
-
- pin@default {
- polarity = "active_high";
- termination = "pull_down";
- startup_state = "inactive";
- function = "input";
- }; // pin
-
- // BANK 0 //
- pin@p0 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p1 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p2 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p3 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p4 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p5 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p6 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p7 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p8 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p9 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p10 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p11 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p12 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p13 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p14 { function = "uart0"; termination = "no_pulling"; }; // UART0_TX
- pin@p15 { function = "uart0"; termination = "pull_up"; }; // UART0_RX
- pin@p16 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p17 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p18 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p19 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p20 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p21 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p22 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p23 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p24 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p25 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p26 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p27 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
-
- // BANK 1 //
- pin@p28 { function = "pcm"; termination = "no_pulling"; }; // PCM_CLK
- pin@p29 { function = "pcm"; termination = "no_pulling"; }; // PCM_FS
- pin@p30 { function = "pcm"; termination = "no_pulling"; }; // PCM_DIN
- pin@p31 { function = "pcm"; termination = "no_pulling"; }; // PCM_DOUT
- pin@p32 { function = "gp_clk"; termination = "no_pulling"; }; // PCM_MCLK (GPCLK0)
- pin@p33 { function = "output"; termination = "no_pulling"; polarity = "active_low"; startup_state = "inactive"; }; // AUD_RST_N
- pin@p34 { function = "input"; termination = "pull_up"; }; // NOT USED
- pin@p35 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "active"; }; // USB_ON
- pin@p36 { function = "input"; termination = "no_pulling"; }; // RTC_IRQ
- pin@p37 { function = "input"; termination = "no_pulling"; }; // IR_RX
- pin@p38 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // STBY_LED
- pin@p39 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // DISK_OFF
- pin@p40 { function = "pwm"; termination = "no_pulling"; }; // LED_PWM
- pin@p41 { function = "output"; termination = "no_pulling"; }; // LAN_RUN
- pin@p42 { function = "gp_clk"; termination = "no_pulling"; }; // ETH_CLK (GPCLK1)
- pin@p43 { function = "output"; termination = "pull_down"; polarity = "active_high"; startup_state = "inactive"; }; // LEDS_ON
- pin@p44 { function = "i2c1"; termination = "no_pulling"; }; // SDA1
- pin@p45 { function = "i2c1"; termination = "no_pulling"; }; // SCL1
-
- // BANK 2 //
- pin@p46 { function = "input"; termination = "no_pulling"; drive_strength_mA = <8>; polarity = "active_high"; }; // HPD_N
- pin@p47 { function = "output"; termination = "no_pulling"; drive_strength_mA = <8>; polarity = "active_low"; startup_state = "active"; }; // EMMC_DISABLE_N CONTROL
- pin@p48 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CLK
- pin@p49 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CMD
- pin@p50 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D0
- pin@p51 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D1
- pin@p52 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D2
- pin@p53 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D3
-
- }; // pin_config
-
- pin_defines {
- pin_define@HDMI_CONTROL_ATTACHED { type = "internal"; number = <46>; }; // HPD_N on GPIO46
- pin_define@LAN_RUN { type = "internal"; number = <41>; }; // LAN_RUN
- }; // pin_defines
-
- }; // pins_cm
-
- clock_setup {
- clock@PWM { freq = < 2400000>; }; // LEDS PWM CLOCK
- clock@GPCLK1 { freq = <25000000>; }; // ETH_CLK
- }; // clock_setup
-
- }; // videocore
-};
diff --git a/projects/RPi/devices/Slice/options b/projects/RPi/devices/Slice/options
index a2566ab649..612ff1b53c 100644
--- a/projects/RPi/devices/Slice/options
+++ b/projects/RPi/devices/Slice/options
@@ -1,2 +1,2 @@
# Additional kernel make parameters
- KERNEL_MAKE_EXTRACMD+=" dt-blob.dtb overlays/slice.dtbo overlays/ws2812.dtbo"
+ KERNEL_MAKE_EXTRACMD+=" overlays/slice.dtbo overlays/ws2812.dtbo"
diff --git a/projects/RPi/devices/Slice/patches/kodi/kodi-002-slice-led.patch b/projects/RPi/devices/Slice/patches/kodi/kodi-002-slice-led.patch
deleted file mode 100644
index 6ba4cfb403..0000000000
--- a/projects/RPi/devices/Slice/patches/kodi/kodi-002-slice-led.patch
+++ /dev/null
@@ -1,677 +0,0 @@
---- a/xbmc/windows/GUIWindowHome.cpp 2016-09-17 16:35:22.000000000 +0100
-+++ b/xbmc/windows/GUIWindowHome.cpp 2016-10-01 19:22:20.908566550 +0100
-@@ -30,9 +30,245 @@
- #include "guilib/GUIWindowManager.h"
- #include "Application.h"
- #include "utils/StringUtils.h"
-+extern "C"
-+{
-+ #include "readpng.h"
-+}
-
- using namespace ANNOUNCEMENT;
-
-+int g_pattern = 0;
-+int g_halt = 0;
-+int g_pattern_playing = 0;
-+int g_speed = 30000;
-+int g_repeat = 0;
-+
-+enum pattern_e {
-+ PAT_PLAY, PAT_PAUSE, PAT_STOP, PAT_SLEEP, PAT_WAKE, PAT_FFWD, PAT_REW, PAT_SKIPF, PAT_SKIPR, PAT_STARTUP, PAT_QUIT, PAT_NONE
-+};
-+#define NUM_PATTERNS 11
-+const char *patterns[NUM_PATTERNS] = {
-+ "play" , "pause", "stop", "sleep", "wake", "ffwd", "rew", "skipf", "skipr", "startup", "quit"
-+};
-+
-+void on_speed_changed(const char *message, const CVariant &data)
-+{
-+ int speed = data["player"]["speed"].asInteger();
-+
-+ CLog::Log(LOGDEBUG, "speed changed %d", speed);
-+
-+ switch(abs(speed))
-+ {
-+ case 1: g_speed = 60000; break;
-+ case 2: g_speed = 40000; break;
-+ case 4: g_speed = 35000; break;
-+ case 8: g_speed = 30000; break;
-+ case 16: g_speed = 25000; break;
-+ case 32: g_speed = 15000; break;
-+ }
-+
-+ if(speed > 0)
-+ g_pattern = PAT_FFWD;
-+ else
-+ g_pattern = PAT_REW;
-+
-+ if(speed != 1)
-+ g_repeat = 1;
-+ else
-+ {
-+ g_repeat = 0;
-+ g_pattern = PAT_NONE;
-+ }
-+}
-+
-+void on_seek(const char *message, const CVariant &data)
-+{
-+ int seek_time = data["player"]["seekoffset"]["seconds"].asInteger() +
-+ data["player"]["seekoffset"]["minutes"].asInteger() * 60;
-+
-+ CLog::Log(LOGDEBUG, "Seek offset = %d", seek_time);
-+ if(seek_time > 0)
-+ {
-+ g_pattern = PAT_SKIPF;
-+ }
-+ else
-+ {
-+ g_pattern = PAT_SKIPR;
-+ }
-+
-+ g_repeat = 0;
-+}
-+
-+enum action_e {
-+ ACTION_DO, ACTION_REPEAT, ACTION_FN
-+ };
-+
-+enum led_state_e {
-+ LED_STATE_INVALID = 0,
-+ LED_STATE_IDLE,
-+ LED_STATE_PLAYING,
-+ LED_STATE_PAUSED,
-+ LED_STATE_SLEEP
-+};
-+
-+struct led_action_s {
-+ const char * event_name;
-+ enum action_e action;
-+ enum pattern_e action_data;
-+ void (*action_fn)(const char *, const CVariant &);
-+ led_state_e action_state;
-+} led_actions[] = {
-+ { "OnPlay", ACTION_DO, PAT_PLAY, NULL, LED_STATE_PLAYING },
-+ { "OnPause", ACTION_DO, PAT_PAUSE, NULL, LED_STATE_PAUSED },
-+ { "OnStop", ACTION_DO, PAT_STOP, NULL, LED_STATE_IDLE },
-+ { "OnSpeedChanged", ACTION_FN, PAT_NONE, on_speed_changed, LED_STATE_INVALID },
-+ { "OnSeek", ACTION_FN, PAT_NONE, on_seek, LED_STATE_INVALID },
-+ { "OnScreensaverActivated", ACTION_DO, PAT_SLEEP, NULL, LED_STATE_SLEEP },
-+ { "OnScreensaverDeactivated", ACTION_DO, PAT_WAKE, NULL, LED_STATE_IDLE },
-+ { "OnQuit", ACTION_REPEAT, PAT_QUIT, NULL, LED_STATE_IDLE },
-+};
-+
-+int zeroes[25] = { 0,};
-+
-+class CLedPattern : public IRunnable
-+{
-+ int m_going;
-+ CEvent *m_ev;
-+ struct pattern {
-+ unsigned long w;
-+ unsigned long h;
-+ unsigned long rowbytes;
-+ unsigned char * img;
-+ } m_pattern[NUM_PATTERNS];
-+
-+ void open_patterns()
-+ {
-+ unsigned int i;
-+ for(i = 0; i < sizeof(patterns)/sizeof(patterns[0]); i++)
-+ {
-+ FILE * fp;
-+ char filename[256];
-+ int channels;
-+
-+ m_pattern[i].img = NULL;
-+ sprintf(filename, "/storage/.kodi/media/ledpatterns/%s.png", patterns[i]);
-+ fp = fopen(filename , "rb");
-+ if(fp == NULL)
-+ {
-+ sprintf(filename, "/usr/share/kodi/media/ledpatterns/%s.png", patterns[i]);
-+ fp = fopen(filename, "rb");
-+ if(fp == NULL)
-+ {
-+ CLog::Log(LOGDEBUG, "Unable to open file %s", filename);
-+ goto drop_out;
-+ }
-+ }
-+
-+ if(readpng_init(fp, &m_pattern[i].w, &m_pattern[i].h) != 0)
-+ {
-+ CLog::Log(LOGERROR, "Unable to parse png files %s", filename);
-+ goto drop_out;
-+ }
-+
-+ m_pattern[i].img = readpng_get_image(1.0, &channels, &m_pattern[i].rowbytes);
-+ if(m_pattern[i].img == NULL || channels != 4)
-+ {
-+ CLog::Log(LOGERROR, "Invalid png %s, width = %lu, height = %lu, channels = %d, rowbytes = %lu",
-+ filename, m_pattern[i].w, m_pattern[i].h, channels, m_pattern[i].rowbytes);
-+ goto drop_out;
-+ }
-+
-+ CLog::Log(LOGDEBUG, "Opened %s: (%lu x %lu)", filename, m_pattern[i].w, m_pattern[i].h);
-+
-+drop_out:
-+ if(fp)
-+ fclose(fp);
-+
-+ }
-+ }
-+
-+ void play_pattern(int pat)
-+ {
-+ int fd = open("/dev/ws2812", O_WRONLY, 0);
-+ if(fd < 0)
-+ {
-+ CLog::Log(LOGERROR, "Unable to open /dev/ws2812");
-+ }
-+ else
-+ {
-+ if(pat < PAT_NONE && m_pattern[pat].img != NULL)
-+ {
-+ CLog::Log(LOGDEBUG, "playing pattern");
-+ g_pattern_playing = 1;
-+ do
-+ {
-+ unsigned char * p_line = m_pattern[pat].img;
-+ unsigned int i;
-+
-+ for(i = 0; i < m_pattern[pat].h; i++)
-+ {
-+ write(fd, p_line, m_pattern[pat].w * 4);
-+ if(m_pattern[pat].w == 26)
-+ {
-+ int *p = (int *) (p_line + (25 * 4));
-+ usleep(*p);
-+ }
-+ else
-+ {
-+ usleep(g_speed);
-+ }
-+ p_line += m_pattern[pat].rowbytes;
-+ // If we get the g_halt signal then stop repeating
-+ // the pattern
-+ if(g_halt)
-+ {
-+ g_halt = 0;
-+ g_repeat = 0;
-+ break;
-+ }
-+ }
-+ p_line += m_pattern[pat].rowbytes;
-+ }
-+ while(g_repeat);
-+ g_pattern_playing = 0;
-+
-+ if(pat != PAT_QUIT)
-+ write(fd, zeroes, sizeof(zeroes));
-+ }
-+ else
-+ {
-+ CLog::Log(LOGDEBUG, "No img for LED pattern %d", pat);
-+ }
-+ close(fd);
-+ }
-+ }
-+
-+public:
-+ CLedPattern(CEvent *ev)
-+ {
-+ CLog::Log(LOGDEBUG, "Initialising CLedPattern");
-+ open_patterns();
-+ m_ev = ev;
-+ }
-+
-+ void Run()
-+ {
-+ m_going = 1;
-+ while(m_going)
-+ {
-+ m_ev->Wait();
-+ CLog::Log(LOGDEBUG, "Led Pattern %d triggered", g_pattern);
-+ play_pattern(g_pattern);
-+ }
-+ }
-+
-+ void Stop()
-+ {
-+ m_going = 0;
-+ m_ev->Set();
-+ }
-+};
-+
- CGUIWindowHome::CGUIWindowHome(void) : CGUIWindow(WINDOW_HOME, "Home.xml"),
- m_recentlyAddedRunning(false),
- m_cumulativeUpdateFlag(0)
-@@ -40,6 +276,14 @@ CGUIWindowHome::CGUIWindowHome(void) : C
- m_updateRA = (Audio | Video | Totals);
- m_loadType = KEEP_IN_MEMORY;
-
-+ m_ledevent = new CEvent();
-+ m_ledthread = new CThread(new CLedPattern(m_ledevent), "LedThread");
-+ m_ledthread->Create();
-+ g_pattern = PAT_STARTUP;
-+ g_speed = 30000;
-+ g_repeat = 0;
-+ m_ledevent->Set();
-+
- CAnnouncementManager::GetInstance().AddAnnouncer(this);
- }
-
-@@ -75,10 +319,49 @@ void CGUIWindowHome::OnInitWindow()
-
- void CGUIWindowHome::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
- {
-+ unsigned int i;
- int ra_flag = 0;
-
- CLog::Log(LOGDEBUG, "GOT ANNOUNCEMENT, type: %i, from %s, message %s",(int)flag, sender, message);
-
-+ for(i = 0; i < sizeof(led_actions)/sizeof(led_actions[0]); i++)
-+ {
-+ if(strcmp(message, led_actions[i].event_name) == 0)
-+ {
-+ switch(led_actions[i].action) {
-+ case ACTION_DO:
-+ case ACTION_REPEAT:
-+ {
-+ g_halt = 1;
-+ while(g_pattern_playing)
-+ usleep(10);
-+ g_halt = 0;
-+ g_repeat = (led_actions[i].action == ACTION_DO) ? 0 : 1;
-+ g_speed = 30000;
-+ g_pattern = (int) led_actions[i].action_data;
-+ m_ledevent->Set();
-+ break;
-+ }
-+ case ACTION_FN:
-+ {
-+ g_halt = 1;
-+ while(g_pattern_playing)
-+ usleep(10);
-+ g_halt = 0;
-+ g_repeat = 0;
-+ g_speed = 30000;
-+ led_actions[i].action_fn(message, data);
-+ m_ledevent->Set();
-+ break;
-+ }
-+ default:
-+ {
-+ CLog::Log(LOGERROR, "Failed to execute LED action %d for event %s\n", i, led_actions[i].event_name);
-+ }
-+ }
-+ }
-+ }
-+
- // we are only interested in library changes
- if ((flag & (VideoLibrary | AudioLibrary)) == 0)
- return;
---- a/xbmc/windows/GUIWindowHome.h 2016-09-17 16:35:22.000000000 +0100
-+++ b/xbmc/windows/GUIWindowHome.h 2016-10-01 19:34:18.585113811 +0100
-@@ -23,6 +23,8 @@
- #include "guilib/GUIWindow.h"
- #include "interfaces/IAnnouncer.h"
- #include "utils/Job.h"
-+#include "threads/Thread.h"
-+#include "threads/Event.h"
-
- class CVariant;
-
-@@ -47,4 +49,7 @@
-
- bool m_recentlyAddedRunning;
- int m_cumulativeUpdateFlag;
-+
-+ CThread *m_ledthread;
-+ CEvent *m_ledevent;
- };
---- a/xbmc/windows/readpng.c 1970-01-01 00:00:00.000000000 +0000
-+++ b/xbmc/windows/readpng.c 2016-01-08 06:49:51.049652775 +0000
-@@ -0,0 +1,274 @@
-+/*---------------------------------------------------------------------------
-+
-+ rpng - simple PNG display program readpng.c
-+
-+ ---------------------------------------------------------------------------
-+
-+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
-+
-+ This software is provided "as is," without warranty of any kind,
-+ express or implied. In no event shall the author or contributors
-+ be held liable for any damages arising in any way from the use of
-+ this software.
-+
-+ Permission is granted to anyone to use this software for any purpose,
-+ including commercial applications, and to alter it and redistribute
-+ it freely, subject to the following restrictions:
-+
-+ 1. Redistributions of source code must retain the above copyright
-+ notice, disclaimer, and this list of conditions.
-+ 2. Redistributions in binary form must reproduce the above copyright
-+ notice, disclaimer, and this list of conditions in the documenta-
-+ tion and/or other materials provided with the distribution.
-+ 3. All advertising materials mentioning features or use of this
-+ software must display the following acknowledgment:
-+
-+ This product includes software developed by Greg Roelofs
-+ and contributors for the book, "PNG: The Definitive Guide,"
-+ published by O'Reilly and Associates.
-+
-+ ---------------------------------------------------------------------------*/
-+
-+#include
-+#include
-+
-+#include "png.h" /* libpng header; includes zlib.h */
-+#include "readpng.h" /* typedefs, common macros, public prototypes */
-+
-+
-+static png_structp png_ptr = NULL;
-+static png_infop info_ptr = NULL;
-+
-+png_uint_32 width, height;
-+int bit_depth, color_type;
-+uch *image_data = NULL;
-+
-+
-+void readpng_version_info(void)
-+{
-+ fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
-+ PNG_LIBPNG_VER_STRING, png_libpng_ver);
-+}
-+
-+
-+/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
-+
-+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
-+{
-+ uch sig[8];
-+
-+
-+ /* first do a quick check that the file really is a PNG image; could
-+ * have used slightly more general png_sig_cmp() function instead */
-+
-+ fread(sig, 1, 8, infile);
-+ if(png_sig_cmp(sig, 0, 8))
-+ return 1; /* bad signature */
-+
-+
-+ /* could pass pointers to user-defined error handlers instead of NULLs: */
-+
-+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-+ if (!png_ptr)
-+ return 4; /* out of memory */
-+
-+ info_ptr = png_create_info_struct(png_ptr);
-+ if (!info_ptr) {
-+ png_destroy_read_struct(&png_ptr, NULL, NULL);
-+ return 4; /* out of memory */
-+ }
-+
-+
-+ /* we could create a second info struct here (end_info), but it's only
-+ * useful if we want to keep pre- and post-IDAT chunk info separated
-+ * (mainly for PNG-aware image editors and converters) */
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return 2;
-+ }
-+
-+
-+ png_init_io(png_ptr, infile);
-+ png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
-+
-+ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
-+
-+
-+ /* alternatively, could make separate calls to png_get_image_width(),
-+ * etc., but want bit_depth and color_type for later [don't care about
-+ * compression_type and filter_type => NULLs] */
-+
-+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-+ NULL, NULL, NULL);
-+ *pWidth = width;
-+ *pHeight = height;
-+
-+
-+ /* OK, that's all we need for now; return happy */
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
-+ * scales values to 8-bit if necessary */
-+
-+int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
-+{
-+ png_color_16p pBackground;
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return 2;
-+ }
-+
-+
-+ if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
-+ return 1;
-+
-+ /* it is not obvious from the libpng documentation, but this function
-+ * takes a pointer to a pointer, and it always returns valid red, green
-+ * and blue values, regardless of color_type: */
-+
-+ png_get_bKGD(png_ptr, info_ptr, &pBackground);
-+
-+
-+ /* however, it always returns the raw bKGD data, regardless of any
-+ * bit-depth transformations, so check depth and adjust if necessary */
-+
-+ if (bit_depth == 16) {
-+ *red = pBackground->red >> 8;
-+ *green = pBackground->green >> 8;
-+ *blue = pBackground->blue >> 8;
-+ } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
-+ if (bit_depth == 1)
-+ *red = *green = *blue = pBackground->gray? 255 : 0;
-+ else if (bit_depth == 2)
-+ *red = *green = *blue = (255/3) * pBackground->gray;
-+ else /* bit_depth == 4 */
-+ *red = *green = *blue = (255/15) * pBackground->gray;
-+ } else {
-+ *red = (uch)pBackground->red;
-+ *green = (uch)pBackground->green;
-+ *blue = (uch)pBackground->blue;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+/* display_exponent == LUT_exponent * CRT_exponent */
-+
-+uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
-+{
-+ double gamma;
-+ png_uint_32 i, rowbytes;
-+ png_bytepp row_pointers = NULL;
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return NULL;
-+ }
-+
-+
-+ /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
-+ * transparency chunks to full alpha channel; strip 16-bit-per-sample
-+ * images to 8 bits per sample; and convert grayscale to RGB[A] */
-+
-+ if (color_type == PNG_COLOR_TYPE_PALETTE)
-+ png_set_expand(png_ptr);
-+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
-+ png_set_expand(png_ptr);
-+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
-+ png_set_expand(png_ptr);
-+ if (bit_depth == 16)
-+ png_set_strip_16(png_ptr);
-+ if (color_type == PNG_COLOR_TYPE_GRAY ||
-+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-+ png_set_gray_to_rgb(png_ptr);
-+
-+
-+ /* unlike the example in the libpng documentation, we have *no* idea where
-+ * this file may have come from--so if it doesn't have a file gamma, don't
-+ * do any correction ("do no harm") */
-+
-+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
-+ png_set_gamma(png_ptr, display_exponent, gamma);
-+
-+
-+ /* all transformations have been registered; now update info_ptr data,
-+ * get rowbytes and channels, and allocate image memory */
-+
-+ png_read_update_info(png_ptr, info_ptr);
-+
-+ *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
-+ *pChannels = (int)png_get_channels(png_ptr, info_ptr);
-+
-+ if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return NULL;
-+ }
-+ if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ free(image_data);
-+ image_data = NULL;
-+ return NULL;
-+ }
-+
-+ Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
-+
-+
-+ /* set the individual row_pointers to point at the correct offsets */
-+
-+ for (i = 0; i < height; ++i)
-+ row_pointers[i] = image_data + i*rowbytes;
-+
-+
-+ /* now we can go ahead and just read the whole image */
-+
-+ png_read_image(png_ptr, row_pointers);
-+
-+
-+ /* and we're done! (png_read_end() can be omitted if no processing of
-+ * post-IDAT text/time/etc. is desired) */
-+
-+ free(row_pointers);
-+ row_pointers = NULL;
-+
-+ png_read_end(png_ptr, NULL);
-+
-+ return image_data;
-+}
-+
-+
-+void readpng_cleanup(int free_image_data)
-+{
-+ if (free_image_data && image_data) {
-+ free(image_data);
-+ image_data = NULL;
-+ }
-+
-+ if (png_ptr && info_ptr) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ png_ptr = NULL;
-+ info_ptr = NULL;
-+ }
-+}
-+
---- a/xbmc/windows/readpng.h 1970-01-01 00:00:00.000000000 +0000
-+++ b/xbmc/windows/readpng.h 2016-01-08 06:49:51.049652775 +0000
-@@ -0,0 +1,65 @@
-+/*---------------------------------------------------------------------------
-+
-+ rpng - simple PNG display program readpng.h
-+
-+ ---------------------------------------------------------------------------
-+
-+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
-+
-+ This software is provided "as is," without warranty of any kind,
-+ express or implied. In no event shall the author or contributors
-+ be held liable for any damages arising in any way from the use of
-+ this software.
-+
-+ Permission is granted to anyone to use this software for any purpose,
-+ including commercial applications, and to alter it and redistribute
-+ it freely, subject to the following restrictions:
-+
-+ 1. Redistributions of source code must retain the above copyright
-+ notice, disclaimer, and this list of conditions.
-+ 2. Redistributions in binary form must reproduce the above copyright
-+ notice, disclaimer, and this list of conditions in the documenta-
-+ tion and/or other materials provided with the distribution.
-+ 3. All advertising materials mentioning features or use of this
-+ software must display the following acknowledgment:
-+
-+ This product includes software developed by Greg Roelofs
-+ and contributors for the book, "PNG: The Definitive Guide,"
-+ published by O'Reilly and Associates.
-+
-+ ---------------------------------------------------------------------------*/
-+
-+#ifndef TRUE
-+# define TRUE 1
-+# define FALSE 0
-+#endif
-+
-+#ifndef MAX
-+# define MAX(a,b) ((a) > (b)? (a) : (b))
-+# define MIN(a,b) ((a) < (b)? (a) : (b))
-+#endif
-+
-+#ifdef DEBUG
-+# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
-+#else
-+# define Trace(x) ;
-+#endif
-+
-+typedef unsigned char uch;
-+typedef unsigned short ush;
-+typedef unsigned long ulg;
-+
-+
-+/* prototypes for public functions in readpng.c */
-+
-+void readpng_version_info(void);
-+
-+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
-+
-+int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
-+
-+uch *readpng_get_image(double display_exponent, int *pChannels,
-+ ulg *pRowbytes);
-+
-+void readpng_cleanup(int free_image_data);
-+
diff --git a/projects/RPi/devices/Slice/patches/kodi/kodi-003-slice-audio.patch b/projects/RPi/devices/Slice/patches/kodi/kodi-003-slice-audio.patch
deleted file mode 100644
index 839cdaeee1..0000000000
--- a/projects/RPi/devices/Slice/patches/kodi/kodi-003-slice-audio.patch
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-09-17 16:35:20.000000000 +0100
-+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-10-01 19:26:40.470553260 +0100
-@@ -527,6 +527,7 @@
- m_info.m_wantsIECPassthrough = true;
- list.push_back(m_info);
-
-+#if 0
- m_info.m_channels.Reset();
- m_info.m_dataFormats.clear();
- m_info.m_streamTypes.clear();
-@@ -548,6 +549,7 @@
-
- m_info.m_wantsIECPassthrough = true;
- list.push_back(m_info);
-+#endif
-
- m_info.m_channels.Reset();
- m_info.m_dataFormats.clear();
diff --git a/projects/RPi/devices/Slice/patches/kodi/kodi-004-keyboard.patch b/projects/RPi/devices/Slice/patches/kodi/kodi-004-keyboard.patch
deleted file mode 100644
index 05158c998a..0000000000
--- a/projects/RPi/devices/Slice/patches/kodi/kodi-004-keyboard.patch
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/system/keymaps/keyboard.xml 2016-09-17 16:35:20.000000000 +0100
-+++ b/system/keymaps/keyboard.xml 2016-10-01 19:31:07.928719606 +0100
-@@ -56,7 +56,7 @@
-
- ContextMenu
- Menu
-- Pause
-+ PlayPause
- Stop
- SkipNext
- SkipPrevious
-@@ -321,8 +321,8 @@
- NextSubtitle
- StepBack
- StepForward
-- ChapterOrBigStepForward
-- ChapterOrBigStepBack
-+ VolumeUp
-+ VolumeDown
- AudioNextLanguage
- NextSubtitle
- AudioDelay
diff --git a/projects/RPi/devices/Slice/patches/kodi/kodi-005-cmake.patch b/projects/RPi/devices/Slice/patches/kodi/kodi-005-cmake.patch
deleted file mode 100644
index 81e238bd44..0000000000
--- a/projects/RPi/devices/Slice/patches/kodi/kodi-005-cmake.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff --git a/xbmc/windows/CMakeLists.txt b/xbmc/windows/CMakeLists.txt
-index 3700602..c75f78f 100644
---- a/xbmc/windows/CMakeLists.txt
-+++ b/xbmc/windows/CMakeLists.txt
-@@ -1,3 +1,5 @@
-+find_package(PNG REQUIRED)
-+
- set(SOURCES GUIMediaWindow.cpp
- GUIWindowDebugInfo.cpp
- GUIWindowFileManager.cpp
-@@ -9,7 +11,8 @@ set(SOURCES GUIMediaWindow.cpp
- GUIWindowSplash.cpp
- GUIWindowStartup.cpp
- GUIWindowSystemInfo.cpp
-- GUIWindowWeather.cpp)
-+ GUIWindowWeather.cpp
-+ readpng.c)
-
- set(HEADERS GUIMediaWindow.h
- GUIWindowDebugInfo.h
-@@ -22,6 +25,9 @@ set(HEADERS GUIMediaWindow.h
- GUIWindowSplash.h
- GUIWindowStartup.h
- GUIWindowSystemInfo.h
-- GUIWindowWeather.h)
-+ GUIWindowWeather.h
-+ readpng.h)
-
- core_add_library(windows)
-+
-+target_link_libraries(windows PRIVATE ${PNG_LIBRARIES})
diff --git a/projects/RPi/devices/Slice3/config/dt-blob.bin b/projects/RPi/devices/Slice3/config/dt-blob.bin
deleted file mode 100644
index 6958aae394..0000000000
Binary files a/projects/RPi/devices/Slice3/config/dt-blob.bin and /dev/null differ
diff --git a/projects/RPi/devices/Slice3/config/dt-blob.dts b/projects/RPi/devices/Slice3/config/dt-blob.dts
deleted file mode 100644
index 938b72fa2c..0000000000
--- a/projects/RPi/devices/Slice3/config/dt-blob.dts
+++ /dev/null
@@ -1,98 +0,0 @@
-/dts-v1/;
-
-/ {
- videocore {
-
- pins_cm3 {
-
- pin_config {
-
- pin@default {
- polarity = "active_high";
- termination = "pull_down";
- startup_state = "inactive";
- function = "input";
- }; // pin
-
- // BANK 0 //
- pin@p0 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p1 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p2 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p3 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p4 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p5 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p6 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p7 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p8 { function = "input"; termination = "pull_up"; }; // NOT USED (DEFAULT STATE)
- pin@p9 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p10 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p11 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p12 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p13 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p14 { function = "uart0"; termination = "no_pulling"; }; // UART0_TX
- pin@p15 { function = "uart0"; termination = "pull_up"; }; // UART0_RX
- pin@p16 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p17 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p18 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p19 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p20 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p21 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p22 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p23 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p24 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p25 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p26 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
- pin@p27 { function = "input"; termination = "pull_down"; }; // NOT USED (DEFAULT STATE)
-
- // BANK 1 //
- pin@p28 { function = "pcm"; termination = "no_pulling"; }; // PCM_CLK
- pin@p29 { function = "pcm"; termination = "no_pulling"; }; // PCM_FS
- pin@p30 { function = "pcm"; termination = "no_pulling"; }; // PCM_DIN
- pin@p31 { function = "pcm"; termination = "no_pulling"; }; // PCM_DOUT
- pin@p32 { function = "gp_clk"; termination = "no_pulling"; }; // PCM_MCLK (GPCLK0)
- pin@p33 { function = "output"; termination = "no_pulling"; polarity = "active_low"; startup_state = "inactive"; }; // AUD_RST_N
- pin@p34 { function = "input"; termination = "pull_up"; }; // NOT USED
- pin@p35 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "active"; }; // USB_ON
- pin@p36 { function = "input"; termination = "no_pulling"; }; // RTC_IRQ
- pin@p37 { function = "input"; termination = "no_pulling"; }; // IR_RX
- pin@p38 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // STBY_LED
- pin@p39 { function = "output"; termination = "no_pulling"; polarity = "active_high"; startup_state = "inactive"; }; // DISK_OFF
- pin@p40 { function = "pwm"; termination = "no_pulling"; }; // LED_PWM
- pin@p41 { function = "output"; termination = "no_pulling"; }; // LAN_RUN
- pin@p42 { function = "gp_clk"; termination = "no_pulling"; }; // ETH_CLK (GPCLK1)
- pin@p43 { function = "output"; termination = "pull_down"; polarity = "active_high"; startup_state = "inactive"; }; // LEDS_ON
- pin@p44 { function = "i2c1"; termination = "no_pulling"; }; // SDA1
- pin@p45 { function = "i2c1"; termination = "no_pulling"; }; // SCL1
-
- // BANK 2 //
- pin@p46 { function = "input"; termination = "pull_up"; }; // SMPS_SCL
- pin@p47 { function = "input"; termination = "pull_up"; }; // SMPS_SDA
- pin@p48 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CLK
- pin@p49 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD CMD
- pin@p50 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D0
- pin@p51 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D1
- pin@p52 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D2
- pin@p53 { function = "sdcard"; termination = "pull_up"; drive_strength_mA = <8>; }; // SD D3
- pin@p128 { function = "input"; termination = "no_pulling"; polarity = "active_low"; }; // Hotplug
- pin@p129 { function = "output"; termination = "no_pulling"; polarity = "active_low"; }; // EMMC_ENABLE_N
-
-
- }; // pin_config
-
- pin_defines {
- pin_define@HDMI_CONTROL_ATTACHED { type = "external"; number = <0>; }; // HPD_N on external gpio
- pin_define@LAN_RUN { type = "internal"; number = <41>; }; // LAN_RUN
- pin_define@EMMC_ENABLE { type = "external"; number = <1>; };
- pin_define@SMPS_SDA { type = "internal"; number = <46>; };
- pin_define@SMPS_SCL { type = "internal"; number = <47>; };
- }; // pin_defines
-
- }; // pins_cm
-
- clock_setup {
- clock@PWM { freq = < 2400000>; }; // LEDS PWM CLOCK
- clock@GPCLK1 { freq = <25000000>; }; // ETH_CLK
- }; // clock_setup
-
- }; // videocore
-};
diff --git a/projects/RPi/devices/Slice3/options b/projects/RPi/devices/Slice3/options
index a2566ab649..612ff1b53c 100644
--- a/projects/RPi/devices/Slice3/options
+++ b/projects/RPi/devices/Slice3/options
@@ -1,2 +1,2 @@
# Additional kernel make parameters
- KERNEL_MAKE_EXTRACMD+=" dt-blob.dtb overlays/slice.dtbo overlays/ws2812.dtbo"
+ KERNEL_MAKE_EXTRACMD+=" overlays/slice.dtbo overlays/ws2812.dtbo"
diff --git a/projects/RPi/devices/Slice3/patches/kodi/kodi-002-slice-led.patch b/projects/RPi/devices/Slice3/patches/kodi/kodi-002-slice-led.patch
deleted file mode 100644
index 6ba4cfb403..0000000000
--- a/projects/RPi/devices/Slice3/patches/kodi/kodi-002-slice-led.patch
+++ /dev/null
@@ -1,677 +0,0 @@
---- a/xbmc/windows/GUIWindowHome.cpp 2016-09-17 16:35:22.000000000 +0100
-+++ b/xbmc/windows/GUIWindowHome.cpp 2016-10-01 19:22:20.908566550 +0100
-@@ -30,9 +30,245 @@
- #include "guilib/GUIWindowManager.h"
- #include "Application.h"
- #include "utils/StringUtils.h"
-+extern "C"
-+{
-+ #include "readpng.h"
-+}
-
- using namespace ANNOUNCEMENT;
-
-+int g_pattern = 0;
-+int g_halt = 0;
-+int g_pattern_playing = 0;
-+int g_speed = 30000;
-+int g_repeat = 0;
-+
-+enum pattern_e {
-+ PAT_PLAY, PAT_PAUSE, PAT_STOP, PAT_SLEEP, PAT_WAKE, PAT_FFWD, PAT_REW, PAT_SKIPF, PAT_SKIPR, PAT_STARTUP, PAT_QUIT, PAT_NONE
-+};
-+#define NUM_PATTERNS 11
-+const char *patterns[NUM_PATTERNS] = {
-+ "play" , "pause", "stop", "sleep", "wake", "ffwd", "rew", "skipf", "skipr", "startup", "quit"
-+};
-+
-+void on_speed_changed(const char *message, const CVariant &data)
-+{
-+ int speed = data["player"]["speed"].asInteger();
-+
-+ CLog::Log(LOGDEBUG, "speed changed %d", speed);
-+
-+ switch(abs(speed))
-+ {
-+ case 1: g_speed = 60000; break;
-+ case 2: g_speed = 40000; break;
-+ case 4: g_speed = 35000; break;
-+ case 8: g_speed = 30000; break;
-+ case 16: g_speed = 25000; break;
-+ case 32: g_speed = 15000; break;
-+ }
-+
-+ if(speed > 0)
-+ g_pattern = PAT_FFWD;
-+ else
-+ g_pattern = PAT_REW;
-+
-+ if(speed != 1)
-+ g_repeat = 1;
-+ else
-+ {
-+ g_repeat = 0;
-+ g_pattern = PAT_NONE;
-+ }
-+}
-+
-+void on_seek(const char *message, const CVariant &data)
-+{
-+ int seek_time = data["player"]["seekoffset"]["seconds"].asInteger() +
-+ data["player"]["seekoffset"]["minutes"].asInteger() * 60;
-+
-+ CLog::Log(LOGDEBUG, "Seek offset = %d", seek_time);
-+ if(seek_time > 0)
-+ {
-+ g_pattern = PAT_SKIPF;
-+ }
-+ else
-+ {
-+ g_pattern = PAT_SKIPR;
-+ }
-+
-+ g_repeat = 0;
-+}
-+
-+enum action_e {
-+ ACTION_DO, ACTION_REPEAT, ACTION_FN
-+ };
-+
-+enum led_state_e {
-+ LED_STATE_INVALID = 0,
-+ LED_STATE_IDLE,
-+ LED_STATE_PLAYING,
-+ LED_STATE_PAUSED,
-+ LED_STATE_SLEEP
-+};
-+
-+struct led_action_s {
-+ const char * event_name;
-+ enum action_e action;
-+ enum pattern_e action_data;
-+ void (*action_fn)(const char *, const CVariant &);
-+ led_state_e action_state;
-+} led_actions[] = {
-+ { "OnPlay", ACTION_DO, PAT_PLAY, NULL, LED_STATE_PLAYING },
-+ { "OnPause", ACTION_DO, PAT_PAUSE, NULL, LED_STATE_PAUSED },
-+ { "OnStop", ACTION_DO, PAT_STOP, NULL, LED_STATE_IDLE },
-+ { "OnSpeedChanged", ACTION_FN, PAT_NONE, on_speed_changed, LED_STATE_INVALID },
-+ { "OnSeek", ACTION_FN, PAT_NONE, on_seek, LED_STATE_INVALID },
-+ { "OnScreensaverActivated", ACTION_DO, PAT_SLEEP, NULL, LED_STATE_SLEEP },
-+ { "OnScreensaverDeactivated", ACTION_DO, PAT_WAKE, NULL, LED_STATE_IDLE },
-+ { "OnQuit", ACTION_REPEAT, PAT_QUIT, NULL, LED_STATE_IDLE },
-+};
-+
-+int zeroes[25] = { 0,};
-+
-+class CLedPattern : public IRunnable
-+{
-+ int m_going;
-+ CEvent *m_ev;
-+ struct pattern {
-+ unsigned long w;
-+ unsigned long h;
-+ unsigned long rowbytes;
-+ unsigned char * img;
-+ } m_pattern[NUM_PATTERNS];
-+
-+ void open_patterns()
-+ {
-+ unsigned int i;
-+ for(i = 0; i < sizeof(patterns)/sizeof(patterns[0]); i++)
-+ {
-+ FILE * fp;
-+ char filename[256];
-+ int channels;
-+
-+ m_pattern[i].img = NULL;
-+ sprintf(filename, "/storage/.kodi/media/ledpatterns/%s.png", patterns[i]);
-+ fp = fopen(filename , "rb");
-+ if(fp == NULL)
-+ {
-+ sprintf(filename, "/usr/share/kodi/media/ledpatterns/%s.png", patterns[i]);
-+ fp = fopen(filename, "rb");
-+ if(fp == NULL)
-+ {
-+ CLog::Log(LOGDEBUG, "Unable to open file %s", filename);
-+ goto drop_out;
-+ }
-+ }
-+
-+ if(readpng_init(fp, &m_pattern[i].w, &m_pattern[i].h) != 0)
-+ {
-+ CLog::Log(LOGERROR, "Unable to parse png files %s", filename);
-+ goto drop_out;
-+ }
-+
-+ m_pattern[i].img = readpng_get_image(1.0, &channels, &m_pattern[i].rowbytes);
-+ if(m_pattern[i].img == NULL || channels != 4)
-+ {
-+ CLog::Log(LOGERROR, "Invalid png %s, width = %lu, height = %lu, channels = %d, rowbytes = %lu",
-+ filename, m_pattern[i].w, m_pattern[i].h, channels, m_pattern[i].rowbytes);
-+ goto drop_out;
-+ }
-+
-+ CLog::Log(LOGDEBUG, "Opened %s: (%lu x %lu)", filename, m_pattern[i].w, m_pattern[i].h);
-+
-+drop_out:
-+ if(fp)
-+ fclose(fp);
-+
-+ }
-+ }
-+
-+ void play_pattern(int pat)
-+ {
-+ int fd = open("/dev/ws2812", O_WRONLY, 0);
-+ if(fd < 0)
-+ {
-+ CLog::Log(LOGERROR, "Unable to open /dev/ws2812");
-+ }
-+ else
-+ {
-+ if(pat < PAT_NONE && m_pattern[pat].img != NULL)
-+ {
-+ CLog::Log(LOGDEBUG, "playing pattern");
-+ g_pattern_playing = 1;
-+ do
-+ {
-+ unsigned char * p_line = m_pattern[pat].img;
-+ unsigned int i;
-+
-+ for(i = 0; i < m_pattern[pat].h; i++)
-+ {
-+ write(fd, p_line, m_pattern[pat].w * 4);
-+ if(m_pattern[pat].w == 26)
-+ {
-+ int *p = (int *) (p_line + (25 * 4));
-+ usleep(*p);
-+ }
-+ else
-+ {
-+ usleep(g_speed);
-+ }
-+ p_line += m_pattern[pat].rowbytes;
-+ // If we get the g_halt signal then stop repeating
-+ // the pattern
-+ if(g_halt)
-+ {
-+ g_halt = 0;
-+ g_repeat = 0;
-+ break;
-+ }
-+ }
-+ p_line += m_pattern[pat].rowbytes;
-+ }
-+ while(g_repeat);
-+ g_pattern_playing = 0;
-+
-+ if(pat != PAT_QUIT)
-+ write(fd, zeroes, sizeof(zeroes));
-+ }
-+ else
-+ {
-+ CLog::Log(LOGDEBUG, "No img for LED pattern %d", pat);
-+ }
-+ close(fd);
-+ }
-+ }
-+
-+public:
-+ CLedPattern(CEvent *ev)
-+ {
-+ CLog::Log(LOGDEBUG, "Initialising CLedPattern");
-+ open_patterns();
-+ m_ev = ev;
-+ }
-+
-+ void Run()
-+ {
-+ m_going = 1;
-+ while(m_going)
-+ {
-+ m_ev->Wait();
-+ CLog::Log(LOGDEBUG, "Led Pattern %d triggered", g_pattern);
-+ play_pattern(g_pattern);
-+ }
-+ }
-+
-+ void Stop()
-+ {
-+ m_going = 0;
-+ m_ev->Set();
-+ }
-+};
-+
- CGUIWindowHome::CGUIWindowHome(void) : CGUIWindow(WINDOW_HOME, "Home.xml"),
- m_recentlyAddedRunning(false),
- m_cumulativeUpdateFlag(0)
-@@ -40,6 +276,14 @@ CGUIWindowHome::CGUIWindowHome(void) : C
- m_updateRA = (Audio | Video | Totals);
- m_loadType = KEEP_IN_MEMORY;
-
-+ m_ledevent = new CEvent();
-+ m_ledthread = new CThread(new CLedPattern(m_ledevent), "LedThread");
-+ m_ledthread->Create();
-+ g_pattern = PAT_STARTUP;
-+ g_speed = 30000;
-+ g_repeat = 0;
-+ m_ledevent->Set();
-+
- CAnnouncementManager::GetInstance().AddAnnouncer(this);
- }
-
-@@ -75,10 +319,49 @@ void CGUIWindowHome::OnInitWindow()
-
- void CGUIWindowHome::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
- {
-+ unsigned int i;
- int ra_flag = 0;
-
- CLog::Log(LOGDEBUG, "GOT ANNOUNCEMENT, type: %i, from %s, message %s",(int)flag, sender, message);
-
-+ for(i = 0; i < sizeof(led_actions)/sizeof(led_actions[0]); i++)
-+ {
-+ if(strcmp(message, led_actions[i].event_name) == 0)
-+ {
-+ switch(led_actions[i].action) {
-+ case ACTION_DO:
-+ case ACTION_REPEAT:
-+ {
-+ g_halt = 1;
-+ while(g_pattern_playing)
-+ usleep(10);
-+ g_halt = 0;
-+ g_repeat = (led_actions[i].action == ACTION_DO) ? 0 : 1;
-+ g_speed = 30000;
-+ g_pattern = (int) led_actions[i].action_data;
-+ m_ledevent->Set();
-+ break;
-+ }
-+ case ACTION_FN:
-+ {
-+ g_halt = 1;
-+ while(g_pattern_playing)
-+ usleep(10);
-+ g_halt = 0;
-+ g_repeat = 0;
-+ g_speed = 30000;
-+ led_actions[i].action_fn(message, data);
-+ m_ledevent->Set();
-+ break;
-+ }
-+ default:
-+ {
-+ CLog::Log(LOGERROR, "Failed to execute LED action %d for event %s\n", i, led_actions[i].event_name);
-+ }
-+ }
-+ }
-+ }
-+
- // we are only interested in library changes
- if ((flag & (VideoLibrary | AudioLibrary)) == 0)
- return;
---- a/xbmc/windows/GUIWindowHome.h 2016-09-17 16:35:22.000000000 +0100
-+++ b/xbmc/windows/GUIWindowHome.h 2016-10-01 19:34:18.585113811 +0100
-@@ -23,6 +23,8 @@
- #include "guilib/GUIWindow.h"
- #include "interfaces/IAnnouncer.h"
- #include "utils/Job.h"
-+#include "threads/Thread.h"
-+#include "threads/Event.h"
-
- class CVariant;
-
-@@ -47,4 +49,7 @@
-
- bool m_recentlyAddedRunning;
- int m_cumulativeUpdateFlag;
-+
-+ CThread *m_ledthread;
-+ CEvent *m_ledevent;
- };
---- a/xbmc/windows/readpng.c 1970-01-01 00:00:00.000000000 +0000
-+++ b/xbmc/windows/readpng.c 2016-01-08 06:49:51.049652775 +0000
-@@ -0,0 +1,274 @@
-+/*---------------------------------------------------------------------------
-+
-+ rpng - simple PNG display program readpng.c
-+
-+ ---------------------------------------------------------------------------
-+
-+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
-+
-+ This software is provided "as is," without warranty of any kind,
-+ express or implied. In no event shall the author or contributors
-+ be held liable for any damages arising in any way from the use of
-+ this software.
-+
-+ Permission is granted to anyone to use this software for any purpose,
-+ including commercial applications, and to alter it and redistribute
-+ it freely, subject to the following restrictions:
-+
-+ 1. Redistributions of source code must retain the above copyright
-+ notice, disclaimer, and this list of conditions.
-+ 2. Redistributions in binary form must reproduce the above copyright
-+ notice, disclaimer, and this list of conditions in the documenta-
-+ tion and/or other materials provided with the distribution.
-+ 3. All advertising materials mentioning features or use of this
-+ software must display the following acknowledgment:
-+
-+ This product includes software developed by Greg Roelofs
-+ and contributors for the book, "PNG: The Definitive Guide,"
-+ published by O'Reilly and Associates.
-+
-+ ---------------------------------------------------------------------------*/
-+
-+#include
-+#include
-+
-+#include "png.h" /* libpng header; includes zlib.h */
-+#include "readpng.h" /* typedefs, common macros, public prototypes */
-+
-+
-+static png_structp png_ptr = NULL;
-+static png_infop info_ptr = NULL;
-+
-+png_uint_32 width, height;
-+int bit_depth, color_type;
-+uch *image_data = NULL;
-+
-+
-+void readpng_version_info(void)
-+{
-+ fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
-+ PNG_LIBPNG_VER_STRING, png_libpng_ver);
-+}
-+
-+
-+/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
-+
-+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
-+{
-+ uch sig[8];
-+
-+
-+ /* first do a quick check that the file really is a PNG image; could
-+ * have used slightly more general png_sig_cmp() function instead */
-+
-+ fread(sig, 1, 8, infile);
-+ if(png_sig_cmp(sig, 0, 8))
-+ return 1; /* bad signature */
-+
-+
-+ /* could pass pointers to user-defined error handlers instead of NULLs: */
-+
-+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-+ if (!png_ptr)
-+ return 4; /* out of memory */
-+
-+ info_ptr = png_create_info_struct(png_ptr);
-+ if (!info_ptr) {
-+ png_destroy_read_struct(&png_ptr, NULL, NULL);
-+ return 4; /* out of memory */
-+ }
-+
-+
-+ /* we could create a second info struct here (end_info), but it's only
-+ * useful if we want to keep pre- and post-IDAT chunk info separated
-+ * (mainly for PNG-aware image editors and converters) */
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return 2;
-+ }
-+
-+
-+ png_init_io(png_ptr, infile);
-+ png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
-+
-+ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
-+
-+
-+ /* alternatively, could make separate calls to png_get_image_width(),
-+ * etc., but want bit_depth and color_type for later [don't care about
-+ * compression_type and filter_type => NULLs] */
-+
-+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-+ NULL, NULL, NULL);
-+ *pWidth = width;
-+ *pHeight = height;
-+
-+
-+ /* OK, that's all we need for now; return happy */
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+/* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
-+ * scales values to 8-bit if necessary */
-+
-+int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
-+{
-+ png_color_16p pBackground;
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return 2;
-+ }
-+
-+
-+ if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
-+ return 1;
-+
-+ /* it is not obvious from the libpng documentation, but this function
-+ * takes a pointer to a pointer, and it always returns valid red, green
-+ * and blue values, regardless of color_type: */
-+
-+ png_get_bKGD(png_ptr, info_ptr, &pBackground);
-+
-+
-+ /* however, it always returns the raw bKGD data, regardless of any
-+ * bit-depth transformations, so check depth and adjust if necessary */
-+
-+ if (bit_depth == 16) {
-+ *red = pBackground->red >> 8;
-+ *green = pBackground->green >> 8;
-+ *blue = pBackground->blue >> 8;
-+ } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
-+ if (bit_depth == 1)
-+ *red = *green = *blue = pBackground->gray? 255 : 0;
-+ else if (bit_depth == 2)
-+ *red = *green = *blue = (255/3) * pBackground->gray;
-+ else /* bit_depth == 4 */
-+ *red = *green = *blue = (255/15) * pBackground->gray;
-+ } else {
-+ *red = (uch)pBackground->red;
-+ *green = (uch)pBackground->green;
-+ *blue = (uch)pBackground->blue;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+
-+
-+/* display_exponent == LUT_exponent * CRT_exponent */
-+
-+uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
-+{
-+ double gamma;
-+ png_uint_32 i, rowbytes;
-+ png_bytepp row_pointers = NULL;
-+
-+
-+ /* setjmp() must be called in every function that calls a PNG-reading
-+ * libpng function */
-+
-+ if (setjmp(png_jmpbuf(png_ptr))) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return NULL;
-+ }
-+
-+
-+ /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
-+ * transparency chunks to full alpha channel; strip 16-bit-per-sample
-+ * images to 8 bits per sample; and convert grayscale to RGB[A] */
-+
-+ if (color_type == PNG_COLOR_TYPE_PALETTE)
-+ png_set_expand(png_ptr);
-+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
-+ png_set_expand(png_ptr);
-+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
-+ png_set_expand(png_ptr);
-+ if (bit_depth == 16)
-+ png_set_strip_16(png_ptr);
-+ if (color_type == PNG_COLOR_TYPE_GRAY ||
-+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-+ png_set_gray_to_rgb(png_ptr);
-+
-+
-+ /* unlike the example in the libpng documentation, we have *no* idea where
-+ * this file may have come from--so if it doesn't have a file gamma, don't
-+ * do any correction ("do no harm") */
-+
-+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
-+ png_set_gamma(png_ptr, display_exponent, gamma);
-+
-+
-+ /* all transformations have been registered; now update info_ptr data,
-+ * get rowbytes and channels, and allocate image memory */
-+
-+ png_read_update_info(png_ptr, info_ptr);
-+
-+ *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
-+ *pChannels = (int)png_get_channels(png_ptr, info_ptr);
-+
-+ if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ return NULL;
-+ }
-+ if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ free(image_data);
-+ image_data = NULL;
-+ return NULL;
-+ }
-+
-+ Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height));
-+
-+
-+ /* set the individual row_pointers to point at the correct offsets */
-+
-+ for (i = 0; i < height; ++i)
-+ row_pointers[i] = image_data + i*rowbytes;
-+
-+
-+ /* now we can go ahead and just read the whole image */
-+
-+ png_read_image(png_ptr, row_pointers);
-+
-+
-+ /* and we're done! (png_read_end() can be omitted if no processing of
-+ * post-IDAT text/time/etc. is desired) */
-+
-+ free(row_pointers);
-+ row_pointers = NULL;
-+
-+ png_read_end(png_ptr, NULL);
-+
-+ return image_data;
-+}
-+
-+
-+void readpng_cleanup(int free_image_data)
-+{
-+ if (free_image_data && image_data) {
-+ free(image_data);
-+ image_data = NULL;
-+ }
-+
-+ if (png_ptr && info_ptr) {
-+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
-+ png_ptr = NULL;
-+ info_ptr = NULL;
-+ }
-+}
-+
---- a/xbmc/windows/readpng.h 1970-01-01 00:00:00.000000000 +0000
-+++ b/xbmc/windows/readpng.h 2016-01-08 06:49:51.049652775 +0000
-@@ -0,0 +1,65 @@
-+/*---------------------------------------------------------------------------
-+
-+ rpng - simple PNG display program readpng.h
-+
-+ ---------------------------------------------------------------------------
-+
-+ Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
-+
-+ This software is provided "as is," without warranty of any kind,
-+ express or implied. In no event shall the author or contributors
-+ be held liable for any damages arising in any way from the use of
-+ this software.
-+
-+ Permission is granted to anyone to use this software for any purpose,
-+ including commercial applications, and to alter it and redistribute
-+ it freely, subject to the following restrictions:
-+
-+ 1. Redistributions of source code must retain the above copyright
-+ notice, disclaimer, and this list of conditions.
-+ 2. Redistributions in binary form must reproduce the above copyright
-+ notice, disclaimer, and this list of conditions in the documenta-
-+ tion and/or other materials provided with the distribution.
-+ 3. All advertising materials mentioning features or use of this
-+ software must display the following acknowledgment:
-+
-+ This product includes software developed by Greg Roelofs
-+ and contributors for the book, "PNG: The Definitive Guide,"
-+ published by O'Reilly and Associates.
-+
-+ ---------------------------------------------------------------------------*/
-+
-+#ifndef TRUE
-+# define TRUE 1
-+# define FALSE 0
-+#endif
-+
-+#ifndef MAX
-+# define MAX(a,b) ((a) > (b)? (a) : (b))
-+# define MIN(a,b) ((a) < (b)? (a) : (b))
-+#endif
-+
-+#ifdef DEBUG
-+# define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);}
-+#else
-+# define Trace(x) ;
-+#endif
-+
-+typedef unsigned char uch;
-+typedef unsigned short ush;
-+typedef unsigned long ulg;
-+
-+
-+/* prototypes for public functions in readpng.c */
-+
-+void readpng_version_info(void);
-+
-+int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
-+
-+int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
-+
-+uch *readpng_get_image(double display_exponent, int *pChannels,
-+ ulg *pRowbytes);
-+
-+void readpng_cleanup(int free_image_data);
-+
diff --git a/projects/RPi/devices/Slice3/patches/kodi/kodi-003-slice-audio.patch b/projects/RPi/devices/Slice3/patches/kodi/kodi-003-slice-audio.patch
deleted file mode 100644
index 839cdaeee1..0000000000
--- a/projects/RPi/devices/Slice3/patches/kodi/kodi-003-slice-audio.patch
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-09-17 16:35:20.000000000 +0100
-+++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp 2016-10-01 19:26:40.470553260 +0100
-@@ -527,6 +527,7 @@
- m_info.m_wantsIECPassthrough = true;
- list.push_back(m_info);
-
-+#if 0
- m_info.m_channels.Reset();
- m_info.m_dataFormats.clear();
- m_info.m_streamTypes.clear();
-@@ -548,6 +549,7 @@
-
- m_info.m_wantsIECPassthrough = true;
- list.push_back(m_info);
-+#endif
-
- m_info.m_channels.Reset();
- m_info.m_dataFormats.clear();
diff --git a/projects/RPi/devices/Slice3/patches/kodi/kodi-004-keyboard.patch b/projects/RPi/devices/Slice3/patches/kodi/kodi-004-keyboard.patch
deleted file mode 100644
index 05158c998a..0000000000
--- a/projects/RPi/devices/Slice3/patches/kodi/kodi-004-keyboard.patch
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/system/keymaps/keyboard.xml 2016-09-17 16:35:20.000000000 +0100
-+++ b/system/keymaps/keyboard.xml 2016-10-01 19:31:07.928719606 +0100
-@@ -56,7 +56,7 @@
-
- ContextMenu
- Menu
-- Pause
-+ PlayPause
- Stop
- SkipNext
- SkipPrevious
-@@ -321,8 +321,8 @@
- NextSubtitle
- StepBack
- StepForward
-- ChapterOrBigStepForward
-- ChapterOrBigStepBack
-+ VolumeUp
-+ VolumeDown
- AudioNextLanguage
- NextSubtitle
- AudioDelay
diff --git a/projects/RPi/devices/Slice3/patches/kodi/kodi-005-cmake.patch b/projects/RPi/devices/Slice3/patches/kodi/kodi-005-cmake.patch
deleted file mode 100644
index 81e238bd44..0000000000
--- a/projects/RPi/devices/Slice3/patches/kodi/kodi-005-cmake.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff --git a/xbmc/windows/CMakeLists.txt b/xbmc/windows/CMakeLists.txt
-index 3700602..c75f78f 100644
---- a/xbmc/windows/CMakeLists.txt
-+++ b/xbmc/windows/CMakeLists.txt
-@@ -1,3 +1,5 @@
-+find_package(PNG REQUIRED)
-+
- set(SOURCES GUIMediaWindow.cpp
- GUIWindowDebugInfo.cpp
- GUIWindowFileManager.cpp
-@@ -9,7 +11,8 @@ set(SOURCES GUIMediaWindow.cpp
- GUIWindowSplash.cpp
- GUIWindowStartup.cpp
- GUIWindowSystemInfo.cpp
-- GUIWindowWeather.cpp)
-+ GUIWindowWeather.cpp
-+ readpng.c)
-
- set(HEADERS GUIMediaWindow.h
- GUIWindowDebugInfo.h
-@@ -22,6 +25,9 @@ set(HEADERS GUIMediaWindow.h
- GUIWindowSplash.h
- GUIWindowStartup.h
- GUIWindowSystemInfo.h
-- GUIWindowWeather.h)
-+ GUIWindowWeather.h
-+ readpng.h)
-
- core_add_library(windows)
-+
-+target_link_libraries(windows PRIVATE ${PNG_LIBRARIES})
diff --git a/projects/RPi/options b/projects/RPi/options
index 14b6b39415..f95c0cdc59 100644
--- a/projects/RPi/options
+++ b/projects/RPi/options
@@ -137,6 +137,10 @@ fi
# e.g. FIRMWARE="dvb-firmware misc-firmware wlan-firmware"
FIRMWARE="misc-firmware wlan-firmware dvb-firmware brcmfmac_sdio-firmware-rpi"
+ if [ "$DEVICE" = "Slice" -o "$DEVICE" = "Slice3" ]; then
+ FIRMWARE="$FIRMWARE slice-firmware"
+ fi
+
# build and install ATV IR remote support (yes / no)
ATVCLIENT_SUPPORT="no"
@@ -155,3 +159,7 @@ fi
# Space separated list is supported,
# e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2"
ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS media_build rpi-cirrus-config"
+
+ if [ "$DEVICE" = "Slice" -o "$DEVICE" = "Slice3" ]; then
+ ADDITIONAL_DRIVERS="$ADDITIONAL_DRIVERS slice-drivers"
+ fi
diff --git a/projects/RPi/patches/linux/linux-01-misc-Kconfig.patch b/projects/RPi/patches/linux/linux-01-misc-Kconfig.patch
deleted file mode 100644
index e30677018d..0000000000
--- a/projects/RPi/patches/linux/linux-01-misc-Kconfig.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/misc/Kconfig 2016-10-01 08:57:18.219952947 +0100
-+++ b/drivers/misc/Kconfig 2016-10-01 09:18:14.792293152 +0100
-@@ -4,6 +4,9 @@
-
- menu "Misc devices"
-
-+config BCM2835_WS2812
-+ tristate "Support DMA user access to WS2812 LEDs"
-+
- config SENSORS_LIS3LV02D
- tristate
- depends on INPUT
diff --git a/projects/RPi/patches/linux/linux-02-misc-Makefile.patch b/projects/RPi/patches/linux/linux-02-misc-Makefile.patch
deleted file mode 100644
index f4ad6286bd..0000000000
--- a/projects/RPi/patches/linux/linux-02-misc-Makefile.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/misc/Makefile 2016-10-01 09:14:16.810942127 +0100
-+++ b/drivers/misc/Makefile 2016-10-01 09:14:05.458686888 +0100
-@@ -2,6 +2,7 @@
- # Makefile for misc devices that really don't fit anywhere else.
- #
-
-+obj-$(CONFIG_BCM2835_WS2812) += ws2812.o
- obj-$(CONFIG_IBM_ASM) += ibmasm/
- obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
- obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
diff --git a/projects/RPi/patches/linux/linux-03-ws2807-c.patch b/projects/RPi/patches/linux/linux-03-ws2807-c.patch
deleted file mode 100644
index 24eedd81ae..0000000000
--- a/projects/RPi/patches/linux/linux-03-ws2807-c.patch
+++ /dev/null
@@ -1,539 +0,0 @@
---- a/drivers/misc/ws2812.c 2016-08-17 21:00:22.264000134 +0100
-+++ b/drivers/misc/ws2812.c 2016-10-04 14:12:32.512699063 +0100
-@@ -0,0 +1,536 @@
-+/*
-+ * Raspberry Pi WS2812 PWM driver
-+ *
-+ * Written by: Gordon Hollingworth
-+ * Based on DMA PWM driver from Jonathan Bell
-+ *
-+ * Copyright (C) 2014 Raspberry Pi Ltd.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ * To use this driver you need to make sure that the PWM clock is set to 2.4MHz
-+ * and the correct PWM0 output is connected. The best way to do this is to
-+ * create a dt-blob.bin on your RaspberryPi, start by downloading the default
-+ * dt-blob.dts from
-+ *
-+ * Note, this uses the same PWM hardware as the standard audio output on the Pi
-+ * so you cannot use both simultaneously.
-+ *
-+ * http://www.raspberrypi.org/documentation/configuration/pin-configuration.md
-+ *
-+ * (Copy the bit from /dts-v1/; through to the end... This will contain the pin
-+ * configuration for all the Raspberry Pi versions (since they are different.
-+ * You can get rid of the ones you don't care about. Next alter the PWM0 output
-+ * you want to use.
-+ *
-+ * http://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf
-+ *
-+ * The link above will help understand what the GPIOs can do, check out page 102
-+ * You can use: GPIO12, GPIO18 or GPIO40, so for the Slice board we use GPIO40 so
-+ * we have the following in the dts file
-+ *
-+ * pin@p40 {
-+ * function = "pwm";
-+ * termination = "no_pulling";
-+ * };
-+ *
-+ * And at the bottom of the dts file, although still in the 'videocore' block we
-+ * have:
-+ *
-+ * clock_setup {
-+ * clock@PWM { freq = <2400000>; };
-+ * };
-+ *
-+ * To check whether the changes are correct you can use 'vcgencmd measure_clock 25'
-+ * This should return the value 2400000
-+ *
-+ * Also if you use wiringPi then you can do 'gpio readall' to check that the pin
-+ * alternate setting is set correctly.
-+ *
-+ */
-+
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+#include
-+
-+#define DRIVER_NAME "ws2812"
-+
-+struct ws2812_state {
-+ struct device * dev;
-+ struct cdev cdev;
-+ struct class * cl;
-+ struct dma_chan * dma_chan;
-+ dma_addr_t dma_addr;
-+
-+ void __iomem * ioaddr;
-+ phys_addr_t phys_addr;
-+
-+ uint8_t * buffer;
-+ uint32_t * pixbuf;
-+
-+ struct gpio_desc * led_en;
-+
-+ unsigned char brightness;
-+ u32 invert;
-+ u32 num_leds;
-+};
-+
-+#ifndef BCM2708_PERI_BASE
-+ #define BCM2708_PERI_BASE 0x20000000
-+#endif
-+
-+#define BCM2835_VCMMU_SHIFT (0x7E000000 - BCM2708_PERI_BASE)
-+
-+/* Each LED is controlled with a 24 bit RGB value
-+ * each bit is created from a nibble of data either
-+ * 1000 or 1110 so to create 24 bits you need 12 bytes
-+ * of PWM output
-+ */
-+#define BYTES_PER_LED 12
-+
-+// Number of 2.4MHz bits in 50us to create a reset condition
-+#define RESET_BYTES ((50 * 24) / 80)
-+
-+#define PWM_CTL 0x0
-+#define PWM_STA 0x4
-+#define PWM_DMAC 0x8
-+#define PWM_RNG1 0x10
-+#define PWM_DAT1 0x14
-+#define PWM_FIFO1 0x18
-+#define PWM_ID 0x50
-+
-+#define PWM_DMA_DREQ 5
-+
-+static dev_t devid = MKDEV(1337, 0);
-+
-+/*
-+** Functions to access the pwm peripheral
-+*/
-+static void pwm_writel(struct ws2812_state * state, uint32_t val, uint32_t reg)
-+{
-+ writel(val, state->ioaddr + reg);
-+}
-+
-+#if 0
-+static uint32_t pwm_readl(struct ws2812_state * state, uint32_t reg)
-+{
-+ return readl(state->ioaddr + reg);
-+}
-+#endif
-+
-+/* Initialise the PWM module to use serial output
-+ * mode
-+ */
-+static int pwm_init(struct ws2812_state * state)
-+{
-+ uint32_t reg;
-+
-+ // serial 32 bits per word
-+ pwm_writel(state, 32, PWM_RNG1);
-+ // Clear
-+ pwm_writel(state, 0, PWM_DAT1);
-+
-+ reg = (1 << 0) | /* CH1EN */
-+ (1 << 1) | /* serialiser */
-+ (0 << 2) | /* don't repeat last word */
-+ (0 << 3) | /* silence is zero */
-+ ((state->invert ? 1 : 0) << 4) | /* polarity */
-+ (1 << 5) | /* use fifo */
-+ (1 << 6) | /* Clear fifo */
-+ (1 << 7) | /* MSEN - Mask space enable */
-+ ((state->invert ? 1 : 0) << 11); /* Silence bit = 1 */
-+ pwm_writel(state, reg, PWM_CTL);
-+ reg = (1 << 31) | /* DMA enabled */
-+ (4 << 8) | /* Threshold for panic */
-+ (8 << 0); /* Threshold for dreq */
-+ pwm_writel(state, reg, PWM_DMAC);
-+
-+ return 0;
-+
-+}
-+
-+/*
-+ * DMA callback function, release the mapping and the calling function
-+ */
-+void ws2812_callback(void * param)
-+{
-+ struct ws2812_state * state = (struct ws2812_state *) param;
-+
-+ dma_unmap_single(state->dev, state->dma_addr, state->num_leds * BYTES_PER_LED,
-+ DMA_TO_DEVICE);
-+
-+}
-+
-+/*
-+ * Issue a DMA to the PWM peripheral from the assigned buffer
-+ * buffer must be unmapped again before being used
-+ */
-+int issue_dma(struct ws2812_state * state, uint8_t *buffer, int length)
-+{
-+ struct dma_async_tx_descriptor *desc;
-+
-+ state->dma_addr = dma_map_single(state->dev,
-+ buffer, length,
-+ DMA_TO_DEVICE);
-+
-+ if(state->dma_addr == 0)
-+ {
-+ pr_err("Failed to map buffer for DMA\n");
-+ return -1;
-+ }
-+
-+ desc = dmaengine_prep_slave_single(state->dma_chan, state->dma_addr,
-+ length, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);
-+ if(desc == NULL)
-+ {
-+ pr_err("Failed to prep the DMA transfer\n");
-+ return -1;
-+ }
-+
-+ desc->callback = ws2812_callback;
-+ desc->callback_param = state;
-+ dmaengine_submit(desc);
-+ dma_async_issue_pending(state->dma_chan);
-+
-+ return 0;
-+}
-+
-+
-+int clear_leds(struct ws2812_state * state)
-+{
-+ int i;
-+
-+ for(i = 0; i < state->num_leds * BYTES_PER_LED; i++)
-+ state->buffer[i] = 0x88;
-+ for(i = 0; i < RESET_BYTES; i++)
-+ state->buffer[state->num_leds * BYTES_PER_LED + i] = 0;
-+
-+ issue_dma(state, state->buffer, state->num_leds * BYTES_PER_LED + RESET_BYTES);
-+
-+ return 0;
-+}
-+
-+static int ws2812_open(struct inode *inode, struct file *file)
-+{
-+ struct ws2812_state * state;
-+ state = container_of(inode->i_cdev, struct ws2812_state, cdev);
-+
-+ file->private_data = state;
-+
-+ return 0;
-+}
-+
-+/* WS2812B gamma correction
-+GammaE=255*(res/255).^(1/.45)
-+From: http://rgb-123.com/ws2812-color-output/
-+*/
-+unsigned char gamma_(unsigned char brightness, unsigned char val)
-+{
-+ int bright = val;
-+ unsigned char GammaE[] = {
-+ 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, 2, 2, 2,
-+ 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
-+ 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11,
-+ 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
-+ 19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28,
-+ 29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40,
-+ 40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
-+ 71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89,
-+ 90, 91, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,110,
-+ 111,113,114,116,117,119,120,121,123,124,126,128,129,131,132,134,
-+ 135,137,138,140,142,143,145,146,148,150,151,153,155,157,158,160,
-+ 162,163,165,167,169,170,172,174,176,178,179,181,183,185,187,189,
-+ 191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220,
-+ 222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255};
-+ bright = (bright * brightness) / 255;
-+ return GammaE[bright];
-+}
-+
-+// LED serial output
-+// 4 bits make up a single bit of the output
-+// 1 1 1 0 -- 1
-+// 1 0 0 0 -- 0
-+//
-+// Plus require a space of 50 microseconds for reset
-+// 24 bits per led
-+//
-+// (24 * 4) / 8 = 12 bytes per led
-+//
-+// red = 0xff0000 == 0xeeeeeeee 0x88888888 0x88888888
-+unsigned char * led_encode(struct ws2812_state * state, int rgb, unsigned char *buf)
-+{
-+ int i;
-+ unsigned char red = gamma_(state->brightness, rgb >> 8);
-+ unsigned char blu = gamma_(state->brightness, rgb);
-+ unsigned char grn = gamma_(state->brightness, rgb >> 16);
-+ int rearrange = red +
-+ (blu << 8) +
-+ (grn << 16);
-+ for(i = 11; i >= 0; i--)
-+ {
-+ switch(rearrange & 3)
-+ {
-+ case 0: *buf++ = 0x88; break;
-+ case 1: *buf++ = 0x8e; break;
-+ case 2: *buf++ = 0xe8; break;
-+ case 3: *buf++ = 0xee; break;
-+ }
-+ rearrange >>= 2;
-+ }
-+
-+ return buf;
-+}
-+
-+
-+/* Write to the PWM through DMA
-+ * Function to write the RGB buffer to the WS2812 leds, the input buffer
-+ * contains a sequence of up to num_leds RGB32 integers, these are then
-+ * converted into the nibble per bit sequence required to drive the PWM
-+ */
-+ssize_t ws2812_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
-+{
-+ int32_t *p_rgb;
-+ int8_t * p_buffer;
-+ int i, length, num_leds;
-+ struct ws2812_state * state = (struct ws2812_state *) filp->private_data;
-+
-+ num_leds = min(count/4, state->num_leds);
-+
-+ if(copy_from_user(state->pixbuf, buf, num_leds * 4))
-+ return -EFAULT;
-+
-+ p_rgb = state->pixbuf;
-+ p_buffer = state->buffer;
-+ for(i = 0; i < num_leds; i++)
-+ p_buffer = led_encode(state, *p_rgb++, p_buffer);
-+
-+ /* Fill rest with '0' */
-+ memset(p_buffer, 0x00, RESET_BYTES);
-+
-+ length = (int) p_buffer - (int) state->buffer + RESET_BYTES;
-+
-+ /* Setup DMA engine */
-+ issue_dma(state, state->buffer, length);
-+
-+ return count;
-+}
-+
-+
-+struct file_operations ws2812_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = NULL,
-+ .read = NULL,
-+ .write = ws2812_write,
-+ .open = ws2812_open,
-+ .release = NULL,
-+};
-+
-+/*
-+ * Probe function
-+ */
-+static int ws2812_probe(struct platform_device *pdev)
-+{
-+ int ret;
-+ struct device *dev = &pdev->dev;
-+ struct device_node *node = dev->of_node;
-+ struct ws2812_state * state;
-+ const __be32 *addr;
-+ struct resource *res;
-+ struct dma_slave_config cfg =
-+ {
-+ .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-+ .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-+ .slave_id = PWM_DMA_DREQ,
-+ .direction = DMA_MEM_TO_DEV,
-+ .src_addr = 0,
-+ };
-+
-+ if(node == NULL)
-+ {
-+ pr_err("Require device tree entry\n");
-+ goto fail;
-+ }
-+
-+ state = kmalloc(sizeof(struct ws2812_state), GFP_KERNEL);
-+ if (!state) {
-+ pr_err("Can't allocate state\n");
-+ goto fail;
-+ }
-+
-+ state->dev = dev;
-+ state->brightness = 255;
-+
-+ // Create character device interface /dev/ws2812
-+ if(alloc_chrdev_region(&devid, 0, 1, "ws2812") < 0)
-+ {
-+ pr_err("Unable to create chrdev region");
-+ goto fail_malloc;
-+ }
-+ if((state->cl = class_create(THIS_MODULE, "ws2812")) == NULL)
-+ {
-+ unregister_chrdev_region(devid, 1);
-+ pr_err("Unable to create class ws2812");
-+ goto fail_chrdev;
-+ }
-+ if(device_create(state->cl, NULL, devid, NULL, "ws2812") == NULL)
-+ {
-+ class_destroy(state->cl);
-+ unregister_chrdev_region(devid, 1);
-+ pr_err("Unable to create device ws2812");
-+ goto fail_class;
-+ }
-+
-+ state->cdev.owner = THIS_MODULE;
-+ cdev_init(&state->cdev, &ws2812_fops);
-+
-+ if(cdev_add(&state->cdev, devid, 1)) {
-+ pr_err("CDEV failed\n");
-+ goto fail_device;
-+ }
-+
-+ platform_set_drvdata(pdev, state);
-+
-+ /* get parameters from device tree */
-+ of_property_read_u32(node,
-+ "rpi,invert",
-+ &state->invert);
-+ of_property_read_u32(node,
-+ "rpi,num_leds",
-+ &state->num_leds);
-+
-+ state->pixbuf = kmalloc(state->num_leds * sizeof(int), GFP_KERNEL);
-+ if(state->pixbuf == NULL)
-+ {
-+ pr_err("Failed to allocate internal buffer\n");
-+ goto fail_cdev;
-+ }
-+
-+ /* base address in dma-space */
-+ addr = of_get_address(node, 0, NULL, NULL);
-+ if (!addr) {
-+ dev_err(dev, "could not get DMA-register address - not using dma mode\n");
-+ goto fail_pixbuf;
-+ }
-+ state->phys_addr = be32_to_cpup(addr);
-+ pr_err("bus_addr = 0x%x\n", state->phys_addr);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ state->ioaddr = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(state->ioaddr)) {
-+ pr_err("Failed to get register resource\n");
-+ goto fail_pixbuf;
-+ }
-+
-+ pr_err("ioaddr = 0x%x\n", (int) state->ioaddr);
-+
-+ state->buffer = kmalloc(state->num_leds * BYTES_PER_LED + RESET_BYTES, GFP_KERNEL);
-+ if(state->buffer == NULL)
-+ {
-+ pr_err("Failed to allocate internal buffer\n");
-+ goto fail_pixbuf;
-+ }
-+
-+ state->dma_chan = dma_request_slave_channel(dev, "pwm_dma");
-+ if(state->dma_chan == NULL)
-+ {
-+ pr_err("Failed to request DMA channel");
-+ goto fail_buffer;
-+ }
-+
-+ /* request a DMA channel */
-+ cfg.dst_addr = state->phys_addr + PWM_FIFO1;
-+ ret = dmaengine_slave_config(state->dma_chan, &cfg);
-+ if (state->dma_chan < 0) {
-+ pr_err("Can't allocate DMA channel\n");
-+ goto fail_dma_init;
-+ }
-+ pwm_init(state);
-+
-+ // Enable the LED power
-+ state->led_en = devm_gpiod_get(dev, "led-en", GPIOD_OUT_HIGH);
-+
-+ clear_leds(state);
-+
-+ return 0;
-+fail_dma_init:
-+ dma_release_channel(state->dma_chan);
-+fail_buffer:
-+ kfree(state->buffer);
-+fail_pixbuf:
-+ kfree(state->pixbuf);
-+fail_cdev:
-+ cdev_del(&state->cdev);
-+fail_device:
-+ device_destroy(state->cl, devid);
-+fail_class:
-+ class_destroy(state->cl);
-+fail_chrdev:
-+ unregister_chrdev_region(devid, 1);
-+fail_malloc:
-+ kfree(state);
-+fail:
-+
-+ return -1;
-+}
-+
-+
-+static int ws2812_remove(struct platform_device *pdev)
-+{
-+ struct ws2812_state *state = platform_get_drvdata(pdev);
-+
-+ platform_set_drvdata(pdev, NULL);
-+
-+ dma_release_channel(state->dma_chan);
-+ kfree(state->buffer);
-+ kfree(state->pixbuf);
-+ cdev_del(&state->cdev);
-+ device_destroy(state->cl, devid);
-+ class_destroy(state->cl);
-+ unregister_chrdev_region(devid, 1);
-+ kfree(state);
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id ws2812_match[] = {
-+ { .compatible = "rpi,ws2812" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, ws2812_match);
-+
-+static struct platform_driver ws2812_driver = {
-+ .probe = ws2812_probe,
-+ .remove = ws2812_remove,
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .owner = THIS_MODULE,
-+ .of_match_table = ws2812_match,
-+ },
-+};
-+module_platform_driver(ws2812_driver);
-+
-+MODULE_ALIAS("platform:ws2812");
-+MODULE_DESCRIPTION("WS2812 PWM driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Gordon Hollingworth");
diff --git a/projects/RPi/patches/linux/linux-06-slice-c.patch b/projects/RPi/patches/linux/linux-06-slice-c.patch
deleted file mode 100644
index d2263c61bc..0000000000
--- a/projects/RPi/patches/linux/linux-06-slice-c.patch
+++ /dev/null
@@ -1,279 +0,0 @@
---- a/sound/soc/bcm/slice.c 1969-12-31 16:00:00.000000000 -0800
-+++ b/sound/soc/bcm/slice.c 2017-02-15 14:39:20.402591342 -0800
-@@ -0,0 +1,276 @@
-+ /*
-+ * ASoC Driver for Slice on-board sound
-+ *
-+ * Author: James Adams
-+ * Based on the HifiBerry DAC driver by Florian Meier
-+ * Copyright 2014
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * version 2 as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ */
-+
-+ #include
-+ #include
-+
-+ #include
-+ #include
-+
-+ #include
-+ #include
-+ #include
-+ #include
-+ #include
-+
-+ #include "../codecs/cs4265.h"
-+
-+struct clk * gp0_clock;
-+
-+ static int snd_slice_init(struct snd_soc_pcm_runtime *rtd)
-+ {
-+ return 0;
-+ }
-+
-+ static int snd_slice_hw_params(struct snd_pcm_substream *substream,
-+ struct snd_pcm_hw_params *params)
-+ {
-+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
-+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
-+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-+ struct snd_soc_codec *codec = rtd->codec;
-+ int err;
-+ int ret;
-+ unsigned int rate = params_rate(params);
-+ unsigned int sysclk = 12288000;
-+
-+ switch (rate) {
-+ case 32000:
-+ sysclk = 12288000;
-+ break;
-+ case 44100:
-+ sysclk = 11289600;
-+ break;
-+ case 48000:
-+ sysclk = 12288000;
-+ break;
-+ case 64000:
-+ sysclk = 12288000;
-+ break;
-+ case 88200:
-+ sysclk = 11289600;
-+ break;
-+ case 96000:
-+ sysclk = 12288000;
-+ break;
-+ case 128000:
-+ dev_err(codec->dev,
-+ "Failed to set CS4265 SYSCLK, sample rate not supported in ALSA: 128000\n");
-+ break;
-+ case 176400:
-+ sysclk = 11289600;
-+ break;
-+ case 192000:
-+ sysclk = 12288000;
-+ break;
-+ default:
-+ dev_err(codec->dev,
-+ "Failed to set CS4265 SYSCLK, sample rate not supported\n");
-+ break;
-+ }
-+
-+ // Need two frequencies: 12.288 or 11.2896MHz
-+ // Source is 1,806,336,000
-+ // /4 /40 - 1128960
-+ // /7 /21 - 1228800
-+ clk_disable_unprepare(gp0_clock);
-+
-+ err = clk_set_rate(gp0_clock, sysclk);
-+ if(err < 0)
-+ pr_err("Failed to set clock rate for gp0 clock\n");
-+
-+ if((ret = clk_prepare_enable(gp0_clock)) < 0)
-+ pr_err("Failed to enable clock\n");
-+
-+ dev_err(codec->dev, "Set sampling frequency %d, using sysclk %d\n", rate, sysclk);
-+
-+ err = snd_soc_dai_set_sysclk(codec_dai, 0, sysclk,
-+ SND_SOC_CLOCK_OUT);
-+
-+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-+ SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM);
-+
-+ if (ret) {
-+ dev_err(cpu_dai->dev,
-+ "Failed to set the cpu dai format.\n");
-+ return ret;
-+ }
-+
-+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-+ SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM);
-+ if (ret) {
-+ dev_err(cpu_dai->dev,
-+ "Failed to set the codec format.\n");
-+ return ret;
-+ }
-+
-+ snd_soc_dai_set_bclk_ratio(cpu_dai, 64);
-+
-+ return 0;
-+ }
-+
-+ static int snd_slice_params_fixup(struct snd_soc_pcm_runtime *rtd,
-+ struct snd_pcm_hw_params *params)
-+ {
-+ printk(KERN_ERR "snd_slice_params_fixup called\n");
-+ /* force 32 bit */
-+ params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
-+ return 0;
-+ }
-+
-+ /* machine stream operations */
-+ static struct snd_soc_ops snd_slice_ops = {
-+ .hw_params = snd_slice_hw_params,
-+ };
-+
-+ /* Widgets */
-+ static const struct snd_soc_dapm_widget snd_slice_dapm_widgets[] = {
-+ SND_SOC_DAPM_SPK("Speaker 1", NULL),
-+ SND_SOC_DAPM_SPK("Speaker 2", NULL),
-+ SND_SOC_DAPM_MIC("Mic 1", NULL),
-+ SND_SOC_DAPM_MIC("Mic 2", NULL),
-+ SND_SOC_DAPM_MIC("LineIn 1", NULL),
-+ SND_SOC_DAPM_MIC("LineIn 2", NULL),
-+ SND_SOC_DAPM_SPK("Spdif", NULL),
-+ };
-+
-+ /* Audio Map */
-+ static const struct snd_soc_dapm_route snd_slice_audio_map[] = {
-+ {"Speaker 1", NULL, "LINEOUTL"},
-+ {"Speaker 2", NULL, "LINEOUTR"},
-+ {"MICL", NULL, "Mic 1"},
-+ {"MICR", NULL, "Mic 2"},
-+ {"LINEINL", NULL, "LineIn 1"},
-+ {"LINEINR", NULL, "LineIn 2"},
-+ {"Spdif", NULL, "SPDIF"},
-+ };
-+
-+ static const struct snd_soc_pcm_stream snd_slice_params = {
-+ .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE,
-+ };
-+
-+ static struct snd_soc_dai_link snd_slice_dai[] = {
-+ {
-+ .name = "Slice",
-+ .stream_name = "Slice HiFi",
-+ .cpu_dai_name = "bcm2708-i2s.0",
-+ .codec_dai_name = "cs4265-dai1",
-+ .platform_name = "bcm2708-i2s.0",
-+ .codec_name = "cs4265.1-004e",
-+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-+ SND_SOC_DAIFMT_CBM_CFM,
-+ .ops = &snd_slice_ops,
-+ .init = snd_slice_init,
-+ .be_hw_params_fixup = snd_slice_params_fixup,
-+ },
-+ };
-+
-+ /* audio machine driver */
-+ static struct snd_soc_card snd_slice = {
-+ .name = "snd_slice",
-+ .dai_link = snd_slice_dai,
-+ .num_links = ARRAY_SIZE(snd_slice_dai),
-+ .fully_routed = 1,
-+ .dapm_widgets = snd_slice_dapm_widgets,
-+ .num_dapm_widgets = ARRAY_SIZE(snd_slice_dapm_widgets),
-+ .dapm_routes = snd_slice_audio_map,
-+ .num_dapm_routes = ARRAY_SIZE(snd_slice_audio_map),
-+ };
-+
-+ static int snd_slice_probe(struct platform_device *pdev)
-+ {
-+ int ret = 0;
-+ snd_slice.dev = &pdev->dev;
-+
-+ if (pdev->dev.of_node) {
-+ struct device_node *i2s_node;
-+ struct snd_soc_dai_link *dai = &snd_slice_dai[0];
-+ i2s_node = of_parse_phandle(pdev->dev.of_node,
-+ "i2s-controller", 0);
-+
-+ if (i2s_node) {
-+ dai->cpu_dai_name = NULL;
-+ dai->cpu_of_node = i2s_node;
-+ dai->platform_name = NULL;
-+ dai->platform_of_node = i2s_node;
-+ }
-+ }
-+ else
-+ {
-+ printk(KERN_ERR "SLICEAUDIO - ERROR no Device Tree!\n");
-+ }
-+
-+ ret = snd_soc_register_card(&snd_slice);
-+ if (ret) {
-+ dev_err(&pdev->dev,
-+ "snd_soc_register_card() failed: %d\n", ret);
-+ goto snd_soc_register_card_failed;
-+ }
-+
-+ gp0_clock = devm_clk_get(&pdev->dev, "gp0");
-+ if (IS_ERR(gp0_clock)) {
-+ pr_err("Failed to get gp0 clock\n");
-+ return PTR_ERR(gp0_clock);
-+ }
-+
-+ ret = clk_set_rate(gp0_clock, 12288000);
-+ if (ret) {
-+ pr_err("Failed to set the GP0 clock rate\n");
-+ return ret;
-+ }
-+
-+ ret = clk_prepare_enable(gp0_clock);
-+ if (ret) {
-+ pr_err("Failed to turn on gp0 clock: %d\n", ret);
-+ return ret;
-+ }
-+
-+ return 0;
-+
-+ snd_soc_register_card_failed:
-+
-+ return ret;
-+ }
-+
-+ static int snd_slice_remove(struct platform_device *pdev)
-+ {
-+ return snd_soc_unregister_card(&snd_slice);
-+ }
-+
-+ static const struct of_device_id slice_of_match[] = {
-+ { .compatible = "fiveninjas,slice", },
-+ {},
-+ };
-+ MODULE_DEVICE_TABLE(of, slice_of_match);
-+
-+ static struct platform_driver snd_slice_driver = {
-+ .driver = {
-+ .name = "snd-slice",
-+ .owner = THIS_MODULE,
-+ .of_match_table = slice_of_match,
-+ },
-+ .probe = snd_slice_probe,
-+ .remove = snd_slice_remove,
-+ };
-+
-+ module_platform_driver(snd_slice_driver);
-+
-+ MODULE_AUTHOR("James Adams ");
-+ MODULE_DESCRIPTION("ASoC Driver for Slice on-board audio");
-+ MODULE_LICENSE("GPL v2");
diff --git a/projects/RPi/patches/linux/linux-07-slice-Kconfig.patch b/projects/RPi/patches/linux/linux-07-slice-Kconfig.patch
deleted file mode 100644
index a51dfde8ca..0000000000
--- a/projects/RPi/patches/linux/linux-07-slice-Kconfig.patch
+++ /dev/null
@@ -1,17 +0,0 @@
---- a/sound/soc/bcm/Kconfig 2016-10-24 08:46:19.034757161 +0100
-+++ b/sound/soc/bcm/Kconfig 2016-10-24 08:52:36.735342726 +0100
-@@ -131,6 +131,13 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC
- help
- Say Y or M if you want to add support for Allo Piano DAC.
-
-+config SND_BCM2708_SOC_SLICE
-+ tristate "Support for Slice on-board sound"
-+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-+ select SND_SOC_CS4265
-+ help
-+ Say Y or M if you want to add support for Slice on-board sound.
-+
- config SND_PISOUND
- tristate "Support for Blokas Labs pisound"
- depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S
-
diff --git a/projects/RPi/patches/linux/linux-08-slice-Makefile.patch b/projects/RPi/patches/linux/linux-08-slice-Makefile.patch
deleted file mode 100644
index 21312e263b..0000000000
--- a/projects/RPi/patches/linux/linux-08-slice-Makefile.patch
+++ /dev/null
@@ -1,15 +0,0 @@
---- a/sound/soc/bcm/Makefile 2016-10-24 08:57:16.805712924 +0100
-+++ b/sound/soc/bcm/Makefile 2016-10-24 08:59:51.541235893 +0100
-@@ -26,6 +26,7 @@ snd-soc-digidac1-soundcard-objs := digid
- snd-soc-allo-piano-dac-objs := allo-piano-dac.o
- snd-soc-pisound-objs := pisound.o
- snd-soc-fe-pi-audio-objs := fe-pi-audio.o
-+snd-soc-slice-objs := slice.o
-
- obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o
- obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
-@@ -44,3 +45,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) +=
- obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o
- obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o
- obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o
-+obj-$(CONFIG_SND_BCM2708_SOC_SLICE) += snd-soc-slice.o