From c8265540674a53533fa71ed324d77d70437104ba Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 30 Jan 2026 06:06:30 -0500 Subject: [PATCH 01/75] manual: Minor correction to the list of ErosQ/K hardare revisions Change-Id: I4691d11b5c26a1b0e09e62ccb62e0661a09851b9 --- manual/getting_started/hibyos_nativeinstall.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/getting_started/hibyos_nativeinstall.tex b/manual/getting_started/hibyos_nativeinstall.tex index bd311444f6..d9286ead64 100644 --- a/manual/getting_started/hibyos_nativeinstall.tex +++ b/manual/getting_started/hibyos_nativeinstall.tex @@ -59,7 +59,7 @@ may not be the most up to date, please see the wiki page at \hfill{} \begin{itemize} \item Aigo Eros Q V2.2 - \item Hifiwalker H2 V1.9 - V2.0 + \item Hifiwalker H2 V1.9 - V2.2 \item Surfans F20 V3.4 \end{itemize} These players use \fname{erosqnative-hw4-erosq\_2024.upt} as the update file. From 5563643b387d3c050fe133f0c595f0a71bf06667 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 30 Jan 2026 06:01:06 -0500 Subject: [PATCH 02/75] x1000: Bump NAND_DRV_MAXPAGESIZE to (2048+128) X6G01C flash has 128B of ECC data per page, overruning our buffer. Change-Id: I8caa8bec6291f1b3391af9c7da1ee22805ff01e2 --- firmware/target/mips/ingenic_x1000/nand-x1000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h index 0ccd075079..f2e5ffa478 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.h +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h @@ -36,7 +36,7 @@ /* keep max page size in sync with the NAND chip table in the .c file */ #define NAND_DRV_SCRATCHSIZE 32 -#define NAND_DRV_MAXPAGESIZE 2112 +#define NAND_DRV_MAXPAGESIZE (2048+128) /* Quad I/O support bit */ #define NAND_CHIPFLAG_QUAD 0x0001 From c23e1ba09adc2893c929a9517b2de7f335074356 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 30 Jan 2026 06:02:21 -0500 Subject: [PATCH 03/75] x1000: Drop XT26G01C flash clock speed to 104MHz as per datasheet Change-Id: I17da992c608a6ad1340c500c34d42009eccf6fbb --- firmware/target/mips/ingenic_x1000/nand-x1000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c index 7c5547f947..d66ce0162e 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.c +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c @@ -99,7 +99,7 @@ static const struct nand_chip chip_xt26g01cwsiga = { .oob_size = 128, .nr_blocks = 1024, .bbm_pos = 2048, - .clock_freq = 150000000, + .clock_freq = 104000000, .dev_conf = jz_orf(SFC_DEV_CONF, CE_DL(1), HOLD_DL(1), WP_DL(1), CPHA(0), CPOL(0), From 2556cfc7b33e3990e53671649cab1e6aa63718ba Mon Sep 17 00:00:00 2001 From: Christian Soffke Date: Fri, 30 Jan 2026 13:48:23 +0100 Subject: [PATCH 04/75] usb: fix hang when disconnecting from USB regression introduced in 33d0a3efa3 Change-Id: I0ded61d70a09b27820e65979381d2c38410d2923 --- firmware/usb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firmware/usb.c b/firmware/usb.c index c088db4ef1..e1d0909613 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -877,6 +877,7 @@ void usb_request_exclusive_storage(void) void usb_release_exclusive_storage(void) { + int bccount; if(!exclusive_storage_requested) { return; } @@ -887,10 +888,12 @@ void usb_release_exclusive_storage(void) } exclusive_storage_enabled = false; -#ifdef DEBUG /* Tell all threads that we are back in business */ - int bccount = queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1; + bccount = queue_broadcast(SYS_USB_DISCONNECTED, 0) - 1; +#ifdef DEBUG DEBUGF("USB extracted. Broadcast to %d threads...\n", bccount); +#else + (void)bccount; #endif return; } From 11263d73af564d28011d74f1fb9e59d4d610be2c Mon Sep 17 00:00:00 2001 From: Christian Soffke Date: Fri, 30 Jan 2026 14:12:57 +0100 Subject: [PATCH 05/75] imageviewer: add back semicolon accidentally removed in 3c6b9bb file isn't normally used, so there was no error Change-Id: I65cc59bfcb3c59678a990b9804070d518318b016 --- apps/plugins/imageviewer/jpegp/FILEGETC.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/plugins/imageviewer/jpegp/FILEGETC.c b/apps/plugins/imageviewer/jpegp/FILEGETC.c index 5b03deb25c..2370923e02 100644 --- a/apps/plugins/imageviewer/jpegp/FILEGETC.c +++ b/apps/plugins/imageviewer/jpegp/FILEGETC.c @@ -5,7 +5,7 @@ static int fd; extern int GETC(void) { unsigned char x = 0; - rb->read(fd, &x, 1) + rb->read(fd, &x, 1); return x; } From e11a449031d40610995e8b565217a027301f99ab Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 30 Jan 2026 15:07:11 -0500 Subject: [PATCH 06/75] rbutil: Pull the internal/external QUAZIP library stuff into the toplevel Prevents a build failure when we have to build quazip as part of the build Change-Id: I274cd4c358c50152bcfea2e33ad580fac0277e4a --- utils/CMakeLists.txt | 35 +++++++++++++++++++++++++++++++- utils/rbutilqt/CMakeLists.txt | 35 -------------------------------- utils/themeeditor/CMakeLists.txt | 7 ------- 3 files changed, 34 insertions(+), 43 deletions(-) diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 55e5b7991f..31f142f913 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -84,6 +84,40 @@ if(APPLE) endif() +find_package(QuaZip-Qt${QT_VERSION_MAJOR} QUIET) +if(QuaZip-Qt${QT_VERSION_MAJOR}_FOUND) + message("-- Found QuaZip") + set(QUAZIP_LIBRARY QuaZip::QuaZip) +else() + message("-- QuaZip not found, building our own") + # TODO: Upstream has cmake support, use that instead. + add_library(quazip + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/ioapi.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/minizip_crypt.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/qioapi.cpp + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazip.cpp + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipfile.cpp + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipfile.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipfileinfo.cpp + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipfileinfo.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazip_global.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazip.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipnewinfo.cpp + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/quazipnewinfo.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/unzip.c + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/unzip.h + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/zip.c + ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip/zip.h) + target_include_directories(quazip PUBLIC ${CMAKE_CURRENT_LIST_DIR}/rbutilqt/quazip) + target_link_libraries(quazip z Qt${QT_VERSION_MAJOR}::Core) + if(QT_VERSION_MAJOR EQUAL 6) + target_link_libraries(quazip Qt${QT_VERSION_MAJOR}::Core5Compat) + endif() + target_compile_definitions(quazip PUBLIC QUAZIP_STATIC) + set_property(TARGET quazip PROPERTY AUTOMOC ON) + set(QUAZIP_LIBRARY quazip) +endif() + add_executable(ipodpatcher-bin ipodpatcher/main.c ipodpatcher/ipodpatcher-aupd.c @@ -392,4 +426,3 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/deploy.cmake) include(${CMAKE_CURRENT_LIST_DIR}/cmake/QtTest.cmake) add_subdirectory(rbutilqt) add_subdirectory(themeeditor) - diff --git a/utils/rbutilqt/CMakeLists.txt b/utils/rbutilqt/CMakeLists.txt index 4addc8d54c..a160279189 100644 --- a/utils/rbutilqt/CMakeLists.txt +++ b/utils/rbutilqt/CMakeLists.txt @@ -256,41 +256,6 @@ if(APPLE) ${CMAKE_CURRENT_LIST_DIR}/base/ttscarbon.h) endif() -find_package(QuaZip-Qt${QT_VERSION_MAJOR} QUIET) -if(QuaZip-Qt${QT_VERSION_MAJOR}_FOUND) - message("-- Found QuaZip") - set(QUAZIP_LIBRARY QuaZip::QuaZip) -else() - message("-- QuaZip not found, building our own") - # TODO: Upstream has cmake support, use that instead. - add_library(quazip - ${CMAKE_CURRENT_LIST_DIR}/quazip/ioapi.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/minizip_crypt.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/qioapi.cpp - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.cpp - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.cpp - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfile.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.cpp - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipfileinfo.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip_global.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazip.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.cpp - ${CMAKE_CURRENT_LIST_DIR}/quazip/quazipnewinfo.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.c - ${CMAKE_CURRENT_LIST_DIR}/quazip/unzip.h - ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.c - ${CMAKE_CURRENT_LIST_DIR}/quazip/zip.h - ) - target_include_directories(quazip PUBLIC ${CMAKE_CURRENT_LIST_DIR}/quazip) - target_link_libraries(quazip z Qt${QT_VERSION_MAJOR}::Core) - if(QT_VERSION_MAJOR EQUAL 6) - target_link_libraries(quazip Qt${QT_VERSION_MAJOR}::Core5Compat) - endif() - target_compile_definitions(quazip PUBLIC QUAZIP_STATIC) - set_property(TARGET quazip PROPERTY AUTOMOC ON) - set(QUAZIP_LIBRARY quazip) -endif() - target_link_libraries(rbbase cutelogger ${QUAZIP_LIBRARY} mspack bspatch rbspeex voicefont sansapatcher ipodpatcher chinachippatcher diff --git a/utils/themeeditor/CMakeLists.txt b/utils/themeeditor/CMakeLists.txt index 8d239b55f1..42a3e19c1b 100644 --- a/utils/themeeditor/CMakeLists.txt +++ b/utils/themeeditor/CMakeLists.txt @@ -13,13 +13,6 @@ # KIND, either express or implied. # -find_package(QuaZip-Qt${QT_VERSION_MAJOR} QUIET) -if(QuaZip-Qt${QT_VERSION_MAJOR}_FOUND) - set(QUAZIP_LIBRARY QuaZip::QuaZip) -else() - set(QUAZIP_LIBRARY quazip) -endif() - add_executable(RockboxThemeEditor WIN32 MACOSX_BUNDLE graphics/rbalbumart.cpp graphics/rbalbumart.h From ee3e630efa4becf7dd6c05a377703bee1cce1b20 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Fri, 30 Jan 2026 20:33:12 -0500 Subject: [PATCH 07/75] rbutil: Upgrade bundled quazip from 0.9.1 to 1.1 Just reducing the delta a little bit. Later versions are more complicated. Change-Id: If0452a529b840383333062ec2604ff257646627a --- utils/rbutilqt/quazip/README.ROCKBOX | 4 +- utils/rbutilqt/quazip/qioapi.cpp | 41 +++----- utils/rbutilqt/quazip/quazip.cpp | 74 +++++++------- utils/rbutilqt/quazip/quazip.h | 38 +++---- utils/rbutilqt/quazip/quazip.pri | 25 ----- utils/rbutilqt/quazip/quazip_qt_compat.h | 120 +++++++++++++++++++++++ utils/rbutilqt/quazip/quazipfile.cpp | 50 +++++----- utils/rbutilqt/quazip/quazipfile.h | 22 ++--- utils/rbutilqt/quazip/quazipfileinfo.cpp | 14 +-- utils/rbutilqt/quazip/quazipfileinfo.h | 20 ++-- utils/rbutilqt/quazip/quazipnewinfo.cpp | 26 ++--- utils/rbutilqt/quazip/quazipnewinfo.h | 8 +- utils/rbutilqt/quazip/unzip.c | 2 +- utils/rbutilqt/quazip/unzip.h | 2 +- utils/rbutilqt/quazip/zip.c | 2 +- utils/rbutilqt/quazip/zip.h | 6 +- 16 files changed, 262 insertions(+), 192 deletions(-) delete mode 100644 utils/rbutilqt/quazip/quazip.pri create mode 100644 utils/rbutilqt/quazip/quazip_qt_compat.h diff --git a/utils/rbutilqt/quazip/README.ROCKBOX b/utils/rbutilqt/quazip/README.ROCKBOX index a168b2a079..2e1dca737f 100644 --- a/utils/rbutilqt/quazip/README.ROCKBOX +++ b/utils/rbutilqt/quazip/README.ROCKBOX @@ -3,7 +3,7 @@ These files are distributed under the LGPL v2.1 or later. Only source files actually used in Rockbox Utility are included, further sources have been left out. Check the quazip source distribution for those. -The source files have been last synced with the projects release 0.9.1 at -https://github.com/stachenov/quazip/ on June 8, 2020. +The source files have been last synced with the project's release 1.1 at +https://github.com/stachenov/quazip/ on October 11, 2020. diff --git a/utils/rbutilqt/quazip/qioapi.cpp b/utils/rbutilqt/quazip/qioapi.cpp index 3932ebeef0..60f101d7e9 100644 --- a/utils/rbutilqt/quazip/qioapi.cpp +++ b/utils/rbutilqt/quazip/qioapi.cpp @@ -16,12 +16,7 @@ #include "ioapi.h" #include "quazip_global.h" #include -#if (QT_VERSION >= 0x050100) -#define QUAZIP_QSAVEFILE_BUG_WORKAROUND -#endif -#ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND -#include -#endif +#include "quazip_qt_compat.h" /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ @@ -39,7 +34,7 @@ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,voidpf file,int mode) { - if (pfilefunc->zfile_func64.zopen64_file != NULL) + if (pfilefunc->zfile_func64.zopen64_file != nullptr) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,file,mode); else { @@ -49,7 +44,7 @@ voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,voidpf file,int mod int call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { - if (pfilefunc->zfile_func64.zseek64_file != NULL) + if (pfilefunc->zfile_func64.zseek64_file != nullptr) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else { @@ -63,7 +58,7 @@ int call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPO ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) { - if (pfilefunc->zfile_func64.zseek64_file != NULL) + if (pfilefunc->zfile_func64.zseek64_file != nullptr) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else { @@ -105,7 +100,7 @@ voidpf ZCALLBACK qiodevice_open_file_func ( && iodevice->isSequential()) { // We can use sequential devices only for writing. delete d; - return NULL; + return nullptr; } else { if ((desiredMode & QIODevice::WriteOnly) != 0) { // open for writing, need to seek existing device @@ -119,7 +114,7 @@ voidpf ZCALLBACK qiodevice_open_file_func ( return iodevice; } else { delete d; - return NULL; + return nullptr; } } iodevice->open(desiredMode); @@ -128,13 +123,13 @@ voidpf ZCALLBACK qiodevice_open_file_func ( // We can use sequential devices only for writing. iodevice->close(); delete d; - return NULL; + return nullptr; } else { return iodevice; } } else { delete d; - return NULL; + return nullptr; } } @@ -287,17 +282,7 @@ int ZCALLBACK qiodevice_close_file_func ( QIODevice_descriptor *d = reinterpret_cast(opaque); delete d; QIODevice *device = reinterpret_cast(stream); -#ifdef QUAZIP_QSAVEFILE_BUG_WORKAROUND - // QSaveFile terribly breaks the is-a idiom: - // it IS a QIODevice, but it is NOT compatible with it: close() is private - QSaveFile *file = qobject_cast(device); - if (file != NULL) { - // We have to call the ugly commit() instead: - return file->commit() ? 0 : -1; - } -#endif - device->close(); - return 0; + return quazip_close(device) ? 0 : -1; } int ZCALLBACK qiodevice_fakeclose_file_func ( @@ -347,17 +332,17 @@ void fill_qiodevice64_filefunc ( void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) { - p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zfile_func64.zopen64_file = nullptr; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; - p_filefunc64_32->zfile_func64.ztell64_file = NULL; - p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.ztell64_file = nullptr; + p_filefunc64_32->zfile_func64.zseek64_file = nullptr; p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; - p_filefunc64_32->zfile_func64.zfakeclose_file = NULL; + p_filefunc64_32->zfile_func64.zfakeclose_file = nullptr; p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; } diff --git a/utils/rbutilqt/quazip/quazip.cpp b/utils/rbutilqt/quazip/quazip.cpp index 61c2ea87eb..29a278da29 100644 --- a/utils/rbutilqt/quazip/quazip.cpp +++ b/utils/rbutilqt/quazip/quazip.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -78,7 +78,7 @@ class QuaZipPrivate { uint osCode; inline QTextCodec *getDefaultFileNameCodec() { - if (defaultFileNameCodec == NULL) { + if (defaultFileNameCodec == nullptr) { return QTextCodec::codecForLocale(); } else { return defaultFileNameCodec; @@ -89,7 +89,7 @@ class QuaZipPrivate { q(q), fileNameCodec(getDefaultFileNameCodec()), commentCodec(QTextCodec::codecForLocale()), - ioDevice(NULL), + ioDevice(nullptr), mode(QuaZip::mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK), @@ -99,8 +99,8 @@ class QuaZipPrivate { utf8(false), osCode(defaultOsCode) { - unzFile_f = NULL; - zipFile_f = NULL; + unzFile_f = nullptr; + zipFile_f = nullptr; lastMappedDirectoryEntry.num_of_file = 0; lastMappedDirectoryEntry.pos_in_zip_directory = 0; } @@ -110,7 +110,7 @@ class QuaZipPrivate { fileNameCodec(getDefaultFileNameCodec()), commentCodec(QTextCodec::codecForLocale()), zipName(zipName), - ioDevice(NULL), + ioDevice(nullptr), mode(QuaZip::mdNotOpen), hasCurrentFile_f(false), zipError(UNZ_OK), @@ -120,8 +120,8 @@ class QuaZipPrivate { utf8(false), osCode(defaultOsCode) { - unzFile_f = NULL; - zipFile_f = NULL; + unzFile_f = nullptr; + zipFile_f = nullptr; lastMappedDirectoryEntry.num_of_file = 0; lastMappedDirectoryEntry.pos_in_zip_directory = 0; } @@ -140,8 +140,8 @@ class QuaZipPrivate { utf8(false), osCode(defaultOsCode) { - unzFile_f = NULL; - zipFile_f = NULL; + unzFile_f = nullptr; + zipFile_f = nullptr; lastMappedDirectoryEntry.num_of_file = 0; lastMappedDirectoryEntry.pos_in_zip_directory = 0; } @@ -160,7 +160,7 @@ class QuaZipPrivate { static uint defaultOsCode; }; -QTextCodec *QuaZipPrivate::defaultFileNameCodec = NULL; +QTextCodec *QuaZipPrivate::defaultFileNameCodec = nullptr; uint QuaZipPrivate::defaultOsCode = QUAZIP_OS_UNIX; void QuaZipPrivate::clearDirectoryMap() @@ -241,7 +241,7 @@ bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) return false; } QIODevice *ioDevice = p->ioDevice; - if (ioDevice == NULL) { + if (ioDevice == nullptr) { if (p->zipName.isEmpty()) { qWarning("QuaZip::open(): set either ZIP file name or IO device first"); return false; @@ -252,14 +252,14 @@ bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) unsigned flags = 0; switch(mode) { case mdUnzip: - if (ioApi == NULL) { + if (ioApi == nullptr) { if (p->autoClose) flags |= UNZ_AUTO_CLOSE; - p->unzFile_f=unzOpenInternal(ioDevice, NULL, 1, flags); + p->unzFile_f=unzOpenInternal(ioDevice, nullptr, 1, flags); } else { - // QuaZIP pre-zip64 compatibility mode + // QuaZip pre-zip64 compatibility mode p->unzFile_f=unzOpen2(ioDevice, ioApi); - if (p->unzFile_f != NULL) { + if (p->unzFile_f != nullptr) { if (p->autoClose) { unzSetFlags(p->unzFile_f, UNZ_AUTO_CLOSE); } else { @@ -267,7 +267,7 @@ bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) } } } - if(p->unzFile_f!=NULL) { + if(p->unzFile_f!=nullptr) { if (ioDevice->isSequential()) { unzClose(p->unzFile_f); if (!p->zipName.isEmpty()) @@ -289,7 +289,7 @@ bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) case mdCreate: case mdAppend: case mdAdd: - if (ioApi == NULL) { + if (ioApi == nullptr) { if (p->autoClose) flags |= ZIP_AUTO_CLOSE; if (p->dataDescriptorWritingEnabled) @@ -300,23 +300,23 @@ bool QuaZip::open(Mode mode, zlib_filefunc_def* ioApi) mode==mdCreate?APPEND_STATUS_CREATE: mode==mdAppend?APPEND_STATUS_CREATEAFTER: APPEND_STATUS_ADDINZIP, - NULL, NULL, flags); + nullptr, nullptr, flags); } else { - // QuaZIP pre-zip64 compatibility mode + // QuaZip pre-zip64 compatibility mode p->zipFile_f=zipOpen2(ioDevice, mode==mdCreate?APPEND_STATUS_CREATE: mode==mdAppend?APPEND_STATUS_CREATEAFTER: APPEND_STATUS_ADDINZIP, - NULL, + nullptr, ioApi); - if (p->zipFile_f != NULL) { + if (p->zipFile_f != nullptr) { zipSetFlags(p->zipFile_f, flags); } } - if(p->zipFile_f!=NULL) { + if(p->zipFile_f!=nullptr) { if (ioDevice->isSequential()) { if (mode != mdCreate) { - zipClose(p->zipFile_f, NULL); + zipClose(p->zipFile_f, nullptr); qWarning("QuaZip::open(): " "only mdCreate can be used with " "sequential devices"); @@ -357,7 +357,7 @@ void QuaZip::close() case mdCreate: case mdAppend: case mdAdd: - p->zipError=zipClose(p->zipFile_f, p->comment.isNull() ? NULL : isUtf8Enabled() + p->zipError=zipClose(p->zipFile_f, p->comment.isNull() ? nullptr : isUtf8Enabled() ? p->comment.toUtf8().constData() : p->commentCodec->fromUnicode(p->comment).constData()); break; @@ -368,7 +368,7 @@ void QuaZip::close() // opened by name, need to delete the internal IO device if (!p->zipName.isEmpty()) { delete p->ioDevice; - p->ioDevice = NULL; + p->ioDevice = nullptr; } p->clearDirectoryMap(); if(p->zipError==UNZ_OK) @@ -382,7 +382,7 @@ void QuaZip::setZipName(const QString& zipName) return; } p->zipName=zipName; - p->ioDevice = NULL; + p->ioDevice = nullptr; } void QuaZip::setIoDevice(QIODevice *ioDevice) @@ -442,7 +442,7 @@ bool QuaZip::setCurrentFile(const QString& fileName, CaseSensitivity cs) return true; } // Unicode-aware reimplementation of the unzLocateFile function - if(p->unzFile_f==NULL) { + if(p->unzFile_f==nullptr) { p->zipError=UNZ_PARAMERROR; return false; } @@ -517,7 +517,7 @@ bool QuaZip::goToNextFile() bool QuaZip::getCurrentFileInfo(QuaZipFileInfo *info)const { QuaZipFileInfo64 info64; - if (info == NULL) { // Very unlikely because of the overloads + if (info == nullptr) { // Very unlikely because of the overloads return false; } if (getCurrentFileInfo(&info64)) { @@ -540,14 +540,14 @@ bool QuaZip::getCurrentFileInfo(QuaZipFileInfo64 *info)const QByteArray fileName; QByteArray extra; QByteArray comment; - if(info==NULL) return false; + if(info==nullptr) return false; if(!isOpen()||!hasCurrentFile()) return false; - if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &info_z, NULL, 0, NULL, 0, NULL, 0))!=UNZ_OK) + if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &info_z, nullptr, 0, nullptr, 0, nullptr, 0))!=UNZ_OK) return false; fileName.resize(info_z.size_filename); extra.resize(info_z.size_file_extra); comment.resize(info_z.size_file_comment); - if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, NULL, + if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, nullptr, fileName.data(), fileName.size(), extra.data(), extra.size(), comment.data(), comment.size()))!=UNZ_OK) @@ -585,7 +585,7 @@ QString QuaZip::getCurrentFileName()const QByteArray fileName(MAX_FILE_NAME_LENGTH, 0); unz_file_info64 file_info; if((fakeThis->p->zipError=unzGetCurrentFileInfo64(p->unzFile_f, &file_info, fileName.data(), fileName.size(), - NULL, 0, NULL, 0))!=UNZ_OK) + nullptr, 0, nullptr, 0))!=UNZ_OK) return QString(); fileName.resize(file_info.size_filename); QString result = (file_info.flag & UNZ_ENCODING_UTF8) @@ -645,7 +645,7 @@ QString QuaZip::getZipName() const QIODevice *QuaZip::getIoDevice() const { if (!p->zipName.isEmpty()) // opened by name, using an internal QIODevice - return NULL; + return nullptr; return p->ioDevice; } diff --git a/utils/rbutilqt/quazip/quazip.h b/utils/rbutilqt/quazip/quazip.h index 8ff0756254..486d5885bf 100644 --- a/utils/rbutilqt/quazip/quazip.h +++ b/utils/rbutilqt/quazip/quazip.h @@ -4,20 +4,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -27,7 +27,7 @@ quazip/(un)zip.h files for details, basically it's zlib license. #include #include -#include +#include "quazip_qt_compat.h" #include "zip.h" #include "unzip.h" @@ -116,7 +116,7 @@ class QUAZIP_EXPORT QuaZip { csSensitive=1, ///< Case sensitive. csInsensitive=2 ///< Case insensitive. }; - /// Returns the actual case sensitivity for the specified QuaZIP one. + /// Returns the actual case sensitivity for the specified QuaZip one. /** \param cs The value to convert. \returns If CaseSensitivity::csDefault, then returns the default @@ -153,17 +153,17 @@ class QUAZIP_EXPORT QuaZip { * * If the ZIP file is accessed via explicitly set QIODevice, then * this device is opened in the necessary mode. If the device was - * already opened by some other means, then QuaZIP checks if the + * already opened by some other means, then QuaZip checks if the * open mode is compatible to the mode needed for the requested operation. * If necessary, seeking is performed to position the device properly. * * \return \c true if successful, \c false otherwise. * * \note ZIP/UNZIP API open calls do not return error code - they - * just return \c NULL indicating an error. But to make things + * just return \c null indicating an error. But to make things * easier, quazip.h header defines additional error code \c * UNZ_ERROROPEN and getZipError() will return it if the open call - * of the ZIP/UNZIP API returns \c NULL. + * of the ZIP/UNZIP API returns \c null. * * Argument \a ioApi specifies IO function set for ZIP/UNZIP * package to use. See unzip.h, zip.h and ioapi.h for details. Note @@ -177,12 +177,12 @@ class QUAZIP_EXPORT QuaZip { * QIODevice instead of file name, but also has a nice side effect * of raising the file size limit from 2G to 4G (in non-zip64 archives). * - * \note If the zip64 support is needed, the ioApi argument \em must be NULL + * \note If the zip64 support is needed, the ioApi argument \em must be null * because due to the backwards compatibility issues it can be used to * provide a 32-bit API only. * * \note If the \ref QuaZip::setAutoClose() "no-auto-close" feature is used, - * then the \a ioApi argument \em should be NULL because the old API + * then the \a ioApi argument \em should be null because the old API * doesn't support the 'fake close' operation, causing slight memory leaks * and other possible troubles (like closing the output device in case * when an error occurs during opening). @@ -190,7 +190,7 @@ class QUAZIP_EXPORT QuaZip { * In short: just forget about the \a ioApi argument and you'll be * fine. **/ - bool open(Mode mode, zlib_filefunc_def *ioApi =NULL); + bool open(Mode mode, zlib_filefunc_def *ioApi =nullptr); /// Closes ZIP file. /** Call getZipError() to determine if the close was successful. * @@ -206,7 +206,7 @@ class QUAZIP_EXPORT QuaZip { * by making close() private and crashing the application if it is called * from the base class where it is public. It is an excellent example * of poor design that illustrates why you should never ever break - * an is-a relationship between the base class and a subclass. QuaZIP + * an is-a relationship between the base class and a subclass. QuaZip * works around this bug by checking if the QIODevice is an instance * of QSaveFile, using qobject_cast<>, and if it is, calls * QSaveFile::commit() instead of close(). It is a really ugly hack, @@ -427,7 +427,7 @@ class QUAZIP_EXPORT QuaZip { According to the ZIP format specification, a file inside archive may have a data descriptor immediately following the file data. This is reflected by a special flag in the local file header - and in the central directory. By default, QuaZIP sets this flag + and in the central directory. By default, QuaZip sets this flag and writes the data descriptor unless both method and level were set to 0, in which case it operates in 1.0-compatible mode and never writes data descriptors. @@ -539,14 +539,14 @@ class QUAZIP_EXPORT QuaZip { bool isAutoClose() const; /// Sets or unsets the auto-close flag. /** - By default, QuaZIP opens the underlying QIODevice when open() is called, + By default, QuaZip opens the underlying QIODevice when open() is called, and closes it when close() is called. In some cases, when the device is set explicitly using setIoDevice(), it may be desirable to leave the device open. If the auto-close flag is unset using this method, then the device isn't closed automatically if it was set explicitly. If it is needed to clear this flag, it is recommended to do so before - opening the archive because otherwise QuaZIP may close the device + opening the archive because otherwise QuaZip may close the device during the open() call if an error is encountered after the device is opened. @@ -567,7 +567,7 @@ class QUAZIP_EXPORT QuaZip { * The codec specified here can be overriden by calling setFileNameCodec(). * If neither function is called, QTextCodec::codecForLocale() will be used * to decode or encode file names. Use this function with caution if - * the application uses other libraries that depend on QuaZIP. Those + * the application uses other libraries that depend on QuaZip. Those * libraries can either call this function by themselves, thus overriding * your setting or can rely on the default encoding, thus failing * mysteriously if you change it. For these reasons, it isn't recommended @@ -576,7 +576,7 @@ class QUAZIP_EXPORT QuaZip { * encoding. * * In most cases, using setFileNameCodec() instead is the right choice. - * However, if you depend on third-party code that uses QuaZIP, then the + * However, if you depend on third-party code that uses QuaZip, then the * reasons stated above can actually become a reason to use this function * in case the third-party code in question fails because it doesn't * understand the encoding you need and doesn't provide a way to specify it. @@ -587,7 +587,7 @@ class QUAZIP_EXPORT QuaZip { * setDefaultFileNameCodec() when you don't have access to the QuaZip * instance. * - * @param codec The codec to use by default. If NULL, resets to default. + * @param codec The codec to use by default. If null, resets to default. */ static void setDefaultFileNameCodec(QTextCodec *codec); /** diff --git a/utils/rbutilqt/quazip/quazip.pri b/utils/rbutilqt/quazip/quazip.pri deleted file mode 100644 index 3a82bd0275..0000000000 --- a/utils/rbutilqt/quazip/quazip.pri +++ /dev/null @@ -1,25 +0,0 @@ - -SOURCES += \ - $$PWD/quazip.cpp \ - $$PWD/quazipfile.cpp \ - $$PWD/quazipnewinfo.cpp \ - $$PWD/quazipfileinfo.cpp \ - $$PWD/qioapi.cpp \ - $$PWD/unzip.c \ - $$PWD/zip.c \ - -HEADERS += \ - $$PWD/minizip_crypt.h \ - $$PWD/ioapi.h \ - $$PWD/quazipfile.h \ - $$PWD/quazipfileinfo.h \ - $$PWD/quazipnewinfo.h \ - $$PWD/quazip.h \ - $$PWD/quazipnewinfo.h \ - $$PWD/quazip_global.h \ - $$PWD/unzip.h \ - $$PWD/zip.h \ - -DEFINES += \ - QUAZIP_STATIC - diff --git a/utils/rbutilqt/quazip/quazip_qt_compat.h b/utils/rbutilqt/quazip/quazip_qt_compat.h new file mode 100644 index 0000000000..d1c912a04d --- /dev/null +++ b/utils/rbutilqt/quazip/quazip_qt_compat.h @@ -0,0 +1,120 @@ +#ifndef QUAZIP_QT_COMPAT_H +#define QUAZIP_QT_COMPAT_H + +/* + * For some reason, Qt 5.14 and 5.15 introduced a whole mess of seemingly random + * moves and deprecations. To avoid populating code with #ifs, + * we handle this stuff here, as well as some other compatibility issues. + * + * Some includes are repeated just in case we want to split this file later. + */ + +#include +#include + +// Legacy encodings are still everywhere, but the Qt team decided we +// don't need them anymore and moved them out of Core in Qt 6. +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +# include +#else +# include +#endif + +// QSaveFile terribly breaks the is-a idiom (Liskov substitution principle): +// QSaveFile is-a QIODevice, but it makes close() private and aborts +// if you call it through the base class. Hence this ugly hack: +#if (QT_VERSION >= 0x050100) +#include +inline bool quazip_close(QIODevice *device) { + QSaveFile *file = qobject_cast(device); + if (file != nullptr) { + // We have to call the ugly commit() instead: + return file->commit(); + } else { + device->close(); + return true; + } +} +#else +inline bool quazip_close(QIODevice *device) { + device->close(); + return true; +} +#endif + +// this is yet another stupid move and deprecation +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) +using Qt::SkipEmptyParts; +#else +#include +const auto SkipEmptyParts = QString::SplitBehavior::SkipEmptyParts; +#endif + +// and yet another... (why didn't they just make qSort delegate to std::sort?) +#include +#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)) +#include +template +inline void quazip_sort(T begin, T end, C comparator) { + std::sort(begin, end, comparator); +} +#else +#include +template +inline void quazip_sort(T begin, T end, C comparator) { + qSort(begin, end, comparator); +} +#endif + +// this is a stupid rename... +#include +#include +#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) +inline QDateTime quazip_ctime(const QFileInfo &fi) { + return fi.birthTime(); +} +#else +inline QDateTime quazip_ctime(const QFileInfo &fi) { + return fi.created(); +} +#endif + +// this is not a deprecation but an improvement, for a change +#include +#if (QT_VERSION >= 0x040700) +inline quint64 quazip_ntfs_ticks(const QDateTime &time, int fineTicks) { + QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); + return base.msecsTo(time) * 10000 + fineTicks; +} +#else +inline quint64 quazip_ntfs_ticks(const QDateTime &time, int fineTicks) { + QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); + QDateTime utc = time.toUTC(); + return (static_cast(base.date().daysTo(utc.date())) + * Q_INT64_C(86400000) + + static_cast(base.time().msecsTo(utc.time()))) + * Q_INT64_C(10000) + fineTicks; +} +#endif + +// yet another improvement... +#include +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) // Yay! Finally a way to get time as qint64! +inline qint64 quazip_to_time64_t(const QDateTime &time) { + return time.toSecsSinceEpoch(); +} +#else +inline qint64 quazip_to_time64_t(const QDateTime &time) { + return static_cast(time.toTime_t()); // 32 bits only, but better than nothing +} +#endif + +#include +// and another stupid move +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) +const auto quazip_endl = Qt::endl; +#else +const auto quazip_endl = endl; +#endif + +#endif // QUAZIP_QT_COMPAT_H diff --git a/utils/rbutilqt/quazip/quazipfile.cpp b/utils/rbutilqt/quazip/quazipfile.cpp index b984de7279..d70acf7fe3 100644 --- a/utils/rbutilqt/quazip/quazipfile.cpp +++ b/utils/rbutilqt/quazip/quazipfile.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -82,7 +82,7 @@ class QuaZipFilePrivate { /// The constructor for the corresponding QuaZipFile constructor. inline QuaZipFilePrivate(QuaZipFile *q): q(q), - zip(NULL), + zip(nullptr), caseSensitivity(QuaZip::csDefault), raw(false), writePos(0), @@ -177,18 +177,18 @@ QuaZipFile::~QuaZipFile() QString QuaZipFile::getZipName() const { - return p->zip==NULL ? QString() : p->zip->getZipName(); + return p->zip==nullptr ? QString() : p->zip->getZipName(); } QuaZip *QuaZipFile::getZip() const { - return p->internal ? NULL : p->zip; + return p->internal ? nullptr : p->zip; } QString QuaZipFile::getActualFileName()const { p->setZipError(UNZ_OK); - if (p->zip == NULL || (openMode() & WriteOnly)) + if (p->zip == nullptr || (openMode() & WriteOnly)) return QString(); QString name=p->zip->getCurrentFileName(); if(name.isNull()) @@ -202,7 +202,7 @@ void QuaZipFile::setZipName(const QString& zipName) qWarning("QuaZipFile::setZipName(): file is already open - can not set ZIP name"); return; } - if(p->zip!=NULL && p->internal) + if(p->zip!=nullptr && p->internal) delete p->zip; p->zip=new QuaZip(zipName); p->internal=true; @@ -214,7 +214,7 @@ void QuaZipFile::setZip(QuaZip *zip) qWarning("QuaZipFile::setZip(): file is already open - can not set ZIP"); return; } - if(p->zip!=NULL && p->internal) + if(p->zip!=nullptr && p->internal) delete p->zip; p->zip=zip; p->fileName=QString(); @@ -223,7 +223,7 @@ void QuaZipFile::setZip(QuaZip *zip) void QuaZipFile::setFileName(const QString& fileName, QuaZip::CaseSensitivity cs) { - if(p->zip==NULL) { + if(p->zip==nullptr) { qWarning("QuaZipFile::setFileName(): call setZipName() first"); return; } @@ -253,7 +253,7 @@ void QuaZipFilePrivate::setZipError(int zipError) const bool QuaZipFile::open(OpenMode mode) { - return open(mode, NULL); + return open(mode, nullptr); } bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const char *password) @@ -279,8 +279,8 @@ bool QuaZipFile::open(OpenMode mode, int *method, int *level, bool raw, const ch return false; } } else { - if(p->zip==NULL) { - qWarning("QuaZipFile::open(): zip is NULL"); + if(p->zip==nullptr) { + qWarning("QuaZipFile::open(): zip is null"); return false; } if(p->zip->getMode()!=QuaZip::mdUnzip) { @@ -321,8 +321,8 @@ bool QuaZipFile::open(OpenMode mode, const QuaZipNewInfo& info, qWarning("QuaZipFile::open(): write mode is incompatible with internal QuaZip approach"); return false; } - if(p->zip==NULL) { - qWarning("QuaZipFile::open(): zip is NULL"); + if(p->zip==nullptr) { + qWarning("QuaZipFile::open(): zip is null"); return false; } if(p->zip->getMode()!=QuaZip::mdCreate&&p->zip->getMode()!=QuaZip::mdAppend&&p->zip->getMode()!=QuaZip::mdAdd) { @@ -382,7 +382,7 @@ bool QuaZipFile::isSequential()const qint64 QuaZipFile::pos()const { - if(p->zip==NULL) { + if(p->zip==nullptr) { qWarning("QuaZipFile::pos(): call setZipName() or setZip() first"); return -1; } @@ -401,7 +401,7 @@ qint64 QuaZipFile::pos()const bool QuaZipFile::atEnd()const { - if(p->zip==NULL) { + if(p->zip==nullptr) { qWarning("QuaZipFile::atEnd(): call setZipName() or setZip() first"); return false; } @@ -433,8 +433,8 @@ qint64 QuaZipFile::csize()const { unz_file_info64 info_z; p->setZipError(UNZ_OK); - if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; - p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(p->zip==nullptr||p->zip->getMode()!=QuaZip::mdUnzip) return -1; + p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, nullptr, 0, nullptr, 0, nullptr, 0)); if(p->zipError!=UNZ_OK) return -1; return info_z.compressed_size; @@ -444,8 +444,8 @@ qint64 QuaZipFile::usize()const { unz_file_info64 info_z; p->setZipError(UNZ_OK); - if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return -1; - p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, NULL, 0, NULL, 0, NULL, 0)); + if(p->zip==nullptr||p->zip->getMode()!=QuaZip::mdUnzip) return -1; + p->setZipError(unzGetCurrentFileInfo64(p->zip->getUnzFile(), &info_z, nullptr, 0, nullptr, 0, nullptr, 0)); if(p->zipError!=UNZ_OK) return -1; return info_z.uncompressed_size; @@ -464,7 +464,7 @@ bool QuaZipFile::getFileInfo(QuaZipFileInfo *info) bool QuaZipFile::getFileInfo(QuaZipFileInfo64 *info) { - if(p->zip==NULL||p->zip->getMode()!=QuaZip::mdUnzip) return false; + if(p->zip==nullptr||p->zip->getMode()!=QuaZip::mdUnzip) return false; p->zip->getCurrentFileInfo(info); p->setZipError(p->zip->getZipError()); return p->zipError==UNZ_OK; @@ -473,7 +473,7 @@ bool QuaZipFile::getFileInfo(QuaZipFileInfo64 *info) void QuaZipFile::close() { p->resetZipError(); - if(p->zip==NULL||!p->zip->isOpen()) return; + if(p->zip==nullptr||!p->zip->isOpen()) return; if(!isOpen()) { qWarning("QuaZipFile::close(): file isn't open"); return; @@ -544,7 +544,7 @@ qint64 QuaZipFile::bytesAvailable() const QByteArray QuaZipFile::getLocalExtraField() { - int size = unzGetLocalExtrafield(p->zip->getUnzFile(), NULL, 0); + int size = unzGetLocalExtrafield(p->zip->getUnzFile(), nullptr, 0); QByteArray extra(size, '\0'); int err = unzGetLocalExtrafield(p->zip->getUnzFile(), extra.data(), static_cast(extra.size())); if (err < 0) { diff --git a/utils/rbutilqt/quazip/quazipfile.h b/utils/rbutilqt/quazip/quazipfile.h index 0fd6829f36..b49c50b9f3 100644 --- a/utils/rbutilqt/quazip/quazipfile.h +++ b/utils/rbutilqt/quazip/quazipfile.h @@ -4,20 +4,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -39,7 +39,7 @@ class QuaZipFilePrivate; * interface to the ZIP/UNZIP package, but also integrates it with Qt by * subclassing QIODevice. This makes possible to access files inside ZIP * archive using QTextStream or QDataStream, for example. Actually, this - * is the main purpose of the whole QuaZIP library. + * is the main purpose of the whole QuaZip library. * * You can either use existing QuaZip instance to create instance of * this class or pass ZIP archive file name to this class, in which case @@ -107,7 +107,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * QuaZipFile constructed by this constructor can be used for read * only access. Use QuaZipFile(QuaZip*,QObject*) for writing. **/ - QuaZipFile(const QString& zipName, QObject *parent =NULL); + QuaZipFile(const QString& zipName, QObject *parent =nullptr); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object, \a * zipName specifies ZIP archive file name and \a fileName and \a cs @@ -119,7 +119,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * \sa QuaZip::setCurrentFile() **/ QuaZipFile(const QString& zipName, const QString& fileName, - QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =NULL); + QuaZip::CaseSensitivity cs =QuaZip::csDefault, QObject *parent =nullptr); /// Constructs a QuaZipFile instance. /** \a parent argument specifies this object's parent object. * @@ -169,7 +169,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * zip.close(); * \endcode **/ - QuaZipFile(QuaZip *zip, QObject *parent =NULL); + QuaZipFile(QuaZip *zip, QObject *parent =nullptr); /// Destroys a QuaZipFile instance. /** Closes file if open, destructs internal QuaZip object (if it * exists and \em is internal, of course). @@ -296,7 +296,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * it is NULL then this function behaves just like open(OpenMode). **/ inline bool open(OpenMode mode, const char *password) - {return open(mode, NULL, NULL, false, password);} + {return open(mode, nullptr, nullptr, false, password);} /// Opens a file for reading. /** \overload * Argument \a password specifies a password to decrypt the file. @@ -309,7 +309,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * \a method should not be \c NULL. \a level can be \c NULL if you * don't want to know the compression level. **/ - bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =NULL); + bool open(OpenMode mode, int *method, int *level, bool raw, const char *password =nullptr); /// Opens a file for writing. /** \a info argument specifies information about file. It should at * least specify a correct file name. Also, it is a good idea to @@ -339,7 +339,7 @@ class QUAZIP_EXPORT QuaZipFile: public QIODevice { * algorithms tuning. See deflateInit2() in zlib. **/ bool open(OpenMode mode, const QuaZipNewInfo& info, - const char *password =NULL, quint32 crc =0, + const char *password =nullptr, quint32 crc =0, int method =Z_DEFLATED, int level =Z_DEFAULT_COMPRESSION, bool raw =false, int windowBits =-MAX_WBITS, int memLevel =DEF_MEM_LEVEL, int strategy =Z_DEFAULT_STRATEGY); /// Returns \c true, but \ref quazipfile-sequential "beware"! diff --git a/utils/rbutilqt/quazip/quazipfileinfo.cpp b/utils/rbutilqt/quazip/quazipfileinfo.cpp index d5798ea771..3f58b40216 100644 --- a/utils/rbutilqt/quazip/quazipfileinfo.cpp +++ b/utils/rbutilqt/quazip/quazipfileinfo.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -28,7 +28,7 @@ see quazip/(un)zip.h files for details. Basically it's the zlib license. static QFile::Permissions permissionsFromExternalAttr(quint32 externalAttr) { quint32 uPerm = (externalAttr & 0xFFFF0000u) >> 16; - QFile::Permissions perm = QFile::Permissions(); + QFile::Permissions perm; if ((uPerm & 0400) != 0) perm |= QFile::ReadOwner; if ((uPerm & 0200) != 0) @@ -115,9 +115,11 @@ static QDateTime getNTFSTime(const QByteArray &extra, int position, timeReader.device()->seek(position); quint64 time; timeReader >> time; + if (time == 0) + return dateTime; QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); dateTime = base.addMSecs(time / 10000); - if (fineTicks != NULL) { + if (fineTicks != nullptr) { *fineTicks = static_cast(time % 10000); } return dateTime; diff --git a/utils/rbutilqt/quazip/quazipfileinfo.h b/utils/rbutilqt/quazip/quazipfileinfo.h index 43665b4ac2..4812fc2db0 100644 --- a/utils/rbutilqt/quazip/quazipfileinfo.h +++ b/utils/rbutilqt/quazip/quazipfileinfo.h @@ -4,20 +4,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -140,7 +140,7 @@ struct QUAZIP_EXPORT QuaZipFileInfo64 { /** * The getNTFS*Time() functions only work if there is an NTFS extra field * present. Otherwise, they all return invalid null timestamps. - * @param fineTicks If not NULL, the fractional part of milliseconds returned + * @param fineTicks If not null, the fractional part of milliseconds returned * there, measured in 100-nanosecond ticks. Will be set to * zero if there is no NTFS extra field. * @sa dateTime @@ -148,12 +148,12 @@ struct QUAZIP_EXPORT QuaZipFileInfo64 { * @sa getNTFScTime() * @return The NTFS modification time, UTC */ - QDateTime getNTFSmTime(int *fineTicks = NULL) const; + QDateTime getNTFSmTime(int *fineTicks = nullptr) const; /// Returns the NTFS access time /** * The getNTFS*Time() functions only work if there is an NTFS extra field * present. Otherwise, they all return invalid null timestamps. - * @param fineTicks If not NULL, the fractional part of milliseconds returned + * @param fineTicks If not null, the fractional part of milliseconds returned * there, measured in 100-nanosecond ticks. Will be set to * zero if there is no NTFS extra field. * @sa dateTime @@ -161,12 +161,12 @@ struct QUAZIP_EXPORT QuaZipFileInfo64 { * @sa getNTFScTime() * @return The NTFS access time, UTC */ - QDateTime getNTFSaTime(int *fineTicks = NULL) const; + QDateTime getNTFSaTime(int *fineTicks = nullptr) const; /// Returns the NTFS creation time /** * The getNTFS*Time() functions only work if there is an NTFS extra field * present. Otherwise, they all return invalid null timestamps. - * @param fineTicks If not NULL, the fractional part of milliseconds returned + * @param fineTicks If not null, the fractional part of milliseconds returned * there, measured in 100-nanosecond ticks. Will be set to * zero if there is no NTFS extra field. * @sa dateTime @@ -174,7 +174,7 @@ struct QUAZIP_EXPORT QuaZipFileInfo64 { * @sa getNTFSaTime() * @return The NTFS creation time, UTC */ - QDateTime getNTFScTime(int *fineTicks = NULL) const; + QDateTime getNTFScTime(int *fineTicks = nullptr) const; /// Returns the extended modification timestamp /** * The getExt*Time() functions only work if there is an extended timestamp diff --git a/utils/rbutilqt/quazip/quazipnewinfo.cpp b/utils/rbutilqt/quazip/quazipnewinfo.cpp index 98630e086a..659e4f7720 100644 --- a/utils/rbutilqt/quazip/quazipnewinfo.cpp +++ b/utils/rbutilqt/quazip/quazipnewinfo.cpp @@ -1,20 +1,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. @@ -25,6 +25,7 @@ see quazip/(un)zip.h files for details. Basically it's the zlib license. #include #include "quazipnewinfo.h" +#include "quazip_qt_compat.h" #include @@ -134,11 +135,7 @@ void QuaZipNewInfo::setFileNTFSTimes(const QString &fileName) } setFileNTFSmTime(fi.lastModified()); setFileNTFSaTime(fi.lastRead()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) - setFileNTFScTime(fi.birthTime()); -#else - setFileNTFScTime(fi.created()); -#endif + setFileNTFScTime(quazip_ctime(fi)); } static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position, @@ -251,16 +248,7 @@ static void setNTFSTime(QByteArray &extra, const QDateTime &time, int position, extra[timesPos + 2] = static_cast(ntfsTimesLength); extra[timesPos + 3] = static_cast(ntfsTimesLength >> 8); } - QDateTime base(QDate(1601, 1, 1), QTime(0, 0), Qt::UTC); -#if (QT_VERSION >= 0x040700) - quint64 ticks = base.msecsTo(time) * 10000 + fineTicks; -#else - QDateTime utc = time.toUTC(); - quint64 ticks = (static_cast(base.date().daysTo(utc.date())) - * Q_INT64_C(86400000) - + static_cast(base.time().msecsTo(utc.time()))) - * Q_INT64_C(10000) + fineTicks; -#endif + quint64 ticks = quazip_ntfs_ticks(time, fineTicks); extra[timesPos + 4 + position] = static_cast(ticks); extra[timesPos + 5 + position] = static_cast(ticks >> 8); extra[timesPos + 6 + position] = static_cast(ticks >> 16); diff --git a/utils/rbutilqt/quazip/quazipnewinfo.h b/utils/rbutilqt/quazip/quazipnewinfo.h index 43a1e6fd08..bad70c27d3 100644 --- a/utils/rbutilqt/quazip/quazipnewinfo.h +++ b/utils/rbutilqt/quazip/quazipnewinfo.h @@ -4,20 +4,20 @@ /* Copyright (C) 2005-2014 Sergey A. Tachenov -This file is part of QuaZIP. +This file is part of QuaZip. -QuaZIP is free software: you can redistribute it and/or modify +QuaZip is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. -QuaZIP is distributed in the hope that it will be useful, +QuaZip 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License -along with QuaZIP. If not, see . +along with QuaZip. If not, see . See COPYING file for the full LGPL text. diff --git a/utils/rbutilqt/quazip/unzip.c b/utils/rbutilqt/quazip/unzip.c index 6aaeba6930..3e147d7d82 100644 --- a/utils/rbutilqt/quazip/unzip.c +++ b/utils/rbutilqt/quazip/unzip.c @@ -10,7 +10,7 @@ Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - Modifications for QIODevice support and other QuaZIP fixes + Modifications for QIODevice support and other QuaZip fixes Copyright (C) 2005-2014 Sergey A. Tachenov For more info read MiniZip_info.txt diff --git a/utils/rbutilqt/quazip/unzip.h b/utils/rbutilqt/quazip/unzip.h index fdefa2217a..e898332f94 100644 --- a/utils/rbutilqt/quazip/unzip.h +++ b/utils/rbutilqt/quazip/unzip.h @@ -206,7 +206,7 @@ extern unzFile ZEXPORT unzOpen2_64 OF((voidpf file, /* - * Exported by Sergey A. Tachenov to implement some QuaZIP features. This + * Exported by Sergey A. Tachenov to implement some QuaZip features. This * function MAY change signature in order to implement even more features. * You have been warned! * */ diff --git a/utils/rbutilqt/quazip/zip.c b/utils/rbutilqt/quazip/zip.c index 0f3deb04c1..dc8e15fc21 100644 --- a/utils/rbutilqt/quazip/zip.c +++ b/utils/rbutilqt/quazip/zip.c @@ -9,7 +9,7 @@ For more info read MiniZip_info.txt - Modifications for QIODevice support and other QuaZIP fixes + Modifications for QIODevice support and other QuaZip fixes Copyright (C) 2005-2014 Sergey A. Tachenov Fixing static code analysis issues diff --git a/utils/rbutilqt/quazip/zip.h b/utils/rbutilqt/quazip/zip.h index 114a1bf6e7..5837d95ade 100644 --- a/utils/rbutilqt/quazip/zip.h +++ b/utils/rbutilqt/quazip/zip.h @@ -129,7 +129,7 @@ extern zipFile ZEXPORT zipOpen OF((voidpf file, int append)); extern zipFile ZEXPORT zipOpen64 OF((voidpf file, int append)); /* Create a zipfile. - the file argument depends on the API used, for QuaZIP it's a QIODevice + the file argument depends on the API used, for QuaZip it's a QIODevice pointer. if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip will be created at the end of the file. @@ -157,9 +157,9 @@ extern zipFile ZEXPORT zipOpen2_64 OF((voidpf file, zlib_filefunc64_def* pzlib_filefunc_def)); /* - * Exported by Sergey A. Tachenov to suit the needs of QuaZIP. + * Exported by Sergey A. Tachenov to suit the needs of QuaZip. * Note that this function MAY change signature in order to - * provide new QuaZIP features. You have been warned! + * provide new QuaZip features. You have been warned! * */ extern zipFile ZEXPORT zipOpen3 (voidpf file, int append, From 3bfce366acea3fdc2620ac7552656808b48c97a4 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Thu, 29 Jan 2026 12:13:26 +0200 Subject: [PATCH 08/75] hiby: r1_patcher: stop script execution on any error Change-Id: Ic683b8ed155a5e9d2779d40a3b7673579056d9b1 --- tools/r1_patcher/r1_patcher.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/r1_patcher/r1_patcher.sh b/tools/r1_patcher/r1_patcher.sh index 7d1653310e..7cc102044b 100755 --- a/tools/r1_patcher/r1_patcher.sh +++ b/tools/r1_patcher/r1_patcher.sh @@ -8,6 +8,12 @@ if [[ $# -ne 2 ]]; then exit 1 fi +# Fail fast on any error, undefined variable, or failed pipeline +set -euo pipefail + +# Report errors with line number and the failing command +trap 'echo "ERROR at line ${LINENO}: ${BASH_COMMAND}" >&2' ERR + ################################################################################ ### init ################################################################################ From 98b25f146ba88fff1dec97a50fab470b91f8ddbe Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Sat, 31 Jan 2026 15:43:14 +0200 Subject: [PATCH 09/75] rockboxdev: glib: drop tests and docs from autreconf Removes dependency on distuitls (ModuleNotFoundError: No module named 'distutils'); gtk-doc-tools still required; Change-Id: I50f69411d146b5b9b9c496b3507bcef5bb1638bc --- tools/rockboxdev.sh | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/rockboxdev.sh b/tools/rockboxdev.sh index e06b3afbef..8b8d4d204a 100755 --- a/tools/rockboxdev.sh +++ b/tools/rockboxdev.sh @@ -391,15 +391,22 @@ buildtool () { cflags='-U_FORTIFY_SOURCE -fgnu89-inline -O2' if [ "$tool" == "glibc" ]; then cflags="$cflags -fcommon" # glibc < 2.30 needs -fcommon for gcc10+ - elif [ "$tool" == "glib" ]; then - run_cmd "$logfile" $SED -i -e 's/m4_copy/m4_copy_force/g' "$cfg_dir/m4macros/glib-gettext.m4" - run_cmd "$logfile" autoreconf -fiv "$cfg_dir" + elif [ "$tool" == "glib" ]; then + # glib < 2.47.5 requires this hack on newer systems to fix legacy python related build failure + # Note: autoreconf call adds dependency on gtk-doc-tools + if version_lt "$version" "2.47.5"; then + run_cmd "$logfile" $SED -i -e 's/m4_copy/m4_copy_force/g' "$cfg_dir/m4macros/glib-gettext.m4" + run_cmd "$logfile" $SED -i 's/tests//' "$cfg_dir/gio/Makefile.am" + run_cmd "$logfile" autoreconf -fiv "$cfg_dir" + config_opt="$config_opt --disable-gtk-doc" + fi + cflags="$cflags -Wno-format-nonliteral -Wno-format-overflow" fi # NOTE glibc requires to be compiled with optimization CFLAGS="$cflags" CXXFLAGS="$CXXFLAGS" run_cmd "$logfile" \ "$cfg_dir/configure" "--prefix=$prefix" \ - --disable-docs $config_opt + --disable-docs --disable-tests $config_opt fi if [ "$make_opts" != "NO_MAKE" ]; then From c458f4663cdc2398a2514aabde2386d0d1391e74 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 1 Feb 2026 07:38:11 -0500 Subject: [PATCH 10/75] x1000: Do not use QSPI mode on the XT26G01C flash Either QSPI is not wired up, or there is some other issue preventing them from working correctly. If this doesn't show any more issues then we should be able to produce a new set of bootloader builds enabling support for the HifiWalker H2 v2.3 variant. We will eventually find out if other OEMs have chosen dfferent flash parts for their specific ErosQ/K variations. (Credit for these experiments goes to the forum users ZappBranigan2972 and gonzyfrigus) Change-Id: I349f4bbac509010753ac2ad24ad42a234cccdea5 --- firmware/target/mips/ingenic_x1000/nand-x1000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c index d66ce0162e..aab7c74fe3 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.c +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c @@ -111,8 +111,8 @@ static const struct nand_chip chip_xt26g01cwsiga = { .cmd_page_read = NANDCMD_PAGE_READ, .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE, .cmd_block_erase = NANDCMD_BLOCK_ERASE, - .cmd_read_cache = NANDCMD_READ_CACHE_x4, - .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4, + .cmd_read_cache = NANDCMD_READ_CACHE, + .cmd_program_load = NANDCMD_PROGRAM_LOAD, }; #define chip_ds35x1gaxxx chip_gd5f1gq4xexx From 3083277ee481b15e10ae4244785fd4bda329e7f6 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 1 Feb 2026 09:14:43 -0500 Subject: [PATCH 11/75] rbutil: Don't forget to bump the version for MacOS builds (And a minor correction to the changelog) Change-Id: Ic00e32444ee815b214755c8a17a511ce4310caca --- utils/rbutilqt/Info.plist | 2 +- utils/rbutilqt/changelog.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/rbutilqt/Info.plist b/utils/rbutilqt/Info.plist index 15a5dc5313..26c22003a6 100644 --- a/utils/rbutilqt/Info.plist +++ b/utils/rbutilqt/Info.plist @@ -7,7 +7,7 @@ CFBundleName Rockbox Utility CFBundleShortVersionString - 1.5.1 + 1.5.2 CFBundleIconFile rbutilqt.icns CFBundleIdentifier diff --git a/utils/rbutilqt/changelog.txt b/utils/rbutilqt/changelog.txt index 1f6c6f58a3..0a244f981c 100644 --- a/utils/rbutilqt/changelog.txt +++ b/utils/rbutilqt/changelog.txt @@ -50,7 +50,7 @@ Version 1.5.1 Version 1.5.2 * Add support for Native Port to AIGO Eros Q and various clones -* Make Hosted Port to AIGO Eros Q and various clones "disabled" (can be reenabled by checking the "show disabled targets" checkbox) +* Mark hosted oort to AIGO Eros Q and various clones "disabled" (can be reenabled by checking the "show disabled targets" checkbox) * Talk clip generation now respects 'talkclips.ignore' files * Generate additional talk clips for language name and 'invalid voice file' * When installing development builds, fall back to daily artefacts for non-firmware files From 01f96e40a7073893aabccc328aec55a7adc594fc Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 1 Feb 2026 12:00:54 +0000 Subject: [PATCH 12/75] mpegplayer: remove IRAM save/restore hack On targets where plugins can use IRAM, mpegplayer copies its own IRAM region to main memory before enabling voiced menus and then copies it back when exiting the menu. I'm reasonably certain this is unnecessary because the core IRAM area is completely separate from plugin IRAM (which is the same memory as codec IRAM). If they _did_ conflict, then we'd expect to see massive problems with voiced menus during normal playback since most codecs make fairly heavy use of IRAM. There are two other reasons to get rid of this hack: (1) it's ugly, and (2) it will not work on targets with "split" IRAM like on the STM32H743 where the fastest code/data memories are separate. Change-Id: Id8656539c7cafb724691494c54a07448fbcf8129 --- apps/plugins/mpegplayer/mpeg_settings.c | 43 --------------- apps/plugins/mpegplayer/mpegplayer.c | 72 ------------------------- apps/plugins/mpegplayer/mpegplayer.h | 6 --- 3 files changed, 121 deletions(-) diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 8c4b6d4ee3..1a5b0d99cb 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c @@ -985,13 +985,6 @@ static int get_start_time(uint32_t duration) case STATE0: if (!sliding) { - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } trigger_cpu_boost(); sliding = true; } @@ -1010,10 +1003,6 @@ static int get_start_time(uint32_t duration) cancel_cpu_boost(); if (rb->global_settings->talk_menu) { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); talk_val(resume_time / TS_SECOND, UNIT_TIME, false); talk_val(resume_time * 100 / duration, UNIT_PERCENT, true); } @@ -1053,14 +1042,6 @@ static int show_start_menu(uint32_t duration) ID2P(LANG_SETTINGS), ID2P(LANG_MENU_QUIT)); - if (rb->global_settings->talk_menu) - { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); - } - rb->button_clear_queue(); while (!menu_quit) @@ -1109,14 +1090,6 @@ static int show_start_menu(uint32_t duration) } } - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } - return result; } @@ -1151,14 +1124,6 @@ int mpeg_menu(void) ID2P(LANG_RESUME_PLAYBACK), ID2P(LANG_MENU_QUIT)); - if (rb->global_settings->talk_menu) - { -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_preserve(); -#endif - rb->talk_disable(false); - } - rb->button_clear_queue(); mpeg_sysevent_clear(); @@ -1184,14 +1149,6 @@ int mpeg_menu(void) if (mpeg_sysevent() != 0) result = MPEG_MENU_QUIT; - if (rb->global_settings->talk_menu) - { - rb->talk_disable(true); -#ifdef PLUGIN_USE_IRAM - mpegplayer_iram_restore(); -#endif - } - return result; } diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 923dff0b40..5d7d6036d2 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -690,54 +690,6 @@ static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount) } #endif -#ifdef PLUGIN_USE_IRAM -/* IRAM preserving mechanism to enable talking menus */ -static char *iram_saved_copy; -extern char iramstart[], iramend[]; - -static void iram_saving_init(void) -{ -#ifndef SIMULATOR - size_t size; - iram_saved_copy = (char *)rb->plugin_get_buffer(&size); - - if (size >= (size_t)(iramend-iramstart)) - iram_saved_copy += size - (size_t)(iramend - iramstart); - else -#endif - iram_saved_copy = NULL; - - return; -} - -void mpegplayer_iram_preserve(void) -{ - if (iram_saved_copy) - { - rb->memcpy(iram_saved_copy, iramstart, iramend-iramstart); -#ifdef HAVE_CPUCACHE_INVALIDATE - /* make the icache (if it exists) up to date with the new code */ - rb->cpucache_invalidate(); -#endif /* HAVE_CPUCACHE_INVALIDATE */ - } - return; -} - -void mpegplayer_iram_restore(void) -{ - if (iram_saved_copy) - { - rb->audio_hard_stop(); - rb->memcpy(iramstart, iram_saved_copy, iramend-iramstart); -#ifdef HAVE_CPUCACHE_INVALIDATE - /* make the icache (if it exists) up to date with the new code */ - rb->cpucache_invalidate(); -#endif /* HAVE_CPUCACHE_INVALIDATE */ - } - return; -} -#endif - /* Drawing functions that operate rotated on LCD_PORTRAIT displays - * most are just wrappers of lcd_* functions with transforms applied. * The origin is the upper-left corner of the OSD area */ @@ -2472,29 +2424,12 @@ enum plugin_status plugin_start(const void* parameter) int status = PLUGIN_OK; /* assume success */ bool quit = false; -#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) - bool preserved_talk_state; -#endif - if (parameter == NULL) { /* No file = GTFO */ rb->splash(HZ*2, "No File"); return PLUGIN_ERROR; } - /* Disable all talking before initializing IRAM */ - rb->talk_disable(true); - -#ifdef PLUGIN_USE_IRAM - iram_saving_init(); - -#ifndef SIMULATOR - preserved_talk_state = rb->global_settings->talk_menu; - if (!iram_saved_copy) - rb->global_settings->talk_menu = false; -#endif -#endif - #ifdef HAVE_LCD_COLOR rb->lcd_set_backdrop(NULL); rb->lcd_set_foreground(LCD_WHITE); @@ -2645,13 +2580,6 @@ enum plugin_status plugin_start(const void* parameter) stream_exit(); -#if defined(PLUGIN_USE_IRAM) && !defined(SIMULATOR) - if (!iram_saved_copy) - rb->global_settings->talk_menu = preserved_talk_state; -#endif - - rb->talk_disable(false); - /* Actually handle delayed processing of system events of interest * that were captured in other button loops */ mpeg_sysevent_handle(); diff --git a/apps/plugins/mpegplayer/mpegplayer.h b/apps/plugins/mpegplayer/mpegplayer.h index 51fb9a8f8a..4ddf0ca7b1 100644 --- a/apps/plugins/mpegplayer/mpegplayer.h +++ b/apps/plugins/mpegplayer/mpegplayer.h @@ -86,10 +86,4 @@ #define LCD_ENABLE_EVENT_0 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0) #define LCD_ENABLE_EVENT_1 MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1) -#ifdef PLUGIN_USE_IRAM -/* IRAM preserving mechanism to enable talking menus */ -extern void mpegplayer_iram_preserve(void); -extern void mpegplayer_iram_restore(void); -#endif - #endif /* MPEGPLAYER_H */ From 7adb9cd1b42a4be15d9da81f11646e99e18a7295 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 25 Jan 2026 12:54:08 +0000 Subject: [PATCH 13/75] arm: add optimized ARMv7-M memcpy implementation This assembly implementation is marginally faster than the non-size-optimized C version for large copies, but is around half the code size. Unaligned loads/stores will be used on platforms that support it: though slower than aligned accesses, this is still faster than copying byte-by-byte and has the advantage of simplicity and small code size. Change-Id: Ieee73d7557318d510601583f190ef3aa018c9121 --- firmware/asm/SOURCES | 3 +- firmware/asm/arm/memcpy-armv7m.S | 80 ++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 firmware/asm/arm/memcpy-armv7m.S diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index dc8d7b5dfc..396381787a 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES @@ -21,8 +21,7 @@ arm/memmove.S arm/memset.S strlen.c #elif defined(CPU_ARM_MICRO) -memcpy.c -mempcpy.c +arm/memcpy-armv7m.S memmove.c arm/memset.S strlen.c diff --git a/firmware/asm/arm/memcpy-armv7m.S b/firmware/asm/arm/memcpy-armv7m.S new file mode 100644 index 0000000000..7d2c671175 --- /dev/null +++ b/firmware/asm/arm/memcpy-armv7m.S @@ -0,0 +1,80 @@ +#include "config.h" + +#if (CONFIG_CPU == STM32H743) +# define CPU_SUPPORTS_UNALIGNED_ACCESS +#endif + + .syntax unified + .section .icode,"ax",%progbits + + .global memcpy + .type memcpy,%function + .global mempcpy + .type mempcpy,%function + + /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ + /* Prototype: void *mempcpy(void *dest, const void *src, size_t n); */ + + /* + * r0 = dest + * r1 = src + * r2 = n + * r3 = scratch + * ip = saved r0 + */ + +mempcpy: + add ip, r0, r2 + b 0f + +memcpy: + movs ip, r0 + +0: +#if !defined(CPU_SUPPORTS_UNALIGNED_ACCESS) + /* fall back to byte copy loop if operands not aligned */ + ands r3, r0, #3 + bne 5f + ands r3, r1, #3 + bne 5f +#endif + + /* check remaining bytes >= 16 */ + subs r2, r2, #16 + blt 2f + +1: /* copy 16-byte blocks */ + ldr r3, [r1, #0] + str r3, [r0, #0] + ldr r3, [r1, #4] + str r3, [r0, #4] + ldr r3, [r1, #8] + str r3, [r0, #8] + ldr r3, [r1, #12] + str r3, [r0, #12] + adds r0, #16 + adds r1, #16 + subs r2, r2, #16 + bge 1b + +2: /* get count of remaining bytes (0-15) */ + and r2, r2, #15 + +3: /* copy 4 bytes at a time */ + subs r2, r2, #4 + ldrge r3, [r1], #4 + strge r3, [r0], #4 + bgt 3b + +4: /* get count of remaining bytes (0-3) */ + and r2, #3 + +5: /* copy 1 byte at a time */ + subs r2, r2, #1 + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + bgt 5b + +6: /* return */ + movs r0, ip + bx lr From ad9471be3b2ef4be5e452a478139778f08878bba Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sat, 24 Jan 2026 21:26:00 +0000 Subject: [PATCH 14/75] echoplayer: add shadow framebuffer to avoid tearing Using a simple memcpy to a separate framebuffer prevents objectionable levels of flickering caused by scanning out the main framebuffer while it's modified between updates. With optimized memcpy, copying the whole framebuffer takes about 260us at maximum CPU+bus frequency. Using DMA would likely be a bit faster and more power-efficient, but that can be left as a future optimization. Change-Id: Ia6dc36d797cdb7a5f6663078c0ecce661267bedf --- .../target/arm/stm32/echoplayer/lcd-echoplayer.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c index bd7ead842c..bf83ad4937 100644 --- a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c @@ -30,6 +30,7 @@ #include "regs/stm32h743/rcc.h" #include "regs/stm32h743/spi.h" #include "regs/stm32h743/ltdc.h" +#include #define MS_TO_TICKS(x) \ (((x) + (1000 / HZ - 1)) / (1000 / HZ)) @@ -60,7 +61,8 @@ struct stm_spi_config spi_cfg = { .hw_cs_output = true, }; -struct stm_spi spi; +static struct stm_spi spi; +static fb_data shadowfb[LCD_WIDTH*LCD_HEIGHT] IRAM_LCDFRAMEBUFFER; enum lcd_controller_state { @@ -101,7 +103,7 @@ static void enable_ltdc(void) reg_assignf(LTDC_LAYER_WHPCR(0), WHSPPOS(ahbp + LCD_HAW), WHSTPOS(ahbp + 1)); reg_assignf(LTDC_LAYER_WVPCR(0), WVSPPOS(avbp + LCD_VAH), WVSTPOS(avbp + 1)); reg_assignf(LTDC_LAYER_PFCR(0), PF(BV_LTDC_LAYER_PFCR_PF_RGB565)); - reg_var(LTDC_LAYER_CFBAR(0)) = (uintptr_t)FBADDR(0, 0); + reg_var(LTDC_LAYER_CFBAR(0)) = (uintptr_t)&shadowfb[0]; reg_assignf(LTDC_LAYER_CFBLR(0), CFBP(row_bytes), CFBLL(row_bytes + 7)); reg_assignf(LTDC_LAYER_CFBLNR(0), CFBLNBR(LCD_HEIGHT)); reg_assignf(LTDC_LAYER_CR(0), LEN(1)); @@ -244,6 +246,8 @@ void lcd_update(void) if (!lcd_active()) return; + /* TODO: optimize using DMA2D */ + memcpy(shadowfb, FBADDR(0, 0), sizeof(shadowfb)); commit_dcache(); } @@ -268,8 +272,13 @@ void lcd_update_rect(int x, int y, int width, int height) if (height > LCD_HEIGHT - y) height = LCD_HEIGHT - y; + /* TODO: optimize using DMA2D */ for (int dy = 0; dy < height; ++dy) - commit_dcache_range(FBADDR(x, y+dy), FB_DATA_SZ * width); + { + fb_data *shaddr = &shadowfb[(y+dy)*LCD_WIDTH + x]; + memcpy(shaddr, FBADDR(x, y+dy), FB_DATA_SZ * width); + commit_dcache_range(shaddr, FB_DATA_SZ * width); + } } void spi5_irq_handler(void) From 3f2ca2024544aca4a0dd78309fff115a75773091 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 1 Feb 2026 17:12:37 +0000 Subject: [PATCH 15/75] misc: fix issues with perceptual volume calculations The constant NVOL_FACTOR used in the calculations needs to be scaled if the target doesn't represent volumes in 1/10th dB units (ie. most targets). Using a wrong factor caused the results to be slightly "off", with wide steps between points on the upper end of the volume curve. Drop use_linear_dB_scale() because the magic constant involved has a similar problem (and we don't use this function anyway). Also, make sure to account for the guaranteed min/max points when generating the normalized volume table to avoid sometimes generating one or two extra volume steps very close to the min/max volumes. Change-Id: I5c15809a7306f14bb1befe6d29a5e2b5b0974eaa --- apps/misc.c | 55 +++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/apps/misc.c b/apps/misc.c index 39936f2b36..5c3d457d54 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -904,7 +904,7 @@ static void update_norm_tab(void) norm_tab[0] = min; norm_tab_size = 1; - for (int i = 0; i < lim; ++i) + for (int i = 1; i < lim - 1; ++i) { int vol = from_normalized_volume(i, min, max, lim); int rem = vol % step; @@ -1944,49 +1944,40 @@ int core_load_bmp(const char * filename, struct bitmap *bm, const int bmformat, #define NVOL_FRACBITS 16 #define NVOL_UNITY (1L << NVOL_FRACBITS) -#define NVOL_FACTOR (600L << NVOL_FRACBITS) - -#define NVOL_MAX_LINEAR_DB_SCALE (240L << NVOL_FRACBITS) #define nvol_div(x,y) fp_div((x), (y), NVOL_FRACBITS) #define nvol_mul(x,y) fp_mul((x), (y), NVOL_FRACBITS) #define nvol_exp10(x) fp_exp10((x), NVOL_FRACBITS) #define nvol_log10(x) fp_log10((x), NVOL_FRACBITS) -static bool use_linear_dB_scale(long min_vol, long max_vol) +static long get_nvol_factor(void) { - /* - * Alsamixer uses a linear scale for small ranges. - * Commented out so perceptual volume works as advertised on all targets. - */ - /* - return max_vol - min_vol <= NVOL_MAX_LINEAR_DB_SCALE; - */ + long factor = 600L << NVOL_FRACBITS; + long numdecimals = sound_numdecimals(SOUND_VOLUME); - (void)min_vol; - (void)max_vol; - return false; + if (numdecimals == 0) + factor /= 10; + + /* nothing *actually* needs this, but: */ + while (numdecimals > 1) + factor *= 10; + + return factor; } long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm) { long norm, min_norm; + long factor = get_nvol_factor(); vol <<= NVOL_FRACBITS; min_vol <<= NVOL_FRACBITS; max_vol <<= NVOL_FRACBITS; max_norm <<= NVOL_FRACBITS; - if (use_linear_dB_scale(min_vol, max_vol)) - { - norm = nvol_div(vol - min_vol, max_vol - min_vol); - } - else - { - min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR)); - norm = nvol_exp10(nvol_div(vol - max_vol, NVOL_FACTOR)); - norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm); - } + min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor)); + norm = nvol_exp10(nvol_div(vol - max_vol, factor)); + norm = nvol_div(norm - min_norm, NVOL_UNITY - min_norm); return nvol_mul(norm, max_norm) >> NVOL_FRACBITS; } @@ -1994,6 +1985,7 @@ long to_normalized_volume(long vol, long min_vol, long max_vol, long max_norm) long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm) { long vol, min_norm; + long factor = get_nvol_factor(); norm <<= NVOL_FRACBITS; min_vol <<= NVOL_FRACBITS; @@ -2002,16 +1994,9 @@ long from_normalized_volume(long norm, long min_vol, long max_vol, long max_norm vol = nvol_div(norm, max_norm); - if (use_linear_dB_scale(min_vol, max_vol)) - { - vol = nvol_mul(vol, max_vol - min_vol) + min_vol; - } - else - { - min_norm = nvol_exp10(nvol_div(min_vol - max_vol, NVOL_FACTOR)); - vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm; - vol = nvol_mul(nvol_log10(vol), NVOL_FACTOR) + max_vol; - } + min_norm = nvol_exp10(nvol_div(min_vol - max_vol, factor)); + vol = nvol_mul(vol, NVOL_UNITY - min_norm) + min_norm; + vol = nvol_mul(nvol_log10(vol), factor) + max_vol; return vol >> NVOL_FRACBITS; } From 78778d6e6f3aa3ff2ff0e95dc37994f9f3560300 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 2 Feb 2026 08:20:21 -0500 Subject: [PATCH 16/75] misc: Correct inifinite loop when volume has a fractional component Introduced in 3f2ca2024 Purely a theretical problem but we should fix it regardless Change-Id: Ifeb4e1aeb3291c723b2addf2f2d391775db57b03 --- apps/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/misc.c b/apps/misc.c index 5c3d457d54..05f1fa6a93 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -1959,7 +1959,7 @@ static long get_nvol_factor(void) factor /= 10; /* nothing *actually* needs this, but: */ - while (numdecimals > 1) + while (numdecimals-- > 1) factor *= 10; return factor; From 9f216921b85e3ff3ac2da35ab60630488180903f Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 2 Feb 2026 08:11:07 -0500 Subject: [PATCH 17/75] x1000: Correct SFC TMODE bit definitions We were using a definition of 0b100 for "Quad Input / Quad Output" mode which is marked as "reserved" in the X1000 TRM. The correct value is 0b101. Somehow this "worked" for some devices but failed for others? Credit for this discovery+fix goes to forum user ZappBranigan2972 Change-Id: Iedbd2d1b6da55113e266ad8aa51fc9c3130bf2b8 --- firmware/target/mips/ingenic_x1000/sfc-x1000.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.h b/firmware/target/mips/ingenic_x1000/sfc-x1000.h index afb4aa3ce6..92430880be 100644 --- a/firmware/target/mips/ingenic_x1000/sfc-x1000.h +++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.h @@ -36,9 +36,10 @@ #define SFC_TMODE_1_1_2 1 #define SFC_TMODE_1_2_2 2 #define SFC_TMODE_2_2_2 3 -#define SFC_TMODE_1_1_4 4 -#define SFC_TMODE_1_4_4 5 -#define SFC_TMODE_4_4_4 6 +#define SFC_TMODE_RESERVED 4 // See 10.7.3.6 SFC Transfer Configure Register MODE Field +#define SFC_TMODE_1_1_4 5 +#define SFC_TMODE_1_4_4 6 +#define SFC_TMODE_4_4_4 7 /* Phase format * _____________________ From 84e5d193fb408833057c59ec1f34d3745bcdae69 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 2 Feb 2026 08:18:55 -0500 Subject: [PATCH 18/75] x1000: Turn on QSPI mode for W25N01GV and XT26G01C flashes With the QSPI TMODE fix, they are confirmed working Change-Id: Ic47b13312299bab8a632ebf517015362a0cb6a49 --- firmware/target/mips/ingenic_x1000/nand-x1000.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c index aab7c74fe3..e3175ca0d9 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.c +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c @@ -61,13 +61,13 @@ static const struct nand_chip chip_w25n01gvxx = { TSH(11), TSETUP(0), THOLD(0), STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), SMP_DELAY(1)), - .flags = NAND_CHIPFLAG_ON_DIE_ECC, - /* TODO: quad mode? */ + .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT | + NAND_CHIPFLAG_ON_DIE_ECC, .cmd_page_read = NANDCMD_PAGE_READ, .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE, .cmd_block_erase = NANDCMD_BLOCK_ERASE, - .cmd_read_cache = NANDCMD_READ_CACHE_SLOW, - .cmd_program_load = NANDCMD_PROGRAM_LOAD, + .cmd_read_cache = NANDCMD_READ_CACHE_x4, + .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4, .setup_chip = winbond_setup_chip, }; @@ -111,8 +111,8 @@ static const struct nand_chip chip_xt26g01cwsiga = { .cmd_page_read = NANDCMD_PAGE_READ, .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE, .cmd_block_erase = NANDCMD_BLOCK_ERASE, - .cmd_read_cache = NANDCMD_READ_CACHE, - .cmd_program_load = NANDCMD_PROGRAM_LOAD, + .cmd_read_cache = NANDCMD_READ_CACHE_x4, + .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4, }; #define chip_ds35x1gaxxx chip_gd5f1gq4xexx From 3a688480994c6264aa7ec771e812c090fb18b85d Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 31 Jan 2026 17:11:28 -0500 Subject: [PATCH 19/75] erosqnative: Rename bootloader entries for stock firmware / recovery "Aigo Player" => "Hiby Player" "Aigo Recovery" => "HibyOS Recovery" All four (so far) brandings of the "erosq/k" family utilize the same HibyOS+HibyPlayer platform. This platform is additionally shared by nearly all X1000-based devices. ...So let's call it what it is. Change-Id: I986ed202ad0ca13b0650be87cf5b612c9648e571 --- bootloader/x1000/x1000bootloader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootloader/x1000/x1000bootloader.h b/bootloader/x1000/x1000bootloader.h index 0b5b02969d..44e56cda80 100644 --- a/bootloader/x1000/x1000bootloader.h +++ b/bootloader/x1000/x1000bootloader.h @@ -100,14 +100,14 @@ struct uimage_header; # define BL_QUIT_NAME "POWER" # define BL_SCREENSHOT_NAME "MENU" # define BOOTBACKUP_FILE "/erosqnative-boot.bin" -# define OF_PLAYER_NAME "Aigo Player" +# define OF_PLAYER_NAME "Hiby Player" # define OF_PLAYER_ADDR 0x300000 # define OF_PLAYER_LENGTH (6 * 1024 * 1024) # define OF_PLAYER_ARGS OF_RECOVERY_ARGS \ " init=/linuxrc ubi.mtd=4 root=ubi0:rootfs ubi.mtd=5 rootfstype=ubifs \ sn_no=00000000000000000000000000000000 bt_mac=xxxxxxxxxxxx wifi_mac=xxxxxxxxxxxx rw" # define OF_PLAYER_BTN BUTTON_PLAY -# define OF_RECOVERY_NAME "Aigo Recovery" +# define OF_RECOVERY_NAME "HibyOS Recovery" # define OF_RECOVERY_ADDR 0x900000 # define OF_RECOVERY_LENGTH (7 * 1024 * 1024) # define OF_RECOVERY_ARGS \ From 828fd7941f4605869149afe95206c8e050b1eb0c Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Mon, 2 Feb 2026 20:50:05 +0000 Subject: [PATCH 20/75] x1000: ensure sections are 4-byte aligned The section copy loops in crt0.S rely on sections starting and ending on 4-byte aligned addresses. If the last variable alloacted in the BSS section isn't a multiple of 4 bytes, then _bssend can get misaligned and break the copy loop. This problem was masked by -fcommon since COMMON variables go at the end of the BSS section, and they were for the most part a multiple of 4 bytes. The switch to -fno-common broke the bootloader because with COMMON gone, the last thing in BSS was a 1-byte variable in led.o. The main binary appears to have had the correct alignments by sheer luck. Change-Id: I21ee3653d89d1607a2f458c457f1a51e33c22f05 --- firmware/target/mips/ingenic_x1000/app.lds | 26 +++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/firmware/target/mips/ingenic_x1000/app.lds b/firmware/target/mips/ingenic_x1000/app.lds index a1e84fb9cf..1df0295d63 100644 --- a/firmware/target/mips/ingenic_x1000/app.lds +++ b/firmware/target/mips/ingenic_x1000/app.lds @@ -71,11 +71,11 @@ SECTIONS * The following sections are loaded after normal DRAM sections * but are copied elsewhere by the startup code. */ - _noloaddram = .; + _noloaddram = ALIGN(4); .iram : { - _iramstart = .; + _iramstart = ALIGN(4); . = 0x000; /* TLB refill */ KEEP(*(.vectors.1)); . = 0x100; /* Cache error */ @@ -89,24 +89,24 @@ SECTIONS *(.icode*); *(.irodata); *(.idata); - _iramend = .; + _iramend = ALIGN(4); } > IRAM AT> DRAM _iramcopy = LOADADDR(.iram); .tcsm : { - _tcsmstart = .; + _tcsmstart = ALIGN(4); KEEP(*(.tcsm*)); - _tcsmend = .; + _tcsmend = ALIGN(4); } > TCSM AT> DRAM _tcsmcopy = LOADADDR(.tcsm); #ifdef HAVE_INIT_ATTR .init : { - _initstart = .; + _initstart = ALIGN(4); *(.init*); - _initend = .; + _initend = ALIGN(4); } > INIT AT> DRAM _initcopy = LOADADDR(.init); #endif @@ -117,22 +117,22 @@ SECTIONS .stack (NOLOAD) : { *(.stack); - stackbegin = .; + stackbegin = ALIGN(4); . += X1000_STACKSIZE; - stackend = .; - _irqstackbegin = .; + stackend = ALIGN(4); + _irqstackbegin = ALIGN(4); . += X1000_IRQSTACKSIZE; - _irqstackend = .; + _irqstackend = ALIGN(4); } > IRAM .bss _noloaddram (NOLOAD) : { - _bssbegin = .; + _bssbegin = ALIGN(4); *(.sbss*); *(.bss*); *(COMMON); *(.scommon*); - _bssend = .; + _bssend = ALIGN(4); _end = .; } > DRAM From 34525a18dc348f36d581f8a10ef06cbfdd9b85a7 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Mon, 2 Feb 2026 21:07:48 +0000 Subject: [PATCH 21/75] plugins: drop audio_hard_stop() from plugin API Commit 01f96e40a7 ("mpegplayer: remove IRAM save/restore hack") removed the only user. Change-Id: Ia6281159387ab984906443f047b849614d92ef9e --- apps/plugin.c | 3 --- apps/plugin.h | 5 +---- docs/PLUGIN_API | 5 ----- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index 5b2bae91b4..fd886ea93f 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -758,9 +758,6 @@ static const struct plugin_api rockbox_api = { audio_current_track, audio_flush_and_reload_tracks, audio_get_file_pos, -#ifdef PLUGIN_USE_IRAM - audio_hard_stop, -#endif add_playbacklog, /* menu */ diff --git a/apps/plugin.h b/apps/plugin.h index 20190846c5..bc700cbbc1 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -178,7 +178,7 @@ int plugin_open(const char *plugin, const char *parameter); * when this happens please take the opportunity to sort in * any new functions "waiting" at the end of the list. */ -#define PLUGIN_API_VERSION 277 +#define PLUGIN_API_VERSION 278 /* 239 Marks the removal of ARCHOS HWCODEC and CHARCELL */ @@ -889,9 +889,6 @@ struct plugin_api { struct mp3entry* (*audio_current_track)(void); void (*audio_flush_and_reload_tracks)(void); int (*audio_get_file_pos)(void); -#ifdef PLUGIN_USE_IRAM - void (*audio_hard_stop)(void); -#endif void (*add_playbacklog)(struct mp3entry *id3); /* menu */ diff --git a/docs/PLUGIN_API b/docs/PLUGIN_API index f8bf383896..337a2c6752 100644 --- a/docs/PLUGIN_API +++ b/docs/PLUGIN_API @@ -107,11 +107,6 @@ int audio_get_file_pos(void) \return \description -void audio_hard_stop(void) - \group playback control - \conditions (defined(PLUGIN_USE_IRAM)) - \description - void audio_next(void) \group playback control \description From 2429e117d0f1722adf704b5f83e6ddbfed016d1f Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 1 Feb 2026 13:21:20 +0000 Subject: [PATCH 22/75] Replace all uses of PLUGIN_USE_IRAM with USE_IRAM PLUGIN_USE_IRAM is almost equivalent to USE_IRAM except that USE_IRAM might be defined in core, but not plugins. All remaining uses of PLUGIN_USE_IRAM are inside plugins, however, so there is no point keeping both defines around. Change-Id: I6902c85651f3d82b7d19ea32eaa60fc5c19eded7 --- apps/plugins/pacbox/pacbox.c | 2 +- apps/plugins/pitch_detector.c | 4 ++-- apps/plugins/plugin_crt0.c | 4 ++-- apps/plugins/test_mem.c | 4 ++-- firmware/export/config.h | 2 -- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c index a7f662a823..c5e9e9c22e 100755 --- a/apps/plugins/pacbox/pacbox.c +++ b/apps/plugins/pacbox/pacbox.c @@ -387,7 +387,7 @@ static void start_sound(void) if (sound_playing) return; -#ifndef PLUGIN_USE_IRAM +#ifndef USE_IRAM /* Ensure control of PCM - stopping music itn't obligatory */ rb->plugin_get_audio_buffer(NULL); #endif diff --git a/apps/plugins/pitch_detector.c b/apps/plugins/pitch_detector.c index 9840aab325..9bed3ff754 100644 --- a/apps/plugins/pitch_detector.c +++ b/apps/plugins/pitch_detector.c @@ -248,7 +248,7 @@ static volatile int audio_tail = 0; /* which of the two buffers to record? */ #ifndef SIMULATOR static int16_t audio_data[2][BUFFER_SIZE] MEM_ALIGN_ATTR; static fixed yin_buffer[YIN_BUFFER_SIZE] IBSS_ATTR; -#ifdef PLUGIN_USE_IRAM +#ifdef USE_IRAM static int16_t iram_audio_data[BUFFER_SIZE] IBSS_ATTR; #else #define iram_audio_data audio_data[audio_head] @@ -1047,7 +1047,7 @@ static void record_and_get_pitch(void) #ifdef HAVE_SCHEDULER_BOOSTCTRL rb->trigger_cpu_boost(); #endif -#ifdef PLUGIN_USE_IRAM +#ifdef USE_IRAM rb->memcpy(iram_audio_data, audio_data[audio_head], settings.sample_size * sizeof (int16_t)); #endif diff --git a/apps/plugins/plugin_crt0.c b/apps/plugins/plugin_crt0.c index 934f4e9338..4358f65aa9 100644 --- a/apps/plugins/plugin_crt0.c +++ b/apps/plugins/plugin_crt0.c @@ -74,7 +74,7 @@ enum plugin_status plugin__start(const void *param) #if (CONFIG_PLATFORM & PLATFORM_NATIVE) /* IRAM must be copied before clearing the BSS ! */ -#ifdef PLUGIN_USE_IRAM +#ifdef USE_IRAM extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; size_t iram_size = iramend - iramstart; size_t ibss_size = iend - iedata; @@ -92,7 +92,7 @@ enum plugin_status plugin__start(const void *param) */ asm volatile ("" ::: "memory"); } -#endif /* PLUGIN_USE_IRAM */ +#endif /* USE_IRAM */ /* zero out the bss section */ rb->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); diff --git a/apps/plugins/test_mem.c b/apps/plugins/test_mem.c index 3e5b8283b0..e7eb08608f 100644 --- a/apps/plugins/test_mem.c +++ b/apps/plugins/test_mem.c @@ -36,7 +36,7 @@ static int loop_repeat_dram = LOOP_REPEAT_DRAM; static volatile int buf_dram[BUF_SIZE] MEM_ALIGN_ATTR; -#if defined(PLUGIN_USE_IRAM) +#if defined(USE_IRAM) #if PLUGIN_BUFFER_SIZE <= 0x8000 #define IBUF_SIZE (1<<12) /* 16 KB = (1<<12)*sizeof(int) */ @@ -231,7 +231,7 @@ enum plugin_status plugin_start(const void* parameter) ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, MEMSET); ret |= test(buf_dram, BUF_SIZE, loop_repeat_dram, MEMCPY); if (ret != 0 && loop_repeat_dram < MAX_REPEAT_DRAM) loop_repeat_dram *= 2; -#if defined(PLUGIN_USE_IRAM) +#if defined(USE_IRAM) TEST_MEM_PRINTF("IRAM cnt: %d size: %d MB", loop_repeat_iram, (loop_repeat_iram*BUF_SIZE*sizeof(buf_iram[0]))>>20); ret = 0; diff --git a/firmware/export/config.h b/firmware/export/config.h index cf79b84fe2..040709af3f 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -1187,12 +1187,10 @@ Lyre prototype 1 */ (CONFIG_CPU == PNX0101) || \ (CONFIG_CPU == TCC7801) # define USE_IRAM -# define PLUGIN_USE_IRAM /* AS3525 +2MB: core, plugins, codecs */ #elif (CONFIG_CPU == AS3525) && (MEMORYSIZE > 2) && !defined(BOOTLOADER) # define USE_IRAM -# define PLUGIN_USE_IRAM /* AS3525 2MB: core only */ #elif (CONFIG_CPU == AS3525) && (MEMORYSIZE <= 2) && !defined(BOOTLOADER) && \ From 78542df46668101f03e940b9fdc030c2aa1cae84 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 3 Feb 2026 10:31:00 +0000 Subject: [PATCH 23/75] Nuke GDB stub It looks like the GDB stub only ever worked for the Archos Recorder and iRiver IFP-7xx, neither of which are in-tree any more. Change-Id: If1910675b88b4707d26df9bc095818902af2d25b --- apps/plugins/plugin.lds | 37 +- firmware/SOURCES | 4 - firmware/target/arm/tcc780x/crt0.S | 3 - firmware/target/mips/ingenic_jz47xx/app.lds | 8 +- gdb/Makefile | 64 -- gdb/README | 95 --- gdb/SOURCES | 3 - gdb/arm-stub.c | 716 -------------------- gdb/linker.cfg | 95 --- gdb/setjmp.S | 61 -- 10 files changed, 15 insertions(+), 1071 deletions(-) delete mode 100644 gdb/Makefile delete mode 100644 gdb/README delete mode 100644 gdb/SOURCES delete mode 100644 gdb/arm-stub.c delete mode 100644 gdb/linker.cfg delete mode 100644 gdb/setjmp.S diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index b0fd8d6d28..f55f6fee6f 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -13,12 +13,6 @@ OUTPUT_FORMAT(elf32-littlemips) #error Unknown CPU architecture #endif -#ifdef DEBUG -#define STUBOFFSET 0x10000 -#else -#define STUBOFFSET 0 -#endif - #if defined(CPU_PP) #ifdef CPU_PP502x #define NOCACHE_BASE 0x10000000 @@ -31,7 +25,7 @@ OUTPUT_FORMAT(elf32-littlemips) #if CONFIG_CPU==IMX31L /* No fudges! */ #include "imx31l.h" -#define DRAMSIZE ((MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE \ +#define DRAMSIZE ((MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE \ - CODEC_SIZE - QHARRAY_SIZE - FRAME_SIZE - TTB_SIZE) #elif CONFIG_CPU==DM320 @@ -56,25 +50,25 @@ OUTPUT_FORMAT(elf32-littlemips) #define LCD_TTB_AREA (TTB_SIZE + LCD_BUFFER_SIZE) #endif -#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_TTB_AREA +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_TTB_AREA #elif CONFIG_CPU==S3C2440 #include "cpu.h" /* must be 16Kb (0x4000) aligned */ #define TTB_SIZE (0x4000) -#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_BUFFER_SIZE - TTB_SIZE +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - CODEC_SIZE - LCD_BUFFER_SIZE - TTB_SIZE #elif CONFIG_CPU==TCC7801 #include "cpu.h" -#define DRAMSIZE (MEMORYSIZE * 0x100000) - STUBOFFSET - PLUGIN_BUFFER_SIZE - CODEC_SIZE - TTB_SIZE +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - CODEC_SIZE - TTB_SIZE #elif CONFIG_CPU==AS3525 || CONFIG_CPU==AS3525v2 #include "cpu.h" #define DRAMORIG DRAM_ORIG #if defined(AMS_LOWMEM) || (CONFIG_CPU == AS3525v2) -#define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - STUBOFFSET - TTB_SIZE) +#define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - TTB_SIZE) #else -#define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE - TTB_SIZE) +#define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE - TTB_SIZE) #endif #elif CONFIG_CPU==S5L8702 || CONFIG_CPU==S5L8720 #define ASM @@ -85,13 +79,12 @@ OUTPUT_FORMAT(elf32-littlemips) #define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE - FRAME_SIZE - TTB_SIZE) #elif CONFIG_CPU==X1000 #include "cpu.h" -#undef STUBOFFSET #define DRAMSIZE (X1000_DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE) #endif /* default to full RAM (minus codecs&plugins) unless specified otherwise */ #ifndef DRAMSIZE -#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - STUBOFFSET - CODEC_SIZE +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - CODEC_SIZE #endif /* MCF5249 have 96KB of IRAM */ @@ -119,17 +112,17 @@ OUTPUT_FORMAT(elf32-littlemips) #define IRAMSIZE 0x0c000 #elif CONFIG_CPU == PNX0101 -#define DRAMORIG 0xc00000 + STUBOFFSET +#define DRAMORIG 0xc00000 #define IRAMORIG 0x407000 #define IRAMSIZE 0x9000 #elif CONFIG_CPU == IMX31L || CONFIG_CPU == S3C2440 -#define DRAMORIG 0x0 + STUBOFFSET +#define DRAMORIG 0x0 #define IRAM DRAM #define IRAMSIZE 0 #elif CONFIG_CPU==DM320 -#define DRAMORIG CONFIG_SDRAM_START + STUBOFFSET +#define DRAMORIG CONFIG_SDRAM_START #define IRAM DRAM /* The bit of IRAM that is available is used in the core */ #define IRAMSIZE 0 @@ -181,13 +174,7 @@ OUTPUT_FORMAT(elf32-littlemips) #define IRAMSIZE (136*1024) #elif CONFIG_CPU == JZ4732 || CONFIG_CPU == JZ4760B -#undef STUBOFFSET -#ifdef DEBUG -#define STUBOFFSET 0x14000 -#else -#define STUBOFFSET 0x4000 -#endif -#define DRAMORIG 0x80000000 + STUBOFFSET +#define DRAMORIG 0x80004000 #define IRAM DRAM #define IRAMSIZE 0 /* The bit of IRAM that is available is used in the core */ @@ -210,7 +197,7 @@ OUTPUT_FORMAT(elf32-littlemips) #define IRAMSIZE 0 #else -#define DRAMORIG 0x09000000 + STUBOFFSET +#define DRAMORIG 0x09000000 #endif #ifndef NOCACHE_BASE diff --git a/firmware/SOURCES b/firmware/SOURCES index d62b8d254c..ef558a8009 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1178,10 +1178,6 @@ target/coldfire/iaudio/audio-iaudio.c #endif #endif /* IAUDIO_M3 */ -#ifdef STUB -libc/sscanf.c -#endif /* STUB */ - #if defined(IRIVER_H300_SERIES) || defined(IRIVER_H100_SERIES) target/coldfire/iriver/ata-iriver.c target/coldfire/iriver/lcd-remote-iriver.c diff --git a/firmware/target/arm/tcc780x/crt0.S b/firmware/target/arm/tcc780x/crt0.S index 5d271616d0..bbdbf96f17 100644 --- a/firmware/target/arm/tcc780x/crt0.S +++ b/firmware/target/arm/tcc780x/crt0.S @@ -179,8 +179,6 @@ copied_start: mcr p15, 0, r0, c7, c6, 0 /* Invalidate Dcache */ mcr p15, 0, r1, c8, c7, 0 /* Invalidate TLB */ -#ifndef STUB - /* Copy exception handler code to address 0 */ mov r2, #0x0 ldr r3, =vectors_start @@ -231,7 +229,6 @@ copied_start: strhi r5, [r3], #4 bhi 1b #endif /* !BOOTLOADER */ -#endif /* !STUB */ /* Initialise bss section to zero */ ldr r2, =_edata diff --git a/firmware/target/mips/ingenic_jz47xx/app.lds b/firmware/target/mips/ingenic_jz47xx/app.lds index 29a973a0ca..701c9b4b58 100644 --- a/firmware/target/mips/ingenic_jz47xx/app.lds +++ b/firmware/target/mips/ingenic_jz47xx/app.lds @@ -9,12 +9,10 @@ STARTUP(target/mips/ingenic_jz47xx/crt0.o) INPUT(target/mips/exception-mips.o) INPUT(target/mips/system-mips.o) -#define STUBOFFSET 0x4000 - -#define DRAMORIG (0x80000000 + STUBOFFSET) -#define DRAMSIZE (MEMORYSIZE * 0x100000 - STUBOFFSET) #define IRAMORIG 0x80000000 -#define IRAMSIZE 16K +#define IRAMSIZE 0x4000 +#define DRAMORIG (IRAMORIG + IRAMSIZE) +#define DRAMSIZE (MEMORYSIZE * 0x100000 - IRAMSIZE) /* End of the audio buffer, where the codec buffer starts */ #define ENDAUDIOADDR (DRAMORIG + DRAMSIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE) diff --git a/gdb/Makefile b/gdb/Makefile deleted file mode 100644 index 0a52e8b5b0..0000000000 --- a/gdb/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# __________ __ ___. -# Open \______ \ ____ ____ | | _\_ |__ _______ ___ -# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -# \/ \/ \/ \/ \/ -# $Id$ -# - -ifeq ($(MODELNAME),EXAMPLE) - -INCLUDES= -I$(FIRMDIR)/include -I$(FIRMDIR)/export -I. -I$(OBJDIR) \ - -I$(BUILDDIR) - -DEPFILE = $(OBJDIR)/dep-stub -LDS := linker.cfg - -SRC := $(shell cat SOURCES | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P -include "config.h" - ) -DIRS = . - -ifdef APPEXTRA - DIRS += $(subst :, ,$(APPEXTRA)) - INCLUDES += $(patsubst %,-I%,$(subst :, ,$(APPEXTRA))) -endif - -ifndef VERSION -VERSION=$(shell date +%y%m%d-%H%M) -endif - -CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(DEFINES) \ - $(EXTRA_DEFINES) -DMEM=${MEMORYSIZE} - -OBJS := $(SRC:%.c=$(OBJDIR)/%.o) -SOURCES = $(SRC) -LINKFILE = $(OBJDIR)/linkage.lds - -LIBROCKBOX = $(BUILDDIR)/librockbox.a - -all: $(BUILDDIR)/$(BINARY) $(FLASHFILE) - -dep: $(DEPFILE) - -$(LINKFILE): $(LDS) - $(call PRINTS,Build $(@F))cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P $(ROMBUILD) - >$@ - -$(OBJDIR)/stub.elf : $(OBJS) $(LINKFILE) $(DEPFILE) $(LIBROCKBOX) - $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -L$(BUILDDIR)/firmware -lrockbox -lgcc -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/stub.map - -$(OBJDIR)/stub.bin : $(OBJDIR)/stub.elf - $(call PRINTS,OBJCOPY $(@F))$(OC) -O binary $< $@ - -$(BUILDDIR)/$(BINARY) : $(OBJDIR)/stub.bin - $(call PRINTS,Build stub file)$(MKFIRMWARE) $< $@ - -include $(TOOLSDIR)/make.inc - -clean: - $(call PRINTS,cleaning stub)-rm -f $(OBJS) $(BUILDDIR)/$(BINARY) \ - $(OBJDIR)/stub.bin $(OBJDIR)/stub.elf $(OBJDIR)/*.map \ - $(LINKFILE) $(DEPFILE) - --include $(DEPFILE) - -endif diff --git a/gdb/README b/gdb/README deleted file mode 100644 index e61c930ea8..0000000000 --- a/gdb/README +++ /dev/null @@ -1,95 +0,0 @@ --------------------------------------------------------------------- - __________ __ ___. - Open \______ \ ____ ____ | | _\_ |__ _______ ___ - Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - \/ \/ \/ \/ \/ - $Id$ - - Copyright (C) 2002 by Linus Nielsen Feltzing - --------------------------------------------------------------------- - -Debugging the Archos Jukebox ----------------------------- - -To debug using the serial port on the Jukebox, you need to do the following: - -1) Connect the serial port to the PC. This is best done with the "serial - port mod" described on the home page, along with a serial port converter - for the 3V signals from the Jukebox. - -2) Build or download a GDB SH1 cross debugger - -3) Compile the GDB stub from the CVS "gdb" archive - For Player models, just type: - # make - - For Recorder, type - #make RECORDER=1 - -4) Copy the newly built ARCHOS.MOD to the Jukebox. - -5) Start the Jukebox and fire up the GDB with the elf file you want to debug - as an argument along with the baud rate: - - For Player: - # sh-elf-gdb -b 38400 test.elf - - For Recorder: - # sh-elf-gdb -b 115200 test.elf - -6) In GDB, type: - - (gdb) target remote /dev/ttyS0 - - /dev/ttyS0 is the serial port you want to use. I guess Windows users - would type COM1 or something like that. - - GDB should answer with a message like: - - Remote debugging using /dev/ttyS0 - 0x090014b6 in ?? () - (gdb) - -7) Load the code from the elf file you specified on the command line: - - (gdb) load - - GDB should answer like this: - - Loading section .text, size 0x6b00 lma 0x9018000 - Loading section .data, size 0x738 lma 0x901eb00 - Start address 0x9018290, load size 29240 - Transfer rate: 11696 bits/sec, 102 bytes/write. - (gdb) - -8) You're set. Now try to set a breakpoint and run: - - (gdb) b main - Breakpoint 1 at 0x9011b2a: file main.c, line 192. - (gdb) c - Continuing. - - Breakpoint 1, main () at main.c:192 - 192 app_main(); - (gdb) - - Good luck! - - -Technical details: - - As for now, the GDB stub occupies the memory from 0x900000 up to - 0x9018000. - - Compile and link your test program at 0x9018000 and up, and it will work. - - The baud rate is 38400 for Player, 115200 for Recorder, and the settings - are 8N1. - - Note that you may have to change the ATA I/O address in the ATA_CONTROL - macro in sh-stub.c. go to Menu->Debug (keep out)->View HW info to find out. - - Linus Nielsen Feltzing diff --git a/gdb/SOURCES b/gdb/SOURCES deleted file mode 100644 index 9668d12dc8..0000000000 --- a/gdb/SOURCES +++ /dev/null @@ -1,3 +0,0 @@ -#ifdef CPU_ARM -arm-stub.c -#endif diff --git a/gdb/arm-stub.c b/gdb/arm-stub.c deleted file mode 100644 index 3a6076ebfe..0000000000 --- a/gdb/arm-stub.c +++ /dev/null @@ -1,716 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Tomasz Malesinski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include "sscanf.h" -#include "gdb_api.h" - -#define BUFMAX 1024 - -#define VEC_UND 1 -#define VEC_SWI 2 -#define VEC_PABT 3 -#define VEC_DABT 4 - -static char packet_buf[BUFMAX]; -static char reply_buf[BUFMAX]; - -static const char hexchars[] = "0123456789abcdef"; -static int gdb_exception_no, gdb_mem_access; -static unsigned char watchdog_enabled; -static unsigned long registers[17]; - -void gdb_api_breakpoint(void); -static void gdb_api_log(char *msg); - -__attribute__((section(".gdbapi"))) struct gdb_api gdb_api = -{ - GDB_API_MAGIC, - {gdb_api_breakpoint, gdb_api_log} -}; - -static void watchdog_enable(int on) -{ - (*(volatile unsigned long *)0x80002804) = on; - watchdog_enabled = on; -} - -static void watchdog_service(void) -{ - if (watchdog_enabled) - { - (*(volatile unsigned long *)0x80002804) = 0; - (*(volatile unsigned long *)0x80002808) = 0; - (*(volatile unsigned long *)0x80002804) = 1; - } -} - -static inline bool isxdigit(char c) -{ - return ((c >= '0') && (c <= '9')) - || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')); -} - -static int hex(char ch) { - if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - if ((ch >= 'A') && (ch <= 'F')) - return ch - 'A' + 10; - return -1; -} - -static void hex_byte(char *s, int byte) { - s[0] = hexchars[(byte >> 4) & 0xf]; - s[1] = hexchars[byte & 0xf]; -} - -static void hex_word(char *s, unsigned long val) { - int i; - for (i = 0; i < 4; i++) - hex_byte(s + i * 2, (val >> (i * 8)) & 0xff); -} - -static void hex_string(char *d, char *s) { - while (*s) { - hex_byte(d, *s++); - d += 2; - } - *d = 0; -} - -static int get_hex_byte(char *s) { - return (hex(s[0]) << 4) + hex(s[1]); -} - -static unsigned long get_hex_word(char *s) { - int i; - unsigned long r = 0; - for (i = 3; i >= 0; i--) - r = (r << 8) + get_hex_byte(s + i * 2); - return r; -} - -static void reply_error(int n, char *reply) { - reply[0] = 'E'; - hex_byte(reply + 1, n); - reply[3] = 0; -} - -static void reply_signal(int n, char *reply) { - int signal; - reply[0] = 'S'; - switch (n) - { - case VEC_UND: - signal = 4; - break; - case VEC_PABT: - case VEC_DABT: - signal = 7; - break; - default: - signal = 5; - break; - } - hex_byte(reply + 1, signal); - reply[3] = 0; -} - -static void reply_ok(char *reply) { - strcpy(reply, "OK"); -} - -static int get_byte(void) { - int b; - while ((b = usb_serial_try_get_byte()) < 0) - watchdog_service(); - watchdog_service(); - return b; -} - -static void put_byte(unsigned char ch) { - while (usb_serial_try_put_byte(ch) < 0) - watchdog_service(); - watchdog_service(); -} - -static void serial_write(unsigned char *buf, int len) { - int i; - for (i = 0; i < len; i++) - put_byte(buf[i]); -} - -static void get_packet(char *buf, int len) { - int count, checksum, escaped; - int ch; - - while (1) { - do { - ch = get_byte(); - } while (ch != '$'); - - checksum = 0; - count = 0; - escaped = 0; - while (count < len) { - ch = get_byte(); - if (!escaped) { - if (ch == '$') { - checksum = 0; - count = 0; - } else if (ch == '#') - break; - else if (ch == 0x7d) { - escaped = 1; - checksum += ch; - } else { - checksum += ch; - buf[count] = ch; - count++; - } - } else { - escaped = 0; - checksum += ch; - buf[count] = ch ^ 0x20; - count++; - } - } - buf[count] = 0; - - if (ch == '#') { - int rchksum; - - ch = get_byte(); - rchksum = hex(ch) << 4; - ch = get_byte(); - rchksum += hex(ch); - - if ((checksum & 0xff) != rchksum) - put_byte('-'); - else { - put_byte('+'); - return; - } - } - } -} - -static void put_packet(char *buf) { - int i, checksum; - int ch; - char tmp[3]; - - do { - put_byte('$'); - - checksum = 0; - for (i = 0; buf[i]; i++) - checksum += buf[i]; - - serial_write(buf, i); - - tmp[0] = '#'; - hex_byte(tmp + 1, checksum & 0xff); - serial_write(tmp, 3); - - ch = get_byte(); - - } while (ch != '+'); -} - -static inline unsigned long get_general_reg(int n) -{ - return registers[n + 1]; -} - -static inline void set_general_reg(int n, unsigned long v) -{ - registers[n + 1] = v; -} - -static inline unsigned long get_cpsr(void) -{ - return registers[0]; -} - -static inline void set_cpsr(unsigned long v) -{ - registers[0] = v; -} - -static void g_reply(char *buf) { - int i; - char *p; - - p = buf; - for (i = 0; i < 16; i++) { - hex_word(p, get_general_reg(i)); - p += 8; - } - - for (i = 0; i < 8; i++) { - memset(p, '0', 16); - p += 16; - } - - hex_word(p, 0); - p += 8; - hex_word(p, get_cpsr()); - p[8] = 0; -} - -static void cmd_get_register(char *args, char *reply) { - int r; - - if (sscanf(args, "%x", &r) != 1) { - reply_error(0, reply); - return; - } - - if (r >= 0 && r < 16) { - hex_word(reply, get_general_reg(r)); - reply[8] = 0; - } else if (r == 25) { - hex_word(reply, get_cpsr()); - reply[8] = 0; - } else { - hex_word(reply, 0); - reply[8] = 0; - } -} - -static void cmd_set_register(char *args, char *reply) { - int r, p; - unsigned long v; - - p = -1; - sscanf(args, "%x=%n", &r, &p); - if (p == -1) { - reply_error(0, reply); - return; - } - - v = get_hex_word(args + p); - if (r >= 0 && r < 16) - set_general_reg(r, v); - else if (r == 25) - set_cpsr(v); - reply_ok(reply); -} - -static void cmd_set_registers(char *args, char *reply) { - char *p; - int i, len; - - len = strlen(args); - - p = args; - for (i = 0; i < 16 && len >= (i + 1) * 8; i++) { - set_general_reg(i, get_hex_word(p)); - p += 8; - } - - if (len >= 16 * 8 + 8 * 16 + 2 * 8) - { - p += 8 * 16 + 8; - set_cpsr(get_hex_word(p)); - } - - reply_ok(reply); -} - -static void cmd_get_memory(char *args, char *reply) { - unsigned long addr, len, i; - - if (sscanf(args, "%lx,%lx", &addr, &len) != 2) { - reply_error(0, reply); - return; - } - - if (len > (BUFMAX - 16) / 2) { - reply_error(1, reply); - return; - } - - gdb_mem_access = 1; - for (i = 0; i < len; i++) - hex_byte(reply + i * 2, *((unsigned char *)(addr + i))); - gdb_mem_access = 0; - - reply[len * 2] = 0; -} - -static void cmd_put_memory(char *args, char *reply) { - unsigned long addr, len, i; - int pos; - - pos = -1; - sscanf(args, "%lx,%lx:%n", &addr, &len, &pos); - if (pos == -1) { - reply_error(0, reply); - return; - } - - gdb_mem_access = 1; - for (i = 0; i < len; i++) - *((unsigned char *)(addr + i)) = get_hex_byte(args + pos + i * 2); - gdb_mem_access = 0; - - reply_ok(reply); -} - -static void cmd_put_memory_binary(char *args, char *reply) { - unsigned long addr, len, i; - int pos; - - pos = -1; - sscanf(args, "%lx,%lx:%n", &addr, &len, &pos); - if (pos == -1) { - reply_error(0, reply); - return; - } - - gdb_mem_access = 1; - for (i = 0; i < len; i++) - *((unsigned char *)(addr + i)) = args[pos + i]; - gdb_mem_access = 0; - - reply_ok(reply); -} - -static void parse_continue_args(char *args) { - int sig; - unsigned long addr; - - if (sscanf(args, "%x;%lx", &sig, &addr) == 2) { - set_general_reg(15, addr); - } else if (sscanf(args, "%lx", &addr) == 1) { - set_general_reg(15, addr); - } -} - -static void cmd_go(char *args) { - parse_continue_args(args); - - asm volatile( - " mov r1, %0\n" - " ldr r12, [r1], #4\n" - " mov r0, r12\n" - " and r0, r0, #0x1f\n" - " cmp r0, #0x10\n" - " bne 1f\n" - " ldr r14, [r1, #60]\n" - " msr spsr_fsxc, r12\n" - " ldmia r1, {r0-r14}^\n" - " movs r15, r14\n" - "1:\n" - " msr cpsr_fsxc, r12\n" - " ldmia r1, {r0-r15}\n" - : : "r" (registers)); -} - -static void remote_cmd(char *cmd, char *reply) { - int i, err; - i = 0; - err = 0; - while ((cmd[i] >= 'a' && cmd[i] <= 'z') || cmd[i] == '_') - i++; - if (!strncmp(cmd, "reboot", i)) - { - reply_ok(reply); - put_packet(reply); - watchdog_enable(1); - (*(volatile unsigned long *)0x80002804) = 1; - while (1); - } - else if (!strncmp(cmd, "power_off", i)) - { - reply_ok(reply); - put_packet(reply); - GPIO1_CLR = 1 << 16; - GPIO2_SET = 1; - while (1); - } - else if (!strncmp(cmd, "watchdog", i)) - { - int t; - if (sscanf(cmd + i, "%d", &t) == 1) - watchdog_enable(t != 0); - else - err = 1; - reply_ok(reply); - } - else - hex_string(reply, "Unrecognized command\n"); - if (err) - reply_error(err, reply); -} - -static void cmd_query(char *args, char *reply) { - if (!strncmp(args, "Rcmd,", 5)) { - unsigned i = 0; - char *s = args + 5; - char cmd[200]; - while (isxdigit(s[0]) && isxdigit(s[1]) && i < sizeof(cmd) - 1) { - cmd[i++] = get_hex_byte(s); - s += 2; - } - cmd[i] = 0; - remote_cmd(cmd, reply); - } else - reply[0] = 0; -} - -void gdb_loop(void) { - int no_reply; - - gdb_mem_access = 0; - - while (1) { - get_packet(packet_buf, sizeof(packet_buf) - 1); - - no_reply = 0; - switch (packet_buf[0]) { - case '?': - reply_signal(gdb_exception_no, reply_buf); - break; - - case 'p': - cmd_get_register(packet_buf + 1, reply_buf); - break; - - case 'P': - cmd_set_register(packet_buf + 1, reply_buf); - break; - - case 'g': - g_reply(reply_buf); - break; - - case 'G': - cmd_set_registers(packet_buf + 1, reply_buf); - break; - - case 'm': - cmd_get_memory(packet_buf + 1, reply_buf); - break; - - case 'M': - cmd_put_memory(packet_buf + 1, reply_buf); - break; - - case 'X': - cmd_put_memory_binary(packet_buf + 1, reply_buf); - break; - - case 'q': - cmd_query(packet_buf + 1, reply_buf); - break; - - case 'c': - cmd_go(packet_buf + 1); - reply_error(1, reply_buf); - break; - -/* case 's': */ -/* cmd_go(packet_buf + 1); */ -/* break; */ - - default: - reply_buf[0] = 0; - } - - if (!no_reply) - put_packet(reply_buf); - } -} - -extern void *vectors[]; - -static void gdb_set_vector(int n, void *p) -{ - vectors[n] = p; -} - -void gdb_und_exc(void); -void gdb_swi_exc(void); -void gdb_pabt_exc(void); -void gdb_dabt_exc(void); - -static void gdb_set_vectors(void) -{ - gdb_set_vector(VEC_UND, gdb_und_exc); - gdb_set_vector(VEC_SWI, gdb_swi_exc); - gdb_set_vector(VEC_PABT, gdb_pabt_exc); - gdb_set_vector(VEC_DABT, gdb_dabt_exc); -} - -void gdb_loop_from_exc(void) -{ - if (gdb_mem_access) - reply_error(1, reply_buf); - else - reply_signal(gdb_exception_no, reply_buf); - put_packet(reply_buf); - gdb_loop(); -} - -#define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg))) - -static inline unsigned long irq_read(int reg) -{ - unsigned long v, v2; - do - { - v = IRQ_REG(reg); - v2 = IRQ_REG(reg); - } while (v != v2); - return v; -} - -#define IRQ_WRITE_WAIT(reg, val, cond) \ - do { unsigned long v, v2; \ - do { \ - IRQ_REG(reg) = (val); \ - v = IRQ_REG(reg); \ - v2 = IRQ_REG(reg); \ - } while ((v != v2) || !(cond)); \ - } while (0); - -void fiq(void) -{ -} - -static void system_init(void) -{ - int i; - - watchdog_enable(0); - - for (i = 0; i < 0x1c; i++) - { - IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1); - IRQ_WRITE_WAIT(0x404 + i * 4, 0x4000000, (v & 0x10000) == 0); - IRQ_WRITE_WAIT(0x404 + i * 4, 0x10000001, (v & 0xf) == 1); - } - - GPIO3_CLR = 1; -} - -static void gdb_api_log(char *msg) -{ - int i; - - reply_buf[0] = 'O'; - i = 1; - while (*msg && i + 2 <= BUFMAX - 1) - { - hex_byte(reply_buf + i, *msg++); - i += 2; - } - reply_buf[i] = 0; - put_packet(reply_buf); -} - -void main(void) -{ - system_init(); - usb_serial_init(); - gdb_mem_access = 0; - gdb_set_vectors(); - gdb_api_breakpoint(); - while (1); -} - -#define str(s) #s -#define xstr(s) str(s) - -asm (".text\n" - "gdb_und_exc:\n" - " ldr sp, =_stub_stack\n" - " sub r14, r14, #4\n" - " stmfd sp!, {r0-r3, r12, r14}\n" - " mov r0, #" xstr(VEC_UND) "\n" - " b gdb_handle_exception\n" - "gdb_swi_exc:\n" - " ldr sp, =_stub_stack\n" - " stmfd sp!, {r0-r3, r12, r14}\n" - " mov r0, #" xstr(VEC_SWI) "\n" - " b gdb_handle_exception\n" - "gdb_pabt_exc:\n" - " ldr sp, =_stub_stack\n" - " stmfd sp!, {r0-r3, r12, r14}\n" - " mov r0, #" xstr(VEC_PABT) "\n" - " b gdb_handle_exception\n" - "gdb_dabt_exc:\n" - " ldr sp, =_stub_stack\n" - " sub r14, r14, #4\n" - " stmfd sp!, {r0-r3, r12, r14}\n" - " ldr r0, =gdb_mem_access\n" - " ldr r0, [r0]\n" - " tst r0, r0\n" - " bne gdb_data_abort\n" - " mov r0, #" xstr(VEC_DABT) "\n" - " b gdb_handle_exception\n" - "gdb_handle_exception:\n" - " ldr r1, =gdb_exception_no\n" - " str r0, [r1]\n" - " ldr r0, =registers\n" - " mrs r12, spsr\n" - " str r12, [r0], #4\n" - " ldmfd sp!, {r2, r3}\n" - " stmia r0!, {r2, r3}\n" - " ldmfd sp!, {r2, r3, r12, r14}\n" - " str r14, [r0, #52]\n" - " stmia r0!, {r2-r12}\n" - " mrs r1, spsr\n" - " and r2, r1, #0x1f\n" - " cmp r2, #0x10\n" - " bne 1f\n" - " stmia r0, {r13, r14}^\n" - " b gdb_data_abort\n" - "1:\n" - " msr cpsr_c, r1\n" - " stmia r0, {r13, r14}\n" - "gdb_data_abort:\n" - " msr cpsr_c, #0xd3\n" - " ldr sp, =_stub_stack\n" - " b gdb_loop_from_exc\n" - "gdb_api_breakpoint:\n" - " stmfd sp!, {r0-r1}\n" - " ldr r0, =registers\n" - " mrs r1, cpsr\n" - " str r1, [r0], #4\n" - " ldmfd sp!, {r1}\n" - " str r1, [r0], #4\n" - " ldmfd sp!, {r1}\n" - " str r1, [r0], #4\n" - " stmia r0!, {r2-r14}\n" - " str r14, [r0]\n" - " msr cpsr_c, #0xd3\n" - " ldr sp, =_stub_stack\n" - " ldr r0, =gdb_exception_no\n" - " mov r1, #5\n" - " str r1, [r0]\n" - " b gdb_loop_from_exc\n"); diff --git a/gdb/linker.cfg b/gdb/linker.cfg deleted file mode 100644 index 053323b9d4..0000000000 --- a/gdb/linker.cfg +++ /dev/null @@ -1,95 +0,0 @@ -#include "config.h" - -#ifdef CPU_ARM -ENTRY(start) -STARTUP(crt0.o) -OUTPUT_FORMAT(elf32-littlearm) -#else -#error "Unsupported CPU!" -#endif - -#ifdef EXAMPLE -MEMORY -{ - IRAM : ORIGIN = 0, LENGTH = 0x10000 - DRAM : ORIGIN = 0xc00000, LENGTH = 0x6000 - DRAM_API : ORIGIN = 0xc06000, LENGTH = 0x100 -} - -SECTIONS -{ - .text : - { - *(.init*) - *(.text) - *(.text*) - *(.rodata) - *(.rodata*) - *(.glue_7) - *(.glue_7t) - } >DRAM - - .gdbapi : - { - *(.gdbapi) - } >DRAM_API - - .data : - { - *(.data) - } >DRAM - - .vectors : - { - _vectorsstart = .; - *(.vectors) - _vectorsend = .; - } >IRAM AT>DRAM - _vectorscopy = LOADADDR(.vectors); - - .stack (NOLOAD) : - { - stackbegin = .; - . += 0x400; - _stub_stack = .; - . += 0x200; - stackend = .; - } >DRAM - - .bss (NOLOAD) : - { - _edata = .; - *(.bss) - _end = .; - } >DRAM -} -#else - -SECTIONS -{ - .vectors 0x09000000 : - { - *(.vectors); - . = ALIGN(0x200); - start.o(.text) - *(.rodata) - } - - .text : - { - *(.text) - } - - .bss : - { - _stack = . + 0x1000; - _stub_stack = _stack + 0x1000; - } - - .pad 0x0900C800 : - { - LONG(0); - } -} - -#endif diff --git a/gdb/setjmp.S b/gdb/setjmp.S deleted file mode 100644 index 89ad16f0f9..0000000000 --- a/gdb/setjmp.S +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Red Hat Inc - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - .type _setjmp,@function - .global _setjmp -_setjmp: - add #(9*4),r4 - - sts.l pr,@-r4 - - mov.l r15,@-r4 - mov.l r14,@-r4 - mov.l r13,@-r4 - mov.l r12,@-r4 - - mov.l r11,@-r4 - mov.l r10,@-r4 - mov.l r9,@-r4 - mov.l r8,@-r4 - - rts - mov #0,r0 - - .type _longjmp,@function - .global _longjmp -_longjmp: - mov.l @r4+,r8 - mov.l @r4+,r9 - mov.l @r4+,r10 - mov.l @r4+,r11 - - mov.l @r4+,r12 - mov.l @r4+,r13 - mov.l @r4+,r14 - mov.l @r4+,r15 - - lds.l @r4+,pr - - mov r5,r0 - tst r0,r0 - bf retr4 - movt r0 -retr4: rts - nop From 8baeeda23fb21f136fe65a0aa1f9904b268888a2 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 3 Feb 2026 06:24:22 -0500 Subject: [PATCH 24/75] x1000: Bootloader now probes for the ONFI flash header at multiple addesses The location (and number of pages) is apparently manufacturer-dependent. here are some known so far: Winbond: page 1 gigadevice: page 4 This info is only queried/dumped when explicitly requested for debug purposes. Change-Id: Icc4f9c0d4f2cc9097b2295c8f42a22aab392d0d5 --- bootloader/x1000/utils.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/bootloader/x1000/utils.c b/bootloader/x1000/utils.c index fecf7908d1..5aeb0d8a25 100644 --- a/bootloader/x1000/utils.c +++ b/bootloader/x1000/utils.c @@ -437,15 +437,29 @@ static int dump_flash_onfi_info(int fd) nand_enable_otp(ndrv, true); + int i; + bool is_onfi; + uint8_t* buf = ndrv->page_buf; + /* read ONFI parameter page */ - ret = nand_page_read(ndrv, 0x01, ndrv->page_buf); - if(ret != NAND_SUCCESS) { - splashf(5*HZ, "Dump failed\nNAND read error"); + for (i = 1; i <= 4; i++) { + ret = nand_page_read(ndrv, i, ndrv->page_buf); + if(ret != NAND_SUCCESS) { + splashf(5*HZ, "Dump failed\nNAND read error"); + goto out; + } + + is_onfi = buf[0] == 'O' && buf[1] == 'N' && buf[2] == 'F' && buf[3] == 'I'; + if (is_onfi) + break; + } + + if(!is_onfi) { + fdprintf(fd, "No ONFI Page!"); goto out; } - uint8_t* buf = ndrv->page_buf; - + fdprintf(fd, "ONFI Page = %02x\n", i); fdprintf(fd, "signature = %08lx\n", load_le32(buf)); fdprintf(fd, "revision = %04x\n", load_le16(buf+4)); From 19fe7a4915c9a7b4148d8235f333bc825830f38c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 3 Feb 2026 07:11:51 -0500 Subject: [PATCH 25/75] rbutil: Fix typo in changelog Change-Id: I8f495f37ea4abb6509e0dcdb26ba38ad94096970 --- utils/rbutilqt/changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/rbutilqt/changelog.txt b/utils/rbutilqt/changelog.txt index 0a244f981c..e2eb98cc76 100644 --- a/utils/rbutilqt/changelog.txt +++ b/utils/rbutilqt/changelog.txt @@ -50,7 +50,7 @@ Version 1.5.1 Version 1.5.2 * Add support for Native Port to AIGO Eros Q and various clones -* Mark hosted oort to AIGO Eros Q and various clones "disabled" (can be reenabled by checking the "show disabled targets" checkbox) +* Mark hosted port to AIGO Eros Q and various clones "disabled" (can be reenabled by checking the "show disabled targets" checkbox) * Talk clip generation now respects 'talkclips.ignore' files * Generate additional talk clips for language name and 'invalid voice file' * When installing development builds, fall back to daily artefacts for non-firmware files From 1a33d7990a34e554084f0891823781e416c1ad3b Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 3 Feb 2026 16:16:36 +0000 Subject: [PATCH 26/75] Remove Meizu M3/M6SL/M6SP and Samsung YP-S3 ports These targets haven't seen any changes since 2008-09 have bitrotted to the point they don't compile anymore. With only internal NAND flash for storage which doesn't seem to have ever been accessible from Rockbox, they've never been usable and there's probably not much point keeping them around any more. Change-Id: I2fc63da20682b439126672065ae013044cb2d1c4 --- apps/SOURCES | 4 - apps/keymaps/keymap-meizu-m6sl.c | 299 ----------- apps/keymaps/keymap-meizu-m6sp.c | 76 --- apps/plugins/pictureflow/pictureflow.c | 2 - bootloader/SOURCES | 8 - bootloader/meizu_m3.c | 220 -------- bootloader/meizu_m6sl.c | 153 ------ bootloader/meizu_m6sp.c | 122 ----- firmware/SOURCES | 42 -- firmware/drivers/rtc/rtc_s35390a.c | 111 ---- firmware/export/config.h | 14 - firmware/export/config/meizum3.h | 176 ------- firmware/export/config/meizum6sl.h | 177 ------- firmware/export/config/meizum6sp.h | 183 ------- firmware/export/config/samsungyps3.h | 176 ------- firmware/target/arm/s5l8700/audio-meizu.c | 68 --- firmware/target/arm/s5l8700/backlight-meizu.c | 79 --- firmware/target/arm/s5l8700/boot.lds | 6 +- firmware/target/arm/s5l8700/crt0.S | 84 --- .../target/arm/s5l8700/fmradio-i2c-meizu.c | 146 ------ firmware/target/arm/s5l8700/ftl-meizu.c | 48 -- .../target/arm/s5l8700/meizu-m3/button-m3.c | 69 --- .../arm/s5l8700/meizu-m3/button-target.h | 37 -- .../target/arm/s5l8700/meizu-m3/ftl-target.h | 45 -- firmware/target/arm/s5l8700/meizu-m3/lcd-m3.c | 321 ------------ .../target/arm/s5l8700/meizu-m3/nand-target.h | 58 -- .../arm/s5l8700/meizu-m3/powermgmt-m3.c | 59 --- .../arm/s5l8700/meizu-m6sl/button-target.h | 45 -- .../arm/s5l8700/meizu-m6sl/ftl-target.h | 45 -- .../target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c | 321 ------------ .../arm/s5l8700/meizu-m6sl/nand-target.h | 58 -- .../target/arm/s5l8700/meizu-m6sl/s6d0154.h | 80 --- .../arm/s5l8700/meizu-m6sp/button-m6sp.c | 68 --- .../arm/s5l8700/meizu-m6sp/button-target.h | 42 -- .../arm/s5l8700/meizu-m6sp/ftl-target.h | 45 -- .../target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c | 494 ------------------ .../arm/s5l8700/meizu-m6sp/nand-target.h | 58 -- .../arm/s5l8700/meizu-m6sp/powermgmt-m6sp.c | 56 -- firmware/target/arm/s5l8700/nand-meizu.c | 81 --- firmware/target/arm/s5l8700/power-meizu.c | 92 ---- firmware/target/arm/s5l8700/system-s5l8700.c | 6 - firmware/target/arm/s5l8700/udacodec-meizu.c | 62 --- .../arm/s5l8700/yps3/backlight-target.h | 33 -- .../target/arm/s5l8700/yps3/backlight-yps3.c | 100 ---- .../target/arm/s5l8700/yps3/button-target.h | 41 -- .../target/arm/s5l8700/yps3/button-yps3.c | 156 ------ .../arm/s5l8700/yps3/fmradio-i2c-yps3.c | 46 -- firmware/target/arm/s5l8700/yps3/ftl-target.h | 39 -- firmware/target/arm/s5l8700/yps3/lcd-yps3.c | 337 ------------ .../target/arm/s5l8700/yps3/nand-target.h | 33 -- firmware/target/arm/s5l8700/yps3/nand-yps3.c | 109 ---- firmware/target/arm/s5l8700/yps3/power-yps3.c | 104 ---- firmware/target/hosted/sdl/sim-ui-defines.h | 7 - tools/builds.pm | 16 - tools/configure | 172 ++---- uisimulator/buttonmap/SOURCES | 2 - utils/meizu_dfu/Makefile | 11 - utils/meizu_dfu/README | 9 - utils/meizu_dfu/meizu_dfu.c | 441 ---------------- utils/themeeditor/resources/targetdb | 36 -- 60 files changed, 38 insertions(+), 5990 deletions(-) delete mode 100644 apps/keymaps/keymap-meizu-m6sl.c delete mode 100644 apps/keymaps/keymap-meizu-m6sp.c delete mode 100644 bootloader/meizu_m3.c delete mode 100644 bootloader/meizu_m6sl.c delete mode 100644 bootloader/meizu_m6sp.c delete mode 100644 firmware/drivers/rtc/rtc_s35390a.c delete mode 100644 firmware/export/config/meizum3.h delete mode 100644 firmware/export/config/meizum6sl.h delete mode 100644 firmware/export/config/meizum6sp.h delete mode 100644 firmware/export/config/samsungyps3.h delete mode 100644 firmware/target/arm/s5l8700/audio-meizu.c delete mode 100644 firmware/target/arm/s5l8700/backlight-meizu.c delete mode 100644 firmware/target/arm/s5l8700/fmradio-i2c-meizu.c delete mode 100644 firmware/target/arm/s5l8700/ftl-meizu.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/button-m3.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/button-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/ftl-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/lcd-m3.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/nand-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m3/powermgmt-m3.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sl/button-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sl/ftl-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sl/nand-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sl/s6d0154.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/button-m6sp.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/button-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/ftl-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/nand-target.h delete mode 100644 firmware/target/arm/s5l8700/meizu-m6sp/powermgmt-m6sp.c delete mode 100644 firmware/target/arm/s5l8700/nand-meizu.c delete mode 100644 firmware/target/arm/s5l8700/power-meizu.c delete mode 100644 firmware/target/arm/s5l8700/udacodec-meizu.c delete mode 100644 firmware/target/arm/s5l8700/yps3/backlight-target.h delete mode 100644 firmware/target/arm/s5l8700/yps3/backlight-yps3.c delete mode 100644 firmware/target/arm/s5l8700/yps3/button-target.h delete mode 100644 firmware/target/arm/s5l8700/yps3/button-yps3.c delete mode 100644 firmware/target/arm/s5l8700/yps3/fmradio-i2c-yps3.c delete mode 100644 firmware/target/arm/s5l8700/yps3/ftl-target.h delete mode 100644 firmware/target/arm/s5l8700/yps3/lcd-yps3.c delete mode 100644 firmware/target/arm/s5l8700/yps3/nand-target.h delete mode 100644 firmware/target/arm/s5l8700/yps3/nand-yps3.c delete mode 100644 firmware/target/arm/s5l8700/yps3/power-yps3.c delete mode 100644 utils/meizu_dfu/Makefile delete mode 100644 utils/meizu_dfu/README delete mode 100644 utils/meizu_dfu/meizu_dfu.c diff --git a/apps/SOURCES b/apps/SOURCES index 285d02fa3d..0191587ab3 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -215,10 +215,6 @@ keymaps/keymap-mr500.c keymaps/keymap-mr100.c #elif CONFIG_KEYPAD == COWON_D2_PAD keymaps/keymap-cowond2.c -#elif CONFIG_KEYPAD == MEIZU_M6SL_PAD -keymaps/keymap-meizu-m6sl.c -#elif CONFIG_KEYPAD == MEIZU_M6SP_PAD -keymaps/keymap-meizu-m6sp.c #elif CONFIG_KEYPAD == CREATIVEZVM_PAD keymaps/keymap-creativezvm.c #elif CONFIG_KEYPAD == CREATIVEZV_PAD diff --git a/apps/keymaps/keymap-meizu-m6sl.c b/apps/keymaps/keymap-meizu-m6sl.c deleted file mode 100644 index 31dbc88432..0000000000 --- a/apps/keymaps/keymap-meizu-m6sl.c +++ /dev/null @@ -1,299 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 Jonathan Gordon - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for the toshiba gigabeat target */ -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -/* CONTEXT_CUSTOM's used in this file... - -CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions) -CONTEXT_CUSTOM|CONTEXT_SETTINGS = the direction keys for the eq/col picker screens - i.e where up/down is inc/dec - CONTEXT_SETTINGS = up/down is prev/next, l/r is inc/dec - -*/ - - -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT,BUTTON_SELECT }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - - { ACTION_WPS_ABSETB_NEXTDIR, BUTTON_PLAY|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_WPS_ABSETA_PREVDIR, BUTTON_PLAY|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_WPS_ABRESET, BUTTON_PLAY|BUTTON_SELECT, BUTTON_NONE }, - - { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, - - { ACTION_WPS_PITCHSCREEN, BUTTON_PLAY|BUTTON_UP, BUTTON_PLAY }, - { ACTION_WPS_VIEW_PLAYLIST, BUTTON_PLAY|BUTTON_DOWN, BUTTON_PLAY }, - - { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_WPS_HOTKEY, BUTTON_PLAY|BUTTON_MENU, BUTTON_NONE }, - { ACTION_WPS_BROWSE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - - LAST_ITEM_IN_LIST -}; /* button_context_wps */ - -static const struct button_mapping button_context_list[] = { - { ACTION_LISTTREE_PGUP, BUTTON_PLAY|BUTTON_UP, BUTTON_NONE }, - { ACTION_LISTTREE_PGUP, BUTTON_PLAY|BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_LISTTREE_PGDOWN, BUTTON_PLAY|BUTTON_DOWN, BUTTON_NONE }, - { ACTION_LISTTREE_PGDOWN, BUTTON_PLAY|BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_list */ - -static const struct button_mapping button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_TREE_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_HOTKEY, BUTTON_PLAY|BUTTON_MENU, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) -}; /* button_context_tree */ - -static const struct button_mapping button_context_listtree_scroll_with_combo[] = { - { ACTION_NONE, BUTTON_PLAY, BUTTON_NONE }, - { ACTION_TREE_PGLEFT, BUTTON_PLAY|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_TREE_ROOT_INIT, BUTTON_PLAY|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_PLAY|BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_PLAY|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_PGRIGHT, BUTTON_PLAY|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_TREE_PGRIGHT, BUTTON_PLAY|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_listtree_scroll_without_combo[] = { - { ACTION_NONE, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - { ACTION_TREE_ROOT_INIT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_TREE_PGRIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings */ - -static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settingsgraphical */ - -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_yesno */ - -static const struct button_mapping button_context_colorchooser[] = { - { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ - -static const struct button_mapping button_context_eq[] = { - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_eq */ - -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { - { ACTION_BMS_DELETE, BUTTON_PLAY, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_bmark */ - -static const struct button_mapping button_context_time[] = { - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_PLAY, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_time */ - -static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ - -static const struct button_mapping button_context_pitchscreen[] = { - { ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE }, - { ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_PS_RESET, BUTTON_PLAY, BUTTON_NONE }, - { ACTION_PS_EXIT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ - -static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_PAGE_FLIP, BUTTON_PLAY|BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_DONE, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_KBD_ABORT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, -// { ACTION_KBD_MORSE_INPUT, BUTTON_PLAY|BUTTON_POWER, BUTTON_NONE }, - { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_keyboard */ - - -const struct button_mapping* get_context_mapping(int context) -{ - switch (context) - { - case CONTEXT_STD: - return button_context_standard; - case CONTEXT_WPS: - return button_context_wps; - - case CONTEXT_LIST: - return button_context_list; - case CONTEXT_MAINMENU: - case CONTEXT_TREE: - if (global_settings.hold_lr_for_scroll_in_list) - return button_context_listtree_scroll_without_combo; - else - return button_context_listtree_scroll_with_combo; - case CONTEXT_CUSTOM|CONTEXT_TREE: - return button_context_tree; - - case CONTEXT_SETTINGS: - return button_context_settings; - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - return button_context_settings_right_is_inc; - - case CONTEXT_SETTINGS_COLOURCHOOSER: - return button_context_colorchooser; - case CONTEXT_SETTINGS_EQ: - return button_context_eq; - - case CONTEXT_SETTINGS_TIME: - return button_context_time; - - case CONTEXT_YESNOSCREEN: - return button_context_yesno; - case CONTEXT_BOOKMARKSCREEN: - return button_context_bmark; - case CONTEXT_QUICKSCREEN: - return button_context_quickscreen; - case CONTEXT_PITCHSCREEN: - return button_context_pitchscreen; - case CONTEXT_KEYBOARD: - case CONTEXT_MORSE_INPUT: - return button_context_keyboard; - } - return button_context_standard; -} diff --git a/apps/keymaps/keymap-meizu-m6sp.c b/apps/keymaps/keymap-meizu-m6sp.c deleted file mode 100644 index 962b8b5579..0000000000 --- a/apps/keymaps/keymap-meizu-m6sp.c +++ /dev/null @@ -1,76 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 Jonathan Gordon - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for the toshiba gigabeat target */ -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -/* CONTEXT_CUSTOM's used in this file... - -CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions) -CONTEXT_CUSTOM|CONTEXT_SETTINGS = the direction keys for the eq/col picker screens - i.e where up/down is inc/dec - CONTEXT_SETTINGS = up/down is prev/next, l/r is inc/dec - -*/ - -/* copied from Meizu M6SP keymap */ -static const struct button_mapping button_context_standard[] = { -#if 0 /* disabled for now, there is no BUTTON_UP/DOWN yet */ - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, -#endif - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT,BUTTON_SELECT }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -const struct button_mapping* get_context_mapping(int context) -{ - (void)context; - - /* TODO add more button contexts */ - return button_context_standard; -} diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 73bf98154b..9ccb73f5ea 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -162,8 +162,6 @@ const struct button_mapping pf_context_buttons[] = {PF_QUIT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, #elif CONFIG_KEYPAD == IAUDIO_M3_PAD {PF_QUIT, BUTTON_RC_REC, BUTTON_NONE}, -#elif CONFIG_KEYPAD == MEIZU_M6SL_PAD - {PF_QUIT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, #elif CONFIG_KEYPAD == IRIVER_H100_PAD || CONFIG_KEYPAD == IRIVER_H300_PAD {PF_QUIT, BUTTON_OFF, BUTTON_NONE}, #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD diff --git a/bootloader/SOURCES b/bootloader/SOURCES index 1221e044c1..1f83d6218b 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -42,14 +42,6 @@ mrobe500.c #elif defined(CPU_TCC780X) telechips.c show_logo.c -#elif defined(MEIZU_M6SL) -meizu_m6sl.c -#elif defined(MEIZU_M6SP) -meizu_m6sp.c -#elif defined(MEIZU_M3) -meizu_m3.c -#elif defined(SAMSUNG_YPS3) -samsung_yps3.c #elif defined(ONDA_VX747) || defined(ONDA_VX747P) || defined(ONDA_VX767) || defined(ONDA_VX777) ondavx747.c show_logo.c diff --git a/bootloader/meizu_m3.c b/bootloader/meizu_m3.c deleted file mode 100644 index bbe3d77deb..0000000000 --- a/bootloader/meizu_m3.c +++ /dev/null @@ -1,220 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Greg White - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include - -#include "config.h" - -#include "inttypes.h" -#include "cpu.h" -#include "system.h" -#include "lcd.h" -#include "../kernel-internal.h" -#include "storage.h" -#include "disk.h" -#include "font.h" -#include "backlight.h" -#include "backlight-target.h" -#include "button.h" -#include "panic.h" -#include "power.h" -#include "file.h" -#include "common.h" -#include "rbunicode.h" -#include "usb.h" -#include "qt1106.h" -#include "bitmaps/rockboxlogo.h" - -#include "i2c-s5l8700.h" -#include "dma-target.h" -#include "pcm.h" -#include "audiohw.h" -#include "rtc.h" -#include "time.h" - -#define LONG_DELAY 200000 -#define SHORT_DELAY 50000 -#define PAUSE_DELAY 50000 - -static inline void delay(int duration) -{ - volatile int i; - for(i=0;i>i & 1); - } - delay(SHORT_DELAY*6); -} - -void post_mortem_stub(void) -{ -} - -void main(void) -{ - char mystring[64]; - int i; - unsigned short data = 0; - char write_data[2], read_data[16]; - struct tm tm; - - //Set backlight pin to output and enable - int oldval = PCON0; - PCON0 = ((oldval & ~(3 << 4)) | (1 << 4)); - PDAT0 |= (1 << 2); - - // Set codec reset pin inactive - PCON5 = (PCON5 & ~0xF) | 1; - PDAT5 &= ~(1 << 0); - - //power on -// oldval = PCON1; -// PCON1 = ((oldval & ~(0xf << 12)) | (1 << 12)); -// PDAT1|=(1<<3); - - //Set PLAY to EINT4 - oldval = PCON1; - PCON1 = ((oldval & ~(0xf << 16)) | (2 << 16)); - - //Set MENU to EINT0 - oldval = PCON1; - PCON1 = (oldval & ~(0xf)) | 2; - - // enable external interrupts - EINTPOL = 0x11; - INTMSK = 0x11; - EINTMSK = 0x11; - asm volatile("msr cpsr_c, #0x13\n\t"); // enable interrupts - - system_init(); - kernel_init(); - - lcd_init(); - backlight_init(); /* BUGFIX backlight_init MUST BE AFTER lcd_init */ - lcd_update(); - - i2c_init(); - - init_qt1106(); - - /* Calibrate the lot */ - qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF | QT1106_DI \ - | QT1106_SLD_SLIDER | QT1106_CAL_WHEEL | QT1106_CAL_KEYS | QT1106_RES_256); - - lcd_clear_display(); - lcd_bitmap(rockboxlogo, 0, 30, BMPWIDTH_rockboxlogo, BMPHEIGHT_rockboxlogo); - lcd_update(); - - /* Set to maximum sensitivity */ - qt1106_io(QT1106_CT | (0x00 << 8) ); - - while(true) - { -#if 1 /* enable this to see info about the slider touchpad */ - qt1106_wait(); - - int slider = qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF \ - | QT1106_DI | QT1106_SLD_SLIDER | QT1106_RES_256); - snprintf(mystring, 64, "%x %2.2x",(slider & 0x008000)>>15, slider&0xff); - lcd_puts(0,1,mystring); - backlight_hw_brightness((slider & 0xFF) >> 4); - - /* - if(slider & 0x008000) - bl_debug_count(((slider&0xff)) + 1); - */ -#endif - -#if 1 /* enable this to see info about the RTC */ - rtc_read_datetime(&tm); - snprintf(mystring, 64, "%04d-%02d-%02d %02d:%02d:%02d", - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - lcd_puts(0, 10, mystring); -#endif - -#if 1 /* enable this so see info about the UDA1380 codec */ - memset(read_data, 0, sizeof(read_data)); - for (i = 0; i < 7; i++) { - write_data[0] = i; - i2c_read(0x30, i, 2, read_data); - data = read_data[0] << 8 | read_data[1]; - snprintf(mystring + 4 * i, 64, "%04X", data); - } - lcd_puts(0, 11, mystring); -#endif - -#if 1 /* enable this to see info about IODMA channel 0 (PCM) */ - snprintf(mystring, 64, "DMA: %08X %08X", (int)DMACADDR0, (int)DMACTCNT0); - lcd_puts(0, 12, mystring); -#endif -#if 1 /* enable this to see info about IIS */ - snprintf(mystring, 64, "IIS: %08X", (int)I2SSTATUS); - lcd_puts(0, 13, mystring); -#endif - - lcd_update(); - } - - //power off - PDAT1&=~(1<<3); -} - diff --git a/bootloader/meizu_m6sl.c b/bootloader/meizu_m6sl.c deleted file mode 100644 index 073c57cb0d..0000000000 --- a/bootloader/meizu_m6sl.c +++ /dev/null @@ -1,153 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Greg White - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" - -#include -#include -#include "inttypes.h" -#include "string.h" -#include "cpu.h" -#include "system.h" -#include "lcd.h" -#include "kernel.h" -#include "thread.h" -#include "storage.h" -#include "disk.h" -#include "font.h" -#include "adc.h" -#include "backlight.h" -#include "backlight-target.h" -#include "button.h" -#include "panic.h" -#include "power.h" -#include "file.h" -#include "common.h" -#include "rbunicode.h" -#include "usb.h" -#include "qt1106.h" - -#include - -#define LONG_DELAY 200000 -#define SHORT_DELAY 50000 -#define PAUSE_DELAY 50000 - -static inline void delay(int duration) -{ - volatile int i; - for(i=0;i>i & 1); - } - delay(SHORT_DELAY*6); -} - -/* These functions are supposed to be static in lcd-m6sl.c, but - we use them here for testing */ -void init_lcd_spi(void); -unsigned int lcd_read_id(void); - -void main(void) -{ - //Set backlight pin to output and enable - unsigned int model; - int oldval = PCON0; - PCON0 = ((oldval & ~(3 << 4)) | (1 << 4)); - PDAT0 |= (1 << 2); - - //Set PLAY to input - oldval = PCON1; - PCON1 = ((oldval & ~(0xf << 16)) | (0 << 16)); - - init_qt1106(); - - // Wait for play to be pressed - while(!(PDAT1 & (1 << 4))); - // Wait for play to be released - while((PDAT1 & (1 << 4))); - PDAT0 ^= (1 << 2); //Toggle backlight - delay(LONG_DELAY); - - init_lcd_spi(); - model=lcd_read_id(); - bl_debug_count((model&0xf000)>>12); - bl_debug_count((model&0xf00)>>8); - bl_debug_count((model&0xf0)>>4); - bl_debug_count(model&0xf); - - /* Calibrate the lot */ - qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF | QT1106_DI \ - | QT1106_SLD_SLIDER | QT1106_CAL_WHEEL | QT1106_CAL_KEYS | QT1106_RES_4); - - /* Set to maximum sensitivity */ - qt1106_io(QT1106_CT | (0x00 << 8) ); - - while(true) - { - qt1106_wait(); - - int slider = qt1106_io(QT1106_MODE_FREE | QT1106_MOD_INF \ - | QT1106_DI | QT1106_SLD_SLIDER | QT1106_RES_4); - if(slider & 0x008000) - bl_debug_count(((slider&0xff)) + 1); - } - - //power off - PDAT1&=~(1<<3); -} - diff --git a/bootloader/meizu_m6sp.c b/bootloader/meizu_m6sp.c deleted file mode 100644 index 0a6dc274d9..0000000000 --- a/bootloader/meizu_m6sp.c +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Greg White - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" - -#include -#include -#include "inttypes.h" -#include "string.h" -#include "cpu.h" -#include "system.h" -#include "lcd.h" -#include "kernel.h" -#include "thread.h" -#include "storage.h" -#include "disk.h" -#include "font.h" -#include "button.h" -#include "panic.h" -#include "power.h" -#include "file.h" -#include "common.h" -#include "rbunicode.h" -#include "usb.h" -#include "qt1106.h" -#include "bitmaps/rockboxlogo.h" - -#include - -#define LONG_DELAY 200000 -#define SHORT_DELAY 50000 -#define PAUSE_DELAY 50000 - -static inline void delay(int duration) -{ - volatile int i; - for(i=0;i>i & 1); - } - delay(SHORT_DELAY*6); -} - -void main(void) -{ - //Set backlight pin to output and enable - int oldval = PCON0; - PCON0 = ((oldval & ~(3 << 4)) | (1 << 4)); - PDAT0 |= (1 << 2); - - //Set PLAY to input - oldval = PCON1; - PCON1 = ((oldval & ~(0xf << 16)) | (0 << 16)); - - lcd_bitmap(rockboxlogo, 0, 0, BMPWIDTH_rockboxlogo, BMPHEIGHT_rockboxlogo); - lcd_init_device(); - - // Wait for play to be pressed - while(!(PDAT1 & (1 << 4))); - // Wait for play to be released - while((PDAT1 & (1 << 4))); - PDAT0 ^= (1 << 2); //Toggle backlight - delay(LONG_DELAY); - - //power off - PDAT1&=~(1<<3); -} - diff --git a/firmware/SOURCES b/firmware/SOURCES index ef558a8009..a3a577d4bd 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -483,8 +483,6 @@ drivers/rtc/rtc_jz4740.c drivers/rtc/rtc_jz4760.c #elif (CONFIG_RTC == RTC_X1000) drivers/rtc/rtc_x1000.c -#elif (CONFIG_RTC == RTC_S35390A) -drivers/rtc/rtc_s35390a.c #elif (CONFIG_RTC == RTC_S35380A) drivers/rtc/rtc_s35380a.c #elif (CONFIG_RTC == RTC_D2) @@ -1600,37 +1598,6 @@ target/arm/tcc780x/cowond2/audio-cowond2.c #endif /* BOOTLOADER */ #endif /* COWON_D2 */ -#ifdef MEIZU_M6SL -target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c -drivers/qt1106.c -#endif /* MEIZU_M6SL */ - -#ifdef MEIZU_M6SP -target/arm/s5l8700/backlight-meizu.c -target/arm/s5l8700/power-meizu.c -target/arm/s5l8700/meizu-m6sp/button-m6sp.c -target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c -#ifndef BOOTLOADER -drivers/generic_i2c.c -drivers/rtc/rtc_s35390a.c -target/arm/s5l8700/audio-meizu.c -target/arm/s5l8700/ftl-meizu.c -target/arm/s5l8700/nand-meizu.c -target/arm/s5l8700/fmradio-i2c-meizu.c -target/arm/s5l8700/powermgmt-meizu.c -target/arm/s5l8700/usb-s5l8700.c -#endif /* BOOTLOADER */ -#endif /* MEIZU_M6SP */ - -#ifdef MEIZU_M3 -target/arm/s5l8700/backlight-meizu.c -target/arm/s5l8700/meizu-m3/lcd-m3.c -drivers/qt1106.c -#ifndef BOOTLOADER -target/arm/s5l8700/udacodec-meizu.c -#endif /* BOOTLOADER */ -#endif /* MEIZU_M3 */ - #ifdef IPOD_NANO2G target/arm/ipod/button-clickwheel.c target/arm/s5l8700/postmortemstub.S @@ -1928,15 +1895,6 @@ target/arm/samsung/yh925/powermgmt-yh925.c target/arm/samsung/fmradio-yh92x.c #endif /* SAMSUNG_YH925 */ -#ifdef SAMSUNG_YPS3 -target/arm/s5l8700/yps3/button-yps3.c -target/arm/s5l8700/yps3/lcd-yps3.c -target/arm/s5l8700/yps3/fmradio-i2c-yps3.c -target/arm/s5l8700/yps3/backlight-yps3.c -target/arm/s5l8700/yps3/nand-yps3.c -target/arm/s5l8700/yps3/power-yps3.c -#endif /* SAMSUNG_YPS3 */ - #ifdef PBELL_VIBE500 drivers/synaptics-mep.c target/arm/pbell/vibe500/lcd-vibe500.c diff --git a/firmware/drivers/rtc/rtc_s35390a.c b/firmware/drivers/rtc/rtc_s35390a.c deleted file mode 100644 index 6e69073254..0000000000 --- a/firmware/drivers/rtc/rtc_s35390a.c +++ /dev/null @@ -1,111 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * Copyright (C) 2008 by Robert Kukla - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "rtc.h" -#include "i2c-s5l8700.h" -#include "timefuncs.h" - -/* Driver for the Seiko S35390A real-time clock chip with i2c interface - - This driver was derived from rtc_mr100.c and adapted for the S35390A - used in the Meizu M3 (and possibly others). - */ - -#define RTC_ADDR 0x60 - -#define STATUS_REG1 0 -#define STATUS_REG2 1 -#define REALTIME_DATA1 2 -#define REALTIME_DATA2 3 -#define INT1_REG 4 -#define INT2_REG 5 -#define CLOCK_CORR_REG 6 -#define FREE_REG 7 - - -static void reverse_bits(unsigned char* v, int size) -{ - static const unsigned char flipnibble[] = - {0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, - 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F}; - int i; - - for (i = 0; i < size; i++) { - v[i] = (flipnibble[v[i] & 0x0F] << 4) | - flipnibble[(v[i] >> 4) & 0x0F]; - } -} - -void rtc_init(void) -{ -} - -int rtc_read_datetime(struct tm *tm) -{ - unsigned char buf[7]; - unsigned int i; - int ret; - - ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf); - reverse_bits(buf, sizeof(buf)); - - buf[4] &= 0x3f; /* mask out p.m. flag */ - - for (i = 0; i < sizeof(buf); i++) - buf[i] = BCD2DEC(buf[i]); - - tm->tm_sec = buf[6]; - tm->tm_min = buf[5]; - tm->tm_hour = buf[4]; - tm->tm_mday = buf[2]; - tm->tm_mon = buf[1] - 1; - tm->tm_year = buf[0] + 100; - - set_day_of_week(tm); - set_day_of_year(tm); - - return ret; -} - -int rtc_write_datetime(const struct tm *tm) -{ - unsigned char buf[7]; - unsigned int i; - int ret; - - buf[6] = tm->tm_sec; - buf[5] = tm->tm_min; - buf[4] = tm->tm_hour; - buf[3] = tm->tm_wday; - buf[2] = tm->tm_mday; - buf[1] = tm->tm_mon + 1; - buf[0] = tm->tm_year - 100; - - for (i = 0; i < sizeof(buf); i++) - buf[i] = DEC2BCD(buf[i]); - - reverse_bits(buf, sizeof(buf)); - ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf); - - return ret; -} - diff --git a/firmware/export/config.h b/firmware/export/config.h index 040709af3f..73694cef30 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -118,17 +118,13 @@ #define CREATIVEZV_PAD 26 #define PHILIPS_SA9200_PAD 27 #define PHILIPS_HDD1630_PAD 29 -#define MEIZU_M6SL_PAD 30 #define ONDAVX747_PAD 31 #define ONDAVX767_PAD 32 -#define MEIZU_M6SP_PAD 33 -#define MEIZU_M3_PAD 34 #define SANSA_CLIP_PAD 35 #define SANSA_FUZE_PAD 36 #define LYRE_PROTO1_PAD 37 #define SAMSUNG_YH820_PAD 38 #define ONDAVX777_PAD 39 -#define SAMSUNG_YPS3_PAD 40 #define MINI2440_PAD 41 #define PHILIPS_HDD6330_PAD 42 #define PBELL_VIBE500_PAD 43 @@ -246,7 +242,6 @@ #define LCD_SA9200 25 /* as used by the Philips SA9200 */ #define LCD_S6B33B2 26 /* as used by the Samsumg YH820 */ #define LCD_HDD1630 27 /* as used by the Philips HDD1630 */ -#define LCD_MEIZUM6 28 /* as used by the Meizu M6SP and M6SL (various models) */ #define LCD_ONDAVX747 29 /* as used by the Onda VX747 */ #define LCD_ONDAVX767 30 /* as used by the Onda VX767 */ #define LCD_SSD1303 31 /* as used by the Sansa Clip */ @@ -354,7 +349,6 @@ Lyre prototype 1 */ #define RTC_MR100 12 #define RTC_MC13783 13 /* Freescale MC13783 PMIC */ #define RTC_S5L8700 14 -#define RTC_S35390A 15 #define RTC_JZ4740 16 /* Ingenic Jz4740 */ #define RTC_NANO2G 17 /* This seems to be a PCF5063x */ #define RTC_D2 18 /* Either PCF50606 or PCF50635 */ @@ -465,12 +459,6 @@ Lyre prototype 1 */ #include "config/gogearhdd1630.h" #elif defined(PHILIPS_HDD6330) #include "config/gogearhdd6330.h" -#elif defined(MEIZU_M6SL) -#include "config/meizum6sl.h" -#elif defined(MEIZU_M6SP) -#include "config/meizum6sp.h" -#elif defined(MEIZU_M3) -#include "config/meizum3.h" #elif defined(ONDA_VX747) || defined(ONDA_VX747P) #include "config/ondavx747.h" #elif defined(ONDA_VX777) @@ -509,8 +497,6 @@ Lyre prototype 1 */ #include "config/samsungyh920.h" #elif defined(SAMSUNG_YH925) #include "config/samsungyh925.h" -#elif defined(SAMSUNG_YPS3) -#include "config/samsungyps3.h" #elif defined(PBELL_VIBE500) #include "config/vibe500.h" #elif defined(MPIO_HD200) diff --git a/firmware/export/config/meizum3.h b/firmware/export/config/meizum3.h deleted file mode 100644 index e519d6469c..0000000000 --- a/firmware/export/config/meizum3.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This config file is for Meizu M3 - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 39 - -#define MODEL_NAME "Meizu M3" - -/* define this if you have recording possibility */ -//#define HAVE_RECORDING - -/* Define bitmask of input sources - recordable bitmask can be defined - explicitly if different */ -#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO) - -/* define the bitmask of hardware sample rates */ -#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - -/* define the bitmask of recording sample rates */ -#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - - - - -/* define this if you can flip your LCD */ -//#define HAVE_LCD_FLIP - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you can invert the colours on your LCD */ -//#define HAVE_LCD_INVERT - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if you have a flash memory storage */ -#define HAVE_FLASH_STORAGE - -#define CONFIG_STORAGE STORAGE_NAND - -#define CONFIG_NAND NAND_SAMSUNG - -/* The NAND flash has 2048-byte sectors, and is our only storage */ -#define SECTOR_SIZE 2048 - -/* LCD dimensions */ -#define LCD_WIDTH 176 -#define LCD_HEIGHT 132 -/* sqrt(176^2 + 132^2) / 1.5 = 146.7 */ -#define LCD_DPI 147 -#define LCD_DEPTH 16 /* pseudo 262.144 colors */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -//#define HAVE_LCD_ENABLE - -/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE - should be defined as well. */ -//#define HAVE_LCD_SLEEP - -#define CONFIG_KEYPAD MEIZU_M3_PAD - -//#define AB_REPEAT_ENABLE -//#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE - - - - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC RTC_S5L8700 -#define CONFIG_RTC RTC_S35390A - -#define CONFIG_LCD LCD_MEIZUM6 - -/* Define the type of audio codec */ -#define HAVE_UDA1380 - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Define this if you have a software controlled poweroff */ -#define HAVE_SW_POWEROFF - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -/* FM Tuner */ -#define CONFIG_TUNER TEA5760 -#define CONFIG_TUNER_XTAL 32768 - -//#define HAVE_TLV320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2250 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 50 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging, software can monitor plug and charge state */ -#define CONFIG_CHARGING CHARGING_MONITOR - -/* Define this if your LCD can set contrast */ -//#define HAVE_LCD_CONTRAST - -/* Define this if you have a Motorola SCF5250 */ -#define CONFIG_CPU S5L8700 - -/* Define this if you want to use coldfire's i2c interface */ -#define CONFIG_I2C I2C_S5L8700 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 11289600 - -/* Define this if you have ATA power-off control */ -//#define HAVE_ATA_POWER_OFF - -/* USB On-the-go */ -//#define CONFIG_USBOTG USBOTG_M5636 - -/* Define this if you have adjustable CPU frequency */ -#define HAVE_ADJUSTABLE_CPU_FREQ - -#define BOOTFILE_EXT "meizu" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define BOOTLOADER_ENTRYPOINT 0x001F0000 -#define FLASH_ENTRYPOINT 0x00001000 -#define FLASH_MAGIC 0xfbfbfbf1 - -/* Define this for FM radio input available */ -#define HAVE_FMRADIO_IN - -/** Port-specific settings **/ - -/* Main LCD contrast range and defaults */ -#define MIN_CONTRAST_SETTING 1 -#define MAX_CONTRAST_SETTING 30 -#define DEFAULT_CONTRAST_SETTING 19 /* Match boot contrast */ - -/* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 0 -#define MAX_BRIGHTNESS_SETTING 15 -#define DEFAULT_BRIGHTNESS_SETTING 10 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/export/config/meizum6sl.h b/firmware/export/config/meizum6sl.h deleted file mode 100644 index 0e5e8b8c4a..0000000000 --- a/firmware/export/config/meizum6sl.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This config file is for Meizu M6SL - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 38 - -#define MODEL_NAME "Meizu M6SL" - -/* define this if you have recording possibility */ -//#define HAVE_RECORDING - -/* Define bitmask of input sources - recordable bitmask can be defined - explicitly if different */ -#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO) - -/* define the bitmask of hardware sample rates */ -#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - -/* define the bitmask of recording sample rates */ -#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - - - - -/* define this if you can flip your LCD */ -//#define HAVE_LCD_FLIP - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you can invert the colours on your LCD */ -//#define HAVE_LCD_INVERT - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if you have a flash memory storage */ -#define HAVE_FLASH_STORAGE - -#define CONFIG_STORAGE STORAGE_NAND - -#define CONFIG_NAND NAND_SAMSUNG - -/* The NAND flash has 512-byte sectors, and is our only storage */ -#define SECTOR_SIZE 512 - -/* LCD dimensions */ -#define LCD_WIDTH 320 -#define LCD_HEIGHT 240 -/* sqrt(320^2 + 240^2) / 2.6 = 153.8 */ -#define LCD_DPI 154 -#define LCD_DEPTH 16 /* pseudo 262.144 colors */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -//#define HAVE_LCD_ENABLE - -/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE - should be defined as well. */ -//#define HAVE_LCD_SLEEP - -#define CONFIG_KEYPAD MEIZU_M6SL_PAD - -//#define AB_REPEAT_ENABLE -//#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE - - - - -/* define this if you have a real-time clock */ -#define CONFIG_RTC RTC_S5L8700 -//#define CONFIG_RTC RTC_S35390A - -#define CONFIG_LCD LCD_MEIZUM6 - -/* Define this if you have the WM8975 audio codec */ -#define HAVE_WM8751 //FIXME - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Define this if you have a software controlled poweroff */ -#define HAVE_SW_POWEROFF - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -/* FM Tuner */ -#define CONFIG_TUNER TEA5760 -#define CONFIG_TUNER_XTAL 32768 - -//#define HAVE_TLV320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2250 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 50 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging? FIXME */ -#define CONFIG_CHARGING CHARGING_SIMPLE - -/* Define this if your LCD can set contrast */ -//#define HAVE_LCD_CONTRAST - -/* Define this if you have a Motorola SCF5250 */ -#define CONFIG_CPU S5L8700 - -/* Define this if you want to use coldfire's i2c interface */ -#define CONFIG_I2C I2C_S5L8700 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 11289600 - -/* Define this if you have ATA power-off control */ -//#define HAVE_ATA_POWER_OFF - -/* USB On-the-go */ -//#define CONFIG_USBOTG USBOTG_M5636 - -/* Define this if you have adjustable CPU frequency */ -#define HAVE_ADJUSTABLE_CPU_FREQ - -#define BOOTFILE_EXT "meizu" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define BOOTLOADER_ENTRYPOINT 0x001F0000 -#define FLASH_ENTRYPOINT 0x00001000 -#define FLASH_MAGIC 0xfbfbfbf1 - -/* Define this for FM radio input available */ -#define HAVE_FMRADIO_IN - -/** Port-specific settings **/ - -/* Main LCD contrast range and defaults */ -#define MIN_CONTRAST_SETTING 1 -#define MAX_CONTRAST_SETTING 30 -#define DEFAULT_CONTRAST_SETTING 19 /* Match boot contrast */ - -/* Main LCD backlight brightness range and defaults */ -/* PCF50506 can output 0%-100% duty cycle but D305A expects %15-100%. */ -#define MIN_BRIGHTNESS_SETTING 1 /* 15/16 (93.75%) */ -#define MAX_BRIGHTNESS_SETTING 13 /* 3/16 (18.75%) */ -#define DEFAULT_BRIGHTNESS_SETTING 8 /* 8/16 (50.00%) = x5 boot default */ - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/export/config/meizum6sp.h b/firmware/export/config/meizum6sp.h deleted file mode 100644 index 972602ffb0..0000000000 --- a/firmware/export/config/meizum6sp.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * This config file is for Meizu M6SP - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 37 - -#define MODEL_NAME "Meizu M6SP" - -/* define this if you have recording possibility */ -//#define HAVE_RECORDING - -/* Define bitmask of input sources - recordable bitmask can be defined - explicitly if different */ -#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO) - -/* define the bitmask of hardware sample rates */ -#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - -/* FIXME: define actual rates applicable for M6SP */ -#define CODEC_SRCTRL_11025HZ (0x19 << 1) -#define CODEC_SRCTRL_22050HZ (0x1b << 1) -#define CODEC_SRCTRL_44100HZ (0x11 << 1) -#define CODEC_SRCTRL_88200HZ (0x1f << 1) - -/* define the bitmask of recording sample rates */ -#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - - - - -/* define this if you can flip your LCD */ -//#define HAVE_LCD_FLIP - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you can invert the colours on your LCD */ -//#define HAVE_LCD_INVERT - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if you have a flash memory storage */ -#define HAVE_FLASH_STORAGE - -#define CONFIG_STORAGE STORAGE_NAND - -#define CONFIG_NAND NAND_SAMSUNG - -/* The NAND flash has 2048-byte sectors, and is our only storage */ -#define SECTOR_SIZE 2048 - -/* LCD dimensions */ -#define LCD_WIDTH 240 -#define LCD_HEIGHT 320 -/* sqrt(240^2 + 320^2) / 2.4 = 166.0 */ -#define LCD_DPI 166 -#define LCD_DEPTH 16 /* pseudo 262.144 colors */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -#define HAVE_LCD_ENABLE - -/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE - should be defined as well. */ -//#define HAVE_LCD_SLEEP - -#define CONFIG_KEYPAD MEIZU_M6SP_PAD - -//#define AB_REPEAT_ENABLE -//#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE - - - - -/* define this if you have a real-time clock */ -#define CONFIG_RTC RTC_S5L8700 -//#define CONFIG_RTC RTC_S35390A - -#define CONFIG_LCD LCD_MEIZUM6 - -/* Define this if you have the WM8975 audio codec */ -#define HAVE_WM8751 //FIXME - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Define this if you have a software controlled poweroff */ -#define HAVE_SW_POWEROFF - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -/* FM Tuner */ -#define CONFIG_TUNER TEA5760 -#define CONFIG_TUNER_XTAL 32768 - -//#define HAVE_TLV320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -#define BATTERY_CAPACITY_DEFAULT 700 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2250 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 50 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging? FIXME */ -#define CONFIG_CHARGING CHARGING_SIMPLE - -/* Define this if your LCD can set contrast */ -//#define HAVE_LCD_CONTRAST - -/* Define this if you have a Motorola SCF5250 */ -#define CONFIG_CPU S5L8700 - -/* Define this if you want to use coldfire's i2c interface */ -#define CONFIG_I2C I2C_S5L8700 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 11289600 - -/* Define this if you have ATA power-off control */ -//#define HAVE_ATA_POWER_OFF - -/* USB On-the-go */ -//#define CONFIG_USBOTG USBOTG_M5636 - -/* Define this if you have adjustable CPU frequency */ -#define HAVE_ADJUSTABLE_CPU_FREQ - -#define BOOTFILE_EXT "meizu" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define BOOTLOADER_ENTRYPOINT 0x001F0000 -#define FLASH_ENTRYPOINT 0x00001000 -#define FLASH_MAGIC 0xfbfbfbf1 - -/* Define this for FM radio input available */ -#define HAVE_FMRADIO_IN - -/** Port-specific settings **/ - -/* Main LCD contrast range and defaults */ -#define MIN_CONTRAST_SETTING 1 -#define MAX_CONTRAST_SETTING 30 -#define DEFAULT_CONTRAST_SETTING 19 /* Match boot contrast */ - -/* Main LCD backlight brightness range and defaults */ -/* PCF50506 can output 0%-100% duty cycle but D305A expects %15-100%. */ -#define MIN_BRIGHTNESS_SETTING 1 /* 15/16 (93.75%) */ -#define MAX_BRIGHTNESS_SETTING 13 /* 3/16 (18.75%) */ -#define DEFAULT_BRIGHTNESS_SETTING 8 /* 8/16 (50.00%) = x5 boot default */ - -/* Define this if a programmable hotkey is mapped */ -//#define HAVE_HOTKEY diff --git a/firmware/export/config/samsungyps3.h b/firmware/export/config/samsungyps3.h deleted file mode 100644 index 826c44aedf..0000000000 --- a/firmware/export/config/samsungyps3.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This config file is for Samsung YP-S3 - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 53 - -#define MODEL_NAME "Samsumg YP-S3" - -/* define this if you have recording possibility */ -//#define HAVE_RECORDING - -/* Define bitmask of input sources - recordable bitmask can be defined - explicitly if different */ -#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_LINEIN | SRC_CAP_FMRADIO) - -/* define the bitmask of hardware sample rates */ -#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - -/* define the bitmask of recording sample rates */ -#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - - - - -/* define this if you can flip your LCD */ -//#define HAVE_LCD_FLIP - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you can invert the colours on your LCD */ -//#define HAVE_LCD_INVERT - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if you have a flash memory storage */ -#define HAVE_FLASH_STORAGE - -#define CONFIG_STORAGE STORAGE_NAND - -#define CONFIG_NAND NAND_SAMSUNG - -/* LCD dimensions */ -#define LCD_WIDTH 176 -#define LCD_HEIGHT 220 -/* sqrt(176^2 + 220^2) / 1.8 = 156.5 */ -#define LCD_DPI 157 -#define LCD_DEPTH 16 /* pseudo 262.144 colors */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -//#define HAVE_LCD_ENABLE - -/* Define this if your LCD can be put to sleep. HAVE_LCD_ENABLE - should be defined as well. */ -//#define HAVE_LCD_SLEEP - -/* We have button lights */ -#define HAVE_BUTTON_LIGHT - -#define CONFIG_KEYPAD MEIZU_M3_PAD - -/* We have headphone detection */ -#define HAVE_HEADPHONE_DETECTION - -//#define AB_REPEAT_ENABLE -//#define ACTION_WPSAB_SINGLE ACTION_WPS_BROWSE - - - - -/* define this if you have a real-time clock */ -#define CONFIG_RTC RTC_S35390A - -/* Define the type of audio codec */ -//#define HAVE_WM.... - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Define this if you have a software controlled poweroff */ -#define HAVE_SW_POWEROFF - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -/* FM Tuner */ -#define CONFIG_TUNER SI4700 -#define CONFIG_TUNER_XTAL 32768 - -/* assume no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -#define BATTERY_CAPACITY_DEFAULT 580 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 580 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 580 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 0 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging, software can monitor plug and charge state */ -#define CONFIG_CHARGING CHARGING_MONITOR - -/* Define this if your LCD can set contrast */ -//#define HAVE_LCD_CONTRAST - -/* We have a Samsung S5L8700 */ -#define CONFIG_CPU S5L8700 - -/* We use the S5L8700 i2c interface */ -#define CONFIG_I2C I2C_S5L8700 - -/* define this if the hardware can be powered off while charging */ -//#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 200000000 - -/* Define this if you have ATA power-off control */ -//#define HAVE_ATA_POWER_OFF - -/* USB */ -//#define HAVE_USBSTACK -#define USB_VENDOR_ID 0x04E8 -#define USB_PRODUCT_ID 0x5090 - -/* Define this if you have adjustable CPU frequency */ -#define HAVE_ADJUSTABLE_CPU_FREQ - -#define BOOTFILE_EXT "yps3" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -//#define BOOTLOADER_ENTRYPOINT 0x001F0000 -//#define FLASH_ENTRYPOINT 0x00001000 -//#define FLASH_MAGIC 0xfbfbfbf1 - -/* Define this for FM radio input available */ -#define HAVE_FMRADIO_IN - -/** Port-specific settings **/ - -/* Main LCD contrast range and defaults */ -#define MIN_CONTRAST_SETTING 1 -#define MAX_CONTRAST_SETTING 30 -#define DEFAULT_CONTRAST_SETTING 19 /* Match boot contrast */ - -/* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 0 -#define MAX_BRIGHTNESS_SETTING 15 -#define DEFAULT_BRIGHTNESS_SETTING 10 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/target/arm/s5l8700/audio-meizu.c b/firmware/target/arm/s5l8700/audio-meizu.c deleted file mode 100644 index 670b7e0100..0000000000 --- a/firmware/target/arm/s5l8700/audio-meizu.c +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "system.h" -#include "cpu.h" -#include "audio.h" -#include "audiohw.h" -#include "sound.h" - -int audio_channels = 2; -int audio_output_source = AUDIO_SRC_PLAYBACK; - -void audio_set_output_source(int source) -{ - if ((unsigned)source >= AUDIO_NUM_SOURCES) - source = AUDIO_SRC_PLAYBACK; - - audio_output_source = source; -} /* audio_set_output_source */ - -void audio_input_mux(int source, unsigned flags) -{ - static int last_source = AUDIO_SRC_PLAYBACK; - - (void)flags; - - switch (source) - { - default: /* playback - no recording */ - source = AUDIO_SRC_PLAYBACK; - case AUDIO_SRC_PLAYBACK: - audio_channels = 2; - if (source != last_source) - { -// audiohw_set_monitor(false); - } - break; - - case AUDIO_SRC_FMRADIO: /* recording and playback */ - audio_channels = 2; - if (source == last_source) - break; - -// audiohw_set_monitor(true); - break; - } /* end switch */ - - last_source = source; -} /* audio_input_mux */ - diff --git a/firmware/target/arm/s5l8700/backlight-meizu.c b/firmware/target/arm/s5l8700/backlight-meizu.c deleted file mode 100644 index d5c9a22f82..0000000000 --- a/firmware/target/arm/s5l8700/backlight-meizu.c +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include - -#include "config.h" -#include "backlight.h" -#include "backlight-target.h" -#include "system.h" - -/* - Backlight driver using the PWM mode of a hardware timer. - - The PWM duty cycle depends exponentially on the configured brightness - level. This makes the brightness curve more linear to the human eye. - */ - -void backlight_hw_brightness(int brightness) -{ - /* pwm = round(sqrt(2)**x), where brightness level x = 1..16 */ - static const unsigned int logtable[] = - {1, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 91, 128, 181, 256}; - - /* set PWM width */ - TCDATA0 = logtable[brightness]; -} - -void backlight_hw_on(void) -{ - /* configure backlight pin P0.2 as timer PWM output */ - PCON0 = ((PCON0 & ~(3 << 4)) | (2 << 4)); - backlight_hw_brightness(backlight_brightness); -} - -void backlight_hw_off(void) -{ - /* configure backlight pin P0.2 as GPIO and switch off */ - PCON0 = ((PCON0 & ~(3 << 4)) | (1 << 4)); - PDAT0 &= ~(1 << 2); -} - -bool backlight_hw_init(void) -{ - /* enable timer clock */ - PWRCON &= ~(1 << 4); - - /* configure timer */ - TCCMD = (1 << 1); /* TC_CLR */ - TCCON = (0 << 13) | /* TC_INT1_EN */ - (0 << 12) | /* TC_INT0_EN */ - (1 << 11) | /* TC_START */ - (3 << 8) | /* TC_CS = PCLK / 64 */ - (1 << 4); /* TC_MODE_SEL = PWM mode */ - TCDATA1 = 256; /* set PWM period */ - TCPRE = 20; /* prescaler */ - TCCMD = (1 << 0); /* TC_EN */ - - backlight_hw_on(); - - return true; -} - diff --git a/firmware/target/arm/s5l8700/boot.lds b/firmware/target/arm/s5l8700/boot.lds index 4d3c80f1b9..a197ced831 100644 --- a/firmware/target/arm/s5l8700/boot.lds +++ b/firmware/target/arm/s5l8700/boot.lds @@ -24,11 +24,7 @@ STARTUP(target/arm/s5l8700/crt0.o) #define IRAMSIZE 256K #endif -#ifdef MEIZU_M6SL -#define DFULOADADDR IRAMORIG -#else #define DFULOADADDR (IRAMORIG+0x20000) -#endif /* This is not available in all versions of the S5L8700 */ #define FLASHORIG 0x24000000 @@ -41,7 +37,7 @@ MEMORY FLASH : ORIGIN = FLASHORIG, LENGTH = FLASHSIZE } -#if defined(IPOD_NANO2G) || defined(MEIZU_M6SL) +#if defined(IPOD_NANO2G) #define LOAD_AREA IRAM #else #define NEEDS_INTVECT_COPYING diff --git a/firmware/target/arm/s5l8700/crt0.S b/firmware/target/arm/s5l8700/crt0.S index b13d89b7e9..49fa9797dc 100644 --- a/firmware/target/arm/s5l8700/crt0.S +++ b/firmware/target/arm/s5l8700/crt0.S @@ -22,28 +22,6 @@ #include "config.h" #include "cpu.h" -/* Meizu M3 SDRAM settings */ -#ifdef MEIZU_M3 -#define SDR_DSS_SEL_B 1 -#define SDR_DSS_SEL_O 1 -#define SDR_DSS_SEL_C 1 -#define SDR_TIMING 0x6A491D -#define SDR_CONFIG 0x900 -#define SDR_MRS 0x37 -#define SDR_EMRS 0x4000 -#endif - -/* Meizu M6SP SDRAM settings */ -#ifdef MEIZU_M6SP -#define SDR_DSS_SEL_B 5 -#define SDR_DSS_SEL_O 2 -#define SDR_DSS_SEL_C 2 -#define SDR_TIMING 0x6A4965 -#define SDR_CONFIG 0x700 -#define SDR_MRS 0x33 -#define SDR_EMRS 0x4033 -#endif - .section .intvect,"ax",%progbits .global start .global _newstart @@ -276,68 +254,6 @@ start_loc: mov r0, #0 // 0x0 str r0, [r1, #44] // do not enter any power saving mode -#if defined(MEIZU_M6SP) || defined(MEIZU_M3) - /* setup SDRAM for Meizu M6SP */ - ldr r1, =0x38200000 - // configure SDR drive strength and pad settings - mov r0, #SDR_DSS_SEL_B - str r0, [r1, #0x4C] // MIU_DSS_SEL_B - mov r0, #SDR_DSS_SEL_O - str r0, [r1, #0x50] // MIU_DSS_SEL_O - mov r0, #SDR_DSS_SEL_C - str r0, [r1, #0x54] // MIU_DSS_SEL_C - mov r0, #2 - str r0, [r1, #0x60] // SSTL2_PAD_ON - // select SDR mode - ldr r0, [r1, #0x40] - mov r2, #0xFFFDFFFF - and r0, r0, r2 - orr r0, r0, #1 - str r0, [r1, #0x40] // MIUORG - // set controller configuration - mov r0, #SDR_CONFIG - str r0, [r1] // MIUCON - // set SDRAM timing - ldr r0, =SDR_TIMING - str r0, [r1, #0x10] // MIUSDPARA - // set refresh rate - mov r0, #0x1080 - str r0, [r1, #0x08] // MIUAREF - // initialise SDRAM - mov r0, #0x003 - str r0, [r1, #0x04] // MIUCOM = nop - ldr r0, =0x203 - str r0, [r1, #0x04] // MIUCOM = precharge all banks - nop - nop - nop - ldr r0, =0x303 - str r0, [r1, #0x04] // MIUCOM = auto-refresh - nop - nop - nop - nop - str r0, [r1, #0x04] // MIUCOM = auto-refresh - nop - nop - nop - nop - str r0, [r1, #0x04] // MIUCOM = auto-refresh - nop - nop - nop - nop - // set mode register - mov r0, #SDR_MRS - str r0, [r1, #0x0C] // MIUMRS - ldr r0, =0x103 - str r0, [r1, #0x04] // MIUCOM = mode register set - ldr r0, =SDR_EMRS - str r0, [r1, #0x0C] // MIUMRS - ldr r0, =0x103 - str r0, [r1, #0x04] // MIUCOM = mode register set -#endif /* MEIZU_M6SP */ - mov r1, #0x1 mrc 15, 0, r0, c1, c0, 0 bic r0, r0, r1 diff --git a/firmware/target/arm/s5l8700/fmradio-i2c-meizu.c b/firmware/target/arm/s5l8700/fmradio-i2c-meizu.c deleted file mode 100644 index d260a72f8b..0000000000 --- a/firmware/target/arm/s5l8700/fmradio-i2c-meizu.c +++ /dev/null @@ -1,146 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - FM radio i2c interface, allows the radio driver to talk to the tuner chip. - - It is implemented using the generic i2c driver, which does "bit-banged" - I2C with a couple of GPIO pins. - */ - -#include "config.h" - -#include "inttypes.h" -#include "s5l87xx.h" -#include "generic_i2c.h" -#include "fmradio_i2c.h" - -#define I2C_GPIO PDAT3 -#define I2C_GPIO_DIR PCON3 -#define I2C_SCL_PIN 4 -#define I2C_SDA_PIN 2 - -#define SCL_DIR_MASK (0xF<<(4*I2C_SCL_PIN)) -#define SCL_DIR_OUT (1<<(4*I2C_SCL_PIN)) -#define SCL_DIR_IN 0 -#define SDA_DIR_MASK (0xF<<(4*I2C_SDA_PIN)) -#define SDA_DIR_OUT (1<<(4*I2C_SDA_PIN)) -#define SDA_DIR_IN 0 - -static int fm_i2c_bus; - -static void fm_scl_hi(void) -{ - I2C_GPIO |= 1 << I2C_SCL_PIN; -} - -static void fm_scl_lo(void) -{ - I2C_GPIO &= ~(1 << I2C_SCL_PIN); -} - -static void fm_sda_hi(void) -{ - I2C_GPIO |= 1 << I2C_SDA_PIN; -} - -static void fm_sda_lo(void) -{ - I2C_GPIO &= ~(1 << I2C_SDA_PIN); -} - -static void fm_sda_input(void) -{ - I2C_GPIO_DIR = (I2C_GPIO_DIR & ~SDA_DIR_MASK) | SDA_DIR_IN; -} - -static void fm_sda_output(void) -{ - I2C_GPIO_DIR = (I2C_GPIO_DIR & ~SDA_DIR_MASK) | SDA_DIR_OUT; -} - -static void fm_scl_input(void) -{ - I2C_GPIO_DIR = (I2C_GPIO_DIR & ~SCL_DIR_MASK) | SCL_DIR_IN; -} - -static void fm_scl_output(void) -{ - I2C_GPIO_DIR = (I2C_GPIO_DIR & ~SCL_DIR_MASK) | SCL_DIR_OUT; -} - -static int fm_sda(void) -{ - return (I2C_GPIO & (1 << I2C_SDA_PIN)); -} - -static int fm_scl(void) -{ - return (I2C_GPIO & (1 << I2C_SCL_PIN)); -} - -/* simple and crude delay, used for all delays in the generic i2c driver */ -static void fm_delay(void) -{ - volatile int i; - - /* this loop is uncalibrated and could use more sophistication */ - for (i = 0; i < 20; i++) { - } -} - -/* interface towards the generic i2c driver */ -static const struct i2c_interface fm_i2c_interface = { - .scl_hi = fm_scl_hi, - .scl_lo = fm_scl_lo, - .sda_hi = fm_sda_hi, - .sda_lo = fm_sda_lo, - .sda_input = fm_sda_input, - .sda_output = fm_sda_output, - .scl_input = fm_scl_input, - .scl_output = fm_scl_output, - .scl = fm_scl, - .sda = fm_sda, - - .delay_hd_sta = fm_delay, - .delay_hd_dat = fm_delay, - .delay_su_dat = fm_delay, - .delay_su_sto = fm_delay, - .delay_su_sta = fm_delay, - .delay_thigh = fm_delay -}; - -/* initialise i2c for fmradio */ -void fmradio_i2c_init(void) -{ - fm_i2c_bus = i2c_add_node(&fm_i2c_interface); -} - -int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) -{ - return i2c_write_data(fm_i2c_bus, address, -1, buf, count); -} - -int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) -{ - return i2c_read_data(fm_i2c_bus, address, -1, buf, count); -} - diff --git a/firmware/target/arm/s5l8700/ftl-meizu.c b/firmware/target/arm/s5l8700/ftl-meizu.c deleted file mode 100644 index abc30e93b9..0000000000 --- a/firmware/target/arm/s5l8700/ftl-meizu.c +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - #include "config.h" -# include "ftl-target.h" - -uint32_t ftl_init(void) -{ - /* TODO implement */ - return 0; -} - -uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) -{ - /* TODO implement */ - return 0; -} - -uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) -{ - /* TODO implement */ - return 0; -} - -uint32_t ftl_sync(void) -{ - /* TODO implement */ - return 0; -} - diff --git a/firmware/target/arm/s5l8700/meizu-m3/button-m3.c b/firmware/target/arm/s5l8700/meizu-m3/button-m3.c deleted file mode 100644 index 2cbb5b4ffc..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m3/button-m3.c +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include "config.h" - -#include "inttypes.h" -#include "s5l87xx.h" -#include "button-target.h" - -/* Button driver for the meizu M3 - - TODO: implement buttons based on on touch strip events, for example - short touch (select), slide up and down, touching the <> button, etc. - */ - - -void button_init_device(void) -{ - PCON0 &= ~(3 << 10); /* P0.5 hold switch */ - PCON1 &= ~(0xF << 0); /* P1.0 menu button */ - PCON1 &= ~(0xF << 16); /* P1.4 play button */ - PCON3 &= ~(0xF << 12); /* P3.3 <> button */ -} - -int button_read_device(void) -{ - int buttons = 0; - - if (button_hold()) { - return 0; - } - - if ((PDAT1 & (1 << 0)) == 0) { - buttons |= BUTTON_MENU; - } - if ((PDAT1 & (1 << 4)) == 0) { - buttons |= BUTTON_PLAY; - } - if ((PDAT3 & (1 << 3)) == 0) { - buttons |= BUTTON_PREVNEXT; - } - - return buttons; -} - -bool button_hold(void) -{ - return ((PDAT0 & (1 << 5)) != 0); -} - diff --git a/firmware/target/arm/s5l8700/meizu-m3/button-target.h b/firmware/target/arm/s5l8700/meizu-m3/button-target.h deleted file mode 100644 index c438628cc9..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m3/button-target.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define HAS_BUTTON_HOLD - -/* Meizu M3 specific button codes */ -#define BUTTON_PREVNEXT 0x00000001 -#define BUTTON_MENU 0x00000002 -#define BUTTON_PLAY 0x00000004 - -#define BUTTON_MAIN (BUTTON_PREVNEXT|BUTTON_MENU|BUTTON_PLAY) - -#define POWEROFF_BUTTON BUTTON_PLAY -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ - diff --git a/firmware/target/arm/s5l8700/meizu-m3/ftl-target.h b/firmware/target/arm/s5l8700/meizu-m3/ftl-target.h deleted file mode 100644 index ad4dc04db1..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m3/ftl-target.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __FTL_TARGET_H__ -#define __FTL_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - -#ifdef BOOTLOADER -/* Bootloaders don't need write access */ -#define FTL_READONLY -#endif - -/* Pointer to an info structure regarding the flash type used */ -const struct nand_device_info_type* ftl_nand_type; - -/* Number of banks we detected a chip on */ -uint32_t ftl_banks; - -uint32_t ftl_init(void); -uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer); -uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer); -uint32_t ftl_sync(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m3/lcd-m3.c b/firmware/target/arm/s5l8700/meizu-m3/lcd-m3.c deleted file mode 100644 index 1fbdc5bd0c..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m3/lcd-m3.c +++ /dev/null @@ -1,321 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Denes Balatoni - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" - -#include "hwcompat.h" -#include "kernel.h" -#include "lcd.h" -#include "system.h" -#include "cpu.h" -#include "inttypes.h" -#include "s5l87xx.h" - -/*** definitions ***/ -#define STAT_BUS_IDLE (1<<8) /* Data bus idle */ -#define STAT_FULL (1<<4) /* FIFO full */ -#define STAT_READON (1<<0) /* Read operation done */ - -/** globals **/ -static uint8_t lcd_type; -static int xoffset; /* needed for flip */ - -/*** hardware configuration ***/ - -int lcd_default_contrast(void) -{ - return 0x1f; -} - -void lcd_set_contrast(int val) -{ -} - -void lcd_set_invert_display(bool yesno) -{ -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ - /* TODO: flip mode isn't working. The commands in the else part of - this function are how the original firmware inits the LCD */ - - if (yesno) - { - xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 128 we have */ - } - else - { - xoffset = 0; - } -} - -static void lcd_sleep(uint32_t t) -{ - volatile uint32_t i; - for(i=0;i> 8; - while (LCD_STATUS & STAT_FULL); - LCD_WCMD = reg & 0xff; - while (LCD_STATUS & STAT_FULL); - LCD_WDATA = data >> 8; - while (LCD_STATUS & STAT_FULL); - LCD_WDATA = data & 0xff; -} - -void lcd_on(void) { - if (lcd_type == 1) { - LCD_WCMD = 0x29; - } else { - lcd_writereg(0x7, 0x21); - lcd_writereg(0x12, 0x137); - lcd_sleep(70000); - lcd_writereg(0x7, 0x21); - lcd_writereg(0x12, 0x1137); - lcd_sleep(700000); - lcd_writereg(0x7, 0x233); - } -} - -void lcd_off(void) { - /* FIXME wait for DMA to finnish */ - if (lcd_type == 1) { - LCD_WCMD = 0x28; - LCD_WDATA = 0; - } else { - - } -} - -/* LCD init */ -void lcd_init_device(void) -{ - uint8_t data[5]; - int i; - -/* init basic things */ - PWRCON &= ~0x800; - PCON_ASRAM = 0x2; - PCON7 = 0x12222233; - - LCD_CON = 0xca0; - LCD_PHTIME = 0; - LCD_INTCON = 0; - LCD_RST_TIME = 0x7ff; - -/* detect lcd type, it's not detected the first time for some reason */ - for(i=0;i<3;++i) { - LCD_WCMD = 0x1; - lcd_sleep(166670); - LCD_WCMD = 0x11; - lcd_sleep(2000040); - lcd_readdata(); - LCD_WCMD = 0x4; - lcd_sleep(100); - data[0]=lcd_readdata(); - data[1]=lcd_readdata(); - data[2]=lcd_readdata(); - data[3]=lcd_readdata(); - data[4]=lcd_readdata(); - - lcd_type=0; - if (((data[1]==0x38) && ((data[2] & 0xf0) == 0x80)) || - ((data[2]==0x38) && ((data[3] & 0xf0) == 0x80))) - lcd_type=1; - } -/* init lcd */ - if (lcd_type == 1) { - LCD_WCMD = 0x3a; - LCD_WDATA = 0x6; - LCD_WCMD = 0xab; - LCD_WCMD = 0x35; - LCD_WDATA = 0; - LCD_WCMD=0x13; - LCD_WCMD = 0x2a; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WCMD = 0x2b; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WCMD = 0x29; - } else { - LCD_WCMD = 0x0; - LCD_WCMD = 0x0; - LCD_WCMD = 0x0; - LCD_WCMD = 0x0; - lcd_sleep(700000); - lcd_writereg(0xa4, 0x1); - lcd_sleep(1100000); - lcd_writereg(0x1, 0x100); - lcd_writereg(0x2, 0x300); - lcd_writereg(0x3, 0x9230); - lcd_writereg(0x8, 0x404); - lcd_writereg(0xe, 0x10); - lcd_writereg(0x70, 0x1000); - lcd_writereg(0x71, 0x1); - lcd_writereg(0x30, 0x2); - lcd_writereg(0x31, 0x400); - lcd_writereg(0x32, 0x7); - lcd_writereg(0x33, 0x500); - lcd_writereg(0x34, 0x7); - lcd_writereg(0x35, 0x703); - lcd_writereg(0x36, 0x507); - lcd_writereg(0x37, 0x5); - lcd_writereg(0x38, 0x1404); - lcd_writereg(0x39, 0xe); - lcd_writereg(0x40, 0x202); - lcd_writereg(0x41, 0x3); - lcd_writereg(0x42, 0x0); - lcd_writereg(0x43, 0x200); - lcd_writereg(0x44, 0x707); - lcd_writereg(0x45, 0x407); - lcd_writereg(0x46, 0x505); - lcd_writereg(0x47, 0x2); - lcd_writereg(0x48, 0x4); - lcd_writereg(0x49, 0x4); - lcd_writereg(0x60, 0x202); - lcd_writereg(0x61, 0x3); - lcd_writereg(0x62, 0x0); - lcd_writereg(0x63, 0x200); - lcd_writereg(0x64, 0x707); - lcd_writereg(0x65, 0x407); - lcd_writereg(0x66, 0x505); - lcd_writereg(0x67, 0x2); - lcd_writereg(0x68, 0x4); - lcd_writereg(0x69, 0x4); - lcd_writereg(0x7, 0x1); - lcd_writereg(0x18, 0x1); - lcd_writereg(0x10, 0x1690); - lcd_writereg(0x11, 0x100); - lcd_writereg(0x12, 0x117); - lcd_writereg(0x13, 0xf80); - lcd_writereg(0x12, 0x137); - lcd_writereg(0x20, 0x0); - lcd_writereg(0x21, 0x0); - lcd_writereg(0x50, 0x0); - lcd_writereg(0x51, 0xaf); - lcd_writereg(0x52, 0x0); - lcd_writereg(0x53, 0x83); - lcd_writereg(0x90, 0x0); - lcd_writereg(0x91, 0x0); - lcd_writereg(0x92, 0x0); - lcd_writereg(0x98, 0x0); - lcd_writereg(0x99, 0x903); - lcd_writereg(0x9a, 0x502); - lcd_writereg(0x9b, 0x300); - LCD_WCMD = 0x0; - LCD_WCMD = 0x22; - lcd_sleep(700000); - lcd_on(); - } -} - -/*** Update functions ***/ - -/* Performance function that works with an external buffer - note that by and bheight are in 8-pixel units! */ -void lcd_blit_mono(const unsigned char *data, int x, int by, int width, - int bheight, int stride) -{ - /* Copy display bitmap to hardware */ - while (bheight--) - { - } -} - - -/* Performance function that works with an external buffer - note that by and bheight are in 8-pixel units! */ -void lcd_blit_grey_phase_blit(unsigned char *values, unsigned char *phases, - int x, int by, int width, int bheight, int stride) -{ - (void)values; - (void)phases; - (void)x; - (void)by; - (void)width; - (void)bheight; - (void)stride; -} - -/* Update the display. - This must be called after all other LCD functions that change the display. */ -void lcd_update(void) ICODE_ATTR; -void lcd_update(void) -{ - int i; - fb_data *p; - - /* Copy display bitmap to hardware */ - if (lcd_type == 1) { - LCD_WCMD = 0x2a; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WDATA = 0xaf; - LCD_WCMD = 0x2b; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WDATA = 0; - LCD_WDATA = 0x83; - LCD_WCMD = 0x2c; - } else { - lcd_writereg(0x20, 0x0); - lcd_writereg(0x21, 0x0); - LCD_WCMD = 0; - LCD_WCMD = 0x22; - } - for(p=FBADDR(0,0), i=0;i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __NAND_TARGET_H__ -#define __NAND_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - - -struct nand_device_info_type -{ - uint32_t id; - uint16_t blocks; - uint16_t userblocks; - uint16_t pagesperblock; - uint8_t blocksizeexponent; - uint8_t tunk1; - uint8_t twp; - uint8_t tunk2; - uint8_t tunk3; -} __attribute__((packed)); - -uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc, - uint32_t checkempty); -uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc); -uint32_t nand_block_erase(uint32_t bank, uint32_t page); - -const struct nand_device_info_type* nand_get_device_type(uint32_t bank); -uint32_t nand_reset(uint32_t bank); -uint32_t nand_device_init(void); -void nand_set_active(void); -long nand_last_activity(void); -void nand_power_up(void); -void nand_power_down(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m3/powermgmt-m3.c b/firmware/target/arm/s5l8700/meizu-m3/powermgmt-m3.c deleted file mode 100644 index 32426f53f6..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m3/powermgmt-m3.c +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright © 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "adc.h" -#include "adc-target.h" -#include "powermgmt.h" - -/* Battery voltage calculation and discharge/charge curves for the Meizu M3. - - Battery voltage is calculated under the assumption that the adc full-scale - readout represents 3.00V and that the battery ADC channel is fed with - exactly half of the battery voltage (through a resistive divider). - Discharge and charge curves have not been calibrated yet. -*/ - -unsigned short battery_level_disksafe = 3400; /* TODO: this is just an initial guess */ - -unsigned short battery_level_shutoff = 3300; /* TODO: this is just an initial guess */ - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ - /* TODO: simple uncalibrated curve, linear except for first 10% */ - 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = - /* TODO: simple uncalibrated curve, linear except for first 10% */ - { 3300, 3600, 3665, 3730, 3795, 3860, 3925, 3990, 4055, 4120, 4185 }; - -/* full-scale ADC readout (2^10) in millivolt */ -#define BATTERY_SCALE_FACTOR 6000 - -/* Returns battery voltage from ADC [millivolts] */ -int _battery_voltage(void) -{ - return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; -} - diff --git a/firmware/target/arm/s5l8700/meizu-m6sl/button-target.h b/firmware/target/arm/s5l8700/meizu-m6sl/button-target.h deleted file mode 100644 index 022a0b61f1..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sl/button-target.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define HAS_BUTTON_HOLD - -/* Toshiba Gigabeat specific button codes */ - -#define BUTTON_LEFT 0x00000001 -#define BUTTON_RIGHT 0x00000002 -#define BUTTON_UP 0x00000004 -#define BUTTON_DOWN 0x00000008 - -#define BUTTON_SELECT 0x00000010 - -#define BUTTON_MENU 0x00000020 -#define BUTTON_PLAY 0x00000040 - - -#define BUTTON_MAIN (BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT\ - |BUTTON_UP|BUTTON_DOWN|BUTTON_SELECT|BUTTON_PLAY) - -#define POWEROFF_BUTTON BUTTON_PLAY -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/s5l8700/meizu-m6sl/ftl-target.h b/firmware/target/arm/s5l8700/meizu-m6sl/ftl-target.h deleted file mode 100644 index ad4dc04db1..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sl/ftl-target.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __FTL_TARGET_H__ -#define __FTL_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - -#ifdef BOOTLOADER -/* Bootloaders don't need write access */ -#define FTL_READONLY -#endif - -/* Pointer to an info structure regarding the flash type used */ -const struct nand_device_info_type* ftl_nand_type; - -/* Number of banks we detected a chip on */ -uint32_t ftl_banks; - -uint32_t ftl_init(void); -uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer); -uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer); -uint32_t ftl_sync(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c b/firmware/target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c deleted file mode 100644 index e6e14b5e57..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sl/lcd-m6sl.c +++ /dev/null @@ -1,321 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2002 by Alan Korr - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" - -#include "hwcompat.h" -#include "kernel.h" -#include "lcd.h" -#include "system.h" -#include "cpu.h" -#include "s6d0154.h" - -/*** definitions ***/ - - -#define SPIDELAY(_x) void(_x); - -#define SETMOSI() (PDAT4 |= (1 << 3)) -#define CLRMOSI() (PDAT4 &= ~(1 << 3)) - -#define MISO ((PDAT1 >> 1) & 1) - -#define SETCLK() (PDAT4 |= (1 << 2)) -#define CLRCLK() (PDAT4 &= ~(1 << 2)) - -#define SETSS() (PDAT7 |= (1 << 1)) -#define CLRSS() (PDAT7 &= ~(1 << 1)) - -static unsigned short controller_type = 0; - -void init_lcd_spi(void) -{ - int oldval; - - oldval = PCON1; - //Set P1.1 to input - PCON1 = ((oldval & ~(0xf << 4))); - - oldval = PCON4; - //Set P4.2 and 4.3 to output - PCON4 = ((oldval & ~(0xf << 8 | 0xf << 12)) | (1 << 8 | 1 << 12)); - - oldval = PCON4; - //Set P4.2 and 4.3 to output - PCON4 = ((oldval & ~(0xf << 8 | 0xf << 12)) | (1 << 8 | 1 << 12)); - - oldval = PCON7; - //Set P7.0 and 7.1 to output - PCON7 = ((oldval & ~(0xf << 0 | 0xf << 4)) | (1 << 0 | 1 << 4)); - - SETSS(); - SETCLK(); -} - -static inline void delay(int duration) -{ - volatile int i; - for(i=0;i 22 us - - for (i = 0; i < bits+inskip; i++) { - - CLRCLK(); - - if(i> 6.7 us - - SETCLK(); - - if(i>=inskip) - { - input <<= 1; - input |= MISO; - } - - //delay(20); // >> 6.7 us - } - - SETSS(); - - return (input); -} - -void spi_set_reg(unsigned char reg,unsigned short value) -{ - lcd_spi_io(0x700000|reg,24,0); // possibly 0x74 - lcd_spi_io(0x720000|value,24,0); // possibly 0x77 -} - -unsigned int lcd_read_id(void) -{ - unsigned int device_code; - lcd_spi_io(0x700000,24,0); // possibly 0x74 - - device_code=lcd_spi_io(0x7300,16,24); // possibly 0x77 - return device_code; -} - -/** globals **/ - -static int xoffset; /* needed for flip */ - -/*** hardware configuration ***/ - -int lcd_default_contrast(void) -{ - return 0x1f; -} - -void lcd_set_contrast(int val) -{ -} - -void lcd_set_invert_display(bool yesno) -{ -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ - /* TODO: flip mode isn't working. The commands in the else part of - this function are how the original firmware inits the LCD */ - - if (yesno) - { - xoffset = 132 - LCD_WIDTH; /* 132 colums minus the 128 we have */ - } - else - { - xoffset = 0; - } -} - - - -void lcd_off(void) -{ - switch(controller_type) - { - case 0x0154: - spi_set_reg(S6D0154_REG_DISPLAY_CONTROL, 0x12); - delay(20); - spi_set_reg(S6D0154_REG_DISPLAY_CONTROL, 0x00); - break; - } -} - -void lcd_on(void) -{ - switch(controller_type) - { - case 0x0154: - spi_set_reg(S6D0154_REG_DISPLAY_CONTROL, 0x12); - delay(20); - spi_set_reg(S6D0154_REG_DISPLAY_CONTROL, 0x13); - break; - } -} -/* LCD init */ -void lcd_init_device(void) -{ - init_lcd_spi(); - controller_type = lcd_read_id(); - switch(controller_type) - { - case 0x0154: - spi_set_reg(S6D0154_REG_EXTERNAL_INTERFACE_CONTROL, 0x130); // RGB interface, RGB interface for PNP mode - spi_set_reg(S6D0154_REG_MTP_TEST_KEY, 0x8d); // ?? - spi_set_reg(0x92, 0x10); - /* See also datasheet 11.3 Set up Flow of Generated Power Supply */ - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0x1b); // VC1IEN, 2.76V - spi_set_reg(S6D0154_REG_POWER_CONTROL_3, 0x3101);// VGH=6*VCI1, VGL=-4*VCI1, f(DCCLK):f(DCCLK1)=1:0.5, f(DCCLK) : f(DCCLK3)= 1:0.5 - spi_set_reg(S6D0154_REG_POWER_CONTROL_4, 0x105f);//DCR_EX=1(Use dotclock) - spi_set_reg(S6D0154_REG_POWER_CONTROL_5, 0x667f); - spi_set_reg(S6D0154_REG_POWER_CONTROL_1, 0x800); - delay(20); // >10ms - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0x11b); - delay(20); // >10ms - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0x31b); - delay(20); // >10ms - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0x71b); - delay(20); // >10ms - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0xf1b); - delay(20); // >10ms - spi_set_reg(S6D0154_REG_POWER_CONTROL_2, 0xf3b); - delay(30); // >30ms - spi_set_reg(S6D0154_REG_DRIVER_OUTPUT_CONTROL, 0x2128); - spi_set_reg(S6D0154_REG_LCD_DRIVING_WAVEFORM_CONTROL, 0x100); - spi_set_reg(S6D0154_REG_ENTRY_MODE, 0x1030);//{DB [17:12], DB [11:6], DB [5:0]} is assigned to {B, G, R}. Horizontal first, auto increment address, write from 0x0000 to 0xdbaf - spi_set_reg(S6D0154_REG_DISPLAY_CONTROL, 0); // all off - spi_set_reg(S6D0154_REG_BLANK_PERIOD_CONTROL, 0x808); - spi_set_reg(S6D0154_REG_FRAME_CYCLE_CONTROL, 0x1100); - spi_set_reg(S6D0154_REG_START_OSCILLATION, 0xf01);// Start oscillator, X 1.25 - spi_set_reg(S6D0154_REG_VCI_RECYCLING, 0); - spi_set_reg(S6D0154_REG_GATE_SCAN_POSITION, 0); - /* Set things up to write to the entire screen */ - spi_set_reg(S6D0154_REG_PARTIAL_SCREEN_DRIVING_POSITION_1, 319); // end of partial screen - spi_set_reg(S6D0154_REG_PARTIAL_SCREEN_DRIVING_POSITION_2, 0); // start of partial screen - spi_set_reg(S6D0154_REG_HORIZONTAL_WINDOW_ADDRESS_1, 239); // end of window - spi_set_reg(S6D0154_REG_HORIZONTAL_WINDOW_ADDRESS_2, 0); // start of window - spi_set_reg(S6D0154_REG_VERTICAL_WINDOW_ADDRESS_1, 319); // end of window - spi_set_reg(S6D0154_REG_VERTICAL_WINDOW_ADDRESS_2, 0); // start of window - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_1, 0); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_2, 0xf00); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_3, 0xa03); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_4, 0x300); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_5, 0xc05); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_6, 0xf00); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_7, 0xf00); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_8, 3); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_9, 0x1f07); - spi_set_reg(S6D0154_REG_GAMMA_CONTROL_10, 0x71f); - delay(20); - lcd_on(); - break; - } -} - - -/*** Update functions ***/ - -/* Performance function that works with an external buffer - note that by and bheight are in 8-pixel units! */ -void lcd_blit_mono(const unsigned char *data, int x, int by, int width, - int bheight, int stride) -{ - /* Copy display bitmap to hardware */ - while (bheight--) - { - } -} - - -/* Performance function that works with an external buffer - note that by and bheight are in 8-pixel units! */ -void lcd_blit_grey_phase_blit(unsigned char *values, unsigned char *phases, - int x, int by, int width, int bheight, int stride) -{ - (void)values; - (void)phases; - (void)x; - (void)by; - (void)width; - (void)bheight; - (void)stride; -} - -/* Update the display. - This must be called after all other LCD functions that change the display. */ -void lcd_update(void) ICODE_ATTR; -void lcd_update(void) -{ - int y; - - /* Copy display bitmap to hardware */ - for (y = 0; y < LCD_FBHEIGHT; y++) - { - } -} - -/* Update a fraction of the display. */ -void lcd_update_rect(int, int, int, int) ICODE_ATTR; -void lcd_update_rect(int x, int y, int width, int height) -{ - int ymax; - - /* The Y coordinates have to work on even 8 pixel rows */ - ymax = (y + height-1) >> 3; - y >>= 3; - - if(x + width > LCD_WIDTH) - width = LCD_WIDTH - x; - if (width <= 0) - return; /* nothing left to do, 0 is harmful to lcd_write_data() */ - if(ymax >= LCD_FBHEIGHT) - ymax = LCD_FBHEIGHT-1; - - /* Copy specified rectange bitmap to hardware */ - for (; y <= ymax; y++) - { - } -} diff --git a/firmware/target/arm/s5l8700/meizu-m6sl/nand-target.h b/firmware/target/arm/s5l8700/meizu-m6sl/nand-target.h deleted file mode 100644 index dee690e5e6..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sl/nand-target.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __NAND_TARGET_H__ -#define __NAND_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - - -struct nand_device_info_type -{ - uint32_t id; - uint16_t blocks; - uint16_t userblocks; - uint16_t pagesperblock; - uint8_t blocksizeexponent; - uint8_t tunk1; - uint8_t twp; - uint8_t tunk2; - uint8_t tunk3; -} __attribute__((packed)); - -uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc, - uint32_t checkempty); -uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc); -uint32_t nand_block_erase(uint32_t bank, uint32_t page); - -const struct nand_device_info_type* nand_get_device_type(uint32_t bank); -uint32_t nand_reset(uint32_t bank); -uint32_t nand_device_init(void); -void nand_set_active(void); -long nand_last_activity(void); -void nand_power_up(void); -void nand_power_down(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m6sl/s6d0154.h b/firmware/target/arm/s5l8700/meizu-m6sl/s6d0154.h deleted file mode 100644 index 70d312ed6d..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sl/s6d0154.h +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Frank Gevaerts - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _S6D0154_H_ -#define _S6D0154_H_ - -#define S6D0154_REG_VERSION 0x00 -#define S6D0154_REG_DRIVER_OUTPUT_CONTROL 0x01 -#define S6D0154_REG_LCD_DRIVING_WAVEFORM_CONTROL 0x02 -#define S6D0154_REG_ENTRY_MODE 0x03 -#define S6D0154_REG_DISPLAY_CONTROL 0x07 -#define S6D0154_REG_BLANK_PERIOD_CONTROL 0x08 -#define S6D0154_REG_FRAME_CYCLE_CONTROL 0x0B -#define S6D0154_REG_EXTERNAL_INTERFACE_CONTROL 0x0C -#define S6D0154_REG_START_OSCILLATION 0x0F -#define S6D0154_REG_POWER_CONTROL_1 0x10 -#define S6D0154_REG_POWER_CONTROL_2 0x11 -#define S6D0154_REG_POWER_CONTROL_3 0x12 -#define S6D0154_REG_POWER_CONTROL_4 0x13 -#define S6D0154_REG_POWER_CONTROL_5 0x14 -#define S6D0154_REG_VCI_RECYCLING 0x15 -#define S6D0154_REG_RAM_ADDRESS_REGISTER_1 0x20 -#define S6D0154_REG_RAM_ADDRESS_REGISTER_2 0x21 -#define S6D0154_REG_GRAM_READ_WRITE 0x22 -#define S6D0154_REG_RESET 0x28 -#define S6D0154_REG_FLM_FUNCTION 0x29 -#define S6D0154_REG_GATE_SCAN_POSITION 0x30 -#define S6D0154_REG_VERTICAL_SCROLL_CONTROL_1A 0x31 -#define S6D0154_REG_VERTICAL_SCROLL_CONTROL_1B 0x32 -#define S6D0154_REG_VERTICAL_SCROLL_CONTROL_2 0x33 -#define S6D0154_REG_PARTIAL_SCREEN_DRIVING_POSITION_1 0x34 -#define S6D0154_REG_PARTIAL_SCREEN_DRIVING_POSITION_2 0x35 -#define S6D0154_REG_HORIZONTAL_WINDOW_ADDRESS_1 0x36 -#define S6D0154_REG_HORIZONTAL_WINDOW_ADDRESS_2 0x37 -#define S6D0154_REG_VERTICAL_WINDOW_ADDRESS_1 0x38 -#define S6D0154_REG_VERTICAL_WINDOW_ADDRESS_2 0x39 -#define S6D0154_REG_SUB_PANEL_CONTROL 0x40 -#define S6D0154_REG_MDDI_LINK_WAKEUP_START_POSITION 0x41 -#define S6D0154_REG_SUB_PANEL_SELECTION_INDEX 0x42 -#define S6D0154_REG_SUB_PANEL_DATA_WRITE_INDEX 0x43 -#define S6D0154_REG_GPIO_VALUE 0x44 -#define S6D0154_REG_GPIO_IO_CONTROL 0x45 -#define S6D0154_REG_GPIO_CLEAR 0x46 -#define S6D0154_REG_GPIO_INTERRUPT_ENABLE 0x47 -#define S6D0154_REG_GPIO_POLARITY_SELECTION 0x48 - -#define S6D0154_REG_GAMMA_CONTROL_1 0x50 -#define S6D0154_REG_GAMMA_CONTROL_2 0x51 -#define S6D0154_REG_GAMMA_CONTROL_3 0x52 -#define S6D0154_REG_GAMMA_CONTROL_4 0x53 -#define S6D0154_REG_GAMMA_CONTROL_5 0x54 -#define S6D0154_REG_GAMMA_CONTROL_6 0x55 -#define S6D0154_REG_GAMMA_CONTROL_7 0x56 -#define S6D0154_REG_GAMMA_CONTROL_8 0x57 -#define S6D0154_REG_GAMMA_CONTROL_9 0x58 -#define S6D0154_REG_GAMMA_CONTROL_10 0x59 - -#define S6D0154_REG_MTP_TEST_KEY 0x80 -#define S6D0154_REG_MTP_CONTROL_REGISTERS 0x81 -#define S6D0154_REG_MTP_DATA_READ_WRITE 0x82 -#define S6D0154_REG_PRODUCT_NAME_VERSION_WRITE 0x83 - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/button-m6sp.c b/firmware/target/arm/s5l8700/meizu-m6sp/button-m6sp.c deleted file mode 100644 index 5373179208..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/button-m6sp.c +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include "config.h" - -#include "inttypes.h" -#include "s5l87xx.h" -#include "button-target.h" - -/* Button driver for the meizu M6SP - - Future improvements: - * touch strip support - * left/right buttons (probably read out with ADC0) - * unify with m3/m6sl button driver if possible - - */ - - -void button_init_device(void) -{ - PCON0 &= ~(0x3 << 10); /* P0.5 hold switch */ - PCON0 &= ~(0x3 << 14); /* P0.7 enter button */ - PCON1 &= ~(0xF << 16); /* P1.4 play/power button */ -} - -int button_read_device(void) -{ - int buttons = 0; - - if (button_hold()) { - return 0; - } - - if ((PDAT1 & (1 << 4)) == 0) { - buttons |= BUTTON_PLAY; - } - if ((PDAT0 & (1 << 7)) == 0) { - buttons |= BUTTON_ENTER; - } - - return buttons; -} - -bool button_hold(void) -{ - return ((PDAT0 & (1 << 5)) != 0); -} - diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/button-target.h b/firmware/target/arm/s5l8700/meizu-m6sp/button-target.h deleted file mode 100644 index 58d19d177c..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/button-target.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define HAS_BUTTON_HOLD - -/* Meizu M6 specific button codes */ - -#define BUTTON_LEFT 0x00000001 -#define BUTTON_RIGHT 0x00000002 -#define BUTTON_PLAY 0x00000004 -#define BUTTON_MENU 0x00000008 -#define BUTTON_SELECT 0x00000010 /* TODO: tap on the touch strip */ -#define BUTTON_ENTER 0x00000020 - - -#define BUTTON_MAIN (BUTTON_LEFT|BUTTON_RIGHT|BUTTON_PLAY|BUTTON_MENU\ - |BUTTON_SELECT|BUTTON_ENTER) - -#define POWEROFF_BUTTON BUTTON_PLAY -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/ftl-target.h b/firmware/target/arm/s5l8700/meizu-m6sp/ftl-target.h deleted file mode 100644 index ad4dc04db1..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/ftl-target.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __FTL_TARGET_H__ -#define __FTL_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - -#ifdef BOOTLOADER -/* Bootloaders don't need write access */ -#define FTL_READONLY -#endif - -/* Pointer to an info structure regarding the flash type used */ -const struct nand_device_info_type* ftl_nand_type; - -/* Number of banks we detected a chip on */ -uint32_t ftl_banks; - -uint32_t ftl_init(void); -uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer); -uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer); -uint32_t ftl_sync(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c b/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c deleted file mode 100644 index 622408a4d4..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/lcd-m6sp.c +++ /dev/null @@ -1,494 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include - -#include "config.h" -#include "s5l87xx.h" -#include "lcd.h" - -/* LCD driver for the Meizu M6 SP using the CLCD controller in the S5L8700 - - The Meizu M6 SP can have two different LCDs, the S6D0139 and another - (yet unknown) type, the exact type is detected at run-time. - - Open issues: - * LCD is currently in portrait mode instead of landscape mode - * This LCD driver accesses the Rockbox framebuffer directly, so any changes - to the framebuffer as shown directly even before lcd_update is called. - * Sometimes part of the top of the screen appears at the bottom - * The Meizu seems to hang after LCD initialisation - * The driver for the S6D0139 LCD has not been tested yet - - */ - -/* LCD SPI connections */ -#define LCD_SPI_SSn (1<<1) /* on PDAT7 */ -#define LCD_SPI_MISO (1<<2) /* on PDAT3 */ -#define LCD_SPI_MOSI (1<<6) /* on PDAT3 */ -#define LCD_SPI_SCLK (1<<7) /* on PDAT3 */ - -/* LCD SPI communication definitions */ -#define LCD_SPI_DEVICE_ID (0x1D<<2) -#define LCD_SPI_INDEX_WRITE (LCD_SPI_DEVICE_ID|0) -#define LCD_SPI_STATUS_READ (LCD_SPI_DEVICE_ID|1) -#define LCD_SPI_DATA_WRITE (LCD_SPI_DEVICE_ID|2) -#define LCD_SPI_DATA_READ (LCD_SPI_DEVICE_ID|3) - -#define LCD_TYPE1_ID 0x139 /* id for LCD type S6D0139 */ - -static int lcd_type = 0; -static bool lcd_is_active = false; - -/* simple and crude delay */ -static void lcd_delay(int count) -{ - volatile int i; - for (i = 0; i < count; i++); -} - -/* write 'data_out' of length 'bits' over SPI and return received data */ -static unsigned int lcd_spi_transfer(int bits, unsigned int data_out) -{ - unsigned int data_in = 0; - - /* SSn active */ - PDAT7 &= ~LCD_SPI_SSn; - lcd_delay(10); - - /* send and receive data */ - while (bits--) { - /* CLK low */ - PDAT3 &= ~LCD_SPI_SCLK; - - /* set MOSI */ - if (data_out & (1 << bits)) { - PDAT3 |= LCD_SPI_MOSI; - } - else { - PDAT3 &= ~LCD_SPI_MOSI; - } - - /* delay */ - lcd_delay(10); - - /* sample MISO */ - data_in <<= 1; - if (PDAT3 & LCD_SPI_MISO) { - data_in |= 1; - } - - /* CLK high */ - PDAT3 |= LCD_SPI_SCLK; - - /* delay */ - lcd_delay(10); - } - - /* SSn inactive */ - PDAT7 |= LCD_SPI_SSn; - lcd_delay(10); - - return data_in; -} - -/* initialize the lcd SPI port interface */ -static void lcd_spi_init(void) -{ - /* configure SSn (P7.1) as output */ - PCON7 = (PCON7 & ~0x000000F0) | 0x00000010; - - /* configure MISO (P3.2) input, MOSI (P3.6) output, SCLK (P3.7) output */ - PCON3 = (PCON3 & ~0xFF000F00) | 0x11000000; - - /* set all outputs high */ - PDAT7 |= LCD_SPI_SSn; - PDAT3 |= (LCD_SPI_MOSI | LCD_SPI_SCLK); -} - -/* read LCD identification word over SPI */ -static unsigned int lcd_read_reg(unsigned reg) -{ - unsigned int data; - - lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg); - data = lcd_spi_transfer(24, (LCD_SPI_DATA_READ << 16)); - return data & 0xFFFF; -} - -/* write LCD register over SPI */ -static void lcd_write_reg(unsigned char reg, unsigned int data) -{ - lcd_spi_transfer(24, (LCD_SPI_INDEX_WRITE << 16) | reg); - lcd_spi_transfer(24, (LCD_SPI_DATA_WRITE << 16) | data); -} - -/* enable/disable clock signals towards the lcd */ -static void lcd_controller_power(bool on) -{ - if (on) { - LCDCON1 |= 0x80003; - } - else { - LCDCON1 &= ~0x80003; - } -} - -/* lcd init configuration for lcd type 1 */ -static void lcd_init1(void) -{ - lcd_write_reg(0x07, 0x0000); /* display control */ - lcd_write_reg(0x13, 0x0000); /* power control 3 */ - lcd_delay(166670); - - lcd_write_reg(0x11, 0x3304); /* power control 2 */ - lcd_write_reg(0x14, 0x1300); /* power control 4 */ - lcd_write_reg(0x10, 0x1A20); /* power control 1 */ - lcd_write_reg(0x13, 0x0040); /* power control 3 */ - lcd_delay(833350); - - lcd_write_reg(0x13, 0x0060); /* power control 3 */ - lcd_write_reg(0x13, 0x0070); /* power control 3 */ - lcd_delay(3333400); - - lcd_write_reg(0x01, 0x0127); /* driver output control */ - lcd_write_reg(0x02, 0x0700); /* lcd driving waveform control */ - lcd_write_reg(0x03, 0x1030); /* entry mode */ - lcd_write_reg(0x08, 0x0208); /* blank period control 1 */ - lcd_write_reg(0x0B, 0x0620); /* frame cycle control */ - lcd_write_reg(0x0C, 0x0110); /* external interface control */ - lcd_write_reg(0x30, 0x0120); /* gamma control 1 */ - lcd_write_reg(0x31, 0x0117); /* gamma control 2 */ - lcd_write_reg(0x32, 0x0000); /* gamma control 3 */ - lcd_write_reg(0x33, 0x0305); /* gamma control 4 */ - lcd_write_reg(0x34, 0x0717); /* gamma control 5 */ - lcd_write_reg(0x35, 0x0124); /* gamma control 6 */ - lcd_write_reg(0x36, 0x0706); /* gamma control 7 */ - lcd_write_reg(0x37, 0x0503); /* gamma control 8 */ - lcd_write_reg(0x38, 0x1F03); /* gamma control 9 */ - lcd_write_reg(0x39, 0x0009); /* gamma control 10 */ - lcd_write_reg(0x40, 0x0000); /* gate scan position */ - lcd_write_reg(0x41, 0x0000); /* vertical scroll control */ - lcd_write_reg(0x42, 0x013F); /* 1st screen driving position (end) */ - lcd_write_reg(0x43, 0x0000); /* 1st screen driving position (start) */ - lcd_write_reg(0x44, 0x013F); /* 2nd screen driving position (end) */ - lcd_write_reg(0x45, 0x0000); /* 2nd screen driving position (start) */ - lcd_write_reg(0x46, 0xEF00); /* horizontal window address */ - lcd_write_reg(0x47, 0x013F); /* vertical window address (end) */ - lcd_write_reg(0x48, 0x0000); /* vertical window address (start) */ - - lcd_write_reg(0x07, 0x0015); /* display control */ - lcd_delay(500000); - lcd_write_reg(0x07, 0x0017); /* display control */ - - lcd_write_reg(0x20, 0x0000); /* RAM address set (low part) */ - lcd_write_reg(0x21, 0x0000); /* RAM address set (high part) */ - lcd_write_reg(0x22, 0x0000); /* write data to GRAM */ -} - -/* lcd init configuration for lcd type 2 */ -static void lcd_init2(void) -{ - lcd_write_reg(0x07, 0x0000); - lcd_write_reg(0x12, 0x0000); - lcd_delay(166670); - - lcd_write_reg(0x11, 0x000C); - lcd_write_reg(0x12, 0x0A1C); - lcd_write_reg(0x13, 0x0022); - lcd_write_reg(0x14, 0x0000); - - lcd_write_reg(0x10, 0x7404); - lcd_write_reg(0x11, 0x0738); - lcd_write_reg(0x10, 0x7404); - lcd_delay(833350); - - lcd_write_reg(0x07, 0x0009); - lcd_write_reg(0x12, 0x065C); - lcd_delay(3333400); - - lcd_write_reg(0x01, 0xE127); - lcd_write_reg(0x02, 0x0300); - lcd_write_reg(0x03, 0x1100); - lcd_write_reg(0x08, 0x0008); - lcd_write_reg(0x0B, 0x0000); - lcd_write_reg(0x0C, 0x0000); - lcd_write_reg(0x0D, 0x0007); - lcd_write_reg(0x15, 0x0003); - lcd_write_reg(0x16, 0x0014); - lcd_write_reg(0x17, 0x0000); - - lcd_write_reg(0x30, 0x0503); /* gamma? */ - lcd_write_reg(0x31, 0x0303); - lcd_write_reg(0x32, 0x0305); - lcd_write_reg(0x33, 0x0202); - lcd_write_reg(0x34, 0x0204); - lcd_write_reg(0x35, 0x0404); - lcd_write_reg(0x36, 0x0402); - lcd_write_reg(0x37, 0x0202); - lcd_write_reg(0x38, 0x1000); - lcd_write_reg(0x39, 0x1000); - - lcd_write_reg(0x07, 0x0009); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x0109); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x010B); -} - -/* lcd enable for lcd type 1 */ -static void lcd_enable1(bool on) -{ - if (on) { - lcd_write_reg(0x00, 0x0001); /* start oscillation */ - lcd_delay(166670); - lcd_write_reg(0x10, 0x0000); /* power control 1 */ - lcd_delay(166670); - - lcd_write_reg(0x11, 0x3304); /* power control 2 */ - lcd_write_reg(0x14, 0x1300); /* power control 4 */ - lcd_write_reg(0x10, 0x1A20); /* power control 1 */ - lcd_write_reg(0x07, 0x0015); /* display control */ - lcd_delay(500000); - - lcd_write_reg(0x20, 0x0000); /* RAM address set (low part) */ - lcd_write_reg(0x21, 0x0000); /* RAM address set (high part) */ - lcd_write_reg(0x22, 0x0000); /* write data to GRAM */ - } - else { - lcd_write_reg(0x07, 0x0016); /* display control */ - lcd_delay(166670 * 4); - lcd_write_reg(0x07, 0x0004); /* display control */ - lcd_delay(166670 * 4); - - lcd_write_reg(0x10, 0x1E21); /* power control 1 */ - lcd_delay(166670); - } -} - -/* lcd enable for lcd type 2 */ -static void lcd_enable2(bool on) -{ - if (on) { - lcd_write_reg(0x10, 0x0400); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x0000); - lcd_write_reg(0x12, 0x0000); - lcd_delay(166670); - - lcd_write_reg(0x11, 0x000C); - lcd_write_reg(0x12, 0x0A1C); - lcd_write_reg(0x13, 0x0022); - lcd_write_reg(0x14, 0x0000); - lcd_write_reg(0x10, 0x7404); - lcd_write_reg(0x11, 0x0738); - lcd_write_reg(0x10, 0x7404); - lcd_delay(833350); - - lcd_write_reg(0x07, 0x0009); - lcd_write_reg(0x12, 0x065C); - lcd_delay(3333400); - - lcd_write_reg(0x0B, 0x0000); - lcd_write_reg(0x07, 0x0009); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x0109); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x010B); - } - else { - lcd_write_reg(0x0B, 0x0109); - lcd_write_reg(0x07, 0x0009); - lcd_delay(666680); - - lcd_write_reg(0x07, 0x0008); - lcd_delay(666680); - - lcd_write_reg(0x10, 0x0400); - lcd_write_reg(0x10, 0x0401); - lcd_delay(166670); - } -} - -/* turn both the lcd controller and the lcd itself on or off */ -void lcd_enable(bool on) -{ - if (on) { - /* enable controller clock */ - PWRCON &= ~(1 << 18); - - lcd_controller_power(true); - lcd_delay(166670); - } - - /* call type specific power function */ - if (lcd_type == 1) { - lcd_enable1(on); - } - else { - lcd_enable2(on); - } - - if (!on) { - lcd_controller_power(false); - - /* disable controller clock */ - PWRCON |= (1 << 18); - } - - lcd_is_active = on; -} - -bool lcd_active(void) -{ - return lcd_is_active; -} - -/* initialise the lcd controller inside the s5l8700 */ -static void lcd_controller_init(void) -{ - PWRCON &= ~(1 << 18); - - LCDCON1 = (0 << 28) | /* BURSTLEN */ - (0 << 19) | /* DIVEN */ - (12 << 13) | /* CLKVAL */ - (1 << 12) | /* CLKDIR, 1=divided clock */ - (0 << 11) | /* CLKSEL, 0=HCLK, 1=PLL */ - (5 << 6) | /* BPPMODEF, 5=rgb565, 7=raw24 */ - (5 << 2) | /* BPPMODEB, 5=rgb565, 7=raw24 */ - (0 << 0); /* ENVID */ - LCDCON2 = (2 << 9) | /* PALFRM, 2=rgb565 palette */ - (1 << 7) | /* IVCLK */ - (1 << 6) | /* IHSYNC */ - (1 << 5) | /* IVSYNC */ - (1 << 3); /* IVDEN */ - LCDTCON1 = (lcd_type == 1) ? 0x070103 : 0x030303; - LCDTCON2 = (lcd_type == 1) ? 0x070103 : 0x030703; - LCDTCON3 = ((LCD_HEIGHT - 1) << 11) | (LCD_WIDTH - 1); - LCDOSD1 = 0; - LCDOSD2 = 0; - LCDOSD3 = 0; - - LCDB1SADDR1 = 0; - LCDB2SADDR1 = 0; - LCDF1SADDR1 = 0; - LCDF2SADDR1 = 0; - LCDB1SADDR2 = 0; - LCDB2SADDR2 = 0; - LCDF1SADDR2 = 0; - LCDF2SADDR2 = 0; - LCDB1SADDR3 = 0; - LCDB2SADDR3 = 0; - LCDF1SADDR3 = 0; - LCDF2SADDR3 = 0; - - LCDKEYCON = 0; - LCDCOLVAL = 0; - LCDBGCON = 0; - LCDFGCON = 0; - LCDDITHMODE = 0; - - LCDINTCON = 0; -} - -void lcd_init_device(void) -{ - unsigned int lcd_id; - uint32_t fb, fb_end, window; - - /* configure LCD SPI pins */ - lcd_spi_init(); - - /* identify display through SPI */ - lcd_id = lcd_read_reg(0); - lcd_type = (lcd_id == LCD_TYPE1_ID) ? 1 : 2; - - /* display specific init sequence */ - if (lcd_type == 1) { - lcd_init1(); - } - else { - lcd_init2(); - } - - /* init LCD controller */ - lcd_controller_init(); - - /* set framebuffer addresses */ - fb = (uint32_t) FBADDR(0,0); - fb_end = (uint32_t) FBADDR(0,LCD_HEIGHT); - window = 2 * LCD_WIDTH; - - LCDB1SADDR1 = fb; - LCDB2SADDR1 = fb; - LCDF1SADDR1 = fb; - LCDF2SADDR1 = fb; - - LCDB1SADDR2 = fb_end; - LCDB2SADDR2 = fb_end; - LCDF1SADDR2 = fb_end; - LCDF2SADDR2 = fb_end; - - LCDB1SADDR3 = window; - LCDB2SADDR3 = window; - LCDF1SADDR3 = window; - LCDF2SADDR3 = window; - - lcd_enable(true); - - /* configure LCD pins */ - PCON_ASRAM = 1; -} - -void lcd_update_rect(int x, int y, int width, int height) -{ - /* not implemented yet, LCD controller accesses framebuffer directly */ - (void) x; - (void) y; - (void) width; - (void) height; -} - -void lcd_update(void) -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - -void lcd_blit_yuv(unsigned char * const src[3], - int src_x, int src_y, int stride, - int x, int y, int width, int height) -{ - (void)src; - (void)src_x; - (void)src_y; - (void)stride; - (void)x; - (void)y; - (void)width; - (void)height; - /* TODO: not implemented yet */ -} - diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/nand-target.h b/firmware/target/arm/s5l8700/meizu-m6sp/nand-target.h deleted file mode 100644 index dee690e5e6..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/nand-target.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __NAND_TARGET_H__ -#define __NAND_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - - -struct nand_device_info_type -{ - uint32_t id; - uint16_t blocks; - uint16_t userblocks; - uint16_t pagesperblock; - uint8_t blocksizeexponent; - uint8_t tunk1; - uint8_t twp; - uint8_t tunk2; - uint8_t tunk3; -} __attribute__((packed)); - -uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc, - uint32_t checkempty); -uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc); -uint32_t nand_block_erase(uint32_t bank, uint32_t page); - -const struct nand_device_info_type* nand_get_device_type(uint32_t bank); -uint32_t nand_reset(uint32_t bank); -uint32_t nand_device_init(void); -void nand_set_active(void); -long nand_last_activity(void); -void nand_power_up(void); -void nand_power_down(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/meizu-m6sp/powermgmt-m6sp.c b/firmware/target/arm/s5l8700/meizu-m6sp/powermgmt-m6sp.c deleted file mode 100644 index 8147d75a37..0000000000 --- a/firmware/target/arm/s5l8700/meizu-m6sp/powermgmt-m6sp.c +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright © 2008 Rafaël Carré - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "powermgmt.h" -#include "adc.h" -#include "adc-target.h" - -unsigned short battery_level_disksafe = 3400;/* TODO: this is just an initial guess */ - -unsigned short battery_level_shutoff = 3300; /* TODO: this is just an initial guess */ - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ - /* TODO: simple uncalibrated curve, linear except for first 10% */ - 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200 -}; - -#if CONFIG_CHARGING -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = -{ - /* TODO: simple uncalibrated curve, linear except for first 10% */ - 3300, 3390, 3480, 3570, 3660, 3750, 3840, 3930, 4020, 4110, 4200 -}; -#endif /* CONFIG_CHARGING */ - -/* ADC should read 0x3ff=6.00V */ -#define BATTERY_SCALE_FACTOR 6000 -/* full-scale ADC readout (2^10) in millivolt */ - - -/* Returns battery voltage from ADC [millivolts] */ -int _battery_voltage(void) -{ - return (adc_read(ADC_BATTERY) * BATTERY_SCALE_FACTOR) >> 10; -} diff --git a/firmware/target/arm/s5l8700/nand-meizu.c b/firmware/target/arm/s5l8700/nand-meizu.c deleted file mode 100644 index 382a147286..0000000000 --- a/firmware/target/arm/s5l8700/nand-meizu.c +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - #include "config.h" - #include "nand-target.h" - -const struct nand_device_info_type* nand_get_device_type(uint32_t bank); - - -uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc, - uint32_t checkempty) -{ - /* TODO implement */ - return 0; -} - -uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, - void* sparebuffer, uint32_t doecc) -{ - /* TODO implement */ - return 0; -} - -uint32_t nand_block_erase(uint32_t bank, uint32_t page) -{ - /* TODO implement */ - return 0; -} - -uint32_t nand_reset(uint32_t bank) -{ - /* TODO implement */ - return 0; -} - -uint32_t nand_device_init(void) -{ - /* TODO implement */ - return 0; -} - -void nand_power_up(void) -{ - /* TODO implement */ -} - -void nand_power_down(void) -{ - /* TODO implement */ -} - -void nand_set_active(void) -{ - /* TODO implement */ -} - -long nand_last_activity(void) -{ - /* TODO implement */ - return 0; -} - diff --git a/firmware/target/arm/s5l8700/power-meizu.c b/firmware/target/arm/s5l8700/power-meizu.c deleted file mode 100644 index 709847e599..0000000000 --- a/firmware/target/arm/s5l8700/power-meizu.c +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright © 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include "config.h" -#include "inttypes.h" -#include "s5l87xx.h" -#include "power.h" - -/* Power handling for S5L8700 based Meizu players - - The M3 and M6 players appear to use the same pins for power, USB detection - and charging status. -*/ - -void power_off(void) -{ - /* take down PWRON_M (P1.3) */ - PDAT1 &= ~(1 << 3); -} - -void power_init(void) -{ - /* configure PWRON_M (P1.3) as output and set it to keep power turned on */ - PCON1 = (PCON1 & ~(0xF << 12)) | (0x1 << 12); - PDAT1 |= (1 << 3); - - /* configure PBSTAT (P1.4) as input */ - PCON1 &= ~(0xF << 16); - - /* configure CHRG (P5.7) as input to monitor charging state */ - PCON5 &= ~(0xF << 28); - - /* enable USB2.0 function controller to allow VBUS monitoring */ - PWRCON &= ~(1 << 15); -} - -#if CONFIG_CHARGING -unsigned int power_input_status(void) -{ - /* check VBUS in the USB2.0 function controller */ - if (USB_TR & (1 << 15)) { - return POWER_INPUT_USB; - } - - return POWER_INPUT_NONE; -} - -bool charging_state(void) -{ - /* CHRG pin goes low when charging */ - return ((PDAT5 & (1 << 7)) == 0); -} -#endif /* CONFIG_CHARGING */ - -#if CONFIG_TUNER -static bool tuner_on = false; - -bool tuner_power(bool status) -{ - if (status != tuner_on) - { - tuner_on = status; - status = !status; - } - - return status; -} - -bool tuner_powered(void) -{ - return tuner_on; /* No debug info */ -} -#endif /* CONFIG_TUNER */ - diff --git a/firmware/target/arm/s5l8700/system-s5l8700.c b/firmware/target/arm/s5l8700/system-s5l8700.c index 226464fb08..c442b74971 100644 --- a/firmware/target/arm/s5l8700/system-s5l8700.c +++ b/firmware/target/arm/s5l8700/system-s5l8700.c @@ -35,12 +35,6 @@ #if defined(IPOD_NANO2G) #define MIUSDPARA_BOOST 0x006A49A5 #define MIUSDPARA_UNBOOST 0x006124D1 -#elif defined(MEIZU_M3) - #define MIUSDPARA_BOOST 0x006A491D - #define MIUSDPARA_UNBOOST 0x0061248D -#elif defined(MEIZU_M6SP) - #define MIUSDPARA_BOOST 0x006A4965 - #define MIUSDPARA_UNBOOST 0x00612491 #endif #define default_interrupt(name) \ diff --git a/firmware/target/arm/s5l8700/udacodec-meizu.c b/firmware/target/arm/s5l8700/udacodec-meizu.c deleted file mode 100644 index e0d4346370..0000000000 --- a/firmware/target/arm/s5l8700/udacodec-meizu.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "kernel.h" -#include "s5l87xx.h" -#include "i2c-s5l8700.h" -#include "uda1380.h" -#include "udacodec.h" - -void udacodec_reset(void) -{ - /* Reset codec using GPIO P5.0 */ - PCON5 = (PCON5 & ~0xF) | 1; - PDAT5 |= (1 << 0); - sleep(HZ/100); - - /* Set codec reset pin inactive */ - PDAT5 &= ~(1 << 0); -} - -int udacodec_write(unsigned char reg, unsigned short value) -{ - unsigned char data[2]; - - data[0] = value >> 8; - data[1] = value & 0xFF; - - return i2c_write(UDA1380_ADDR, reg, 2, data); -} - -int udacodec_write2(unsigned char reg, - unsigned short value1, unsigned short value2) -{ - unsigned char data[4]; - - data[0] = value1 >> 8; - data[1] = value1 & 0xFF; - data[2] = value2 >> 8; - data[3] = value2 & 0xFF; - - return i2c_write(UDA1380_ADDR, reg, 4, data); -} - diff --git a/firmware/target/arm/s5l8700/yps3/backlight-target.h b/firmware/target/arm/s5l8700/yps3/backlight-target.h deleted file mode 100644 index 74ea0aa035..0000000000 --- a/firmware/target/arm/s5l8700/yps3/backlight-target.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H - -bool backlight_hw_init(void); -void backlight_hw_on(void); -void backlight_hw_off(void); -void backlight_hw_brightness(int brightness); - -void buttonlight_hw_on(void); -void buttonlight_hw_off(void); - -#endif /* BACKLIGHT_TARGET_H */ - diff --git a/firmware/target/arm/s5l8700/yps3/backlight-yps3.c b/firmware/target/arm/s5l8700/yps3/backlight-yps3.c deleted file mode 100644 index ae3cc3b0a1..0000000000 --- a/firmware/target/arm/s5l8700/yps3/backlight-yps3.c +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include - -#include "config.h" -#include "backlight.h" -#include "backlight-target.h" -#include "system.h" - -/* - Backlight driver using the PWM mode of a hardware timer. - - The PWM duty cycle depends exponentially on the configured brightness - level. This makes the brightness curve more linear to the human eye. - - The button LEDs are all activated at the same time (even though there - are three individually controllable groups: menu/back, cursor, middle). - */ - -void backlight_hw_brightness(int brightness) -{ - /* pwm = round(16 * 16**(x/16)), where brightness level x = 1..16 */ - static const unsigned int logtable[] = - {19, 23, 27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 256}; - - /* set PWM width */ - TADATA0 = logtable[brightness]; -} - -void backlight_hw_on(void) -{ - /* configure backlight pin P0.0 as timer PWM output */ - PCON0 = ((PCON0 & ~(3 << 0)) | (2 << 0)); - - backlight_hw_brightness(backlight_brightness); -} - -void backlight_hw_off(void) -{ - /* configure backlight pin P0.0 as GPIO and switch off */ - PCON0 = ((PCON0 & ~(3 << 0)) | (1 << 0)); - PDAT0 &= ~(1 << 0); -} - -void buttonlight_hw_on(void) -{ - PDAT3 |= (3 << 2); - PDAT4 |= (1 << 2); -} - -void buttonlight_hw_off(void) -{ - PDAT3 &= ~(3 << 2); - PDAT4 &= ~(1 << 2); -} - -bool backlight_hw_init(void) -{ - /* Enable button LEDs: P3.2 (menu/back), P3.3 (cursor), P4.2 (middle) */ - PCON3 = (PCON3 & ~0x0000FF00) | 0x00001100; - PCON4 = (PCON4 & ~0x00000F00) | 0x00000100; - buttonlight_hw_off(); - - /* enable timer clock */ - PWRCON &= ~(1 << 4); - - /* configure timer */ - TACMD = (1 << 1); /* TA_CLR */ - TACON = (0 << 13) | /* TA_INT1_EN */ - (0 << 12) | /* TA_INT0_EN */ - (1 << 11) | /* TA_START */ - (3 << 8) | /* TA_CS = PCLK / 64 */ - (1 << 4); /* TA_MODE_SEL = PWM mode */ - TADATA1 = 256; /* set PWM period */ - TAPRE = 20; /* prescaler */ - TACMD = (1 << 0); /* TA_EN */ - - backlight_hw_on(); - - return true; -} - diff --git a/firmware/target/arm/s5l8700/yps3/button-target.h b/firmware/target/arm/s5l8700/yps3/button-target.h deleted file mode 100644 index 4b3ffa4a76..0000000000 --- a/firmware/target/arm/s5l8700/yps3/button-target.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define HAS_BUTTON_HOLD - -#define BUTTON_BACK 0x00000001 -#define BUTTON_MENU 0x00000002 -#define BUTTON_UP 0x00000004 -#define BUTTON_DOWN 0x00000008 -#define BUTTON_LEFT 0x00000010 -#define BUTTON_RIGHT 0x00000020 -#define BUTTON_SELECT 0x00000040 -#define BUTTON_POWER 0x00000080 - -#define BUTTON_MAIN (BUTTON_BACK|BUTTON_MENU|BUTTON_UP|BUTTON_DOWN|BUTTON_LEFT|\ - BUTTON_RIGHT|BUTTON_SELECT) - -#define POWEROFF_BUTTON BUTTON_POWER -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/s5l8700/yps3/button-yps3.c b/firmware/target/arm/s5l8700/yps3/button-yps3.c deleted file mode 100644 index 23b71a4675..0000000000 --- a/firmware/target/arm/s5l8700/yps3/button-yps3.c +++ /dev/null @@ -1,156 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include "config.h" - -#include "inttypes.h" -#include "s5l87xx.h" -#include "button.h" -#include "button-target.h" - -/* Button driver for the touch keys on the Samsung YP-S3 - - The exact controller is not known, but it is likely from Melfas. - - The protocol is as follows: - * the communication is done using three signals: DRDY, DCLK and DOUT - * in the idle state these signals are all high. - * when a key is touched or released, the key controller pulls down DRDY - and outputs the first bit of a 20-bit word on its DOUT signal. - * the CPU stores the bit, then acknowledges it by toggling the DCLK signal. - * the key controller prepares the next bit, then toggles its DRDY output, - unless all 20 bits have been transferred (in that case it stays high). - * the 20-bit word contains separate bits for each button, some fixed bits - and a bit indicating the number of keys pressed (modulo 2). - */ - - -void button_init_device(void) -{ - /* P0.5/P1.0 power switch input */ - PCON0 &= ~(3 << 10); - PCON1 &= ~0x0000000F; - - /* P1.3 headphones detect input */ - PCON1 &= ~0x0000F000; - - /* P1.5 DATA, P1.6 DRDY inputs (touch key controller) */ - PCON1 &= ~0x0FF00000; - - /* P3.4 DCLK output (touch key controller) */ - PCON3 = (PCON3 & ~0x000F0000) | 0x00010000; - PDAT3 |= (1 << 4); - - /* P4.3 hold switch input */ - PCON4 &= ~0x0000F000; -} - -/* returns the raw 20-bit word from the touch key controller */ -static int tkey_read(void) -{ - static int value = 0; - int i; - - /* check activity */ - if (PDAT1 & (1 << 6)) { - return value; - } - - /* get key bits */ - value = 0; - for (i = 0; i < 10; i++) { - /* sample bit from falling edge of DRDY */ - while ((PDAT1 & (1 << 6)) != 0); - value <<= 1; - if (PDAT1 & (1 << 5)) { - value |= 1; - } - - /* acknowledge on DCLK */ - PDAT3 &= ~(1 << 4); - - /* sample bit from rising edge of DRDY */ - while ((PDAT1 & (1 << 6)) == 0); - value <<= 1; - if (PDAT1 & (1 << 5)) { - value |= 1; - } - - /* acknowledge on DCLK */ - PDAT3 |= (1 << 4); - } - return value; -} - - -int button_read_device(void) -{ - int buttons = 0; - int tkey_data; - - /* hold switch */ - if (button_hold()) { - return 0; - } - - /* power button */ - if (PDAT1 & (1 << 0)) { - buttons |= BUTTON_POWER; - } - - /* touch keys */ - tkey_data = tkey_read(); - if (tkey_data & (1 << 9)) { - buttons |= BUTTON_BACK; - } - if (tkey_data & (1 << 8)) { - buttons |= BUTTON_UP; - } - if (tkey_data & (1 << 7)) { - buttons |= BUTTON_MENU; - } - if (tkey_data & (1 << 6)) { - buttons |= BUTTON_LEFT; - } - if (tkey_data & (1 << 5)) { - buttons |= BUTTON_SELECT; - } - if (tkey_data & (1 << 4)) { - buttons |= BUTTON_RIGHT; - } - if (tkey_data & (1 << 3)) { - buttons |= BUTTON_DOWN; - } - - return buttons; -} - -bool button_hold(void) -{ - return (PDAT4 & (1 << 3)); -} - -bool headphones_inserted(void) -{ - return ((PDAT1 & (1 << 3)) == 0); -} - diff --git a/firmware/target/arm/s5l8700/yps3/fmradio-i2c-yps3.c b/firmware/target/arm/s5l8700/yps3/fmradio-i2c-yps3.c deleted file mode 100644 index 29261b8265..0000000000 --- a/firmware/target/arm/s5l8700/yps3/fmradio-i2c-yps3.c +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - FM radio i2c interface, allows the radio driver to talk to the tuner chip. - - */ - -#include "config.h" - -#include "i2c-s5l8700.h" -#include "fmradio_i2c.h" - -void fmradio_i2c_init(void) -{ - /* nothing to do */ -} - -int fmradio_i2c_write(unsigned char address, const unsigned char* buf, int count) -{ - return i2c_write(address, -1, count, buf); -} - -int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count) -{ - return i2c_read(address, -1, count, buf); -} - diff --git a/firmware/target/arm/s5l8700/yps3/ftl-target.h b/firmware/target/arm/s5l8700/yps3/ftl-target.h deleted file mode 100644 index cb943e34f2..0000000000 --- a/firmware/target/arm/s5l8700/yps3/ftl-target.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Michael Sparmann - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __FTL_TARGET_H__ -#define __FTL_TARGET_H__ - -#include "config.h" -#include "inttypes.h" - -#ifdef BOOTLOADER -/* Bootloaders don't need write access */ -#define FTL_READONLY -#endif - -uint32_t ftl_init(void); -uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer); -uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer); -uint32_t ftl_sync(void); - - -#endif diff --git a/firmware/target/arm/s5l8700/yps3/lcd-yps3.c b/firmware/target/arm/s5l8700/yps3/lcd-yps3.c deleted file mode 100644 index 2445198c65..0000000000 --- a/firmware/target/arm/s5l8700/yps3/lcd-yps3.c +++ /dev/null @@ -1,337 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" - -#include "s5l87xx.h" -#include "lcd.h" - -/* LCD driver for the Samsung YP-S3 - - It appears that this player can contain two display types. - Detection of the display type is done by looking at the level of pin P0.4. - Currently only display "type 2" has been implemented and tested. - - This driver could use DMA to do the screen updates, but currently writes - the data to the LCD using the processor instead. -*/ - - -static int lcd_type = 0; - - -static void lcd_delay(int delay) -{ - volatile int i; - for (i = 0; i < delay; i++); -} - -static void lcd_reset_delay(void) -{ - lcd_delay(10000); -} - -static void lcd_reset(void) -{ - LCD_CON = 0xDB8; - LCD_PHTIME = 0x22; - LCD_RST_TIME = 0x7FFF; - - lcd_reset_delay(); - LCD_DRV_RST = 0; - lcd_reset_delay(); - LCD_DRV_RST = 1; - lcd_reset_delay(); - LCD_DRV_RST = 0; - lcd_reset_delay(); - LCD_DRV_RST = 1; - - LCD_INTCON = 0; -} - -static void lcd_wcmd(unsigned int cmd) -{ - while ((LCD_STATUS & 0x10) != 0); - LCD_WCMD = cmd; -} - -static void lcd_wdata(unsigned int data) -{ - while ((LCD_STATUS & 0x10) != 0); - LCD_WDATA = data; -} - -static void lcd_wcmd_data(unsigned int cmd, unsigned int data) -{ - lcd_wcmd(cmd); - lcd_wdata(data); -} - -static void lcd_init1(void) -{ - lcd_wcmd(0x11); - lcd_delay(10000); - - lcd_wcmd(0xF0); - lcd_wdata(0x5A); - - lcd_wcmd(0xC0); - lcd_wdata(0x05); - lcd_wdata(0x01); - - lcd_wcmd(0xC1); - lcd_wdata(0x04); - - lcd_wcmd(0xC5); - lcd_wdata(0xB0); - - lcd_wcmd(0xC6); - lcd_wdata(0x0); - - lcd_wcmd(0xB1); - lcd_wdata(0x02); - lcd_wdata(0x0E); - lcd_wdata(0x00); - - lcd_wcmd(0xF2); - lcd_wdata(0x01); - - lcd_wcmd(0xE0); - lcd_wdata(0x09); - lcd_wdata(0x00); - lcd_wdata(0x06); - lcd_wdata(0x2E); - lcd_wdata(0x2B); - lcd_wdata(0x0B); - lcd_wdata(0x1A); - lcd_wdata(0x02); - lcd_wdata(0x06); - lcd_wdata(0x0C); - lcd_wdata(0x0D); - lcd_wdata(0x00); - lcd_wdata(0x05); - lcd_wdata(0x02); - lcd_wdata(0x05); - - lcd_wcmd(0xE1); - lcd_wdata(0x06); - lcd_wdata(0x23); - lcd_wdata(0x25); - lcd_wdata(0x0F); - lcd_wdata(0x0A); - lcd_wdata(0x04); - lcd_wdata(0x02); - lcd_wdata(0x1A); - lcd_wdata(0x05); - lcd_wdata(0x03); - lcd_wdata(0x06); - lcd_wdata(0x01); - lcd_wdata(0x0C); - lcd_wdata(0x0B); - lcd_wdata(0x05); - lcd_wdata(0x05); - - lcd_wcmd(0x3A); - lcd_wdata(0x05); - - lcd_wcmd(0x29); - - lcd_wcmd(0x2C); -} - -static void lcd_init2(void) -{ - lcd_wcmd_data(0x00, 0x0001); - lcd_delay(50000); - - lcd_wcmd_data(0x07, 0x0000); - lcd_wcmd_data(0x12, 0x0000); - lcd_delay(10000); - - lcd_wcmd(0); - lcd_wcmd(0); - lcd_wcmd(0); - lcd_wcmd(0); - - lcd_wcmd_data(0xA4, 0x0001); - lcd_delay(10000); - - lcd_wcmd_data(0x70, 0x1B00); - lcd_wcmd_data(0x08, 0x030A); - lcd_wcmd_data(0x30, 0x0000); - lcd_wcmd_data(0x31, 0x0305); - lcd_wcmd_data(0x32, 0x0304); - lcd_wcmd_data(0x33, 0x0107); - lcd_wcmd_data(0x34, 0x0304); - - lcd_wcmd_data(0x35, 0x0204); - lcd_wcmd_data(0x36, 0x0707); - lcd_wcmd_data(0x37, 0x0701); - lcd_wcmd_data(0x38, 0x1B08); - lcd_wcmd_data(0x39, 0x030F); - lcd_wcmd_data(0x3A, 0x0E0E); - - lcd_wcmd_data(0x07, 0x0001); - lcd_delay(50000); - - lcd_wcmd_data(0x18, 0x0001); - lcd_wcmd_data(0x10, 0x12B0); - lcd_wcmd_data(0x11, 0x0001); - - lcd_wcmd_data(0x12, 0x0114); - lcd_wcmd_data(0x13, 0x8D0F); - lcd_wcmd_data(0x12, 0x0134); - lcd_delay(1000); - lcd_wcmd_data(0x01, 0x0100); - lcd_wcmd_data(0x02, 0x0700); - lcd_wcmd_data(0x03, 0x5030); - - lcd_wcmd_data(0x04, 0x0000); - lcd_wcmd_data(0x09, 0x0000); - lcd_wcmd_data(0x0C, 0x0000); - lcd_wcmd_data(0x0F, 0x0000); - - lcd_wcmd_data(0x14, 0x8000); - lcd_wcmd_data(0x20, 0x0000); - lcd_wcmd_data(0x21, 0x0000); - lcd_wcmd_data(0x71, 0x0001); - lcd_wcmd_data(0x7A, 0x0000); - lcd_wcmd_data(0x90, 0x0000); - lcd_wcmd_data(0x91, 0x0100); - lcd_wcmd_data(0x92, 0x0000); - lcd_wcmd_data(0x98, 0x0001); - lcd_wcmd_data(0x99, 0x030C); - lcd_wcmd_data(0x9A, 0x030C); - - lcd_delay(50000); - lcd_wcmd_data(0x07, 0x0001); - lcd_delay(30000); - lcd_wcmd_data(0x07, 0x0021); - - lcd_wcmd_data(0x12, 0x1134); - lcd_delay(10000); - - lcd_wcmd_data(0x07, 0x0233); - lcd_delay(30000); -} - - -static void lcd_set_window1(int x, int y, int width, int height) -{ - (void)x; - (void)width; - - lcd_wcmd(0x2A); - lcd_wdata(0); - lcd_wdata(y); - lcd_wdata(0); - - lcd_wcmd(0x2B); - lcd_wdata(0); - lcd_wdata(y + height - 1); - lcd_wdata(0); -} - -static void lcd_set_window2(int x, int y, int width, int height) -{ - lcd_wcmd_data(0x50, x); - lcd_wcmd_data(0x51, x + width - 1); - lcd_wcmd_data(0x52, y); - lcd_wcmd_data(0x53, y + height - 1); -} - - -static void lcd_set_position1(int x, int y) -{ - (void)x; - (void)y; -} - -static void lcd_set_position2(int x, int y) -{ - lcd_wcmd_data(0x20, x); - lcd_wcmd_data(0x21, y); - lcd_wcmd(0x22); -} - -void lcd_init_device(void) -{ - /* enable LCD clock */ - PWRCON &= ~(1 << 18); - - /* configure LCD pins */ - PCON0 &= ~(3 << 8); - PCON7 = (PCON7 & ~(0x000000FF)) | 0x00000033; - PCON_ASRAM = 2; - - lcd_reset(); - - /* detect LCD type on P0.4 */ - lcd_type = (PDAT0 & (1 << 4)) ? 1 : 2; - - /* initialise display */ - if (lcd_type == 1) { - lcd_init1(); - } else { - lcd_init2(); - } -} - -void lcd_update_rect(int x, int y, int width, int height) -{ - fb_data* p; - int h, w; - - void* (*fbaddr)(int x, int y) = FB_CURRENTVP_BUFFER->get_address_fn; - if (lcd_type == 1) { - /* TODO implement and test */ - lcd_set_window1(x, y, width, height); - lcd_set_position1(x, y); - - for (h = 0; h < height; h++) { - p = fbaddr(0,y); - for (w = 0; w < LCD_WIDTH; w++) { - while (LCD_STATUS & 0x10); - LCD_WDATA = *p++; - } - y++; - } - } - else { - lcd_set_window2(x, y, width, height); - lcd_set_position2(x, y); - - for (h = 0; h < height; h++) { - p = fbaddr(x,y); - for (w = 0; w < width; w++) { - while (LCD_STATUS & 0x10); - LCD_WDATA = *p++; - } - y++; - } - } -} - -void lcd_update(void) -{ - lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); -} - diff --git a/firmware/target/arm/s5l8700/yps3/nand-target.h b/firmware/target/arm/s5l8700/yps3/nand-target.h deleted file mode 100644 index b617c2c27f..0000000000 --- a/firmware/target/arm/s5l8700/yps3/nand-target.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _NAND_TARGET_H_ -#define _NAND_TARGET_H_ - -#include "config.h" - -void nand_ll_init(void); -unsigned int nand_ll_read_id(int bank); - -/* TODO later: create nand_ll_read/write/erase prototypes */ - -#endif /* _NAND_TARGET_H_ */ - diff --git a/firmware/target/arm/s5l8700/yps3/nand-yps3.c b/firmware/target/arm/s5l8700/yps3/nand-yps3.c deleted file mode 100644 index 86098ae8b0..0000000000 --- a/firmware/target/arm/s5l8700/yps3/nand-yps3.c +++ /dev/null @@ -1,109 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include - -#include "config.h" -#include "s5l87xx.h" -#include "nand-target.h" - -/* Driver for the S5L8700 flash memory controller for low-level access to the - NAND flash of the Samsung YP-S3. - - The YP-S3 seems to use the pins P6.5 and P6.6 as chip selects in GPIO mode - instead of using the regular pins P6.3 and P6.4. -*/ - -#define FMSTAT_RBB (1<<0) -#define FMSTAT_RBBDone (1<<1) -#define FMSTAT_CMDDone (1<<2) -#define FMSTAT_AddrDone (1<<3) -#define FMSTAT_TransDone (1<<4) -#define FMSTAT_WFIFO_HEMPTY (1<<5) -#define FMSTAT_RFIFO_HFULL (1<<6) -#define FMSTAT_WFIFO_EMPTY (1<<8) -#define FMSTAT_RFIFO_FULL (1<<9) -#define FMSTAT_EndECC (1<<10) - -#define FMCTRL1_DoTransAddr (1<<0) -#define FMCTRL1_DoReadData (1<<1) -#define FMCTRL1_DoWriteData (1<<2) -#define FMCTRL1_WriteREQSEL (1<<4) -#define FMCTRL1_ClearSyndPtr (1<<5) -#define FMCTRL1_ClearWFIFO (1<<6) -#define FMCTRL1_ClearRFIFO (1<<7) -#define FMCTRL1_ParityPtr (1<<8) -#define FMCTRL1_SyndPtr (1<<9) - -static void nand_chip_select(int bank) -{ - unsigned int select; - - select = (1 << bank); - FMCTRL0 = 0x1821 | ((select & 3) << 1); - PDAT6 = (PDAT6 & ~0x60) | ((~select & 0xC) << 3); -} - -void nand_ll_init(void) -{ - /* enable flash memory controller */ - PWRCON &= ~(1 << 1); - - /* P2.X is SMC I/O */ - PCON2 = 0x55555555; - /* P4.1 = CLE, P4.4 = nWR, P4.5 = nRD */ - PCON4 = (PCON4 & ~0x00FF00F0) | 0x00550050; - /* P6.0 = nf_rbn, P6.1 = smc_ce0, P6.2 = smc_ce1, - P6.5 = smc_ce2 (as GPIO), P6.6 = smc_ce3 (as GPIO), P6.7 = ALE */ - PCON6 = (PCON6 & ~0xFFF00FFF) | 0x51100555; - PDAT6 |= 0x60; -} - -unsigned int nand_ll_read_id(int bank) -{ - unsigned int nand_id; - - nand_chip_select(bank); - - /* send "read id" command */ - FMCMD = 0x90; - while ((FMCSTAT & FMSTAT_CMDDone) == 0); - FMCSTAT = FMSTAT_CMDDone; - - /* transfer address */ - FMANUM = 0; - FMADDR0 = 0; - FMCTRL1 = FMCTRL1_DoTransAddr; - while ((FMCSTAT & FMSTAT_AddrDone) == 0); - FMCSTAT = FMSTAT_AddrDone; - - /* read back data */ - FMDNUM = 3; - FMCTRL1 = FMCTRL1_DoReadData; - while ((FMCSTAT & FMSTAT_TransDone) == 0); - FMCSTAT = FMSTAT_TransDone; - nand_id = FMFIFO; - - /* clear read FIFO */ - FMCTRL1 = FMCTRL1_ClearRFIFO; - - return nand_id; -} - diff --git a/firmware/target/arm/s5l8700/yps3/power-yps3.c b/firmware/target/arm/s5l8700/yps3/power-yps3.c deleted file mode 100644 index 6f845bd5ff..0000000000 --- a/firmware/target/arm/s5l8700/yps3/power-yps3.c +++ /dev/null @@ -1,104 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright © 2009 Bertrik Sikken - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include "config.h" -#include "s5l87xx.h" -#include "power.h" - -/* Power handling for the S5L8700 based Samsung YP-S3 - - Pins involved in power management: - * P0.1: stay powered up (even with the USB cable unplugged) - * P1.1: USB power detect - * P4.7: tuner power/enable - * P5.2: unknown output - * P5.3: unknown output, related to charging (perhaps charge current?) - * P5.4: charge status input (only valid if charger enabled) - * P5.6: charger enable -*/ - -void power_off(void) -{ - /* take down P0.1 to power off (plugged USB cable overrides this though) */ - PDAT0 &= ~(1 << 1); - - while(1); /* wait for system to shut down */ -} - -void power_init(void) -{ - /* configure P0.1 as output for power-up and stay powered up */ - PCON0 = (PCON0 & ~(3 << 2)) | (1 << 2); - PDAT0 |= (1 << 1); - - /* configure P1.1 as input for USB power detect */ - PCON1 = (PCON1 & ~0x000000F0) | 0x00000000; - - /* configure P4.7 as output for tuner power and turn power off */ - PCON4 = (PCON4 & ~0xF0000000) | 0x10000000; - PDAT4 &= ~(1 << 7); - - /* configure P5.2 / P5.3 / P5.6 as output, P5.4 as input */ - PCON5 = (PCON5 & ~0x0F0FFF00) | 0x01001100; - PDAT5 &= ~((1 << 2) | (1 << 3) | (1 << 6)); -} - -#if CONFIG_CHARGING -unsigned int power_input_status(void) -{ - /* check USB power on P1.1 */ - if (PDAT1 & (1 << 1)) { - return POWER_INPUT_USB; - } - - return POWER_INPUT_NONE; -} - -bool charging_state(void) -{ - /* check if charger is enabled */ - if (PDAT5 & (1 << 6)) { - /* check if charging is busy */ - return (PDAT5 & (1 << 4)); - } - return false; -} -#endif /* CONFIG_CHARGING */ - -#if CONFIG_TUNER -bool tuner_power(bool status) -{ - if (status) { - PDAT4 |= (1 << 7); - } - else { - PDAT4 &= ~(1 << 7); - } - /* TODO what should we return here? */ - return status; -} - -bool tuner_powered(void) -{ - return (PDAT4 & (1 << 7)); -} -#endif /* CONFIG_TUNER */ - diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h index 5f336d6bc8..8de6ce93cd 100644 --- a/firmware/target/hosted/sdl/sim-ui-defines.h +++ b/firmware/target/hosted/sdl/sim-ui-defines.h @@ -237,13 +237,6 @@ #define UI_LCD_POSX 129 /* x position of lcd */ #define UI_LCD_POSY 85 /* y position of lcd */ -#elif defined(MEIZU_M6SL) -#define UI_TITLE "Meizu M6" -#define UI_WIDTH 512 /* width of GUI window */ -#define UI_HEIGHT 322 /* height of GUI window */ -#define UI_LCD_POSX 39 /* x position of lcd */ -#define UI_LCD_POSY 38 /* y position of lcd */ - #elif defined(SANSA_FUZEPLUS) #define UI_TITLE "Sansa Fuze+" #define UI_WIDTH 322 /* width of GUI window */ diff --git a/tools/builds.pm b/tools/builds.pm index e2af574df4..595a20c517 100644 --- a/tools/builds.pm +++ b/tools/builds.pm @@ -207,18 +207,6 @@ $releasenotes="/wiki/ReleaseNotes400"; name => 'Mini 2440', status => 1, }, - 'meizum3' => { - name => 'Meizu M3', - status => 1, - }, - 'meizum6sl' => { - name => 'Meizu M6SL', - status => 1, - }, - 'meizum6sp' => { - name => 'Meizu M6SP', - status => 1, - }, 'mrobe100' => { name => 'Olympus M-Robe 100', status => 3, @@ -276,10 +264,6 @@ $releasenotes="/wiki/ReleaseNotes400"; sim => 0, status => 2, }, - 'samsungyps3' => { - name => 'Samsung YP-S3', - status => 1, - }, 'sansac200' => { name => 'SanDisk Sansa c200', status => 3, diff --git a/tools/configure b/tools/configure index 5d1cd44791..61da0e36ef 100755 --- a/tools/configure +++ b/tools/configure @@ -566,13 +566,6 @@ arm9tdmicc () { endian="little" } -arm940tbecc () { - findarmgcc - GCCOPTS="$CCOPTS -mbig-endian -mcpu=arm940t" - GCCOPTIMIZE="-fomit-frame-pointer" - endian="big" -} - arm940tcc () { findarmgcc GCCOPTS="$CCOPTS -mcpu=arm940t" @@ -1703,48 +1696,43 @@ cat < ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno and Frank Gevaerts - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define bswap_16(value) \ - ((((value) & 0xff) << 8) | ((value) >> 8)) - -#define bswap_32(value) \ - (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ - (uint32_t)bswap_16((uint16_t)((value) >> 16))) - -#define host_to_le32(_x) bswap_32(htonl(_x)) -#define host_to_le16(_x) bswap_16(htons(_x)) - -void usage() -{ - fprintf(stderr, "usage: meizu_dfu m3 [SST39VF800.dfu] \n"); - fprintf(stderr, " meizu_dfu m6 [SST39VF800.dfu] \n"); - fprintf(stderr, " meizu_dfu m6sl [updateNAND_BE_070831.dfu] \n"); - exit(1); -} - -uint32_t crc32(char *data, int len, uint32_t poly, uint32_t init) -{ - uint32_t crc_table[256]; - uint32_t crc, t; - int i, j; - - // generate the table - for (i = 0; i < 256; ++i) { - t = i; - for (j = 0; j < 8; ++j) - if (t & 1) - t = (t >> 1) ^ poly; - else - t >>= 1; - crc_table[i] = t; - } - - // calculate the crc - crc = init; - for (i = 0; i < len; ++i) - crc = (crc >> 8) ^ crc_table[(crc^data[i]) & 0xff]; - - return crc; -} - -typedef struct { - char *name; - char *data; - int len; -} image_data_t; - -typedef struct { - int delay; - int pre_off; - uint32_t pre_sig; - uint16_t suf_dev; - uint16_t suf_prod; - uint16_t suf_ven; - uint16_t suf_dfu; - char suf_sig[3]; - uint8_t suf_len; -} image_attr_t; - -#define BLOCK_SIZE 2048 -#define DFU_TIMEOUT 0xa000 -#define DFU_CRC_POLY 0xedb88320 -#define DFU_INIT_CRC 0xffffffff - -#define USB_VID_SAMSUNG 0x0419 -#define USB_PID_M6SL 0x0145 -#define USB_PID_M3_M6 0x0141 - -void init_img(image_data_t *img, const char *filename, image_attr_t *attr) -{ - int fd, len, i, readlen; - struct stat statbuf; - char buf[BLOCK_SIZE]; - uint32_t dfu_crc; - uint32_t le_len; - - printf("Reading %s...", filename); - - if (stat(filename, &statbuf) < 0) { - printf("\nCould not stat file, exiting.\n"); - exit(1); - } - len = statbuf.st_size; - - img->name = basename(strdup(filename)); - img->data = malloc(len + 16); - img->len = len + 16; - - fd = open(filename, O_RDONLY); - for (i = 0; i < len; i += BLOCK_SIZE) { - readlen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE; - read(fd, buf, readlen); - memcpy(img->data + i, buf, readlen); - } - close(fd); - - le_len = host_to_le32(img->len); - // patch the data size in after the signature - memcpy(img->data + attr->pre_off + 4, &le_len, 4); - - /* convert to little endian */ - attr->suf_dev = host_to_le16(attr->suf_dev); - attr->suf_prod = host_to_le16(attr->suf_prod); - attr->suf_ven = host_to_le16(attr->suf_ven); - attr->suf_dfu = host_to_le16(attr->suf_dfu); - - // append the suffix (excluding the checksum) - memcpy(img->data + len, &attr->suf_dev, 2); - memcpy(img->data + len + 2, &attr->suf_prod, 2); - memcpy(img->data + len + 4, &attr->suf_ven, 2); - memcpy(img->data + len + 6, &attr->suf_dfu, 2); - memcpy(img->data + len + 8, &attr->suf_sig, 3); - memcpy(img->data + len + 11, &attr->suf_len, 1); - - dfu_crc = host_to_le32(crc32(img->data, len + 12, DFU_CRC_POLY, DFU_INIT_CRC)); - memcpy(img->data + len + 12, &dfu_crc, 4); - -#if 0 - FILE *f = fopen(img->name, "w"); - fwrite(img->data, len + 16, 1, f); - fclose(f); -#endif - - printf("OK\n"); -} - -usb_dev_handle *usb_dev_open(uint16_t dfu_vid, uint16_t dfu_pid) -{ - struct usb_bus *bus; - struct usb_device *dev; - usb_dev_handle *device; - - printf("USB initialization..."); - - usb_init(); - usb_find_busses(); - usb_find_devices(); - - for (bus = usb_get_busses(); bus != NULL; bus = bus->next) - for (dev = bus->devices; dev != NULL; dev = dev->next) - if (dev->descriptor.idVendor == dfu_vid - && dev->descriptor.idProduct == dfu_pid) - goto found; - - printf("\nNo device found, exiting.\n"); - exit(1); - -found: - printf(" Device found.\n"); - device = usb_open(dev); - usb_claim_interface(device, 0); - return device; -} - -void usb_mimic_windows(usb_dev_handle *device) -{ - char data[1024]; - - usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x001b, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0040, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0303, 0x0409, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); - usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0209, DFU_TIMEOUT); -} - -void usb_dev_close(usb_dev_handle *device) -{ - printf("Releasing interface..."); - - usb_release_interface(device, 0); - - printf(" OK\n"); -} - -enum DFU_REQUEST { - DFU_DETACH = 0, - DFU_DOWNLOAD, - DFU_UPLOAD, - DFU_GETSTATUS, - DFU_CLRSTATUS, - DFU_GETSTATE, - DFU_ABORT -}; - -void get_cpu(usb_dev_handle *device) -{ - char data[64]; - int req_out_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - int len; - - printf("GET CPU"); - - // check for "S5L8700 Rev.1" - len = usb_control_msg(device, req_out_if, 0xff, 0x0002, 0, data, 0x003f, DFU_TIMEOUT); - if (len < 0) { - printf("\nError trying to get CPU model, exiting.\n"); - exit(1); - } - - memset(data + len, 0, 64 - len); - printf(", got: %s\n", data); -} - -void send_file(usb_dev_handle *device, image_data_t *img) -{ - char dfu_ret[6]; - char *data; - int req_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - int req_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - int len, idx, writelen, i; - - printf("Sending %s... ", img->name); - - len = img->len; - data = img->data; - - // loop for the file - for (i = 0, idx = 0; i < len; i += BLOCK_SIZE, ++idx) { - writelen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE; - usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, data + i, writelen, DFU_TIMEOUT); - dfu_ret[4] = 0x00; - while (dfu_ret[4] != 0x05) - usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); - printf("#"); - } - - usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, NULL, 0, DFU_TIMEOUT); - dfu_ret[4] = 0x00; - while (dfu_ret[4] != 0x07) - usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); - - printf(" OK\n"); -} - -void clear_status(usb_dev_handle *device) -{ - char dfu_ret[6]; - int usb_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - int usb_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - - printf("Clearing status..."); - - dfu_ret[4] = 0x00; - while (dfu_ret[4] != 0x08) - usb_control_msg(device, usb_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); - usb_control_msg(device, usb_out_if, DFU_CLRSTATUS, 0, 0, NULL, 0, DFU_TIMEOUT); - - printf(" OK\n"); -} - -void dfu_detach(usb_dev_handle *device) -{ - char usb_ret[4]; - int usb_in_oth = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_OTHER; - int usb_out_oth = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; - - printf("Detaching..."); - - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - usb_control_msg(device, usb_out_oth, DFU_DOWNLOAD, 0x0010, 3, NULL, 0, DFU_TIMEOUT); - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); - - printf(" OK\n"); -} - -void dfu_m3_m6(char *file1, char *file2) -{ - image_data_t img1, img2; - image_attr_t attr1, attr2; - usb_dev_handle *device; - - attr1.delay = 1000; - attr1.pre_off = 0x20; - attr1.pre_sig = 0x44465543; - attr1.suf_dev = 0x0100; - attr1.suf_prod = 0x0140; - attr1.suf_ven = 0x0419; - attr1.suf_dfu = 0x0100; - memcpy(attr1.suf_sig, "RON", 3); - attr1.suf_len = 0x10; - - init_img(&img1, file1, &attr1); - - if (file2) { - attr2.delay = 1000; - attr2.pre_off = 0x20; - attr2.pre_sig = 0x44465543; - attr2.suf_dev = 0x0100; - attr2.suf_prod = 0x0140; - attr2.suf_ven = 0x0419; - attr2.suf_dfu = 0x0100; - memcpy(attr2.suf_sig, "UFD", 3); - attr2.suf_len = 0x10; - - init_img(&img2, file2, &attr2); - } - - device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M3_M6); -// usb_mimic_windows(); - get_cpu(device); - get_cpu(device); - send_file(device, &img1); - - if (file2) { - printf("Wait a sec (literally)..."); - sleep(1); - printf(" OK\n"); - - clear_status(device); - get_cpu(device); - send_file(device, &img2); - dfu_detach(device); - } - - usb_dev_close(device); -} - -void dfu_m6sl(char *file1, char *file2) -{ - image_data_t img1, img2; - image_attr_t attr1, attr2; - usb_dev_handle *device; - - attr1.delay = 1000; - attr1.pre_off = 0x20; - attr1.pre_sig = 0x44465543; - attr1.suf_dev = 0x0100; - attr1.suf_prod = 0x0140; - attr1.suf_ven = 0x0419; - attr1.suf_dfu = 0x0100; - memcpy(attr1.suf_sig, "UFD", 3); - attr1.suf_len = 0x10; - - init_img(&img1, file1, &attr1); - - if (file2) { - attr2.delay = 1000; - attr2.pre_off = 0x20; - attr2.pre_sig = 0x44465543; - attr2.suf_dev = 0x0100; - attr2.suf_prod = 0x0140; - attr2.suf_ven = 0x0419; - attr2.suf_dfu = 0x0100; - memcpy(attr2.suf_sig, "UFD", 3); - attr2.suf_len = 0x10; - - init_img(&img2, file2, &attr2); - } - - device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL); - get_cpu(device); - get_cpu(device); - send_file(device, &img1); - - if (file2) { - printf("Wait a sec (literally)..."); - sleep(1); - printf(" OK\n"); - usb_dev_close(device); - - device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL); - get_cpu(device); - get_cpu(device); - send_file(device, &img2); - dfu_detach(device); - } - - usb_dev_close(device); -} - - -int main(int argc, char **argv) -{ - if (argc < 3 || argc > 4) - usage(); - - setvbuf(stdout, NULL, _IONBF, 0); - - char *second_file = (argc == 4) ? argv[3] : NULL; - - if (!strcmp(argv[1], "m3")) - dfu_m3_m6(argv[2], second_file); - else if (!strcmp(argv[1], "m6")) - dfu_m3_m6(argv[2], second_file); - else if (!strcmp(argv[1], "m6sl")) - dfu_m6sl(argv[2], second_file); - else - usage(); - - return 0; -} - diff --git a/utils/themeeditor/resources/targetdb b/utils/themeeditor/resources/targetdb index 4d94992953..68bf3f04e8 100644 --- a/utils/themeeditor/resources/targetdb +++ b/utils/themeeditor/resources/targetdb @@ -589,33 +589,6 @@ lyreproto1 record : no } -meizum3 -{ - name : Meizu M3 - screen : 176 x 132 @ rgb - remote : no - fm : yes - record : no -} - -meizum6sl -{ - name : Meizu M6SL - screen : 320 x 240 @ rgb - remote : no - fm : yes - record : no -} - -meizum6sp -{ - name : Meizu M6SP - screen : 240 x 320 @ rgb - remote : no - fm : yes - record : no -} - mini2440 { name : Mini 2440 @@ -688,15 +661,6 @@ samsungypr0 record : no } -samsungyps3 -{ - name : Samsung YP-S3 - screen : 176 x 220 @ rgb - remote : no - fm : yes - record : no -} - sansac100 { name : SanDisk Sansa c100 From 53862c7eed866c083fc12998aa97bcf261341e01 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 3 Feb 2026 21:34:51 +0000 Subject: [PATCH 27/75] Remove Sansa View port It doesn't seem to have been functional ever and currently doesn't build; eg. the last commit to the LCD driver added a syntax error, and there's some duplicate functions between mmu-armv6.S and system-pp502x.c. Doesn't seem worth the effort to fix. Change-Id: I82b5bec3ed9686f28aedbe283818af792b96daf4 --- bootloader/SOURCES | 4 +- bootloader/main-pp.c | 4 +- bootloader/sansaview.c | 63 ---- firmware/SOURCES | 12 - firmware/export/config.h | 2 - firmware/export/config/sansaview.h | 196 ---------- firmware/target/arm/pp/usb-fw-pp502x.c | 6 - .../target/arm/sandisk/sansa-view/adc-view.c | 33 -- .../arm/sandisk/sansa-view/backlight-target.h | 33 -- .../arm/sandisk/sansa-view/backlight-view.c | 82 ----- .../arm/sandisk/sansa-view/button-target.h | 53 --- .../arm/sandisk/sansa-view/button-view.c | 37 -- .../target/arm/sandisk/sansa-view/i2c-view.c | 26 -- .../target/arm/sandisk/sansa-view/lcd-view.c | 340 ------------------ .../arm/sandisk/sansa-view/power-view.c | 28 -- .../arm/sandisk/sansa-view/powermgmt-view.c | 49 --- .../target/arm/sandisk/sansa-view/usb-view.c | 36 -- tools/builds.pm | 4 - tools/configure | 103 +++--- utils/themeeditor/resources/targetdb | 9 - 20 files changed, 43 insertions(+), 1077 deletions(-) delete mode 100644 bootloader/sansaview.c delete mode 100644 firmware/export/config/sansaview.h delete mode 100644 firmware/target/arm/sandisk/sansa-view/adc-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/backlight-target.h delete mode 100644 firmware/target/arm/sandisk/sansa-view/backlight-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/button-target.h delete mode 100644 firmware/target/arm/sandisk/sansa-view/button-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/i2c-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/lcd-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/power-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/powermgmt-view.c delete mode 100644 firmware/target/arm/sandisk/sansa-view/usb-view.c diff --git a/bootloader/SOURCES b/bootloader/SOURCES index 1f83d6218b..478cb9a73c 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -19,14 +19,12 @@ show_logo.c defined(MROBE_100) || defined(PHILIPS_SA9200) || \ defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330) || \ defined(SAMSUNG_YH820) || defined(SAMSUNG_YH920) || \ - defined(SAMSUNG_YH925) || defined(SANSA_VIEW) + defined(SAMSUNG_YH925) #ifdef E200R_INSTALLER main-e200r-installer.c #elif defined(SANSA_PP_ERASE) main-ppsansawipe.c fat32format.c -#elif defined(SANSA_VIEW) -sansaview.c #else show_logo.c main-pp.c diff --git a/bootloader/main-pp.c b/bootloader/main-pp.c index 0bd4dcbca0..581f486a21 100644 --- a/bootloader/main-pp.c +++ b/bootloader/main-pp.c @@ -265,8 +265,8 @@ static int handle_usb(int connect_timeout) return usb; } -#elif (defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) \ - || defined (SANSA_VIEW)) && !defined(USE_ROCKBOX_USB) +#elif (defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)) && \ + !defined(USE_ROCKBOX_USB) /* Return USB_INSERTED if cable present */ static int handle_usb(int connect_timeout) { diff --git a/bootloader/sansaview.c b/bootloader/sansaview.c deleted file mode 100644 index 31716d4b25..0000000000 --- a/bootloader/sansaview.c +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2014 by Szymon Dziok - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* -SANSA VIEW: TESTING CODE -*/ - - -#include -#include -#include -#include -#include "config.h" -#include "inttypes.h" -#include "cpu.h" -#include "system.h" -#include "lcd.h" -#include "../kernel-internal.h" -#include "storage.h" -#include "disk.h" -#include "font.h" -#include "backlight.h" -#include "backlight-target.h" -#include "button.h" -#include "panic.h" -#include "power.h" -#include "file.h" -#include "common.h" - -void main(void) -{ - system_init(); - kernel_init(); - disable_irq(); - - while(1) - { - backlight_hw_on(); - buttonlight_hw_off(); - sleep(HZ/4); - backlight_hw_off(); - buttonlight_hw_on(); - sleep(HZ/4); - } -} diff --git a/firmware/SOURCES b/firmware/SOURCES index a3a577d4bd..4138efb672 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1074,18 +1074,6 @@ target/arm/sandisk/sansa-c200/button-c200.c target/arm/sandisk/sansa-c200/powermgmt-c200.c #endif /* SANSA_C200 */ -#ifdef SANSA_VIEW -target/arm/sandisk/sansa-view/backlight-view.c -target/arm/sandisk/sansa-view/adc-view.c -target/arm/sandisk/sansa-view/power-view.c -target/arm/sandisk/sansa-view/lcd-view.c -target/arm/sandisk/sansa-view/button-view.c -target/arm/sandisk/sansa-view/powermgmt-view.c -#ifndef BOOTLOADER -/* target/arm/sandisk/audio-view.c */ -#endif /* BOOTLOADER */ -#endif /* SANSA_VIEW */ - #ifdef PHILIPS_SA9200 #ifndef BOOTLOADER drivers/synaptics-mep.c diff --git a/firmware/export/config.h b/firmware/export/config.h index 73694cef30..9fb964be5d 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -485,8 +485,6 @@ Lyre prototype 1 */ #include "config/sansaclipzip.h" #elif defined(SANSA_C200V2) #include "config/sansac200v2.h" -#elif defined(SANSA_VIEW) -#include "config/sansaview.h" #elif defined(LYRE_PROTO1) #include "config/lyreproto1.h" #elif defined(MINI2440) diff --git a/firmware/export/config/sansaview.h b/firmware/export/config/sansaview.h deleted file mode 100644 index 238102d567..0000000000 --- a/firmware/export/config/sansaview.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * This config file is for the Sandisk Sansa View - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 63 -#define MODEL_NAME "Sandisk View" - -#define HW_SAMPR_CAPS (SAMPR_CAP_44) - -/* define this if you have recording possibility */ -/* #define HAVE_RECORDING */ - -#define REC_SAMPR_CAPS (SAMPR_CAP_22) -#define REC_FREQ_DEFAULT REC_FREQ_22 /* Default is not 44.1kHz */ -#define REC_SAMPR_DEFAULT SAMPR_22 - -/* Define bitmask of input sources - recordable bitmask can be defined - explicitly if different */ -#define INPUT_SRC_CAPS (SRC_CAP_MIC | SRC_CAP_FMRADIO) - - - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you want album art for this target */ -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -/* define this if you have a light associated with the buttons */ -#define HAVE_BUTTON_LIGHT - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* LCD dimensions */ -#define LCD_WIDTH 240 -#define LCD_HEIGHT 320 -/* sqrt(240^2 + 320^2) / 2.4 = 166.7 */ -#define LCD_DPI 167 -#define LCD_DEPTH 16 /* 65536 colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -#ifndef BOOTLOADER -/* define this if you have LCD enable function */ -#define HAVE_LCD_ENABLE -#endif - -/* define this if you can flip your LCD */ -#define HAVE_LCD_FLIP - -/* define this if you can invert the colours on your LCD */ -#define HAVE_LCD_INVERT - -/* The only difference is that the power/hold is on the left instead of right on Fuze */ -#define CONFIG_KEYPAD SANSA_FUZE_PAD - -/* Define this to have CPU boosted while scrolling in the UI */ -#define HAVE_GUI_BOOST - -/* Define this to enable morse code input */ -#define HAVE_MORSE_INPUT - - - -/* There is no hardware tone control */ -/* #define HAVE_SW_TONE_CONTROLS*/ -#define HAVE_WM8731 - -/* define this if you have a real-time clock */ -#ifndef BOOTLOADER -/* #define CONFIG_RTC RTC_ */ -#endif - -/* Define this if you have a software controlled poweroff */ -#define HAVE_SW_POWEROFF - -/* Required for MicroSD cards */ -#define HAVE_FAT16SUPPORT - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x80000 - -#define AB_REPEAT_ENABLE - -/* Define this for LCD backlight available */ -#define HAVE_BACKLIGHT -/* #define HAVE_BACKLIGHT_BRIGHTNESS */ - -/* define this if the unit uses a scrollwheel for navigation */ -#define HAVE_SCROLLWHEEL -/* define to activate advanced wheel acceleration code */ -#define HAVE_WHEEL_ACCELERATION -/* define from which rotation speed [degree/sec] on the acceleration starts */ -#define WHEEL_ACCEL_START 540 -/* define type of acceleration (1 = ^2, 2 = ^3, 3 = ^4) */ -#define WHEEL_ACCELERATION 1 - -/* define this if you have a flash memory storage */ -#define HAVE_FLASH_STORAGE - -/* define this if the flash memory uses the SecureDigital Memory Card protocol */ -#define CONFIG_STORAGE STORAGE_SD - -#define BATTERY_CAPACITY_DEFAULT 750 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 750 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 750 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 0 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Charging implemented in a target-specific algorithm */ -#define CONFIG_CHARGING CHARGING_SIMPLE -#define HAVE_POWEROFF_WHILE_CHARGING - -/* define current usage levels */ -#define CURRENT_NORMAL 30 /* Toni's measurements in Nov 2008 */ -#define CURRENT_BACKLIGHT 40 /* Screen is about 20, blue LEDs are another 20, so 40 if both */ -#define CURRENT_RECORD 30 /* flash player, so this is just unboosted current*/ - -/* define this if the unit can be powered or charged via USB */ -#define HAVE_USB_POWER - -/* Define this if you have a PortalPlayer PP5024 */ -#define CONFIG_CPU PP6100 - -/* Define this if you want to use the PP5024 i2c interface */ -#define CONFIG_I2C I2C_PP5024 - -/* define this if the hardware can be powered off while charging */ -/* Sansa can't be powered off while charging */ -/* #define HAVE_POWEROFF_WHILE_CHARGING */ - -/* The start address index for ROM builds */ -#define ROM_START 0x00000000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 250000000 - -/* Type of LCD */ -#define CONFIG_LCD LCD_VIEW - -#ifndef BOOTLOADER -#define HAVE_MULTIDRIVE -#define NUM_DRIVES 2 -#define HAVE_HOTSWAP -#endif - -/* USB On-the-go */ -#define CONFIG_USBOTG USBOTG_ARC - -/* enable these for the experimental usb stack */ -#define HAVE_USBSTACK -#define USB_VENDOR_ID 0x0781 -#define USB_PRODUCT_ID 0x74b1 - -/* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ */ - -#define MI4_FORMAT -#define BOOTFILE_EXT "mi4" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define ICODE_ATTR_TREMOR_NOT_MDCT - -#define INCLUDE_TIMEOUT_API - -/** Port-specific settings **/ - -/* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 1 -#define MAX_BRIGHTNESS_SETTING 12 -#define DEFAULT_BRIGHTNESS_SETTING 6 - -/* Default recording levels */ -#define DEFAULT_REC_MIC_GAIN 23 -#define DEFAULT_REC_LEFT_GAIN 23 -#define DEFAULT_REC_RIGHT_GAIN 23 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/target/arm/pp/usb-fw-pp502x.c b/firmware/target/arm/pp/usb-fw-pp502x.c index e3fa02e26f..fb04566cf5 100644 --- a/firmware/target/arm/pp/usb-fw-pp502x.c +++ b/firmware/target/arm/pp/usb-fw-pp502x.c @@ -87,12 +87,6 @@ #define USB_GPIO_MASK 0x04 #define USB_GPIO_VAL 0x04 -#elif defined(SANSA_VIEW) - /* GPIO A bit 7 is usb detect */ -#define USB_GPIO GPIOA -#define USB_GPIO_MASK 0x80 -#define USB_GPIO_VAL 0x80 - #else #error No USB GPIO config specified #endif diff --git a/firmware/target/arm/sandisk/sansa-view/adc-view.c b/firmware/target/arm/sandisk/sansa-view/adc-view.c deleted file mode 100644 index deb8de2471..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/adc-view.c +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "adc-target.h" - -void adc_init(void) -{ -} - -/* Called to get the recent ADC reading */ -inline unsigned short adc_read(int channel) -{ - (void)channel; - return 0; -} diff --git a/firmware/target/arm/sandisk/sansa-view/backlight-target.h b/firmware/target/arm/sandisk/sansa-view/backlight-target.h deleted file mode 100644 index c51875754d..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/backlight-target.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H - -#include - -void backlight_hw_on(void); -void backlight_hw_off(void); - -void buttonlight_hw_on(void); -void buttonlight_hw_off(void); - -#endif diff --git a/firmware/target/arm/sandisk/sansa-view/backlight-view.c b/firmware/target/arm/sandisk/sansa-view/backlight-view.c deleted file mode 100644 index 637e5b4269..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/backlight-view.c +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * Copyright (C) 2014 by Szymon Dziok - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "backlight-target.h" -#include "system.h" -#include "lcd.h" -#include "backlight.h" - -bool backlight_hw_init(void) -{ - GPIO_SET_BITWISE(GPIOD_ENABLE, 0x01); - GPIO_SET_BITWISE(GPIOD_OUTPUT_EN, 0x01); - GPIO_SET_BITWISE(GPIOA_ENABLE, 0x01); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x01); - GPIO_SET_BITWISE(GPIOA_ENABLE, 0x02); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x02); - GPIO_SET_BITWISE(GPIOR_ENABLE, 0x10); - GPIO_SET_BITWISE(GPIOR_ENABLE, 0x20); - GPIO_SET_BITWISE(GPIOR_ENABLE, 0x40); - GPIO_SET_BITWISE(GPIOR_ENABLE, 0x80); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x10); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x20); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x40); - GPIO_SET_BITWISE(GPIOA_OUTPUT_EN, 0x80); - return true; -} - -void backlight_hw_brightness(int brightness) -{ - (void)brightness; -} - -void backlight_hw_off(void) -{ - GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x01); -} - -void backlight_hw_on(void) -{ - GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x01); -} - -void buttonlight_hw_off(void) -{ - GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_VAL, 0x02); /* vertical buttonlight */ - GPIO_CLEAR_BITWISE(GPIOA_OUTPUT_VAL, 0x01); /* horizontal buttonlight */ - - GPIO_CLEAR_BITWISE(GPIOR_OUTPUT_VAL, 0x80); /* scrollwheel bottom led */ - GPIO_CLEAR_BITWISE(GPIOR_OUTPUT_VAL, 0x40); /* scrollwheel right led */ - GPIO_CLEAR_BITWISE(GPIOR_OUTPUT_VAL, 0x20); /* scrollwheel top led */ - GPIO_CLEAR_BITWISE(GPIOR_OUTPUT_VAL, 0x10); /* scrollwheel left led */ -} - -void buttonlight_hw_on(void) -{ - GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x02); /* vertical buttonlight */ - GPIO_SET_BITWISE(GPIOA_OUTPUT_VAL, 0x01); /* horizontal buttonlight */ - - GPIO_SET_BITWISE(GPIOR_OUTPUT_VAL, 0x80); /* scrollwheel bottom led */ - GPIO_SET_BITWISE(GPIOR_OUTPUT_VAL, 0x40); /* scrollwheel right led */ - GPIO_SET_BITWISE(GPIOR_OUTPUT_VAL, 0x20); /* scrollwheel top led */ - GPIO_SET_BITWISE(GPIOR_OUTPUT_VAL, 0x10); /* scrollwheel left led */ -} diff --git a/firmware/target/arm/sandisk/sansa-view/button-target.h b/firmware/target/arm/sandisk/sansa-view/button-target.h deleted file mode 100644 index 6b49f9053b..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/button-target.h +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Barry Wardell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define HAS_BUTTON_HOLD - -/* Sandisk Sansa View button codes */ - -/* Main unit's buttons */ -#define BUTTON_HOME 0x00000001 - -#define BUTTON_DOWN 0x00000002 -#define BUTTON_RIGHT 0x00000004 - -#define BUTTON_LEFT 0x00000008 -#define BUTTON_SELECT 0x00000010 -#define BUTTON_UP 0x00000020 -#define BUTTON_POWER 0x00000040 - -#define BUTTON_SCROLL_BACK 0x00000080 -#define BUTTON_SCROLL_FWD 0x00000100 - -#define BUTTON_HOLD 0x00000400 - -#define BUTTON_MAIN (BUTTON_HOME|BUTTON_DOWN|BUTTON_RIGHT|BUTTON_LEFT \ - |BUTTON_SELECT|BUTTON_UP|BUTTON_POWER \ - |BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD \ - |BUTTON_HOLD) - -#define POWEROFF_BUTTON BUTTON_POWER -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/sandisk/sansa-view/button-view.c b/firmware/target/arm/sandisk/sansa-view/button-view.c deleted file mode 100644 index e1a0bbbcaf..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/button-view.c +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "button.h" - -void button_init_device(void) -{ - -} - -bool button_hold(void) -{ - return false; -} - -int button_read_device(void) -{ - return 0; -} diff --git a/firmware/target/arm/sandisk/sansa-view/i2c-view.c b/firmware/target/arm/sandisk/sansa-view/i2c-view.c deleted file mode 100644 index a8ded7d2bf..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/i2c-view.c +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "i2c.h" - -void i2c_init(void) -{ -} diff --git a/firmware/target/arm/sandisk/sansa-view/lcd-view.c b/firmware/target/arm/sandisk/sansa-view/lcd-view.c deleted file mode 100644 index 6b24aadc8c..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/lcd-view.c +++ /dev/null @@ -1,340 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Rockbox driver for Sansa View LCDs - * - * Copyright (c) 2009 Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include "cpu.h" -#include "kernel.h" -#include "system.h" -#include "backlight-target.h" -#include "lcd.h" - -static bool display_on SHAREDBSS_ATTR = true; -static int lcd_type; - -#define LCD_DATA_OUT_GPIO GPIOH_OUTPUT_VAL -#define LCD_DATA_OUT_PIN 4 - -#define LCD_CLOCK_GPIO GPIOH_OUTPUT_VAL -#define LCD_CLOCK_PIN 6 - -#define LCD_CS_GPIO GPIOH_OUTPUT_VAL -#define LCD_CS_PIN 7 - - - -static void lcd_init_gpio(void) -{ - DEV_INIT1 |= 0xfc000000; - DEV_INIT3 |= 0xc300000; - - GPIOE_ENABLE = 0; - GPIOM_ENABLE &= ~0x3; - GPIOF_ENABLE = 0; - GPIOJ_ENABLE &= ~0x1a; - // reset low - GPIOB_ENABLE &= ~0x8; - // SPI chip select - GPIOH_OUTPUT_VAL |= 0x80; - GPIOH_OUTPUT_EN |= 0x80; - GPIOH_ENABLE |= 0x80; - // SPI clock - GPIOH_OUTPUT_VAL |= 0x40; - GPIOH_OUTPUT_EN |= 0x40; - GPIOH_ENABLE |= 0x40; - // unk - GPIOH_OUTPUT_VAL |= 0x20; - GPIOH_OUTPUT_EN |= 0x20; - GPIOH_ENABLE |= 0x20; - // SPI data - GPIOH_OUTPUT_VAL |= 0x10; - GPIOH_OUTPUT_EN |= 0x10; - GPIOH_ENABLE |= 0x10; - // LCD reset - GPIOB_OUTPUT_VAL |= 0x4; - GPIOB_ENABLE |= 0x4; - GPIOB_OUTPUT_EN |= 0x4; - DEV_INIT2 = 0x40000000; - // LCD type - GPIOG_ENABLE |= 0x8; - GPIOG_OUTPUT_EN &= ~0x8; - - if(GPIOG_INPUT_VAL & 0x8) - lcd_type = 0; - else - lcd_type = 1; -} - -static void lcd_send_msg(unsigned char count, unsigned int data) -{ - GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN); - - for(int i = count - 1; i >= 0; i--) - { - if(data & (1 << i)) - GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN); - else - GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN); - GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - udelay(1); - GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - udelay(2); - } - - GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN); -} - -static void lcd_send_cmd(unsigned int cmd) -{ - lcd_send_msg(24, (0x700000 | cmd)); -} - -static void lcd_send_data(unsigned int data) -{ - lcd_send_msg(24, (0x720000 | data)); -} - -static void lcd_write_reg(unsigned int cmd, unsigned int data) -{ - lcd_send_cmd(cmd); - lcd_send_data(data); -} - -void lcd_reset(void) -{ - GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4); - udelay(1000); - GPIO_CLEAR_BITWISE(GPIOB_OUTPUT_VAL, 0x4); - udelay(10000); - GPIO_SET_BITWISE(GPIOB_OUTPUT_VAL, 0x4); - udelay(50000); -} - -/* Run the powerup sequence for the driver IC */ -static void lcd_power_on(void) -{ - lcd_init_gpio(); - lcd_reset(); - - lcd_write_reg(0xE5, 0x8000); - lcd_write_reg(0x0, 0x1); - lcd_write_reg(0x1, 0x100); - lcd_write_reg(0x2, 0x700); - lcd_write_reg(0x3, 0x5230); - lcd_write_reg(0x4, 0x0); - lcd_write_reg(0x8, 0x408); /* back porch = 8, front porch = 4 */ - lcd_write_reg(0x9, 0x0); - lcd_write_reg(0xa, 0x0); - lcd_write_reg(0xd, 0x0); - lcd_write_reg(0xf, 0x2); - lcd_write_reg(0x10, 0x0); - lcd_write_reg(0x11, 0x0); - lcd_write_reg(0x12, 0x0); - lcd_write_reg(0x13, 0x0); - sleep(HZ/5); - lcd_write_reg(0x10, 0x17B0); - lcd_write_reg(0x11, 0x7); - sleep(HZ/20); - lcd_write_reg(0x12, 0x13c); - sleep(HZ/20); - - if (lcd_type == 0) - { - lcd_write_reg(0x13, 0x1700); - lcd_write_reg(0x29, 0x10); - sleep(HZ/10); - lcd_write_reg(0x20, 0x0); - lcd_write_reg(0x21, 0x0); - - lcd_write_reg(0x30, 0x7); - lcd_write_reg(0x31, 0x403); - lcd_write_reg(0x32, 0x400); - lcd_write_reg(0x35, 0x3); - lcd_write_reg(0x36, 0xF07); - lcd_write_reg(0x37, 0x606); - lcd_write_reg(0x38, 0x106); - lcd_write_reg(0x39, 0x7); - } - else - { - lcd_write_reg(0x13, 0x1800); - lcd_write_reg(0x29, 0x13); - sleep(HZ/10); - lcd_write_reg(0x20, 0x0); - lcd_write_reg(0x21, 0x0); - - lcd_write_reg(0x30, 0x2); - lcd_write_reg(0x31, 0x606); - lcd_write_reg(0x32, 0x501); - lcd_write_reg(0x35, 0x206); - lcd_write_reg(0x36, 0x504); - lcd_write_reg(0x37, 0x707); - lcd_write_reg(0x38, 0x306); - lcd_write_reg(0x39, 0x7); - } - - lcd_write_reg(0x3c, 0x700); - lcd_write_reg(0x3d, 0x700); - - lcd_write_reg(0x50, 0x0); - lcd_write_reg(0x51, 0xef); - lcd_write_reg(0x52, 0x0); - lcd_write_reg(0x53, 0x13f); - - lcd_write_reg(0x60, 0x2700); - lcd_write_reg(0x61, 0x1); - lcd_write_reg(0x6a, 0x0); - - lcd_write_reg(0x80, 0x0); - lcd_write_reg(0x81, 0x0); - lcd_write_reg(0x82, 0x0); - lcd_write_reg(0x83, 0x0); - lcd_write_reg(0x84, 0x0); - lcd_write_reg(0x85, 0x0); - - lcd_write_reg(0x90, 0x10); - lcd_write_reg(0x92, 0x0); - lcd_write_reg(0x93, 0x3); - lcd_write_reg(0x95, 0x110); - lcd_write_reg(0x97, 0x0); - lcd_write_reg(0x98, 0x0); - - lcd_write_reg(0xc, 0x000); // SYSTEM mode - lcd_write_reg(0x7, 0x173); - sleep(HZ/10); -} - -{ - - lcd_power_on(); - - lcd_write_reg(0x7, 0x160); - lcd_write_reg(0x10, 0x17B1); -} - -void unknown03(bool r0) -{ - if (r0) - GPIOJ_ENABLE &= ~0x2; - else - { - GPIOJ_ENABLE |= 0x2; - GPIOJ_OUTPUT_EN |= 0x2; - GPIOJ_OUTPUT_VAL &= ~0x02; - } -} - -void lcd_init_device(void) -{ - lcd_power_on(); -} - -#if defined(HAVE_LCD_ENABLE) -bool lcd_active(void) -{ - return display_on; -} - -void lcd_enable(bool on) -{ - display_on = on; - if(on) - { - lcd_write_reg(0x10, 0x17B0); - udelay(100); - lcd_write_reg(0x7, 0x173); - } - else - { - lcd_write_reg(0x7, 0x160); - lcd_write_reg(0x10, 0x17B1); - } -} -#endif - -static inline void lcd_send_frame_byte(unsigned char data) -{ - for(int bit = 0; bit < 8; bit++) - { - if(data & 0x80) - GPIO_SET_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN); - else - GPIO_CLEAR_BITWISE(LCD_DATA_OUT_GPIO, 1 << LCD_DATA_OUT_PIN); - data <<= 1; - GPIO_CLEAR_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - } -} - -static void lcd_send_frame(const fb_data *addr, int count) -{ - GPIO_SET_BITWISE(LCD_CLOCK_GPIO, 1 << LCD_CLOCK_PIN); - GPIO_CLEAR_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN); - - lcd_send_frame_byte(0x72); - while(count-- > 0) - { - lcd_send_frame_byte(*addr >> 8); - lcd_send_frame_byte(*addr++ & 0xff); - } - - GPIO_SET_BITWISE(LCD_CS_GPIO, 1 << LCD_CS_PIN); -} - -void lcd_update(void) -{ - if(!display_on) - return; - lcd_write_reg(0x20, 0x0); - lcd_write_reg(0x21, 0x0); - lcd_send_cmd(0x22); - lcd_send_frame(FBADDR(0, 0), LCD_WIDTH * LCD_HEIGHT); -} - -/* Update a fraction of the display. */ -void lcd_update_rect(int x, int y, int width, int height) -{ - (void)x; - (void)y; - (void)width; - (void)height; - lcd_update(); -} - - -/*** hardware configuration ***/ - -void lcd_set_contrast(int val) -{ - (void)val; -} - -void lcd_set_invert_display(bool yesno) -{ - (void)yesno; -} - -/* turn the display upside down (call lcd_update() afterwards) */ -void lcd_set_flip(bool yesno) -{ - (void)yesno; -} diff --git a/firmware/target/arm/sandisk/sansa-view/power-view.c b/firmware/target/arm/sandisk/sansa-view/power-view.c deleted file mode 100644 index 7df7296718..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/power-view.c +++ /dev/null @@ -1,28 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -void power_init(void) -{ -} - -void power_off(void) -{ -} diff --git a/firmware/target/arm/sandisk/sansa-view/powermgmt-view.c b/firmware/target/arm/sandisk/sansa-view/powermgmt-view.c deleted file mode 100644 index 649e667707..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/powermgmt-view.c +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "adc.h" -#include "powermgmt.h" - -int _battery_voltage(void) -{ - return 0; -} - -/* FIXME - next 4 functions taken from e200 - last 2 will need - to be updated */ -unsigned short battery_level_disksafe = 3400; - -unsigned short battery_level_shutoff = 3300; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ - /* Sansa Li Ion 750mAH FIXME */ - 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = -{ - /* Sansa Li Ion 750mAH FIXME */ - 3300, 3680, 3740, 3760, 3780, 3810, 3870, 3930, 3970, 4070, 4160 -}; diff --git a/firmware/target/arm/sandisk/sansa-view/usb-view.c b/firmware/target/arm/sandisk/sansa-view/usb-view.c deleted file mode 100644 index 6356ee6ffd..0000000000 --- a/firmware/target/arm/sandisk/sansa-view/usb-view.c +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Robert Keevil - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "usb.h" - -int usb_detect(void) -{ - return.0; -} - -void usb_enable(bool on) -{ - (void)on; -} - -void usb_init_device(void) -{ -} diff --git a/tools/builds.pm b/tools/builds.pm index 595a20c517..02a4b6fea8 100644 --- a/tools/builds.pm +++ b/tools/builds.pm @@ -322,10 +322,6 @@ $releasenotes="/wiki/ReleaseNotes400"; status => 1, sim => 1, }, - 'sansaview' => { - name => 'SanDisk Sansa View', - status => 1, - }, 'vibe500' => { name => 'Packard Bell Vibe 500', status => 3, diff --git a/tools/configure b/tools/configure index 61da0e36ef..1e44235cb3 100755 --- a/tools/configure +++ b/tools/configure @@ -1691,48 +1691,47 @@ cat < Date: Wed, 4 Feb 2026 13:25:56 +0200 Subject: [PATCH 28/75] hiby: debug_menu: Add RAM info for hosted targets Change-Id: I627cdd71fc7c923b2e917c395d6c2d1111147b17 --- apps/debug_menu.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 61788fe559..8f4e1d673c 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -143,6 +143,10 @@ #include "iap.h" #endif +#ifdef HIBY_LINUX +#include +#endif + #define SCREEN_MAX_CHARS (LCD_WIDTH / SYSFONT_WIDTH) static const char* threads_getname(int selected_item, void *data, @@ -2800,6 +2804,55 @@ static bool dbg_bootflash_dump(void) { } #endif +#ifdef HIBY_LINUX +static bool view_ram_info(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, "RAM Info", 0, NULL); + + simplelist_reset_lines(); + simplelist_addline("Rockbox: %d MB", MEMORYSIZE); + + struct sysinfo sys_info; + if (sysinfo(&sys_info) == 0) { + long total_ram = sys_info.totalram * sys_info.mem_unit / 1024 / 1024; + long free_ram = sys_info.freeram * sys_info.mem_unit / 1024 / 1024; + long buffer_ram = sys_info.bufferram * sys_info.mem_unit / 1024 / 1024; + simplelist_addline("Total RAM: %ld MB", total_ram); + simplelist_addline("Free RAM: %ld MB", free_ram); + simplelist_addline("Buffer RAM: %ld MB", buffer_ram); + + /* Try to read MemAvailable from /proc/meminfo for a better "free" estimate */ + FILE *fp = fopen("/proc/meminfo", "r"); + if (fp) { + char line[128]; + long mem_avail = -1; + long cached = -1; + while (fgets(line, sizeof(line), fp)) { + if (sscanf(line, "MemAvailable: %ld kB", &mem_avail) == 1) { + mem_avail /= 1024; + } + else if (sscanf(line, "Cached: %ld kB", &cached) == 1) { + cached /= 1024; + } + } + fclose(fp); + + if (mem_avail != -1) { + /* Estimate of how much memory is available for starting new applications */ + simplelist_addline("Available: %ld MB", mem_avail); + } + if (cached != -1) { + /* Memory used by the page cache. */ + simplelist_addline("Cached: %ld MB", cached); + } + } + } + + return simplelist_show_list(&info); +} +#endif + /****** The menu *********/ static const struct { unsigned char *desc; /* string or ID */ @@ -2839,6 +2892,9 @@ static const struct { #ifdef __linux__ { "View CPU stats", dbg_cpuinfo }, #endif +#ifdef HIBY_LINUX + { "View RAM info", view_ram_info }, +#endif #if (CONFIG_BATTERY_MEASURE != 0) && !defined(SIMULATOR) { "View battery", view_battery }, #endif From 91ec6f1e1efe41577c2414cfcf62ec86d4a90e95 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Wed, 4 Feb 2026 10:49:09 +0000 Subject: [PATCH 29/75] make: allow building flat binary plugins on USE_ELF targets From what I can see the Creative Zen Vision ports, which were the only ones to set USE_ELF prior to the Echo R1 port, do not work except for a bootloader and never even got to the point of booting Rockbox. This explains why they build codecs and plugins as ELF binaries, yet there is no code to load ELF format codecs or plugins. Anyhow, add a new setting, PLUGIN_USE_ELF, which controls whether plugins & codecs are left as ELF or converted to flat binaries. This makes it possible for the Echo R1 to use the flat binary .rock format, and makes it possible to have ELF plugins/codecs on targets with non-ELF main binaries. Seeing as nothing needs ELF plugins/codecs right now, the new default is to generate them as flat binaries unless the target requests otherwise. Change-Id: I9ffae669978de5cc7ad214cd50d97ad6e8938394 --- apps/plugins/chessbox/chessbox.make | 2 +- apps/plugins/goban/goban.make | 2 +- apps/plugins/imageviewer/imageviewer.make | 2 +- apps/plugins/lua/lua.make | 2 +- apps/plugins/pictureflow/pictureflow.make | 2 +- apps/plugins/plugins.make | 2 +- apps/plugins/puzzles/puzzles.make | 4 ++-- apps/plugins/rockboy/rockboy.make | 2 +- apps/plugins/sdl/sdl.make | 4 ++-- apps/plugins/zxbox/zxbox.make | 2 +- lib/rbcodec/codecs/codecs.make | 2 +- tools/configure | 2 ++ tools/functions.make | 5 +++++ 13 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/plugins/chessbox/chessbox.make b/apps/plugins/chessbox/chessbox.make index 87f0a6ecc0..77a038febc 100644 --- a/apps/plugins/chessbox/chessbox.make +++ b/apps/plugins/chessbox/chessbox.make @@ -39,7 +39,7 @@ $(CHESSBOX_OBJDIR)/chessbox.ovl: $(CHESSBOX_OBJ) $(CHESSBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CHESSBOX_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling chessbox with extra flags $(CHESSBOX_OBJDIR)/%.o: $(CHESSBOX_SRCDIR)/%.c $(CHESSBOX_SRCDIR)/chessbox.make diff --git a/apps/plugins/goban/goban.make b/apps/plugins/goban/goban.make index 2201dc60f4..ae221e8840 100644 --- a/apps/plugins/goban/goban.make +++ b/apps/plugins/goban/goban.make @@ -36,4 +36,4 @@ $(GOBAN_BUILDDIR)/goban.ovl: $(GOBAN_OBJ) $(GOBAN_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(GOBAN_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) diff --git a/apps/plugins/imageviewer/imageviewer.make b/apps/plugins/imageviewer/imageviewer.make index 23f9813357..25701fc6d2 100644 --- a/apps/plugins/imageviewer/imageviewer.make +++ b/apps/plugins/imageviewer/imageviewer.make @@ -40,7 +40,7 @@ $(IMGVBUILDDIR)/%.ovl: $(IMGDEC_OUTLDS) $(filter-out $(PLUGIN_CRT0),$(filter %.o, $^)) \ $(filter %.a, $+) \ -lgcc $(IMGDEC_OVLFLAGS) - $(SILENT)$(call objcopy,$(IMGVBUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(IMGVBUILDDIR)/$*.elf,$@) # rule to create reference map for image decoder $(IMGVBUILDDIR)/%.refmap: $(APPSDIR)/plugin.h $(IMGVSRCDIR)/imageviewer.h $(PLUGINLINK_LDS) $(PLUGIN_LIBS) diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make index a5d1813a8b..ec8a7e8b38 100644 --- a/apps/plugins/lua/lua.make +++ b/apps/plugins/lua/lua.make @@ -73,7 +73,7 @@ $(LUA_BUILDDIR)/lua.ovl: $(LUA_OBJ) $(TLSFLIB) $(LUA_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(LUA_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) $(LUA_BUILDDIR): $(call PRINTS,MKDIR $@)mkdir -p $(LUA_BUILDDIR)/ diff --git a/apps/plugins/pictureflow/pictureflow.make b/apps/plugins/pictureflow/pictureflow.make index e13ba61a72..7436af2433 100644 --- a/apps/plugins/pictureflow/pictureflow.make +++ b/apps/plugins/pictureflow/pictureflow.make @@ -37,7 +37,7 @@ $(PICTUREFLOW_OBJDIR)/pictureflow.ovl: $(PICTUREFLOW_OBJ) $(PICTUREFLOW_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PICTUREFLOW_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling pictureflow with extra flags $(PICTUREFLOW_OBJDIR)/%.o: $(PICTUREFLOW_SRCDIR)/%.c $(PICTUREFLOW_SRCDIR)/pictureflow.make diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make index 2babb329a5..8620d3f9c0 100644 --- a/apps/plugins/plugins.make +++ b/apps/plugins/plugins.make @@ -169,7 +169,7 @@ $(BUILDDIR)/%.rock: $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PLUGINLDFLAGS) - $(SILENT)$(call objcopy,$(BUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(BUILDDIR)/$*.elf,$@) $(BUILDDIR)/apps/plugins/%.lua: $(ROOTDIR)/apps/plugins/%.lua $(call PRINTS,CP $(subst $(ROOTDIR)/,,$<))cp $< $(BUILDDIR)/apps/plugins/ diff --git a/apps/plugins/puzzles/puzzles.make b/apps/plugins/puzzles/puzzles.make index 91e84c50da..4c3322d32e 100644 --- a/apps/plugins/puzzles/puzzles.make +++ b/apps/plugins/puzzles/puzzles.make @@ -49,14 +49,14 @@ $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/%.o $(PUZZLES_OBJDIR)/help/% $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/unfinished/%.o $(PUZZLES_OBJDIR)/help/%.o $(PUZZLES_SHARED_OBJ) $(TLSFLIB) $(call PRINTS,LD $(@F))$(CC) $(PLUGINFLAGS) -o $(PUZZLES_OBJDIR)/$*.elf \ $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_SRCDIR)/rbcompat.h: $(APPSDIR)/plugin.h \ $(APPSDIR)/plugins/lib/pluginlib_exit.h \ diff --git a/apps/plugins/rockboy/rockboy.make b/apps/plugins/rockboy/rockboy.make index 8be44ef9c5..8725604933 100644 --- a/apps/plugins/rockboy/rockboy.make +++ b/apps/plugins/rockboy/rockboy.make @@ -37,7 +37,7 @@ $(ROCKBOY_OBJDIR)/rockboy.ovl: $(ROCKBOY_OBJ) $(ROCKBOY_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ROCKBOY_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special rule to build with devkitarm gcc ifeq ($(APP_TYPE),ctru-app) diff --git a/apps/plugins/sdl/sdl.make b/apps/plugins/sdl/sdl.make index 9d666bd732..7234656268 100644 --- a/apps/plugins/sdl/sdl.make +++ b/apps/plugins/sdl/sdl.make @@ -95,7 +95,7 @@ $(SDL_OBJDIR)/wolf3d.ovl: $(SDL_OBJ) $(WOLF3D_OBJ) $(TLSFLIB) $(WOLF3D_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(WOLF3D_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # Quake ### @@ -113,7 +113,7 @@ $(SDL_OBJDIR)/quake.ovl: $(SDL_OBJ) $(QUAKE_OBJ) $(TLSFLIB) $(QUAKE_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(QUAKE_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) ### diff --git a/apps/plugins/zxbox/zxbox.make b/apps/plugins/zxbox/zxbox.make index 4638d5f0a2..1ee64d6fb5 100644 --- a/apps/plugins/zxbox/zxbox.make +++ b/apps/plugins/zxbox/zxbox.make @@ -45,7 +45,7 @@ $(ZXBOX_OBJDIR)/zxbox.ovl: $(ZXBOX_OBJ) $(ZXBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ZXBOX_LDFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling zxbox with extra flags $(ZXBOX_OBJDIR)/%.o: $(ZXBOX_SRCDIR)/%.c $(ZXBOX_SRCDIR)/zxbox.make diff --git a/lib/rbcodec/codecs/codecs.make b/lib/rbcodec/codecs/codecs.make index 6d790f5d9a..6f20a8c101 100644 --- a/lib/rbcodec/codecs/codecs.make +++ b/lib/rbcodec/codecs/codecs.make @@ -245,4 +245,4 @@ $(CODECDIR)/%.codec: $(CODECDIR)/%.o $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CODECLDFLAGS) - $(SILENT)$(call objcopy,$(CODECDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(CODECDIR)/$*.elf,$@) diff --git a/tools/configure b/tools/configure index 1e44235cb3..b166cf5a07 100755 --- a/tools/configure +++ b/tools/configure @@ -1755,6 +1755,7 @@ fi x1000tools="$genericbitmaptools scramble mkspl-x1000 uclpack" # default to not generating ELF files USE_ELF="no" + PLUGIN_USE_ELF="no" # ---- For each target ---- # @@ -5006,6 +5007,7 @@ export TTS_ENGINE=${TTS_ENGINE} export ENC_OPTS=${ENC_OPTS} export ENCODER=${ENCODER} export USE_ELF=${USE_ELF} +export PLUGIN_USE_ELF=${PLUGIN_USE_ELF} export RBDIR=${rbdir} export ROCKBOX_SHARE_PATH=${sharedir} export ROCKBOX_BINARY_PATH=${bindir} diff --git a/tools/functions.make b/tools/functions.make index 1c16e1415f..772db0eeda 100644 --- a/tools/functions.make +++ b/tools/functions.make @@ -38,15 +38,20 @@ a2lnk = $(patsubst lib%.a,-l%,$(notdir $(1))) # handles the $(1) == $(2) case too ifndef APP_TYPE objcopy = $(OC) $(if $(filter yes, $(USE_ELF)), -S -x, -O binary) $(1) $(2) # objcopy native +objcopy_plugin = $(OC) $(if $(filter yes, $(PLUGIN_USE_ELF)), -S -x, -O binary) $(1) $(2) else ifneq (,$(findstring sdl-sim,$(APP_TYPE))) objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy simulator +objcopy_plugin = objcopy else ifneq (,$(findstring ctru,$(MODELNAME))) # 3dsxtool requires symbols objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) +objcopy_plugin = objcopy else ifdef DEBUG objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy hosted (DEBUG) + objcopy_plugin = objcopy else objcopy = $(OC) -S -x $(1) $(2) # objcopy hosted (!DEBUG) + objcopy_plugin = objcopy endif endif From bbe72761a4b37c0deb70009185511a10f2b8a8bd Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 3 Feb 2026 21:02:44 +0000 Subject: [PATCH 30/75] ipodnano3g/4g: fix compile issues for normal build Some purely mechanical fixes to get the normal build working. Besides missing symbols all the plugins and codecs build just fine. Change-Id: I946ba39096a46be8308450bafd51a0995db8e323 --- apps/lang/basque.lang | 12 +++++----- apps/lang/bulgarian.lang | 12 +++++----- apps/lang/catala.lang | 12 +++++----- apps/lang/chinese-simp.lang | 12 +++++----- apps/lang/chinese-trad.lang | 12 +++++----- apps/lang/czech.lang | 12 +++++----- apps/lang/dansk.lang | 12 +++++----- apps/lang/deutsch.lang | 12 +++++----- apps/lang/english-us.lang | 12 +++++----- apps/lang/english.lang | 12 +++++----- apps/lang/espanol.lang | 12 +++++----- apps/lang/finnish.lang | 12 +++++----- apps/lang/francais.lang | 12 +++++----- apps/lang/galego.lang | 12 +++++----- apps/lang/greek.lang | 12 +++++----- apps/lang/hebrew.lang | 12 +++++----- apps/lang/hrvatski.lang | 12 +++++----- apps/lang/italiano.lang | 12 +++++----- apps/lang/japanese.lang | 12 +++++----- apps/lang/korean.lang | 12 +++++----- apps/lang/latviesu.lang | 12 +++++----- apps/lang/lietuviu.lang | 12 +++++----- apps/lang/magyar.lang | 12 +++++----- apps/lang/moldoveneste.lang | 12 +++++----- apps/lang/nederlands.lang | 12 +++++----- apps/lang/norsk-nynorsk.lang | 12 +++++----- apps/lang/norsk.lang | 12 +++++----- apps/lang/polski.lang | 12 +++++----- apps/lang/portugues-brasileiro.lang | 12 +++++----- apps/lang/portugues.lang | 12 +++++----- apps/lang/romaneste.lang | 12 +++++----- apps/lang/russian.lang | 12 +++++----- apps/lang/slovak.lang | 12 +++++----- apps/lang/slovenscina.lang | 12 +++++----- apps/lang/srpski.lang | 12 +++++----- apps/lang/svenska.lang | 12 +++++----- apps/lang/tagalog.lang | 12 +++++----- apps/lang/thai.lang | 12 +++++----- apps/lang/turkce.lang | 12 +++++----- apps/lang/ukrainian.lang | 12 +++++----- apps/lang/vietnamese.lang | 12 +++++----- apps/lang/vlaams.lang | 12 +++++----- apps/lang/walon.lang | 12 +++++----- firmware/export/config/ipodnano3g.h | 1 - firmware/export/config/ipodnano4g.h | 1 - .../arm/s5l8702/ipodnano3g/adc-nano3g.c | 17 ++++++++++++++ .../arm/s5l8702/ipodnano3g/nand-nano3g.c | 22 +++++++++++++++++++ .../arm/s5l8702/ipodnano3g/pmu-nano3g.c | 2 +- .../arm/s5l8702/ipodnano3g/powermgmt-nano3g.c | 15 ++++--------- .../arm/s5l8702/ipodnano4g/adc-nano4g.c | 17 ++++++++++++++ .../arm/s5l8702/ipodnano4g/cscodec-nano4g.c | 1 + .../arm/s5l8702/ipodnano4g/nand-nano4g.c | 22 +++++++++++++++++++ .../arm/s5l8702/ipodnano4g/pmu-nano4g.c | 2 +- .../arm/s5l8702/ipodnano4g/powermgmt-nano4g.c | 15 ++++--------- .../arm/s5l8702/ipodnano4g/serial-nano4g.c | 2 +- firmware/target/arm/s5l8702/lcd-s5l8702.c | 2 +- 56 files changed, 349 insertions(+), 286 deletions(-) diff --git a/apps/lang/basque.lang b/apps/lang/basque.lang index 4aa63f8cc3..44d62202bf 100644 --- a/apps/lang/basque.lang +++ b/apps/lang/basque.lang @@ -10142,15 +10142,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Baxuen Mozketa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Baxuen Mozketa" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Baxuen Mozketa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Baxuen Mozketa" @@ -10159,15 +10159,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Altuen Mozketa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Altuen Mozketa" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Altuen Mozketa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Altuen Mozketa" diff --git a/apps/lang/bulgarian.lang b/apps/lang/bulgarian.lang index 179b73e2ec..06f75d50a4 100644 --- a/apps/lang/bulgarian.lang +++ b/apps/lang/bulgarian.lang @@ -9105,15 +9105,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на баса" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на баса" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на баса" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на баса" @@ -9122,15 +9122,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на високите" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на високите" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на високите" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отрязване на високите" diff --git a/apps/lang/catala.lang b/apps/lang/catala.lang index 853d3c4409..dbc9aa17ed 100644 --- a/apps/lang/catala.lang +++ b/apps/lang/catala.lang @@ -10136,15 +10136,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Freq. de tall de baixos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Freq. de tall de baixos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frequència de tall de baix" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frequència de tall de baix" @@ -10153,15 +10153,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Freq. de tall d'aguts" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Freq. de tall d'aguts" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frequència de tall d'aguts" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frequència de tall d'aguts" diff --git a/apps/lang/chinese-simp.lang b/apps/lang/chinese-simp.lang index 4448432ded..0495b17a0a 100644 --- a/apps/lang/chinese-simp.lang +++ b/apps/lang/chinese-simp.lang @@ -8889,15 +8889,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低频截止频率" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低频截止频率" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低频截止频率" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低频截止频率" @@ -9095,15 +9095,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高频截止频率" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高频截止频率" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高频截止频率" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高频截止频率" diff --git a/apps/lang/chinese-trad.lang b/apps/lang/chinese-trad.lang index 5e92c5b1d3..cc7eca6ab4 100644 --- a/apps/lang/chinese-trad.lang +++ b/apps/lang/chinese-trad.lang @@ -9160,15 +9160,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音截斷" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音截斷" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音截斷" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音截斷" @@ -9366,15 +9366,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音截斷" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音截斷" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音截斷" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音截斷" diff --git a/apps/lang/czech.lang b/apps/lang/czech.lang index 305b2a5589..90a4246006 100644 --- a/apps/lang/czech.lang +++ b/apps/lang/czech.lang @@ -10159,15 +10159,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí basů" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí basů" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí basů" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí basů" @@ -10176,15 +10176,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí výšek" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí výšek" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí výšek" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Oříznutí výšek" diff --git a/apps/lang/dansk.lang b/apps/lang/dansk.lang index 964c60d106..a0fbcacdd0 100644 --- a/apps/lang/dansk.lang +++ b/apps/lang/dansk.lang @@ -9936,15 +9936,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgrænse" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgrænse" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgrænse" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgrænse" @@ -10142,15 +10142,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrænse" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrænse" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrænse" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrænse" diff --git a/apps/lang/deutsch.lang b/apps/lang/deutsch.lang index 572187cef9..8a8f5ae5a1 100644 --- a/apps/lang/deutsch.lang +++ b/apps/lang/deutsch.lang @@ -9092,15 +9092,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiefengrenzfrequenz" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiefengrenzfrequenz" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiefengrenzfrequenz" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiefengrenzfrequenz" @@ -9109,15 +9109,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Höhengrenzfrequenz" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Höhengrenzfrequenz" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Höhengrenzfrequenz" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Höhengrenzfrequenz" diff --git a/apps/lang/english-us.lang b/apps/lang/english-us.lang index 1063dbc539..1b3a7d83ab 100644 --- a/apps/lang/english-us.lang +++ b/apps/lang/english-us.lang @@ -9113,15 +9113,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" @@ -9130,15 +9130,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 52adf54617..de9eb1d942 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -9284,15 +9284,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" @@ -9301,15 +9301,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" diff --git a/apps/lang/espanol.lang b/apps/lang/espanol.lang index 1eba90de21..d6d989d395 100644 --- a/apps/lang/espanol.lang +++ b/apps/lang/espanol.lang @@ -7392,15 +7392,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de bajos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de bajos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de bajos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de bajos" @@ -8934,15 +8934,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frec. de corte de agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frec. de corte de agudos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frecuencia de corte de agudos" diff --git a/apps/lang/finnish.lang b/apps/lang/finnish.lang index 7a9b95cdbc..5476e09018 100644 --- a/apps/lang/finnish.lang +++ b/apps/lang/finnish.lang @@ -10127,15 +10127,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basson katkaisu" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basson katkaisu" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basson katkaisu" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basson katkaisu" @@ -10144,15 +10144,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantin katkaisu" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantin katkaisu" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantin katkaisu" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantin katkaisu" diff --git a/apps/lang/francais.lang b/apps/lang/francais.lang index bbb195f4e0..316c3eef6c 100644 --- a/apps/lang/francais.lang +++ b/apps/lang/francais.lang @@ -9201,15 +9201,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour basses" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour basses" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour les basses" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour les basses" @@ -9218,15 +9218,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour aigus" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour aigus" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour les aigus" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Fréquence de coupure pour les aigus" diff --git a/apps/lang/galego.lang b/apps/lang/galego.lang index e9dfaf00e3..c7b2a62db7 100644 --- a/apps/lang/galego.lang +++ b/apps/lang/galego.lang @@ -5985,15 +5985,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de baixos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de baixos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de baixos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de baixos" @@ -11323,15 +11323,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de agudos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de agudos" diff --git a/apps/lang/greek.lang b/apps/lang/greek.lang index f2dc518393..b9f07d4c33 100644 --- a/apps/lang/greek.lang +++ b/apps/lang/greek.lang @@ -10054,15 +10054,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή μπάσων" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή μπάσων" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή μπάσων" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή μπάσων" @@ -10071,15 +10071,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή πρίμων" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή πρίμων" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή πρίμων" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Αποκοπή πρίμων" diff --git a/apps/lang/hebrew.lang b/apps/lang/hebrew.lang index 16b4d91285..b49104adb0 100644 --- a/apps/lang/hebrew.lang +++ b/apps/lang/hebrew.lang @@ -10175,15 +10175,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך בס" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך בס" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך בס" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך בס" @@ -10192,15 +10192,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך טרבל" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך טרבל" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך טרבל" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "חיתוך טרבל" diff --git a/apps/lang/hrvatski.lang b/apps/lang/hrvatski.lang index 8e89965509..55b8d1beeb 100644 --- a/apps/lang/hrvatski.lang +++ b/apps/lang/hrvatski.lang @@ -10139,15 +10139,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje basa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje basa" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje basa" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje basa" @@ -10156,15 +10156,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje treblea" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje treblea" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje treblea" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Odsijecanje treblea" diff --git a/apps/lang/italiano.lang b/apps/lang/italiano.lang index 22f37d489e..9d873e219f 100644 --- a/apps/lang/italiano.lang +++ b/apps/lang/italiano.lang @@ -9089,15 +9089,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Bassi" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Bassi" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Bassi" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Bassi" @@ -9106,15 +9106,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Alti" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Alti" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Alti" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Taglio Alti" diff --git a/apps/lang/japanese.lang b/apps/lang/japanese.lang index 26a8b767c2..dcabb9ab73 100644 --- a/apps/lang/japanese.lang +++ b/apps/lang/japanese.lang @@ -9176,15 +9176,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音域カットオフ" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音域カットオフ" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音域カットオフ" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "低音域カットオフ" @@ -9193,15 +9193,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音域カットオフ" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音域カットオフ" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音域カットオフ" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "高音域カットオフ" diff --git a/apps/lang/korean.lang b/apps/lang/korean.lang index 77ec04eafc..441d5545cd 100644 --- a/apps/lang/korean.lang +++ b/apps/lang/korean.lang @@ -9131,15 +9131,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "저음 컷오프" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "저음 컷오프" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "저음 컷오프" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "저음 컷오프" @@ -9148,15 +9148,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "고음 컷오프" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "고음 컷오프" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "고음 컷오프" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "고음 컷오프" diff --git a/apps/lang/latviesu.lang b/apps/lang/latviesu.lang index 67136695c2..ddaf06299b 100644 --- a/apps/lang/latviesu.lang +++ b/apps/lang/latviesu.lang @@ -9102,15 +9102,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basu robežfrekvence" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basu robežfrekvence" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basu robežfrekvence" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basu robežfrekvence" @@ -9119,15 +9119,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Augšu robežfrekvence" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Augšu robežfrekvence" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Augšu robežfrekvence" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Augšu robežfrekvence" diff --git a/apps/lang/lietuviu.lang b/apps/lang/lietuviu.lang index 60a32afcfa..5423cb6ba7 100644 --- a/apps/lang/lietuviu.lang +++ b/apps/lang/lietuviu.lang @@ -10217,15 +10217,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bosų nukirpimas" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bosų nukirpimas" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bosų nukirpimas" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bosų nukirpimas" @@ -10234,15 +10234,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Aukštų daž. Nukirpimas" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Aukštų daž. Nukirpimas" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Aukštų daž. Nukirpimas" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Aukštų daž. Nukirpimas" diff --git a/apps/lang/magyar.lang b/apps/lang/magyar.lang index 0836f589eb..e054ff7e24 100644 --- a/apps/lang/magyar.lang +++ b/apps/lang/magyar.lang @@ -8922,15 +8922,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Alsó határfrekvencia" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Alsó határfrekvencia" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Alsó határfrekvencia" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Alsó határfrekvencia" @@ -9599,15 +9599,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Magas határfrekvencia" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Magas határfrekvencia" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Magas határfrekvencia" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Magas határfrekvencia" diff --git a/apps/lang/moldoveneste.lang b/apps/lang/moldoveneste.lang index 142842c00a..d3b315e8d6 100644 --- a/apps/lang/moldoveneste.lang +++ b/apps/lang/moldoveneste.lang @@ -2232,15 +2232,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" @@ -8280,15 +8280,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" diff --git a/apps/lang/nederlands.lang b/apps/lang/nederlands.lang index 88f73c1fa4..d5ef15c06c 100644 --- a/apps/lang/nederlands.lang +++ b/apps/lang/nederlands.lang @@ -9078,15 +9078,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" @@ -9095,15 +9095,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" diff --git a/apps/lang/norsk-nynorsk.lang b/apps/lang/norsk-nynorsk.lang index c62796a27b..928805ace2 100644 --- a/apps/lang/norsk-nynorsk.lang +++ b/apps/lang/norsk-nynorsk.lang @@ -9877,15 +9877,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bassgrense" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bassgrense" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bassgrense" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bassgrense" @@ -10083,15 +10083,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrense" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrense" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrense" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgrense" diff --git a/apps/lang/norsk.lang b/apps/lang/norsk.lang index 8c498a9616..71f96172b7 100644 --- a/apps/lang/norsk.lang +++ b/apps/lang/norsk.lang @@ -8846,15 +8846,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass-knekkfrekvens" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass-knekkfrekvens" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass-knekkfrekvens" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass-knekkfrekvens" @@ -9901,15 +9901,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantknekkfrekvens" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantknekkfrekvens" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantknekkfrekvens" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantknekkfrekvens" diff --git a/apps/lang/polski.lang b/apps/lang/polski.lang index 7dc97aebc8..f65875e0d5 100644 --- a/apps/lang/polski.lang +++ b/apps/lang/polski.lang @@ -9095,15 +9095,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie basów" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie basów" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie basów" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie basów" @@ -9112,15 +9112,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie tonów niskich" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie tonów niskich" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie tonów niskich" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Ścięcie tonów niskich" diff --git a/apps/lang/portugues-brasileiro.lang b/apps/lang/portugues-brasileiro.lang index fd7509b6db..b16f331b76 100644 --- a/apps/lang/portugues-brasileiro.lang +++ b/apps/lang/portugues-brasileiro.lang @@ -9171,15 +9171,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" @@ -9188,15 +9188,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" diff --git a/apps/lang/portugues.lang b/apps/lang/portugues.lang index 5853ff9397..8eb325986f 100644 --- a/apps/lang/portugues.lang +++ b/apps/lang/portugues.lang @@ -10140,15 +10140,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Graves" @@ -10515,15 +10515,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte de Agudos" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte dos Agudos" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Corte dos Agudos" diff --git a/apps/lang/romaneste.lang b/apps/lang/romaneste.lang index aa30868589..c83af7ad2f 100644 --- a/apps/lang/romaneste.lang +++ b/apps/lang/romaneste.lang @@ -2232,15 +2232,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Retezare basuri" @@ -8280,15 +8280,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tăiere inalte" diff --git a/apps/lang/russian.lang b/apps/lang/russian.lang index d282fd5c09..01df4bb766 100644 --- a/apps/lang/russian.lang +++ b/apps/lang/russian.lang @@ -6289,15 +6289,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отсечение баса" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отсечение баса" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отсечение баса" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Отсечение баса" @@ -8856,15 +8856,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Подавление высоких частот" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Подавление высоких частот" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Подавление высоких частот" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Подавление высоких частот" diff --git a/apps/lang/slovak.lang b/apps/lang/slovak.lang index 4e347617eb..6c4589903e 100644 --- a/apps/lang/slovak.lang +++ b/apps/lang/slovak.lang @@ -9087,15 +9087,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica hĺbok" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica hĺbok" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica hĺbok" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica hĺbok" @@ -9104,15 +9104,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica výšok" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica výšok" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica výšok" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Hranica výšok" diff --git a/apps/lang/slovenscina.lang b/apps/lang/slovenscina.lang index 9d763cec9b..1f88f15c2d 100644 --- a/apps/lang/slovenscina.lang +++ b/apps/lang/slovenscina.lang @@ -2988,15 +2988,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" @@ -10628,15 +10628,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" diff --git a/apps/lang/srpski.lang b/apps/lang/srpski.lang index e043cf8fb0..61e2015854 100644 --- a/apps/lang/srpski.lang +++ b/apps/lang/srpski.lang @@ -9213,15 +9213,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фрекв. за ниске" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фрекв. за ниске" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фреквенција за ниске" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фреквенција за ниске" @@ -9230,15 +9230,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фрекв. за високе" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фрекв. за високе" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фреквенција за високе" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Гранична фреквенција за високе" diff --git a/apps/lang/svenska.lang b/apps/lang/svenska.lang index 335b1e975e..671fecaf46 100644 --- a/apps/lang/svenska.lang +++ b/apps/lang/svenska.lang @@ -9110,15 +9110,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgräns" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgräns" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgräns" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Basgräns" @@ -9127,15 +9127,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgräns" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgräns" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgräns" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Diskantgräns" diff --git a/apps/lang/tagalog.lang b/apps/lang/tagalog.lang index b7e1dfab51..b259c86da6 100644 --- a/apps/lang/tagalog.lang +++ b/apps/lang/tagalog.lang @@ -6019,15 +6019,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass araw ng katapusan" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass araw ng katapusan" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass araw ng katapusan" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass araw ng katapusan" @@ -9590,15 +9590,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Pagtatluhin araw ng katapusan" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Pagtatluhin araw ng katapusan" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Pagtatluhin araw ng katapusan" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Pagtatluhin araw ng katapusan" diff --git a/apps/lang/thai.lang b/apps/lang/thai.lang index f2be4962e9..bcd4505eab 100644 --- a/apps/lang/thai.lang +++ b/apps/lang/thai.lang @@ -9918,15 +9918,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "ความถี่ตัดเสียงทุ้ม" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "ความถี่ตัดเสียงทุ้ม" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" @@ -10152,15 +10152,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "ความถี่ตัดเสียงแหลม" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "ความถี่ตัดเสียงแหลม" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" diff --git a/apps/lang/turkce.lang b/apps/lang/turkce.lang index 8840378509..f8cd2e1c96 100644 --- a/apps/lang/turkce.lang +++ b/apps/lang/turkce.lang @@ -5446,15 +5446,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiz Kesme" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiz Kesme" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiz Kesme" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Tiz Kesme" @@ -9553,15 +9553,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas Kesme" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas Kesme" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas Kesme" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas Kesme" diff --git a/apps/lang/ukrainian.lang b/apps/lang/ukrainian.lang index 7ef0df1edb..c5a7f1926b 100644 --- a/apps/lang/ukrainian.lang +++ b/apps/lang/ukrainian.lang @@ -9102,15 +9102,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Басу" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Басу" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Басу" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Басу" @@ -9119,15 +9119,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Високих Частот" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Високих Частот" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Високих Частот" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Вiдсiкання Високих Частот" diff --git a/apps/lang/vietnamese.lang b/apps/lang/vietnamese.lang index 11d20d84bb..1b9c6f948e 100644 --- a/apps/lang/vietnamese.lang +++ b/apps/lang/vietnamese.lang @@ -9140,15 +9140,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm trầm" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm trầm" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm trầm" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm trầm" @@ -9157,15 +9157,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm cao" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm cao" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm cao" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Khoảng cắt âm cao" diff --git a/apps/lang/vlaams.lang b/apps/lang/vlaams.lang index fac4ff2c4d..cf10d3441c 100644 --- a/apps/lang/vlaams.lang +++ b/apps/lang/vlaams.lang @@ -10103,15 +10103,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bas-afsnijfrequentie" @@ -10120,15 +10120,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble-afsnijfrequentie" diff --git a/apps/lang/walon.lang b/apps/lang/walon.lang index a53272a20c..b9d440ee63 100644 --- a/apps/lang/walon.lang +++ b/apps/lang/walon.lang @@ -10158,15 +10158,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Bass Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des basses" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des basses" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des basses" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des basses" @@ -10175,15 +10175,15 @@ user: core *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Treble Cutoff" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des hôts sons" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des hôts sons" *: none - gigabeatfx,ipod6g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des hôts sons" + gigabeatfx,ipod6g,ipodnano3g,ipodnano4g,ipodvideo,mpiohd200,mpiohd300,mrobe100: "Frécwince di côpaedje des hôts sons" diff --git a/firmware/export/config/ipodnano3g.h b/firmware/export/config/ipodnano3g.h index 1030da1717..9583b3b3d2 100644 --- a/firmware/export/config/ipodnano3g.h +++ b/firmware/export/config/ipodnano3g.h @@ -160,7 +160,6 @@ #define BATTERY_CAPACITY_MIN 300 /* min. capacity selectable */ #define BATTERY_CAPACITY_MAX 500 /* max. capacity selectable */ #define BATTERY_CAPACITY_INC 10 /* capacity increment */ -#define BATTERY_TYPES_COUNT 1 /* only one type */ #define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE diff --git a/firmware/export/config/ipodnano4g.h b/firmware/export/config/ipodnano4g.h index 7c4b6c8e73..6b651dfe65 100644 --- a/firmware/export/config/ipodnano4g.h +++ b/firmware/export/config/ipodnano4g.h @@ -162,7 +162,6 @@ #define BATTERY_CAPACITY_MIN 300 /* min. capacity selectable */ #define BATTERY_CAPACITY_MAX 500 /* max. capacity selectable */ #define BATTERY_CAPACITY_INC 10 /* capacity increment */ -#define BATTERY_TYPES_COUNT 1 /* only one type */ #define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE diff --git a/firmware/target/arm/s5l8702/ipodnano3g/adc-nano3g.c b/firmware/target/arm/s5l8702/ipodnano3g/adc-nano3g.c index 24a2bc88e9..42c5518210 100644 --- a/firmware/target/arm/s5l8702/ipodnano3g/adc-nano3g.c +++ b/firmware/target/arm/s5l8702/ipodnano3g/adc-nano3g.c @@ -41,6 +41,23 @@ unsigned short adc_read(int channel) return 0; } +int adc_read_accessory_resistor(void) +{ + return 0; +} + +unsigned int adc_read_usbdata_voltage(bool dp) +{ + (void)dp; + return 0; +} + +const char *adc_name(int channel) +{ + (void) channel; + return ""; +} + void adc_init(void) { } diff --git a/firmware/target/arm/s5l8702/ipodnano3g/nand-nano3g.c b/firmware/target/arm/s5l8702/ipodnano3g/nand-nano3g.c index 9115df03aa..9eede7b074 100644 --- a/firmware/target/arm/s5l8702/ipodnano3g/nand-nano3g.c +++ b/firmware/target/arm/s5l8702/ipodnano3g/nand-nano3g.c @@ -28,6 +28,22 @@ int nand_init(void) return 0; } +void nand_spindown(int seconds) +{ + (void)seconds; +} + +void nand_spin(void) +{ +} + +#ifdef HAVE_STORAGE_FLUSH +int nand_flush(void) +{ + return 0; +} +#endif + int nand_read_sectors(IF_MD(int drive,) sector_t start, int incount, void* inbuf) { @@ -74,3 +90,9 @@ void nand_get_info(IF_MD(int drive,) struct storage_info *info) info->revision = ""; } #endif + +long nand_last_disk_activity(void) +{ + // TODO + return 0; +} diff --git a/firmware/target/arm/s5l8702/ipodnano3g/pmu-nano3g.c b/firmware/target/arm/s5l8702/ipodnano3g/pmu-nano3g.c index c485877fa8..1de7a0918e 100644 --- a/firmware/target/arm/s5l8702/ipodnano3g/pmu-nano3g.c +++ b/firmware/target/arm/s5l8702/ipodnano3g/pmu-nano3g.c @@ -202,7 +202,7 @@ int pmu_firewire_present(void) } #endif -#if 1 // XXX: from usb-s5l8702.c +#if defined(BOOTLOADER) // XXX: from usb-s5l8702.c #include "usb.h" static int usb_status = USB_EXTRACTED; diff --git a/firmware/target/arm/s5l8702/ipodnano3g/powermgmt-nano3g.c b/firmware/target/arm/s5l8702/ipodnano3g/powermgmt-nano3g.c index 732046e74a..e126fdabab 100644 --- a/firmware/target/arm/s5l8702/ipodnano3g/powermgmt-nano3g.c +++ b/firmware/target/arm/s5l8702/ipodnano3g/powermgmt-nano3g.c @@ -26,20 +26,13 @@ #include "audiohw.h" #include "adc-target.h" -const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = -{ - 3500 -}; - -const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = -{ - 3300 -}; +const unsigned short battery_level_disksafe = 3500; +const unsigned short battery_level_shutoff = 3300; /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +const unsigned short percent_to_volt_discharge[11] = { - { 3500, 3670, 3720, 3750, 3770, 3800, 3860, 3920, 3980, 4070, 4170 } + 3500, 3670, 3720, 3750, 3770, 3800, 3860, 3920, 3980, 4070, 4170 }; #if CONFIG_CHARGING diff --git a/firmware/target/arm/s5l8702/ipodnano4g/adc-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/adc-nano4g.c index 24a2bc88e9..42c5518210 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/adc-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/adc-nano4g.c @@ -41,6 +41,23 @@ unsigned short adc_read(int channel) return 0; } +int adc_read_accessory_resistor(void) +{ + return 0; +} + +unsigned int adc_read_usbdata_voltage(bool dp) +{ + (void)dp; + return 0; +} + +const char *adc_name(int channel) +{ + (void) channel; + return ""; +} + void adc_init(void) { } diff --git a/firmware/target/arm/s5l8702/ipodnano4g/cscodec-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/cscodec-nano4g.c index 9daca61f5c..ea80cd177e 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/cscodec-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/cscodec-nano4g.c @@ -55,6 +55,7 @@ void cscodec_power(bool state) void cscodec_reset(bool state) { + (void)state; // TODO: not tested // if (state) PDAT(3) &= ~8; // else PDAT(3) |= 8; diff --git a/firmware/target/arm/s5l8702/ipodnano4g/nand-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/nand-nano4g.c index 9115df03aa..9eede7b074 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/nand-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/nand-nano4g.c @@ -28,6 +28,22 @@ int nand_init(void) return 0; } +void nand_spindown(int seconds) +{ + (void)seconds; +} + +void nand_spin(void) +{ +} + +#ifdef HAVE_STORAGE_FLUSH +int nand_flush(void) +{ + return 0; +} +#endif + int nand_read_sectors(IF_MD(int drive,) sector_t start, int incount, void* inbuf) { @@ -74,3 +90,9 @@ void nand_get_info(IF_MD(int drive,) struct storage_info *info) info->revision = ""; } #endif + +long nand_last_disk_activity(void) +{ + // TODO + return 0; +} diff --git a/firmware/target/arm/s5l8702/ipodnano4g/pmu-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/pmu-nano4g.c index d5b7ecb1bf..8b15bf6e86 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/pmu-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/pmu-nano4g.c @@ -201,7 +201,7 @@ int pmu_firewire_present(void) } #endif -#if 1 // XXX: from usb-s5l8702.c +#if defined(BOOTLOADER) // XXX: from usb-s5l8702.c #include "usb.h" static int usb_status = USB_EXTRACTED; diff --git a/firmware/target/arm/s5l8702/ipodnano4g/powermgmt-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/powermgmt-nano4g.c index 7cafe4fe66..652ccff1d8 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/powermgmt-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/powermgmt-nano4g.c @@ -26,20 +26,13 @@ #include "audiohw.h" #include "adc-target.h" -const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = -{ - 3500 -}; - -const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = -{ - 3300 -}; +const unsigned short battery_level_disksafe = 3500; +const unsigned short battery_level_shutoff = 3300; /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +const unsigned short percent_to_volt_discharge[11] = { - { 3500, 3670, 3720, 3750, 3770, 3800, 3860, 3920, 3980, 4070, 4170 } + 3500, 3670, 3720, 3750, 3770, 3800, 3860, 3920, 3980, 4070, 4170 }; #if CONFIG_CHARGING diff --git a/firmware/target/arm/s5l8702/ipodnano4g/serial-nano4g.c b/firmware/target/arm/s5l8702/ipodnano4g/serial-nano4g.c index 03b9a61024..c08107c096 100644 --- a/firmware/target/arm/s5l8702/ipodnano4g/serial-nano4g.c +++ b/firmware/target/arm/s5l8702/ipodnano4g/serial-nano4g.c @@ -26,7 +26,7 @@ #include "system.h" #include "serial.h" -#include "s5l87x.h" +#include "s5l87xx.h" #include "uc87xx.h" /* Define LOGF_ENABLE to enable logf output in this file */ diff --git a/firmware/target/arm/s5l8702/lcd-s5l8702.c b/firmware/target/arm/s5l8702/lcd-s5l8702.c index 3dcb788a43..cc0fa37605 100644 --- a/firmware/target/arm/s5l8702/lcd-s5l8702.c +++ b/firmware/target/arm/s5l8702/lcd-s5l8702.c @@ -567,7 +567,7 @@ void lcd_init_device(void) lcd_target_enable_clocks(true); #if defined(IPOD_6G) || defined(IPOD_NANO3G) LCD_PHTIME = 0x33; -#elif defined(IPOD_NANO4G) +#elif defined(IPOD_NANO4G) && defined(BOOTLOADER) cg16_config(&CG16_LCD, true, CG16_SEL_PLL0, 16, 1, 0x0); s5l_lcd_write_config(LCD_MODE_S9); cg16_config(&CG16_LCD, false, CG16_SEL_PLL0, 16, 1, 0x0); From 1e2950cc6cbf055500ee51ec8390be98c621d173 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 4 Feb 2026 08:48:43 -0500 Subject: [PATCH 31/75] Revert "make: allow building flat binary plugins on USE_ELF targets" This reverts commit 91ec6f1e1efe41577c2414cfcf62ec86d4a90e95. Reason for revert: Massive sea of red, looks like hosted + sim builds. Change-Id: I98a3954d68ad2cc521e13c3683bf4a6f45f88b36 --- apps/plugins/chessbox/chessbox.make | 2 +- apps/plugins/goban/goban.make | 2 +- apps/plugins/imageviewer/imageviewer.make | 2 +- apps/plugins/lua/lua.make | 2 +- apps/plugins/pictureflow/pictureflow.make | 2 +- apps/plugins/plugins.make | 2 +- apps/plugins/puzzles/puzzles.make | 4 ++-- apps/plugins/rockboy/rockboy.make | 2 +- apps/plugins/sdl/sdl.make | 4 ++-- apps/plugins/zxbox/zxbox.make | 2 +- lib/rbcodec/codecs/codecs.make | 2 +- tools/configure | 2 -- tools/functions.make | 5 ----- 13 files changed, 13 insertions(+), 20 deletions(-) diff --git a/apps/plugins/chessbox/chessbox.make b/apps/plugins/chessbox/chessbox.make index 77a038febc..87f0a6ecc0 100644 --- a/apps/plugins/chessbox/chessbox.make +++ b/apps/plugins/chessbox/chessbox.make @@ -39,7 +39,7 @@ $(CHESSBOX_OBJDIR)/chessbox.ovl: $(CHESSBOX_OBJ) $(CHESSBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CHESSBOX_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) # special pattern rule for compiling chessbox with extra flags $(CHESSBOX_OBJDIR)/%.o: $(CHESSBOX_SRCDIR)/%.c $(CHESSBOX_SRCDIR)/chessbox.make diff --git a/apps/plugins/goban/goban.make b/apps/plugins/goban/goban.make index ae221e8840..2201dc60f4 100644 --- a/apps/plugins/goban/goban.make +++ b/apps/plugins/goban/goban.make @@ -36,4 +36,4 @@ $(GOBAN_BUILDDIR)/goban.ovl: $(GOBAN_OBJ) $(GOBAN_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(GOBAN_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) diff --git a/apps/plugins/imageviewer/imageviewer.make b/apps/plugins/imageviewer/imageviewer.make index 25701fc6d2..23f9813357 100644 --- a/apps/plugins/imageviewer/imageviewer.make +++ b/apps/plugins/imageviewer/imageviewer.make @@ -40,7 +40,7 @@ $(IMGVBUILDDIR)/%.ovl: $(IMGDEC_OUTLDS) $(filter-out $(PLUGIN_CRT0),$(filter %.o, $^)) \ $(filter %.a, $+) \ -lgcc $(IMGDEC_OVLFLAGS) - $(SILENT)$(call objcopy_plugin,$(IMGVBUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy,$(IMGVBUILDDIR)/$*.elf,$@) # rule to create reference map for image decoder $(IMGVBUILDDIR)/%.refmap: $(APPSDIR)/plugin.h $(IMGVSRCDIR)/imageviewer.h $(PLUGINLINK_LDS) $(PLUGIN_LIBS) diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make index ec8a7e8b38..a5d1813a8b 100644 --- a/apps/plugins/lua/lua.make +++ b/apps/plugins/lua/lua.make @@ -73,7 +73,7 @@ $(LUA_BUILDDIR)/lua.ovl: $(LUA_OBJ) $(TLSFLIB) $(LUA_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(LUA_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) $(LUA_BUILDDIR): $(call PRINTS,MKDIR $@)mkdir -p $(LUA_BUILDDIR)/ diff --git a/apps/plugins/pictureflow/pictureflow.make b/apps/plugins/pictureflow/pictureflow.make index 7436af2433..e13ba61a72 100644 --- a/apps/plugins/pictureflow/pictureflow.make +++ b/apps/plugins/pictureflow/pictureflow.make @@ -37,7 +37,7 @@ $(PICTUREFLOW_OBJDIR)/pictureflow.ovl: $(PICTUREFLOW_OBJ) $(PICTUREFLOW_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PICTUREFLOW_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) # special pattern rule for compiling pictureflow with extra flags $(PICTUREFLOW_OBJDIR)/%.o: $(PICTUREFLOW_SRCDIR)/%.c $(PICTUREFLOW_SRCDIR)/pictureflow.make diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make index 8620d3f9c0..2babb329a5 100644 --- a/apps/plugins/plugins.make +++ b/apps/plugins/plugins.make @@ -169,7 +169,7 @@ $(BUILDDIR)/%.rock: $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PLUGINLDFLAGS) - $(SILENT)$(call objcopy_plugin,$(BUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy,$(BUILDDIR)/$*.elf,$@) $(BUILDDIR)/apps/plugins/%.lua: $(ROOTDIR)/apps/plugins/%.lua $(call PRINTS,CP $(subst $(ROOTDIR)/,,$<))cp $< $(BUILDDIR)/apps/plugins/ diff --git a/apps/plugins/puzzles/puzzles.make b/apps/plugins/puzzles/puzzles.make index 4c3322d32e..91e84c50da 100644 --- a/apps/plugins/puzzles/puzzles.make +++ b/apps/plugins/puzzles/puzzles.make @@ -49,14 +49,14 @@ $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/%.o $(PUZZLES_OBJDIR)/help/% $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/unfinished/%.o $(PUZZLES_OBJDIR)/help/%.o $(PUZZLES_SHARED_OBJ) $(TLSFLIB) $(call PRINTS,LD $(@F))$(CC) $(PLUGINFLAGS) -o $(PUZZLES_OBJDIR)/$*.elf \ $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_SRCDIR)/rbcompat.h: $(APPSDIR)/plugin.h \ $(APPSDIR)/plugins/lib/pluginlib_exit.h \ diff --git a/apps/plugins/rockboy/rockboy.make b/apps/plugins/rockboy/rockboy.make index 8725604933..8be44ef9c5 100644 --- a/apps/plugins/rockboy/rockboy.make +++ b/apps/plugins/rockboy/rockboy.make @@ -37,7 +37,7 @@ $(ROCKBOY_OBJDIR)/rockboy.ovl: $(ROCKBOY_OBJ) $(ROCKBOY_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ROCKBOY_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) # special rule to build with devkitarm gcc ifeq ($(APP_TYPE),ctru-app) diff --git a/apps/plugins/sdl/sdl.make b/apps/plugins/sdl/sdl.make index 7234656268..9d666bd732 100644 --- a/apps/plugins/sdl/sdl.make +++ b/apps/plugins/sdl/sdl.make @@ -95,7 +95,7 @@ $(SDL_OBJDIR)/wolf3d.ovl: $(SDL_OBJ) $(WOLF3D_OBJ) $(TLSFLIB) $(WOLF3D_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(WOLF3D_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) # Quake ### @@ -113,7 +113,7 @@ $(SDL_OBJDIR)/quake.ovl: $(SDL_OBJ) $(QUAKE_OBJ) $(TLSFLIB) $(QUAKE_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(QUAKE_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) ### diff --git a/apps/plugins/zxbox/zxbox.make b/apps/plugins/zxbox/zxbox.make index 1ee64d6fb5..4638d5f0a2 100644 --- a/apps/plugins/zxbox/zxbox.make +++ b/apps/plugins/zxbox/zxbox.make @@ -45,7 +45,7 @@ $(ZXBOX_OBJDIR)/zxbox.ovl: $(ZXBOX_OBJ) $(ZXBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ZXBOX_LDFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) # special pattern rule for compiling zxbox with extra flags $(ZXBOX_OBJDIR)/%.o: $(ZXBOX_SRCDIR)/%.c $(ZXBOX_SRCDIR)/zxbox.make diff --git a/lib/rbcodec/codecs/codecs.make b/lib/rbcodec/codecs/codecs.make index 6f20a8c101..6d790f5d9a 100644 --- a/lib/rbcodec/codecs/codecs.make +++ b/lib/rbcodec/codecs/codecs.make @@ -245,4 +245,4 @@ $(CODECDIR)/%.codec: $(CODECDIR)/%.o $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CODECLDFLAGS) - $(SILENT)$(call objcopy_plugin,$(CODECDIR)/$*.elf,$@) + $(SILENT)$(call objcopy,$(CODECDIR)/$*.elf,$@) diff --git a/tools/configure b/tools/configure index b166cf5a07..1e44235cb3 100755 --- a/tools/configure +++ b/tools/configure @@ -1755,7 +1755,6 @@ fi x1000tools="$genericbitmaptools scramble mkspl-x1000 uclpack" # default to not generating ELF files USE_ELF="no" - PLUGIN_USE_ELF="no" # ---- For each target ---- # @@ -5007,7 +5006,6 @@ export TTS_ENGINE=${TTS_ENGINE} export ENC_OPTS=${ENC_OPTS} export ENCODER=${ENCODER} export USE_ELF=${USE_ELF} -export PLUGIN_USE_ELF=${PLUGIN_USE_ELF} export RBDIR=${rbdir} export ROCKBOX_SHARE_PATH=${sharedir} export ROCKBOX_BINARY_PATH=${bindir} diff --git a/tools/functions.make b/tools/functions.make index 772db0eeda..1c16e1415f 100644 --- a/tools/functions.make +++ b/tools/functions.make @@ -38,20 +38,15 @@ a2lnk = $(patsubst lib%.a,-l%,$(notdir $(1))) # handles the $(1) == $(2) case too ifndef APP_TYPE objcopy = $(OC) $(if $(filter yes, $(USE_ELF)), -S -x, -O binary) $(1) $(2) # objcopy native -objcopy_plugin = $(OC) $(if $(filter yes, $(PLUGIN_USE_ELF)), -S -x, -O binary) $(1) $(2) else ifneq (,$(findstring sdl-sim,$(APP_TYPE))) objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy simulator -objcopy_plugin = objcopy else ifneq (,$(findstring ctru,$(MODELNAME))) # 3dsxtool requires symbols objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) -objcopy_plugin = objcopy else ifdef DEBUG objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy hosted (DEBUG) - objcopy_plugin = objcopy else objcopy = $(OC) -S -x $(1) $(2) # objcopy hosted (!DEBUG) - objcopy_plugin = objcopy endif endif From ebd273832dc7ea41695057791ae53d844d8c1b53 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 3 Feb 2026 21:57:43 +0000 Subject: [PATCH 32/75] Remove Mini2440 and Lyre prototype 1 ports Both targets were part of the (presumably dead) Lyre project and no longer build. The Mini2440 was much more complete than the Lyre and doesn't seem terribly difficult to fix up to the point where it at least builds, if someone still cares -- but given it is a dev board in a box, it's unlikely it ever saw much use. Change-Id: I09745379d28db69ea9aaf77f0a62b049884260e1 --- apps/SOURCES | 2 - apps/keymaps/keymap-mini2440.c | 380 ----- bootloader/SOURCES | 6 - bootloader/lyre_proto1.c | 33 - bootloader/mini2440.c | 122 -- firmware/SOURCES | 30 +- firmware/asm/SOURCES | 2 +- firmware/export/at91sam9260.h | 682 -------- firmware/export/config.h | 9 - firmware/export/config/lyreproto1.h | 102 -- firmware/export/config/mini2440.h | 154 -- firmware/target/arm/at91sam/boot.lds | 81 - .../arm/at91sam/lyre_proto1/adc-lyre_proto1.c | 33 - .../arm/at91sam/lyre_proto1/adc-target.h | 0 .../lyre_proto1/backlight-lyre_proto1.c | 45 - .../at91sam/lyre_proto1/backlight-target.h | 26 - .../at91sam/lyre_proto1/button-lyre_proto1.c | 99 -- .../arm/at91sam/lyre_proto1/button-target.h | 39 - .../target/arm/at91sam/lyre_proto1/crt0.S | 286 ---- .../at91sam/lyre_proto1/debug-lyre_proto1.c | 33 - .../at91sam/lyre_proto1/kernel-lyre_proto1.c | 78 - .../arm/at91sam/lyre_proto1/lcd-lyre_proto1.c | 29 - .../arm/at91sam/lyre_proto1/lcd-target.h | 0 .../at91sam/lyre_proto1/system-lyre_proto1.c | 149 -- .../arm/at91sam/lyre_proto1/system-target.h | 29 - .../at91sam/lyre_proto1/timer-lyre_proto1.c | 123 -- firmware/target/arm/mmu-arm.S | 2 +- firmware/target/arm/s3c2440/adc-s3c2440.c | 8 - firmware/target/arm/s3c2440/crt0.S | 32 - firmware/target/arm/s3c2440/debug-s3c2440.c | 2 - firmware/target/arm/s3c2440/dma-target.h | 3 - .../target/arm/s3c2440/mini2440/adc-target.h | 38 - .../arm/s3c2440/mini2440/backlight-mini2440.c | 159 -- .../arm/s3c2440/mini2440/backlight-target.h | 31 - .../arm/s3c2440/mini2440/button-mini2440.c | 92 -- .../arm/s3c2440/mini2440/button-target.h | 75 - .../target/arm/s3c2440/mini2440/lcd-target.h | 47 - .../arm/s3c2440/mini2440/led-mini2440.c | 67 - .../arm/s3c2440/mini2440/led-mini2440.h | 46 - .../arm/s3c2440/mini2440/pcm-mini2440.c | 261 --- .../arm/s3c2440/mini2440/power-mini2440.c | 55 - .../arm/s3c2440/mini2440/powermgmt-mini2440.c | 64 - .../s3c2440/mini2440/touchscreen-mini2440.c | 189 --- .../arm/s3c2440/mini2440/touchscreen-target.h | 33 - firmware/target/arm/s3c2440/system-s3c2440.c | 2 - firmware/target/arm/s3c2440/system-target.h | 14 - firmware/target/hosted/sdl/sim-ui-defines.h | 7 - .../images/mini2440-front.svg | 1466 ----------------- tools/builds.pm | 8 - tools/configure | 110 +- utils/themeeditor/resources/targetdb | 18 - 51 files changed, 37 insertions(+), 5364 deletions(-) delete mode 100644 apps/keymaps/keymap-mini2440.c delete mode 100644 bootloader/lyre_proto1.c delete mode 100644 bootloader/mini2440.c delete mode 100644 firmware/export/at91sam9260.h delete mode 100644 firmware/export/config/lyreproto1.h delete mode 100644 firmware/export/config/mini2440.h delete mode 100644 firmware/target/arm/at91sam/boot.lds delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/adc-target.h delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/backlight-target.h delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/button-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/button-target.h delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/crt0.S delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/debug-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/kernel-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/lcd-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/lcd-target.h delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/system-lyre_proto1.c delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/system-target.h delete mode 100644 firmware/target/arm/at91sam/lyre_proto1/timer-lyre_proto1.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/adc-target.h delete mode 100644 firmware/target/arm/s3c2440/mini2440/backlight-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/backlight-target.h delete mode 100644 firmware/target/arm/s3c2440/mini2440/button-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/button-target.h delete mode 100644 firmware/target/arm/s3c2440/mini2440/lcd-target.h delete mode 100644 firmware/target/arm/s3c2440/mini2440/led-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/led-mini2440.h delete mode 100644 firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/power-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/powermgmt-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/touchscreen-mini2440.c delete mode 100644 firmware/target/arm/s3c2440/mini2440/touchscreen-target.h delete mode 100644 manual/rockbox_interface/images/mini2440-front.svg diff --git a/apps/SOURCES b/apps/SOURCES index 0191587ab3..1898fa6284 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -240,8 +240,6 @@ keymaps/keymap-ondavx767.c #elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) \ || (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) keymaps/keymap-yh8xx_yh9xx.c -#elif CONFIG_KEYPAD == MINI2440_PAD -keymaps/keymap-mini2440.c #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD keymaps/keymap-vibe500.c #elif CONFIG_KEYPAD == MPIO_HD200_PAD diff --git a/apps/keymaps/keymap-mini2440.c b/apps/keymaps/keymap-mini2440.c deleted file mode 100644 index 3fe0698fa0..0000000000 --- a/apps/keymaps/keymap-mini2440.c +++ /dev/null @@ -1,380 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for the Mini2440 target - * based on Toshiba Gigabeat F keymap - */ -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -/* CONTEXT_CUSTOM's used in this file... - -CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions) -CONTEXT_CUSTOM|CONTEXT_SETTINGS = the direction keys for the eq/col picker screens - i.e where up/down is inc/dec - CONTEXT_SETTINGS = up/down is prev/next, l/r is inc/dec - -*/ - - -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, - - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT,BUTTON_SELECT }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_A|BUTTON_REL, BUTTON_A }, - { ACTION_WPS_STOP, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - - { ACTION_WPS_ABSETB_NEXTDIR,BUTTON_A|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_WPS_ABSETA_PREVDIR,BUTTON_A|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_WPS_ABRESET, BUTTON_A|BUTTON_SELECT, BUTTON_NONE }, - - { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, - - { ACTION_WPS_PITCHSCREEN, BUTTON_A|BUTTON_UP, BUTTON_A }, - { ACTION_WPS_VIEW_PLAYLIST, BUTTON_A|BUTTON_DOWN, BUTTON_NONE }, - - { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_WPS_HOTKEY, BUTTON_A|BUTTON_MENU, BUTTON_NONE }, - { ACTION_WPS_BROWSE, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - - LAST_ITEM_IN_LIST -}; /* button_context_wps */ - -static const struct button_mapping button_context_list[] = { - { ACTION_LISTTREE_PGUP, BUTTON_A|BUTTON_UP, BUTTON_NONE }, - { ACTION_LISTTREE_PGUP, BUTTON_A|BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_LISTTREE_PGDOWN, BUTTON_A|BUTTON_DOWN, BUTTON_NONE }, - { ACTION_LISTTREE_PGDOWN, BUTTON_A|BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, -#ifdef HAVE_VOLUME_IN_LIST - { ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, - { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, - { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, -#endif - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_list */ - -static const struct button_mapping button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_A|BUTTON_REL, BUTTON_A }, - { ACTION_TREE_STOP, BUTTON_POWER, BUTTON_NONE }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_HOTKEY, BUTTON_A|BUTTON_MENU, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) -}; /* button_context_tree */ - -static const struct button_mapping button_context_listtree_scroll_with_combo[] = { - { ACTION_NONE, BUTTON_A, BUTTON_NONE }, - { ACTION_TREE_PGLEFT, BUTTON_A|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_TREE_ROOT_INIT, BUTTON_A|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_A|BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_A|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_PGRIGHT, BUTTON_A|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_TREE_PGRIGHT, BUTTON_A|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_listtree_scroll_without_combo[] = { - { ACTION_NONE, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - { ACTION_TREE_ROOT_INIT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_TREE_PGRIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings */ - -static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settingsgraphical */ - -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_yesno */ - -static const struct button_mapping button_context_colorchooser[] = { - { ACTION_STD_OK, BUTTON_A|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ - -static const struct button_mapping button_context_eq[] = { - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_eq */ - -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { - { ACTION_BMS_DELETE, BUTTON_A, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_bmark */ - -static const struct button_mapping button_context_time[] = { - { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_A, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_time */ - -static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ - -static const struct button_mapping button_context_pitchscreen[] = { - { ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE }, - { ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_TOGGLE_MODE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_PS_RESET, BUTTON_A, BUTTON_NONE }, - { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE }, - { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ - -static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_A|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_A|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_A|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_A|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_PAGE_FLIP, BUTTON_A|BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_DONE, BUTTON_A|BUTTON_REL, BUTTON_A }, - { ACTION_KBD_ABORT, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_MORSE_INPUT, BUTTON_A|BUTTON_POWER, BUTTON_NONE }, - { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_keyboard */ - -#ifdef HAVE_MINI2440_REMOTE -/***************************************************************************** - * Remote control mappings - *****************************************************************************/ - -static const struct button_mapping remote_button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_RC_VOL_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_RC_REW, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RC_FF|BUTTON_REL, BUTTON_RC_FF }, - { ACTION_STD_CONTEXT, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_RC_FF }, - { ACTION_STD_MENU, BUTTON_RC_DSP, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; - -static const struct button_mapping remote_button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_RC_PLAY, BUTTON_NONE }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RC_FF|BUTTON_REL, BUTTON_RC_FF }, - { ACTION_WPS_SKIPPREV, BUTTON_RC_REW|BUTTON_REL, BUTTON_RC_REW }, - - { ACTION_WPS_SEEKBACK, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RC_FF|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_RC_REW|BUTTON_REL, BUTTON_RC_REW|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RC_FF|BUTTON_REL, BUTTON_RC_FF|BUTTON_REPEAT }, - - { ACTION_WPS_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_RC_PLAY }, - { ACTION_WPS_MENU, BUTTON_RC_DSP, BUTTON_NONE }, - - { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_RC_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_RC_VOL_UP, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; - -static const struct button_mapping remote_button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_RC_PLAY|BUTTON_REL, BUTTON_RC_PLAY }, - { ACTION_TREE_STOP, BUTTON_RC_PLAY|BUTTON_REPEAT, BUTTON_RC_PLAY }, - { ACTION_STD_CANCEL, BUTTON_RC_REW|BUTTON_REPEAT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; - -static const struct button_mapping* get_context_mapping_remote( int context ) -{ - context ^= CONTEXT_REMOTE; - - switch (context) - { - case CONTEXT_WPS: - return remote_button_context_wps; - case CONTEXT_MAINMENU: - case CONTEXT_TREE: - return remote_button_context_tree; - } - return remote_button_context_standard; -} -#endif - -const struct button_mapping* target_get_context_mapping(int context) -{ -#ifdef HAVE_MINI2440_REMOTE - if (context&CONTEXT_REMOTE) - return get_context_mapping_remote(context); -#endif - switch (context) - { - case CONTEXT_STD: - return button_context_standard; - case CONTEXT_WPS: - return button_context_wps; - - case CONTEXT_LIST: - return button_context_list; - case CONTEXT_MAINMENU: - case CONTEXT_TREE: - if (global_settings.hold_lr_for_scroll_in_list) - return button_context_listtree_scroll_without_combo; - else - return button_context_listtree_scroll_with_combo; - case CONTEXT_CUSTOM|CONTEXT_TREE: - return button_context_tree; - - case CONTEXT_SETTINGS: - return button_context_settings; - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - return button_context_settings_right_is_inc; - - case CONTEXT_SETTINGS_COLOURCHOOSER: - return button_context_colorchooser; - case CONTEXT_SETTINGS_EQ: - return button_context_eq; - - case CONTEXT_SETTINGS_TIME: - return button_context_time; - - case CONTEXT_YESNOSCREEN: - return button_context_yesno; - case CONTEXT_BOOKMARKSCREEN: - return button_context_bmark; - case CONTEXT_QUICKSCREEN: - return button_context_quickscreen; - case CONTEXT_PITCHSCREEN: - return button_context_pitchscreen; - case CONTEXT_KEYBOARD: - return button_context_keyboard; - } - return button_context_standard; -} diff --git a/bootloader/SOURCES b/bootloader/SOURCES index 478cb9a73c..ff6a6b8d6f 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -53,12 +53,6 @@ sansa_as3525.c show_logo.c #elif CONFIG_CPU==IMX233 imx233.c -#elif defined(LYRE_PROTO1) -lyre_proto1.c -show_logo.c -#elif defined(MINI2440) -mini2440.c -show_logo.c #elif defined(PBELL_VIBE500) main-pp.c show_logo.c diff --git a/bootloader/lyre_proto1.c b/bootloader/lyre_proto1.c deleted file mode 100644 index 6ad095170c..0000000000 --- a/bootloader/lyre_proto1.c +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Include Standard files */ -#include "../kernel-internal.h" -#include "system.h" - -int main(void) -{ - /* Initialize Rockbox kernel */ - kernel_init(); - - /* Never returns */ - while(1) ; -} diff --git a/bootloader/mini2440.c b/bootloader/mini2440.c deleted file mode 100644 index 3556fb0633..0000000000 --- a/bootloader/mini2440.c +++ /dev/null @@ -1,122 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins, Lyre Project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Include Standard files */ -#include -#include -#include "inttypes.h" -#include "string.h" -#include "cpu.h" -#include "system.h" -#include "lcd.h" -#include "../kernel-internal.h" -#include "storage.h" -#include "file_internal.h" -#include "disk.h" -#include "font.h" -#include "backlight.h" -#include "button.h" -#include "panic.h" -#include "power.h" -#include "file.h" -#include "common.h" -#include "rb-loader.h" -#include "loader_strerror.h" -#include "sd.h" -#include "backlight-target.h" -#include "lcd-target.h" -#include "dma-target.h" -#include "uart-s3c2440.h" -#include "led-mini2440.h" -#include "version.h" - - -int main(void) -{ - unsigned char* loadbuffer; - int buffer_size; - int rc; - int(*kernel_entry)(void); - - led_init(); - clear_leds(LED_ALL); - /* NB: something in system_init() prevents H-JTAG from downloading */ -/* system_init(); */ - kernel_init(); -/* enable_interrupt(IRQ_FIQ_STATUS); */ - lcd_init(); - backlight_init(); /* BUGFIX backlight_init MUST BE AFTER lcd_init */ - lcd_setfont(FONT_SYSFIXED); - button_init(); - dma_init(); - - uart_init(); - uart_init_device(DEBUG_UART_PORT); - -/* mini2440_test(); */ - - /* Show debug messages if button is pressed */ - int touch_data; - if(button_read_device(&touch_data) & BUTTON_MENU) - verbose = true; - - printf("Rockbox boot loader"); - printf("Version %s", rbversion); - - rc = storage_init(); - if(rc) - { - reset_screen(); - error(EATA, rc, true); - } - - filesystem_init(); - rc = disk_mount_all(); - if (rc<=0) - { - error(EDISK,rc, true); - } - - printf("Loading firmware"); - - /* Flush out anything pending first */ - commit_discard_idcache(); - - loadbuffer = (unsigned char*) 0x31000000; - buffer_size = (unsigned char*)0x31400000 - loadbuffer; - - rc = load_firmware(loadbuffer, BOOTFILE, buffer_size); - if(rc <= 0) - error(EBOOTFILE, rc, true); - - printf("Loaded firmware %d\n", rc); - -/* storage_close(); */ - system_prepare_fw_start(); - - commit_discard_idcache(); - kernel_entry = (void*) loadbuffer; - rc = kernel_entry(); - - /* end stop - should not get here */ - led_flash(LED_ALL, LED_NONE); - while (1); /* avoid warning */ -} diff --git a/firmware/SOURCES b/firmware/SOURCES index 4138efb672..6c0bec8219 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -929,7 +929,7 @@ target/arm/ipod/lcd-color_nano.c target/arm/ipod/lcd-gray.c #elif CONFIG_LCD == LCD_GIGABEATS target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c -#elif CONFIG_LCD == LCD_GIGABEAT || CONFIG_LCD == LCD_MINI2440 +#elif CONFIG_LCD == LCD_GIGABEAT target/arm/s3c2440/lcd-s3c2440.c #elif CONFIG_LCD == LCD_ILI9342 || CONFIG_LCD == LCD_ILI9342C target/arm/rk27xx/ma/lcd-ma.c @@ -1826,34 +1826,6 @@ target/mips/ingenic_x1000/erosqnative/power-erosqnative.c target/mips/ingenic_x1000/spl-nand-x1000.c #endif /* EROS_QN */ -#if defined(LYRE_PROTO1) -target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c -target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c -target/arm/at91sam/lyre_proto1/button-lyre_proto1.c -target/arm/at91sam/lyre_proto1/crt0.S -target/arm/at91sam/lyre_proto1/debug-lyre_proto1.c -target/arm/at91sam/lyre_proto1/kernel-lyre_proto1.c -target/arm/at91sam/lyre_proto1/lcd-lyre_proto1.c -target/arm/at91sam/lyre_proto1/system-lyre_proto1.c -target/arm/at91sam/lyre_proto1/timer-lyre_proto1.c -#endif - -#if defined(MINI2440) -drivers/lcd-memframe.c -target/arm/s3c2440/dma-s3c2440.c -target/arm/s3c2440/sd-s3c2440.c -target/arm/s3c2440/uart-s3c2440.c -target/arm/s3c2440/mini2440/backlight-mini2440.c -target/arm/s3c2440/mini2440/button-mini2440.c -target/arm/s3c2440/mini2440/led-mini2440.c -target/arm/s3c2440/mini2440/power-mini2440.c -target/arm/s3c2440/mini2440/touchscreen-mini2440.c -#ifndef BOOTLOADER -target/arm/s3c2440/mini2440/powermgmt-mini2440.c -target/arm/s3c2440/mini2440/pcm-mini2440.c -#endif -#endif /* MINI2440 */ - #if defined(SAMSUNG_YH820) || defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925) target/arm/samsung/akcodec-yh82x_yh92x.c target/arm/samsung/button-yh82x_yh92x.c diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index 396381787a..ea1cf94cfa 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES @@ -50,7 +50,7 @@ mempcpy.c #if (defined(SANSA_E200) || defined(GIGABEAT_F) || defined(GIGABEAT_S) || \ defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ - defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ + defined(COWON_D2) || defined(SAMSUNG_YPR0) || \ defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \ defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || \ defined(FIIO_M3K_LINUX)) && \ diff --git a/firmware/export/at91sam9260.h b/firmware/export/at91sam9260.h deleted file mode 100644 index 87826d4d4d..0000000000 --- a/firmware/export/at91sam9260.h +++ /dev/null @@ -1,682 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* MATRIX_MRCR : (MATRIX Offset: 0x100) MRCR Register */ -#define AT91C_MATRIX_RCA926I (0x1 << 0) /* (MATRIX) Remap Command for -ARM926EJ-S Instruction Master */ -#define AT91C_MATRIX_RCA926D (0x1 << 1) /* (MATRIX) Remap Command for -ARM926EJ-S Data Master */ - -/* Register definition for MATRIX peripheral */ -#define AT91C_MATRIX_MCFG0 (*(volatile unsigned long*) 0xFFFFEE00) /*(MATRIX) -Master Configuration Register 0 (ram96k) */ -#define AT91C_MATRIX_MCFG7 (*(volatile unsigned long*) 0xFFFFEE1C) /*(MATRIX) -Master Configuration Register 7 (teak_prog) */ -#define AT91C_MATRIX_SCFG1 (*(volatile unsigned long*) 0xFFFFEE44) /*(MATRIX) -Slave Configuration Register 1 (rom) */ -#define AT91C_MATRIX_MCFG4 (*(volatile unsigned long*) 0xFFFFEE10) /*(MATRIX) -Master Configuration Register 4 (bridge) */ -#define AT91C_MATRIX_VERSION (*(volatile unsigned long*) 0xFFFFEFFC) /*(MATRIX) -Version Register */ -#define AT91C_MATRIX_MCFG2 (*(volatile unsigned long*) 0xFFFFEE08) /*(MATRIX) -Master Configuration Register 2 (hperiphs) */ -#define AT91C_MATRIX_PRBS0 (*(volatile unsigned long*) 0xFFFFEE84) /*(MATRIX) -PRBS0 (ram0) */ -#define AT91C_MATRIX_SCFG3 (*(volatile unsigned long*) 0xFFFFEE4C) /*(MATRIX) -Slave Configuration Register 3 (ebi) */ -#define AT91C_MATRIX_MCFG6 (*(volatile unsigned long*) 0xFFFFEE18) /*(MATRIX) -Master Configuration Register 6 (ram16k) */ -#define AT91C_MATRIX_EBI (*(volatile unsigned long*) 0xFFFFEF1C) /*(MATRIX) -Slave 3 (ebi) Special Function Register */ -#define AT91C_MATRIX_SCFG0 (*(volatile unsigned long*) 0xFFFFEE40) /*(MATRIX) -Slave Configuration Register 0 (ram96k) */ -#define AT91C_MATRIX_PRAS0 (*(volatile unsigned long*) 0xFFFFEE80) /*(MATRIX) -PRAS0 (ram0) */ -#define AT91C_MATRIX_MCFG3 (*(volatile unsigned long*) 0xFFFFEE0C) /*(MATRIX) -Master Configuration Register 3 (ebi) */ -#define AT91C_MATRIX_PRAS1 (*(volatile unsigned long*) 0xFFFFEE88) /*(MATRIX) -PRAS1 (ram1) */ -#define AT91C_MATRIX_PRAS2 (*(volatile unsigned long*) 0xFFFFEE90) /*(MATRIX) -PRAS2 (ram2) */ -#define AT91C_MATRIX_SCFG2 (*(volatile unsigned long*) 0xFFFFEE48) /*(MATRIX) -Slave Configuration Register 2 (hperiphs) */ -#define AT91C_MATRIX_MCFG5 (*(volatile unsigned long*) 0xFFFFEE14) /*(MATRIX) -Master Configuration Register 5 (mailbox) */ -#define AT91C_MATRIX_MCFG1 (*(volatile unsigned long*) 0xFFFFEE04) /*(MATRIX) -Master Configuration Register 1 (rom) */ -#define AT91C_MATRIX_MRCR (*(volatile unsigned long*) 0xFFFFEF00) /*(MATRIX) -Master Remp Control Register */ -#define AT91C_MATRIX_PRBS2 (*(volatile unsigned long*) 0xFFFFEE94) /*(MATRIX) -PRBS2 (ram2) */ -#define AT91C_MATRIX_SCFG4 (*(volatile unsigned long*) 0xFFFFEE50) /*(MATRIX) -Slave Configuration Register 4 (bridge) */ -#define AT91C_MATRIX_TEAKCFG (*(volatile unsigned long*) 0xFFFFEF2C) /*(MATRIX) -Slave 7 (teak_prog) Special Function Register */ -#define AT91C_MATRIX_PRBS1 (*(volatile unsigned long*) 0xFFFFEE8C) /*(MATRIX) -PRBS1 (ram1) */ - -/* SOFTWARE API DEFINITION FOR Watchdog Timer Controller Interface */ -/* - WDTC_WDCR : (WDTC Offset: 0x0) Periodic Interval Image Register ---- */ -#define AT91C_WDTC_WDRSTT (0x1 << 0) /* (WDTC) Watchdog Restart */ -#define AT91C_WDTC_KEY (0xFF << 24) /* (WDTC) Watchdog KEY Password */ -/* -------- WDTC_WDMR : (WDTC Offset: 0x4) Watchdog Mode Register -------- */ -#define AT91C_WDTC_WDV (0xFFF << 0) /* (WDTC) Watchdog Timer Restart */ -#define AT91C_WDTC_WDFIEN (0x1 << 12) /* (WDTC) Watchdog Fault Interrupt -Enable */ -#define AT91C_WDTC_WDRSTEN (0x1 << 13) /* (WDTC) Watchdog Reset Enable */ -#define AT91C_WDTC_WDRPROC (0x1 << 14) /* (WDTC) Watchdog Timer Restart */ -#define AT91C_WDTC_WDDIS (0x1 << 15) /* (WDTC) Watchdog Disable */ -#define AT91C_WDTC_WDD (0xFFF << 16) /* (WDTC) Watchdog Delta Value */ -#define AT91C_WDTC_WDDBGHLT (0x1 << 28) /* (WDTC) Watchdog Debug Halt */ -#define AT91C_WDTC_WDIDLEHLT (0x1 << 29) /* (WDTC) Watchdog Idle Halt */ -/* -------- WDTC_WDSR : (WDTC Offset: 0x8) Watchdog Status Register ----- */ -#define AT91C_WDTC_WDUNF (0x1 << 0) /* (WDTC) Watchdog Underflow */ -#define AT91C_WDTC_WDERR (0x1 << 1) /* (WDTC) Watchdog Error */ - -/* SOFTWARE API DEFINITION FOR Watchdog Timer Controller Interface */ -/* - WDTC_WDCR : (WDTC Offset: 0x0) Periodic Interval Image Register ---- */ -#define AT91C_WDTC_WDRSTT (0x1 << 0) /* (WDTC) Watchdog Restart */ -#define AT91C_WDTC_KEY (0xFF << 24) /* (WDTC) Watchdog KEY Password */ -/* -------- WDTC_WDMR : (WDTC Offset: 0x4) Watchdog Mode Register -------- */ -#define AT91C_WDTC_WDV (0xFFF << 0) /* (WDTC) Watchdog Timer Restart */ -#define AT91C_WDTC_WDFIEN (0x1 << 12) /* (WDTC) Watchdog Fault Interrupt -Enable */ -#define AT91C_WDTC_WDRSTEN (0x1 << 13) /* (WDTC) Watchdog Reset Enable */ -#define AT91C_WDTC_WDRPROC (0x1 << 14) /* (WDTC) Watchdog Timer Restart */ -#define AT91C_WDTC_WDDIS (0x1 << 15) /* (WDTC) Watchdog Disable */ -#define AT91C_WDTC_WDD (0xFFF << 16) /* (WDTC) Watchdog Delta Value */ -#define AT91C_WDTC_WDDBGHLT (0x1 << 28) /* (WDTC) Watchdog Debug Halt */ -#define AT91C_WDTC_WDIDLEHLT (0x1 << 29) /* (WDTC) Watchdog Idle Halt */ -/* -------- WDTC_WDSR : (WDTC Offset: 0x8) Watchdog Status Register ----- */ -#define AT91C_WDTC_WDUNF (0x1 << 0) /* (WDTC) Watchdog Underflow */ -#define AT91C_WDTC_WDERR (0x1 << 1) /* (WDTC) Watchdog Error */ - -/* Register definition for WDTC peripheral */ -#define AT91C_WDTC_WDCR (*(volatile unsigned long*) 0xFFFFFD40) /* (WDTC) -Watchdog Control Register */ -#define AT91C_WDTC_WDSR (*(volatile unsigned long*) 0xFFFFFD48) /* (WDTC) -Watchdog Status Register */ -#define AT91C_WDTC_WDMR (*(volatile unsigned long*) 0xFFFFFD44) /* (WDTC) -Watchdog Mode Register */ - -/* CKGR_MOR : (CKGR Offset: 0x0) Main Oscillator Register */ -#define AT91C_CKGR_MOSCEN (0x1 << 0) /* (CKGR) Main Oscillator Enable */ -#define AT91C_CKGR_OSCBYPASS (0x1 << 1) /* (CKGR) Main Oscillator Bypass */ -#define AT91C_CKGR_OSCOUNT (0xFF << 8) /* (CKGR) Main Oscillator Start --up Time */ -/* CKGR_MCFR : (CKGR Offset: 0x4) Main Clock Frequency Register */ -#define AT91C_CKGR_MAINF (0xFFFF << 0) /* (CKGR) Main Clock Frequency */ -#define AT91C_CKGR_MAINRDY (0x1 << 16) /* (CKGR) Main Clock Ready */ -/* CKGR_PLLAR : (CKGR Offset: 0x8) PLL A Register */ -#define AT91C_CKGR_DIVA (0xFF << 0) /* (CKGR) Divider A Selected */ -#define AT91C_CKGR_DIVA_0 (0x0) /* (CKGR) Divider A output is 0 */ -#define AT91C_CKGR_DIVA_BYPASS (0x1) /* (CKGR) Divider A is bypassed */ -#define AT91C_CKGR_PLLACOUNT (0x3F << 8) /* (CKGR) PLL A Counter */ -#define AT91C_CKGR_OUTA (0x3 << 14) /* (CKGR) PLL A Output Frequency Range */ -#define AT91C_CKGR_OUTA_0 (0x0 << 14) /* (CKGR) Please -refer to the PLLA datasheet */ -#define AT91C_CKGR_OUTA_1 (0x1 << 14) /* (CKGR) Please -refer to the PLLA datasheet */ -#define AT91C_CKGR_OUTA_2 (0x2 << 14) /* (CKGR) Please -refer to the PLLA datasheet */ -#define AT91C_CKGR_OUTA_3 (0x3 << 14) /* (CKGR) Please -refer to the PLLA datasheet */ -#define AT91C_CKGR_MULA (0x7FF << 16) /* (CKGR) PLL A Multiplier */ -#define AT91C_CKGR_SRCA (0x1 << 29) /* (CKGR) */ -/* CKGR_PLLBR : (CKGR Offset: 0xc) PLL B Register */ -#define AT91C_CKGR_DIVB (0xFF << 0) /* (CKGR) Divider B Selected */ -#define AT91C_CKGR_DIVB_0 (0x0) /* (CKGR) Divider B output is 0 */ -#define AT91C_CKGR_DIVB_BYPASS (0x1) /* (CKGR) Divider B is bypassed */ -#define AT91C_CKGR_PLLBCOUNT (0x3F << 8) /* (CKGR) PLL B Counter */ -#define AT91C_CKGR_OUTB (0x3 << 14) /* (CKGR) PLL B Output Frequency Range */ -#define AT91C_CKGR_OUTB_0 (0x0 << 14) /* (CKGR) Please -refer to the PLLB datasheet */ -#define AT91C_CKGR_OUTB_1 (0x1 << 14) /* (CKGR) Please -refer to the PLLB datasheet */ -#define AT91C_CKGR_OUTB_2 (0x2 << 14) /* (CKGR) Please -refer to the PLLB datasheet */ -#define AT91C_CKGR_OUTB_3 (0x3 << 14) /* (CKGR) Please -refer to the PLLB datasheet */ -#define AT91C_CKGR_MULB (0x7FF << 16) /* (CKGR) PLL B Multiplier */ -#define AT91C_CKGR_USBDIV (0x3 << 28) /* (CKGR) Divider for USB Clocks */ -#define AT91C_CKGR_USBDIV_0 (0x0 << 28) /* (CKGR) -Divider output is PLL clock output */ -#define AT91C_CKGR_USBDIV_1 (0x1 << 28) /* (CKGR) -Divider output is PLL clock output divided by 2 */ -#define AT91C_CKGR_USBDIV_2 (0x2 << 28) /* (CKGR) -Divider output is PLL clock output divided by 4 */ - -/* SOFTWARE API DEFINITION FOR Power Management Controler */ -/* -------- PMC_SCER : (PMC Offset: 0x0) System Clock Enable Register ----- */ -#define AT91C_PMC_PCK (0x1 << 0) /* (PMC) Processor Clock */ -#define AT91C_PMC_UHP (0x1 << 6) /* (PMC) USB Host Port Clock */ -#define AT91C_PMC_UDP (0x1 << 7) /* (PMC) USB Device Port Clock */ -#define AT91C_PMC_PCK0 (0x1 << 8) /* (PMC) Programmable Clock Output */ -#define AT91C_PMC_PCK1 (0x1 << 9) /* (PMC) Programmable Clock Output */ -#define AT91C_PMC_HCK0 (0x1 << 16) /* (PMC) AHB UHP Clock Output */ -#define AT91C_PMC_HCK1 (0x1 << 17) /* (PMC) AHB LCDC Clock Output */ -/* -------- PMC_SCDR : (PMC Offset: 0x4) System Clock Disable Register ----- */ - /* -------- PMC_SCSR : (PMC Offset: 0x8) System Clock Status Register ----- */ - /* -------- CKGR_MOR : (PMC Offset: 0x20) Main Oscillator Register -------- */ - /* -------- CKGR_MCFR : (PMC Offset: 0x24) Main Clock Frequency Register--- */ - /* -------- CKGR_PLLAR : (PMC Offset: 0x28) PLL A Register -------- */ - /* -------- CKGR_PLLBR : (PMC Offset: 0x2c) PLL B Register -------- */ - /* -------- PMC_MCKR : (PMC Offset: 0x30) Master Clock Register -------- */ - #define AT91C_PMC_CSS (0x3 << 0) /* (PMC) Programmable Clock Selection */ - #define AT91C_PMC_CSS_SLOW_CLK (0x0) /* (PMC) Slow Clock is selected */ - #define AT91C_PMC_CSS_MAIN_CLK (0x1) /* (PMC) Main Clock is selected */ - #define AT91C_PMC_CSS_PLLA_CLK (0x2) /* (PMC) Clock from PLL A is selected */ - #define AT91C_PMC_CSS_PLLB_CLK (0x3) /* (PMC) Clock from PLL B is selected */ - #define AT91C_PMC_PRES (0x7 << 2) /* (PMC) Programmable Clock Prescaler */ - #define AT91C_PMC_PRES_CLK (0x0 << 2) /* (PMC) Selected clock */ - #define AT91C_PMC_PRES_CLK_2 (0x1 << 2) /* (PMC) Selected clock - divided by 2 */ - #define AT91C_PMC_PRES_CLK_4 (0x2 << 2) /* (PMC) Selected clock - divided by 4 */ - #define AT91C_PMC_PRES_CLK_8 (0x3 << 2) /* (PMC) Selected clock - divided by 8 */ - #define AT91C_PMC_PRES_CLK_16 (0x4 << 2) /* (PMC) Selected clock - divided by 16 */ - #define AT91C_PMC_PRES_CLK_32 (0x5 << 2) /* (PMC) Selected clock - divided by 32 */ - #define AT91C_PMC_PRES_CLK_64 (0x6 << 2) /* (PMC) Selected clock - divided by 64 */ - #define AT91C_PMC_MDIV (0x3 << 8) /* (PMC) Master Clock Divisionv */ - #define AT91C_PMC_MDIV_1 (0x0 << 8) /* (PMC) The master clock and the - processor clock are the same */ - #define AT91C_PMC_MDIV_2 (0x1 << 8) /* (PMC) The processor clock is twice - as fast as the master clock */ - #define AT91C_PMC_MDIV_3 (0x2 << 8) /* (PMC) The processor clock is four - times faster than the master clock */ - /* -------- PMC_PCKR : (PMC Offset: 0x40) Programmable Clock Register ----- */ - /* -------- PMC_IER : (PMC Offset: 0x60) PMC Interrupt Enable Register ---- */ - #define AT91C_PMC_MOSCS (0x1 << 0) /* (PMC) MOSC Status/Enable/Disable/Mask*/ - #define AT91C_PMC_LOCKA (0x1 << 1) /* (PMC) PLL A Status/Enable/Disable/ - Mask */ - #define AT91C_PMC_LOCKB (0x1 << 2) /* (PMC) PLL B Status/Enable/Disable/ - Mask */ - #define AT91C_PMC_MCKRDY (0x1 << 3) /* (PMC) Master Clock Status/Enable/ - Disable/Mask */ - #define AT91C_PMC_PCK0RDY (0x1 << 8) /* (PMC) PCK0_RDY Status/Enable/ - Disable/Mask */ - #define AT91C_PMC_PCK1RDY (0x1 << 9) /* (PMC) PCK1_RDY Status/Enable/ - Disable/Mask */ - /* ---PMC_IDR : (PMC Offset: 0x64) PMC Interrupt Disable Register -------- */ - /* ------ PMC_SR : (PMC Offset: 0x68) PMC Status Register -------- */ - #define AT91C_PMC_OSCSEL (0x1 << 7) /* (PMC) 32kHz Oscillator - selection status */ - /* -------- PMC_IMR : (PMC Offset: 0x6c) PMC Interrupt Mask Register ---- */ - -/* SOFTWARE API DEFINITION FOR Advanced Interrupt Controller */ -/* -------- AIC_SMR : (AIC Offset: 0x0) Control Register -------- */ -#define AT91C_AIC_PRIOR (0x7 << 0) /* (AIC) Priority Level */ -#define AT91C_AIC_PRIOR_LOWEST (0x0) /* (AIC) Lowest priority - level */ -#define AT91C_AIC_PRIOR_HIGHEST (0x7) /* (AIC) Highest - priority level */ -#define AT91C_AIC_SRCTYPE (0x3 << 5) /* (AIC) Interrupt Source Type */ -#define AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE (0x0 << 5) /* (AIC) - Internal Sources Code Label Level Sensitive */ -#define AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED (0x1 << 5) /* (AIC) - Internal Sources Code Label Edge triggered */ -#define AT91C_AIC_SRCTYPE_EXT_HIGH_LEVEL (0x2 << 5) /* (AIC) - External Sources Code Label High-level Sensitive */ -#define AT91C_AIC_SRCTYPE_EXT_POSITIVE_EDGE (0x3 << 5) /* (AIC) - External Sources Code Label Positive Edge triggered */ -/* - AIC_CISR : (AIC Offset: 0x114) AIC Core Interrupt Status Register ----- */ -#define AT91C_AIC_NFIQ (0x1 << 0) /* (AIC) NFIQ Status */ -#define AT91C_AIC_NIRQ (0x1 << 1) /* (AIC) NIRQ Status */ -/* - AIC_DCR : (AIC Offset: 0x138) AIC Debug Control Register (Protect) ---- */ -#define AT91C_AIC_DCR_PROT (0x1 << 0) /* (AIC) Protection Mode */ -#define AT91C_AIC_DCR_GMSK (0x1 << 1) /* (AIC) General Mask */ - -/* Register definition for AIC peripheral */ -#define AT91C_AIC_IVR (*(volatile unsigned long*) 0xFFFFF100) /* (AIC) IRQ -Vector Register */ -#define AIC_IVR 0x00000100 -/* (AIC) Source Mode Register */ -#define AT91C_AIC_SMR(a) (*(volatile unsigned long*) (0xFFFFF000 + 4*(a))) -#define AT91C_AIC_FVR (*(volatile unsigned long*) 0xFFFFF104) /* (AIC) FIQ -Vector Register */ -#define AT91C_AIC_DCR (*(volatile unsigned long*) 0xFFFFF138) /* (AIC) Debug -Control Register (Protect) */ -#define AT91C_AIC_EOICR (*(volatile unsigned long*) 0xFFFFF130) /* (AIC) End -of Interrupt Command Register */ -#define AIC_EOICR 0x00000130 -/* (AIC) Source Vector Register */ -#define AT91C_AIC_SVR(a) (*(volatile unsigned long*) (0xFFFFF080 + 4*(a))) -#define AT91C_AIC_FFSR (*(volatile unsigned long*) 0xFFFFF148) /* (AIC) Fast -Forcing Status Register */ -#define AT91C_AIC_ICCR (*(volatile unsigned long*) 0xFFFFF128) /* (AIC) -Interrupt Clear Command Register */ -#define AT91C_AIC_ISR (*(volatile unsigned long*) 0xFFFFF108) /* (AIC) -Interrupt Status Register */ -#define AT91C_AIC_IMR (*(volatile unsigned long*) 0xFFFFF110) /* (AIC) -Interrupt Mask Register */ -#define AT91C_AIC_IPR (*(volatile unsigned long*) 0xFFFFF10C) /* (AIC) -Interrupt Pending Register */ -#define AT91C_AIC_FFER (*(volatile unsigned long*) 0xFFFFF140) /* (AIC) -Fast Forcing Enable Register */ -#define AT91C_AIC_IECR (*(volatile unsigned long*) 0xFFFFF120) /* (AIC) -Interrupt Enable Command Register */ -#define AT91C_AIC_ISCR (*(volatile unsigned long*) 0xFFFFF12C) /* (AIC) -Interrupt Set Command Register */ -#define AT91C_AIC_FFDR (*(volatile unsigned long*) 0xFFFFF144) /* (AIC) -Fast Forcing Disable Register */ -#define AT91C_AIC_CISR (*(volatile unsigned long*) 0xFFFFF114) /* (AIC) -Core Interrupt Status Register */ -#define AT91C_AIC_IDCR (*(volatile unsigned long*) 0xFFFFF124) /* (AIC) -Interrupt Disable Command Register */ -#define AT91C_AIC_SPU (*(volatile unsigned long*) 0xFFFFF134) /* (AIC) -Spurious Vector Register */ - -/* SOFTWARE API DEFINITION FOR Periodic Interval Timer Controller Interface */ -/* PITC_PIMR : (PITC Offset: 0x0) Periodic Interval Mode Register -------- */ -#define AT91C_PITC_PIV (0xFFFFF << 0) /* (PITC) Periodic Interval -Value */ -#define AT91C_PITC_PITEN (0x1 << 24) /* (PITC) Periodic Interval Timer -Enabled */ -#define AT91C_PITC_PITIEN (0x1 << 25) /* (PITC) Periodic Interval Timer -Interrupt Enable */ -/* --- PITC_PISR : (PITC Offset: 0x4) Periodic Interval Status Register - */ -#define AT91C_PITC_PITS (0x1 << 0) /* (PITC) Periodic Interval Timer -Status */ -/* - PITC_PIVR : (PITC Offset: 0x8) Periodic Interval Value Register ---- */ -#define AT91C_PITC_CPIV (0xFFFFF << 0) /* (PITC) Current Periodic -Interval Value */ -#define AT91C_PITC_PICNT (0xFFF << 20) /* (PITC) Periodic Interval Counter */ -/* PITC_PIIR : (PITC Offset: 0xc) Periodic Interval Image Register ---- */ - -/* Register definition for AIC peripheral */ -#define AT91C_AIC_IVR (*(volatile unsigned long*) 0xFFFFF100) /* (AIC) IRQ -Vector Register */ -#define AIC_IVR 0x00000100 -#define AT91C_AIC_EOICR (*(volatile unsigned long*) 0xFFFFF130) /* (AIC) End -of Interrupt Command Register */ -#define AIC_EOICR 0x00000130 - -/* Register definition for PIOA peripheral */ -#define AT91C_PIOA_ODR (*(volatile unsigned long*) 0xFFFFF414) /* (PIOA) -Output Disable Registerr */ -#define AT91C_PIOA_SODR (*(volatile unsigned long*) 0xFFFFF430) /* (PIOA) -Set Output Data Register */ -#define AT91C_PIOA_ISR (*(volatile unsigned long*) 0xFFFFF44C) /* (PIOA) -Interrupt Status Register */ -#define AT91C_PIOA_ABSR (*(volatile unsigned long*) 0xFFFFF478) /* (PIOA) -AB Select Status Register */ -#define AT91C_PIOA_IER (*(volatile unsigned long*) 0xFFFFF440) /* (PIOA) -Interrupt Enable Register */ -#define AT91C_PIOA_PPUDR (*(volatile unsigned long*) 0xFFFFF460) /* (PIOA) -Pull-up Disable Register */ -#define AT91C_PIOA_IMR (*(volatile unsigned long*) 0xFFFFF448) /* (PIOA) -Interrupt Mask Register */ -#define AT91C_PIOA_PER (*(volatile unsigned long*) 0xFFFFF400) /* (PIOA) -PIO Enable Register */ -#define AT91C_PIOA_IFDR (*(volatile unsigned long*) 0xFFFFF424) /* (PIOA) -Input Filter Disable Register */ -#define AT91C_PIOA_OWDR (*(volatile unsigned long*) 0xFFFFF4A4) /* (PIOA) -Output Write Disable Register */ -#define AT91C_PIOA_MDSR (*(volatile unsigned long*) 0xFFFFF458) /* (PIOA) -Multi-driver Status Register */ -#define AT91C_PIOA_IDR (*(volatile unsigned long*) 0xFFFFF444) /* (PIOA) -Interrupt Disable Register */ -#define AT91C_PIOA_ODSR (*(volatile unsigned long*) 0xFFFFF438) /* (PIOA) -Output Data Status Register */ -#define AT91C_PIOA_PPUSR (*(volatile unsigned long*) 0xFFFFF468) /* (PIOA) -Pull-up Status Register */ -#define AT91C_PIOA_OWSR (*(volatile unsigned long*) 0xFFFFF4A8) /* (PIOA) -Output Write Status Register */ -#define AT91C_PIOA_BSR (*(volatile unsigned long*) 0xFFFFF474) /* (PIOA) -Select B Register */ -#define AT91C_PIOA_OWER (*(volatile unsigned long*) 0xFFFFF4A0) /* (PIOA) -Output Write Enable Register */ -#define AT91C_PIOA_IFER (*(volatile unsigned long*) 0xFFFFF420) /* (PIOA) -Input Filter Enable Register */ -#define AT91C_PIOA_PDSR (*(volatile unsigned long*) 0xFFFFF43C) /* (PIOA) -Pin Data Status Register */ -#define AT91C_PIOA_PPUER (*(volatile unsigned long*) 0xFFFFF464) /* (PIOA) -Pull-up Enable Register */ -#define AT91C_PIOA_OSR (*(volatile unsigned long*) 0xFFFFF418) /* (PIOA) -Output Status Register */ -#define AT91C_PIOA_ASR (*(volatile unsigned long*) 0xFFFFF470) /* (PIOA) -Select A Register */ -#define AT91C_PIOA_MDDR (*(volatile unsigned long*) 0xFFFFF454) /* (PIOA) -Multi-driver Disable Register */ -#define AT91C_PIOA_CODR (*(volatile unsigned long*) 0xFFFFF434) /* (PIOA) -Clear Output Data Register */ -#define AT91C_PIOA_MDER (*(volatile unsigned long*) 0xFFFFF450) /* (PIOA) -Multi-driver Enable Register */ -#define AT91C_PIOA_PDR (*(volatile unsigned long*) 0xFFFFF404) /* (PIOA) -PIO Disable Register */ -#define AT91C_PIOA_IFSR (*(volatile unsigned long*) 0xFFFFF428) /* (PIOA) -Input Filter Status Register */ -#define AT91C_PIOA_OER (*(volatile unsigned long*) 0xFFFFF410) /* (PIOA) -Output Enable Register */ -#define AT91C_PIOA_PSR (*(volatile unsigned long*) 0xFFFFF408) /* (PIOA) -PIO Status Register */ - -/* Register definition for PIOB peripheral */ -#define AT91C_PIOB_OWDR (*(volatile unsigned long*) 0xFFFFF6A4) /* (PIOB) -Output Write Disable Register */ -#define AT91C_PIOB_MDER (*(volatile unsigned long*) 0xFFFFF650) /* (PIOB) -Multi-driver Enable Register */ -#define AT91C_PIOB_PPUSR (*(volatile unsigned long*) 0xFFFFF668) /* (PIOB) -Pull-up Status Register */ -#define AT91C_PIOB_IMR (*(volatile unsigned long*) 0xFFFFF648) /* (PIOB) -Interrupt Mask Register */ -#define AT91C_PIOB_ASR (*(volatile unsigned long*) 0xFFFFF670) /* (PIOB) -Select A Register */ -#define AT91C_PIOB_PPUDR (*(volatile unsigned long*) 0xFFFFF660) /* (PIOB) -Pull-up Disable Register */ -#define AT91C_PIOB_PSR (*(volatile unsigned long*) 0xFFFFF608) /* (PIOB) -PIO Status Register */ -#define AT91C_PIOB_IER (*(volatile unsigned long*) 0xFFFFF640) /* (PIOB) -Interrupt Enable Register */ -#define AT91C_PIOB_CODR (*(volatile unsigned long*) 0xFFFFF634) /* (PIOB) -Clear Output Data Register */ -#define AT91C_PIOB_OWER (*(volatile unsigned long*) 0xFFFFF6A0) /* (PIOB) -Output Write Enable Register */ -#define AT91C_PIOB_ABSR (*(volatile unsigned long*) 0xFFFFF678) /* (PIOB) -AB Select Status Register */ -#define AT91C_PIOB_IFDR (*(volatile unsigned long*) 0xFFFFF624) /* (PIOB) -Input Filter Disable Register */ -#define AT91C_PIOB_PDSR (*(volatile unsigned long*) 0xFFFFF63C) /* (PIOB) -Pin Data Status Register */ -#define AT91C_PIOB_IDR (*(volatile unsigned long*) 0xFFFFF644) /* (PIOB) -Interrupt Disable Register */ -#define AT91C_PIOB_OWSR (*(volatile unsigned long*) 0xFFFFF6A8) /* (PIOB) -Output Write Status Register */ -#define AT91C_PIOB_PDR (*(volatile unsigned long*) 0xFFFFF604) /* (PIOB) -PIO Disable Register */ -#define AT91C_PIOB_ODR (*(volatile unsigned long*) 0xFFFFF614) /* (PIOB) -Output Disable Registerr */ -#define AT91C_PIOB_IFSR (*(volatile unsigned long*) 0xFFFFF628) /* (PIOB) -Input Filter Status Register */ -#define AT91C_PIOB_PPUER (*(volatile unsigned long*) 0xFFFFF664) /* (PIOB) -Pull-up Enable Register */ -#define AT91C_PIOB_SODR (*(volatile unsigned long*) 0xFFFFF630) /* (PIOB) -Set Output Data Register */ -#define AT91C_PIOB_ISR (*(volatile unsigned long*) 0xFFFFF64C) /* (PIOB) -Interrupt Status Register */ -#define AT91C_PIOB_ODSR (*(volatile unsigned long*) 0xFFFFF638) /* (PIOB) -Output Data Status Register */ -#define AT91C_PIOB_OSR (*(volatile unsigned long*) 0xFFFFF618) /* (PIOB) -Output Status Register */ -#define AT91C_PIOB_MDSR (*(volatile unsigned long*) 0xFFFFF658) /* (PIOB) -Multi-driver Status Register */ -#define AT91C_PIOB_IFER (*(volatile unsigned long*) 0xFFFFF620) /* (PIOB) -Input Filter Enable Register */ -#define AT91C_PIOB_BSR (*(volatile unsigned long*) 0xFFFFF674) /* (PIOB) -Select B Register */ -#define AT91C_PIOB_MDDR (*(volatile unsigned long*) 0xFFFFF654) /* (PIOB) -Multi-driver Disable Register */ -#define AT91C_PIOB_OER (*(volatile unsigned long*) 0xFFFFF610) /* (PIOB) -Output Enable Register */ -#define AT91C_PIOB_PER (*(volatile unsigned long*) 0xFFFFF600) /* (PIOB) -PIO Enable Register */ - -/* Register definition for PIOC peripheral */ -#define AT91C_PIOC_OWDR (*(volatile unsigned long*) 0xFFFFF8A4) /* (PIOC) -Output Write Disable Register */ -#define AT91C_PIOC_SODR (*(volatile unsigned long*) 0xFFFFF830) /* (PIOC) -Set Output Data Register */ -#define AT91C_PIOC_PPUER (*(volatile unsigned long*) 0xFFFFF864) /* (PIOC) -Pull-up Enable Register */ -#define AT91C_PIOC_CODR (*(volatile unsigned long*) 0xFFFFF834) /* (PIOC) -Clear Output Data Register */ -#define AT91C_PIOC_PSR (*(volatile unsigned long*) 0xFFFFF808) /* (PIOC) -PIO Status Register */ -#define AT91C_PIOC_PDR (*(volatile unsigned long*) 0xFFFFF804) /* (PIOC) -PIO Disable Register */ -#define AT91C_PIOC_ODR (*(volatile unsigned long*) 0xFFFFF814) /* (PIOC) -Output Disable Register */ -#define AT91C_PIOC_PPUSR (*(volatile unsigned long*) 0xFFFFF868) /* (PIOC) -Pull-up Status Register */ -#define AT91C_PIOC_ABSR (*(volatile unsigned long*) 0xFFFFF878) /* (PIOC) -AB Select Status Register */ -#define AT91C_PIOC_IFSR (*(volatile unsigned long*) 0xFFFFF828) /* (PIOC) -Input Filter Status Register */ -#define AT91C_PIOC_OER (*(volatile unsigned long*) 0xFFFFF810) /* (PIOC) -Output Enable Register */ -#define AT91C_PIOC_IMR (*(volatile unsigned long*) 0xFFFFF848) /* (PIOC) -Interrupt Mask Register */ -#define AT91C_PIOC_ASR (*(volatile unsigned long*) 0xFFFFF870) /* (PIOC) -Select A Register */ -#define AT91C_PIOC_MDDR (*(volatile unsigned long*) 0xFFFFF854) /* (PIOC) -Multi-driver Disable Register */ -#define AT91C_PIOC_OWSR (*(volatile unsigned long*) 0xFFFFF8A8) /* (PIOC) -Output Write Status Register */ -#define AT91C_PIOC_PER (*(volatile unsigned long*) 0xFFFFF800) /* (PIOC) -PIO Enable Register */ -#define AT91C_PIOC_IDR (*(volatile unsigned long*) 0xFFFFF844) /* (PIOC) -Interrupt Disable Register */ -#define AT91C_PIOC_MDER (*(volatile unsigned long*) 0xFFFFF850) /* (PIOC) -Multi-driver Enable Register */ -#define AT91C_PIOC_PDSR (*(volatile unsigned long*) 0xFFFFF83C) /* (PIOC) -Pin Data Status Register */ -#define AT91C_PIOC_MDSR (*(volatile unsigned long*) 0xFFFFF858) /* (PIOC) -Multi-driver Status Register */ -#define AT91C_PIOC_OWER (*(volatile unsigned long*) 0xFFFFF8A0) /* (PIOC) -Output Write Enable Register */ -#define AT91C_PIOC_BSR (*(volatile unsigned long*) 0xFFFFF874) /* (PIOC) -Select B Register */ -#define AT91C_PIOC_PPUDR (*(volatile unsigned long*) 0xFFFFF860) /* (PIOC) -Pull-up Disable Register */ -#define AT91C_PIOC_IFDR (*(volatile unsigned long*) 0xFFFFF824) /* (PIOC) -Input Filter Disable Register */ -#define AT91C_PIOC_IER (*(volatile unsigned long*) 0xFFFFF840) /* (PIOC) -Interrupt Enable Register */ -#define AT91C_PIOC_OSR (*(volatile unsigned long*) 0xFFFFF818) /* (PIOC) -Output Status Register */ -#define AT91C_PIOC_ODSR (*(volatile unsigned long*) 0xFFFFF838) /* (PIOC) -Output Data Status Register */ -#define AT91C_PIOC_ISR (*(volatile unsigned long*) 0xFFFFF84C) /* (PIOC) -Interrupt Status Register */ -#define AT91C_PIOC_IFER (*(volatile unsigned long*) 0xFFFFF820) /* (PIOC) -Input Filter Enable Register */ - -/* Register definition for PMC peripheral */ -#define AT91C_PMC_PCER (*(volatile unsigned long*) 0xFFFFFC10) /* (PMC) -Peripheral Clock Enable Register */ -#define AT91C_PMC_PCKR (*(volatile unsigned long*) 0xFFFFFC40) /* (PMC) -Programmable Clock Register */ -#define AT91C_PMC_MCKR (*(volatile unsigned long*) 0xFFFFFC30) /* (PMC) -Master Clock Register */ -#define AT91C_PMC_PLLAR (*(volatile unsigned long*) 0xFFFFFC28) /* (PMC) -PLL A Register */ -#define AT91C_PMC_PCDR (*(volatile unsigned long*) 0xFFFFFC14) /* (PMC) -Peripheral Clock Disable Register */ -#define AT91C_PMC_SCSR (*(volatile unsigned long*) 0xFFFFFC08) /* (PMC) -System Clock Status Register */ -#define AT91C_PMC_MCFR (*(volatile unsigned long*) 0xFFFFFC24) /* (PMC) -Main Clock Frequency Register */ -#define AT91C_PMC_IMR (*(volatile unsigned long*) 0xFFFFFC6C) /* (PMC) -Interrupt Mask Register */ -#define AT91C_PMC_IER (*(volatile unsigned long*) 0xFFFFFC60) /* (PMC) -Interrupt Enable Register */ -#define AT91C_PMC_MOR (*(volatile unsigned long *) 0xFFFFFC20) /* (PMC) -Main Oscillator Register */ -#define AT91C_PMC_IDR (*(volatile unsigned long *) 0xFFFFFC64) /* (PMC) -Interrupt Disable Register */ -#define AT91C_PMC_PLLBR (*(volatile unsigned long*) 0xFFFFFC2C) /* (PMC) -PLL B Register */ -#define AT91C_PMC_SCDR (*(volatile unsigned long*) 0xFFFFFC04) /* (PMC) -System Clock Disable Register */ -#define AT91C_PMC_PCSR (*(volatile unsigned long*) 0xFFFFFC18) /* (PMC) -Peripheral Clock Status Register */ -#define AT91C_PMC_SCER (*(volatile unsigned long*) 0xFFFFFC00) /* (PMC) -System Clock Enable Register */ -#define AT91C_PMC_SR (*(volatile unsigned long*) 0xFFFFFC68) /* (PMC) -Status Register */ - -/* Register definition for PITC peripheral */ -#define AT91C_PITC_PIVR (*(volatile unsigned long*) 0xFFFFFD38) /* (PITC) -Period Interval Value Register */ -#define AT91C_PITC_PISR (*(volatile unsigned long*) 0xFFFFFD34) /* (PITC) -Period Interval Status Register */ -#define AT91C_PITC_PIIR (*(volatile unsigned long*) 0xFFFFFD3C) /* (PITC) -Period Interval Image Register */ -#define AT91C_PITC_PIMR (*(volatile unsigned long*) 0xFFFFFD30) /* (PITC) -Period Interval Mode Register */ - -/* PIO DEFINITIONS FOR AT91SAM9260 */ -#define AT91C_PIO_PA0 (1 << 0) /* Pin Controlled by PA0 */ -#define AT91C_PIO_PA1 (1 << 1) /* Pin Controlled by PA1 */ -#define AT91C_PIO_PA10 (1 << 10) /* Pin Controlled by PA10 */ -#define AT91C_PIO_PA11 (1 << 11) /* Pin Controlled by PA11 */ -#define AT91C_PIO_PA12 (1 << 12) /* Pin Controlled by PA12 */ -#define AT91C_PIO_PA13 (1 << 13) /* Pin Controlled by PA13 */ -#define AT91C_PIO_PA14 (1 << 14) /* Pin Controlled by PA14 */ -#define AT91C_PIO_PA15 (1 << 15) /* Pin Controlled by PA15 */ -#define AT91C_PIO_PA16 (1 << 16) /* Pin Controlled by PA16 */ -#define AT91C_PIO_PA17 (1 << 17) /* Pin Controlled by PA17 */ -#define AT91C_PIO_PA18 (1 << 18) /* Pin Controlled by PA18 */ -#define AT91C_PIO_PA19 (1 << 19) /* Pin Controlled by PA19 */ -#define AT91C_PIO_PA2 (1 << 2) /* Pin Controlled by PA2 */ -#define AT91C_PIO_PA20 (1 << 20) /* Pin Controlled by PA20 */ -#define AT91C_PIO_PA21 (1 << 21) /* Pin Controlled by PA21 */ -#define AT91C_PIO_PA22 (1 << 22) /* Pin Controlled by PA22 */ -#define AT91C_PIO_PA23 (1 << 23) /* Pin Controlled by PA23 */ -#define AT91C_PIO_PA24 (1 << 24) /* Pin Controlled by PA24 */ -#define AT91C_PIO_PA25 (1 << 25) /* Pin Controlled by PA25 */ -#define AT91C_PIO_PA26 (1 << 26) /* Pin Controlled by PA26 */ -#define AT91C_PIO_PA27 (1 << 27) /* Pin Controlled by PA27 */ -#define AT91C_PIO_PA28 (1 << 28) /* Pin Controlled by PA28 */ -#define AT91C_PIO_PA29 (1 << 29) /* Pin Controlled by PA29 */ -#define AT91C_PIO_PA3 (1 << 3) /* Pin Controlled by PA3 */ -#define AT91C_PIO_PA30 (1 << 30) /* Pin Controlled by PA30 */ -#define AT91C_PIO_PA31 (1 << 31) /* Pin Controlled by PA31 */ -#define AT91C_PIO_PA4 (1 << 4) /* Pin Controlled by PA4 */ -#define AT91C_PIO_PA5 (1 << 5) /* Pin Controlled by PA5 */ -#define AT91C_PIO_PA6 (1 << 6) /* Pin Controlled by PA6 */ -#define AT91C_PIO_PA7 (1 << 7) /* Pin Controlled by PA7 */ -#define AT91C_PIO_PA8 (1 << 8) /* Pin Controlled by PA8 */ -#define AT91C_PIO_PA9 (1 << 9) /* Pin Controlled by PA9 */ -#define AT91C_PIO_PB0 (1 << 0) /* Pin Controlled by PB0 */ -#define AT91C_PIO_PB1 (1 << 1) /* Pin Controlled by PB1 */ -#define AT91C_PIO_PB10 (1 << 10) /* Pin Controlled by PB10 */ -#define AT91C_PIO_PB11 (1 << 11) /* Pin Controlled by PB11 */ -#define AT91C_PIO_PB12 (1 << 12) /* Pin Controlled by PB12 */ -#define AT91C_PIO_PB13 (1 << 13) /* Pin Controlled by PB13 */ -#define AT91C_PIO_PB14 (1 << 14) /* Pin Controlled by PB14 */ -#define AT91C_PIO_PB15 (1 << 15) /* Pin Controlled by PB15 */ -#define AT91C_PIO_PB16 (1 << 16) /* Pin Controlled by PB16 */ -#define AT91C_PIO_PB17 (1 << 17) /* Pin Controlled by PB17 */ -#define AT91C_PIO_PB18 (1 << 18) /* Pin Controlled by PB18 */ -#define AT91C_PIO_PB19 (1 << 19) /* Pin Controlled by PB19 */ -#define AT91C_PIO_PB2 (1 << 2) /* Pin Controlled by PB2 */ -#define AT91C_PIO_PB20 (1 << 20) /* Pin Controlled by PB20 */ -#define AT91C_PIO_PB21 (1 << 21) /* Pin Controlled by PB21 */ -#define AT91C_PIO_PB22 (1 << 22) /* Pin Controlled by PB22 */ -#define AT91C_PIO_PB23 (1 << 23) /* Pin Controlled by PB23 */ -#define AT91C_PIO_PB24 (1 << 24) /* Pin Controlled by PB24 */ -#define AT91C_PIO_PB25 (1 << 25) /* Pin Controlled by PB25 */ -#define AT91C_PIO_PB26 (1 << 26) /* Pin Controlled by PB26 */ -#define AT91C_PIO_PB27 (1 << 27) /* Pin Controlled by PB27 */ -#define AT91C_PIO_PB28 (1 << 28) /* Pin Controlled by PB28 */ -#define AT91C_PIO_PB29 (1 << 29) /* Pin Controlled by PB29 */ -#define AT91C_PIO_PB3 (1 << 3) /* Pin Controlled by PB3 */ -#define AT91C_PIO_PB30 (1 << 30) /* Pin Controlled by PB30 */ -#define AT91C_PIO_PB31 (1 << 31) /* Pin Controlled by PB31 */ -#define AT91C_PIO_PB4 (1 << 4) /* Pin Controlled by PB4 */ -#define AT91C_PIO_PB5 (1 << 5) /* Pin Controlled by PB5 */ -#define AT91C_PIO_PB6 (1 << 6) /* Pin Controlled by PB6 */ -#define AT91C_PIO_PB7 (1 << 7) /* Pin Controlled by PB7 */ -#define AT91C_PIO_PB8 (1 << 8) /* Pin Controlled by PB8 */ -#define AT91C_PIO_PB9 (1 << 9) /* Pin Controlled by PB9 */ -#define AT91C_PIO_PC0 (1 << 0) /* Pin Controlled by PC0 */ -#define AT91C_PIO_PC1 (1 << 1) /* Pin Controlled by PC1 */ -#define AT91C_PIO_PC10 (1 << 10) /* Pin Controlled by PC10 */ -#define AT91C_PIO_PC11 (1 << 11) /* Pin Controlled by PC11 */ -#define AT91C_PIO_PC12 (1 << 12) /* Pin Controlled by PC12 */ -#define AT91C_PIO_PC13 (1 << 13) /* Pin Controlled by PC13 */ -#define AT91C_PIO_PC14 (1 << 14) /* Pin Controlled by PC14 */ -#define AT91C_PIO_PC15 (1 << 15) /* Pin Controlled by PC15 */ -#define AT91C_PIO_PC16 (1 << 16) /* Pin Controlled by PC16 */ -#define AT91C_PIO_PC17 (1 << 17) /* Pin Controlled by PC17 */ -#define AT91C_PIO_PC18 (1 << 18) /* Pin Controlled by PC18 */ -#define AT91C_PIO_PC19 (1 << 19) /* Pin Controlled by PC19 */ -#define AT91C_PIO_PC2 (1 << 2) /* Pin Controlled by PC2 */ -#define AT91C_PIO_PC20 (1 << 20) /* Pin Controlled by PC20 */ -#define AT91C_PIO_PC21 (1 << 21) /* Pin Controlled by PC21 */ -#define AT91C_PIO_PC22 (1 << 22) /* Pin Controlled by PC22 */ -#define AT91C_PIO_PC23 (1 << 23) /* Pin Controlled by PC23 */ -#define AT91C_PIO_PC24 (1 << 24) /* Pin Controlled by PC24 */ -#define AT91C_PIO_PC25 (1 << 25) /* Pin Controlled by PC25 */ -#define AT91C_PIO_PC26 (1 << 26) /* Pin Controlled by PC26 */ -#define AT91C_PIO_PC27 (1 << 27) /* Pin Controlled by PC27 */ -#define AT91C_PIO_PC28 (1 << 28) /* Pin Controlled by PC28 */ -#define AT91C_PIO_PC29 (1 << 29) /* Pin Controlled by PC29 */ -#define AT91C_PIO_PC3 (1 << 3) /* Pin Controlled by PC3 */ -#define AT91C_PIO_PC30 (1 << 30) /* Pin Controlled by PC30 */ -#define AT91C_PIO_PC31 (1 << 31) /* Pin Controlled by PC31 */ -#define AT91C_PIO_PC4 (1 << 4) /* Pin Controlled by PC4 */ -#define AT91C_PIO_PC5 (1 << 5) /* Pin Controlled by PC5 */ -#define AT91C_PIO_PC6 (1 << 6) /* Pin Controlled by PC6 */ -#define AT91C_PIO_PC7 (1 << 7) /* Pin Controlled by PC7 */ -#define AT91C_PIO_PC8 (1 << 8) /* Pin Controlled by PC8 */ -#define AT91C_PIO_PC9 (1 << 9) /* Pin Controlled by PC9 */ - -/* PERIPHERAL ID DEFINITIONS FOR AT91SAM9260 */ -#define AT91C_ID_FIQ ( 0) /* Advanced Interrupt Controller (FIQ) */ -#define AT91C_ID_SYS ( 1) /* System Controller */ -#define AT91C_ID_PIOA ( 2) /* Parallel IO Controller A */ -#define AT91C_ID_PIOB ( 3) /* Parallel IO Controller B */ -#define AT91C_ID_PIOC ( 4) /* Parallel IO Controller C */ -#define AT91C_ID_ADC ( 5) /* ADC */ -#define AT91C_ID_US0 ( 6) /* USART 0 */ -#define AT91C_ID_US1 ( 7) /* USART 1 */ -#define AT91C_ID_US2 ( 8) /* USART 2 */ -#define AT91C_ID_MCI ( 9) /* Multimedia Card Interface 0 */ -#define AT91C_ID_UDP (10) /* USB Device Port */ -#define AT91C_ID_TWI (11) /* Two-Wire Interface */ -#define AT91C_ID_SPI0 (12) /* Serial Peripheral Interface 0 */ -#define AT91C_ID_SPI1 (13) /* Serial Peripheral Interface 1 */ -#define AT91C_ID_SSC0 (14) /* Serial Synchronous Controller 0 */ -#define AT91C_ID_TC0 (17) /* Timer Counter 0 */ -#define AT91C_ID_TC1 (18) /* Timer Counter 1 */ -#define AT91C_ID_TC2 (19) /* Timer Counter 2 */ -#define AT91C_ID_UHP (20) /* USB Host Port */ -#define AT91C_ID_EMAC (21) /* Ethernet Mac */ -#define AT91C_ID_HISI (22) /* Image Sensor Interface */ -#define AT91C_ID_US3 (23) /* USART 3 */ -#define AT91C_ID_US4 (24) /* USART 4 */ -#define AT91C_ID_US5 (25) /* USART 5 */ -#define AT91C_ID_TC3 (26) /* Timer Counter 3 */ -#define AT91C_ID_TC4 (27) /* Timer Counter 4 */ -#define AT91C_ID_TC5 (28) /* Timer Counter 5 */ -#define AT91C_ID_IRQ0 (29) /* Advanced Interrupt Controller (IRQ0) */ -#define AT91C_ID_IRQ1 (30) /* Advanced Interrupt Controller (IRQ1) */ -#define AT91C_ID_IRQ2 (31) /* Advanced Interrupt Controller (IRQ2) */ -#define AT91C_ALL_INT (0xFFFE7FFF) /* ALL VALID INTERRUPTS */ - -/* MEMORY MAPPING DEFINITIONS FOR AT91SAM9260 */ -#define AT91C_IRAM_1 (0x00200000) /* Maximum IRAM_1 Area : 4Kbyte -base address */ -#define AT91C_IRAM_1_SIZE (0x00001000) /* Maximum IRAM_1 Area : 4Kbyte size - in byte (4 Kbytes) */ -#define AT91C_EBI_SDRAM_32BIT (0x20000000) /* SDRAM on EBI Chip Select 1 -base address */ -#define AT91C_BASE_AIC 0xFFFFF000 /* (AIC) Base Address */ - -/* Timer frequency */ -/* timer is based on PCLK and minimum division is 2 */ -#define TIMER_FREQ (49156800/2) diff --git a/firmware/export/config.h b/firmware/export/config.h index 9fb964be5d..e43dce9568 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -79,7 +79,6 @@ #define JZ4732 4732 #define JZ4760B 47602 #define AS3525 3525 -#define AT91SAM9260 9260 #define AS3525v2 35252 #define IMX233 233 #define RK27XX 2700 @@ -122,10 +121,8 @@ #define ONDAVX767_PAD 32 #define SANSA_CLIP_PAD 35 #define SANSA_FUZE_PAD 36 -#define LYRE_PROTO1_PAD 37 #define SAMSUNG_YH820_PAD 38 #define ONDAVX777_PAD 39 -#define MINI2440_PAD 41 #define PHILIPS_HDD6330_PAD 42 #define PBELL_VIBE500_PAD 43 #define MPIO_HD200_PAD 44 @@ -246,11 +243,9 @@ #define LCD_ONDAVX767 30 /* as used by the Onda VX767 */ #define LCD_SSD1303 31 /* as used by the Sansa Clip */ #define LCD_FUZE 32 /* as used by the Sansa Fuze */ -#define LCD_LYRE_PROTO1 33 /* as used by the Lyre prototype 1 */ #define LCD_YH925 34 /* as used by Samsung YH-925 (similar to the H10 20GB) */ #define LCD_VIEW 35 /* as used by the Sansa View */ #define LCD_NANO2G 36 /* as used by the iPod Nano 2nd Generation */ -#define LCD_MINI2440 37 /* as used by the Mini2440 */ #define LCD_HDD6330 38 /* as used by the Philips HDD6330 */ #define LCD_VIBE500 39 /* as used by the Packard Bell Vibe 500 */ #define LCD_IPOD6GNANO3G4G 40 /* as used by the iPod Classic, Nano 3G and Nano 4G */ @@ -485,10 +480,6 @@ Lyre prototype 1 */ #include "config/sansaclipzip.h" #elif defined(SANSA_C200V2) #include "config/sansac200v2.h" -#elif defined(LYRE_PROTO1) -#include "config/lyreproto1.h" -#elif defined(MINI2440) -#include "config/mini2440.h" #elif defined(SAMSUNG_YH820) #include "config/samsungyh820.h" #elif defined(SAMSUNG_YH920) diff --git a/firmware/export/config/lyreproto1.h b/firmware/export/config/lyreproto1.h deleted file mode 100644 index e30b3c4213..0000000000 --- a/firmware/export/config/lyreproto1.h +++ /dev/null @@ -1,102 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * This config file is for the Lyre prototype 1. - */ - -#define CONFIG_SDRAM_START 0x20000000 - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 130 - -/* define this if the flash memory uses the - * SecureDigital Memory Card protocol */ -#define CONFIG_STORAGE STORAGE_SD -#define HAVE_FLASH_STORAGE - - - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -#define CONFIG_LCD LCD_LYRE_PROTO1 - -/* LCD dimensions */ -#define LCD_WIDTH 128 -#define LCD_HEIGHT 128 -/* sqrt(128^2 + 128^2) / 1.8 = 100.6 */ -#define LCD_DPI 101 -/* The LCD used is just rgb444, 64 colours. We do a bit conversion on LCD - * drivers. */ -#define LCD_DEPTH 16 /* 65536 colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -#define HAVE_ALBUMART - -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING - -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -#define CONFIG_KEYPAD LYRE_PROTO1_PAD - - - - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x100000 - -/* Lyre prototype 1 do not use I2C, just SPI */ -#define CONFIG_I2C I2C_NONE - -/* Define this if you have the TLV320 audio codec -> controlled by the DSP */ -#define HAVE_TLV320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -#define BATTERY_CAPACITY_DEFAULT 1100 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 100 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -#define CONFIG_CPU AT91SAM9260 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 198656000 -#define MCK_FREQ 99328000 -#define SLOW_CLOCK 32768 - -#define BOOTFILE_EXT "lyre_proto1" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -/* Define this if a programmable hotkey is mapped */ -//#define HAVE_HOTKEY diff --git a/firmware/export/config/mini2440.h b/firmware/export/config/mini2440.h deleted file mode 100644 index b22098e859..0000000000 --- a/firmware/export/config/mini2440.h +++ /dev/null @@ -1,154 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * Copyright (C) 2009 by Bob Cousins, Lyre Project - * Copyright (C) 2009 by Jorge Pinto, Lyre Project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * This config file is for the Mini2440 - */ - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 131 -#define MODEL_NAME "Mini2440" - -/***************************************************************************/ -/* Hardware Config */ - -/* TODO: ??? */ -#define CONFIG_SDRAM_START 0x30000000 - -/* Flash storage */ -#define HAVE_FLASH_STORAGE -/* define the storage type */ -#define CONFIG_STORAGE STORAGE_SD - -#define HAVE_MULTIVOLUME -#define HAVE_HOTSWAP -#define HAVE_HOTSWAP_STORAGE_AS_MAIN -#define INCLUDE_TIMEOUT_API - -/* Disk storage */ -/* define this if you have a disk storage, i.e. something - that needs spinups and can cause skips when shaked */ -/* #define HAVE_DISK_STORAGE */ - -/* Display */ - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR -/* The LCD is assumed to be 3.5" TFT touch screen, others are possible */ -#define CONFIG_LCD LCD_MINI2440 -/* LCD dimensions */ -#define LCD_WIDTH 240 -#define LCD_HEIGHT 320 -/* sqrt(240^2 + 320^2) / 3.5 = 114.3 */ -#define LCD_DPI 114 -#define LCD_DPI 114 /* 400 pixels diagonally / 3.5 inch */ -/* The LCD is configured for RGB565 */ -#define LCD_DEPTH 16 /* 65536 colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ -/* Define this for LCD backlight available */ -/* The Mini2440 supports backlight brightness depending on LCD type */ -/* But the 3.5" LCD touch screen does not support brightness*/ -#define HAVE_BACKLIGHT -#define HAVE_BACKLIGHT_BRIGHTNESS -/* Main LCD backlight brightness range and defaults */ -#define MIN_BRIGHTNESS_SETTING 1 /* 0.5 mA */ -#define MAX_BRIGHTNESS_SETTING 12 /* 32 mA */ -#define DEFAULT_BRIGHTNESS_SETTING 10 /* 16 mA */ - -/* Keypad */ -#define CONFIG_KEYPAD MINI2440_PAD -#define HAVE_TOUCHSCREEN -#define HAVE_BUTTON_DATA - -/* I2C */ -/* We do not use currently use hardware I2C, but does not build without */ -#define CONFIG_I2C I2C_S3C2440 - -/* Define DAC/Codec */ -#define HAVE_UDA1341 - -#define HW_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11) - -/* Battery */ -#define BATTERY_CAPACITY_DEFAULT 1100 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 100 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - - - -/***************************************************************************/ -/* Application Config */ - -#define HAVE_ALBUMART -/* define this to enable bitmap scaling */ -#define HAVE_BMP_SCALING -/* define this to enable JPEG decoding */ -#define HAVE_JPEG - -#define HAVE_QUICKSCREEN - -/* define this if you have a real-time clock */ -#define CONFIG_RTC RTC_S3C2440 - - - - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x100000 - -#define CONFIG_CPU S3C2440 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 406000000 -#define MCK_FREQ (CPU_FREQ/4) -#define SLOW_CLOCK 32768 - - -/* Define this if your LCD can set contrast */ -#define HAVE_LCD_CONTRAST -#define MIN_CONTRAST_SETTING 0 -#define MAX_CONTRAST_SETTING 63 -#define DEFAULT_CONTRAST_SETTING 47 /* Match boot contrast */ - -/* USB */ -/* TODO:#define HAVE_USBSTACK */ -#define USB_NONE - -#define HAVE_SERIAL - -/* Hardware controlled charging with monitoring */ -#define CONFIG_CHARGING CHARGING_MONITOR -/*#define POWER_INPUT_BATTERY 0*/ - -#define BOOTFILE_EXT "mini2440" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/target/arm/at91sam/boot.lds b/firmware/target/arm/at91sam/boot.lds deleted file mode 100644 index 2497e09958..0000000000 --- a/firmware/target/arm/at91sam/boot.lds +++ /dev/null @@ -1,81 +0,0 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") -OUTPUT_ARCH(arm) -ENTRY(reset_handler) -STARTUP(target/arm/at91sam/lyre_proto1/crt0.o) - -#define DRAMSIZE (MEMORYSIZE * 0x100000) -#define DRAMORIG 0x20000000 -#define IRAM0ORIG 0x200000 -#define IRAM0SIZE 4K -#define IRAM1ORIG 0x300000 -#define IRAM1SIZE 4K -#define STACKSIZE 2k - -MEMORY -{ - DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE - IRAM0 : ORIGIN = IRAM0ORIG, LENGTH = IRAM0SIZE -} - -SECTIONS -{ - /* We will put Rockbox bootloader at the last 1MByte of the SDRAM. */ - - /* Example of a section: - * .section VMA(Virtual Memory Address) : LMA(Load Memory Address). - * VMA and LMA addresses can be verified by doing: - * "arm-elf-objdump -h bootloader.elf". */ - - .vectors 0 : AT (DRAMORIG + DRAMSIZE - 1M) - { - _start_vectors_section = .; - KEEP(*(.vectors)) - *(.glue_7) - *(.glue_7t) - . = ALIGN(4); - _end_vectors_section = .; - } - - .text (DRAMORIG + DRAMSIZE -1M + SIZEOF(.vectors)) : \ - AT (DRAMORIG + DRAMSIZE -1M + SIZEOF(.vectors)) - { - *(.text) - *(.text*) - *(.icode) - *(.icode*) - *(.rodata) - *(.rodata*) - . = ALIGN(4); - } - - /* Initialized variables are placed on SDRAM, right after .vectors section. */ - /* Data section: VMA is the same as the LMA, right after the end of .vector */ - .data . : - { - *(.data) - *(.data*) - . = ALIGN(4); - _end_data_section = .; - } - - /* Uninitialized variables are placed at SDRAM, right after .text section. */ - .bss (NOLOAD) : - - { - _start_bss_section = .; - *(.bss) /* Bss section contains all uninitialized data generated by the compiler. */ - *(.bss*) - *(COMMON) - . = ALIGN(4); - _end_bss_section = .; - } - - /* Stack is placed at SDRAM, right after .bss section. */ - .stack . : - { - *(.stack) - stackbegin = .; - . += STACKSIZE; - stackend = .; - } -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c deleted file mode 100644 index d3674055ab..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "adc.h" - -void adc_init(void) -{ -} - -/* Called to get the recent ADC reading */ -inline unsigned short adc_read(int channel) -{ - (void)channel; - return 0; -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/adc-target.h b/firmware/target/arm/at91sam/lyre_proto1/adc-target.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/firmware/target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c deleted file mode 100644 index b60449417a..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -void backlight_hw_brightness(int brightness) -{ - (void)brightness; -} - -void backlight_hw_on(void) -{ - -} - -void backlight_hw_off(void) -{ - -} - -void buttonlight_hw_on(void) -{ - -} - -void buttonlight_hw_off(void) -{ - -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/backlight-target.h b/firmware/target/arm/at91sam/lyre_proto1/backlight-target.h deleted file mode 100644 index f4e253abbe..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/backlight-target.h +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H - - -#endif diff --git a/firmware/target/arm/at91sam/lyre_proto1/button-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/button-lyre_proto1.c deleted file mode 100644 index 2d38803115..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/button-lyre_proto1.c +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "at91sam9260.h" -#include "button.h" - -#define BUTTON_01 AT91C_PIO_PB4 -#define BUTTON_02 AT91C_PIO_PB5 -#define BUTTON_03 AT91C_PIO_PB27 -#define BUTTON_04 AT91C_PIO_PB26 -#define BUTTON_05 AT91C_PIO_PB25 -#define BUTTON_06 AT91C_PIO_PB24 -#define BUTTON_07 AT91C_PIO_PB22 -#define BUTTON_08 AT91C_PIO_PB23 - -void button_init_device(void) -{ - /* Enable the periph clock for the PIO controller */ - /* This is mandatory when PIO are configured as input */ - AT91C_PMC_PCER = (1 << AT91C_ID_PIOB); - - /* Set the PIO line in input */ - AT91C_PIOB_ODR = (BUTTON_01 | - BUTTON_02 | - BUTTON_03 | - BUTTON_04 | - BUTTON_05 | - BUTTON_06 | - BUTTON_07 | - BUTTON_08); - - /* Set the PIO controller in PIO mode instead of peripheral mode */ - AT91C_PIOB_PER = (BUTTON_01 | - BUTTON_02 | - BUTTON_03 | - BUTTON_04 | - BUTTON_05 | - BUTTON_06 | - BUTTON_07 | - BUTTON_08); -} - -bool button_hold(void) -{ - return (0); -} - -/* - * Get button pressed from hardware - */ -int button_read_device(void) -{ - uint32_t buttons = AT91C_PIOB_PDSR; - uint32_t ret = 0; - - if ((buttons & BUTTON_01) == 0) - ret |= BUTTON_UP; - - if ((buttons & BUTTON_02) == 0) - ret |= BUTTON_RIGHT; - - if ((buttons & BUTTON_03) == 0) - ret |= BUTTON_PLAY; - - if ((buttons & BUTTON_04) == 0) - ret |= BUTTON_SELECT; - - if ((buttons & BUTTON_05) == 0) - ret |= BUTTON_LEFT; - - if ((buttons & BUTTON_06) == 0) - ret |= BUTTON_DOWN; - - if ((buttons & BUTTON_07) == 0) - ret |= BUTTON_STOP; - - if ((buttons & BUTTON_08) == 0) - ret |= BUTTON_MENU; - - return ret; -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/button-target.h b/firmware/target/arm/at91sam/lyre_proto1/button-target.h deleted file mode 100644 index bfba483df1..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/button-target.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#define BUTTON_SELECT 0x00000001 -#define BUTTON_MENU 0x00000002 -#define BUTTON_PLAY 0x00000004 -#define BUTTON_STOP 0x00000008 - -#define BUTTON_LEFT 0x00000010 -#define BUTTON_RIGHT 0x00000020 -#define BUTTON_UP 0x00000040 -#define BUTTON_DOWN 0x00000080 - -#define BUTTON_MAIN (BUTTON_UP|BUTTON_DOWN|BUTTON_RIGHT|BUTTON_LEFT \ - |BUTTON_SELECT|BUTTON_MENU|BUTTON_PLAY \ - |BUTTON_STOP) - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/at91sam/lyre_proto1/crt0.S b/firmware/target/arm/at91sam/lyre_proto1/crt0.S deleted file mode 100644 index 029c1b7aec..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/crt0.S +++ /dev/null @@ -1,286 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "at91sam9260.h" - -#define DRAMORIG AT91C_EBI_SDRAM_32BIT -#define DRAMSIZE (MEMORYSIZE * 0x100000) -#define IRAM0ORIG AT91C_IRAM_1 -#define IRAM0SIZE AT91C_IRAM_1_SIZE -#define TOP_OF_MEMORY (IRAM0ORIG + IRAM0SIZE) -#define ABT_STACK_SIZE 8*3*4 -#define IRQ_STACK_SIZE 8*3*4 - -#define ARM_MODE_ABT 0x17 -#define ARM_MODE_FIQ 0x11 -#define ARM_MODE_IRQ 0x12 -#define ARM_MODE_SVC 0x13 -#define ARM_MODE_UND 0x1b -#define ARM_MODE_SYS 0x1f - -#define I_BIT 0x80 -#define F_BIT 0x40 - - -/* Application startup entry point */ -.globl reset_handler - -.align 4 - -.section .vectors -.arm - - -/* Exception vectors (should be a branch to be detected as a valid code - * by the rom) */ -_exception_vectors: -reset_vector: - ldr pc, =reset_handler -undef_vector: - b undef_vector /* Undefined Instruction */ -swi_vector: - b swi_vector /* Software Interrupt */ -pabt_vector: - ldr pc, =pabt_handler /* Prefetch Abort */ -dabt_vector: - ldr pc, =dabt_handler /* Data Abort */ -rsvd_vector: - b rsvd_vector /* reserved */ -irq_vector: - b irq_handler /* IRQ : read the AIC */ -fiq_vector: -/*----------------------------------------------------------------------------- - *- Function : fiq_handler - *- Treatments : FIQ (Fast Interrupt) Interrupt Handler. - *- Called Functions : - *---------------------------------------------------------------------------*/ -fiq_handler: -pabt_handler: -dabt_handler: - b fiq_handler - -/*----------------------------------------------------------------------------- - *- Function : irq_handler - *- Treatments : IRQ Controller Interrupt Handler. - *- Called Functions : AIC_IVR[interrupt] - *---------------------------------------------------------------------------*/ -irq_handler: -/*- Manage Exception Entry */ -/*- Adjust and save LR_irq in IRQ stack - (LR - Link Register) */ - sub lr, lr, #4 - stmfd sp!, {lr} -/*- Save r0 and SPSR (Saved Program Status Register) in IRQ stack */ - mrs r14, SPSR - stmfd sp!, {r0,r14} - -/*- Write in the IVR (Interrupt Vector Register) to support Protect Mode */ -/*- No effect in Normal Mode */ -/*- De-assert the NIRQ and clear the source in Protect Mode */ - ldr r14, =AT91C_BASE_AIC - ldr r0 , [r14, #AIC_IVR] - str r14, [r14, #AIC_IVR] - -/*- Enable Interrupt and Switch in Supervisor Mode */ - msr CPSR_c, #ARM_MODE_SVC - -/*- Save scratch/used registers and LR in User Stack */ - stmfd sp!, {r1-r3, r12, r14} - -/*- Branch to the routine pointed by the AIC_IVR */ - mov r14, pc - bx r0 - -/*- Restore scratch/used registers and LR from User Stack */ - ldmia sp!, {r1-r3, r12, r14} - -/*- Disable Interrupt and switch back in IRQ mode */ - msr CPSR_c, #ARM_MODE_IRQ | I_BIT - -/*- Mark the End of Interrupt on the AIC */ - ldr r14, =AT91C_BASE_AIC - str r14, [r14, #AIC_EOICR] - -/*- Restore SPSR_irq and r0 from IRQ stack */ - ldmia sp!, {r0,r14} - msr SPSR_cxsf, r14 - -/*- Restore adjusted LR_irq from IRQ stack directly in the PC */ - ldmia sp!, {pc}^ - -/*----------------------------------------------------------------------------- - *- Function : reset_handler - *- Treatments : Reset Interrupt Handler. - *- Called Functions : lowlevel_init - * main - *---------------------------------------------------------------------------*/ -.section .text -reset_handler: -/*----------------------------------------------------------------------------- - *- Low level Init is performed in a C function: lowlevel_init - *- Init Stack Pointer to a valid memory area before calling lowlevel_init - * - * Put Stack Pointer on end of IRAM 1 and branches to lowlevel_init function. - *---------------------------------------------------------------------------*/ -/*- Temporary stack in internal RAM for Low Level Init execution */ -_low_level_init: - ldr r2, =_litteral_pool_lowlevel_init /* Load r2 with the address of - * _litteral_pool_lowlevel_init - */ - ldmia r2, {r0, r1} /* r0 = lowlevel_init and r1 = TOP_OF_MEMORY */ - mov sp, r1 /* sp (Stack Pointer) = TOP_OF_MEMORY (end of IRAM 1) */ - mov lr, pc /* lr (Link register) = pc (Program Counter) */ - bx r0 /* Branch on C function (interworking) -- branch to - * lowlevel_init - */ - -/*----------------------------------------------------------------------------- - *- Setup the stack for each mode - * - * Executes this code after returning from lowlevel_init fucntion. - * Configures Abort Mode Stack + Interrupt Mode Stack + Supervisor Mode Stack, - * reserves 3 blocks, one for each mode and they start at end of IRAM 1. - *---------------------------------------------------------------------------*/ -_stack_init: - ldr r2, =_litteral_pool_stack_init - ldmia r2, {r0, r1, r2} /* r0 = TOP_OF_MEMORY (end of IRAM 1); - * r1 = ABT_STACK_SIZE; - * r2 = IRQ_STACK_SIZE - */ - - /*- Set up Interrupt Mode and set IRQ Mode Stack */ - msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* Enter in Mode Interrupt - * and disable IRQ (Interrupt) and FIQ (Fast Interrupt) - */ - - mov sp, r0 /* sp (Interrupt Mode Stack Pointer) = - * TOP_OF_MEMORY (end of IRAM 1) - */ - - /*- Set up Abort Mode and set ABT Mode Stack */ - msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT /* Enter in Mode Abort - * and disable IRQ (Interrupt) and FIQ (Fast Interrupt) - */ - - mov sp, r0 /* sp (ABT Mode Stack Pointer) = TOP_OF_MEMORY - * (end of IRAM 1) - */ - - /*- Set up Abort Mode and set ABT Mode Stack */ - msr CPSR_c, #ARM_MODE_UND | I_BIT | F_BIT /* Enter in Mode Undefined - * and disable IRQ (Interrupt) and FIQ (Fast Interrupt) - */ - - mov sp, r0 /* sp (ABT Mode Stack Pointer) = TOP_OF_MEMORY - * (end of IRAM 1) - */ - - /*- Set up Supervisor Mode and set Supervisor Mode Stack */ - msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT - mov sp, r0 - - sub r0, r0, r2 /* Put on r0 the new address for next - * Stack (Sys Mode) - */ - - /*- Set up Sys Mode and set Sys Mode Stack */ - msr CPSR_c, #ARM_MODE_SYS | F_BIT /* Enter in Sys Mode - * and enable IRQ (Interrupt) and disable FIQ (Fast Interrupt) - */ - mov sp, r0 - -/*----------------------------------------------------------------------------- - *- Segments initialization - *---------------------------------------------------------------------------*/ -/* Copy the vectors section code from the LMA address to the LVA address */ -_init_vectors: - ldr r1, =_litteral_pool_vectors /* Load r1 with the address of - * _litteral_pool_vectors - */ - ldmia r1, {r2, r3, r4} /* r2 = DRAMORIG; r3 = _start_vectors_section; - * r4 = _end_vectors_section; - */ -1: - cmp r3, r4 /* Compare r3 with r4 (r3 - r4) */ - ldrcc r5, [r2], #4 /* if (_start_vectors_section < _end_vectors_section) - * { r5 = [r2]; r2 = r2 + 4; } - */ - strcc r5, [r3], #4 /* if (_start_vectors_section < _end_vectors_section) - * { [r3] = r5; r3 = r3 + 4; } - */ - bcc 1b /* loop while (_start_vectors_section < _end_vectors_section) */ - -/* Clear the bss segment */ -_init_bss: - ldr r2, =_litteral_pool_bss - ldmia r2, {r3, r4} /* r3 = _start_bss_section; r4 = _end_bss_section */ - mov r2, #0 /* r2 = 0 */ -1: - cmp r3, r4 /* Compare --> (_start_bss_section - _end_bss_section) */ - strcc r2, [r3], #4 /* if (_start_bss_section < _end_bss_section) { - * [r3] = 0; r3 = r3 + 4; } - */ - bcc 1b /* loop while _start_bss_section < _end_bss_section */ - -/* Set up some stack and munge it with 0xdeadbeef */ - ldr sp, =stackend - mov r3, sp - ldr r2, =stackbegin - ldr r4, =0xdeadbeef - -stackmunge: - cmp r3, r2 - strhi r4, [r2], #4 - bhi stackmunge - -/*----------------------------------------------------------------------------- - *- Branch to the main - *---------------------------------------------------------------------------*/ -_branch_main: - ldr r0, =main - mov lr, pc - bx r0 - -/*----------------------------------------------------------------------------- - *- Litteral pools - *---------------------------------------------------------------------------*/ -_litteral_pool_lowlevel_init: - .word lowlevel_init - .word TOP_OF_MEMORY /* Default SVC stack after power up */ - -_litteral_pool_stack_init: - .word TOP_OF_MEMORY /* Top of the stack */ - .word ABT_STACK_SIZE /* ABT stack size */ - .word IRQ_STACK_SIZE /* IRQ stack size */ - -_litteral_pool_bss: - .word _start_bss_section - .word _end_bss_section - -_litteral_pool_vectors: -#if defined(BOOTLOADER) - .word (DRAMORIG + DRAMSIZE - 0x100000) /* LMA address of vectors are at - * end of DRAM minus 1MByte - */ -#else - .word DRAMORIG /* LMA address of vectors are at DRAMORIG */ -#endif - .word _start_vectors_section - .word _end_vectors_section diff --git a/firmware/target/arm/at91sam/lyre_proto1/debug-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/debug-lyre_proto1.c deleted file mode 100644 index 320833a55b..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/debug-lyre_proto1.c +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include "system.h" - -bool dbg_ports(void) -{ - return false; -} - -bool dbg_hw_info(void) -{ - return false; -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/kernel-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/kernel-lyre_proto1.c deleted file mode 100644 index 4d7167b3ba..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/kernel-lyre_proto1.c +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "system.h" -#include "kernel.h" -#include "timer.h" -#include "thread.h" -#include "at91sam9260.h" - -/*----------------------------------------------------------------------------- - * Function Name : pitc_handler - * Object : Handler for PITC interrupt - *---------------------------------------------------------------------------*/ -void pitc_handler(void) -{ - unsigned long pivr = 0; - unsigned long pisr = 0; - - /* Read the PISR */ - pisr = AT91C_PITC_PISR & AT91C_PITC_PITS; - - /* Read the PIVR. It acknowledges the IT */ - pivr = AT91C_PITC_PIVR; - - /* Run through the list of tick tasks */ - call_tick_tasks(); -} - -void tick_start(unsigned int interval_in_ms) -{ - volatile unsigned long pimr = 0; - - /* Configure a resolution of 1 ms */ - AT91C_PITC_PIMR = MCK_FREQ / (((16 * 1000) - 1) / interval_in_ms); - - /* Enable interrupts */ - /* Disable the interrupt on the interrupt controller */ - AT91C_AIC_IDCR = (1 << AT91C_ID_SYS); - - /* Save the interrupt handler routine pointer and the interrupt priority */ - AT91C_AIC_SVR(AT91C_ID_SYS) = (unsigned long) pitc_handler; - - /* Store the Source Mode Register */ - AT91C_AIC_SMR(AT91C_ID_SYS) = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | \ - AT91C_AIC_PRIOR_LOWEST; - /* Clear the interrupt on the interrupt controller */ - AT91C_AIC_ICCR = (1 << AT91C_ID_SYS); - - /* Enable the interrupt on the interrupt controller */ - AT91C_AIC_IECR = (1 << AT91C_ID_SYS); - - /* Enable the interrupt on the pit */ - pimr = AT91C_PITC_PIMR; - AT91C_PITC_PIMR = pimr | AT91C_PITC_PITIEN; - - /* Enable the pit */ - pimr = AT91C_PITC_PIMR; - AT91C_PITC_PIMR = pimr | AT91C_PITC_PITEN; -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/lcd-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/lcd-lyre_proto1.c deleted file mode 100644 index 258b2052a6..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/lcd-lyre_proto1.c +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "lcd.h" - -/* Update the display. - This must be called after all other LCD functions that change the display */ -void lcd_update(void) -{ - -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/lcd-target.h b/firmware/target/arm/at91sam/lyre_proto1/lcd-target.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/firmware/target/arm/at91sam/lyre_proto1/system-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/system-lyre_proto1.c deleted file mode 100644 index 34318d24aa..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/system-lyre_proto1.c +++ /dev/null @@ -1,149 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Include Standard files */ -#include "at91sam9260.h" -#include "config.h" - -/*----------------------------------------------------------------------------- - * Function Name : default_spurious_handler - * Object : default handler for spurious interrupt - *---------------------------------------------------------------------------*/ -void default_spurious_handler(void) -{ - while (1); -} - -/*----------------------------------------------------------------------------- - * Function Name : default_fiq_handler - * Object : default handler for fast interrupt - *---------------------------------------------------------------------------*/ -void default_fiq_handler(void) -{ - while (1); -} - -/*----------------------------------------------------------------------------- - * Function Name : default_irq_handler - * Object : default handler for irq - *---------------------------------------------------------------------------*/ -void default_irq_handler(void) -{ -#if defined(BOOTLOADER) - while (1); -#endif -} - -/*----------------------------------------------------------------------------- - * Function Name : lowlevel_init - * Object : This function performs very low level HW initialization - * this function can use a Stack, depending the compilation - * optimization mode - *---------------------------------------------------------------------------*/ -void lowlevel_init(void) -{ - unsigned char i = 0; - - /* void default_fiq_handler(void) - * Init PMC Step 1. Enable Main Oscillator - * Main Oscillator startup time is board specific: - * Main Oscillator Startup Time worst case (3MHz) corresponds to 15ms - * (0x40 for AT91C_CKGR_OSCOUNT field) - */ - AT91C_PMC_MOR = (((AT91C_CKGR_OSCOUNT & (0x40 << 8)) | AT91C_CKGR_MOSCEN)); - /* Wait Main Oscillator stabilization */ - while (!(AT91C_PMC_SR & AT91C_PMC_MOSCS)); - - /* Init PMC Step 2. - * Set PLLA to 198,608MHz - * PLL Startup time depends on PLL RC filter: worst case is choosen. - * - * Crystal frequency = 18.432MHz; PLLA = (18.432 * 96) / 9 = 198,608MHz. - */ - - AT91C_PMC_PLLAR = (1 << 29) | - (0x60 << 16) | /* MULA = 96 */ - (0x2 << 14) | - (0x3f << 8) | - (0x09); /* DIVA = 9 */ - - /* Wait for PLLA stabilization */ - while (!(AT91C_PMC_SR & AT91C_PMC_LOCKA)); - /* Wait until the master clock is established for the case we already */ - /* turn on the PLLA */ - while (!(AT91C_PMC_SR & AT91C_PMC_MCKRDY)); - - /* Init PMC Step 3. - * Processor Clock = 198,608MHz (PLLA); Master clock = - * (198,608MHz (PLLA))/2 = 98,304MHz. - * The PMC_MCKR register must not be programmed in a single write operation - * (see. Product Errata Sheet) - */ - AT91C_PMC_MCKR = AT91C_PMC_PRES_CLK | AT91C_PMC_MDIV_2; - /* Wait until the master clock is established */ - while (!(AT91C_PMC_SR & AT91C_PMC_MCKRDY)); - - AT91C_PMC_MCKR |= AT91C_PMC_CSS_PLLA_CLK; - /* Wait until the master clock is established */ - while (!(AT91C_PMC_SR & AT91C_PMC_MCKRDY)); - - /* Reset AIC: assign default handler for each interrupt source - */ - - /* Disable the interrupt on the interrupt controller */ - AT91C_AIC_IDCR = (1 << AT91C_ID_SYS); - - /* Assign default handler for each IRQ source */ - AT91C_AIC_SVR(AT91C_ID_FIQ) = (int) default_fiq_handler; - for (i = 1; i < 31; i++) - { - AT91C_AIC_SVR(i) = (int) default_irq_handler; - } - AT91C_AIC_SPU = (unsigned int) default_spurious_handler; - - /* Perform 8 IT acknoledge (write any value in EOICR) */ - -/* The End of Interrupt Command Register (AIC_EOICR) must be written in order -to indicate to the AIC that the current interrupt is finished. This causes the -current level to be popped from the stack, restoring the previous current level -if one exists on the stack. If another interrupt is pending, with lower or -equal priority than the old current level but with higher priority than the new -current level, the nIRQ line is re-asserted, but the interrupt sequence does -not immediately start because the “I” bit is set in the core. -SPSR_irq is restored. Finally, the saved value of the link register is restored -directly into the PC. This has the effect of returning from the interrupt to -whatever was being executed before, and of loading the CPSR with the stored -SPSR, masking or unmasking the interrupts depending on the state saved in -SPSR_irq. */ - for (i = 0; i < 8 ; i++) - { - AT91C_AIC_EOICR = 0; - } - - /* Enable the interrupt on the interrupt controller */ - AT91C_AIC_IECR = (1 << AT91C_ID_SYS); - - /* Disable Watchdog */ - AT91C_WDTC_WDMR = AT91C_WDTC_WDDIS; - - /* Remap */ - AT91C_MATRIX_MRCR = AT91C_MATRIX_RCA926I | AT91C_MATRIX_RCA926D; -} diff --git a/firmware/target/arm/at91sam/lyre_proto1/system-target.h b/firmware/target/arm/at91sam/lyre_proto1/system-target.h deleted file mode 100644 index 479614f634..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/system-target.h +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef SYSTEM_TARGET_H -#define SYSTEM_TARGET_H - -#include "system-arm.h" - -void system_init(void); - -#endif /* SYSTEM_TARGET_H */ diff --git a/firmware/target/arm/at91sam/lyre_proto1/timer-lyre_proto1.c b/firmware/target/arm/at91sam/lyre_proto1/timer-lyre_proto1.c deleted file mode 100644 index 1b620e9c4f..0000000000 --- a/firmware/target/arm/at91sam/lyre_proto1/timer-lyre_proto1.c +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * - * Copyright (C) 2009 by Jorge Pinto - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "cpu.h" -#include "system.h" -#include "timer.h" -#include "logf.h" -#include "at91sam9260.h" - -/*----------------------------------------------------------------------------- - * Function Name : pitc_handler - * Object : Handler for PITC interrupt - *---------------------------------------------------------------------------*/ -void pitc_handler(void) -{ - unsigned long pivr = 0; - unsigned long pisr = 0; - - /* Read the PISR */ - pisr = AT91C_PITC_PISR & AT91C_PITC_PITS; - - if (pisr != 0) - { - /* Read the PIVR. It acknowledges the IT */ - pivr = AT91C_PITC_PIVR; - - if (pfn_timer != NULL) - pfn_timer(); - } -} - -bool timer_set(long cycles, bool start) -{ - if (cycles < 1000) /* Max value on PITC?? */ - { - if (start && pfn_unregister != NULL) - { - pfn_unregister(); - pfn_unregister = NULL; - } - - /* Configure a resolution of ms */ - AT91C_PITC_PIMR = MCK_FREQ / ( 16 * cycles) - 1; - - return true; - } - - return false; -} - -bool timer_start(void) -{ - bool retval = true; - volatile unsigned long pimr = 0; - - /* Configure a resolution of 1 ms */ - AT91C_PITC_PIMR = MCK_FREQ / (16 * 1000) - 1; - - /* Enable interrupts */ - /* Disable the interrupt on the interrupt controller */ - AT91C_AIC_IDCR = (1 << AT91C_ID_SYS); - - /* Save the interrupt handler routine pointer and the interrupt priority */ - AT91C_AIC_SVR(AT91C_ID_SYS) = (unsigned long) pitc_handler; - /* Store the Source Mode Register */ - AT91C_AIC_SMR(AT91C_ID_SYS) = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | \ - AT91C_AIC_PRIOR_LOWEST; - /* Clear the interrupt on the interrupt controller */ - AT91C_AIC_ICCR = (1 << AT91C_ID_SYS); - - /* Enable the interrupt on the interrupt controller */ - AT91C_AIC_IECR = (1 << AT91C_ID_SYS); - - /* Enable the interrupt on the pit */ - pimr = AT91C_PITC_PIMR; - AT91C_PITC_PIMR = pimr | AT91C_PITC_PITIEN; - - /* Enable the pit */ - pimr = AT91C_PITC_PIMR; - AT91C_PITC_PIMR = pimr | AT91C_PITC_PITEN; - - return retval; -} - -void timer_stop(void) -{ - volatile unsigned long pimr = 0; - - /* Disable the interrupt on the interrupt controller */ - AT91C_AIC_IDCR = (1 << AT91C_ID_SYS); - - /* Clear the interrupt on the interrupt controller */ - AT91C_AIC_ICCR = (1 << AT91C_ID_SYS); - - /* Disable the interrupt on the pit */ - pimr = AT91C_PITC_PIMR; - pimr &= ~AT91C_PITC_PITIEN; - AT91C_PITC_PIMR = pimr; - - /* Disable the pit */ - pimr = AT91C_PITC_PIMR; - pimr &= ~AT91C_PITC_PITEN; - AT91C_PITC_PIMR = pimr; -} diff --git a/firmware/target/arm/mmu-arm.S b/firmware/target/arm/mmu-arm.S index 2458118186..bb3bfa9815 100644 --- a/firmware/target/arm/mmu-arm.S +++ b/firmware/target/arm/mmu-arm.S @@ -24,7 +24,7 @@ /* Used by ARMv4 & ARMv5 CPUs with cp15 register and MMU */ -#if CONFIG_CPU == TCC7801 || CONFIG_CPU == AT91SAM9260 +#if CONFIG_CPU == TCC7801 /* MMU present but unused */ #define HAVE_TEST_AND_CLEAN_CACHE diff --git a/firmware/target/arm/s3c2440/adc-s3c2440.c b/firmware/target/arm/s3c2440/adc-s3c2440.c index 2e0cf8a512..f7faf54786 100644 --- a/firmware/target/arm/s3c2440/adc-s3c2440.c +++ b/firmware/target/arm/s3c2440/adc-s3c2440.c @@ -24,10 +24,6 @@ #include "adc-target.h" #include "kernel.h" -#ifdef MINI2440 -#include "touchscreen-target.h" -#endif - static unsigned short adc_readings[NUM_ADC_CHANNELS]; /* prototypes */ @@ -136,10 +132,6 @@ static void adc_tick(void) { channel = 0; } -#ifdef MINI2440 - /* interleave a touchscreen read if neccessary */ - touchscreen_scan_device(); -#endif /* setup the next conversion and start it*/ ADCCON = (ADCCON & ~(0x7<<3)) | (channel<<3) | 0x01; } diff --git a/firmware/target/arm/s3c2440/crt0.S b/firmware/target/arm/s3c2440/crt0.S index e103f4f49f..7f4cd2aa00 100644 --- a/firmware/target/arm/s3c2440/crt0.S +++ b/firmware/target/arm/s3c2440/crt0.S @@ -133,38 +133,6 @@ #define VAL_MRSRB7 0x00000030 #define VAL_GPACON 0x00FFFFFF -/****************************************************************************/ -#elif defined (MINI2440) - -/* For Mini2440 board or compatible */ -/* Clock and Power Management setup values */ -/* NB: clock settings must match values in s3c2440/system-target.h */ -#define VAL_CLKDIV 0x5 /* HCLK = FCLK/4, PCLK = HCLK/2 */ -#define VAL_UPLLCON 0x00038022 /* UCLK = 48 MHz */ -#define VAL_MPLLCON 0x000C3041 /* FCLK = 406 MHz */ - - -/* Memory Controller setup */ -#define VAL_BWSCON 0x22111112 -#define VAL_BANKCON0 0x00002F50 -#define VAL_BANKCON1 0x00000700 -#define VAL_BANKCON2 0x00000700 -#define VAL_BANKCON3 0x00000700 -#define VAL_BANKCON4 0x00000700 -#define VAL_BANKCON5 0x0007FFFC -#define VAL_BANKCON6 0x00018009 -#define VAL_BANKCON7 0x00018009 - -#define VAL_REFRESH 0x008E04EB -#define VAL_BANKSIZE 0x000000B2 -#define VAL_MRSRB6 0x00000030 -#define VAL_MRSRB7 0x00000030 - -#define VAL_GPACON 0x00FFFFFF -#define VAL_GPFCON 0x000055AA -#define VAL_GPGCON 0xAA2A0128 -#define VAL_GPGDAT 0x0000 - #else #error Unknown target #endif diff --git a/firmware/target/arm/s3c2440/debug-s3c2440.c b/firmware/target/arm/s3c2440/debug-s3c2440.c index de06a43bb9..92d78767eb 100644 --- a/firmware/target/arm/s3c2440/debug-s3c2440.c +++ b/firmware/target/arm/s3c2440/debug-s3c2440.c @@ -31,8 +31,6 @@ #ifdef GIGABEAT_F #define DEBUG_CANCEL BUTTON_POWER -#elif defined(MINI2440) -#define DEBUG_CANCEL BUTTON_MENU #endif bool dbg_hw_info(void) diff --git a/firmware/target/arm/s3c2440/dma-target.h b/firmware/target/arm/s3c2440/dma-target.h index 350a4a2d23..8be19640f5 100644 --- a/firmware/target/arm/s3c2440/dma-target.h +++ b/firmware/target/arm/s3c2440/dma-target.h @@ -29,9 +29,6 @@ #ifdef GIGABEAT_F #define DMA_CHAN_ATA 0 #define DMA_CHAN_AUDIO_OUT 2 -#elif defined(MINI2440) -#define DMA_CHAN_SD 0 -#define DMA_CHAN_AUDIO_OUT 2 #else #error Unsupported target #endif diff --git a/firmware/target/arm/s3c2440/mini2440/adc-target.h b/firmware/target/arm/s3c2440/mini2440/adc-target.h deleted file mode 100644 index 5abf0d06c5..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/adc-target.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _ADC_TARGET_H_ -#define _ADC_TARGET_H_ - -/* Channel 0 is connected to an on board pot for testing - Channels 0-3 are available via expansion connector CON4 - Channels 4-7 are routed to LCD connector for touchscreen operation if - supported by display panel. -*/ -#define NUM_ADC_CHANNELS 4 - -#define ADC_ONBOARD 0 -#define ADC_SPARE_1 1 -#define ADC_SPARE_2 2 -#define ADC_SPARE_3 3 - -#define ADC_READ_ERROR 0xFFFF - -#endif diff --git a/firmware/target/arm/s3c2440/mini2440/backlight-mini2440.c b/firmware/target/arm/s3c2440/mini2440/backlight-mini2440.c deleted file mode 100644 index c4b93da9bc..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/backlight-mini2440.c +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "cpu.h" -#include "system.h" -#include "backlight-target.h" -#include "backlight.h" -#include "lcd.h" -#include "power.h" - - -/* Dummy value at index 0, 1-12 used. */ -static const unsigned char log_brightness[13] = - {0,0,1,2,3,5,7,10,15,22,31,44,63}; - - -static enum backlight_states -{ - BACKLIGHT_CONTROL_IDLE, - BACKLIGHT_CONTROL_OFF, - BACKLIGHT_CONTROL_ON, - BACKLIGHT_CONTROL_SET, - BACKLIGHT_CONTROL_FADE -} backlight_control; - -static unsigned char _backlight_brightness; -static unsigned char backlight_target; - - -/* Assumes that the backlight has been initialized */ -void backlight_hw_brightness(int brightness) -{ - if (brightness < 0) - brightness = 0; - else if(brightness > MAX_BRIGHTNESS_SETTING) - brightness = MAX_BRIGHTNESS_SETTING; - - /* stop the interrupt from messing us up */ - backlight_control = BACKLIGHT_CONTROL_IDLE; - _backlight_brightness = log_brightness[brightness]; - backlight_control = BACKLIGHT_CONTROL_SET; -} - -static void _backlight_set_state (unsigned int level) -{ - if (level == 0) - GPGDAT &= ~GPIO_LCD_PWR; - else - GPGDAT |= GPIO_LCD_PWR; -} - -/* led_control_service runs in interrupt context - be brief! - * This service is called once per interrupt timer tick - 100 times a second. - * - * There should be at most only one i2c operation per call - if more are need - * the calls should be spread across calls. - * - * Putting all led servicing in one thread means that we wont step on any - * i2c operations - they are all serialized here in the ISR tick. It also - * insures that we get called at equal timing for good visual effect. - */ -#ifndef BOOTLOADER -static void led_control_service(void) -{ - switch (backlight_control) - { - case BACKLIGHT_CONTROL_IDLE: - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - case BACKLIGHT_CONTROL_OFF: - backlight_hw_brightness(0); - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - case BACKLIGHT_CONTROL_ON: - backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - case BACKLIGHT_CONTROL_SET: - /* TODO: This is probably wrong since it sets a fixed value. - It was a fixed value of 255 before, but that was even more wrong - since it accessed the log_brightness buffer out of bounds */ - backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - case BACKLIGHT_CONTROL_FADE: - backlight_hw_brightness(0); - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - default: - backlight_control = BACKLIGHT_CONTROL_IDLE; - break; - } -} -#endif /* BOOTLOADER */ - -static void __backlight_dim(bool dim_now) -{ - /* dont let the interrupt tick happen */ - backlight_control = BACKLIGHT_CONTROL_IDLE; - backlight_target = dim_now ? 0 : _backlight_brightness; - if(backlight_target==0 && _backlight_brightness==0) - { - if(dim_now == false) - backlight_control = BACKLIGHT_CONTROL_ON; - else - backlight_control = BACKLIGHT_CONTROL_OFF; - } - else - backlight_control = BACKLIGHT_CONTROL_FADE; -} - -void backlight_hw_on(void) -{ -#ifdef HAVE_LCD_ENABLE - lcd_enable(true); /* power on lcd + visible display */ -#endif - __backlight_dim(false); -} - -void backlight_hw_off(void) -{ - __backlight_dim(true); -} - - -bool backlight_hw_init(void) -{ - unsigned char brightness = log_brightness[DEFAULT_BRIGHTNESS_SETTING]; - _backlight_brightness = brightness; - - backlight_control = BACKLIGHT_CONTROL_ON; - - _backlight_set_state (1); - S3C2440_GPIO_CONFIG (GPGCON, 4, GPIO_OUTPUT); - -#ifndef BOOTLOADER - /* put the led control on the tick list */ - tick_add_task(led_control_service); -#endif - return true; -} diff --git a/firmware/target/arm/s3c2440/mini2440/backlight-target.h b/firmware/target/arm/s3c2440/mini2440/backlight-target.h deleted file mode 100644 index ceb6824841..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/backlight-target.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Linus Nielsen Feltzing - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H - -#define GPIO_LCD_PWR (1 << 4) /* GPIO.G4 */ - -bool backlight_hw_init(void); -void backlight_hw_on(void); -void backlight_hw_off(void); -void backlight_hw_brightness(int brightness); - -#endif diff --git a/firmware/target/arm/s3c2440/mini2440/button-mini2440.c b/firmware/target/arm/s3c2440/mini2440/button-mini2440.c deleted file mode 100644 index 981e2a1280..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/button-mini2440.c +++ /dev/null @@ -1,92 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "cpu.h" -#include "system.h" -#include "button.h" -#include "kernel.h" -#include "touchscreen-target.h" - -void button_init_device(void) -{ - /* Configure port directions and enable internal pullups on button inputs */ - - /* These are the standard 6 buttons on the Mini2440 */ - S3C2440_GPIO_CONFIG (GPGCON, 0, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 3, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 5, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 6, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 7, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 11, GPIO_INPUT); - - S3C2440_GPIO_PULLUP (GPGUP, 0, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 3, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 5, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 6, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 7, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 11, GPIO_PULLUP_ENABLE); - - /* These are additional buttons on my add on keypad */ - S3C2440_GPIO_CONFIG (GPGCON, 9, GPIO_INPUT); - S3C2440_GPIO_CONFIG (GPGCON, 10, GPIO_INPUT); - S3C2440_GPIO_PULLUP (GPGUP, 9, GPIO_PULLUP_ENABLE); - S3C2440_GPIO_PULLUP (GPGUP, 10, GPIO_PULLUP_ENABLE); - - /* init touchscreen */ - touchscreen_init_device(); -} - -inline bool button_hold(void) -{ - return 0; -} - -int button_read_device(int* data) -{ - int btn = BUTTON_NONE; - static int old_data = 0; - - *data = old_data; - - /* Read the buttons - active low */ - btn = (GPGDAT & BUTTON_MAIN) ^ BUTTON_MAIN; - - /* read touchscreen */ - btn |= touchscreen_read_device(data, &old_data); - - return btn; -} - -void touchpad_set_sensitivity(int level) -{ - (void)level; - /* No touchpad */ -} - -#ifdef HAVE_HEADPHONE_DETECTION -bool headphones_inserted(void) -{ - /* No detect */ - return false; -} -#endif /* HAVE_HEADPHONE_DETECTION */ - diff --git a/firmware/target/arm/s3c2440/mini2440/button-target.h b/firmware/target/arm/s3c2440/mini2440/button-target.h deleted file mode 100644 index 685af7270f..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/button-target.h +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -void touchpad_set_sensitivity(int level); - -/* Mini2440 specific button codes */ - -#define BUTTON_ONE 0x0001 -#define BUTTON_TWO 0x0008 -#define BUTTON_THREE 0x0020 -#define BUTTON_FOUR 0x0040 -#define BUTTON_FIVE 0x0080 -#define BUTTON_SIX 0x0800 - -/* Add on buttons */ -#define BUTTON_SEVEN 0x0200 -#define BUTTON_EIGHT 0x0400 - -/* Touch Screen Area Buttons */ -#define BUTTON_TOPLEFT 0x010000 -#define BUTTON_TOPMIDDLE 0x020000 -#define BUTTON_TOPRIGHT 0x040000 -#define BUTTON_MIDLEFT 0x080000 -#define BUTTON_CENTER 0x100000 -#define BUTTON_MIDRIGHT 0x200000 -#define BUTTON_BOTTOMLEFT 0x400000 -#define BUTTON_BOTTOMMIDDLE 0x800000 -#define BUTTON_BOTTOMRIGHT 0x100000 - -#define BUTTON_TOUCH 0x200000 - - -#define BUTTON_MENU BUTTON_ONE -#define BUTTON_UP BUTTON_TWO -#define BUTTON_SELECT BUTTON_THREE -#define BUTTON_DOWN BUTTON_FOUR -#define BUTTON_LEFT BUTTON_FIVE -#define BUTTON_RIGHT BUTTON_SIX - -/* Add on buttons */ -#define BUTTON_A BUTTON_SEVEN -#define BUTTON_POWER BUTTON_EIGHT - -/* TODO: bodge to keep keymap-mini2440 happy */ -#define BUTTON_VOL_DOWN 0x4000 -#define BUTTON_VOL_UP 0x8000 - -#define BUTTON_MAIN (BUTTON_MENU|BUTTON_LEFT|BUTTON_RIGHT | \ - BUTTON_UP |BUTTON_DOWN|BUTTON_SELECT | \ - BUTTON_A |BUTTON_POWER ) - -#define POWEROFF_BUTTON BUTTON_MENU -#define POWEROFF_COUNT 10 - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/s3c2440/mini2440/lcd-target.h b/firmware/target/arm/s3c2440/mini2440/lcd-target.h deleted file mode 100644 index 97643f8163..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/lcd-target.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins, Lyre Project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef LCD_TARGET_H -#define LCD_TARGET_H - -#define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) - -/* Setup for Mini2440, 3.5" TFT LCD Touchscreen */ - -/* Config values for LCDCON1 */ -#define LCD_CLKVAL 4 -#define LCD_MMODE 0 -#define LCD_PNRMODE 3 -#define LCD_BPPMODE 12 -#define LCD_ENVID 1 - -/* Config values for LCDCON2 */ -#define LCD_UPPER_MARGIN 1 -#define LCD_LOWER_MARGIN 4 -#define LCD_VSYNC_LEN 1 - -/* Config values for LCDCON3 */ -#define LCD_RIGHT_MARGIN 0 -#define LCD_LEFT_MARGIN 25 - -/* Config values for LCDCON4 */ -#define LCD_HSYNC_LEN 4 - -#endif /* LCD_TARGET_H */ diff --git a/firmware/target/arm/s3c2440/mini2440/led-mini2440.c b/firmware/target/arm/s3c2440/mini2440/led-mini2440.c deleted file mode 100644 index 606d443184..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/led-mini2440.c +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "cpu.h" -#include "kernel.h" -#include "led-mini2440.h" - -/* LED functions for debug */ - -void led_init (void) -{ - S3C2440_GPIO_CONFIG (GPBCON, 5, GPIO_OUTPUT); - S3C2440_GPIO_CONFIG (GPBCON, 6, GPIO_OUTPUT); - S3C2440_GPIO_CONFIG (GPBCON, 7, GPIO_OUTPUT); - S3C2440_GPIO_CONFIG (GPBCON, 8, GPIO_OUTPUT); - - S3C2440_GPIO_PULLUP (GPBUP, 5, GPIO_PULLUP_DISABLE); - S3C2440_GPIO_PULLUP (GPBUP, 6, GPIO_PULLUP_DISABLE); - S3C2440_GPIO_PULLUP (GPBUP, 7, GPIO_PULLUP_DISABLE); - S3C2440_GPIO_PULLUP (GPBUP, 8, GPIO_PULLUP_DISABLE); -} - -/* Turn on one or more LEDS */ -void set_leds (int led_mask) -{ - GPBDAT &= ~led_mask; -} - -/* Turn off one or more LEDS */ -void clear_leds (int led_mask) -{ - GPBDAT |= led_mask; -} - -/* Alternate flash pattern1 and pattern2 */ -/* Never returns */ -void led_flash (int led_pattern1, int led_pattern2) -{ - while (1) - { - set_leds (led_pattern1); - sleep(HZ/2); - clear_leds (led_pattern1); - - set_leds(led_pattern2); - sleep(HZ/2); - clear_leds (led_pattern2); - } -} diff --git a/firmware/target/arm/s3c2440/mini2440/led-mini2440.h b/firmware/target/arm/s3c2440/mini2440/led-mini2440.h deleted file mode 100644 index 0aaad1c9a4..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/led-mini2440.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _LED_MINI2440_H_ -#define _LED_MINI2440_H_ - -/* LED functions for debug etc */ - -#define LED1 0x0020 /* GPB5 */ -#define LED2 0x0040 /* GPB6 */ -#define LED3 0x0080 /* GPB7 */ -#define LED4 0x0100 /* GPB8 */ - -#define LED_NONE 0x0000 -#define LED_ALL (LED1|LED2|LED3|LED4) - -void led_init (void); - -/* Turn on one or more LEDS */ -void set_leds (int led_mask); - -/* Turn off one or more LEDS */ -void clear_leds (int led_mask); - -/* Alternate flash of pattern1 and pattern2 - never returns */ -void led_flash (int led_pattern1, int led_pattern2); - -#endif /* _LED_MINI2440_H_ */ diff --git a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c deleted file mode 100644 index 999a53e3f9..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c +++ /dev/null @@ -1,261 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006 by Michael Sevakis - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include -#include "config.h" -#include "system.h" -#include "kernel.h" -#include "logf.h" -#include "audio.h" -#include "sound.h" -#include "file.h" -#include "pcm-internal.h" - -/* PCM interrupt routine lockout */ -static struct -{ - int locked; - unsigned long state; -} dma_play_lock = -{ - .locked = 0, - .state = 0, -}; - -#define FIFO_COUNT ((IISFCON >> 6) & 0x3F) - -/* Setup for the DMA controller */ -#define DMA_CONTROL_SETUP ((1<<31) | (1<<29) | (1<<23) | (1<<22) | (1<<20)) - -#ifdef HAVE_UDA1341 -/* for PCLK = 50 MHz, frame size = 32 */ -/* [prescaler, master clock rate] */ -static const unsigned char pcm_freq_parms[HW_NUM_FREQ][2] = -{ - [HW_FREQ_44] = { 2, IISMOD_MASTER_CLOCK_384FS }, - [HW_FREQ_22] = { 8, IISMOD_MASTER_CLOCK_256FS }, - [HW_FREQ_11] = { 17, IISMOD_MASTER_CLOCK_256FS }, -}; -#endif - -/* DMA count has hit zero - no more data */ -/* Get more data from the callback and top off the FIFO */ -void fiq_handler(void) __attribute__((interrupt ("FIQ"))); - -/* Mask the DMA interrupt */ -void pcm_play_lock(void) -{ - if (++dma_play_lock.locked == 1) - bitset32(&INTMSK, DMA2_MASK); -} - -/* Unmask the DMA interrupt if enabled */ -void pcm_play_unlock(void) -{ - if (--dma_play_lock.locked == 0) - bitclr32(&INTMSK, dma_play_lock.state); -} - -void pcm_play_dma_init(void) -{ - /* There seem to be problems when changing the IIS interface configuration - * when a clock is not present. - */ - bitset32(&CLKCON, 1<<17); - -#ifdef HAVE_UDA1341 - /* master, transmit mode, 16 bit samples, BCLK 32fs, PCLK */ - IISMOD = IISMOD_MASTER_CLOCK_PCLK | IISMOD_MASTER_MODE | IISMOD_TRANSMIT_MODE - | IISMOD_16_BIT | IISMOD_MASTER_CLOCK_256FS | IISMOD_BIT_CLOCK_32FS; - - /* TX idle, enable prescaler */ - IISCON |= IISCON_TX_IDLE | IISCON_IIS_PRESCALER_ENABLE; -#else - /* slave, transmit mode, 16 bit samples - MCLK 384fs - use 16.9344Mhz - - BCLK 32fs */ - IISMOD = (1<<9) | (1<<8) | (2<<6) | (1<<3) | (1<<2) | (1<<0); - - /* RX,TX off,on */ - IISCON |= (1<<3) | (1<<2); -#endif - - bitclr32(&CLKCON, 1<<17); - - audiohw_init(); - - /* init GPIO */ -#ifdef GIGABEAT_F -/* GPCCON = (GPCCON & ~(3<<14)) | (1<<14); */ - S3C244_GPIO_CONFIG (GPCCON, 7, GPIO_OUTPUT); - GPCDAT |= (1<<7); -#endif - - /* GPE4=I2SDO, GPE3=I2SDI, GPE2=CDCLK, GPE1=I2SSCLK, GPE0=I2SLRCK */ - GPECON = (GPECON & ~0x3ff) | 0x2aa; - - /* Do not service DMA requests, yet */ - - /* clear any pending int and mask it */ - bitset32(&INTMSK, DMA2_MASK); - SRCPND = DMA2_MASK; - - /* connect to FIQ */ - bitset32(&INTMOD, DMA2_MASK); -} - -void pcm_play_dma_postinit(void) -{ - audiohw_postinit(); -} - -void pcm_dma_apply_settings(void) -{ -#ifdef HAVE_UDA1341 - unsigned int reg_val; - /* set prescaler and master clock rate according to freq */ - reg_val = (pcm_freq_parms [pcm_fsel][0] << 5) | pcm_freq_parms [pcm_fsel][0]; - - IISMOD = (IISMOD & ~IISMOD_MASTER_CLOCK_384FS) | pcm_freq_parms [pcm_fsel][1] ; - IISPSR = reg_val; -#endif - - audiohw_set_frequency(pcm_fsel); -} - -/* Connect the DMA and start filling the FIFO */ -static void play_start_pcm(void) -{ - /* clear pending DMA interrupt */ - SRCPND = DMA2_MASK; - - /* Flush any pending writes */ - commit_dcache_range((char*)DISRC2-0x30000000, (DCON2 & 0xFFFFF) * 2); - - /* unmask DMA interrupt when unlocking */ - dma_play_lock.state = DMA2_MASK; - - /* turn on the request */ - IISCON |= (1<<5); - - /* Activate the channel */ - DMASKTRIG2 = 0x2; - - /* turn off the idle */ - IISCON &= ~(1<<3); - -#ifdef HAVE_UDA1341 - IISMOD = (IISMOD & ~IISMOD_MASTER_CLOCK_384FS) | pcm_freq_parms [pcm_fsel][1] ; - IISPSR = (pcm_freq_parms [pcm_fsel][0] << 5) | pcm_freq_parms [pcm_fsel][0]; -#endif - - /* start the IIS */ - IISCON |= (1<<0); -} - -/* Disconnect the DMA and wait for the FIFO to clear */ -static void play_stop_pcm(void) -{ - /* Mask DMA interrupt */ - bitset32(&INTMSK, DMA2_MASK); - - /* De-Activate the DMA channel */ - DMASKTRIG2 = 0x4; - - /* are we playing? wait for the chunk to finish */ - if (dma_play_lock.state != 0) - { - /* wait for the FIFO to empty and DMA to stop */ - while ((IISCON & (1<<7)) || (DMASKTRIG2 & 0x2)); - } - - /* Keep interrupt masked when unlocking */ - dma_play_lock.state = 0; - - /* turn off the request */ - IISCON &= ~(1<<5); - - /* turn on the idle */ - IISCON |= (1<<3); - - /* stop the IIS */ - IISCON &= ~(1<<0); -} - -void pcm_play_dma_start(const void *addr, size_t size) -{ - /* Enable the IIS clock */ - bitset32(&CLKCON, 1<<17); - - /* stop any DMA in progress - idle IIS */ - play_stop_pcm(); - - /* connect DMA to the FIFO and enable the FIFO */ - IISFCON = (1<<15) | (1<<13); - - /* set DMA dest */ - DIDST2 = (unsigned int)&IISFIFO; - - /* IIS is on the APB bus, INT when TC reaches 0, fixed dest addr */ - DIDSTC2 = 0x03; - - /* set DMA source and options */ - DISRC2 = (unsigned int)addr + 0x30000000; - /* How many transfers to make - we transfer half-word at a time = 2 bytes */ - /* DMA control: CURR_TC int, single service mode, I2SSDO int, HW trig */ - /* no auto-reload, half-word (16bit) */ - DCON2 = DMA_CONTROL_SETUP | (size / 2); - DISRCC2 = 0x00; /* memory is on AHB bus, increment addresses */ - - play_start_pcm(); -} - -/* Promptly stop DMA transfers and stop IIS */ -void pcm_play_dma_stop(void) -{ - play_stop_pcm(); - - /* Disconnect the IIS clock */ - bitclr32(&CLKCON, 1<<17); -} - -void fiq_handler(void) -{ - static const void *start; - static size_t size; - - /* clear any pending interrupt */ - SRCPND = DMA2_MASK; - - /* Buffer empty. Try to get more. */ - if (!pcm_play_dma_complete_callback(PCM_DMAST_OK, &start, &size)) - return; - - /* Flush any pending cache writes */ - commit_dcache_range(start, size); - - /* set the new DMA values */ - DCON2 = DMA_CONTROL_SETUP | (size >> 1); - DISRC2 = (unsigned int)start + 0x30000000; - - /* Re-Activate the channel */ - DMASKTRIG2 = 0x2; - - pcm_play_dma_status_callback(PCM_DMAST_STARTED); -} diff --git a/firmware/target/arm/s3c2440/mini2440/power-mini2440.c b/firmware/target/arm/s3c2440/mini2440/power-mini2440.c deleted file mode 100644 index d4b00751e0..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/power-mini2440.c +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "cpu.h" -#include -#include -#include "kernel.h" -#include "system.h" -#include "power.h" -#include "led-mini2440.h" - -void power_init(void) -{ - /* Nothing to do */ -} - -unsigned int power_input_status(void) -{ - unsigned int status = 0; - - /* Always on*/ - status = POWER_INPUT_MAIN; - return status; -} - -/* Returns true if the unit is charging the batteries. */ -bool charging_state(void) -{ - return false; -} - -void power_off(void) -{ - /* we don't have any power control, user must do it */ - led_flash (LED_NONE, LED_ALL); - while (1); -} diff --git a/firmware/target/arm/s3c2440/mini2440/powermgmt-mini2440.c b/firmware/target/arm/s3c2440/mini2440/powermgmt-mini2440.c deleted file mode 100644 index 2838c7a74a..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/powermgmt-mini2440.c +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Bob Cousins - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "config.h" -#include "system.h" -#include "adc.h" -#include "power.h" -#include "powermgmt.h" - -/* The following constants are dummy values since there is no battery */ -unsigned short battery_level_disksafe = 3450; - -unsigned short battery_level_shutoff = 3400; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ - /* Typical Li Ion 830mAH */ - 3480, 3550, 3590, 3610, 3630, 3650, 3700, 3760, 3800, 3910, 3990 -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = -{ - /* Typical Li Ion 830mAH */ - 3480, 3550, 3590, 3610, 3630, 3650, 3700, 3760, 3800, 3910, 3990 -}; - - -/* Returns battery voltage from ADC [millivolts] */ -/* full-scale (2^10) in millivolt */ -int _battery_voltage(void) -{ - /* Since we have no battery, return a fully charged value */ - return 4000 * 1024 / 1000; -} - -#ifdef HAVE_BATTERY_SWITCH -unsigned int input_millivolts(void) -{ - unsigned int batt_millivolts = battery_voltage(); - - /* No battery, return nominal value */ - return batt_millivolts; -} -#endif /* HAVE_BATTERY_SWITCH */ - diff --git a/firmware/target/arm/s3c2440/mini2440/touchscreen-mini2440.c b/firmware/target/arm/s3c2440/mini2440/touchscreen-mini2440.c deleted file mode 100644 index 4ab4a46351..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/touchscreen-mini2440.c +++ /dev/null @@ -1,189 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___void - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Rob Purchase - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "touchscreen-target.h" -#include "adc-target.h" -#include "system.h" -#include "stdlib.h" -#include "button.h" -#include "tick.h" -#include "touchscreen.h" - -#define NO_OF_TOUCH_DATA 5 - -struct touch_calibration_point { - short px_x; /* known pixel value */ - short px_y; - short val_x; /* touchscreen value at the known pixel */ - short val_y; -}; - -static struct touch_calibration_point topleft, bottomright; - -static bool touch_available = false; - -static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA]; - -/* comparator for qsort */ -static int short_cmp(const void *a, const void *b) -{ - return *(short*)a - *(short*)b; -} - -static int touch_to_pixels(short val_x, short val_y) -{ - short x,y; - - x=val_x; - y=val_y; - - x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x) - / (bottomright.val_x - topleft.val_x) + topleft.px_x; - - y = (y-topleft.val_y)*(bottomright.px_y - topleft.px_y) - / (bottomright.val_y - topleft.val_y) + topleft.px_y; - - if (x < 0) - x = 0; - else if (x>=LCD_WIDTH) - x=LCD_WIDTH-1; - - if (y < 0) - y = 0; - else if (y>=LCD_HEIGHT) - y=LCD_HEIGHT-1; - - return (x<<16)|y; -} - -void touchscreen_init_device() -{ - /* set touchscreen adc controller into wait for interrupt mode */ - ADCTSC = 0xd3; /* Wfait,XP-PU,XP_DIS,XM_DIS,YP_dis,YM_end */ - - /* Arbitrary touchscreen calibration */ - topleft.px_x = 0; - topleft.px_y = 0; - topleft.val_x = 105; - topleft.val_y = 925; - - bottomright.px_x = LCD_WIDTH; - bottomright.px_y = LCD_HEIGHT; - bottomright.val_x = 890; - bottomright.val_y = 105; - - touch_available = false; -} - -void touchscreen_scan_device() -{ - static long last_touch_read = 0; - static int touch_data_index = 0; - - int saveADCDLY; - - /* check touch state */ - if(ADCDAT1 & (1<<15)) - { - return; - } - - if (TIME_AFTER(current_tick, last_touch_read + 1)) - { - /* resets the index if the last touch could not be read 5 times */ - touch_data_index = 0; - } - - /* read touch data */ - saveADCDLY = ADCDLY; - ADCDLY = 40000; /*delay ~0.8ms (1/50M)*4000 */ - ADCTSC = (1<<3)|(1<<2); /* pullup disable, seq x,y pos measure */ - /* start adc */ - ADCCON|= 0x1; - /* wait for start and end */ - while(ADCCON & 0x1); - while(!(ADCCON & 0x8000)); - - x[touch_data_index] = ADCDAT0&0x3ff; - y[touch_data_index] = ADCDAT1&0x3ff; - - ADCTSC = 0xd3; /* back to interrupt mode */ - ADCDLY = saveADCDLY; - - touch_data_index++; - - if (touch_data_index > NO_OF_TOUCH_DATA - 1) - { - /* coordinates 5 times read */ - touch_available = true; - touch_data_index = 0; - } - last_touch_read = current_tick; -} - -int touchscreen_read_device(int *data, int *old_data) -{ - int btn = BUTTON_NONE; - static bool touch_hold = false; - static long last_touch = 0; - - if (touch_available || touch_hold) - { - short x_touch, y_touch; - static short last_x = 0, last_y = 0; - - if (touch_hold) - { - /* get rid of very fast unintended double touches */ - x_touch = last_x; - y_touch = last_y; - } - else - { - /* sort the 5 data taken and use the median value */ - qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); - qsort(y, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); - - x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2]; - y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2]; - - last_touch = current_tick; - - touch_hold = true; - touch_available = false; - } - - *old_data = *data = touch_to_pixels(x_touch, y_touch); - - btn |= touchscreen_to_pixels((*data&0xffff0000) >> 16, - (*data&0x0000ffff), - data); - } - - if (TIME_AFTER(current_tick, last_touch + 10)) - { - /* put the touchscreen back into interrupt mode */ - touch_hold = false; - } - - return btn; -} diff --git a/firmware/target/arm/s3c2440/mini2440/touchscreen-target.h b/firmware/target/arm/s3c2440/mini2440/touchscreen-target.h deleted file mode 100644 index 1019a98330..0000000000 --- a/firmware/target/arm/s3c2440/mini2440/touchscreen-target.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2009 by Dominik Wenger - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _TOUCHSCREEN_TARGET_H -#define _TOUCHSCREEN_TARGET_H - -/* try to get a touchscreen reading from adc */ -void touchscreen_scan_device(void); -/* init touchscreen driver */ -void touchscreen_init_device(void); - -int touchscreen_read_device(int *data, int *old_data); - -#endif - diff --git a/firmware/target/arm/s3c2440/system-s3c2440.c b/firmware/target/arm/s3c2440/system-s3c2440.c index 569dcabdbe..b9c6dd5879 100644 --- a/firmware/target/arm/s3c2440/system-s3c2440.c +++ b/firmware/target/arm/s3c2440/system-s3c2440.c @@ -191,8 +191,6 @@ void system_init(void) CLKCON &= ~0xFF1ED0; CLKSLOW |= 0x80; -#elif defined(MINI2440) - /* TODO: anything? */ #else #error Unknown target #endif diff --git a/firmware/target/arm/s3c2440/system-target.h b/firmware/target/arm/s3c2440/system-target.h index 33662cd9e5..e69998f4b9 100644 --- a/firmware/target/arm/s3c2440/system-target.h +++ b/firmware/target/arm/s3c2440/system-target.h @@ -48,20 +48,6 @@ #define UNCACHED_ADDR(a) ((typeof(a))((unsigned int)(a) | UNCACHED_BASE_ADDR )) #endif /* BOOTLOADER */ -#elif defined(MINI2440) - - /* Uses 1:4:8 */ - #define FCLK 406000000 - #define HCLK (FCLK/4) /* = 101,250,000 */ - #define PCLK (HCLK/2) /* = 50,625,000 */ - - #define CPUFREQ_DEFAULT FCLK /* 406 MHz */ - #define CPUFREQ_NORMAL (FCLK/4)/* 101.25 MHz */ - #define CPUFREQ_MAX FCLK /* 406 MHz */ - - #define UNCACHED_BASE_ADDR 0x30000000 - #define UNCACHED_ADDR(a) ((typeof(a))((unsigned int)(a) | UNCACHED_BASE_ADDR )) - #else #error Unknown target #endif diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h index 8de6ce93cd..5a404736b4 100644 --- a/firmware/target/hosted/sdl/sim-ui-defines.h +++ b/firmware/target/hosted/sdl/sim-ui-defines.h @@ -346,13 +346,6 @@ #define UI_LCD_POSX 124 /* x position of lcd */ #define UI_LCD_POSY 42 /* y position of lcd */ -#elif defined(MINI2440) -#define UI_TITLE "Mini2440" -#define UI_WIDTH 441 /* width of GUI window */ -#define UI_HEIGHT 436 /* height of GUI window */ -#define UI_LCD_POSX 148 /* x position of lcd */ -#define UI_LCD_POSY 50 /* y position of lcd */ - #elif defined(PBELL_VIBE500) #define UI_TITLE "Packard Bell Vibe 500" #define UI_WIDTH 287 /* width of GUI window */ diff --git a/manual/rockbox_interface/images/mini2440-front.svg b/manual/rockbox_interface/images/mini2440-front.svg deleted file mode 100644 index 12aa85ab4c..0000000000 --- a/manual/rockbox_interface/images/mini2440-front.svg +++ /dev/null @@ -1,1466 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/builds.pm b/tools/builds.pm index 02a4b6fea8..157720a0d8 100644 --- a/tools/builds.pm +++ b/tools/builds.pm @@ -199,14 +199,6 @@ $releasenotes="/wiki/ReleaseNotes400"; name => 'iriver H320/340', status => 3, }, - 'lyreproto1' => { - name => 'Lyre Prototype 1', - status => 1, - }, - 'mini2440' => { - name => 'Mini 2440', - status => 1, - }, 'mrobe100' => { name => 'Olympus M-Robe 100', status => 3, diff --git a/tools/configure b/tools/configure index 1e44235cb3..b1260d88c2 100755 --- a/tools/configure +++ b/tools/configure @@ -1697,41 +1697,41 @@ cat < Date: Wed, 4 Feb 2026 15:06:58 +0000 Subject: [PATCH 33/75] make: allow building flat binary plugins on USE_ELF targets (attempt 2) Looks like I forgot to test the hosted builds and for some reason thought that make would expand objcopy recursively... Change-Id: I61264eadcb1235660566f6a9f19f8718ebe14583 --- apps/plugins/chessbox/chessbox.make | 2 +- apps/plugins/goban/goban.make | 2 +- apps/plugins/imageviewer/imageviewer.make | 2 +- apps/plugins/lua/lua.make | 2 +- apps/plugins/pictureflow/pictureflow.make | 2 +- apps/plugins/plugins.make | 2 +- apps/plugins/puzzles/puzzles.make | 4 ++-- apps/plugins/rockboy/rockboy.make | 2 +- apps/plugins/sdl/sdl.make | 4 ++-- apps/plugins/zxbox/zxbox.make | 2 +- lib/rbcodec/codecs/codecs.make | 2 +- tools/configure | 2 ++ tools/functions.make | 5 +++++ 13 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/plugins/chessbox/chessbox.make b/apps/plugins/chessbox/chessbox.make index 87f0a6ecc0..77a038febc 100644 --- a/apps/plugins/chessbox/chessbox.make +++ b/apps/plugins/chessbox/chessbox.make @@ -39,7 +39,7 @@ $(CHESSBOX_OBJDIR)/chessbox.ovl: $(CHESSBOX_OBJ) $(CHESSBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CHESSBOX_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling chessbox with extra flags $(CHESSBOX_OBJDIR)/%.o: $(CHESSBOX_SRCDIR)/%.c $(CHESSBOX_SRCDIR)/chessbox.make diff --git a/apps/plugins/goban/goban.make b/apps/plugins/goban/goban.make index 2201dc60f4..ae221e8840 100644 --- a/apps/plugins/goban/goban.make +++ b/apps/plugins/goban/goban.make @@ -36,4 +36,4 @@ $(GOBAN_BUILDDIR)/goban.ovl: $(GOBAN_OBJ) $(GOBAN_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(GOBAN_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) diff --git a/apps/plugins/imageviewer/imageviewer.make b/apps/plugins/imageviewer/imageviewer.make index 23f9813357..25701fc6d2 100644 --- a/apps/plugins/imageviewer/imageviewer.make +++ b/apps/plugins/imageviewer/imageviewer.make @@ -40,7 +40,7 @@ $(IMGVBUILDDIR)/%.ovl: $(IMGDEC_OUTLDS) $(filter-out $(PLUGIN_CRT0),$(filter %.o, $^)) \ $(filter %.a, $+) \ -lgcc $(IMGDEC_OVLFLAGS) - $(SILENT)$(call objcopy,$(IMGVBUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(IMGVBUILDDIR)/$*.elf,$@) # rule to create reference map for image decoder $(IMGVBUILDDIR)/%.refmap: $(APPSDIR)/plugin.h $(IMGVSRCDIR)/imageviewer.h $(PLUGINLINK_LDS) $(PLUGIN_LIBS) diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make index a5d1813a8b..ec8a7e8b38 100644 --- a/apps/plugins/lua/lua.make +++ b/apps/plugins/lua/lua.make @@ -73,7 +73,7 @@ $(LUA_BUILDDIR)/lua.ovl: $(LUA_OBJ) $(TLSFLIB) $(LUA_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(LUA_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) $(LUA_BUILDDIR): $(call PRINTS,MKDIR $@)mkdir -p $(LUA_BUILDDIR)/ diff --git a/apps/plugins/pictureflow/pictureflow.make b/apps/plugins/pictureflow/pictureflow.make index e13ba61a72..7436af2433 100644 --- a/apps/plugins/pictureflow/pictureflow.make +++ b/apps/plugins/pictureflow/pictureflow.make @@ -37,7 +37,7 @@ $(PICTUREFLOW_OBJDIR)/pictureflow.ovl: $(PICTUREFLOW_OBJ) $(PICTUREFLOW_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PICTUREFLOW_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling pictureflow with extra flags $(PICTUREFLOW_OBJDIR)/%.o: $(PICTUREFLOW_SRCDIR)/%.c $(PICTUREFLOW_SRCDIR)/pictureflow.make diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make index 2babb329a5..8620d3f9c0 100644 --- a/apps/plugins/plugins.make +++ b/apps/plugins/plugins.make @@ -169,7 +169,7 @@ $(BUILDDIR)/%.rock: $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(PLUGINLDFLAGS) - $(SILENT)$(call objcopy,$(BUILDDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(BUILDDIR)/$*.elf,$@) $(BUILDDIR)/apps/plugins/%.lua: $(ROOTDIR)/apps/plugins/%.lua $(call PRINTS,CP $(subst $(ROOTDIR)/,,$<))cp $< $(BUILDDIR)/apps/plugins/ diff --git a/apps/plugins/puzzles/puzzles.make b/apps/plugins/puzzles/puzzles.make index 91e84c50da..4c3322d32e 100644 --- a/apps/plugins/puzzles/puzzles.make +++ b/apps/plugins/puzzles/puzzles.make @@ -49,14 +49,14 @@ $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/%.o $(PUZZLES_OBJDIR)/help/% $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_OBJDIR)/sgt-%.rock: $(PUZZLES_OBJDIR)/src/unfinished/%.o $(PUZZLES_OBJDIR)/help/%.o $(PUZZLES_SHARED_OBJ) $(TLSFLIB) $(call PRINTS,LD $(@F))$(CC) $(PLUGINFLAGS) -o $(PUZZLES_OBJDIR)/$*.elf \ $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(filter-out -Wl%.map, $(PLUGINLDFLAGS)) -Wl,$(LDMAP_OPT),$(PUZZLES_OBJDIR)/src/$*.map - $(SILENT)$(call objcopy,$(PUZZLES_OBJDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(PUZZLES_OBJDIR)/$*.elf,$@) $(PUZZLES_SRCDIR)/rbcompat.h: $(APPSDIR)/plugin.h \ $(APPSDIR)/plugins/lib/pluginlib_exit.h \ diff --git a/apps/plugins/rockboy/rockboy.make b/apps/plugins/rockboy/rockboy.make index 8be44ef9c5..8725604933 100644 --- a/apps/plugins/rockboy/rockboy.make +++ b/apps/plugins/rockboy/rockboy.make @@ -37,7 +37,7 @@ $(ROCKBOY_OBJDIR)/rockboy.ovl: $(ROCKBOY_OBJ) $(ROCKBOY_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ROCKBOY_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special rule to build with devkitarm gcc ifeq ($(APP_TYPE),ctru-app) diff --git a/apps/plugins/sdl/sdl.make b/apps/plugins/sdl/sdl.make index 9d666bd732..7234656268 100644 --- a/apps/plugins/sdl/sdl.make +++ b/apps/plugins/sdl/sdl.make @@ -95,7 +95,7 @@ $(SDL_OBJDIR)/wolf3d.ovl: $(SDL_OBJ) $(WOLF3D_OBJ) $(TLSFLIB) $(WOLF3D_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(WOLF3D_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # Quake ### @@ -113,7 +113,7 @@ $(SDL_OBJDIR)/quake.ovl: $(SDL_OBJ) $(QUAKE_OBJ) $(TLSFLIB) $(QUAKE_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc -T$(QUAKE_OUTLDS) $(SDL_OVLFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) ### diff --git a/apps/plugins/zxbox/zxbox.make b/apps/plugins/zxbox/zxbox.make index 4638d5f0a2..1ee64d6fb5 100644 --- a/apps/plugins/zxbox/zxbox.make +++ b/apps/plugins/zxbox/zxbox.make @@ -45,7 +45,7 @@ $(ZXBOX_OBJDIR)/zxbox.ovl: $(ZXBOX_OBJ) $(ZXBOX_OUTLDS) $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(ZXBOX_LDFLAGS) - $(call PRINTS,LD $(@F))$(call objcopy,$(basename $@).elf,$@) + $(call PRINTS,LD $(@F))$(call objcopy_plugin,$(basename $@).elf,$@) # special pattern rule for compiling zxbox with extra flags $(ZXBOX_OBJDIR)/%.o: $(ZXBOX_SRCDIR)/%.c $(ZXBOX_SRCDIR)/zxbox.make diff --git a/lib/rbcodec/codecs/codecs.make b/lib/rbcodec/codecs/codecs.make index 6d790f5d9a..6f20a8c101 100644 --- a/lib/rbcodec/codecs/codecs.make +++ b/lib/rbcodec/codecs/codecs.make @@ -245,4 +245,4 @@ $(CODECDIR)/%.codec: $(CODECDIR)/%.o $(filter %.o, $^) \ $(filter %.a, $+) \ -lgcc $(CODECLDFLAGS) - $(SILENT)$(call objcopy,$(CODECDIR)/$*.elf,$@) + $(SILENT)$(call objcopy_plugin,$(CODECDIR)/$*.elf,$@) diff --git a/tools/configure b/tools/configure index b1260d88c2..09178d0426 100755 --- a/tools/configure +++ b/tools/configure @@ -1755,6 +1755,7 @@ fi x1000tools="$genericbitmaptools scramble mkspl-x1000 uclpack" # default to not generating ELF files USE_ELF="no" + PLUGIN_USE_ELF="no" # ---- For each target ---- # @@ -4964,6 +4965,7 @@ export TTS_ENGINE=${TTS_ENGINE} export ENC_OPTS=${ENC_OPTS} export ENCODER=${ENCODER} export USE_ELF=${USE_ELF} +export PLUGIN_USE_ELF=${PLUGIN_USE_ELF} export RBDIR=${rbdir} export ROCKBOX_SHARE_PATH=${sharedir} export ROCKBOX_BINARY_PATH=${bindir} diff --git a/tools/functions.make b/tools/functions.make index 1c16e1415f..ccb23102fc 100644 --- a/tools/functions.make +++ b/tools/functions.make @@ -38,15 +38,20 @@ a2lnk = $(patsubst lib%.a,-l%,$(notdir $(1))) # handles the $(1) == $(2) case too ifndef APP_TYPE objcopy = $(OC) $(if $(filter yes, $(USE_ELF)), -S -x, -O binary) $(1) $(2) # objcopy native +objcopy_plugin = $(OC) $(if $(filter yes, $(PLUGIN_USE_ELF)), -S -x, -O binary) $(1) $(2) else ifneq (,$(findstring sdl-sim,$(APP_TYPE))) objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy simulator +objcopy_plugin = $(objcopy) else ifneq (,$(findstring ctru,$(MODELNAME))) # 3dsxtool requires symbols objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) +objcopy_plugin = $(objcopy) else ifdef DEBUG objcopy = cp $(1) $(1).tmp;mv -f $(1).tmp $(2) # objcopy hosted (DEBUG) + objcopy_plugin = $(objcopy) else objcopy = $(OC) -S -x $(1) $(2) # objcopy hosted (!DEBUG) + objcopy_plugin = $(objcopy) endif endif From 1a2235fb18a12d140de785be9a278a21bcf34ac5 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 4 Feb 2026 23:28:57 -0500 Subject: [PATCH 34/75] manual: Document HifiWalker H2 v2.3 as an erosqnative hw4 variant Change-Id: I685a5c71b074f1942e1d345a2fe7d73f97ccfe76 --- manual/getting_started/hibyos_nativeinstall.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/getting_started/hibyos_nativeinstall.tex b/manual/getting_started/hibyos_nativeinstall.tex index d9286ead64..197733c1dc 100644 --- a/manual/getting_started/hibyos_nativeinstall.tex +++ b/manual/getting_started/hibyos_nativeinstall.tex @@ -59,7 +59,7 @@ may not be the most up to date, please see the wiki page at \hfill{} \begin{itemize} \item Aigo Eros Q V2.2 - \item Hifiwalker H2 V1.9 - V2.2 + \item Hifiwalker H2 V1.9 - V2.3 \item Surfans F20 V3.4 \end{itemize} These players use \fname{erosqnative-hw4-erosq\_2024.upt} as the update file. From 7b91b81e4969379db8ff9ee346f12a1ef81bbe4d Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Wed, 4 Feb 2026 16:51:54 +0000 Subject: [PATCH 35/75] stm32h7: define correct DRAM origin for plugins Change-Id: I7fab9da0e99f328ce602607057f52620812476a8 --- apps/plugins/plugin.lds | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index f55f6fee6f..6fbc834a86 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -196,6 +196,12 @@ OUTPUT_FORMAT(elf32-littlemips) #define IRAM DRAM #define IRAMSIZE 0 +#elif CONFIG_CPU == STM32H743 +#include "cpu.h" +#define DRAMORIG STM32_SDRAM1_BASE +#define IRAM DRAM +#define IRAMSIZE 0 + #else #define DRAMORIG 0x09000000 #endif From bce2c4e069a27b94ce6ae838d53e2c2d83aaf3b9 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 5 Feb 2026 10:04:27 +0000 Subject: [PATCH 36/75] Convert users of SHAREDDATA_ATTR to SHAREDBSS_ATTR The handful of uses are only doing zero initialization so don't need to go in the data section, they can go in bss instead. Change-Id: I7108ac60867aa20b4429ac0747d00109563bb3bf --- apps/plugins/fft/fft.c | 2 +- apps/voice_thread.c | 2 +- firmware/backlight.c | 2 +- firmware/kernel/tick.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c index deb5a115bc..fb719ab9aa 100644 --- a/apps/plugins/fft/fft.c +++ b/apps/plugins/fft/fft.c @@ -799,7 +799,7 @@ static inline bool fft_get_fft(void) #if NUM_CORES > 1 /* use a worker thread if there is another processor core */ -static volatile bool fft_thread_run SHAREDDATA_ATTR = false; +static volatile bool fft_thread_run SHAREDBSS_ATTR; static unsigned long fft_thread = 0; static long fft_thread_stack[CACHEALIGN_UP(DEFAULT_STACK_SIZE*4/sizeof(long))] diff --git a/apps/voice_thread.c b/apps/voice_thread.c index 0f0d89c24e..b31bc5bc76 100644 --- a/apps/voice_thread.c +++ b/apps/voice_thread.c @@ -97,7 +97,7 @@ static const char voice_thread_name[] = "voice"; /* Voice thread synchronization objects */ static struct event_queue voice_queue SHAREDBSS_ATTR; static struct queue_sender_list voice_queue_sender_list SHAREDBSS_ATTR; -static int quiet_counter SHAREDDATA_ATTR = 0; +static int quiet_counter SHAREDBSS_ATTR; static bool voice_playing = false; #define VOICE_PCM_FRAME_COUNT ((PLAY_SAMPR_MAX*VOICE_FRAME_COUNT + \ diff --git a/firmware/backlight.c b/firmware/backlight.c index e28793253b..a00483c070 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -199,7 +199,7 @@ static int lcd_sleep_timeout = 10*HZ; #define lcd_sleep_timeout LCD_SLEEP_TIMEOUT #endif -static int lcd_sleep_timer SHAREDDATA_ATTR = 0; +static int lcd_sleep_timer SHAREDBSS_ATTR; static void backlight_lcd_sleep_countdown(bool start) { diff --git a/firmware/kernel/tick.c b/firmware/kernel/tick.c index c524560687..6fe2bf4305 100644 --- a/firmware/kernel/tick.c +++ b/firmware/kernel/tick.c @@ -34,7 +34,7 @@ void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void); #if !defined(CPU_PP) || !defined(BOOTLOADER) || \ defined(HAVE_BOOTLOADER_USB_MODE) -volatile long current_tick SHAREDDATA_ATTR = 0; +volatile long current_tick SHAREDBSS_ATTR; #endif /* - Timer initialization and interrupt handler is defined at From 92b0bf7a273b9d2b4126b8c10b358a621bab9e2f Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 5 Feb 2026 12:01:21 +0000 Subject: [PATCH 37/75] Clean up .ncdata/ncbss hackery in plugin linker script The mess here can be reduced by paying careful attention to how the linker allocates LMAs/VMAs within MEMORY regions. Changing the way .ncdata and .ncbss are defined so that they reserve the LMA/VMA ranges they use in PLUGIN_RAM removes the need to explicitly set the VMAs of other sections, cutting down on the number of ifdefs needed and making the script a bit simpler. Change-Id: I316fc6e8dedd621537261d52c1ec7c20ec09438a --- apps/plugins/plugin.lds | 72 +++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index 6fbc834a86..fbba450b2b 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -281,25 +281,18 @@ SECTIONS } > PLUGIN_RAM #if NOCACHE_BASE != 0 - .ncdata . + NOCACHE_BASE : + /* + * Allocate .ncdata based on the following constraints: + * + * 1. the LMA must be allocated at the next free LMA in + * PLUGIN_RAM and aligned to a cacheline boundary. + * 2. the VMA - LMA offset must equal NOCACHE_BASE. + */ + .ncdata ALIGN(. + NOCACHE_BASE, CACHEALIGN_SIZE) : ALIGN(CACHEALIGN_SIZE) { - . = ALIGN(CACHEALIGN_SIZE); *(.ncdata*) . = ALIGN(CACHEALIGN_SIZE); -/* EABI currently needs these defined here, otherwise .iram and .bss can - sometimes have an incorrect load address, breaking codecs and plugins. */ - bssaddr = . - NOCACHE_BASE; -#if defined(IRAMSIZE) && IRAMSIZE != 0 - iramcopy = . - NOCACHE_BASE; -#endif } AT> PLUGIN_RAM -/* This definition is used when NOCACHE_BASE is 0. The address offset bug only - seems to occur when the empty .ncdata is present. */ -#else - bssaddr = .; -#if defined(IRAMSIZE) && IRAMSIZE != 0 - iramcopy = .; -#endif #endif /DISCARD/ : @@ -311,7 +304,7 @@ SECTIONS #endif } - .bss bssaddr (NOLOAD) : + .bss (NOLOAD) : { plugin_bss_start = .; _plugin_bss_start = .; @@ -324,29 +317,47 @@ SECTIONS } > PLUGIN_RAM #if NOCACHE_BASE != 0 - .ncbss . + NOCACHE_BASE (NOLOAD) : + /* + * .ncbss has the same constraints as the .ncdata section + * above but there is an extra complication: because it is + * a NOLOAD section, unlike .ncdata it cannot consume any + * VMAs or LMAs in PLUGIN_RAM itself. + * + * Because free VMA/LMAs in PLUGIN_RAM are unchanged, any + * subsequent sections will get placed at the end of the + * .bss section, overlapping .ncbss, which we don't want. + * + * One solution is to manually place the next sections to + * account for the size of .ncbss, but a cleaner solution + * is to define a dummy section (.ncbss_vma) allocated at + * the same VMA as .ncbss and equal in size, and placed in + * the PLUGIN_RAM region. This allocates the correct VMA + * range in plugin RAM so that the next section will not + * overlap .ncbss. + */ + .ncbss ALIGN(. + NOCACHE_BASE, CACHEALIGN_SIZE) (NOLOAD) : ALIGN(CACHEALIGN_SIZE) { - . = ALIGN(CACHEALIGN_SIZE); *(.ncbss*) . = ALIGN(CACHEALIGN_SIZE); - /* We won't trust this one any more than with .ncdata */ - pluginendaddr = . - NOCACHE_BASE; } AT> PLUGIN_RAM -#else - pluginendaddr = .; + + .ncbss_vma (NOLOAD) : ALIGN(CACHEALIGN_SIZE) + { + . += SIZEOF(.ncbss); + } > PLUGIN_RAM #endif /* Final end of plugin after IRAM setup. The plugin or codec buffer is considered unused by the in-RAM image at this point once IRAM is copied. */ - .pluginend pluginendaddr : + .pluginend (NOLOAD) : { _plugin_end_addr = .; plugin_end_addr = .; - } + } > PLUGIN_RAM #if defined(IRAMSIZE) && IRAMSIZE != 0 - .iram IRAMORIG : AT (iramcopy) + .iram IRAMORIG : AT(LOADADDR(.bss)) { iramstart = .; *(.icode) @@ -354,6 +365,7 @@ SECTIONS *(.idata) iramend = .; } > PLUGIN_IRAM + iramcopy = LOADADDR(.iram); .ibss (NOLOAD) : { @@ -384,3 +396,13 @@ SECTIONS KEEP(*(.comment)) } } + +#if NOCACHE_BASE != 0 +/* Some asserts to make sure nocache sections appear correctly defined */ +ASSERT(LOADADDR(.ncdata) == ADDR(.ncdata) - NOCACHE_BASE, ".ncdata has incorrect LMA/VMA address"); +ASSERT(LOADADDR(.ncdata) % CACHEALIGN_SIZE == 0, ".ncdata incorrectly aligned"); +ASSERT(LOADADDR(.ncbss) == ADDR(.ncbss) - NOCACHE_BASE, ".ncbss has incorrect LMA/VMA address"); +ASSERT(LOADADDR(.ncbss) % CACHEALIGN_SIZE == 0, ".ncbss incorrectly aligned"); +ASSERT(ADDR(.ncbss_vma) == LOADADDR(.ncbss), ".ncbss_vma has wrong address"); +ASSERT(SIZEOF(.ncbss_vma) == SIZEOF(.ncbss), ".ncbss_vma has wrong size"); +#endif From a6c290e8e514ad28ea0397efa650b6832ce54820 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 5 Feb 2026 20:33:51 +0000 Subject: [PATCH 38/75] jz47xx: fix plugins/codec link address Removing STUBOFFSET in commit 78542df4666 caused DRAMSIZE to be computed incorrectly, not taking into account the 16k offset used for 'IRAM'. As a result plugins & codecs got shifted 16k upwards from their intended load address, making them unable to load. Change-Id: I6c338e04506e12fa2b8a69286a1ed785a2f8042d --- apps/plugins/plugin.lds | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/plugins/plugin.lds b/apps/plugins/plugin.lds index fbba450b2b..9437be1766 100644 --- a/apps/plugins/plugin.lds +++ b/apps/plugins/plugin.lds @@ -77,6 +77,9 @@ OUTPUT_FORMAT(elf32-littlemips) #elif CONFIG_CPU==IMX233 #include "cpu.h" #define DRAMSIZE (DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE - FRAME_SIZE - TTB_SIZE) +#elif CONFIG_CPU == JZ4732 || CONFIG_CPU == JZ4760B +/* fake 'iram' region occupies first 16k */ +#define DRAMSIZE (MEMORYSIZE * 0x100000) - PLUGIN_BUFFER_SIZE - CODEC_SIZE - 0x4000 #elif CONFIG_CPU==X1000 #include "cpu.h" #define DRAMSIZE (X1000_DRAM_SIZE - PLUGIN_BUFFER_SIZE - CODEC_SIZE) From acc9c21a78ccf86197d15e76cc086c17c100abca Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 5 Feb 2026 19:41:56 -0500 Subject: [PATCH 39/75] FS#13773 - Update Latvian Translation (Renalds Belaks) Change-Id: I8bc5a9f9ca5ed652d3751e7a54034f3aa19f1df1 --- apps/lang/latviesu.lang | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/lang/latviesu.lang b/apps/lang/latviesu.lang index ddaf06299b..8434a4a05f 100644 --- a/apps/lang/latviesu.lang +++ b/apps/lang/latviesu.lang @@ -16945,3 +16945,17 @@ general_purpose_led: "Izmantot LED indikatorus" + + id: LANG_ANNOUNCE_STATUS + desc: announnnce_status plugin + user: core + + *: "Announce Status" + + + *: "Paziņot statusu" + + + *: "Paziņot statusu" + + From 6da20a18c3dc81d7ca2ae5462d2ed77b4ddd5617 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Fri, 6 Feb 2026 10:22:25 +0000 Subject: [PATCH 40/75] sdmmc_host: support multiblock transfers Change-Id: I6414028bbafd4ea4ef469f9a387f4bd52ec227e5 --- firmware/drivers/sdmmc_host.c | 40 +++++++++++++++++++++++++++++------ firmware/export/sdmmc_host.h | 3 +++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/firmware/drivers/sdmmc_host.c b/firmware/drivers/sdmmc_host.c index c012731a7e..ad21cfed32 100644 --- a/firmware/drivers/sdmmc_host.c +++ b/firmware/drivers/sdmmc_host.c @@ -677,10 +677,12 @@ static int sdmmc_host_transfer(struct sdmmc_host *host, if (start + count > host->cardinfo.numblocks) goto out; + int max_nr_blocks = MAX(host->config.max_nr_blocks, 1); while (count > 0) { - /* TODO: multiple block transfers */ - int xfer_count = 1; + int xfer_count = count; + if (xfer_count > max_nr_blocks) + xfer_count = max_nr_blocks; /* Set block length for non-HCS cards */ if (!host->is_hcs_card) @@ -692,15 +694,25 @@ static int sdmmc_host_transfer(struct sdmmc_host *host, struct sdmmc_host_command cmd = { .buffer = buf, - .nr_blocks = 1, + .nr_blocks = xfer_count, .block_len = SD_BLOCK_SIZE, .flags = SDMMC_RESP_SHORT | data_dir, }; - if (data_dir == SDMMC_DATA_WRITE) - cmd.command = SD_WRITE_BLOCK; + if (xfer_count > 1) + { + if (data_dir == SDMMC_DATA_WRITE) + cmd.command = SD_WRITE_MULTIPLE_BLOCK; + else + cmd.command = SD_READ_MULTIPLE_BLOCK; + } else - cmd.command = SD_READ_SINGLE_BLOCK; + { + if (data_dir == SDMMC_DATA_WRITE) + cmd.command = SD_WRITE_BLOCK; + else + cmd.command = SD_READ_SINGLE_BLOCK; + } if (host->cardinfo.sd2plus) cmd.argument = start; @@ -711,6 +723,22 @@ static int sdmmc_host_transfer(struct sdmmc_host *host, if (rc) goto out; + /* + * NOTE: some controllers can send CMD12 automatically after + * the end of a transfer, eg. X1000; it might be worth + * supporting that via a feature flag. + */ + if (xfer_count > 1) + { + memset(&cmd, 0, sizeof(cmd)); + cmd.command = SD_STOP_TRANSMISSION; + cmd.flags = SDMMC_RESP_SHORT | SDMMC_RESP_BUSY; + + rc = sdmmc_host_submit_cmd(host, &cmd, NULL); + if (rc) + goto out; + } + buf += xfer_count * SD_BLOCK_SIZE; start += xfer_count; count -= xfer_count; diff --git a/firmware/export/sdmmc_host.h b/firmware/export/sdmmc_host.h index 1d00c94a27..3d6c7fbb0f 100644 --- a/firmware/export/sdmmc_host.h +++ b/firmware/export/sdmmc_host.h @@ -207,6 +207,9 @@ struct sdmmc_host_config uint32_t bus_widths; uint32_t bus_clocks; + /* Max number of blocks in a multiblock transfer */ + int max_nr_blocks; + /* Set to true if the device is removable at runtime */ bool is_removable; }; From 45a61d7e7b112f19a6cb870d09576055d2b6e061 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Fri, 6 Feb 2026 10:24:30 +0000 Subject: [PATCH 41/75] echoplayer: enable multiblock transfers for SDMMC Change-Id: I152a6d58b008041d646ddcfec4273a47c4060932 --- firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c index 7a192bc914..803b7cae2b 100644 --- a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c @@ -48,6 +48,7 @@ static const struct sdmmc_host_config sdmmc_config INITDATA_ATTR = { .bus_clocks = SDMMC_BUS_CLOCK_400KHZ | SDMMC_BUS_CLOCK_25MHZ | SDMMC_BUS_CLOCK_50MHZ, + .max_nr_blocks = 65535, .is_removable = true, }; From 02648abb8a2bc62f17f45e59b1cf773ce51899e3 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Fri, 6 Feb 2026 10:35:29 +0000 Subject: [PATCH 42/75] echoplayer: disable 50 MHz SDMMC bus clock While 50 MHz works for low activity and small amounts of data, there are frequent CRC errors when handling larger transfers. Increasing drive strength only makes it worse. Everything seems stable at 25 MHz though. Change-Id: I3471c490ab63b2302b21ee2fe601519ee5a40ce5 --- firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c index 803b7cae2b..3b3b860680 100644 --- a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c @@ -46,8 +46,7 @@ static const struct sdmmc_host_config sdmmc_config INITDATA_ATTR = { .bus_widths = SDMMC_BUS_WIDTH_1BIT | SDMMC_BUS_WIDTH_4BIT, .bus_clocks = SDMMC_BUS_CLOCK_400KHZ | - SDMMC_BUS_CLOCK_25MHZ | - SDMMC_BUS_CLOCK_50MHZ, + SDMMC_BUS_CLOCK_25MHZ, .max_nr_blocks = 65535, .is_removable = true, }; From 19af7131e28d35a5afcfa77cb5c1b7e19e000f56 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 5 Feb 2026 22:11:40 +0000 Subject: [PATCH 43/75] echoplayer: allow enabling system debug in normal builds Allow toggling the system debug state from the debug menu in Rockbox, or by holding a button combo at boot, so that an SWD/JTAG debugger can be attached to normal non-debug builds without too much hassle. Change-Id: Iee47ef916ade2e5ec1094a63c68e48f1b27b0bbb --- bootloader/echoplayer.c | 16 ++++ firmware/SOURCES | 2 + firmware/reggen/cortex-m.regs | 7 ++ firmware/target/arm/stm32/debug-stm32h7.c | 107 +++++++++++++++++++++- 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/bootloader/echoplayer.c b/bootloader/echoplayer.c index 6f742aec50..97b5ec2749 100644 --- a/bootloader/echoplayer.c +++ b/bootloader/echoplayer.c @@ -34,6 +34,7 @@ #include "rbversion.h" #include "system-echoplayer.h" #include "gpio-stm32h7.h" +#include "regs/cortex-m/cm_debug.h" #define SDRAM_SIZE (MEMORYSIZE * 1024 * 1024) @@ -136,6 +137,14 @@ static bool is_usbmode_button_pressed(void) return button_status() & BUTTON_DOWN; } +static bool is_sysdebug_button_pressed(void) +{ + const int mask = BUTTON_A | BUTTON_B; + + /* Both buttons must be held */ + return (button_status() & mask) == mask; +} + static int send_event_on_tmo(struct timeout *tmo) { button_queue_post(tmo->data, 0); @@ -370,6 +379,13 @@ void main(void) power_init(); button_init(); + /* Enable system debugging if button combo held or debugger attached */ + if (reg_readf(CM_DEBUG_DHCSR, C_DEBUGEN) || + is_sysdebug_button_pressed()) + { + system_debug_enable(true); + } + /* Start monitoring power button / usb state */ monitor_init(); diff --git a/firmware/SOURCES b/firmware/SOURCES index 6c0bec8219..4fa1cfaaf1 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1943,7 +1943,9 @@ target/arm/rk27xx/ihifi2/audio-ihifi800.c target/arm/stm32/crt0-stm32h7.S target/arm/stm32/vectors-stm32h7.S target/arm/stm32/adc-stm32h7.c +#ifndef BOOTLOADER target/arm/stm32/debug-stm32h7.c +#endif target/arm/stm32/gpio-stm32h7.c target/arm/stm32/i2c-stm32h7.c target/arm/stm32/pcm-stm32h7.c diff --git a/firmware/reggen/cortex-m.regs b/firmware/reggen/cortex-m.regs index 4be406b928..cb95bed5cf 100644 --- a/firmware/reggen/cortex-m.regs +++ b/firmware/reggen/cortex-m.regs @@ -168,3 +168,10 @@ CM_SYSTICK @ 0xe000e000 : block { 23 00 TENMS } } + +// Debug +CM_DEBUG @ 0xe000edf0 : block { + DHCSR @ 0x00 : reg { + 0 C_DEBUGEN + } +} diff --git a/firmware/target/arm/stm32/debug-stm32h7.c b/firmware/target/arm/stm32/debug-stm32h7.c index e7ffd1c37a..99a3849b41 100644 --- a/firmware/target/arm/stm32/debug-stm32h7.c +++ b/firmware/target/arm/stm32/debug-stm32h7.c @@ -19,10 +19,115 @@ * ****************************************************************************/ #include "system.h" +#include "kernel.h" +#include "button.h" +#include "lcd.h" +#include "font.h" +#include "action.h" +#include "list.h" +#include "regs/stm32h743/dbgmcu.h" +#include "regs/cortex-m/cm_debug.h" +#include + +enum +{ + SWD_MENU_IS_ENABLED, + SWD_MENU_IS_ATTACHED, + SWD_MENU_NUM_ENTRIES +}; + +static int swd_menu_action_cb(int action, struct gui_synclist *lists) +{ + int sel = gui_synclist_get_sel_pos(lists); + + if (sel == SWD_MENU_IS_ENABLED && action == ACTION_STD_OK) + { + if (reg_readf(DBGMCU_CR, DBGSLEEP_D1)) + system_debug_enable(false); + else + system_debug_enable(true); + + action = ACTION_REDRAW; + } + + if (action == ACTION_NONE) + action = ACTION_REDRAW; + + return action; +} + +static const char *swd_menu_get_name(int item, void *data, char *buf, size_t bufsz) +{ + (void)data; + + switch (item) + { + case SWD_MENU_IS_ENABLED: + snprintf(buf, bufsz, "System debug enabled: %d", + (int)!!reg_readf(DBGMCU_CR, DBGSLEEP_D1)); + return buf; + + case SWD_MENU_IS_ATTACHED: + snprintf(buf, bufsz, "DHCSR.C_DEBUGEN bit: %d", + (int)!!reg_readf(CM_DEBUG_DHCSR, C_DEBUGEN)); + return buf; + + default: + return ""; + } +} + +static bool swd_menu(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, "SWD/JTAG", SWD_MENU_NUM_ENTRIES, NULL); + info.action_callback = swd_menu_action_cb; + info.get_name = swd_menu_get_name; + return simplelist_show_list(&info); +} + +/* Menu definition */ +static const struct { + const char *name; + bool (*function) (void); +} menuitems[] = { + {"SWD/JTAG", swd_menu}, +}; + +static int hw_info_menu_action_cb(int btn, struct gui_synclist *lists) +{ + if (btn == ACTION_STD_OK) + { + int sel = gui_synclist_get_sel_pos(lists); + FOR_NB_SCREENS(i) + viewportmanager_theme_enable(i, false, NULL); + + menuitems[sel].function(); + btn = ACTION_REDRAW; + + FOR_NB_SCREENS(i) + viewportmanager_theme_undo(i, false); + } + + return btn; +} + +static const char* hw_info_menu_get_name(int item, void *data, char *buf, size_t bufsz) +{ + (void)buf; + (void)bufsz; + (void)data; + return menuitems[item].name; +} bool dbg_hw_info(void) { - return false; + struct simplelist_info info; + simplelist_info_init(&info, MODEL_NAME " debug menu", + ARRAYLEN(menuitems), NULL); + info.action_callback = hw_info_menu_action_cb; + info.get_name = hw_info_menu_get_name; + return simplelist_show_list(&info); } bool dbg_ports(void) From 5a21f049dc7bb9eb6b0735a048db3687b7b6f856 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 5 Feb 2026 22:20:14 +0000 Subject: [PATCH 44/75] echoplayer: add exit WPS button to keymap Change-Id: I3a7ef3ee0fb7494645338d3951fc9bc0c793503c --- apps/keymaps/keymap-echor1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/keymaps/keymap-echor1.c b/apps/keymaps/keymap-echor1.c index 4964535b82..140c682f82 100644 --- a/apps/keymaps/keymap-echor1.c +++ b/apps/keymaps/keymap-echor1.c @@ -57,6 +57,7 @@ static const struct button_mapping button_context_wps[] = { {ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT}, {ACTION_WPS_QUICKSCREEN, BUTTON_B, BUTTON_NONE}, + {ACTION_WPS_MENU, BUTTON_Y, BUTTON_NONE}, LAST_ITEM_IN_LIST }; /* button_context_wps */ From 58b186d6de1febe934f0715eb1f8a823c9d4ecd6 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Wed, 4 Feb 2026 11:45:07 +0000 Subject: [PATCH 45/75] Remove Creative Zen Vision and Vision:M ports They haven't seen development activity for the better part of two decades and apparently were never able to even boot to Rockbox, although the Rockbox bootloader could load the original firmware. Change-Id: I5cfa5909c21feaf2825aa685a05e78044b893a13 --- apps/SOURCES | 4 - apps/debug_menu.c | 28 - apps/keymaps/keymap-creativezv.c | 256 - apps/keymaps/keymap-creativezvm.c | 255 - apps/lang/english.lang | 6 +- apps/plugins/battery_bench.c | 6 - apps/plugins/blackjack.c | 16 - apps/plugins/brickmania.c | 11 +- apps/plugins/calculator.c | 11 - apps/plugins/calendar.c | 10 - apps/plugins/chessbox/chessbox_pgn.h | 14 - apps/plugins/chessclock.c | 10 - apps/plugins/chip8.c | 10 - apps/plugins/chopper.c | 6 - apps/plugins/clix.c | 8 - apps/plugins/cube.c | 10 - apps/plugins/doom/i_video.c | 12 - apps/plugins/flipit.c | 12 - apps/plugins/fractals/fractal.h | 12 - apps/plugins/goban/goban.h | 14 - apps/plugins/imageviewer/imageviewer_button.h | 12 - apps/plugins/invadrox.c | 7 - apps/plugins/jewels.c | 10 - apps/plugins/lib/keymaps.h | 5 - apps/plugins/lib/pluginlib_actions.c | 7 - apps/plugins/midi/midiplay.c | 8 - apps/plugins/minesweeper.c | 10 - apps/plugins/mp3_encoder.c | 6 - apps/plugins/mpegplayer/mpeg_settings.c | 10 - apps/plugins/mpegplayer/mpegplayer.c | 9 - apps/plugins/oscilloscope.c | 14 - apps/plugins/pacbox/pacbox.h | 11 - apps/plugins/pegbox.c | 17 - apps/plugins/pictureflow/pictureflow.c | 3 +- apps/plugins/pong.c | 7 - apps/plugins/reversi/reversi-gui.h | 9 - apps/plugins/rockblox.c | 10 - apps/plugins/rockboy/rockboy.c | 10 - apps/plugins/rockpaint.c | 11 - apps/plugins/sliding_puzzle.c | 9 - apps/plugins/snake.c | 8 - apps/plugins/snake2.c | 9 - apps/plugins/sokoban.c | 15 - apps/plugins/solitaire.c | 18 - apps/plugins/spacerocks.c | 9 - apps/plugins/star.c | 17 - apps/plugins/stopwatch.c | 8 - apps/plugins/sudoku/sudoku.h | 10 - apps/plugins/text_viewer/tv_button.h | 11 - apps/plugins/vu_meter.c | 11 - apps/plugins/wormlet.c | 10 - apps/plugins/xobox.c | 9 - apps/plugins/zxbox/keymaps.h | 8 - apps/plugins/zxbox/zxbox_keyb.c | 9 - bootloader/SOURCES | 2 - bootloader/creativezvm.c | 120 - firmware/SOURCES | 13 - firmware/asm/SOURCES | 2 +- firmware/drivers/audio/tlv320.c | 8 - firmware/export/config.h | 9 - firmware/export/config/zenvision.h | 166 - firmware/export/config/zenvisionm30gb.h | 175 - firmware/export/config/zenvisionm60gb.h | 167 - firmware/target/arm/ata-as-arm.S | 3 - firmware/target/arm/system-arm-classic.h | 13 - .../creative-zvm/adc-creativezvm.c | 35 - .../arm/tms320dm320/creative-zvm/adc-target.h | 40 - .../creative-zvm/ata-creativezvm.c | 544 -- .../arm/tms320dm320/creative-zvm/ata-target.h | 58 - .../creative-zvm/backlight-target.h | 33 - .../tms320dm320/creative-zvm/button-target.h | 68 - .../creative-zvm/dma-creativezvm.c | 132 - .../arm/tms320dm320/creative-zvm/dma-target.h | 30 - .../creative-zvm/lcd-creativezvm.c | 427 -- .../arm/tms320dm320/creative-zvm/lcd-target.h | 38 - .../creative-zvm/pcm-creativezvm.c | 80 - .../creative-zvm/pic-creativezvm.c | 380 -- .../creative-zvm/power-creativezvm.c | 53 - .../creative-zvm/powermgmt-creativezvm.c | 50 - .../creative-zvm/usb-creativezvm.c | 71 - firmware/target/arm/tms320dm320/crt0.S | 2 +- firmware/target/arm/tms320dm320/debug-dm320.c | 11 - firmware/target/arm/tms320dm320/dsp/Makefile | 10 +- firmware/target/arm/tms320dm320/dsp/aic23.c | 60 - firmware/target/arm/tms320dm320/i2c-dm320.c | 7 - firmware/target/arm/tms320dm320/spi-dm320.c | 5 +- firmware/target/arm/tms320dm320/spi-target.h | 4 +- .../target/arm/tms320dm320/system-dm320.c | 7 - .../target/arm/tms320dm320/system-target.h | 10 - firmware/target/hosted/sdl/sim-ui-defines.h | 18 - manual/plugins/xworld.tex | 6 +- .../images/zenvision-front.pdf | Bin 218758 -> 0 bytes .../images/zenvision-front.png | Bin 90707 -> 0 bytes .../images/zenvision-front.svg | 4979 ----------------- .../images/zenvisionm-front.pdf | Bin 85097 -> 0 bytes .../images/zenvisionm-front.png | Bin 64810 -> 0 bytes .../images/zenvisionm-front.svg | 1368 ----- tools/builds.pm | 15 - tools/configure | 144 +- tools/creative.c | 8 - tools/creative.h | 11 +- tools/scramble.c | 11 +- uisimulator/buttonmap/SOURCES | 4 - utils/themeeditor/resources/targetdb | 27 - 104 files changed, 59 insertions(+), 10413 deletions(-) delete mode 100644 apps/keymaps/keymap-creativezv.c delete mode 100644 apps/keymaps/keymap-creativezvm.c delete mode 100644 bootloader/creativezvm.c delete mode 100644 firmware/export/config/zenvision.h delete mode 100644 firmware/export/config/zenvisionm30gb.h delete mode 100644 firmware/export/config/zenvisionm60gb.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/adc-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/adc-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/ata-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/backlight-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/button-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/dma-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/dma-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/lcd-target.h delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/power-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/powermgmt-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/creative-zvm/usb-creativezvm.c delete mode 100644 firmware/target/arm/tms320dm320/dsp/aic23.c delete mode 100644 manual/rockbox_interface/images/zenvision-front.pdf delete mode 100644 manual/rockbox_interface/images/zenvision-front.png delete mode 100644 manual/rockbox_interface/images/zenvision-front.svg delete mode 100644 manual/rockbox_interface/images/zenvisionm-front.pdf delete mode 100644 manual/rockbox_interface/images/zenvisionm-front.png delete mode 100644 manual/rockbox_interface/images/zenvisionm-front.svg diff --git a/apps/SOURCES b/apps/SOURCES index 1898fa6284..923e979af5 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -215,10 +215,6 @@ keymaps/keymap-mr500.c keymaps/keymap-mr100.c #elif CONFIG_KEYPAD == COWON_D2_PAD keymaps/keymap-cowond2.c -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -keymaps/keymap-creativezvm.c -#elif CONFIG_KEYPAD == CREATIVEZV_PAD -keymaps/keymap-creativezv.c #elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD keymaps/keymap-zenxfi2.c #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 8f4e1d673c..117194b834 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -2601,31 +2601,6 @@ static bool dbg_isp1583(void) } #endif -#if defined(CREATIVE_ZVx) && !defined(SIMULATOR) -extern int pic_dbg_num_items(void); -extern const char* pic_dbg_item(int selected_item, void *data, - char *buffer, size_t buffer_len); - -static int pic_action_callback(int action, struct gui_synclist *lists) -{ - (void)lists; - if (action == ACTION_NONE) - action = ACTION_REDRAW; - return action; -} - -static bool dbg_pic(void) -{ - struct simplelist_info pic; - pic.scroll_all = true; - simplelist_info_init(&pic, "PIC", pic_dbg_num_items(), NULL); - pic.timeout = HZ/100; - pic.get_name = pic_dbg_item; - pic.action_callback = pic_action_callback; - return simplelist_show_list(&pic); -} -#endif - #if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) static bool dbg_boot_data(void) { @@ -2942,9 +2917,6 @@ static const struct { #if CONFIG_USBOTG == USBOTG_ISP1583 { "View ISP1583 info", dbg_isp1583 }, #endif -#if defined(CREATIVE_ZVx) && !defined(SIMULATOR) - { "View PIC info", dbg_pic }, -#endif #ifdef ROCKBOX_HAS_LOGF {"Show Log File", logfdisplay }, {"Dump Log File", logfdump }, diff --git a/apps/keymaps/keymap-creativezv.c b/apps/keymaps/keymap-creativezv.c deleted file mode 100644 index 3242e8924f..0000000000 --- a/apps/keymaps/keymap-creativezv.c +++ /dev/null @@ -1,256 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for the Creative Zen Vision target */ -/* Copied from ZVM target for now... */ -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -/* CONTEXT_CUSTOM's used in this file... - -CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions) -CONTEXT_CUSTOM|CONTEXT_SETTINGS = the direction keys for the eq/col picker screens - i.e where up/down is inc/dec - CONTEXT_SETTINGS = up/down is prev/next, l/r is inc/dec - -*/ - -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, - - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - - //{ ACTION_WPS_ABSETB_NEXTDIR,BUTTON_RIGHT, BUTTON_CUSTOM }, - //{ ACTION_WPS_ABSETA_PREVDIR,BUTTON_LEFT, BUTTON_CUSTOM }, - //{ ACTION_WPS_ABRESET, BUTTON_CUSTOM|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, - - { ACTION_WPS_PITCHSCREEN, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK }, - - { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_WPS_VIEW_PLAYLIST, BUTTON_POWER, BUTTON_NONE }, - { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_WPS_HOTKEY, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - { ACTION_WPS_BROWSE, BUTTON_SELECT|BUTTON_REL, BUTTON_BACK }, - LAST_ITEM_IN_LIST -}; /* button_context_wps */ - -static const struct button_mapping button_context_list[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_list */ - -static const struct button_mapping button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_TREE_STOP, BUTTON_POWER, BUTTON_NONE }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_HOTKEY, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) -}; /* button_context_tree */ - -static const struct button_mapping button_context_listtree_scroll_without_combo[] = { - { ACTION_NONE, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - { ACTION_TREE_ROOT_INIT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_TREE_PGRIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_RIGHT }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings */ - -static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settingsgraphical */ - -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_yesno */ - -static const struct button_mapping button_context_colorchooser[] = { - { ACTION_STD_OK, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ - -static const struct button_mapping button_context_eq[] = { - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_eq */ - -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { - { ACTION_BMS_DELETE, BUTTON_BACK, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_bmark */ - -static const struct button_mapping button_context_time[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_time */ - -static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ - -static const struct button_mapping button_context_pitchscreen[] = { - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ - -static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_CUSTOM, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_CUSTOM|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_PAGE_FLIP, BUTTON_BACK|BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_DONE, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_KBD_ABORT, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST -}; /* button_context_keyboard */ - -const struct button_mapping* get_context_mapping(int context) -{ - switch (context&~CONTEXT_REMOTE) - { - case CONTEXT_STD: - return button_context_standard; - case CONTEXT_WPS: - return button_context_wps; - case CONTEXT_LIST: - return button_context_list; - case CONTEXT_MAINMENU: - case CONTEXT_TREE: - return button_context_listtree_scroll_without_combo; - case CONTEXT_CUSTOM|CONTEXT_TREE: - return button_context_tree; - case CONTEXT_SETTINGS: - return button_context_settings; - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - return button_context_settings_right_is_inc; - case CONTEXT_SETTINGS_COLOURCHOOSER: - return button_context_colorchooser; - case CONTEXT_SETTINGS_EQ: - return button_context_eq; - case CONTEXT_SETTINGS_TIME: - return button_context_time; - case CONTEXT_YESNOSCREEN: - return button_context_yesno; - case CONTEXT_BOOKMARKSCREEN: - return button_context_bmark; - case CONTEXT_QUICKSCREEN: - return button_context_quickscreen; - case CONTEXT_PITCHSCREEN: - return button_context_pitchscreen; - case CONTEXT_KEYBOARD: - case CONTEXT_MORSE_INPUT: - return button_context_keyboard; - } - return button_context_standard; -} diff --git a/apps/keymaps/keymap-creativezvm.c b/apps/keymaps/keymap-creativezvm.c deleted file mode 100644 index 47b24bf8b3..0000000000 --- a/apps/keymaps/keymap-creativezvm.c +++ /dev/null @@ -1,255 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* Button Code Definitions for the Creative Zen Vision:M target */ -#include -#include -#include - -#include "config.h" -#include "action.h" -#include "button.h" -#include "settings.h" - -/* - * The format of the list is as follows - * { Action Code, Button code, Prereq button code } - * if there's no need to check the previous button's value, use BUTTON_NONE - * Insert LAST_ITEM_IN_LIST at the end of each mapping - */ - -/* CONTEXT_CUSTOM's used in this file... - -CONTEXT_CUSTOM|CONTEXT_TREE = the standard list/tree defines (without directions) -CONTEXT_CUSTOM|CONTEXT_SETTINGS = the direction keys for the eq/col picker screens - i.e where up/down is inc/dec - CONTEXT_SETTINGS = up/down is prev/next, l/r is inc/dec - -*/ - -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_UP|BUTTON_REL, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, - - { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, - { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, - - LAST_ITEM_IN_LIST -}; /* button_context_standard */ - - -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - - //{ ACTION_WPS_ABSETB_NEXTDIR,BUTTON_RIGHT, BUTTON_CUSTOM }, - //{ ACTION_WPS_ABSETA_PREVDIR,BUTTON_LEFT, BUTTON_CUSTOM }, - //{ ACTION_WPS_ABRESET, BUTTON_CUSTOM|BUTTON_REPEAT, BUTTON_NONE }, - - { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, - - { ACTION_WPS_PITCHSCREEN, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK }, - - { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, - { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, - { ACTION_WPS_VIEW_PLAYLIST, BUTTON_POWER, BUTTON_NONE }, - { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, - - { ACTION_WPS_HOTKEY, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - { ACTION_WPS_BROWSE, BUTTON_SELECT|BUTTON_REL, BUTTON_BACK }, - LAST_ITEM_IN_LIST -}; /* button_context_wps */ - -static const struct button_mapping button_context_list[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_list */ - -static const struct button_mapping button_context_tree[] = { - { ACTION_TREE_WPS, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_TREE_STOP, BUTTON_POWER, BUTTON_NONE }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, - { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_TREE_HOTKEY, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) -}; /* button_context_tree */ - -static const struct button_mapping button_context_listtree_scroll_without_combo[] = { - { ACTION_NONE, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, - { ACTION_TREE_ROOT_INIT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_TREE_PGLEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_NONE, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, - { ACTION_TREE_PGRIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), -}; - -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP }, - { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_LEFT }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_RIGHT }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings */ - -static const struct button_mapping button_context_settings_right_is_inc[] = { - { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settingsgraphical */ - -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_settings_yesno */ - -static const struct button_mapping button_context_colorchooser[] = { - { ACTION_STD_OK, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ - -static const struct button_mapping button_context_eq[] = { - { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), -}; /* button_context_eq */ - -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { - { ACTION_BMS_DELETE, BUTTON_BACK, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_bmark */ - -static const struct button_mapping button_context_time[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_time */ - -static const struct button_mapping button_context_quickscreen[] = { - { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, - { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ - -static const struct button_mapping button_context_pitchscreen[] = { - - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ - -static const struct button_mapping button_context_keyboard[] = { - { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_CUSTOM, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_CUSTOM|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, - { ACTION_KBD_PAGE_FLIP, BUTTON_BACK|BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_DONE, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_KBD_ABORT, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU, BUTTON_NONE }, - { ACTION_KBD_BACKSPACE, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_MORSE_SELECT, BUTTON_SELECT|BUTTON_REL, BUTTON_NONE }, - LAST_ITEM_IN_LIST -}; /* button_context_keyboard */ - -const struct button_mapping* get_context_mapping(int context) -{ - switch (context&~CONTEXT_REMOTE) - { - case CONTEXT_STD: - return button_context_standard; - case CONTEXT_WPS: - return button_context_wps; - case CONTEXT_LIST: - return button_context_list; - case CONTEXT_MAINMENU: - case CONTEXT_TREE: - return button_context_listtree_scroll_without_combo; - case CONTEXT_CUSTOM|CONTEXT_TREE: - return button_context_tree; - case CONTEXT_SETTINGS: - return button_context_settings; - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - return button_context_settings_right_is_inc; - case CONTEXT_SETTINGS_COLOURCHOOSER: - return button_context_colorchooser; - case CONTEXT_SETTINGS_EQ: - return button_context_eq; - case CONTEXT_SETTINGS_TIME: - return button_context_time; - case CONTEXT_YESNOSCREEN: - return button_context_yesno; - case CONTEXT_BOOKMARKSCREEN: - return button_context_bmark; - case CONTEXT_QUICKSCREEN: - return button_context_quickscreen; - case CONTEXT_PITCHSCREEN: - return button_context_pitchscreen; - case CONTEXT_KEYBOARD: - case CONTEXT_MORSE_INPUT: - return button_context_keyboard; - } - return button_context_standard; -} diff --git a/apps/lang/english.lang b/apps/lang/english.lang index de9eb1d942..c244096637 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -14919,7 +14919,7 @@ user: core *: "Press LEFT to cancel." - android,hifietma*,zenvision: "Press BACK to cancel." + android,hifietma*: "Press BACK to cancel." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel." ihifi760,ihifi960: "Double tap RETURN to cancel." ihifi770,ihifi770c,ihifi800: "Press HOME to cancel." @@ -14934,7 +14934,7 @@ *: "Press LEFT to cancel." - android,hifietma*,zenvision: "Press BACK to cancel." + android,hifietma*: "Press BACK to cancel." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel." ihifi760,ihifi960: "Double tap RETURN to cancel." ihifi770,ihifi770c,ihifi800: "Press HOME to cancel." @@ -14949,7 +14949,7 @@ *: "Press LEFT to cancel." - android,hifietma*,zenvision: "Press BACK to cancel." + android,hifietma*: "Press BACK to cancel." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel." ihifi760,ihifi960: "Double tap RETURN to cancel." ihifi770,ihifi770c,ihifi800: "Press HOME to cancel." diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index fc67b306b0..6245340fb3 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -150,12 +150,6 @@ struct battery_tables_t { #define BATTERY_OFF BUTTON_POWER #define BATTERY_OFF_TXT "POWER" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define BATTERY_ON BUTTON_PLAY -#define BATTERY_ON_TXT "PLAY - start" -#define BATTERY_OFF BUTTON_BACK -#define BATTERY_OFF_TXT "BACK" - #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD #define BATTERY_ON BUTTON_MENU diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c index b39aa4b2f4..10272f90e4 100644 --- a/apps/plugins/blackjack.c +++ b/apps/plugins/blackjack.c @@ -237,22 +237,6 @@ enum { #define BJACK_QUIT BUTTON_POWER #define BJACK_DOUBLEDOWN BUTTON_MINUS -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define BJACK_SELECT_NAME "SELECT" -#define BJACK_STAY_NAME "PLAY" -#define BJACK_QUIT_NAME "POWER" -#define BJACK_DOUBLE_NAME "CUSTOM" -#define BJACK_SELECT BUTTON_SELECT -#define BJACK_QUIT BUTTON_POWER -#define BJACK_STAY BUTTON_PLAY -#define BJACK_MAX (BUTTON_CUSTOM|BUTTON_UP) -#define BJACK_MIN (BUTTON_CUSTOM|BUTTON_DOWN) -#define BJACK_DOUBLEDOWN BUTTON_CUSTOM -#define BJACK_UP BUTTON_UP -#define BJACK_DOWN BUTTON_DOWN -#define BJACK_RIGHT BUTTON_RIGHT -#define BJACK_LEFT BUTTON_LEFT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define BJACK_SELECT_NAME "PLAY" #define BJACK_STAY_NAME "MENU" diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c index 121a96cdda..bb34219895 100644 --- a/apps/plugins/brickmania.c +++ b/apps/plugins/brickmania.c @@ -169,14 +169,6 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define DOWN BUTTON_RC_VOL_DOWN #define RC_QUIT BUTTON_REC -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define QUIT BUTTON_BACK -#define LEFT BUTTON_LEFT -#define RIGHT BUTTON_RIGHT -#define SELECT BUTTON_SELECT -#define UP BUTTON_UP -#define DOWN BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define QUIT BUTTON_POWER #define LEFT BUTTON_BACK @@ -1504,8 +1496,7 @@ static int brickmania_help(void) "Releases", "the", "ball/Fire!", "", /* 30 */ #if CONFIG_KEYPAD == IAUDIO_M3_PAD "REC:", -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ - (CONFIG_KEYPAD == CREATIVEZVM_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) "BACK:", #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) || \ diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index f4790a00cd..5e69e1f12a 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c @@ -269,17 +269,6 @@ F3: equal to "=" #define CALCULATOR_QUIT BUTTON_POWER #define CALCULATOR_CLEAR BUTTON_MENU -#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD) - -#define CALCULATOR_LEFT BUTTON_LEFT -#define CALCULATOR_RIGHT BUTTON_RIGHT -#define CALCULATOR_UP BUTTON_UP -#define CALCULATOR_DOWN BUTTON_DOWN -#define CALCULATOR_QUIT BUTTON_BACK -#define CALCULATOR_INPUT BUTTON_SELECT -#define CALCULATOR_CALC BUTTON_MENU -#define CALCULATOR_CLEAR BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CALCULATOR_LEFT (BUTTON_BACK|BUTTON_REL) diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c index deb23f05e7..d1213367ae 100644 --- a/apps/plugins/calendar.c +++ b/apps/plugins/calendar.c @@ -149,16 +149,6 @@ #define CALENDAR_PREV_MONTH BUTTON_BOTTOMLEFT #define CALENDAR_EVENT_MENU_NAME "menu" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CALENDAR_QUIT BUTTON_BACK -#define CALENDAR_SELECT BUTTON_SELECT -#define CALENDAR_NEXT_WEEK BUTTON_DOWN -#define CALENDAR_PREV_WEEK BUTTON_UP -#define CALENDAR_NEXT_DAY BUTTON_RIGHT -#define CALENDAR_PREV_DAY BUTTON_LEFT -#define CALENDAR_NEXT_MONTH BUTTON_CUSTOM -#define CALENDAR_PREV_MONTH BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CALENDAR_QUIT BUTTON_POWER #define CALENDAR_SELECT BUTTON_PLAY diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h index 342f2f2cce..681f89150c 100644 --- a/apps/plugins/chessbox/chessbox_pgn.h +++ b/apps/plugins/chessbox/chessbox_pgn.h @@ -222,20 +222,6 @@ #define CB_RESTART BUTTON_MINUS #define CB_MENU (BUTTON_MENU|BUTTON_REL) -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CB_SELECT BUTTON_PLAY -#define CB_UP BUTTON_UP -#define CB_DOWN BUTTON_DOWN -#define CB_LEFT BUTTON_LEFT -#define CB_RIGHT BUTTON_RIGHT -#define CB_PLAY BUTTON_SELECT -#define CB_LEVEL BUTTON_CUSTOM -#define CB_MENU BUTTON_MENU -#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) -#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) -#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) -#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CB_SELECT (BUTTON_PLAY|BUTTON_REL) #define CB_UP BUTTON_UP diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c index 7b01ece12f..521ae034b7 100644 --- a/apps/plugins/chessclock.c +++ b/apps/plugins/chessclock.c @@ -147,16 +147,6 @@ #define CHC_SETTINGS_DEC BUTTON_MINUS #define CHC_SETTINGS_CANCEL BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CHC_QUIT BUTTON_BACK -#define CHC_STARTSTOP BUTTON_PLAY -#define CHC_RESET BUTTON_CUSTOM -#define CHC_MENU BUTTON_MENU -#define CHC_SETTINGS_INC BUTTON_UP -#define CHC_SETTINGS_DEC BUTTON_DOWN -#define CHC_SETTINGS_OK BUTTON_SELECT -#define CHC_SETTINGS_CANCEL BUTTON_BACK - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CHC_QUIT BUTTON_POWER #define CHC_STARTSTOP BUTTON_PLAY diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c index acb23b38c3..fa6acea82a 100644 --- a/apps/plugins/chip8.c +++ b/apps/plugins/chip8.c @@ -1048,16 +1048,6 @@ CONFIG_KEYPAD == SANSA_M200_PAD #elif (CONFIG_KEYPAD == COWON_D2_PAD) #define CHIP8_OFF BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CHIP8_OFF BUTTON_BACK -#define CHIP8_KEY1 BUTTON_MENU -#define CHIP8_KEY2 BUTTON_UP -#define CHIP8_KEY3 BUTTON_CUSTOM -#define CHIP8_KEY4 BUTTON_LEFT -#define CHIP8_KEY5 BUTTON_PLAY -#define CHIP8_KEY6 BUTTON_RIGHT -#define CHIP8_KEY8 BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CHIP8_OFF BUTTON_POWER #define CHIP8_KEY1 BUTTON_VOL_UP diff --git a/apps/plugins/chopper.c b/apps/plugins/chopper.c index 864d087076..74d1fc9237 100644 --- a/apps/plugins/chopper.c +++ b/apps/plugins/chopper.c @@ -108,12 +108,6 @@ Still To do: #define QUIT BUTTON_POWER #define ACTION2 BUTTON_PLUS -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define QUIT BUTTON_BACK -#define ACTION BUTTON_UP -#define ACTION2 BUTTON_MENU -#define ACTIONTEXT "UP" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define QUIT BUTTON_POWER #define ACTION BUTTON_UP diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c index 321e7129bd..210864968b 100644 --- a/apps/plugins/clix.c +++ b/apps/plugins/clix.c @@ -114,14 +114,6 @@ #define CLIX_BUTTON_UP BUTTON_UP #define CLIX_BUTTON_DOWN BUTTON_DOWN -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CLIX_BUTTON_QUIT BUTTON_BACK -#define CLIX_BUTTON_LEFT BUTTON_LEFT -#define CLIX_BUTTON_RIGHT BUTTON_RIGHT -#define CLIX_BUTTON_CLICK BUTTON_SELECT -#define CLIX_BUTTON_UP BUTTON_UP -#define CLIX_BUTTON_DOWN BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CLIX_BUTTON_QUIT BUTTON_POWER #define CLIX_BUTTON_LEFT BUTTON_BACK diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c index 929630a09f..d3c95be10f 100644 --- a/apps/plugins/cube.c +++ b/apps/plugins/cube.c @@ -163,16 +163,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define CUBE_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define CUBE_QUIT BUTTON_BACK -#define CUBE_NEXT BUTTON_RIGHT -#define CUBE_PREV BUTTON_LEFT -#define CUBE_INC BUTTON_UP -#define CUBE_DEC BUTTON_DOWN -#define CUBE_MODE BUTTON_MENU -#define CUBE_PAUSE BUTTON_PLAY -#define CUBE_HIGHSPEED BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define CUBE_QUIT BUTTON_POWER #define CUBE_NEXT BUTTON_UP diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index 31a646f988..cdae2a2b5c 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -316,18 +316,6 @@ void I_ShutdownGraphics(void) #define DOOMBUTTON_ENTER BUTTON_MENU #define DOOMBUTTON_WEAPON BUTTON_DISPLAY -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define DOOMBUTTON_UP BUTTON_UP -#define DOOMBUTTON_DOWN BUTTON_DOWN -#define DOOMBUTTON_LEFT BUTTON_LEFT -#define DOOMBUTTON_RIGHT BUTTON_RIGHT -#define DOOMBUTTON_SHOOT BUTTON_SELECT -#define DOOMBUTTON_OPEN BUTTON_PLAY -#define DOOMBUTTON_ESC BUTTON_BACK -#define DOOMBUTTON_ENTER BUTTON_PLAY -#define DOOMBUTTON_WEAPON BUTTON_MENU -#define DOOMBUTTON_MAP BUTTON_CUSTOM - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define DOOMBUTTON_UP BUTTON_UP #define DOOMBUTTON_DOWN BUTTON_DOWN diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c index 79518bfa80..3080f2f239 100644 --- a/apps/plugins/flipit.c +++ b/apps/plugins/flipit.c @@ -226,18 +226,6 @@ #define FLIPIT_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define FLIPIT_LEFT BUTTON_LEFT -#define FLIPIT_RIGHT BUTTON_RIGHT -#define FLIPIT_UP BUTTON_UP -#define FLIPIT_DOWN BUTTON_DOWN -#define FLIPIT_QUIT BUTTON_BACK -#define FLIPIT_SHUFFLE BUTTON_CUSTOM -#define FLIPIT_SOLVE BUTTON_PLAY -#define FLIPIT_STEP_BY_STEP BUTTON_MENU -#define FLIPIT_TOGGLE BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define FLIPIT_LEFT BUTTON_BACK #define FLIPIT_RIGHT BUTTON_MENU diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h index f3da8bc781..d56b7a1f39 100644 --- a/apps/plugins/fractals/fractal.h +++ b/apps/plugins/fractals/fractal.h @@ -200,18 +200,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define FRACTAL_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define FRACTAL_QUIT BUTTON_BACK -#define FRACTAL_UP BUTTON_UP -#define FRACTAL_DOWN BUTTON_DOWN -#define FRACTAL_LEFT BUTTON_LEFT -#define FRACTAL_RIGHT BUTTON_RIGHT -#define FRACTAL_ZOOM_IN BUTTON_PLAY -#define FRACTAL_ZOOM_OUT BUTTON_MENU -#define FRACTAL_PRECISION_INC (BUTTON_UP | BUTTON_CUSTOM) -#define FRACTAL_PRECISION_DEC (BUTTON_DOWN | BUTTON_CUSTOM) -#define FRACTAL_RESET BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define FRACTAL_QUIT BUTTON_POWER #define FRACTAL_UP BUTTON_UP diff --git a/apps/plugins/goban/goban.h b/apps/plugins/goban/goban.h index 83c8a81221..159f3d2fbd 100644 --- a/apps/plugins/goban/goban.h +++ b/apps/plugins/goban/goban.h @@ -150,20 +150,6 @@ #define GBN_BUTTON_CONTEXT BUTTON_SELECT | BUTTON_REPEAT #define GBN_BUTTON_NEXT_VAR BUTTON_NEXT - -#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD) \ - || (CONFIG_KEYPAD == CREATIVEZV_PAD) -#define GBN_BUTTON_UP BUTTON_UP -#define GBN_BUTTON_DOWN BUTTON_DOWN -#define GBN_BUTTON_LEFT BUTTON_LEFT -#define GBN_BUTTON_RIGHT BUTTON_RIGHT -#define GBN_BUTTON_RETREAT BUTTON_BACK -#define GBN_BUTTON_ADVANCE BUTTON_CUSTOM -#define GBN_BUTTON_MENU BUTTON_MENU -#define GBN_BUTTON_PLAY BUTTON_SELECT | BUTTON_REL -#define GBN_BUTTON_CONTEXT BUTTON_SELECT | BUTTON_REPEAT -#define GBN_BUTTON_NEXT_VAR BUTTON_PLAY - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) #define GBN_BUTTON_UP BUTTON_UP | BUTTON_REL #define GBN_BUTTON_DOWN BUTTON_DOWN diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h index aea8904280..46e99ff3f8 100644 --- a/apps/plugins/imageviewer/imageviewer_button.h +++ b/apps/plugins/imageviewer/imageviewer_button.h @@ -209,18 +209,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define IMGVIEW_ZOOM_IN BUTTON_PLAY -#define IMGVIEW_ZOOM_OUT BUTTON_CUSTOM -#define IMGVIEW_UP BUTTON_UP -#define IMGVIEW_DOWN BUTTON_DOWN -#define IMGVIEW_LEFT BUTTON_LEFT -#define IMGVIEW_RIGHT BUTTON_RIGHT -#define IMGVIEW_NEXT BUTTON_SELECT -#define IMGVIEW_PREVIOUS BUTTON_BACK -#define IMGVIEW_MENU BUTTON_MENU - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define IMGVIEW_ZOOM_IN (BUTTON_VOL_UP|BUTTON_REL) #define IMGVIEW_ZOOM_OUT (BUTTON_VOL_DOWN|BUTTON_REL) diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c index 0a4eae97f3..d8b792aedc 100644 --- a/apps/plugins/invadrox.c +++ b/apps/plugins/invadrox.c @@ -155,13 +155,6 @@ #define RIGHT BUTTON_PLUS #define FIRE BUTTON_MENU -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define QUIT BUTTON_BACK -#define LEFT BUTTON_LEFT -#define RIGHT BUTTON_RIGHT -#define FIRE BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define QUIT BUTTON_POWER diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c index e9c137b12f..e681c578ad 100644 --- a/apps/plugins/jewels.c +++ b/apps/plugins/jewels.c @@ -191,16 +191,6 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define JEWELS_CANCEL BUTTON_POWER #define HK_CANCEL "POWER" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define JEWELS_UP BUTTON_UP -#define JEWELS_DOWN BUTTON_DOWN -#define JEWELS_LEFT BUTTON_LEFT -#define JEWELS_RIGHT BUTTON_RIGHT -#define JEWELS_SELECT BUTTON_SELECT -#define JEWELS_CANCEL BUTTON_BACK -#define HK_SELECT "MIDDLE" -#define HK_CANCEL "BACK" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define JEWELS_UP BUTTON_UP #define JEWELS_DOWN BUTTON_DOWN diff --git a/apps/plugins/lib/keymaps.h b/apps/plugins/lib/keymaps.h index a8521af23e..f5194ee053 100644 --- a/apps/plugins/lib/keymaps.h +++ b/apps/plugins/lib/keymaps.h @@ -56,7 +56,6 @@ (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) || \ (CONFIG_KEYPAD == CREATIVE_ZEN_PAD) || \ (CONFIG_KEYPAD == SONY_NWZ_PAD) || \ - (CONFIG_KEYPAD == CREATIVEZVM_PAD) || \ (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) || \ (CONFIG_KEYPAD == HM801_PAD) || \ @@ -128,10 +127,6 @@ #define BTN_FIRE BUTTON_SELECT #define BTN_PAUSE BUTTON_BACK -#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD) -#define BTN_FIRE BUTTON_PLAY -#define BTN_PAUSE BUTTON_MENU - #elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define BTN_FIRE BUTTON_USER #define BTN_PAUSE BUTTON_MENU diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c index 4b759b2437..171522acae 100644 --- a/apps/plugins/lib/pluginlib_actions.c +++ b/apps/plugins/lib/pluginlib_actions.c @@ -96,7 +96,6 @@ const struct button_mapping pla_main_ctx[] = || (CONFIG_KEYPAD == MROBE100_PAD) \ || (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD) \ || (CONFIG_KEYPAD == SANSA_CLIP_PAD) \ - || (CONFIG_KEYPAD == CREATIVEZVM_PAD) \ || (CONFIG_KEYPAD == SANSA_M200_PAD)\ || (CONFIG_KEYPAD == SANSA_E200_PAD) \ || (CONFIG_KEYPAD == SANSA_FUZE_PAD) \ @@ -405,12 +404,6 @@ const struct button_mapping pla_main_ctx[] = {PLA_SELECT, BUTTON_PLAY, BUTTON_NONE}, {PLA_SELECT_REL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, {PLA_SELECT_REPEAT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE}, -#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD) - {PLA_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, - {PLA_EXIT, BUTTON_BACK|BUTTON_REPEAT, BUTTON_NONE}, - {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE}, - {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, - {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE}, #elif (CONFIG_KEYPAD == ONDAVX747_PAD) {PLA_CANCEL, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, {PLA_EXIT, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE}, diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index f3e74d4ec0..510b03f789 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c @@ -140,14 +140,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define MIDI_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MIDI_QUIT BUTTON_BACK -#define MIDI_FFWD BUTTON_RIGHT -#define MIDI_REWIND BUTTON_LEFT -#define MIDI_VOL_UP BUTTON_UP -#define MIDI_VOL_DOWN BUTTON_DOWN -#define MIDI_PLAYPAUSE BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define MIDI_QUIT (BUTTON_PLAY|BUTTON_REPEAT) #define MIDI_FFWD BUTTON_MENU diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c index bda2093b2a..e4a99e8f22 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -165,16 +165,6 @@ enum minesweeper_status { #elif (CONFIG_KEYPAD == COWON_D2_PAD) # define MINESWP_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -# define MINESWP_LEFT BUTTON_LEFT -# define MINESWP_RIGHT BUTTON_RIGHT -# define MINESWP_UP BUTTON_UP -# define MINESWP_DOWN BUTTON_DOWN -# define MINESWP_QUIT BUTTON_BACK -# define MINESWP_TOGGLE BUTTON_SELECT -# define MINESWP_DISCOVER BUTTON_PLAY -# define MINESWP_INFO BUTTON_MENU - #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD # define MINESWP_LEFT BUTTON_LEFT # define MINESWP_RIGHT BUTTON_RIGHT diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c index 89851de875..7e96ab81d9 100644 --- a/apps/plugins/mp3_encoder.c +++ b/apps/plugins/mp3_encoder.c @@ -2446,12 +2446,6 @@ static void get_mp3_filename(const char *wav_name) #elif CONFIG_KEYPAD == COWON_D2_PAD #define MP3ENC_DONE BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MP3ENC_PREV BUTTON_UP -#define MP3ENC_NEXT BUTTON_DOWN -#define MP3ENC_DONE BUTTON_BACK -#define MP3ENC_SELECT BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define MP3ENC_PREV BUTTON_UP #define MP3ENC_NEXT BUTTON_DOWN diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 1a5b0d99cb..58dc11c89a 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c @@ -142,16 +142,6 @@ struct mpeg_settings settings; #elif CONFIG_KEYPAD == COWON_D2_PAD #define MPEG_START_TIME_EXIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MPEG_START_TIME_SELECT BUTTON_SELECT -#define MPEG_START_TIME_LEFT BUTTON_LEFT -#define MPEG_START_TIME_RIGHT BUTTON_RIGHT -#define MPEG_START_TIME_UP BUTTON_UP -#define MPEG_START_TIME_DOWN BUTTON_DOWN -#define MPEG_START_TIME_LEFT2 BUTTON_PLAY -#define MPEG_START_TIME_RIGHT2 BUTTON_MENU -#define MPEG_START_TIME_EXIT BUTTON_BACK - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) #define MPEG_START_TIME_SELECT (BUTTON_PLAY|BUTTON_REL) #define MPEG_START_TIME_LEFT BUTTON_BACK diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index 5d7d6036d2..02eeb6455d 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -254,15 +254,6 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define MPEG_VOLDOWN BUTTON_MINUS #define MPEG_VOLUP BUTTON_PLUS -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define MPEG_MENU BUTTON_MENU -#define MPEG_STOP BUTTON_BACK -#define MPEG_PAUSE BUTTON_PLAY -#define MPEG_VOLDOWN BUTTON_UP -#define MPEG_VOLUP BUTTON_DOWN -#define MPEG_RW BUTTON_LEFT -#define MPEG_FF BUTTON_RIGHT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define MPEG_MENU BUTTON_MENU #define MPEG_STOP (BUTTON_PLAY|BUTTON_REPEAT) diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c index 9943b78aba..49c0aeda4e 100644 --- a/apps/plugins/oscilloscope.c +++ b/apps/plugins/oscilloscope.c @@ -223,20 +223,6 @@ #define OSCILLOSCOPE_VOL_UP BUTTON_PLUS #define OSCILLOSCOPE_VOL_DOWN BUTTON_MINUS -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define OSCILLOSCOPE_QUIT BUTTON_BACK -#define OSCILLOSCOPE_DRAWMODE BUTTON_SELECT -#define OSCILLOSCOPE_ADVMODE BUTTON_CUSTOM -#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_MENU -#define OSCILLOSCOPE_ORIENTATION (BUTTON_MENU | BUTTON_REL) -#define OSCILLOSCOPE_GRAPHMODE_PRE BUTTON_MENU -#define OSCILLOSCOPE_GRAPHMODE (BUTTON_MENU | BUTTON_REPEAT) -#define OSCILLOSCOPE_PAUSE BUTTON_PLAY -#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT -#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT -#define OSCILLOSCOPE_VOL_UP BUTTON_UP -#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define OSCILLOSCOPE_QUIT BUTTON_POWER #define OSCILLOSCOPE_DRAWMODE (BUTTON_MENU | BUTTON_UP) diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h index 1102a01ab1..00cc6b1f59 100644 --- a/apps/plugins/pacbox/pacbox.h +++ b/apps/plugins/pacbox/pacbox.h @@ -169,17 +169,6 @@ #define PACMAN_MENU (BUTTON_MENU|BUTTON_REL) -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define PACMAN_UP BUTTON_UP -#define PACMAN_DOWN BUTTON_DOWN -#define PACMAN_LEFT BUTTON_LEFT -#define PACMAN_RIGHT BUTTON_RIGHT -#define PACMAN_1UP BUTTON_CUSTOM -#define PACMAN_2UP BUTTON_PLAY -#define PACMAN_COIN BUTTON_SELECT -#define PACMAN_MENU BUTTON_MENU - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define PACMAN_UP BUTTON_UP diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c index 8547df603b..832ebc49f7 100644 --- a/apps/plugins/pegbox.c +++ b/apps/plugins/pegbox.c @@ -271,23 +271,6 @@ #define QUIT_TEXT "POWER" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define PEGBOX_SELECT BUTTON_CUSTOM -#define PEGBOX_QUIT BUTTON_BACK -#define PEGBOX_RESTART BUTTON_SELECT -#define PEGBOX_LVL_UP BUTTON_PLAY -#define PEGBOX_LVL_DOWN BUTTON_MENU -#define PEGBOX_UP BUTTON_UP -#define PEGBOX_DOWN BUTTON_DOWN -#define PEGBOX_RIGHT BUTTON_RIGHT -#define PEGBOX_LEFT BUTTON_LEFT - -#define SELECT_TEXT "CUSTOM" -#define QUIT_TEXT "BACK" -#define RESTART_TEXT "MIDDLE" -#define LVL_UP_TEXT "SELECT" -#define LVL_DOWN_TEXT "MENU" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define PEGBOX_SELECT (BUTTON_PLAY|BUTTON_REL) #define PEGBOX_QUIT BUTTON_POWER diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 9ccb73f5ea..259b95f5f0 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -126,8 +126,7 @@ const struct button_mapping pf_context_buttons[] = {PF_SELECT, BUTTON_CENTER, BUTTON_NONE}, {PF_BACK, BUTTON_BOTTOMRIGHT, BUTTON_NONE}, #endif -#if CONFIG_KEYPAD == CREATIVEZV_PAD || CONFIG_KEYPAD == CREATIVEZVM_PAD || \ - CONFIG_KEYPAD == PHILIPS_HDD1630_PAD || \ +#if CONFIG_KEYPAD == PHILIPS_HDD1630_PAD || \ CONFIG_KEYPAD == GIGABEAT_PAD || CONFIG_KEYPAD == GIGABEAT_S_PAD || \ CONFIG_KEYPAD == MROBE100_PAD || CONFIG_KEYPAD == MROBE500_PAD || \ CONFIG_KEYPAD == PHILIPS_SA9200_PAD || CONFIG_KEYPAD == SANSA_CLIP_PAD || \ diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c index 8f409712b6..c9addff347 100644 --- a/apps/plugins/pong.c +++ b/apps/plugins/pong.c @@ -139,13 +139,6 @@ #elif (CONFIG_KEYPAD == COWON_D2_PAD) #define PONG_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define PONG_QUIT BUTTON_BACK -#define PONG_LEFT_UP BUTTON_UP -#define PONG_LEFT_DOWN BUTTON_DOWN -#define PONG_RIGHT_UP BUTTON_PLAY -#define PONG_RIGHT_DOWN BUTTON_MENU - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) #define PONG_QUIT BUTTON_POWER #define PONG_PAUSE BUTTON_PLAY diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h index 8bf5475164..389d190169 100644 --- a/apps/plugins/reversi/reversi-gui.h +++ b/apps/plugins/reversi/reversi-gui.h @@ -136,15 +136,6 @@ #define REVERSI_BUTTON_QUIT BUTTON_POWER #define REVERSI_BUTTON_MENU BUTTON_MENU -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define REVERSI_BUTTON_QUIT BUTTON_BACK -#define REVERSI_BUTTON_UP BUTTON_UP -#define REVERSI_BUTTON_DOWN BUTTON_DOWN -#define REVERSI_BUTTON_LEFT BUTTON_LEFT -#define REVERSI_BUTTON_RIGHT BUTTON_RIGHT -#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT -#define REVERSI_BUTTON_MENU BUTTON_MENU - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define REVERSI_BUTTON_QUIT BUTTON_POWER #define REVERSI_BUTTON_UP BUTTON_UP diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c index d2887af78f..a657dde2d7 100644 --- a/apps/plugins/rockblox.c +++ b/apps/plugins/rockblox.c @@ -195,16 +195,6 @@ #define ROCKBLOX_OFF BUTTON_POWER #define ROCKBLOX_RESTART BUTTON_MENU -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define ROCKBLOX_OFF BUTTON_BACK -#define ROCKBLOX_ROTATE_CCW BUTTON_UP -#define ROCKBLOX_ROTATE_CW BUTTON_PLAY -#define ROCKBLOX_DOWN BUTTON_DOWN -#define ROCKBLOX_LEFT BUTTON_LEFT -#define ROCKBLOX_RIGHT BUTTON_RIGHT -#define ROCKBLOX_DROP BUTTON_SELECT -#define ROCKBLOX_RESTART BUTTON_CUSTOM - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define ROCKBLOX_OFF BUTTON_POWER #define ROCKBLOX_ROTATE_CCW BUTTON_VOL_DOWN diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index 7cca8d9130..3cb4ba6771 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c @@ -210,16 +210,6 @@ static void setoptions (void) options.SELECT = BUTTON_SELECT; options.MENU = BUTTON_MENU; -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - options.UP = BUTTON_UP; - options.DOWN = BUTTON_DOWN; - - options.A = BUTTON_CUSTOM; - options.B = BUTTON_PLAY; - options.START = BUTTON_BACK; - options.SELECT = BUTTON_SELECT; - options.MENU = BUTTON_MENU; - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD options.UP = BUTTON_UP; options.DOWN = BUTTON_DOWN; diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index c821cd234d..8c7d05c00d 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -134,17 +134,6 @@ #define ROCKPAINT_QUIT BUTTON_POWER #define ROCKPAINT_MENU BUTTON_MENU -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define ROCKPAINT_QUIT BUTTON_BACK -#define ROCKPAINT_DRAW BUTTON_SELECT -#define ROCKPAINT_MENU BUTTON_MENU -#define ROCKPAINT_TOOLBAR BUTTON_PLAY -#define ROCKPAINT_TOOLBAR2 ( BUTTON_PLAY | BUTTON_LEFT ) -#define ROCKPAINT_UP BUTTON_UP -#define ROCKPAINT_DOWN BUTTON_DOWN -#define ROCKPAINT_LEFT BUTTON_LEFT -#define ROCKPAINT_RIGHT BUTTON_RIGHT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define ROCKPAINT_QUIT BUTTON_POWER #define ROCKPAINT_DRAW BUTTON_VOL_UP diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c index 273a178c2d..63121edba1 100644 --- a/apps/plugins/sliding_puzzle.c +++ b/apps/plugins/sliding_puzzle.c @@ -140,15 +140,6 @@ #define PUZZLE_QUIT BUTTON_POWER #define PUZZLE_QUIT_TEXT "[POWER]" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define PUZZLE_QUIT BUTTON_BACK -#define PUZZLE_LEFT BUTTON_LEFT -#define PUZZLE_RIGHT BUTTON_RIGHT -#define PUZZLE_UP BUTTON_UP -#define PUZZLE_DOWN BUTTON_DOWN -#define PUZZLE_SHUFFLE BUTTON_PLAY -#define PUZZLE_PICTURE BUTTON_MENU - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) #define PUZZLE_QUIT BUTTON_POWER #define PUZZLE_LEFT BUTTON_BACK diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c index 23842e443c..4055087159 100644 --- a/apps/plugins/snake.c +++ b/apps/plugins/snake.c @@ -133,14 +133,6 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left; #define SNAKE_RC_QUIT BUTTON_REC -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define SNAKE_QUIT BUTTON_BACK -#define SNAKE_LEFT BUTTON_LEFT -#define SNAKE_RIGHT BUTTON_RIGHT -#define SNAKE_UP BUTTON_UP -#define SNAKE_DOWN BUTTON_DOWN -#define SNAKE_PLAYPAUSE BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define SNAKE_QUIT BUTTON_POWER #define SNAKE_LEFT BUTTON_BACK diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c index 864cda688a..d8a97f159f 100644 --- a/apps/plugins/snake2.c +++ b/apps/plugins/snake2.c @@ -265,15 +265,6 @@ Head and Tail are stored #elif (CONFIG_KEYPAD == COWON_D2_PAD) #define SNAKE2_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define SNAKE2_LEFT BUTTON_LEFT -#define SNAKE2_RIGHT BUTTON_RIGHT -#define SNAKE2_UP BUTTON_UP -#define SNAKE2_DOWN BUTTON_DOWN -#define SNAKE2_QUIT BUTTON_BACK -#define SNAKE2_PLAYPAUSE BUTTON_PLAY -#define SNAKE2_PLAYPAUSE_TEXT "Play" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define SNAKE2_LEFT BUTTON_BACK #define SNAKE2_RIGHT BUTTON_MENU diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c index 1d61ba1749..7b6e79f70b 100644 --- a/apps/plugins/sokoban.c +++ b/apps/plugins/sokoban.c @@ -312,21 +312,6 @@ #define SOKOBAN_LEVEL_UP BUTTON_PLUS #define SOKOBAN_MENU_NAME "[MENU]" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define SOKOBAN_LEFT BUTTON_LEFT -#define SOKOBAN_RIGHT BUTTON_RIGHT -#define SOKOBAN_UP BUTTON_UP -#define SOKOBAN_DOWN BUTTON_DOWN -#define SOKOBAN_MENU BUTTON_MENU -#define SOKOBAN_UNDO BUTTON_BACK -#define SOKOBAN_REDO (BUTTON_BACK | BUTTON_PLAY) -#define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_DOWN) -#define SOKOBAN_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_RIGHT) -#define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_UP) -#define SOKOBAN_PAUSE BUTTON_PLAY -#define BUTTON_SAVE BUTTON_CUSTOM -#define BUTTON_SAVE_NAME "CUSTOM" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define SOKOBAN_LEFT BUTTON_BACK #define SOKOBAN_RIGHT BUTTON_MENU diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c index 07cebef043..6205c186ca 100644 --- a/apps/plugins/solitaire.c +++ b/apps/plugins/solitaire.c @@ -295,24 +295,6 @@ #elif (CONFIG_KEYPAD == COWON_D2_PAD) # define SOL_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -# define SOL_QUIT BUTTON_BACK -# define SOL_UP BUTTON_UP -# define SOL_DOWN BUTTON_DOWN -# define SOL_LEFT BUTTON_LEFT -# define SOL_RIGHT BUTTON_RIGHT -# define SOL_MOVE_PRE BUTTON_SELECT -# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL) -# define SOL_DRAW BUTTON_MENU -# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_SELECT) -# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT) -# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_SELECT) -# define HK_MOVE "MIDDLE" -# define HK_DRAW "MENU" -# define HK_REM2CUR "PLAY+LEFT" -# define HK_CUR2STACK "PLAY.." -# define HK_REM2STACK "PLAY+RIGHT" - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) # define SOL_QUIT BUTTON_POWER # define SOL_UP BUTTON_UP diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c index f543065f27..38ee7504ac 100644 --- a/apps/plugins/spacerocks.c +++ b/apps/plugins/spacerocks.c @@ -152,15 +152,6 @@ #elif (CONFIG_KEYPAD == COWON_D2_PAD) #define AST_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define AST_PAUSE BUTTON_PLAY -#define AST_QUIT BUTTON_BACK -#define AST_THRUST BUTTON_UP -#define AST_HYPERSPACE BUTTON_DOWN -#define AST_LEFT BUTTON_LEFT -#define AST_RIGHT BUTTON_RIGHT -#define AST_FIRE BUTTON_SELECT - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define AST_PAUSE (BUTTON_PLAY | BUTTON_REL) #define AST_QUIT BUTTON_POWER diff --git a/apps/plugins/star.c b/apps/plugins/star.c index 5a7cff70ef..856a2af51a 100644 --- a/apps/plugins/star.c +++ b/apps/plugins/star.c @@ -242,23 +242,6 @@ #define STAR_QUIT BUTTON_POWER #define STAR_QUIT_NAME "POWER" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define STAR_QUIT BUTTON_BACK -#define STAR_LEFT BUTTON_LEFT -#define STAR_RIGHT BUTTON_RIGHT -#define STAR_UP BUTTON_UP -#define STAR_DOWN BUTTON_DOWN -#define STAR_TOGGLE_CONTROL BUTTON_PLAY -#define STAR_LEVEL_UP (BUTTON_CUSTOM | BUTTON_UP) -#define STAR_LEVEL_DOWN (BUTTON_CUSTOM | BUTTON_DOWN) -#define STAR_LEVEL_REPEAT (BUTTON_CUSTOM | BUTTON_RIGHT) -#define STAR_TOGGLE_CONTROL_NAME "PLAY" -#define STAR_QUIT_NAME "BACK" -#define STAR_LEVEL_UP_NAME "CUSTOM+UP" -#define STAR_LEVEL_DOWN_NAME "CUSTOM+DOWN" -#define STAR_LEVEL_REPEAT_NAME "CUSTOM+RIGHT" - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define STAR_QUIT BUTTON_POWER diff --git a/apps/plugins/stopwatch.c b/apps/plugins/stopwatch.c index 7a9737815f..d7ae418611 100644 --- a/apps/plugins/stopwatch.c +++ b/apps/plugins/stopwatch.c @@ -123,14 +123,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define STOPWATCH_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define STOPWATCH_QUIT BUTTON_BACK -#define STOPWATCH_START_STOP BUTTON_PLAY -#define STOPWATCH_RESET_TIMER BUTTON_SELECT -#define STOPWATCH_LAP_TIMER BUTTON_CUSTOM -#define STOPWATCH_SCROLL_UP BUTTON_UP -#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define STOPWATCH_QUIT BUTTON_POWER #define STOPWATCH_START_STOP (BUTTON_PLAY|BUTTON_REL) diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h index 2ed792872a..8df6fcb870 100644 --- a/apps/plugins/sudoku/sudoku.h +++ b/apps/plugins/sudoku/sudoku.h @@ -181,16 +181,6 @@ #define SUDOKU_BUTTON_QUIT BUTTON_POWER #define SUDOKU_BUTTON_MENU BUTTON_MENU -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define SUDOKU_BUTTON_QUIT BUTTON_BACK -#define SUDOKU_BUTTON_UP BUTTON_UP -#define SUDOKU_BUTTON_DOWN BUTTON_DOWN -#define SUDOKU_BUTTON_LEFT BUTTON_LEFT -#define SUDOKU_BUTTON_RIGHT BUTTON_RIGHT -#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT -#define SUDOKU_BUTTON_MENU BUTTON_MENU -#define SUDOKU_BUTTON_POSSIBLE BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define SUDOKU_BUTTON_QUIT BUTTON_POWER #define SUDOKU_BUTTON_UP BUTTON_UP diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h index 10a2b3ee3e..a7a38221d0 100644 --- a/apps/plugins/text_viewer/tv_button.h +++ b/apps/plugins/text_viewer/tv_button.h @@ -236,17 +236,6 @@ #define TV_SCROLL_DOWN BUTTON_PLUS #define TV_BOOKMARK (BUTTON_MENU|BUTTON_PLUS) -/* Creative Zen Vision:M keys */ -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define TV_QUIT BUTTON_BACK -#define TV_SCROLL_UP BUTTON_UP -#define TV_SCROLL_DOWN BUTTON_DOWN -#define TV_SCREEN_LEFT BUTTON_LEFT -#define TV_SCREEN_RIGHT BUTTON_RIGHT -#define TV_MENU BUTTON_MENU -#define TV_AUTOSCROLL BUTTON_SELECT -#define TV_BOOKMARK BUTTON_PLAY - /* Creative Zen X-Fi3 keys */ #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define TV_QUIT BUTTON_POWER diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index f52ac140fe..d18b6a658c 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c @@ -181,17 +181,6 @@ #define LABEL_QUIT "POWER" #define LABEL_MENU "MENU" -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define VUMETER_QUIT BUTTON_BACK -#define VUMETER_HELP BUTTON_SELECT -#define VUMETER_MENU BUTTON_MENU -#define VUMETER_UP BUTTON_UP -#define VUMETER_DOWN BUTTON_DOWN -#define LABEL_HELP "MIDDLE" -#define LABEL_QUIT "BACK" -#define LABEL_MENU "MENU" -#define LABEL_VOLUME "UP/DOWN" - #elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) #define VUMETER_QUIT BUTTON_POWER #define VUMETER_HELP BUTTON_MENU|BUTTON_REPEAT diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c index 5002ca8790..c02234d500 100644 --- a/apps/plugins/wormlet.c +++ b/apps/plugins/wormlet.c @@ -175,16 +175,6 @@ static long max_cycle; #define BTN_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define BTN_DIR_UP BUTTON_UP -#define BTN_DIR_DOWN BUTTON_DOWN -#define BTN_DIR_LEFT BUTTON_LEFT -#define BTN_DIR_RIGHT BUTTON_RIGHT -#define BTN_STARTPAUSE BUTTON_PLAY -#define BTN_QUIT BUTTON_BACK -#define BTN_STOPRESET BUTTON_MENU - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define BTN_DIR_UP BUTTON_UP diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c index b8b883709f..f82cde1c32 100644 --- a/apps/plugins/xobox.c +++ b/apps/plugins/xobox.c @@ -146,15 +146,6 @@ #define QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define QUIT BUTTON_BACK -#define LEFT BUTTON_LEFT -#define RIGHT BUTTON_RIGHT -#define UP BUTTON_UP -#define DOWN BUTTON_DOWN -#define PAUSE BUTTON_PLAY - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define QUIT BUTTON_POWER #define LEFT BUTTON_BACK diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h index 94472d4e15..0bb7d3e80f 100644 --- a/apps/plugins/zxbox/keymaps.h +++ b/apps/plugins/zxbox/keymaps.h @@ -102,14 +102,6 @@ #elif CONFIG_KEYPAD == COWON_D2_PAD #define ZX_MENU (BUTTON_MENU|BUTTON_REL) -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD -#define ZX_UP BUTTON_UP -#define ZX_DOWN BUTTON_DOWN -#define ZX_LEFT BUTTON_LEFT -#define ZX_RIGHT BUTTON_RIGHT -#define ZX_SELECT BUTTON_SELECT -#define ZX_MENU BUTTON_MENU - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define ZX_UP BUTTON_UP #define ZX_DOWN BUTTON_DOWN diff --git a/apps/plugins/zxbox/zxbox_keyb.c b/apps/plugins/zxbox/zxbox_keyb.c index 2eb7feaa06..6a5c2a6c81 100644 --- a/apps/plugins/zxbox/zxbox_keyb.c +++ b/apps/plugins/zxbox/zxbox_keyb.c @@ -102,15 +102,6 @@ #define KBD_ABORT BUTTON_POWER -#elif CONFIG_KEYPAD == CREATIVEZVM_PAD - -#define KBD_SELECT BUTTON_SELECT -#define KBD_ABORT BUTTON_BACK -#define KBD_LEFT BUTTON_LEFT -#define KBD_RIGHT BUTTON_RIGHT -#define KBD_UP BUTTON_UP -#define KBD_DOWN BUTTON_DOWN - #elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD #define KBD_SELECT (BUTTON_PLAY|BUTTON_REL) diff --git a/bootloader/SOURCES b/bootloader/SOURCES index ff6a6b8d6f..8510479739 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -46,8 +46,6 @@ show_logo.c #elif defined(XDUOO_X3) xduoox3.c show_logo.c -#elif defined(CREATIVE_ZVx) -creativezvm.c #elif CONFIG_CPU==AS3525 || CONFIG_CPU==AS3525v2 sansa_as3525.c show_logo.c diff --git a/bootloader/creativezvm.c b/bootloader/creativezvm.c deleted file mode 100644 index db7a8c7459..0000000000 --- a/bootloader/creativezvm.c +++ /dev/null @@ -1,120 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2008 by Maurus Cuelenaere -* -* All files in this archive are subject to the GNU General Public License. -* See the file COPYING in the source tree root for full license agreement. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include "system.h" -#include "lcd.h" -#include "../kernel-internal.h" -#include "storage.h" -#include "ata-target.h" -#include "file_internal.h" -#include "disk.h" -#include "font.h" -#include "backlight.h" -#include "button.h" -#include "common.h" -#include "loader_strerror.h" -#include "rb-loader.h" -#include "usb.h" -#include "version.h" - - -static void load_fw(unsigned char* ptr, unsigned int len) -{ - (void)ptr; - (void)len; - asm volatile("ldr pc, =0x1EE0000"); -} - -void main(void) -{ - unsigned char* loadbuffer; - int buffer_size; - int(*kernel_entry)(void); - int ret; - - /* Make sure interrupts are disabled */ - set_irq_level(IRQ_DISABLED); - set_fiq_status(FIQ_DISABLED); - system_init(); - kernel_init(); - - /* Now enable interrupts */ - set_irq_level(IRQ_ENABLED); - set_fiq_status(FIQ_ENABLED); - lcd_init(); - backlight_init(); /* BUGFIX backlight_init MUST BE AFTER lcd_init */ - font_init(); - button_init(); - usb_init(); - -#ifdef HAVE_LCD_ENABLE - lcd_enable(true); -#endif - lcd_setfont(FONT_SYSFIXED); - reset_screen(); - printf("Rockbox boot loader"); - printf("Version %s", rbversion); - - ret = storage_init(); - if(ret) - printf("ATA error: %d", ret); - - filesystem_init(); - - /* If no button is held, start the OF */ - if(button_read_device() == 0) - { - printf("Loading Creative firmware..."); - - loadbuffer = (unsigned char*)0x00A00000; - ret = load_minifs_file("creativeos.jrm", loadbuffer); - if(ret != -1) - { - set_irq_level(IRQ_DISABLED); - set_fiq_status(FIQ_DISABLED); - /* Doesn't return! */ - load_fw(loadbuffer, ret); - } - else - printf("FAILED!"); - } - else - { - ret = disk_mount_all(); - if (ret <= 0) - error(EDISK, ret, true); - - printf("Loading Rockbox firmware..."); - - loadbuffer = (unsigned char*)0x00900000; - buffer_size = (unsigned char*)0x01900000 - loadbuffer; - - ret = load_firmware(loadbuffer, BOOTFILE, buffer_size); - if(ret <= EFILE_EMPTY) - error(EBOOTFILE, ret, true); - - kernel_entry = (void*) loadbuffer; - ret = kernel_entry(); - printf("FAILED!"); - } - - storage_sleepnow(); - - while(1); -} diff --git a/firmware/SOURCES b/firmware/SOURCES index 4fa1cfaaf1..c992b2010c 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1304,19 +1304,6 @@ target/arm/tms320dm320/mrobe-500/power-mr500.c target/arm/tms320dm320/mrobe-500/usb-mr500.c #endif /* MROBE_500 */ -#ifdef CREATIVE_ZVx -drivers/lcd-memframe.c -target/arm/tms320dm320/creative-zvm/adc-creativezvm.c -target/arm/tms320dm320/creative-zvm/ata-creativezvm.c -target/arm/tms320dm320/creative-zvm/dma-creativezvm.c -target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c -target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c -target/arm/tms320dm320/creative-zvm/pic-creativezvm.c -target/arm/tms320dm320/creative-zvm/power-creativezvm.c -target/arm/tms320dm320/creative-zvm/powermgmt-creativezvm.c -target/arm/tms320dm320/creative-zvm/usb-creativezvm.c -#endif /* CREATIVE_ZVx */ - #if defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(CREATIVE_ZENMOZAIC) \ || defined(CREATIVE_ZENV) || defined(CREATIVE_ZENXFISTYLE) #ifndef BOOTLOADER diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index ea1cf94cfa..463c120213 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES @@ -49,7 +49,7 @@ mempcpy.c #endif #if (defined(SANSA_E200) || defined(GIGABEAT_F) || defined(GIGABEAT_S) || \ - defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ + defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ defined(COWON_D2) || defined(SAMSUNG_YPR0) || \ defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \ defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || \ diff --git a/firmware/drivers/audio/tlv320.c b/firmware/drivers/audio/tlv320.c index c4c748d527..19212155b1 100644 --- a/firmware/drivers/audio/tlv320.c +++ b/firmware/drivers/audio/tlv320.c @@ -50,11 +50,7 @@ static int vol_tenthdb2hw(int db) } /* local functions and definations */ -#ifndef CREATIVE_ZVx #define TLV320_ADDR 0x34 -#else -#define TLV320_ADDR 0x1A -#endif static struct tlv320_info { @@ -133,11 +129,7 @@ void audiohw_init(void) audiohw_mute(true); tlv320_write_reg(REG_AAP, AAP_DAC | AAP_MICM); tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ -#ifndef CREATIVE_ZVx tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S); -#else - tlv320_write_reg(REG_DAIF, DAIF_IWL_32 | DAIF_FOR_DSP); -#endif tlv320_write_reg(REG_DIA, DIA_ACT); audiohw_set_frequency(-1); /* default */ } diff --git a/firmware/export/config.h b/firmware/export/config.h index e43dce9568..261b2d7402 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -112,9 +112,7 @@ #define GIGABEAT_S_PAD 19 #define COWON_D2_PAD 22 #define IAUDIO_M3_PAD 23 -#define CREATIVEZVM_PAD 24 #define SANSA_M200_PAD 25 -#define CREATIVEZV_PAD 26 #define PHILIPS_SA9200_PAD 27 #define PHILIPS_HDD1630_PAD 29 #define ONDAVX747_PAD 31 @@ -233,7 +231,6 @@ #define LCD_C200 17 /* as used by Sandisk Sansa c200 */ #define LCD_MROBE500 18 /* as used by Olympus M:Robe 500i */ #define LCD_MROBE100 19 /* as used by Olympus M:Robe 100 */ -#define LCD_CREATIVEZVM 22 /* as used by Creative Zen Vision:M */ #define LCD_TL0350A 23 /* as used by the iAudio M3 remote, treated as main LCD */ #define LCD_COWOND2 24 /* as used by Cowon D2 - LTV250QV, TCC7801 driver */ #define LCD_SA9200 25 /* as used by the Philips SA9200 */ @@ -438,12 +435,6 @@ Lyre prototype 1 */ #include "config/mrobe500.h" #elif defined(COWON_D2) #include "config/cowond2.h" -#elif defined(CREATIVE_ZVM) -#include "config/zenvisionm30gb.h" -#elif defined(CREATIVE_ZVM60GB) -#include "config/zenvisionm60gb.h" -#elif defined(CREATIVE_ZV) -#include "config/zenvision.h" #elif defined(CREATIVE_ZENXFI2) #include "config/creativezenxfi2.h" #elif defined(CREATIVE_ZENXFI3) diff --git a/firmware/export/config/zenvision.h b/firmware/export/config/zenvision.h deleted file mode 100644 index eb94c84ca7..0000000000 --- a/firmware/export/config/zenvision.h +++ /dev/null @@ -1,166 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * This config file is for the Creative Zen Vision - */ - -#define CONFIG_SDRAM_START 0x00900000 - -#define CREATIVE_ZV 1 - -#define MODEL_NAME "Creative Zen Vision" - -/* This makes it part of the Creative Zen Vision family :) */ -#define CREATIVE_ZVx 1 - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 28 - -/* define this if you use an ATA controller */ -#define CONFIG_STORAGE STORAGE_ATA - -/*define this if the ATA controller and method of USB access support LBA48 */ -#define HAVE_LBA48 - - - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if the target has volume keys which can be used in the lists */ -//#define HAVE_VOLUME_IN_LIST - -/* LCD dimensions */ -#define CONFIG_LCD LCD_CREATIVEZVM - -/* choose the lcd orientation. both work */ -#define CONFIG_ORIENTATION SCREEN_PORTRAIT - -#define LCD_WIDTH 640 -#define LCD_HEIGHT 480 -/* sqrt(640^2 + 480^2) / 2.5 = 320.0 */ -#define LCD_DPI 320 - -#define LCD_DEPTH 16 /* 65k colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -#define HAVE_LCD_ENABLE - -#define CONFIG_KEYPAD CREATIVEZV_PAD -#define HAVE_HEADPHONE_DETECTION -//#define HAVE_TOUCHPAD - -/* Define this to enable morse code input */ -#define HAVE_MORSE_INPUT - - - - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC RTC_RX5X348AB - -/* define this if you have a disk storage, i.e. something - that needs spinups and can cause skips when shaked */ -#define HAVE_DISK_STORAGE - -/* Define this for LCD backlight available */ -//#define HAVE_BACKLIGHT - -//#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Main LCD backlight brightness range and defaults */ -//#define MIN_BRIGHTNESS_SETTING 0 -//#define MAX_BRIGHTNESS_SETTING 127 -//#define DEFAULT_BRIGHTNESS_SETTING 85 /* OF "full brightness" */ -//#define DEFAULT_DIMNESS_SETTING 22 /* OF "most dim" */ - -/* Define this if you have a software controlled poweroff */ -//#define HAVE_SW_POWEROFF -//TODO: enable this back - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x100000 - -/* Define this if you have the TLV320 audio codec -> controlled by the DSP */ -#define HAVE_TLV320 - -#define CONFIG_I2C I2C_DM320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -/*#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ - SAMPR_CAP_11)*/ - -#define BATTERY_CAPACITY_DEFAULT 1250 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 100 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging with monitoring */ -//#define CONFIG_CHARGING CHARGING_MONITOR - -/* Define this if you have a TI TMS320DM320 */ -#define CONFIG_CPU DM320 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 16934400 - -/* Define this if you have ATA power-off control */ -#define HAVE_ATA_POWER_OFF - -/* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ */ - -#define BOOTFILE_EXT "zv" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define CONFIG_USBOTG USBOTG_ISP1583 -#define HAVE_USBSTACK -//#define HAVE_BOOTLOADER_USB_MODE -#define USB_VENDOR_ID 0x041e -#define USB_PRODUCT_ID 0x4133 -#define USB_NUM_ENDPOINTS 7 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/export/config/zenvisionm30gb.h b/firmware/export/config/zenvisionm30gb.h deleted file mode 100644 index 236a153a3c..0000000000 --- a/firmware/export/config/zenvisionm30gb.h +++ /dev/null @@ -1,175 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * This config file is for the Creative Zen Vision:M - */ - -#define CONFIG_SDRAM_START 0x00900000 - -#define CREATIVE_ZVM 1 - -#define MODEL_NAME "Creative Zen Vision:M" - -/* This makes it part of the Creative Zen Vision family :) */ -#define CREATIVE_ZVx 1 - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 26 - -/* define this if you use an ATA controller */ -#define CONFIG_STORAGE STORAGE_ATA - -/*define this if the ATA controller and method of USB access support LBA48 */ -#define HAVE_LBA48 - - - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if the target has volume keys which can be used in the lists */ -//#define HAVE_VOLUME_IN_LIST - -/* LCD dimensions */ -#define CONFIG_LCD LCD_CREATIVEZVM - -/* choose the lcd orientation. both work */ -#define CONFIG_ORIENTATION SCREEN_PORTRAIT - -#define LCD_WIDTH 320 -#define LCD_HEIGHT 240 -/* sqrt(320^2 + 240^2) / 2.5 = 160.0 */ -#define LCD_DPI 160 - -#define LCD_DEPTH 16 /* 65k colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -/* Disabled until properly working -#define HAVE_LCD_ENABLE */ - -#define CONFIG_KEYPAD CREATIVEZVM_PAD -#define HAVE_HEADPHONE_DETECTION -//#define HAVE_TOUCHPAD - -/* Define this to enable morse code input */ -#define HAVE_MORSE_INPUT - - - - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC RTC_RX5X348AB - -/* define this if you have a disk storage, i.e. something - that needs spinups and can cause skips when shaked */ -#define HAVE_DISK_STORAGE - -/* Define this for LCD backlight available */ -//#define HAVE_BACKLIGHT - -//#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Main LCD backlight brightness range and defaults */ -//#define MIN_BRIGHTNESS_SETTING 0 -//#define MAX_BRIGHTNESS_SETTING 127 -//#define DEFAULT_BRIGHTNESS_SETTING 85 /* OF "full brightness" */ -//#define DEFAULT_DIMNESS_SETTING 22 /* OF "most dim" */ - -/* Define this if you have a software controlled poweroff */ -//#define HAVE_SW_POWEROFF -//TODO: enable this back - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x100000 - -/* Define this if you have the TLV320 audio codec -> controlled by the DSP */ -#define HAVE_TLV320 - -#define CONFIG_I2C I2C_DM320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -/*#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ - SAMPR_CAP_11)*/ - -#define BATTERY_CAPACITY_DEFAULT 1250 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 100 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging with monitoring */ -//#define CONFIG_CHARGING CHARGING_MONITOR - -/* Define this if you have a TI TMS320DM320 */ -#define CONFIG_CPU DM320 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 16934400 - -/* Define this if you have ATA power-off control */ -#define HAVE_ATA_POWER_OFF - -/* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ */ - -#define BOOTFILE_EXT "zvm" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -#define CONFIG_USBOTG USBOTG_ISP1583 -#define HAVE_USBSTACK -//#define HAVE_BOOTLOADER_USB_MODE -#define USB_VENDOR_ID 0x041e -#define USB_PRODUCT_ID 0x4133 -#define USB_NUM_ENDPOINTS 7 - -/*DEBUGGING!*/ -/* -#define THREAD_EXTRA_CHECKS 1 -#define DEBUG 1 -#define debug(msg) printf(msg) -#define BUTTON_DEBUG -*/ - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/export/config/zenvisionm60gb.h b/firmware/export/config/zenvisionm60gb.h deleted file mode 100644 index 64f6925328..0000000000 --- a/firmware/export/config/zenvisionm60gb.h +++ /dev/null @@ -1,167 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -/* - * This config file is for the Creative Zen Vision:M 60GB - */ - -#define CONFIG_SDRAM_START 0x00900000 - -#define CREATIVE_ZVM60GB 1 - -#define MODEL_NAME "Creative Zen Vision:M 60GB" - -/* This makes it part of the Creative Zen Vision family :) */ -#define CREATIVE_ZVx 1 - -/* For Rolo and boot loader */ -#define MODEL_NUMBER 27 - -/* define this if you use an ATA controller */ -#define CONFIG_STORAGE STORAGE_ATA - -/*define this if the ATA controller and method of USB access support LBA48 */ -#define HAVE_LBA48 - - - - -/* define this if you have a colour LCD */ -#define HAVE_LCD_COLOR - -/* define this if you have access to the quickscreen */ -#define HAVE_QUICKSCREEN - -/* define this if you would like tagcache to build on this target */ -#define HAVE_TAGCACHE - -/* define this if the target has volume keys which can be used in the lists */ -//#define HAVE_VOLUME_IN_LIST - -/* LCD dimensions */ -#define CONFIG_LCD LCD_CREATIVEZVM - -/* choose the lcd orientation. both work */ -#define CONFIG_ORIENTATION SCREEN_PORTRAIT - -#define LCD_WIDTH 320 -#define LCD_HEIGHT 240 -/* sqrt(320^2 + 240^2) / 2.5 = 160.0 */ -#define LCD_DPI 160 - -#define LCD_DEPTH 16 /* 65k colours */ -#define LCD_PIXELFORMAT RGB565 /* rgb565 */ - -/* Define this if your LCD can be enabled/disabled */ -#define HAVE_LCD_ENABLE - -#define CONFIG_KEYPAD CREATIVEZVM_PAD -#define HAVE_HEADPHONE_DETECTION -//#define HAVE_TOUCHPAD - -/* Define this to enable morse code input */ -#define HAVE_MORSE_INPUT - - - - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC RTC_RX5X348AB - -/* define this if you have a disk storage, i.e. something - that needs spinups and can cause skips when shaked */ -#define HAVE_DISK_STORAGE - -/* Define this for LCD backlight available */ -//#define HAVE_BACKLIGHT - -//#define HAVE_BACKLIGHT_BRIGHTNESS - -/* Main LCD backlight brightness range and defaults */ -//#define MIN_BRIGHTNESS_SETTING 0 -//#define MAX_BRIGHTNESS_SETTING 127 -//#define DEFAULT_BRIGHTNESS_SETTING 85 /* OF "full brightness" */ -//#define DEFAULT_DIMNESS_SETTING 22 /* OF "most dim" */ - -/* Define this if you have a software controlled poweroff */ -//#define HAVE_SW_POWEROFF -//TODO: enable this back - -/* The number of bytes reserved for loadable codecs */ -#define CODEC_SIZE 0x100000 - -/* The number of bytes reserved for loadable plugins */ -#define PLUGIN_BUFFER_SIZE 0x100000 - -/* Define this if you have the TLV320 audio codec -> controlled by the DSP */ -#define HAVE_TLV320 - -#define CONFIG_I2C I2C_DM320 - -/* TLV320 has no tone controls, so we use the software ones */ -#define HAVE_SW_TONE_CONTROLS - -/*#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ - SAMPR_CAP_11)*/ - -#define BATTERY_CAPACITY_DEFAULT 1250 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 500 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 2500 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 100 /* capacity increment */ - - -#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE - -/* Hardware controlled charging with monitoring */ -//#define CONFIG_CHARGING CHARGING_MONITOR - -/* Define this if you have a TI TMS320DM320 */ -#define CONFIG_CPU DM320 - -/* define this if the hardware can be powered off while charging */ -#define HAVE_POWEROFF_WHILE_CHARGING - -/* The size of the flash ROM */ -#define FLASH_SIZE 0x400000 - -/* Define this to the CPU frequency */ -#define CPU_FREQ 16934400 - -/* Define this if you have ATA power-off control */ -#define HAVE_ATA_POWER_OFF - -/* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ */ - -#define BOOTFILE_EXT "zvm60" -#define BOOTFILE "rockbox." BOOTFILE_EXT -#define BOOTDIR "/.rockbox" - -/* #define CONFIG_USBOTG USBOTG_ISP1761 */ -#define CONFIG_USBOTG USBOTG_ISP1583 -#define HAVE_USBSTACK -//#define HAVE_BOOTLOADER_USB_MODE -#define USB_VENDOR_ID 0x041e -#define USB_PRODUCT_ID 0x4133 -#define USB_NUM_ENDPOINTS 7 - -/* Define this if a programmable hotkey is mapped */ -#define HAVE_HOTKEY diff --git a/firmware/target/arm/ata-as-arm.S b/firmware/target/arm/ata-as-arm.S index cec4a7e235..4b4701f7fa 100644 --- a/firmware/target/arm/ata-as-arm.S +++ b/firmware/target/arm/ata-as-arm.S @@ -36,9 +36,6 @@ /* Untested */ .text .equ .ata_port, 0x18000000 -#elif defined(CREATIVE_ZVx) /* Zen Vision could have an other address */ - .text - .equ .ata_port, 0x50FEE000 #elif defined(MROBE_500) .text .equ .ata_port, 0x50400000 diff --git a/firmware/target/arm/system-arm-classic.h b/firmware/target/arm/system-arm-classic.h index bc648e43ed..a941a36a7e 100644 --- a/firmware/target/arm/system-arm-classic.h +++ b/firmware/target/arm/system-arm-classic.h @@ -104,18 +104,6 @@ static inline int set_interrupt_status(int status, int mask) unsigned long cpsr; int oldstatus; /* Read the old levels and set the new ones */ -#if defined(CREATIVE_ZVx) && defined(BOOTLOADER) -// FIXME: This workaround is for a problem with inlining; -// for some reason 'mask' gets treated as a variable/non-immediate constant -// but only on this build. All others (including the nearly-identical mrobe500boot) are fine - asm volatile ( - "mrs %1, cpsr \n" - "bic %0, %1, %[mask] \n" - "orr %0, %0, %2 \n" - "msr cpsr_c, %0 \n" - : "=&r,r"(cpsr), "=&r,r"(oldstatus) - : "r,i"(status & mask), [mask]"r,i"(mask)); -#else asm volatile ( "mrs %1, cpsr \n" "bic %0, %1, %[mask] \n" @@ -123,7 +111,6 @@ static inline int set_interrupt_status(int status, int mask) "msr cpsr_c, %0 \n" : "=&r,r"(cpsr), "=&r,r"(oldstatus) : "r,i"(status & mask), [mask]"i,i"(mask)); -#endif return oldstatus; } diff --git a/firmware/target/arm/tms320dm320/creative-zvm/adc-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/adc-creativezvm.c deleted file mode 100644 index e891b98eac..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/adc-creativezvm.c +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: adc-mr500.c 14817 2007-09-22 15:43:38Z kkurbjun $ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "cpu.h" -#include "adc.h" -#include "adc-target.h" -#include "kernel.h" - -void adc_init(void) -{ -} - -/* Called to get the recent ADC reading */ -inline unsigned short adc_read(int channel) -{ - return (short)channel; -} diff --git a/firmware/target/arm/tms320dm320/creative-zvm/adc-target.h b/firmware/target/arm/tms320dm320/creative-zvm/adc-target.h deleted file mode 100644 index bf2c5dfc08..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/adc-target.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: adc-target.h 14817 2007-09-22 15:43:38Z kkurbjun $ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _ADC_TARGET_H_ -#define _ADC_TARGET_H_ - -/* only two channels used by the Gigabeat */ -#define NUM_ADC_CHANNELS 2 - -#define ADC_BATTERY 0 -#define ADC_HPREMOTE 1 -#define ADC_UNKNOWN_3 2 -#define ADC_UNKNOWN_4 3 -#define ADC_UNKNOWN_5 4 -#define ADC_UNKNOWN_6 5 -#define ADC_UNKNOWN_7 6 -#define ADC_UNKNOWN_8 7 - -#define ADC_UNREG_POWER ADC_BATTERY /* For compatibility */ -#define ADC_READ_ERROR 0xFFFF - -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c deleted file mode 100644 index 6936a24873..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/ata-creativezvm.c +++ /dev/null @@ -1,544 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "cpu.h" -#include "kernel.h" -#include "thread.h" -#include "system.h" -#include "power.h" -#include "panic.h" -#include "ata-driver.h" -#include "dm320.h" -#include "ata.h" -#include "string.h" -#include "core_alloc.h" -#include "logf.h" -#include "ata-defines.h" - -#undef ata_read_sectors -#undef ata_write_sectors - -static void sleep_ms(int ms) -{ - sleep(ms*HZ/1000); -} - -void ide_power_enable(bool on) -{ -/* Disabled until figured out what's wrong */ -#if 0 - int old_level = disable_irq_save(); - if(on) - { - IO_GIO_BITSET0 = (1 << 14); - ata_reset(); - } - else - IO_GIO_BITCLR0 = (1 << 14); - restore_irq(old_level); -#else - (void)on; -#endif -} - -inline bool ide_powered() -{ -#if 0 - return (IO_GIO_BITSET0 & (1 << 14)); -#else - return true; -#endif -} - -void ata_reset(void) -{ - int old_level = disable_irq_save(); - if(!ide_powered()) - { - ide_power_enable(true); - sleep_ms(150); - } - else - { - IO_GIO_BITSET0 = (1 << 5); - IO_GIO_BITCLR0 = (1 << 3); - sleep_ms(1); - } - IO_GIO_BITCLR0 = (1 << 5); - sleep_ms(10); - IO_GIO_BITSET0 = (1 << 3); - while(!(ATA_COMMAND & STATUS_RDY)) - sleep_ms(10); - restore_irq(old_level); -} - -void ata_enable(bool on) -{ - (void)on; - return; -} - -bool ata_is_coldstart(void) -{ - return true; -} - -void ata_device_init(void) -{ - IO_INTC_EINT1 |= INTR_EINT1_EXT2; /* enable GIO2 interrupt */ - /* TODO: mimic OF inits... */ - return; -} - -void GIO2(void) -{ -#ifdef DEBUG - logf("GIO2 interrupt..."); -#endif - IO_INTC_IRQ1 = INTR_IRQ1_EXT2; /* Mask GIO2 interrupt */ - return; -} - -/* - --------------------------------------------------------------------------- - CreativeFileSystem parsing/handling code - --------------------------------------------------------------------------- - */ - -#define VFAT_SECTOR_SIZE(x) ( (x)/0x8000 ) /* 1GB array requires 80kB of RAM */ - -extern int ata_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf); -extern int ata_write_sectors(IF_MD(int drive,) sector_t start, int count, const void* buf); - -// XXX 64-bit: Due to this it's not likely that this target will ever handle 64-bit storage. - -struct main_header -{ - char mblk[4]; - unsigned int sector_size; - long long disk_size; - struct partition_header - { - unsigned long end; - unsigned long start; - char name[8]; - } partitions[31]; -}; - -struct cfs_header -{ - unsigned int unk; - unsigned int unk2; - unsigned int sector_size; - unsigned int unk4; - unsigned int unk5; - char identifier[4]; - unsigned int first_inode; - unsigned int unk8; - unsigned int unk9; - unsigned int unk10; - unsigned int unk11; -}; - -struct cfs_inode -{ - unsigned char magic[4]; - unsigned int number; - unsigned int parent; - unsigned int unk; - unsigned int type; - unsigned int created_time; - unsigned int lastmodified_time; - unsigned int unk2; - unsigned int first_class_chain[12]; - unsigned int unk3; - unsigned int unk4; - unsigned int second_class_chain_first_cluster; - unsigned int unk9; - unsigned int unk10; - unsigned int second_class_chain_second_cluster; - unsigned int unk11; - unsigned int unk12; - unsigned int unk13; - unsigned int filesize; - unsigned int serial_number; - unsigned int number_of_metadata_records; -}; - -struct cfs_direntry -{ - unsigned char identifier[4]; - unsigned int unk; - unsigned int items; - unsigned int unk2; - unsigned char maxlen[2]; - unsigned char padding[202]; - /* struct cfs_direntry_item _items[items]; */ -}; -struct cfs_direntry_item -{ - unsigned int inode_number; - unsigned short strlen; - unsigned short bytesperchar; - char string[32]; -}; - -static bool cfs_inited = false; -static unsigned long cfs_start; -#ifdef BOOTLOADER -static unsigned long *sectors; -#else -static int sectors_handle; -#endif - -#define CFS_START ( ((hdr->partitions[1].start*hdr->sector_size) & ~0xFFFF) + 0x10000 ) -#define CFS_CLUSTER2CLUSTER(x) ( (CFS_START/512)+((x)-1)*64 ) - -/* Limited version of UCS -> ASCII */ -static char* ucs2letostring(unsigned char* s) -{ - static char res[256]; - int i; - - for(i=0; (s[i] == 0 && s[i+1] == 0 && i<256); i++) - res[i] = s[i*2]; - - return (char*)&res; -} - -static void cfs_init(void) -{ - struct main_header *hdr; - struct cfs_header *cfs; - struct cfs_inode *root_inode, *vfat_inode, *inode; - struct cfs_direntry *root_direntry, *vfat_direntry; - struct cfs_direntry_item *root_direntry_items, *vfat_direntry_items; - unsigned int i, j, k, vfat_inode_nr=0, vfat_inodes_nr[10], vfat_sector_count; - unsigned char sector[512]; - static unsigned int vfat_data[2][0x8000]; - static unsigned char sector2[0x8000]; - - if(cfs_inited) - return; - - /* Read MBLK */ - _ata_read_sectors(0, 1, §or); - hdr = (struct main_header*)§or; - - logf("CFS is at 0x%x [0x%x]", CFS_START, CFS_START/512); - - /* Read CFS header */ - _ata_read_sectors(CFS_START/512, 64, §or2); - cfs = (struct cfs_header*)§or2; - - logf("First inode = 0x%x", cfs->first_inode); - - /* Read root inode */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(cfs->first_inode), 64, §or2); - root_inode = (struct cfs_inode*)§or2; - - logf("Root inode = 0x%x", root_inode); - - logf("0x%x 0x%x", CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), root_inode->first_class_chain[0]); - - /* Read root inode's first sector */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), 64, §or2); - root_direntry = (struct cfs_direntry*)§or2; - root_direntry_items = (struct cfs_direntry_item*)(§or2[0]+sizeof(struct cfs_direntry)); - - logf("0x%x", root_direntry->identifier); - - logf("%d", root_direntry->items); - - /* Search VFAT inode */ - for(i=0; i < root_direntry->items; i++) - { - if(root_direntry_items[i].inode_number != 0) - { - //logf(" * [%s] at 0x%x", ucs2letostring(&root_direntry_items[i].string[0]), root_direntry_items[i].inode_number); - if(strcmp(ucs2letostring(&root_direntry_items[i].string[0]), "VFAT") == 0) - vfat_inode_nr = root_direntry_items[i].inode_number; - } - } - - logf("VFAT inode = 0x%x", vfat_inode_nr); - - if(vfat_inode_nr != 0) - { - /* Read VFAT inode */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode_nr), 64, §or2); - vfat_inode = (struct cfs_inode*)§or2; - - /* Read VFAT inode's first sector */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode->first_class_chain[0]), 64, §or2); - vfat_direntry = (struct cfs_direntry*)§or2; - vfat_direntry_items = (struct cfs_direntry_item*)(§or2[0]+sizeof(struct cfs_direntry)); - - /* Search for VFAT's subinodes */ - for(i=0; i < vfat_direntry->items; i++) - { - logf(" * [%s] at 0x%x\n", ucs2letostring(&vfat_direntry_items[i].string[0]), vfat_direntry_items[i].inode_number); - if(i > 0) - vfat_inodes_nr[i-1] = vfat_direntry_items[i].inode_number; - } - - /* Determine size of VFAT file */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[1]), 1, §or); - inode = (struct cfs_inode*)§or; -#ifndef BOOTLOADER - sectors_handle = core_alloc(VFAT_SECTOR_SIZE(inode->filesize)); - unsigned long *sectors = core_get_data(sectors_handle); -#else - static unsigned long _sector[VFAT_SECTOR_SIZE(1024*1024*1024)]; /* 1GB guess */ - sectors = _sector; -#endif - - logf("VFAT file size: 0x%x", inode->filesize); - - /* Clear data sectors */ - memset(§ors, 0, VFAT_SECTOR_SIZE(inode->filesize)*sizeof(unsigned long)); - - /* Read all data sectors' addresses in memory */ - vfat_sector_count = 0; - for(i=0; vfat_inodes_nr[i] != 0; i++) - { - _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[i]), 1, §or); - inode = (struct cfs_inode*)§or; - - /* Read second & third class chain */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_first_cluster), 64, &vfat_data[0]); - _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_second_cluster), 64, &vfat_data[1]); - - /* First class chain */ -#ifndef BOOTLOADER - sectors = core_get_data(sectors_handle); -#endif - for(j=0; j<12; j++) - { - if( (inode->first_class_chain[j] & 0xFFFF) != 0xFFFF && - inode->first_class_chain[j] != 0 - ) - sectors[vfat_sector_count++] = inode->first_class_chain[j]; - } - - /* Second class chain */ -#ifndef BOOTLOADER - sectors = core_get_data(sectors_handle); -#endif - for(j=0; j<0x8000/4; j++) - { - if( (vfat_data[0][j] & 0xFFFF) != 0xFFFF && - vfat_data[0][j] != 0 - ) - sectors[vfat_sector_count++] = vfat_data[0][j]; - } - - /* Third class chain */ - for(j=0; j<0x8000/4; j++) - { - if( (vfat_data[1][j] & 0xFFFF) != 0xFFFF && - vfat_data[1][j] != 0 - ) - { - memset(&vfat_data[0], 0, 0x8000*sizeof(unsigned int)); - - /* Read third class subchain(s) */ - _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_data[1][j]), 64, &vfat_data[0]); - -#ifndef BOOTLOADER - sectors = core_get_data(sectors_handle); -#endif - for(k=0; k<0x8000/4; k++) - { - if( (vfat_data[0][k] & 0xFFFF) != 0xFFFF && - vfat_data[0][k] != 0 - ) - sectors[vfat_sector_count++] = vfat_data[0][k]; - } - } - } - } - - logf("Sector count: %d 0x%x", vfat_sector_count, vfat_sector_count); - } - else - panicf("Cannot find virtual FAT filesystem!"); - - cfs_inited = true; -} - -static inline sector_t map_sector(sector_t sector) -{ - /* - * Sector mapping: start of CFS + FAT_SECTOR2CFS_SECTOR(sector) + missing part - * FAT works with sectors of 0x200 bytes, CFS with sectors of 0x8000 bytes. - */ -#ifndef BOOTLOADER - sector_t *sectors = core_get_data(sectors_handle); -#endif - return cfs_start+sectors[sector/64]*64+sector%64; -} - -int ata_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf) -{ - if(!cfs_inited) - cfs_init(); - - /* Check if count is lesser than or equal to 1 native CFS sector */ - if(count <= 64) - return _ata_read_sectors(IF_MD(drive,) map_sector(start), count, buf); - else - { - int i; - unsigned char* dest = (unsigned char*)buf; - - /* Read sectors in parts of 0x8000 */ - for(i=0; i= 64 ? 64 : count-i), (void*)dest); - if(ret != 0) - return ret; - - dest += (count-i >= 64 ? 0x8000 : (count-i)*512); - } - - return 0; - } -} - -int ata_write_sectors(IF_MD(int drive,) sector_t start, int count, const void* buf) -{ - if(!cfs_inited) - cfs_init(); - -#if 0 /* Disabled for now */ - /* Check if count is lesser than or equal to 1 native CFS sector */ - if(count <= 64) - return _ata_write_sectors(IF_MD(drive,) map_sector(start), count, buf); - else - { - int i, ret; - unsigned char* dest = (unsigned char*)buf; - - /* Read sectors in parts of 0x8000 */ - for(i=0; i= 64 ? 64 : count-i), (const void*)dest); - if(ret != 0) - return ret; - - dest += (count-i >= 64 ? 0x8000 : (count-i)*512); - } - - return ret; - } -#else - (void)start; - (void)count; - (void)buf; - return 0; -#endif -} - -#ifdef BOOTLOADER - -/* - --------------------------------------------------------------------------- - MiniFileSystem parsing code - --------------------------------------------------------------------------- - */ - -struct minifs_file -{ - char name[0x10]; - unsigned int unk; - unsigned long size; - unsigned int chain1; - unsigned int chain2; -}; - -struct minifs_chain -{ - unsigned int unknown; - unsigned short chain[0x27FE]; - unsigned int unknown2; - unsigned long length; -}; - - -#define DIR_BITMAP_START 0x0143 -#define DIR_START 0x0144 -#define DATASPACE_BITMAP_START 0x0145 -#define DATASPACE_START 0x0146 - -#define CLUSTER_CHAIN_SIZE 0x5008 -#define CLUSTER_CHAIN_HEAD 0x0000 -#define CLUSTER_CHAIN_BITMAP 0x0001 -#define CLUSTER_CHAIN_CHAIN 0x0002 - - -int load_minifs_file(char* filename, unsigned char* location) -{ - struct main_header *hdr; - static struct minifs_file files[128]; - struct minifs_chain *chain; - unsigned int i; - int found = -1; - unsigned char sector[512]; - static unsigned char chain_data[42*512]; /* stack overflow if not static */ - - /* Read MBLK */ - _ata_read_sectors(0, 1, §or); - hdr = (struct main_header*)§or; - - /* Read directory listing */ -#define CLUSTER2SECTOR(x) ( (hdr->partitions[0].start + (x)*8) ) - _ata_read_sectors(CLUSTER2SECTOR(DIR_START), 8, &files); - - for(i=0; i<127; i++) - { - if(strcmp(files[i].name, filename) == 0) - found = i; - } - - if(found == -1) - return -1; - -#define GET_CHAIN(x) ( CLUSTER2SECTOR(CLUSTER_CHAIN_CHAIN)*512 + (x)*CLUSTER_CHAIN_SIZE ) -#define FILE2SECTOR(x) ( CLUSTER2SECTOR(DATASPACE_START + (x)) ) - - /* Read chain list */ - _ata_read_sectors(GET_CHAIN(files[found].chain1)/512, 41, &chain_data[0]); - - chain = (struct minifs_chain*)&chain_data[GET_CHAIN(files[found].chain1)%512]; - - /* Copy data */ - for(i=0; ilength; i++) - { - _ata_read_sectors(FILE2SECTOR(chain->chain[i]), 8, location); - location += 0x1000; - } - - return files[found].size; -} - -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h b/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h deleted file mode 100644 index 41b8e73ad4..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/ata-target.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef ATA_TARGET_H -#define ATA_TARGET_H - -#include "ata.h" - -/* DMA optimized reading and writing */ -#define ATA_OPTIMIZED_READING -#define ATA_OPTIMIZED_WRITING -/* -#include "dma-target.h" -#define copy_read_sectors dma_ata_read -#define copy_write_sectors dma_ata_write -*/ - -/* Nasty hack, but Creative is nasty... */ -#define ata_read_sectors _ata_read_sectors -#define ata_write_sectors _ata_write_sectors -extern int _ata_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf); -extern int _ata_write_sectors(IF_MD(int drive,) sector_t start, int count, const void* buf); - -/* General purpose memory region #1 */ -#define ATA_IOBASE 0x50FEE000 -#define ATA_DATA (*((volatile unsigned short*)(ATA_IOBASE))) -#define ATA_ERROR (*((volatile unsigned char*)(ATA_IOBASE+0x2))) -#define ATA_NSECTOR (*((volatile unsigned char*)(ATA_IOBASE+0x4))) -#define ATA_SECTOR (*((volatile unsigned char*)(ATA_IOBASE+0x6))) -#define ATA_LCYL (*((volatile unsigned char*)(ATA_IOBASE+0x8))) -#define ATA_HCYL (*((volatile unsigned char*)(ATA_IOBASE+0xA))) -#define ATA_SELECT (*((volatile unsigned char*)(ATA_IOBASE+0xC))) -#define ATA_COMMAND (*((volatile unsigned char*)(ATA_IOBASE+0xE))) -#define ATA_CONTROL (*((volatile unsigned char*)(ATA_IOBASE+0x800C))) - -#ifdef BOOTLOADER -int load_minifs_file(char* filename, unsigned char* location); -#endif - -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/backlight-target.h b/firmware/target/arm/tms320dm320/creative-zvm/backlight-target.h deleted file mode 100644 index 4ebe3144cf..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/backlight-target.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: backlight-target.h 15599 2007-11-12 18:49:53Z amiconn $ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H - -bool backlight_hw_init(void); -void backlight_hw_on(void); -void backlight_hw_off(void); -void backlight_hw_brightness(int brightness); - -/* true: backlight fades off - false: backlight fades on */ -void __backlight_dim(bool dim); - -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/button-target.h b/firmware/target/arm/tms320dm320/creative-zvm/button-target.h deleted file mode 100644 index 50a182a210..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/button-target.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2008 by Maurus Cuelenaere -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#ifndef _BUTTON_TARGET_H_ -#define _BUTTON_TARGET_H_ - -#include "config.h" - -#define BUTTON_BACK (1 << 0) -#define BUTTON_CUSTOM (1 << 1) -#define BUTTON_MENU (1 << 2) - -#define BUTTON_LEFT (1 << 3) -#define BUTTON_RIGHT (1 << 4) -#define BUTTON_UP (1 << 5) -#define BUTTON_DOWN (1 << 6) -#define BUTTON_SELECT (1 << 7) - -#define BUTTON_POWER (1 << 8) -#define BUTTON_PLAY (1 << 9) - -#define BUTTON_HOLD (1 << 10) - -#ifdef CREATIVE_ZV -#define BUTTON_PREV (1 << 11) -#define BUTTON_NEXT (1 << 12) - -#define BUTTON_VOL_UP (1 << 13) -#define BUTTON_VOL_DOWN (1 << 14) -#endif - -#ifndef CREATIVE_ZV -#define BUTTON_MAIN ( BUTTON_BACK | BUTTON_MENU | BUTTON_LEFT | BUTTON_RIGHT \ - | BUTTON_UP | BUTTON_DOWN | BUTTON_SELECT | BUTTON_POWER \ - | BUTTON_PLAY | BUTTON_HOLD | BUTTON_CUSTOM ) -#else -#define BUTTON_MAIN ( BUTTON_BACK | BUTTON_MENU | BUTTON_LEFT | BUTTON_RIGHT \ - | BUTTON_UP | BUTTON_DOWN | BUTTON_SELECT | BUTTON_POWER \ - | BUTTON_PLAY | BUTTON_HOLD | BUTTON_NEXT | BUTTON_PREV \ - | BUTTON_VOL_UP | BUTTON_VOL_DOWN ) -#endif - -#define POWEROFF_BUTTON BUTTON_POWER -#define POWEROFF_COUNT 10 - -#define HAS_BUTTON_HOLD - -bool button_usb_connected(void); - -#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/arm/tms320dm320/creative-zvm/dma-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/dma-creativezvm.c deleted file mode 100644 index 418a28ff09..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/dma-creativezvm.c +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "kernel.h" -#include "thread.h" -#include "system.h" -#include "dma-target.h" -#include "dm320.h" -#include "ata.h" -#include "ata-driver.h" -#include "ata-defines.h" -#include - -#define CS1_START 0x50000000 -#define CS2_START 0x60000000 -#define SDRAM_START 0x00900000 -#define FLASH_START 0x00100000 -#define CF_START 0x40000000 -#define SSFDC_START 0x48000000 - -static struct semaphore transfer_completion_signal; - -static bool dma_in_progress = false; - -void MTC0(void) -{ - IO_INTC_IRQ1 = INTR_IRQ1_MTC0; - semaphore_release(&transfer_completion_signal); - dma_in_progress = false; -} - -void dma_start(const void* addr, size_t size) -{ - /* Compatibility with Gigabeat S in dma_start.c */ - (void) addr; - (void) size; -} - -#define ATA_DEST (ATA_IOBASE-CS1_START) -void dma_ata_read(unsigned char* buf, int shortcount) -{ - if(dma_in_progress) - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); - - while((unsigned long)buf & 0x1F) - { - unsigned short tmp; - tmp = ATA_IN16(ATA_DATA); - *buf++ = tmp & 0xFF; - *buf++ = tmp >> 8; - shortcount--; - } - - if (!shortcount) - return; - - IO_SDRAM_SDDMASEL = 0x0820; /* 32-byte burst mode transfer */ - IO_EMIF_DMAMTCSEL = 1; /* Select CS1 */ - IO_EMIF_AHBADDH = ((unsigned long)buf >> 16) & 0x7FFF; /* Set variable address */ - IO_EMIF_AHBADDL = (unsigned long)buf & 0xFFFF; - IO_EMIF_MTCADDH = ( (1 << 15) | (ATA_DEST >> 16) ); /* Set fixed address */ - IO_EMIF_MTCADDL = ATA_DEST & 0xFFFF; - IO_EMIF_DMASIZE = shortcount/2; /* 16-bits *2 = 1 word */ - IO_EMIF_DMACTL = 3; /* Select MTC->AHB and start transfer */ - - dma_in_progress = true; - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); - - if(shortcount % 2) - { - unsigned short tmp; - tmp = ATA_IN16(ATA_DATA); - *buf++ = tmp & 0xFF; - *buf++ = tmp >> 8; - } -} - -void dma_ata_write(unsigned char* buf, int wordcount) -{ - if(dma_in_progress) - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); - - while((unsigned long)buf & 0x1F) - { - unsigned short tmp; - tmp = (unsigned short) *buf++; - tmp |= (unsigned short) *buf++ << 8; - ATA_OUT16(ATA_DATA, tmp); - wordcount--; - } - - if (!wordcount) - return; - - IO_SDRAM_SDDMASEL = 0x0830; /* 32-byte burst mode transfer */ - IO_EMIF_DMAMTCSEL = 1; /* Select CS1 */ - IO_EMIF_AHBADDH = ((unsigned long)buf >> 16) & ~(1 << 15); /* Set variable address */ - IO_EMIF_AHBADDL = (unsigned long)buf & 0xFFFF; - IO_EMIF_MTCADDH = ( (1 << 15) | (ATA_DEST >> 16) ); /* Set fixed address */ - IO_EMIF_MTCADDL = ATA_DEST & 0xFFFF; - IO_EMIF_DMASIZE = (wordcount+1)/2; - IO_EMIF_DMACTL = 1; /* Select AHB->MTC and start transfer */ - - dma_in_progress = true; - semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); -} - -void dma_init(void) -{ - IO_INTC_EINT1 |= INTR_EINT1_MTC0; /* enable MTC interrupt */ - semaphore_init(&transfer_completion_signal, 1, 0); - dma_in_progress = false; -} diff --git a/firmware/target/arm/tms320dm320/creative-zvm/dma-target.h b/firmware/target/arm/tms320dm320/creative-zvm/dma-target.h deleted file mode 100644 index f7e1d76626..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/dma-target.h +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef DMA_TARGET_H -#define DMA_TARGET_H - -void dma_start(const void* addr, size_t size); /* Compatibility with Gigabeat S in dma_start.c */ -void dma_ata_read(unsigned char* buf, int wordcount); -void dma_ata_write(unsigned char* buf, int wordcount); -void dma_init(void); - -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c deleted file mode 100644 index 9621b532fe..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/lcd-creativezvm.c +++ /dev/null @@ -1,427 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2008 by Maurus Cuelenaere -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ -#include -#include "config.h" - -#include "hwcompat.h" -#include "kernel.h" -#include "lcd.h" -#include "system.h" -#include "string-extra.h" /* memset16() */ -#include "cpu.h" -#include "spi.h" -#include "lcd-target.h" -#include "ltv350qv.h" - -/* Power and display status */ -extern bool lcd_on; /* lcd-memframe.c */ -static bool direct_fb_access = false; /* Does the DM320 has direct access to the FB? */ - -/* Copies a rectangle from one framebuffer to another. Can be used in - single transfer mode with width = num pixels, and height = 1 which - allows a full-width rectangle to be copied more efficiently. */ -extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, - int width, int height); - -int lcd_default_contrast(void) -{ - return 0x1f; -} - -void lcd_set_contrast(int val) -{ - /* find S6F2002 controller datasheet first */ - (void)val; -} - -void lcd_set_invert_display(bool yesno) { - (void) yesno; - /* TODO: */ -} - -void lcd_set_flip(bool yesno) { - (void) yesno; - /* TODO: */ -} - -static void enable_venc(bool enable) -{ - if(enable) - { - /* Set OSD clock */ - IO_CLK_MOD1 &= ~(CLK_MOD1_VENC | CLK_MOD1_OSD); /* disable OSD clock and VENC clock */ - IO_CLK_O2DIV = 3; - - IO_CLK_OSEL &= ~CLK_OSEL_O2SEL(0xF); /* reset 'General purpose clock output (GIO26, GIO34)' and */ - IO_CLK_OSEL |= CLK_OSEL_O2SEL(4); /* set to 'PLLIN clock' */ - - IO_CLK_SEL1 |= (CLK_SEL1_OSD | CLK_SEL1_VENC(7)); /* set to 'GP clock output 2 (GIO26, GIO34)' and turn on 'VENC clock' */ - IO_CLK_MOD1 |= (CLK_MOD1_VENC | CLK_MOD1_OSD); /* enable OSD clock and VENC clock */ - } - else - { - /* Disable video encoder */ - IO_VID_ENC_VMOD &= ~VENC_VMOD_VENC; - /* Disable clock for power saving */ - IO_CLK_MOD1 &= ~(CLK_MOD1_VENC | CLK_MOD1_OSD); - } -} - -/* LTV250QV panel functions */ -static void lcd_write_reg(unsigned char reg, unsigned short val) -{ - unsigned char block[3] = {LTV_OPC_INDEX, 0, reg | 0xFF}; - spi_block_transfer(SPI_target_LTV250QV, block, sizeof(block), NULL, 0); - block[0] = LTV_OPC_DATA; - block[1] = val >> 8; - block[2] = val & 0xFF; - spi_block_transfer(SPI_target_LTV250QV, block, sizeof(block), NULL, 0); -} - -static void sleep_ms(unsigned int ms) -{ - sleep(ms*HZ/1000); -} - -static void lcd_display_on(bool reset) -{ - /* Enable main power */ - IO_GIO_BITSET2 |= (1 << 3); - - /* power on sequence as per the ZVM firmware */ - sleep_ms(250); - IO_GIO_BITSET1 = (1 << 13); - sleep_ms(5); - IO_GIO_BITSET2 = (1 << 5); - IO_GIO_BITSET2 = (1 << 8); - sleep_ms(1); - - /*Init SPI here... */ - sleep_ms(32); - - IO_GIO_BITSET2 = (1 << 0); - sleep_ms(5); - IO_GIO_BITSET2 = (1 << 7); - sleep_ms(5); - IO_GIO_BITSET2 = (1 << 4); - sleep_ms(5); - IO_GIO_BITCLR2 = (1 << 8); - /*TODO: figure out what OF does after this... */ - IO_GIO_BITSET2 = (1 << 8); - sleep_ms(1); - - lcd_write_reg(LTV_IFCTL, LTV_NL(29)); - lcd_write_reg(LTV_DATACTL, 0); - lcd_write_reg(LTV_ENTRY_MODE,0); - lcd_write_reg(LTV_GATECTL1, 0); - lcd_write_reg(LTV_GATECTL2, (LTV_NW_INV_1LINE | LTV_FHN | LTV_FTI(2) | LTV_FWI(3))); - lcd_write_reg(LTV_VBP, 0); - lcd_write_reg(LTV_HBP, 0); - lcd_write_reg(LTV_SOTCTL, 0); - lcd_write_reg(LTV_PWRCTL1, 0); - lcd_write_reg(LTV_PWRCTL2, 0); - lcd_write_reg(LTV_GAMMA(0), 0); - lcd_write_reg(LTV_GAMMA(1), 0); - lcd_write_reg(LTV_GAMMA(2), 0); - lcd_write_reg(LTV_GAMMA(3), 0); - lcd_write_reg(LTV_GAMMA(4), 0); - lcd_write_reg(LTV_GAMMA(5), 0); - lcd_write_reg(LTV_GAMMA(6), 0); - lcd_write_reg(LTV_GAMMA(7), 0); - lcd_write_reg(LTV_GAMMA(8), 0); - lcd_write_reg(LTV_GAMMA(9), 0); - sleep_ms(10); - - lcd_write_reg(LTV_PWRCTL1, (LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) | LTV_SUPPLY_CURRENT(5))); - lcd_write_reg(LTV_PWRCTL2, 0); - sleep_ms(40); - - lcd_write_reg(LTV_PWRCTL2, LTV_VCOML_ENABLE); - sleep_ms(40); - - lcd_write_reg(LTV_IFCTL, (LTV_NMD | LTV_NL(29))); - lcd_write_reg(LTV_DATACTL, (LTV_DS_SAME | LTV_CHS_480 | LTV_DF_RGB | LTV_RGB_BGR)); - lcd_write_reg(LTV_ENTRY_MODE,(LTV_VSPL_ACTIVE_LOW | LTV_HSPL_ACTIVE_LOW | LTV_DPL_SAMPLE_RISING | LTV_EPL_ACTIVE_LOW | LTV_SS_RIGHT_TO_LEFT)); - lcd_write_reg(LTV_GATECTL1, LTV_CLW(1)); - lcd_write_reg(LTV_GATECTL2, (LTV_NW_INV_1LINE | LTV_DSC | LTV_FTI(3) | LTV_FWI(3))); - lcd_write_reg(LTV_VBP, 0x5); - lcd_write_reg(LTV_HBP, 0x1B); - lcd_write_reg(LTV_SOTCTL, LTV_SDT(2)); - lcd_write_reg(LTV_GAMMA(0), 0x203); - lcd_write_reg(LTV_GAMMA(1), 0x302); - lcd_write_reg(LTV_GAMMA(2), 0xC08); - lcd_write_reg(LTV_GAMMA(3), 0xC08); - lcd_write_reg(LTV_GAMMA(4), 0x707); - lcd_write_reg(LTV_GAMMA(5), 0x707); - lcd_write_reg(LTV_GAMMA(6), 0x104); - lcd_write_reg(LTV_GAMMA(7), 0x306); - lcd_write_reg(LTV_GAMMA(8), 0); - lcd_write_reg(LTV_GAMMA(9), 0); - sleep_ms(60); - - lcd_write_reg(LTV_PWRCTL1, (LTV_VCOMOUT_ENABLE | LTV_POWER_ON | LTV_DRIVE_CURRENT(5) | LTV_SUPPLY_CURRENT(5))); - lcd_write_reg(LTV_PWRCTL2, (LTV_VCOML_VOLTAGE(17) | LTV_VCOMH_VOLTAGE(26))); /* VCOML=0,0625V VCOMH=1,21875V */ - sleep_ms(10); - - if(!reset) - { - enable_venc(true); - /* Re-enable video encoder */ - IO_VID_ENC_VMOD |= VENC_VMOD_VENC; - } - /* tell that we're on now */ - lcd_on = true; -} - -#ifdef HAVE_LCD_ENABLE -static void lcd_display_off(void) -{ - /* LQV shutdown sequence */ - lcd_write_reg(LTV_PWRCTL1, (LTV_VCOMOUT_ENABLE | LTV_DRIVE_CURRENT(5) | LTV_SUPPLY_CURRENT(5))); - sleep_ms(20); - - lcd_write_reg(LTV_PWRCTL1, (LTV_DRIVE_CURRENT(5) | LTV_SUPPLY_CURRENT(5))); - lcd_write_reg(LTV_GATECTL2, (LTV_NW_INV_1LINE | LTV_FTI(3) | LTV_FWI(3))); - lcd_write_reg(LTV_PWRCTL2, 0); - sleep_ms(20); - - lcd_write_reg(LTV_PWRCTL1, 0); - sleep_ms(10); - unsigned char temp[1]; - temp[0] = 0; - spi_block_transfer(SPI_target_LTV250QV, temp, sizeof(temp), NULL, 0); - - IO_GIO_BITCLR2 = (1 << 4); - sleep_ms(5); - IO_GIO_BITCLR2 = (1 << 7); - sleep_ms(5); - IO_GIO_BITCLR2 = (1 << 0); - sleep_ms(2); - IO_GIO_BITCLR2 = (1 << 8); - IO_GIO_BITCLR2 = (1 << 5); - - /* Disable main power */ - IO_GIO_BITCLR2 |= (1 << 3); - - enable_venc(false); - - lcd_on = false; -} - -void lcd_enable(bool on) -{ -/* Disabled until properly working */ -return; - if (on == lcd_on) - return; - - if (on) - { - lcd_display_on(false); /* Turn on display */ - lcd_update(); /* Resync display */ - send_event(LCD_EVENT_ACTIVATION, NULL); - } - else - { - lcd_display_off(); /* Turn off display */ - } -} -#endif - -void lcd_set_direct_fb(bool yes) -{ - unsigned int addr; - direct_fb_access = yes; - if(yes) - addr = ((unsigned int)FBADDR(0,0)-CONFIG_SDRAM_START) / 32; - else - addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32; - IO_OSD_OSDWINADH = addr >> 16; - IO_OSD_OSDWIN0ADL = addr & 0xFFFF; -} - -bool lcd_get_direct_fb(void) -{ - return direct_fb_access; -} - -static bool _lcd_enabled(void) -{ - /* Needed to detect if VENC/LCD already is initialized... */ - if(IO_VID_ENC_VDCTL & VENC_VDCTL_VCLKE) - return true; - else if(!(IO_VID_ENC_VDCTL & VENC_VDCTL_YCDC)) - return true; - else if(IO_CLK_MOD1 & CLK_MOD1_VENC) - return true; - else if(IO_CLK_MOD1 & CLK_MOD1_OSD) - return true; - else - return false; -} - -void lcd_init_device(void) -{ - if(!_lcd_enabled()) - { - lcd_display_on(true); - - enable_venc(true); - - /* Set LCD values in Video Encoder */ - IO_VID_ENC_VMOD &= 0x8800; /* Clear all values */ - IO_VID_ENC_VMOD |= (VENC_VMOD_DACPD | VENC_VMOD_VMD | VENC_VMOD_ITLC | VENC_VMOD_VDMD(2)); /* set mode to RGB666 parallel 16 bit */ - IO_VID_ENC_VDCTL &= 0x8FE8; /* Clear all values */ - IO_VID_ENC_VDCTL |= (VENC_VDCTL_VCLKP | VENC_VDCTL_DOMD(2)), - IO_VID_ENC_VDPRO = VENC_VDPRO_PFLTR; - IO_VID_ENC_SYNCTL &= 0xE000; /* Clear all values */ - IO_VID_ENC_SYNCTL |= (VENC_SYNCTL_VPL | VENC_SYNCTL_HPL); - IO_VID_ENC_HSDLY = 0; - IO_VID_ENC_HSPLS = 0x12; - IO_VID_ENC_HSTART = 0x1B; - IO_VID_ENC_HVALID = 0x140; - IO_VID_ENC_HINT = 0x168; - IO_VID_ENC_VSDLY = 0; - IO_VID_ENC_VSPLS = 3; - IO_VID_ENC_VSTART = 5; - IO_VID_ENC_VVALID = 0xF0; - IO_VID_ENC_VINT = 0x118; - IO_VID_ENC_RGBCTL &= 0x088; /* Clear all values */ - IO_VID_ENC_RGBCTL |= VENC_RGBCTL_DFLTR; - IO_VID_ENC_RGBCLP = VENC_RGBCLP_UCLIP(0xFF); - IO_VID_ENC_LCDOUT &= 0xFE00; /* Clear all values */ - IO_VID_ENC_LCDOUT |= (VENC_LCDOUT_OEE | VENC_LCDOUT_FIDS); - IO_VID_ENC_DCLKCTL &= 0xC0C0; /* Clear all values */ - IO_VID_ENC_DCLKCTL |= VENC_DCLKCTL_DCKEC; - IO_VID_ENC_DCLKPTN0 = 1; - DM320_REG(0x0864) = 0; /* ???? */ - } - else - lcd_on = true; - - /* Based on lcd-mr500.c from Catalin Patulea */ - /* Clear the Frame */ - memset16(FRAME, 0x0000, LCD_WIDTH*LCD_HEIGHT); - - IO_OSD_MODE = 0x00ff; - IO_OSD_VIDWINMD = 0x0002; - IO_OSD_OSDWINMD0 = 0x2001; - IO_OSD_OSDWINMD1 = 0x0002; - IO_OSD_ATRMD = 0x0000; - IO_OSD_RECTCUR = 0x0000; - - unsigned int addr; - IO_OSD_OSDWIN0OFST = (LCD_WIDTH*16) / 256; - addr = ((unsigned int)FRAME-CONFIG_SDRAM_START) / 32; - IO_OSD_OSDWINADH = addr >> 16; - IO_OSD_OSDWIN0ADL = addr & 0xFFFF; - -#ifndef ZEN_VISION - IO_OSD_BASEPX = 26; - IO_OSD_BASEPY = 5; -#else - IO_OSD_BASEPX = 80; - IO_OSD_BASEPY = 0; -#endif - - IO_OSD_OSDWIN0XP = 0; - IO_OSD_OSDWIN0YP = 0; - IO_OSD_OSDWIN0XL = LCD_WIDTH; - IO_OSD_OSDWIN0YL = LCD_HEIGHT; - - IO_VID_ENC_VDCTL |= VENC_VDCTL_VCLKE; /* Enable VCLK */ - IO_VID_ENC_VMOD |= VENC_VMOD_VENC; /* Enable video encoder */ - IO_VID_ENC_SYNCTL |= VENC_SYNCTL_SYE; /* Enable sync output */ - IO_VID_ENC_VDCTL &= ~VENC_VDCTL_DOMD(3); /* Normal digital data output */ -} - - -/*** Update functions ***/ - -/* Update a fraction of the display. */ -void lcd_update_rect(int x, int y, int width, int height) -{ - register fb_data *dst, *src; - - if (!lcd_on || direct_fb_access) - return; - - if (x + width > LCD_WIDTH) - width = LCD_WIDTH - x; /* Clip right */ - if (x < 0) - width += x, x = 0; /* Clip left */ - if (width <= 0) - return; /* nothing left to do */ - - if (y + height > LCD_HEIGHT) - height = LCD_HEIGHT - y; /* Clip bottom */ - if (y < 0) - height += y, y = 0; /* Clip top */ - if (height <= 0) - return; /* nothing left to do */ - -#if CONFIG_ORIENTATION == SCREEN_PORTRAIT - dst = (fb_data *)FRAME + LCD_WIDTH*y + x; - src = FBADDR(x,y); - - /* Copy part of the Rockbox framebuffer to the second framebuffer */ - if (width < LCD_WIDTH) - { - /* Not full width - do line-by-line */ - lcd_copy_buffer_rect(dst, src, width, height); - } - else - { - /* Full width - copy as one line */ - lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); - } -#else - src = FBADDR(x,y); - - register int xc, yc; - register fb_data *start=FRAME + LCD_HEIGHT*(LCD_WIDTH-x-1) + y + 1; - - for(yc=0;yc ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef LCD_TARGET_H -#define LCD_TARGET_H - -void lcd_set_direct_fb(bool yes); -bool lcd_get_direct_fb(void); - -/* Direct FB access disables regular updates */ -#define lcd_write_enabled() \ - ({ lcd_on && !lcd_get_direct_fb(); }) - -/* Very strange functions */ -#define LCD_OPTIMIZED_UPDATE -#define LCD_OPTIMIZED_UPDATE_RECT - -#define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) - -#endif /* LCD_TARGET_H */ diff --git a/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c deleted file mode 100644 index fa1eb2481f..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/pcm-creativezvm.c +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "system.h" -#include "kernel.h" -#include "logf.h" -#include "audio.h" -#include "sound.h" -#include "file.h" -#include "dm320.h" -#include "audiohw.h" -#include "dsp-target.h" -#include "pcm-internal.h" - -void pcm_play_dma_init(void) -{ - IO_CLK_O1DIV = 3; - /* Set GIO25 to CLKOUT1A */ - IO_GIO_FSEL2 |= 3; - sleep(5); - - audiohw_init(); - - audiohw_set_frequency(HW_FREQ_DEFAULT); - - /* init DSP */ -// dsp_init(); -} - -void pcm_play_dma_postinit(void) -{ - audiohw_postinit(); - - /* wake DSP */ -// dsp_wake(); -} - -void pcm_dma_apply_settings(void) -{ - audiohw_set_frequency(pcm_fsel); -} - -void pcm_play_dma_start(const void *addr, size_t size) -{ - (void)addr; - (void)size; - DEBUGF("pcm_play_dma_start(0x%x, %d)", addr, size); -} - -void pcm_play_dma_stop(void) -{ - -} - -void pcm_play_lock(void) -{ - -} - -void pcm_play_unlock(void) -{ - -} diff --git a/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c deleted file mode 100644 index ab5462fa90..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/pic-creativezvm.c +++ /dev/null @@ -1,380 +0,0 @@ -/*************************************************************************** -* __________ __ ___. -* Open \______ \ ____ ____ | | _\_ |__ _______ ___ -* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / -* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < -* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ -* \/ \/ \/ \/ \/ -* $Id$ -* -* Copyright (C) 2008 by Maurus Cuelenaere -* -* Creative Zen Vision:M interrupt based PIC driver -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -* KIND, either express or implied. -* -****************************************************************************/ - -#include -#include "config.h" -#include "system.h" -#include "kernel.h" -#include "button-target.h" -#include "i2c-dm320.h" -#include "logf.h" - -#ifdef BUTTON_DEBUG -#include "lcd-target.h" -#include "lcd.h" -#include "font.h" -#endif - -#ifndef ZEN_VISION -/* Creative Zen Vision:M */ -#define BTN_LEFT 0xAF00 -#define BTN_RIGHT 0xA700 -#define BTN_BACK 0xDF00 -#define BTN_CUSTOM 0xC700 -#define BTN_PLAY 0x9700 -#define BTN_POWER 0x8700 -#define BTN_MENU 0xCF00 -#define BTN_HOLD 0xCF07 -#define BTN_UNHOLD 0xD707 - -#define BTN_REL 1 - -#define BTN_TOUCHPAD_PRESS 0x8F00 -#define BTN_TOUCHPAD_SCROLL_DOWN 0x0F03 -#define BTN_TOUCHPAD_CORNER_DOWN 0xD700 -#define BTN_TOUCHPAD_CORNER_UP 0x9F00 -#define BTN_TOUCHPAD_SCROLL_UP 0x0F04 - -#define HEADPHONE_PLUGIN_A 0x5707 -#define HEADPHONE_PLUGIN_B 0x5F07 -#define HEADPHONE_UNPLUG_A 0x3707 -#define HEADPHONE_UNPLUG_B 0x3F07 - -#define DOCK_INSERT 0x6707 -#define DOCK_UNPLUG 0xDF06 -#define DOCK_USB_INSERT 0x2F06 -#define DOCK_USB_UNPLUG 0x3F06 -#define DOCK_POWER_INSERT 0x1707 -#define DOCK_POWER_UNPLUG 0x1F07 - -#else -/* Creative Zen Vision */ -#define BTN_LEFT 0xCF00 -#define BTN_RIGHT 0xEF00 -#define BTN_BACK 0xBF00 -#define BTN_CUSTOM 0x0 -#define BTN_PLAY 0x2F00 -#define BTN_POWER 0x0F00 -#define BTN_MENU 0x9F00 -#define BTN_HOLD 0x9F06 -#define BTN_UNHOLD 0xAF06 - - -/* TODO: other values - -First number is just pressing it, second is when you release it or keep it -pressed a bit longer - -On/Off = 0F00 && 0F01 -Hold = 9F06 && AF06 -Volume Up = 6F00 && 6F01 -Vol Down = 7F00 && 7F01 -Up = DF00 && DF01 -Right = EF00 && EF01 -Down = FF00 && FF01 -Left = CF00 && CF01 -Back = BF00 && BF01 -Menu = 9F00 && Etcetera -Ok = 1F00 -Play = 2F00 -Next = 4F00 -Prev = 5F00 - -USB = 2F06 -USB ouot = 3F06 -Headphones= AF06 -Hdphns out= BF06 -Charger = 4F06 -> 9F05 -Chgrout = 5F06 -> 8F05 -AV in = 8F06 -AV out = 9F06 */ - -#define BTN_REL 1 - -#define BTN_TOUCHPAD_PRESS 0x1F00 -#define BTN_TOUCHPAD_LONG_PRESS 0x1F01 -#define BTN_TOUCHPAD_CORNER_DOWN 0xFF00 -#define BTN_TOUCHPAD_SCROLL_DOWN 0xFF01 -#define BTN_TOUCHPAD_CORNER_UP 0xDF00 -#define BTN_TOUCHPAD_SCROLL_UP 0xDF01 - -#define HEADPHONE_PLUGIN_A 0xAF06 -#define HEADPHONE_PLUGIN_B 0x00AF06 //Dummy Value -#define HEADPHONE_UNPLUG_A 0x00BF06 //Dummy Value -#define HEADPHONE_UNPLUG_B 0x00BF061 //Dummy Value - -#define DOCK_INSERT 0x00003 //Dummy Value -#define DOCK_UNPLUG 0x00002 //Dummy Value -#define DOCK_USB_INSERT 0x2F06 -#define DOCK_USB_UNPLUG 0x3F06 -#define DOCK_POWER_INSERT 0x4F06 -#define DOCK_POWER_UNPLUG 0x5F06 -#define DOCK_AV_INSERT 0x8F06 -#define DOCK_AV_UNPLUG 0x9F06 -#endif - -#define PIC_ADR 0x07 - -#define MASK_TV_OUT(x) ((x >> 14) & 1) -#define MASK_xx1(x) ((x >> 9) & 3) -#define MASK_xx2(x) ((x >> 4) & 1) -#define MASK_xx3(x) ((x >> 5) & 1) -#define MASK_xx4(x) ((x >> 6) & 1) -#define MASK_xx5(x) ((x >> 13) & 1) -#define MASK_xx6(x) ((x >> 12) & 1) -#define MASK_xx7(x) ((x >> 11) & 1) - -#define NONBUTTON_HEADPHONE (1 << 0) -#define NONBUTTON_DOCK (1 << 1) -#define NONBUTTON_USB (1 << 2) -#define NONBUTTON_POWER (1 << 3) -#define NONBUTTON_VIDEOUT (1 << 4) - -static unsigned int btn; -static bool hold_switch; -static unsigned char nonbtn; -static unsigned int pic_init_value; -static unsigned int pic_init2_value; -static unsigned int last_btn; -static long last_tick; -static int tick_diff; - -#define TICK_MIN 0x33 -#define TICK_MAX 0x34 - -/* Taken from scramble.c and modified */ -static inline unsigned short le2short(unsigned char* buf) -{ - return (unsigned short)((buf[1] << 8) | buf[0]); -} - -#define map_button(BtN,BtN2) case BtN: \ - btn ^= BtN2; \ - btn &= BtN2; \ - break; \ - case BtN ^ BTN_REL: \ - btn ^= BtN2; \ - btn &= BtN2; \ - break; - -#ifdef BUTTON_DEBUG -static bool sw = false; -#endif - -void GIO0(void) -{ - /* Mask GIO0 interrupt */ - IO_INTC_IRQ1 = INTR_IRQ1_EXT0; - - unsigned char msg[4]; - i2c_read(PIC_ADR, msg, sizeof(msg)); - tick_diff = current_tick - last_tick; - last_tick = current_tick; - unsigned short btn_press = le2short(msg); - if(tick_diff >= TICK_MIN && tick_diff <= TICK_MAX) - { - /* Ignore this, as it is a hold event */ - return; - } - last_btn = btn_press; - switch(btn_press) - { - map_button(BTN_LEFT, BUTTON_LEFT); - map_button(BTN_RIGHT, BUTTON_RIGHT); - map_button(BTN_BACK, BUTTON_BACK); - map_button(BTN_CUSTOM, BUTTON_CUSTOM); - map_button(BTN_MENU, BUTTON_MENU); - map_button(BTN_PLAY, BUTTON_PLAY); - map_button(BTN_POWER, BUTTON_POWER); - map_button(BTN_TOUCHPAD_PRESS, BUTTON_SELECT); - map_button(BTN_TOUCHPAD_CORNER_DOWN, BUTTON_DOWN); - map_button(BTN_TOUCHPAD_CORNER_UP, BUTTON_UP); - #ifndef ZEN_VISION - /* These don't seem to work for some reason on the Zen Vision.. */ - case BTN_TOUCHPAD_SCROLL_DOWN: - btn = BUTTON_DOWN; - break; - case BTN_TOUCHPAD_SCROLL_UP: - btn = BUTTON_UP; - break; - #endif - case BTN_HOLD: - hold_switch = true; - break; - case BTN_UNHOLD: - hold_switch = false; - break; - #ifndef ZEN_VISION - /* These don't seem to work for some reason.. */ - case HEADPHONE_PLUGIN_A: - case HEADPHONE_PLUGIN_B: - nonbtn |= NONBUTTON_HEADPHONE; - break; - case HEADPHONE_UNPLUG_A: - case HEADPHONE_UNPLUG_B: - nonbtn &= ~NONBUTTON_HEADPHONE; - break; - #endif - case DOCK_INSERT: - nonbtn |= NONBUTTON_DOCK; - break; - case DOCK_UNPLUG: - nonbtn &= ~(NONBUTTON_DOCK | NONBUTTON_USB | NONBUTTON_POWER); - break; - case DOCK_USB_INSERT: - nonbtn |= NONBUTTON_USB; - break; - case DOCK_USB_UNPLUG: - nonbtn &= ~NONBUTTON_USB; - break; - case DOCK_POWER_INSERT: - nonbtn |= NONBUTTON_POWER; - break; - case DOCK_POWER_UNPLUG: - nonbtn &= ~NONBUTTON_POWER; - break; - } -#ifdef BUTTON_DEBUG -#ifdef BOOTLOADER - lcd_set_foreground((sw ? LCD_RGBPACK(255,0,0) : LCD_RGBPACK(0,255,0) )); -#endif - lcd_putsxyf(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*10, "%x", - (unsigned int)((msg[3] << 24) | - (msg[2] << 16) | (msg[1] << 8) | msg[0])); - lcd_putsxy(LCD_WIDTH-SYSFONT_WIDTH*10, LCD_HEIGHT-SYSFONT_HEIGHT*7, "%x", - btn); -#ifdef BOOTLOADER - lcd_set_foreground(LCD_BLACK); -#endif - lcd_update(); - sw = !sw; -#endif - logf("PIC: 0x%x", (unsigned int)((msg[3] << 24) | - (msg[2] << 16) | (msg[1] << 8) | msg[0])); -} - -static void send_command_to_pic(const unsigned char in, unsigned char* out, - const unsigned int length) -{ - /* Disable GIO0 interrupt */ - IO_INTC_EINT1 &= ~INTR_EINT1_EXT0; - /* Clear EXT0 interrupt */ - IO_INTC_IRQ1 = INTR_IRQ1_EXT0; - /* Write command to I²C */ - restart: - i2c_write(PIC_ADR, &in, 1); - /* Wait for PIC */ - int i = 0; - while(!(IO_INTC_IRQ1 & INTR_IRQ1_EXT0)) - { - sleep(0); - i++; - if(i > 50) - goto restart; - } - /* Read return from I²C */ - i2c_read(PIC_ADR, out, length); - /* Re-enable GIO0 interrupt */ - IO_INTC_EINT1 |= INTR_EINT1_EXT0; -} - -bool headphones_inserted(void) -{ - return (bool)(nonbtn & NONBUTTON_HEADPHONE); -} - -void button_init_device(void) -{ - /* TODO: I suppose GIO0 has to be set to input and enable interrupts on - it? */ - /* Enable GIO0 interrupt */ - IO_INTC_EINT1 |= INTR_EINT1_EXT0; - btn=nonbtn=pic_init_value=pic_init2_value=last_btn=hold_switch=0; - /* Initialize PIC */ - send_command_to_pic(1, (unsigned char *)&pic_init_value, - sizeof(pic_init_value)); - send_command_to_pic(2, (unsigned char *)&pic_init2_value, - sizeof(pic_init2_value)); -} - -int button_read_device(void) -{ - if(hold_switch) - return 0; - else - return btn; -} - -bool button_hold(void) -{ - return hold_switch; -} - -bool button_usb_connected(void) -{ - return (bool)(nonbtn & NONBUTTON_USB); -} - -#ifndef BOOTLOADER -int pic_dbg_num_items(void) -{ - return 13; -} - -const char* pic_dbg_item(int selected_item, void *data, - char *buffer, size_t buffer_len) -{ - (void)data; - switch(selected_item) - { - case 0: - snprintf(buffer, buffer_len, "Init value 1: 0x%04x", pic_init_value); - return buffer; - case 1: - snprintf(buffer, buffer_len, "Init value 2: 0x%04x", pic_init2_value); - return buffer; - case 2: - snprintf(buffer, buffer_len, "Last button value: 0x%04x Raw value: 0x%04x", last_btn, btn); - return buffer; - case 3: - snprintf(buffer, buffer_len, "Last button differs in ticks: 0x%04x", tick_diff); - return buffer; - case 4: - snprintf(buffer, buffer_len, "Dock values: 0x%04x", nonbtn); - return buffer; - #define B(n,w,b) case n: \ - snprintf(buffer, buffer_len, "%s: 0x%04x", w, b); \ - return buffer; - B(5, "MASK_TV_OUT", MASK_TV_OUT(pic_init_value)); - B(6, "MASK_xx1", MASK_xx1(pic_init_value)); - B(7, "MASK_xx2", MASK_xx2(pic_init_value)); - B(8, "MASK_xx3", MASK_xx3(pic_init_value)); - B(9, "MASK_xx4", MASK_xx4(pic_init_value)); - B(10, "MASK_xx5", MASK_xx5(pic_init_value)); - B(11, "MASK_xx6", MASK_xx6(pic_init_value)); - B(12, "MASK_xx7", MASK_xx7(pic_init_value)); - #undef B - } - return NULL; -} -#endif diff --git a/firmware/target/arm/tms320dm320/creative-zvm/power-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/power-creativezvm.c deleted file mode 100644 index 90c30d326c..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/power-creativezvm.c +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: power-mr500.c 15599 2007-11-12 18:49:53Z amiconn $ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "cpu.h" -#include -#include "kernel.h" -#include "system.h" -#include "power.h" -#include "backlight.h" -#include "backlight-target.h" - -void power_init(void) -{ - /* Initialize IDE power pin */ - /* set ATA power on and output */ - /* Charger detect */ -} - -#if CONFIG_CHARGING -unsigned int power_input_status(void) -{ - return POWER_INPUT_NONE; -} - -/* Returns true if the unit is charging the batteries. */ -bool charging_state(void) -{ - return false; -} -#endif - -void power_off(void) -{ -} diff --git a/firmware/target/arm/tms320dm320/creative-zvm/powermgmt-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/powermgmt-creativezvm.c deleted file mode 100644 index 69b29a3e64..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/powermgmt-creativezvm.c +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2007 by Karl Kurbjun - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "adc.h" -#include "powermgmt.h" -#include "kernel.h" - -/* THIS CONTAINS CURRENTLY DUMMY CODE! */ - -static const unsigned short current_voltage = 3910; -unsigned short battery_level_disksafe = 0; - -unsigned short battery_level_shutoff = 0; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -unsigned short percent_to_volt_discharge[11] = -{ - 100, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1320 -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ -unsigned short percent_to_volt_charge[11] = -{ - 100, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1320, -}; - -/* Returns battery voltage from ADC [millivolts] */ -int _battery_voltage(void) -{ - return current_voltage; -} diff --git a/firmware/target/arm/tms320dm320/creative-zvm/usb-creativezvm.c b/firmware/target/arm/tms320dm320/creative-zvm/usb-creativezvm.c deleted file mode 100644 index 82a59d792a..0000000000 --- a/firmware/target/arm/tms320dm320/creative-zvm/usb-creativezvm.c +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include "system.h" -#include "kernel.h" -#include "usb.h" -#include "usb_drv.h" -#include "usb_core.h" -#include "isp1583.h" - -#define printf - -bool usb_drv_connected(void) -{ - return button_usb_connected(); -} - -int usb_detect(void) -{ - if(usb_drv_connected()) - return USB_INSERTED; - else - return USB_EXTRACTED; -} - -void usb_init_device(void) -{ - return; -} - -void usb_enable(bool on) -{ - if(on) - usb_core_init(); - else - usb_core_exit(); -} - -void usb_attach(void) -{ - usb_enable(true); -} - -void IRAM_ATTR GIO7(void) -{ -#ifdef DEBUG - //printf("GIO7 interrupt... [%d]", current_tick); -#endif - usb_drv_int(); - - IO_INTC_IRQ1 = INTR_IRQ1_EXT7; -} diff --git a/firmware/target/arm/tms320dm320/crt0.S b/firmware/target/arm/tms320dm320/crt0.S index e57e28a470..4abf1e5e30 100644 --- a/firmware/target/arm/tms320dm320/crt0.S +++ b/firmware/target/arm/tms320dm320/crt0.S @@ -111,7 +111,7 @@ _start: mov r0, #0x20 bl _delay_cycles -#if defined(BOOTLOADER) && !defined(CREATIVE_ZVx) +#if defined(BOOTLOADER) bl _init_board #endif diff --git a/firmware/target/arm/tms320dm320/debug-dm320.c b/firmware/target/arm/tms320dm320/debug-dm320.c index 37e48d16a2..a82984f90b 100644 --- a/firmware/target/arm/tms320dm320/debug-dm320.c +++ b/firmware/target/arm/tms320dm320/debug-dm320.c @@ -370,17 +370,6 @@ bool dbg_hw_info(void) button = button_get_w_tmo(1); if(button & BUTTON_POWER) done = true; -#if defined(CREATIVE_ZVx) - else if(button & BUTTON_LEFT) - lcd_set_direct_fb(false); - else if(button & BUTTON_RIGHT) - lcd_set_direct_fb(true); - - lcd_puts(0, line++, "LCD info:"); - lcd_putsf(0, line++, " LCD direct FB access? %s", - (lcd_get_direct_fb() ? "yes" : "no")); - line++; -#endif #endif lcd_puts(0, line++, "[Rockbox info]"); lcd_putsf(0, line++, "current tick: %08x Seconds running: %08d", diff --git a/firmware/target/arm/tms320dm320/dsp/Makefile b/firmware/target/arm/tms320dm320/dsp/Makefile index 8cc1bd98c0..42cd01254b 100644 --- a/firmware/target/arm/tms320dm320/dsp/Makefile +++ b/firmware/target/arm/tms320dm320/dsp/Makefile @@ -16,18 +16,12 @@ LDFLAGS = -w OBJDIR=./build -OBJS = arm.obj main.obj vectors.obj dma.obj - -ifeq ($(findstring -DCREATIVE_ZV,$(TARGET)), -DCREATIVE_ZV) -OBJS += aic23.obj -else -OBJS += tsc2100.obj -endif +OBJS = arm.obj main.obj vectors.obj dma.obj tsc2100.obj OBJS := $(patsubst %.obj, $(OBJDIR)/%.obj, $(OBJS)) all: dsp-image.h - + clean: $(call PRINTS,cleaning DSP firmware)rm -f $(OBJS) $(OBJDIR)/dsp-image.out $(OBJDIR)/dsp-image.xml rmdir $(OBJDIR) diff --git a/firmware/target/arm/tms320dm320/dsp/aic23.c b/firmware/target/arm/tms320dm320/dsp/aic23.c deleted file mode 100644 index 8ffa5d4e70..0000000000 --- a/firmware/target/arm/tms320dm320/dsp/aic23.c +++ /dev/null @@ -1,60 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2008 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "audio.h" -#include "registers.h" - -/* based on http://archopen.svn.sourceforge.net/viewvc/archopen/ArchOpen/trunk/libdsp/aic23.c?revision=213&view=markup */ -void audiohw_init(void) -{ - /* port config */ -#if 0 - SPCR10 = 0; /* DLB = 0 ** RJUST = 0 ** CLKSTP = 0 ** DXENA = 0 ** ABIS = 0 ** RINTM = 0 ** RSYNCER = 0 ** RFULL = 0 ** RRDY = 0 ** RRST = 0 */ - SPCR20 = (1 << 9); /* FREE = 1 ** SOFT = 0 ** FRST = 0 ** GRST = 0 ** XINTM = 0 ** XSYNCER = 0 ** XEMPTY = 0 ** XRDY = 0 ** XRST = 0 */ - RCR10 = (1 << 8) | (2 << 5); /* RFRLEN1 = 1 ** RWDLEN1 = 2 */ - RCR20 = 0; /* RPHASE = 0 ** RFRLEN2 = 0 ** RWDLEN2 = 0 ** RCOMPAND = 0 ** RFIG = 0 ** RDATDLY = 0 */ - XCR10 = (1 << 8) | (2 << 5); /* XFRLEN1 = 1 ** XWDLEN1 = 2 */ - XCR20 = 0; /* XPHASE = 0 ** XFRLEN2 = 0 ** XWDLEN2 = 0 ** XCOMPAND = 0 ** XFIG = 0 ** XDATDLY = 0 */ - SRGR10 = 0; /* FWID = 0 ** CLKGDV = 0 */ - SRGR20 = 0; /* FREE = 0 ** CLKSP = 0 ** CLKSM = 0 ** FSGM = 0 ** FPER = 0 */ - PCR0 = (1 << 1) | 1; /* IDLEEN = 0 ** XIOEN = 0 ** RIOEN = 0 ** FSXM = 0 ** FSRM = 0 ** SCLKME = 0 ** CLKSSTAT = 0 ** DXSTAT = 0 ** DRSTAT = 0 ** CLKXM = 0 ** CLKRM = 0 ** FSXP = 0 ** FSRP = 0 ** CLKXP = 1 ** CLKRP = 1 */ -#else - SPCR10 = 0; - SPCR20 = 0x0200; /* SPCR : free running mode */ - - RCR10 = 0x00A0; - RCR20 = 0x00A1; /* RCR : 32 bit receive data length */ - - XCR10 = 0x00A0; - XCR20 = 0x00A0; /* XCR : 32 bit transmit data length */ - - SRGR10 = 0; - SRGR20 = 0x3000; /* SRGR 1 & 2 */ - - PCR0 = 0x000E - 8; /* PCR : FSX, FSR active low, external FS/CLK source */ -#endif -} - -void audiohw_postinit(void) -{ - /* Trigger first XEVT0 */ - SPCR20 |= 1; -} diff --git a/firmware/target/arm/tms320dm320/i2c-dm320.c b/firmware/target/arm/tms320dm320/i2c-dm320.c index 364d3b5c17..d552ba6b68 100644 --- a/firmware/target/arm/tms320dm320/i2c-dm320.c +++ b/firmware/target/arm/tms320dm320/i2c-dm320.c @@ -156,13 +156,6 @@ void i2c_init(void) { mutex_init(&i2c_mtx); -#ifdef CREATIVE_ZVx //TODO: mimic OF I2C clock settings; currently this is done by the bootloader - IO_CLK_MOD2 &= ~CLK_MOD2_I2C; // turn I²C clock off (just to be sure) - IO_CLK_LPCTL1 &= ~1; // set Powerdown mode to off - IO_CLK_SEL0 &= ~0x800; // set I²C clock to PLLA - IO_CLK_DIV4 &= ~0x1F; // I²C clock division = 1 - IO_CLK_MOD2 |= CLK_MOD2_I2C; // enable I²C clock -#endif IO_I2C_SCS &= ~0x8; //set clock to 100 kHz IO_INTC_EINT2 &= ~INTR_EINT2_I2C; // disable I²C interrupt } diff --git a/firmware/target/arm/tms320dm320/spi-dm320.c b/firmware/target/arm/tms320dm320/spi-dm320.c index 2dca324664..f1f5828430 100644 --- a/firmware/target/arm/tms320dm320/spi-dm320.c +++ b/firmware/target/arm/tms320dm320/spi-dm320.c @@ -43,10 +43,7 @@ struct SPI_info { static const struct SPI_info spi_targets[SPI_MAX_TARGETS] = { -#if defined(CREATIVE_ZVx) - [SPI_target_LTV250QV] = { &IO_GIO_BITCLR2, &IO_GIO_BITSET2, - GIO_LCD_ENABLE, true, 0x07}, -#elif defined(MROBE_500) +#if defined(MROBE_500) [SPI_target_TSC2100] = { &IO_GIO_BITCLR1, &IO_GIO_BITSET1, GIO_TS_ENABLE, 0x260D, true}, /* RTC seems to have timing problems if the CLK idles low */ diff --git a/firmware/target/arm/tms320dm320/spi-target.h b/firmware/target/arm/tms320dm320/spi-target.h index 965d499377..16fb2ff01b 100644 --- a/firmware/target/arm/tms320dm320/spi-target.h +++ b/firmware/target/arm/tms320dm320/spi-target.h @@ -23,9 +23,7 @@ #define SPI_TARGET_H enum SPI_target { -#if defined(CREATIVE_ZVx) - SPI_target_LTV250QV = 0, -#elif defined(MROBE_500) +#if defined(MROBE_500) SPI_target_TSC2100 = 0, SPI_target_RX5X348AB, SPI_target_BACKLIGHT, diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c index 6df9868f1c..ae8472ca53 100644 --- a/firmware/target/arm/tms320dm320/system-dm320.c +++ b/firmware/target/arm/tms320dm320/system-dm320.c @@ -27,9 +27,6 @@ #include "system-arm.h" #include "spi.h" #include "i2c.h" -#ifdef CREATIVE_ZVx -#include "dma-target.h" -#endif #ifdef MROBE_500 #include "usb-mr500.h" #endif @@ -370,10 +367,6 @@ void system_init(void) IO_GIO_BITCLR2 = 0x0001; #endif -#ifdef CREATIVE_ZVx - dma_init(); -#endif - #ifdef SANSA_CONNECT #ifndef HAVE_WIFI /* keep WIFI CS and reset high to save power */ diff --git a/firmware/target/arm/tms320dm320/system-target.h b/firmware/target/arm/tms320dm320/system-target.h index d228129e0f..cf5a278dc2 100644 --- a/firmware/target/arm/tms320dm320/system-target.h +++ b/firmware/target/arm/tms320dm320/system-target.h @@ -38,16 +38,6 @@ void udelay(int usec); void mdelay(int msec); -#if defined(CREATIVE_ZVx) && defined(BOOTLOADER) - /* hacky.. */ -#define SLEEP_KERNEL_HOOK(ticks) \ - ({ \ - long _sleep_ticks = current_tick + (ticks) + 1; \ - while (TIME_BEFORE(current_tick, _sleep_ticks)) \ - switch_thread(); \ - true; }) /* handled here */ -#endif - #ifdef BOOTLOADER void tick_stop(void); void system_prepare_fw_start(void); diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h index 5a404736b4..c29c4e0be7 100644 --- a/firmware/target/hosted/sdl/sim-ui-defines.h +++ b/firmware/target/hosted/sdl/sim-ui-defines.h @@ -219,24 +219,6 @@ #define UI_LCD_POSX 58 /* x position of lcd */ #define UI_LCD_POSY 67 /* y position of lcd */ -#elif defined(CREATIVE_ZVM) || defined(CREATIVE_ZVM60GB) -#ifdef CREATIVE_ZVM - #define UI_TITLE "Creative Zen Vision:M 30GB" -#else - #define UI_TITLE "Creative Zen Vision:M 60GB" -#endif -#define UI_WIDTH 383 /* width of GUI window */ -#define UI_HEIGHT 643 /* height of GUI window */ -#define UI_LCD_POSX 31 /* x position of lcd */ -#define UI_LCD_POSY 62 /* y position of lcd */ - -#elif defined(CREATIVE_ZV) -#define UI_TITLE "Creative Zen Vision" -#define UI_WIDTH 1054 /* width of GUI window */ -#define UI_HEIGHT 643 /* height of GUI window */ -#define UI_LCD_POSX 129 /* x position of lcd */ -#define UI_LCD_POSY 85 /* y position of lcd */ - #elif defined(SANSA_FUZEPLUS) #define UI_TITLE "Sansa Fuze+" #define UI_WIDTH 322 /* width of GUI window */ diff --git a/manual/plugins/xworld.tex b/manual/plugins/xworld.tex index 36585615db..29e97e4f99 100644 --- a/manual/plugins/xworld.tex +++ b/manual/plugins/xworld.tex @@ -49,12 +49,12 @@ Additionally, ``extra'' data files that modify the in-game strings and font can \opt{SAMSUNG_YH92X_PAD}{\ButtonFF} \opt{IRIVER_H300_PAD,SANSA_E200_PAD,SAMSUNG_YH820_PAD,IAUDIO_X5M5_PAD}{\ButtonRec} \opt{IPOD_4G_PAD,IPOD_3G_PAD,IPOD_1G2G_PAD,CREATIVE_ZEN_PAD,SANSA_CLIP_PAD}{\ButtonSelect} - \opt{SONY_NWZ_PAD,CREATIVEZVM_PAD}{\ButtonPlay} + \opt{SONY_NWZ_PAD}{\ButtonPlay} \opt{ONDAVX777_PAD,MROBE500_PAD,PBELL_VIBE500_PAD}{\ButtonPower} \opt{SAMSUNG_YPR0_PAD}{\ButtonUser} \opt{IRIVER_H10_PAD}{\ButtonRew} \opt{HM801_PAD}{\ButtonPrev} - \opt{SONY_NWZ_PAD,CREATIVEZVM_PAD}{\ButtonPlay} + \opt{SONY_NWZ_PAD}{\ButtonPlay} \opt{MROBE500_PAD}{\ButtonPower} \opt{DX50_PAD,ONDAVX747_PAD,PHILIPS_HDD1630_PAD,PHILIPS_HDD6330_PAD,PHILIPS_SA9200_PAD% ,CREATIVE_ZENXFI2_PAD,CREATIVE_ZENXFI3_PAD,SANSA_CONNECT_PAD,SANSA_C200_PAD% @@ -73,7 +73,7 @@ Additionally, ``extra'' data files that modify the in-game strings and font can \opt{SAMSUNG_YH820_PAD,IAUDIO_X5M5_PAD}{\ButtonPlay} \opt{SANSA_E200_PAD,SANSA_CLIP_PAD}{\ButtonPower} \opt{CREATIVE_ZEN_PAD,SONY_NWZ_PAD}{\ButtonBack} - \opt{CREATIVEZVM_PAD,SAMSUNG_YPR0_PAD}{\ButtonMenu} + \opt{SAMSUNG_YPR0_PAD}{\ButtonMenu} \opt{IRIVER_H300_PAD}{\ButtonMode} \opt{HM801_PAD}{\ButtonNext} \opt{PBELL_VIBE500_PAD}{\ButtonRec} diff --git a/manual/rockbox_interface/images/zenvision-front.pdf b/manual/rockbox_interface/images/zenvision-front.pdf deleted file mode 100644 index 386fa7ac5a16ac8f63866a62c96f137c2e11cb6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 218758 zcmZs?V{|3k^FJKh6Wg|VV%xTD+nLz5?POxxwrx9;nSbuR-}PJ1i|18$*E&_7Q?A~- zH<^Nn7#$Nm8w^>?b?qk%3n3$+y^$3RFE1g3jH#Wuiv=O;H%SSGkdTl;%+kii)amSuksxhE`8jkRw^@hpzx5)1^Un9{ zcloHtuCr&?v2)k2M122`>qCw>|Ls3*_Y5toPiv?C=dZj{mJ(fgT+1JCZ(D!<cC?yBZAn;^r1w@lA@ZW=WW5=bE#(kS6}Z;dLiN}}Tne#tM*Lbw z6^E*ZkFD@+;?sh^PFAQh?y-u!9N3b4f*U{i)oQT>cEK zW44OegI|@x?C%v9e|pCa#Rc`Pc*gGqx}y@$dAvX)Y{_z$Wj9ldGmo`P&=X|3v&vVQi*9{C}M=>$5|%FnYE0OOjPnwDkB z>=SqW;?}SYpk`~^=P@lDzq));XgW5P&e^{*g00qN;6;kNh!@+3-Th##RI}^ui(sX% z3r49Pu;;k+~jmK3h{mOs9Tpv*+D0CcI2N_{PRFOd;oBqyVf~Q(~G}x zM~iT8T^|w_d7|;l0A^k=&S_8Vs@4ul7Hs3D{+x{P`!=0Q@>thz;xMO2V#ChIse&5H z524R-qqny;@6)@oRM)qsX6v&plB3Rd{rKUhd%yf9EZsCS zNMJ`YF#NyH_3>pI1NZ%6DP@6YEW=UASXjS&7)m-gxyB!O#n*WUmoh7s#poq}l!F|0 zM+#898&|#oWb(60`K$dV3Ad=;2l!y07V>w$@TjKq>*HkO!~UFeJ8>0fLa_-3*syedi%;RJbyy)hWcqEVW_sAg zUM!)mYKu5>DP99I({XkeUjXQl+yznlunXCZ(^YYTzsGSEtOmGYToH-^mW%V!ESjZk zIpdZ>I?>r8EOD<~Q?|ML9{gHvPLds%;OR5qGGIw0>)xm&W&B-!vjYGA>8Se!!j)9! zB(88XYK78`X{XaZPo&SJ>+u;}M}*4Q#H1Lm4cX6D&#*7NyqpB-h0F>8@47dObleGn z9a4;5%a6g!Rk(qiM20P8mO6M8Tdsw46b0Lar6+`)M_j-uqsGD!XIjrMRqcnFje|m` z&w@U#&Ar0R7dI1(6w=^wTF|J0F*3^+;lOjOD?yb{@6DoePCSv4|BMh<*nxeNhq?^F zyRwXZoeXCiZKx_QH&6cYs zx+!Wx?8}W~++ZkL2KUfajyu*mNUJFxSCyZvW?os;o9@Y zq9aX_fY)vRVg~kZ+{yHj$r9u=;aAO3BI`Fj=eP~fryP?TTdYe!8|+Ya1p68V(5ar1 zzYxAo$H}`ywY(7SJPU@M2tf78Sie&X&gaB>7G#m|r)eh}J(!ePbcE11WA75t7h9-B zBm#B(Pk==*y03$BW#4@dMmNtvEvo{KFgi#ZXPF&^NyMGT8J# zZ7&9wlm9dWk}ZF~y68ck883$uQUaf-G>~4#t>-(_262xTBBlm@ZjOF%uCcHQHtb#mDUGUum-HgSvob!nL15cWzt`rk z)#ZR*iYk1OQ?~Fx)Eid@8PzR=mDtt5O0h%`CTk^HoxvIOs*Dd?vk7KsS1n)O4rD1Y zbTI^dq^je9i|X0pthO(-!At-oK-cKLq0PUcmH!V~3kYULI1sZm?8xQ71l7UkUdhU4BK>2;Zl)P$}=Kv0slZ*OLpT(JJ7P#8R{NS zSzjn3E>Su{o&}XnQAV$p{9+~3KKyOO8z5bQ0a;pXANIzIiatasu)kh6vND0&&|Q+; zIEG)w0lS4&L&~Q@B9N2k@1tYYfb z6kY{WCd7()js%acC7TIbCU9(7tR$ZsTV939B$}xgE{u(V?cs#>|L5+9^y1i)YJraUfJu^H7m#1xv0s z;_!jCXw^BS7SUTB3k7Zr8$4h(;S#9bTior zOSTT?!LU?%u0RVnvoe!^+>{;!H&48Hn=l_MUo==hE~|65c{=FeXs>L@C-0EKwT^l&WH0ZyWV4g%{lTrD*1$+ zKeSu{1_3+DZh3~c*{I*yq);9J_aS6U4~&8D3sJkp3}t=6LR;;O!%*|yz?}TLBTjQ@ zomWuBOu8Y5T1*;%@R2l#>;r+E^bXflGK%jLhNlSmip6>!gdzapOYWW)5UKA2QTvZa zzr}2Qn*d%bnJ798&B~2I#nI}m7 z-Ig;y;9xHmf7AkkeIx+bF!_f)>EQQRBD>4x3QdH7V80ikDoGp|v~LqvER)3#1kV!w zoA171q0hs#KC|WyvTpdl=BSt{g_}e@&bo3!i0cb=1%`GrUhi313=x&Kj9X3rE33&_tdWgVrh1V zRs2sJRLs^p5IpZ^0fgtmR{_GZRRAzS==@;7Yj`^tG36tc3IS{I)2~G91#r_osKJnS zFlx%ze>e@UVi{%rZ4%Fh^0%hzTKNI7pP$~_%hHs>=*`3Cl*Vf69UpL}xZJ%EHDtC0 z62SQXg*@*YoKpJ-+(c#vF6`yfh_$s}Ih?ZdjISTxvQJo*?HuOOQBld6234OifRg}S zjghEgl#wg*fD1p%lyld+R*p^*BMFH2h^CzrOv&dCv)IcOGnwO=1ARwRD(!?ebMN11 zmNt)%GRPrA2!1Bxf!kOVvX<1=Rt*sMDKhi#gK-ZRq`?Rm)KvC2HsrG!c*PAXhrVKL zmVRqURYeO*2HO+V{|w>4be5X8BfIR0SCSHYT$hm}YAmyhdjW+*GzZ z=G(!uIB&u%@Rq#i$3_d_ciMm6m=HmOUR zy*&(>BM%kP`N}(3#0OzrD>L6=EIee1ItV4xl7P53ezdfMsCdB9OI)W4dMICnx}z;F zWQ(E=P*Mhbz%1b4>dfsl?ghD&LSVF2#eC!2q6z13f6pvthb~}Lw$BO*z-zQvpp2!u8S$U@ zE@;NYkBahvE@&bo_vV5wIzrKhNG&V`0iGo(#k1+)bNzbd%V^&TT=!oBe>ZH5q&q(S z{^z|YI=B{n8KLAvAg;4OQG`l6(D}Kbbg(boZ{F4;4V8W|??QHU0hu63^k%nd!Y;H= z9gy27$+kBb+Ac;gnEW1)*RWyuwgjSjfo&`h*saa)s+`9Fn;*<)9o!DGFttbXU*bRf z>)R)^Aoi}EK84Xr_^5oSxiO&E@L~AM8_@GfAj4i~dz=UXY1tv`mLF-kx zkt-Ki)Ap9J2rUx@!+;UfOSjElXA5MT8(ZWe zAfF2)_$0Jz?Ba5Bbl_yxuZeiU5rPuEsV-ojGllVEi9%_`S=#>_zG#P}ozZpgwfznvDfYX;S+UKA77{`MQXK@(!7F_mu%VQhX359fkjUY3X?AHWm<6Kf;_N zgIOjeu2_I|LJ5ewm#`nhBKVPn55jB;g|);mT?;2DGwd^noE$j&Cc;#Lk|OAjv6Jkz z&qqCYp_zGQBi;()6ET_`826?@^9&bH6Kq!h6~KoX%h-S(fOucdJcdkQU6KRb_}$t5 z8}XTaF5wguAhbWfyZTov+tO=&XEaMA!Z4Ky&OQeG4=B+8fhywk zxPwqyf#v~qKoDwa{+rN%0g`Q^Q}3YcnFb5tv3z<-M`h$AlRl_c!I{^#>?fdjwYpxM zCX%%00r8JK=Y<2@L*U3jZ>9{UrW*f2=NoN8*0DP8hBYR%1bR?uw|MFxA!X>rkw2$W$xvJf`CGk$RX3d}OX&Q!JNz0Ex{!2|8`8_o*H^n@T? zbofi!D3e!3vi1(5id?=>n>&$MoE}(OCQNNkic0j7=cHp}nc$$9E@2I zcX2QrTLYWkln%!t$Kj)MZ*;7Pmb#E7A^2bnX(w%ap&yu zTGfapxCQ+cYWXTPE~CPZma|?Zl|!6Dr5a|D<_Qrp>chg1s_z>#B(xL(a;W)#e)siI z$nD}JlI(YgxK?Iw6x-3H0U%Y}U<~O+nX(7(L)LAq$*4;#JQDMXoydbSPmc_snqLG? zPO9!=hh*f&rbBb`N)m-_w9Gz~^c9W5h3hNp3w2S-Cu<)-1kNriGes_K;k8^4h2quG zJ0jNROUw?*_rSR|Ak0UIjF=vop;8V8a5A5oEwu+Nr8=M>8fFMF@yhW#S+aWgZ^dt{ zIhEvc>6Dy{!H6Zazq1`4Fa;{q5GPr<$Z)abF|JhM(VruV_N`^h%JpRFRP`5#;p)<5 zE?gr%}YIh@ci{=Tnhe zNJ0wgCpf`9gsIG>x(TM8D@T7p1+j~O!521k8q|G*sLUN_C(5egXm@Zn_ZAmFsxF9U z`sxQ4mo;q6;<9c4D_Q`{vS_!CFO2OBb2`9YS zGtc!B1yklZpnN0grD;Ud$k51ajNa-}9o~CFR8#PfWYPOjHA$aA)bo)Y1>X;IY3Qq?L^{uUC~QXh1gdxW?kA3Ws&2wOEH)H|a zQN#fBhZ~L3x%e0w^-l|{?rEPQ3~*0{wPo>*Y$0l9vNByW6E%s+TwU$;8;w>7eFa^y zudP`rSEk`~!dgU&*ut*G)FwtvhMuYXshqo7kIhuOe-Trg6<1z^KL{}%X~gT?l++{p zIr158U=WEN|fsq9BP-g9AIv*>f< zi$^5n@(G4G;8aqY)%oP7ED9^IL5TNHTyDWR@e(HtRvqGD%jR&5NdPUZ(D=(fG9zB! z0htlpjUE}rFDjt@NZ>?^mMi5<7nRt^1u*re0!u?v<9(KaEh)u?ROv^inO#!mGP(4# z(!k3aEYV5MO+QvVOSl>8s+)7dAiJs6W)pV`_N z`Y*v&xNdYyx_IKqEO7D9+@vUvkc0~Mo$^KG08Q-~t?PM4>q#NORQj0q<2 z(IFwocYHhS4s+=xL8w>oLD)Z38qn;E=PY3&mhK&Aa#sOZR~z1CF;e%Om#iTRB<-ZK zl@Rqyp*o)-QE@r!2$sbroDSODWTVh}kK-su)hXE*e{%Ot7wfWq|L*$h6XAnAB0jwc zTB^cN`IC~9%uyR5K!-XF0>kI78LmXIO+$jK&0)h^)+oED6J!XU9t(7?{wEa_zF?d* zzrfdm%3V?N97kA$%VKsUZo8(t3=OwxdB}|J^lG0&0P7y(is@ zSnd{ z3ab5>RuLz7$9F*gP(H*7&Z?XqEn zZ+xBz;&|41F5xmPVw6$G>qW@A#P#P#08PdWt3A=Apt1vl;DTBm$(FfN$ZN*3k+0ej zjF@Odjh97TpfxW}es@?Ni(OQMoTf7`oA_9O_Sj5iHw603O7|+zQl?NHaDM^kH5+SD znoW1u6A=N+D|R}k1L3xJ%+a;J))i7Dwmx^n70JzLRZbygJBgCH#JVL8+ky$Y0>RWH zphWHMm1zvs@Dqa`Q>-rKJeu5wQ2N2~z&XP*+gh1okA#rBwzRvx;WcoX@M-ZZ1Zo{N zLEH(dpn))3|GaDJLm{_^3{h^Ql{LX9!wU+qK zeoSq06vmL4OPlsaOloLTq+YAPFjVaLRg3zRFh#0a7#V!eXarG6>zJ6OT?ktJ#M!zW z`R8Syx7y7>U9hj)J9865aoBZGq=I1?`g+#8UCgG8XN*4+UQzBq>Hz>mn zY>u9vo_u8DKVE^8AgoN#&RsT=-}^I{j)mie*2Untbp;=AtD|hyp=bR}TS~J{y>1IB zL$R65<*EtsiR+u3Wj=W|3b(41yK&eUd);FXVrjuRyM+6Y_>d=sf^`b03bn8ee{OPE zSc3F1C8A>`byqr|ad{UYJjC5xh4MX#;Peg76$f}ZtRd@d=NLE}AP~~4*y|?5^tMXa zx~XsRgAaWwd%0dmwtM0nr%qg(8>)S;)Q(%JyI0E=CEq^jX_jfD4RTi-smE+#u6XLbJy-+PDwE*+>-OF@R>r1!)Y~hOJycKEQM!H-C znySMvUY0TY)Z)^G^tY;H(_l(O^izl=0cH*(3eo-`iFOJj-7p?o-uQgZu?f zaI)cr0)<|TI8q<(Ck3|oBl8Uu6Hu?S@Fgu2(k3#>+p->pjQbd}O|*^YEdBXv65)fQ z6XGwT7A0R60{>N-ES({1$>PH9YM@}_$PVt6;d7G?I^}{qii2l}=7cSJb>c2>LPBn; zF)XZ3R1t$>a3@gsv=OW{h~A;#0mYR*+z&Gq<59jVB=_DksUB!GuP>msN)tCDycT4z zo1w&qYzVLomd$T-cN{@B}8L%b`v&tXP9Wp}#A5ZIGpHMO4 zskO~nHcpL6s1#^miW%a?6=ndH2N%K0Fem9CkwRe))7KnhOL7+OY%}$u!>p=2*u$J!fVf z__5D>)uYkbhBp85dXDC{SU0;aAVMncoQtRM>{Q5OBmx$JxQ<*LtD@DO<|7y~fkY3b zzVoBLNy#9KeF2;K*mkSp&~?~mjD--DY`a*8e6f!T2|EFd$I%(=`ils2ExTA4>cst+6QkBl^8(rZHkVbZH2Q45uDnxDw3hl7pT z=wbWBta#b%A%^nK24;xV273Jhm^|G=UD7`-I*D$UMFV^~=8u}p%is;ysSi~s>+v*Dxg*cAl;ddNljhmTUqcTX+>`EOG8zV#}xdijOQ9fPO*9G;J5``I&X05;q7`)0u!3CUaf2725*YB+ztKSFk}H zM2H7mD`(<1_nCvWz8H#597L$JuOE!Jw37xE)yra7KaAr@%$f?2*hd7zG%KU9_)X{Y z$Sn&ONzxMPw)U?8$vHE>lC^vP!JGzmI^q1m7{a?&Hm{Sk0tv~rvWW-7%5&Y-QzBdv z)!U;>XwyA?q23S{fT&kkcr-dlMvKiF>gT4t80gFwY6rz*EiWX66Glkqh)HU3ZKRAy zuxucoB4f)0DbVq3;|wOBMZ_``E__vwJ(*q?5hXINM_8<$CE)9lg%jYtEIWl)i$bVc z%%@7?7ZawT+TF9dystp|7AbRYp?)=BD3FY1nU z^b6M!`n5;P5j2|xv~7ugCvj!t{b%9WT6}^|6P#w+GBIyWG`xO0+Q`VCo|i6=k#wN) zP_<2W1Y1Sg2Iq{jST@nB_2F~M7RkjSr@2zl^>Dhu{%GSeFG;dYM=xb^S|RUD`1XW! zqF+M8@zN!BV|DQ4M0=Ux=2? zC=IMajc;6`?J-e0j4a^xKpY-(aURi);P<-5K=7}|Tb}F4P+m2&!(Fm%a})w7)+m1C zW2D&T%*EM(9K$_cH_bsPk*pTm<~RU((H>zV-PQcSCj4iKyh-|q=Cuo^lEyW7#Tj7v zeoGsB_hCS@m529AI_)C2L#x@K6Af!ezVn$V8m3EcSo2Im`-q_D_P4mj)Xgm!S*r&S zi59$k!~#KM(fc@h9_?cb;>yZi9iH&}aUbe2w3*&tId8pd z)XOzh`qjoWl^PaJOQau{nsgHs`6?*k_5ZMr3 zd4P}7)~@wjQY)M+5qF6*{1~2IXmO<@0LfZM#3E>B7yf6yj_=ifW;qlGbx zWW;PRcf;aAl<__k7?Y8Fn}+D}L`?$~Gy-6SS6V+HI%a?$m+W9UcA%qqXaP#BR{e%d4_7)Ww~5G% zi}rBI{O)V-j08$|tM&U30$2T}m>GwSa==Tl{s-%#lC3n#ELZ?vRU~0LPJU{nLch#T z0QZ?kN18WqtAbqx$|Zs;1%i7hZ>)u^NXvFXn&>TRSA-~wk*GavoX~e$sFvtjZ8tNq z)Z+4_NxX}Y$>HZX)k3a|u4v_XilklI^>jn7q%ipmx^fkqEg?L{<~dX|WNE&mG;t?Y z&^38#XT5G&!W3k^f^bmPzKT=$+z^f?GbhBxC z*MZsa){TtS8ZvPgfdNTA7doSC5<(mtDdj3m;abK3Zzw38b}q1(Vwo+m5I1}L1)Cvp zq%@aA>m}Hy!1?inrxr*OT>T~HCSGls{z9}g=E+X=3CpYwMb=58g_J)LWmx-raX(*D z*rJ+bB0*VmaU}@TvP)*`RamN27ZAjY0T$Upr&4HT%>>LyVqVh52&E|#sjwX&knFil z!x(*R3Eq|xM(Hl+BA&cI1gLI(cnmkGRs8OsL2V&Ks~rzLexWcPJfSAwt;fcdS23(G zR- zN_UKO;}LB=4kmKCUVeB?=2Tb^b~z5liyj>BA|O|hiMK}o0r3K1m)(~m#T_mzP9&br zhwRzomS!2=pfGY=bTlCinI7u zB=ckT=_5tC!|kb5ijtQqQe0rO%bw_>thV$#@O%(R#*!PA1zD27eLt)hag43tjR-?j zf}yv11I}R9>)pvinW7NgK4&D_9Ia?i~tMHm7F*4k*%Z| zgH#m{jxNGk@cwNZnq?6^v>_;Yr}V2wsa6FtoBnNd<{&*(7m}jFhQ(VQSSL#7PtbL| z`3dw&+k}WDszzh|yYGlE&R;{Cd3qOSrmabaRh?#l^>R`;fFm=HEQ%qEBBAuuE^n)q zW=e?IoB@B7Q7viUdaA5l1qY@o06l)Ca~WPGeFXuztR~$o`(4ZZD0;&%mM6Ad?@rII z{mes5GhPGq@ltQyZFes{=$F%M0uy1uT@${-(6UAV6hQ-piiQ9!iWrQ%7O~Z z+{kmF!n5LAE4wIDcgfL6faa1mcDibUf&as7ljDqdjIwAJLut|ln`5{Xy4mD{m4X@F z65ex36a#bppp0CFV^0e85})@PwZ%v5Nbad49cTVj49b>Fqa4%mPsjxX=QOOPW|1C@ z^b10=dO!vbM!UN2bqJ^9Ttyu5k+PjUVrP3=MW1i$Jxl>tKYAGsw{+XIubLfskg)c` zF3BRjDTs!K_;g~pTUoC_slSg-WIJ$5_*3`Y46hJ<-9p?>Ify|59}Rwq!m4wCcskR}Wh zZQ_K9eY|@Ci%h=^S$zQ2P=u|zcDg3x!6FDQ0XD;;u5d>4qIB16#9Ei&qz~{Jm;l!g zlTK#uvJbc^53bmH>t0dj9POt$44_&8X7OYWjfAv7f83!8kD_hPK+wXnJg} zzcefC`nnCQ22aRF&A>${xaHi$%L&8QAj&g+rsHM^y1%G#g~mtSD&En`@mK<%l5+*6KhDIh-pZL32Vh8m z?W=GI9OYkTSCVY5cBPAH@YNxm+Y)csja60l?t#~i{Lzzj;YE{RkEl>S9E-V7W$HRs zM#^g>!+~*KIEvr~h@l4B5^bDo-Jiwz4M)%VH4|q6daZu2%l3--$eEFWuH~+piT&w0 zNdMI_lJP-tTUjjIR6s8}H1Al6Q;!`$7H_1V9u9@ZL_$um#&&Ip%0j}P>@SF7Y-8M# zW9OmwLsTzk3>i-@W{lYNS4WP7QIr+eG?_zyWh=pIx0s`D+l79+gYRfS>q5C*z-z>t z+(^A?Lz|gEG9N_;$rNL@Rva;LGGcgVjx{=Xak7Amcu2Vc&MA85O}NT}tBjj?YiRYH zsa~y>SjhwIu#TnAm0r|Ol@-sC{O4dIndYx@r`H%cz>^Y>?)#l2RE{_@*oNtxN=4CNg&=9ju6yJ&31MHuu z^?x`rVNrVXa$c)L{dnGgE1z+Q*0QooYryW;-s}|4rjRO$_@02`tDi|1j#Vvk7D7x_ zJT(Ur)d;zx=3C$5}MK^_xIW8x{f4puOLt@zDcbro0(9IR6j@R-?~tCUV33Lm?pE ztozrU%M)Lue)G*=)UNttbX2pIf#$DalrB-Dk0g7bP<>#p!Y|C&a!-dw9^(01nhYC_ z32VW~wtf}ryv*Kmefks_H~M?W^u8974!94{R@*|W?-9bG_?c&uM*L0}n}8yL*AP@C znwzuO5c0d9VRvhkvr~1Jwh)SDlYBS#@5PQ7*qK&4&btph&++G00YJC%clE@ze6AJ8 zh|NWRc15=(|ItJVf^Nuke~MMs8tVZiG=2ls)E0Wd_tbdz2=|DGC zO_t#H1ZgKB)CEHQK7y;79-yV^g&>A8luo5ejDSpJx|7(D7;If1C*AqK9R|C}`K&=U zzl=aqaAfLq;7_OpA|@+_^lFEB&ug<;wP-QjkDp9kvl7U%vA$y`@%jKdla_Oq*qwyM z5px~Su@Y8%iv5#wCV{vVyPy$#J$0k`%l&BP8T=;?E%7?q{aK^^YFf;c&C9Pgs&%m- zkAQ&d8+d4GqmJhr7`_$XzlQRE!RJ$0Y0g0S^m3RzLM?bKQmnPLs$lhZkaX2Mhzxi6 zbI{jr=9GF9yM=o8&dzDP0>yO?onu{GuY#&^eSJ{|xDtbE$Kp7>lr%zXn_zfv9(rV_ zSYC{`sbk$qWDx}yzpOm66$8bNAvVl{GPye`K6QWC5DrR)TOrQ@ zq*f+@;g;SKzTCbJVtq&vuTat0OChr7(&R})^s4`3<1{s4qg&RwVenZpr;)W|)0r_= zG9EOz=a<&p1Tx0-{Ktcy^bdTre&1$kL6C0RvCCfKf_(Bo7ltw9CI3@OV&<52q4ib( zCX(he-1o4jvs6XM4=PTtC90?TA}YuWQ6KF?@{_pLqf8o+rk-BTBKji}9cDY$6V&JU ze&A=cd}AbGmA8JaC+((p+ff^&1ab_qm1-RlY>nqNwwCsrp>p<1E7YvIzl(RApq^YB z!!cSRoaKDaKBa(E>7|7GkeQcMGsq->s6*9c9=J=lp1uq7AaEwEYVa2iYL=mBuTXO3 z0Ycq10(foA1;mgVBRpNDtu%{G4jrq^%0cv1tc0LE0>nZp5u1Pjca3=ka0FCVj6}=r zwW^?eWYk3uaSp1LAfQuuh(wI@dN-|IN5ExZ*;aZEZ$2oRBrk~SpsBOx%D2POwhT3F znCh(=n4o)kmJDcPR<0;-TMO>Az#C0??n|hJ@S_EcdAX~FQ0xxDNn@^swo-RhimBsT8R`qsly_oD!df@kxrti5fKU7$o7{+RfHHOTx|iaAC0uK2CjcKRxsiE zKdS=2*Nf`13SwS)8EAI>mOh3J4nPEd&2&Y}ag4AGq{l+&C+-BL6q>I2CoX`s>1k$8>F z?BgXMCgpbSvAM*Qv2Q}v-K&VZv{ck;e}Nc8nLRi1-&qqQim$rP?zqvM%*5c9@lKM> zVtET8*xi^~b`VzrW@g!HezUb}yu%DLtiN@V+=HQpZ+0Q0-#p4hz8xe(Kr@WJBu>44 zO106^%5gO+e3j?(Xl^mxs$l=p9^Z#N&iM*t_v0BB1CX-onzh39aatk_82GYpTMU@KQ5^kg&@Pszgo#6}X% zYvdM+?+EZ-i+2(=TAXdAmHjON&|4pOAJIiiyPC! zc?iDj&IIB7Z{AM^6H@WIyg3SYgU8%{}Z;Rp1h z{ib@oNB7bLN&_PA7-^YdwVTP|O5!c0`QANd_bMXf@aiRfl(ZCm8`+VPC*Rvg-xAhj zxltKyvh#5@Ez@>9Qw&u`k7r^o%I#l$hr;kc+7FJsop0)Eg7Kq2A@v@brE&4A1xv#= z;~p-pYusBA^y1ntPJ_QYvhf5b{Nsz%NAVMU9eu0eir26$f~gJ@)qQkfzSyyA(K$&JYr``U4kuXcO$-p3;C zdpBTO@HVPjsQN}webEk<2Qp5ld$K|%o-Et4gT&(~Eji+>;T7hgfSY0NEw@-BVX1MSFyO%;iZJkL5mT3l%&xn^F9oP%`ffs(M){N_h84K z@BS+}c5gwy`r4%%6;Xl=YS8otOLPVXeF1?_)L)ffMLI|w?mF@C0@$v4nHppu9qaBA#vRou#v-*oJQOwU6NIjK&FMh|X~ZTZ`Po_` zCocP-Q%;VZdS|?!rl{9EnW6jrPbw|`((40vPhLOlV_Jy;nApUCI;h2sR9%DMJxnPMB&EO>?ru=!k{^$&u(gr-8~WQPm~Ci& z88JY;UGj$9-g?!*lRR~BO&`RG$l>+2%I-4p`6v+|Tyr0ZS_rd;1|^Z0xPt+bP={)< zr*w@@e+CTS#*ZrN5&g`y2xRMDf#hWMJe4L&(3zX+1-AMy|676!YH9DA1g!fcCrfXYM zUn+%Md8ZRv`X+g~-5VZqipJC``;dHR)(xT;N?f_26LjC!9C$N9z+7jV^zc)hS&5Y? zTW(aaPC_x0{KuUb1ySyr1?Mf8f7@ab&Qsf>%mWWinT>kiEl>BGpd6E_yoXURi*Z+0 zh9ep)uU6Zp^B50gi@%o8)dDvpA_ivekCAZta2_*AV?%fdpF1D7j%5kO5VOo}5&L4` z{_j&DKa;z&tJ8TXJgv!g`a)#0mhS-rR4g(__n9a%Pb#VGy})hlPT&`385yT^94Wb9 zBgQhpJg|eb<&N|*JN6}U4yk#rgS##l3c9b0+!6~Qe`#x|c{2D~bDW%`%kO@0o*L|8 zvESvFDRcKiYOsKl-p#3|T@J?c9w!Q9&rweCg1|S&f}SAu!q}CiDNu)>-KlW8Uc^t1 zX&spBaEC`2@X2i~3=`4$!9YtXa8biNIz z2&loufkECJli}>W*^r^(*ktZDh-jdpCaE03N-i~C$7)-^esq6+a&UP7Uj>O|Cbe$q zE-rqbAmvR72&5wvKRHdgYlEELhU+uNq3iI0cJq{v`oW1u{Q@h$;VAl&ox8BFeiq2; zN$J4Nl#*TA{Yd&A>Cl`>5nC?(63rA4jz8`t^qFweH5Wof!D_Z^iVy!RrU1<(Q4tS+y(&=yY;2I zGS`%F@CozOaA50iISB1Ye%bC)YyQcm)H-yrKzrbLq)J{eMg z;jU>J1~_t5R%sx9g4t{|#9U5V^9-rb#$IC%ZYh~*%CEWm_vupI)1iA&J!J zjq{N7Hnkyy?bT3_(ppVpl%F?4TiD!z0DBd`)O=RRsM)ERahX^yv20vhf%uX~8oT27 zH?|~N2)-SJgADukn_xUf#FjgW?}N{g=DM=nVU=>23LKf-#(r|P6_^n6xu4mRaQX$m ze$Ec%eaNt<+8iL`c0>lvXhkvb zQM%_$DWFRo2$tki@SJJe7rK(S{V#^sXL-#Br~Wqh*3+}@B#);(Bo0J_H*o%LCT=`% zY79-`h3XXMk=7pTNC(yJ9#CFY$BT`tKS}1?0EZR6CBkMF-xA?=d|-xKFO&mtdy|BZ zxQnk6M-uvuza;(J;j-6lIbIMp++J8x_{eeRuM6c*ppz#vip5=5+OA8 zl>UBhG?T-l{{7`$i$eT#XufDfbTdLyffG?L&ZbO{?xvtnSIhPAVX#Kj)V5hy9(&Xa zRXq@3A1x8KUNkcpRFFcpL*XJ`gAde6-~DtMtr*1{7Yfb>&ZLp;ZNWTI&o2dtmR_55 zR-)VAR08PGA=q~6Nh_ND0D)0h-cK(%!;UrKcXLG#5a9Jyi9A5E8JOhW4oNhu?KNlh zn(pTq+sASM2+qq>bJsQNV)HM9KCY5*5tjc)-kZQv-F%PZPYbPAd+KJnB`pefb?-$a zAzMhuPRPEmS(A{2l2RebT6WpjM5zebDM=I(*~-p;-tT*_Ql70(&+q@do^P-5JhQ!L z&YW}R%$b=p=Vn$PsR`jaW6w~q`*p&;%=4ip7wER|xfOzZp~&W0E*4~iLrTxq{^QpWOYhgCZ9EQWO8LZCMp>?rdsS(+UMzQm_vZn*7q4&h z1juk+7e|&3N}SsJ@!aKFuWMDe&dGS)Wm6oow{kIbU;CW=Vb{@ZgraJ%HRXbdo1>q+ zWwYhkTVTD+^4*7Rj7;>4a26AJqSFlIL^>_3Una8}lKgII4(tFTvxl7wSBwZ_bT$)QC;Bpvw$W zeBKsU?HDe-zOG3^S+l)dmo&?M7O7#ms|bb z!OPN{53EfSy_&z=hi^H!NlwwYRZ&r$b>`}N*Ob%TOk5jE5poe{gryi)`kz~)V#FYl z&XzqAIP<0eNqFCV=taugY`O=pOKH(A!6<()3acg95? zZ@6D0ww=?Z^hkH4?9$H%;|@p1ltQoSPfUy(D4Ksv0~P!Rva`j zX7#jDJ@8u}o2ln#xj5m8xbE)#F2~>5t?Xly=1$zgK63fm+9>A9j`DUD7WD3tY{tBM z%lvEf@Uya7n4l)H@Us!GQv0~KNJPowgLJ1nB1(M@ss!zjKXPx=YIYL8<5>Nj89)2! zE1MX+*2}K+!bUxnrC*N;ijc(ysp+AE+;?MwvW57U3HzwekheTjH*;a|vTB@JC!AB; z;?wf9;N{!oIt#0fuM#$K#?kQ^y7br`^L~G*{6RR+apHkpml$p_6dp`7yI#J+^6hif z#o1Sxhnb}e{cc?*N?Y!1Ia{^7Pv}YpU!hUZ4Wk>=2U}8Gv3*(-%a=QCl$r2jThFNL ztAJ8_Q5AgT4zq8>?R{x4@V-?X2A}O8od2+W13~QQ>r3vkd~HPyz!-sgNU#?Cpe zrFiwFqFv`11251?C7)kT+}Js!*hymN*g0V*%}2N6zOIDQk;0uHT@Ni`IQ=X;=l)aV zv_zTa;gi`#_v(k9K6yjeRpTJ$)o}KJa*~Ih#Dl9?E8ckeLzk8}K=(Q8Q-!Ob2VGrntH%5Bdem)KpxP&yYjp6+w-4 z56(>=jXTdnWd**tT|`M~jW z9vWL%UH!+dlh_{5T%Gb#5^4Ohecvh5+6L5P!O1bdHGK~1OLg=D-w|J?Rapk#4PX|l zP8l>DF%;BMa0yV*Ygu(Z5_w*zeE&(FRf)s*)^n>F-hX`kOZOYqt&$JrZeNV+Bn@RG zZR|BlAHMnF=6kzc>)66-Id#M{S3*6KIo)$-!_@+=khGy>)f?B& z^4!y1TJ}CzL$V#gxSBuq5{_^8>fzYrceAU{Gq`BQ#_b|%9FLTby4KNc6v7f+;Jo#`ir)wipsrd+0xTaj=SE!eirmto$k<`ycOb=vqukj#!DN;t;oHs z!<$%3j<;yW?g%JvZ{zZIn?2%kXfkf-_JOSZE-h@ko&>2~PV6{)JaqY4V_)H`wF;Nh zL(!iS(gNRYNym)!JbAjUHKE$j2^j8Y96Lt1M(S972{_cjF7jj;w%u1j>^Vb z+=^bs7q9r?G#Jr2U)WH3gO< zcD;UfeHZO|E;c8`?=cHYo%9|!c(I7tx@E*`Fh^$=^LA_`yhbL0r%2(Wcxdg%9xsL= z9*nVw;MB|Xftq!Gd?$~-IGw!h+FvTP!_tyciZ{CEIM3rZZD6F=%v@}N4@=p)or9!^I`U`l(*>J(08@$eTVhh zgUMZ}&FQS$5id4wZ+>@g@P183gxAOXujJgKpCNzb87VoP&QCSd zaLB{aD{J7%=8T(H_)kAt+O#BHiF-}e-MT2kF`4%dEm^hi)oePdki%eT*67Vv^Cfmi zh)>zdO@qn>yR9F}V$H@AybL!=B39)L8D@xO+Vi}4R zH1i(s?QwsUf0NhyAl>QpV(Ho3N1~UpkAa&`l_M&OLi@6g-QUQ3aP`yl52l`PFX&yQ zSK*8uSFQEbs~n07h|m*51z#(WlHQDYwVI?OQ?(<(*u5p)mvmxGY2Ea>k<|TdDKfdM zTV^kYtX3Sf-z>OGVUz0CZJJdF@3$O|t$vMsblP;Wm__l7>aF0)LDt<{J#X#^J1>{% zrB|r8n6c{tzO17|WXY;>rrl1G`TU=*F5;Hvh}7)5__nyyr7Y>9RPDBk@{@Wxn)`aw zQZF-{uUYgm>mklH+4$im{d(C=v)6eW>tn^Z8;@Vpc~d%iOevJEc1Ge$l}d6hV#2TC zZ3+ImMZ!ASyzV%@%+1)-F;#1w$g%H~m#ko`IJ>XXhdEz|$$e>IS~~*QGkme{kjbIL zPXtfheD2OWoblU6*5Zcf6AFX(-fZ_xJ{#tfeV8-KS|xw02_ej}^L2%|yYiqK&k}*N z_GL!~`nRBEq@Ru8>vKgu`ETi1zvqPdn1ddt)n4hIwN`6SuB!R-(R}Bf=eM5QOZYG9ka&F&0#EZb94EH zj@{||YA+w^)!@I;_54l!d#@Ww6~%)+CDsFrwiPDVO9XCUmsww&vja&E}*rEMeo z`o`Ob&p1Eo{4&YNKJ677G8}>|OSry!axzrD-+D(|%vKX?SDauGG1S>WPfaxQMZ&Vw z-T4CjZkL=iqEtyXgW~Qh1lVnBl2-X|eId$Xyl80Pag4=`-i zPgbsMiZpXew|t<=XlJmGN%9l!H_s)8aW@&S-doD?K;uf->_-Oc=aS?iwheFf5V;>s zo-69P=9McO_`Iwx46ju!;(TW;SJdv?tYNpAD~(0};R>^!gz0Rx3ZD8f$M~2Xqn`#| z9Li1#Tc$1)GZPgSygJn>B-5xNXzU!}?0p}HP~K;G8#!w~X>RnNIika$VO>|8;OyEw zvrJ%@2|1Z5{m}7_E6?;KmkK6{ze{&Z+3B-Rv1K(+cE5y@((O&DC_R17P=UKH=MNB8 zXl>k8`+ofs=SwLYb22Zm%bs6>?Hr3TW1kj1OWz>fAi}49%uXuFQkKs5E&HfrPvkJ4 zW>Ch;t~=cq4yK2VvSSyw88^LHg7IqcAQif9Zb);I6Z|}V=Ip1bv}adBvxF5yM6T+F z>{KNli+k8;Zd;f>Rf)TQe{RjWMlBLXZfq?*NN5Sn-Z^ljjnd?dcA^F%fz&pzZ)fXd97Bo_|?VJMLRxBeU;g;n7QPUR0bX9Cl9ic_^v)}98<=ux>#x6J-@=YhX)k<{^F&s; zWi%sGqNa2DaXMo8m8FHnd<}M?E4CA?Vg`HtS1r2kT6UT1iDT~mvU`5_b4MaY*cF#& z-{NOga9O*v+XK~*krJohJ#`0jAr4dPdf4_zZNMWF&GORenG-B^D&)jeoW(Bk)DpSU zjPUY{xo*`6_L-*}5!+AfIt4U{O!d+T_xmD;l%hj5_(k>QpB*NqJ4XklbJH_K?0JW2 zJ(jNJXx@`OqUstElz!l|{s-O5xiP_V<`V079U2f#*|6vkat&|v)S>N*WHjGpbL?D~ z<^R0NpfM*4r~ctysIyz@Dx*@?7VKeSz99n;jaqsO~1ZBTR0z06TwcC6Xvc9mj6+N+dX4?6iin#9_6IZwwh zE(tU&={{o9^V_QzN9Ei;F3!BS{3uDDO>UOlXy6fRBG%)XguHnRxvN!DVI1ppTZm2W z_{v4oQf*D=Lzb-&2z1yo!j_b{?(GF*MT-i);?g7qk(cg?Wy3lTwVUpGdC)Z(gm~63 zP2aJ;)J*>21>Awj3fj+Je2+9TO!$Fg|$f!`GAU1N@- z$K5vtH1b|HPB5$ika+%aZ_i_ zz30}hbKte)@8_Iwx1L;6^g89!4YAWxay{8PWs81ms(T?3AD~(F)^#+qNLpOLbvm!l zd}i8w_Vet_OU>EfzM|RBUU@To*PiyfRj8!od9Pod%ZzR*ahqK;yCk#ZzzqM53HxEU zS-nY_*{w?h++Kg^XcL?n(>h()&gxiT_Kf>-mV3Ri^HQ50wTK)Z|8-JDvBS1pRb_(w zhbp>l*{YaF1FPMO?QY3eG%C)N2)azM&K9K)c}usmji(1>8%UmdX%XHqp6Jy{e)1Mc z4%Ij4ay2evMh zPH7h9UlU)wwJgD!hahQl`SWezjcqe0EoARJ$DC}rWo$eX+cwkBXugVb{7It87V9V- z-E{@d$$PC2^2ropMxG$-$23BQSZ7Av#;3X4xKBLkoZidX+o;Kx{GNHE@QkbKn-lK@ zeDgEjxlIeYjVDJxDZ$6f*&V;siO=L5gheCh$VK7h3|vV%3E2M`YLGvdh^5M;h|SJkgOGK1(-qF`i?R7d4y`pgmFba zBQG8r-*kUaa5jj|U1?SA4dLkjzlN#T2`!g=qf+H`G&hPp zpRWHhyC~-M-prMHX1Y{AyC4R6=!M+!LjMPjd9hd=4*{wHrLl7!d|{uxA`UiU@;1O< zFN&WZ$^iekwb3Af;uaP{VNl#U+Tg#yi!Zgzn#6+wf$H*?lFuz~psj0YrVoE*ZGa)6 zKmavR+#o?lfj~`Q(I^mT2@DF0nM+^+lyeCj3JW9h#WM#15sdIhL>vkPY6%I40)dvmqeye$kO(LcXeC4xX$}Gs z2?YYRgp5alKuZu%fqn<#6bRIO z9u$VwBZi0qfs#+aqd=g>0eH0f1RfL!lzbu{1p+lrKoMzmh&(6|sQF+Rv^I$(6bRIO zGKxqW3ki(^fs#+cpg^F;u_zL4EF>}t1WG;`jRJuh$Dqix`eZB$1ZqAGMW&6N4A4gV z7K4TmNBbIs2B-snly5L-fIRR=O9AwuX>DN80D<6-Rt8Xrri~Ya21o>dv@(E3G;Pcn zG!T#Ak5&fcBYF-Nh=|`%5hCLpEP#rbuatyH`IVM{l9;d5gvj}oo`9N|uM~wyI!99s zB&un$8gLDOg(j>WFhEj6e^fYusK(I5H7J9aY7Q?zSYv1c8776I4kU)HX2XjuKw4XrmOhHPf*%G&h6$$HJf;HaFEaG=qnQp$z~H zCBgW3NRXWUAwnG{2Cju6VhPaV!1aBEQtK!R^DQ(GDIj2=A){bfMP2;ALPROz7B)9A zx01Ke)&XRhH{`i;b1PkI00NjPTxcSO1g0t;N90122_zs<0OxZ7@JT@E<8c@+92P)H z86NffAID8C04fdO5YRA$c*=j^p-_uyC<@WlRS#`v$HBP_1|>tlq(#eaQ_kQn}_#t0PSe}l|{7tDWVjQ<{)1F1*<^)W(9 z-+z6KkShDnjPc*IcKjdEbLP}%in0MI(f>JJZccgrC&u_MSv%k}tpE6YgpcO_>tp;U z^_+jn-U>cQ{jbyUpVM>xHR~gM?EPP-i`Df_(uQ?}& z?Q#C=WBljzoPQ4;|GD#=f6W*%bBB-6@iFac{i`hi_m8*q+`?4r1RV4avQGFeGS4~z z3ogbXvpTNtBMVw5%pDW{ZD_u4ey+oL(BR1=G-S%h^?hVvXlM-Z12nkbv)rIz5Vnh; z8Yg0?c8Qce4w>5mQ%~4(gMcFwfXx&oU&KtuTvrduhmBq!JA$t!4Y2LruNEm-9I(~E z5P?Y>hQz}~0`?h@=?@-QaNv1J!1fD6BynLeBs4IffY%HW7Rz)A?>*zY2gTHjg9z-FQl&i^(v-#0(k;XG&vXaWhc zhU5A^vM@BXi^(6L`HQ?rv2?>wjbAB!%;QA@24Ikq|Hr)ePh72i!;3s*E*@Zt2Q1tE zU$7!<8U?J^A}kW!tF6&z6Fiy7?tI|Wkoca2+Wu%eg82l(jfVTw}WId z7Y4^egls9l%0FNpxqz&MA^dex5gN<_QgQBR@CS7NDJue@2$`C5;lGQ_Cq9;phwM@T zE6$HBNc_1&yuS_2_s!3BI1d^u35$cw)`29SA6Xb0ni~28G=Gg1sh0d0su4e>k8fBJ z&x40lHA?;;vLb9Y|BF}XKV`)^Q3(V1%Q%tpis470ICt>(1GfK^6M@zR*&B1==OR?3 zQkQ0UErix4t{-CyQ67Gn@QcySLnK1*VSrgbjs!pjqzBf;WHg401m-_5y2hd*@bF}y z&;4SAFRT#34=(=mgQO|hzfgw%`zZMj94G(l28n^+IQ^8y47P|^=tT-xdgn(dbDt_C zz{3Ziz(cjZi!3A|Fz_R*pM&PR=I1(`4-F5R2)#7o!h9E57@FVJ-~UW@e&76Dhx4Gp z0s#xX65;wjvM@A1t=@j${9K3gp#gdaw9$g}kFWn<7?j`DZU5pDPTkm0-_&8K&*{MC zVPWkOO9HQj;B6PU{DmH_aq-~Mkf5hP_roH;&~_Yt;`WOLGbea-!$l?lxWOwkumvIm zH3&SW!*LNwI4pRz#EIj9_N_$lKnsTS*RA%j8ot14PgAb{_G*s-vlMzg1!l(l$UGkT z{<#XMPI<|)Ae+n`9RGc2{`h?iRkqCMR2t_l3<~rp>8AwCA9XSZ2c!VOQ)hl;VNm{8 z{TJSIfX9QBcVZaoQ&LJ_-{`?O9t;lB3c2v$xfytcNvW{lT>19c3V!|htLF(gPXrH( z2;jljw{zm#>B9*a38-&GGVh^M@I{paMoC=C7Q|-zZ?;t|0#pR4|Iq zg&&udxl@iGNb_f#hB=;v6kI$wVg^1x<}nDgJVF$L*GXywzNw?s`fl>fokaX?K>nnk zIgvsF_k;i%EZ9BvyDeQdcr$qao^g|Qv)Xf}i z*M+AT%TOTx9+uzT>i-#L=31xq_H8dTNaj|cxd`RXaA8<}cLDxu^MvZ*2}5=61Z|QQ zTwHiCBm#8l#Kl9vqrrsvs}qHGK=U7%C=@SOKdvXRpQfK;&F|+2(19pZXWm5l6Y)Bq zIbr(!M`uLWa){0nFf{ zoeXv#3qk{Xllv)Y_b2`Qu>8@q2o5(MU_lr+_cAO;@o z0Oje9@wSiFJ9DuSqTs> zU@YJ^kH7`&ZSjydK^`I(xQXPUT=LCj!>sqqqz=VF=8sYb_Lccl-1AkBpy-o8kAM!4 zXk7X;ygUcY!m=LbASy=wx_3HotqP2Gh~Hutb~g$g_bpI>2aE$*J`wuKvQ}8XK)Q{zQOlDL3x^prgXZX6o7rM{{GbYpXm6_+?hwl`T74C6=9WT0V>i| zrJvzkF)MAFyGiglaJ)!!tVre1`9lM8YQg+}Y{;_iDWJ!7OWD$ktq=4hJ? zjZ+9mowC?DXX6;yEiX+-P(YT}wl;>T0$ia=*_s-fnOhs$!2HWC21XCB-`_l4nI~o_ zEzF|;w>;D!a54@r^l-xv0pJMa!5oeViOZu-X`5K+$6xwkjrpjNDfvjnyKM;7^mrh zzmT1Q7jfX48BYMmr{G5zc<{i~5nQiAKEr`?X0TWi!0jHE0PLxN;!dW)_3L;VzA{{Z zr)eYo`)CK)gAIVeTQzEgvN@fPb_nb6O(e~Tgh~iXt?$rI(}I5`+R)K2YwVeO4|*7hx9+zmVauo{QsHP7gmztUx@hSVw4P6hX|giK$98^nJ@r$ zhXm>WlS#esKr!$SW6;=(wi|$l4-4L(*$s%B(tZp;$xs(;E{G(GSU#d>sBd5cem8{& z)(w9=383l2+~VMO0IV#`p$*8K7k}3 z(vo#tv7+bFB?-srBE4N__@Dmv-ld;u+NG-5`isL->ozCB8>3<3{e&%RuiE4(H^((M z?<1$%1zOt~#&&+_@9%&AzQ6tM`^5Jh@$Va7YbLoI)Y3XrG%-6>=k_6fT2iAWTy{1+ zFE4(`KEpI}>d{euh7WF!k50>|sJ4D#jAx%fMsDso8uL0^#k5|pPC`BLsA&sNj>>ep z?cF3fH@%E!v#S^w7*?)iU|6BBQpxxH`5@m5{)O?@S!S)dquupg?cS`XM^bl(y9o6^ zaw`%rsJ=~X^Y_{Mr9ZDk)PEbF<4AYvl^Cg8c*CK(>>H`6sW|2%Y7b`JB5bqk-`crB)czTBxA#6`S0}#o*T;(m z^oQ};oo~2stnlWO<$cDh>W>w6-$t1(b-yX#_WVu&?=d#sHJ_2$d3VpKhh8nO&AsZF z`qA`LX=pcL=wUYe=`kxw!us-CdL+Ns1_^1-2b5|+9`nL zfYWE!Bg!JvGjT}`ZmS&>l(jv)w<`5!WBlT6RbK7aQ+FMB!K8PYOC|TPS@XU6c*P{O z&pln5N$PoD;{66gh^8(1??TKstY2UFGQ+9rwaereRtf&VprDc3r?vW3nz9nolELLq zj+Z}sdaXRiW<2oKyZroDuU_Tv8#nUw^rUNCgcGDZ&RuouNkET zefO*TpIC3Pj=fL0th4*5pPyd{PUc4Axa2j1-s3k0>oxb(7JZ4AmI%q>C_k#i9KMI4h$Re7oqU6VG1%^A9I zK_cg#QN~S`498qAz6775qwz<_*EG}_%ue5v$XNMKav%3Tg`&!M_GgUh$DZ=PAPkh{^QE){Mu3#d>-^uiESROe4-+v=RCcZKF#uQ6=kpV|B~5IG};)b z>3ZM1?+%v}>o`3x3cY9Ne*PWz5&#pH1BH9#^6Kmri+p5GQ);OQ|Ygg`-5uT`)tJR;d^-5U)3(v^snW_<|+fHTOapwon`u1d_T9wTOCL`TMavXhayprwJ)kjXT={zkj2)Yus zcORL1-?(;FrD;fmTdL!Djpu!xSZNlbRVg2L(Lk5jr%$hh6n3x~e(LJ#c-P+E&#^Bx zuiamAWN~b6dq!ohWxdnnSbSTra7mDAD9f5JPVd<}?#*gdKHL=FnD8=NLF2RFtxHAC zv3j~)oqNg)Z^vav9iQ>iP>`Q|ss35|a~{$pG7x#gXKE!|QPM`W%jPewIw#Y887o<4 z2Or!DYb$jtIQ1?~WLWTGh=6O|fc>)B$s9rcro<~}cj8YJvzC1adwG@z#53m!j9t(F;C*om&a7snd6;p(`gn5-;^q3nHmB~Up5YjU z@YuwOG%LOO#_4`V7y0%bd(@Mo^3$WTj|c^_6$M7cg!0*bd@}PX%e;A@zH8sL{nrmz zPfT`*`EB7D6Pyn3x7Q5rM!!?ma6LP!@ETs3RM369q7Z>#GY>-Uv#LUf9@Z`YxwHP^$7EVnX27R zhrO1LJ7uQU`<=V$A*SW+YX1C0q3h&~&eNV7&+b&^+39GS=9Uy!ymrk#Wh07EP#B7I zI<0KjQy;kg-RXjZr)8_k3--6E?+y6CC?Av+x`|0#jDeLm#jUNMc~CP+Wg{`otqNUa zm&v*2;jD zTRNyCw#H@B@Rjia5B`s;>(A+SAP0jj!&#o~zZdr?zh_+%M=P^2$#x=i=&|mp7SE10 zPQRWFZ**IaZT`sr>9lqIi;r)ODsE`BKdYIRKq!-Q#_7h%j5DJztmTq;IJJu#CJWbX z3-mQcYx8>fN;WP=u9SSnAz>Ymy!BO1YqG0Lie)bk&-Q}!qa%9be#;OxoRJY}xtW=r zQ^CoH`BbNos}w7lU!Mq9WLV`0l|~C`6x*`LD&?=8+IK6~bShlkGG^)Kku}I}6E6|e0b^LCQ$m@Px|A_aY(+IeL484}I+Kd{^8O+4i<`rPKz=>T<;9FpeJ*mC_WeeSgeR1tqvvg5-(J93j(8PmfJOH`{5Hoir6 z#(L+EF}j$4YA=qc?Y#2t`i@MCyFE75)v`(>MMA|{!*Zd*qjY=gA959cLL1z!1#r3a z1VomYnllS$J-Xqb`(`z=+vY{Jtfr-v^H^dbZ-~ki9x+f;0kbe-tI&7Y*HfLSjBwkn z);l=VPV>?uGW0bH$DbDWyQ@1Gt=){T#uymvQQPcVtIwd(fyJ;td>9?uQ7s#012P)I zh{36T>!z^=w?S4oU->L!QTLmn8s({v_p)!h`vWqHJS-s2=w@}!zSxws?oJ3G*k*+7 z)8x!NA&=(;E5;&Ly9+I0_Vw~Q8?eMYTft~j0&5nulpbNjkK`!&r0rDVSHtvbj}M@} z1HLXg-*q}MP{D@ZEa)&?1)1dh#=bT2Sp06c$J{*UL9OffAlFTnt;;O>OK_(}y}JPr z;=SL5 z08_Bn+p9u;$k1DY-ZI7Y6vu1xZU;Fogk)!n+yhy&mSG);Kb8ns=n>*h*$ZQ0%_z!o;L`^R5+ba zs;xS8HOm5rpIbdAMqJ6ZBMwxf2y_PU%$hkO?rPJ=I4Sk3C*j0CK@j!12vs7*DD zYuc<`_XdmJbbmXKnj0?<;_8aaqKG8(7#*HcuU?t5mN?Vevrt(0RiZ-fJm!>}6nKyH6JNy2*g-Zo=2iG?hENx!Tpl2c6K1bXpTb=I9Gvq-)jk*XXJ~Yt6jY};z4_M0!mZn6R)W!w;ni;R zB^#b^^77kF2ZJ=!WvD76ae2kn)k}n*gX!;#T)COv0C}e{`Q(-@M!TSa%Vr;cd0yc| z_Og)mtKc>^CRSGprT1Ii_R`jhy8!@~5gz=YrQji*%+_>=GW7NjT`jv>LCTo|gE%p> zdo$~-X(1D?dK3Y9)^@IAn-x0ZK^iDU^Ur7 z2z7hBPSr+L6aW<`^b*QfJqX3y-@2)#h-B#j1YAU>!(c%2@gfpiKbHta*3HG8k;pW$ z(^|e}<;$UF4Panb{m=2vDkXTRo7VynV6^8%lt~SzNMGsZ);oYrMG-JYUoHlG@weg+ zSA)i?sSTex<1got36Uf740_4e(Vp9STc=KTTs`OTa8T6Q|^Fhx5T0$F%{e!GwsV*MsP0x`GzptF;L5 z4GX^7(&)(r%V5HOzy}WjE))@L2U4^PL|_`#arQ<(kO9d7KzfA|0~zHKtif9FQL53F zUY`=F{X5`(nDlqhC7z*g2W`iDS!$$tT_v@MIRNV4(>}|{kehZMd@b)`Rd;n`J`#Bj zOpbhHz8)g{Z4(jtBo-2hmdo!zT_zx7_8jvnK!k)vve1{&PlW`^Q-_v$VV=w0Ii7d)kVnhQQL~JNWG)I8^0WeW;xfU#bpymW_N0Fe7N_K z%z`TvDDSneQZAVmY<*UA!3F`LEdg=$BMZQF%6K75#rJYoxG0pT&o~6iA&|ycNY(bt!=a-|qXstT&spPEj zpdSRlogjQH+J@Y}14h8jCF%*SI=6+K;l7vUspPGxdPo`Yy><(talqwjlmJ|_h3$YT zzo=fXz%E@bh_^1;geR667_4Q5rWwhxD6wk`oB#uw92Zip8nv=v-GF6;OJA2&8Z+U~ z1EwMo>cX8%UmNqosS|`y*NWH157}GG&Q$>2Bmr5;-~Z;oI%FxBeIOyw^X9;KTEEVr z_b}6U&AjcN7NC9U_V|VVN@`-~Y+^)N8zgHD0(#Jy8Sc_;x=#*ZUFFGMAM2 zSuubX7z=}$@w1`MRQU6eUfJVSl)jR^>|eE1c~kqXuy1W~Q@cHR{ZbB?G)g7t(KB># z6CL$yJ6KZIQb(NTCF}u7k5|bEhYOkKK-I~dMW0es4gnx$PA_rAmO#S4KfGdK@;AW} z4gf;O^xcBSmWj%9a7UlaCs*4HhPk)7Yyfl_oY~ba_)@ECwIo=W97Zb~Dp%zBDno7M zHNLL(Z}P5(FwyUFB2}k=9Tsax4;XzSZ>9jFKgraq<1N3I6Oz&gHl$}ImMsru1grKU zfX7l6o_@>?8n@RmeKhJ5SUtykpUn1UZQn{M1?-k1X~i7sPnjt4!u3f8cl(SDY2P02 zzZj@SA9Iq*@R!!^C6CG!)8^bsr>M>mH7tdVk0Rcwvh6I3t)$J4wX9rZ{?nUjvm?!~ zJ#acQmNGklpi&2u{WIBa-z-NB0U}lk*YUKzu;cMm(IsC}&wXfT2#ZfOiXU1aWYcyX zPV09}5girUj)Nus+xp_b`qs&NwyYbmK=%UTW9v?F`#vwKP`dLj&FiatJV9_?zeik- zZy&Wb06=X$O8oK)TJtHgFH#B)%{4wX-p9W8r13X0eVTnQKMO3#Ly<`pig=U#wJx$x zASLeZ_D@R$!3v^zZ%*t=ffYr48CB%v;B*n&HPz~A)!T>gtR5TFVh&S#i}xBWKpY$R zaFQzhLy=t4L4>7=w529=5G;r9MCOEVewX2;#ey{9`|$+}{a!802&&{3MSNCf+k{xP zYJ_!@5yXOZm$r78U23VSYIHjuHx4ffXl0LCHFymM3-^|{yNs{9h|J1GyocAn9uIXy zVB50O69Fp;fK4rpjyM&B2@Qp9fk>aUxs(fYK;!-IS4I2$T@iwTknULsV#&$=3X6rw8O>9 z1}emI!hJ6$P4y6L_tA`ZN>&4yNHw*OwJZXjma3g+zyS?00&FCVl}pfIP>>2G{JAhM zaWy@}=Br)+4T%J?Id+TMvRECi!``qim9bByq54Y(zQVH`R>osPf>;WxSFn~Zid>Lnu z;xxAN{UMv{i-1BH-CLrI$Q+%u**7_~{Q#^lDm8jNLz+15Z1^C!zYdaeaS^)G=M#!^ z%iWRF-kvwX;<<&eF`3~S;Ry5S@!q*g1|pa4YoW2(z)UbBS&}Z%w zF6l3d_@#;a8|EOXT*|FbV#O5B1?|!5&<*l0)@E-ki}eK?l`RC_fFW7@()|wyd+q>) z2mr<{X$88M0IYk(Z68)Aig?U28NfSkqbCk86<)j<-R>{L2<^ZDS4M{2S+q=)vUAu| zCQ?2wRp$NzYDpB@`YGZaWQy12P|{uDrin%m*5yDdh$!O2q8xgUMiSFX4geJx$j~|` z5s$7dlr-2-jSer#yg(08Y>_Sgr zArW}bbDR0B0Xp4fQyJ<4!v?Uui?9+4x)<@h$YS*!$`>4ke#Z%<0|6dwhrtIrbt#;O z>felQWN_WUybEl|^mJP6V z#LL#6@o0n8X=rCjXMnUA2!T{uxstLz0#IT>67EHKhRID@cx)GFg#>+R@lIG!dI^9U z=<$PwPke{#@o(P1ns~U^tF6z3lt^RGq2)^e5gfaPFjpjbC7*yGjY&hAaqM>e(BPQu z7F$6p;B*bN!qQ<_m$GzO(F)2zfWF^IHDHg@VspyKZ(#aw(gOg%a-dT;;2#oG?8e}q zyPoo`L%Bljo6$wIG$gZPiiw-W)S<@4@KJ?zqV-w>H|PQH)|%&Xp0}EvI){C;I(fl%a(Sj+u5=5~I_$+AA|zt<>Z^qA}cG z+M}n5=n?V!%*MI15|aSDk%c1zgb%2K@OZ=WNH0aV#{eIcHZ%9WiYqQ;h42UWT9aII z5%3CANwN7!co>gCAM`ILsYHakV46C$2nc`>FQC%ehu?xJcGt>^h|*KMM3kfosk{}<^ODZec%qO^0}-$mX(_olB$8)byp zi)Dp-k*7M|5GiM3BgIL(5U%$DdMG1qi8qyoCIBSxq=i2eLDiQPwa4wFRPXExlS1b2 zrsAh0CzeSXnZFD0Hl?^W;AIHjq0pPs8#u`GA5FypF7c#g7+rCEc@v+#rVNm$ zjjVNch%E(aYOdg%OVB10YiP0UEcn2yT&65K!m&y{P#l_N%v^%tJQ3_Kwh^-PFV2+@ z<;962DyJbDS&a8&th7k#$FP?Tj97&&7NO~m(tuN8-EiVMGoiTqVJ2j1cIeXKqnmhG#R5iegWXZd`F@C$R zBCZM)Z^j-1OvZ&!E;*27I1uKpNw*0!0ggubMh|r)7q&0Edd@purYtJL(ak=@7^yNn zxU^D+aVu11&or-EZcOpL+N1f8IKbJjPL0L%wuEOZ7{c3^F1rla^NJVHdAxe@V^WWj zw(bDkupn$>!;AX2w`f_+6x|;aXLkp+0=zDm^Qvkl7f;+Wx71C4000yd7V6M`@mMwb zjAv82h87s(orwOos!3kkthQOL%aV8tWYT7Y!X#@-9yt7T$s1sa&jz1~2)Ea0^@t*l zJz)B%!VPv%;50gT%8{>x+iIrF(wT{KKb(~r?faaYaKe6UJ?n!NtH2V5uj`WfGR{u# zQLIDCyu5C65JHIyU4gq2wXe#BR_Cg#b_Xdc6(nxo=-XtHug4+vKg}h{yXVCq=Si%~+^$8v#kKx>CRaPs5#U91HQ;|%s_W6K)g-wI3wPT8R zT@bxTiLk1~X>Z>;P*W4}IfqrObp$h#v2#=?Hia$z44kXi_SyLDx|T5%GkN!_QHd!4 zQ4;c=48x$&gn;Ymt$LWlB>&H&w4*KG$%t;g!z$>4rQ8eGr3US#%M5O2^dS{C!h zkNq`(fE)4ooj3hB;q&$pzh>K;F6)Yxl>wgWiH_J|XmBRu^a`YRrFCtwI}WrUChYR4 zss!8tgxPRTat(96X?DkeY!T4#<@Sgyf1&r)mP0-(rPirt*V#CNo0!)J_6*pep9Ivj zV|=2ovn5$XgZm@d;8|(6HdU8XXuS<1kCPTpU7`mUC5=N!Bdfxx`;&4P27Cd+L6cG_Eh~? zN4aqPz@qTjpbk6nuG{WO@9=e-nN6A%ZtZw~d_`L-;1spF1mlNpf8mkbgj@M=8%g`joDo z<}(paxm)}h=OvT}$j!>nE>s}&PG_%0ddnUh&stkZi8#1$Em3f&{ZCJ;=#Co4L8Qsd|@OrnpD1Zzb+zmCz# zZNNw0m5)7oW2mr3H%I)+F6p2UwDv=XXv>br1;kTh)k3r5s#OCA1*>>6CnO9uZhyK< z?G-H!CJ{^Z8p_TgWe;?Hln|{4%?Q^KePo0#6FQHGU%l!$F!E z`M2hubCzQN)4P$MwiG)ib_lj1`>Tdxz({oNy#oBq<2%zaA5D4tnNNe228oHSA1_MQ z^VZoJ1>ZG|b?WOso~Iqp$zinV>aoMJo7q<^LM}HxbSCA~jytHdn)mnax`xJpJ-Q$s@| zUNJFnQZO{3K3=J4;zRr=4Ndc+>CCAsSt{G=0^O?wCZ*^L^9r4vou{Uz&W3WJP+Ft? zt;NN~mm4`q`}d>y`PICnuIS;tdTo|ne7yYbl4T5Wvr(chXQXzc(XuzrBlnKW@7lJp zGqzO5M@68pu&}b6O)}fAPbHW=*!Hq*&{ZpqvS3Zu@#n-g=k^JeG+iH)9l?I@^K)V* zbE5ZLxU;8m!p-Pu>Sy7sz>@HCA=BnGJ+Aea0+-x*#mmaxn5b&+yT01LjB9;Us*X2P zHe2$^g9rS*&z)1_dlmnp$3`^cm{iQhNAwcR{0?Yd-WC&{-SK*g`}_x?%s8i9lLhh zHcs)QN2S8{E6+Gw5${iJPPoxy7`Qs5J}_{HFGoppvmNJ+8$F7~_nu$7cI8SKpK^1v za!-#TS^3L;C$Ed4S4^v(KbH%N# zfV3b34h<3#g3=5l);YM=Gtcwvy}$YS#@mp0=DqyA)T z{I2SvHFW5H$u^mkrYb?(a4rLOw3-u1#k#4yg>U zkHsquF^@AljFvfSb>|Hih&6Vt-`{JT?JE!)LaopC+F!qZx4G($JMB`W7u#)hD$>jz zMqU@T+f0^u2l?Y?vuDW|Wz%U=3o9xa3OCL-C&ctUjSMYuV4^TWOAnxfl0r7vE* zsHmt&N}>@GVq}&LPQYEd%qwhUWQ0ozhrNKbbt;vDO*t-Gu{8*p*1P#} zAnr-p#-B=xNVY}_hz7r#4%3tp7Jf{3oY!31@b0b*4ECx4k(OrCKZj3p8P_l+ZG6H| zmVAEPB{4icA_9tkvmvUuK@E|}D9xOEh3+aLVI&c;l;L$DA+=pbW@bTcRT?NGl;vYv zb6X3Pp+U&w^{k}p8&MpX|2b)xe+W5LNR#~v2@8~kK}cIuL*wDBsn~e?4Meg;2zgfa zZ4ITtPYS~dYW!iFWfQk#t*lJi60E|CO1P!_G__h2g?bz_mf@3ixzfa){Q;hpgCb9M zo}5HfeXa4D#JjKtb-s8(JBTlJpm)Jz^3~?|mo+|NU+*!Ch@5<4m&Wneagr)hE6&D8 zGKL0l&yzdByMn&8?Kh-p9n}9vNzf@bRM+i{<*`{?U5$uZmMb0`eUt}}EwM>7jqk7W z+)9;=t=gC%qe`^#FtSYaLu`3?@-&!+xyDo65e znsp#a<_61oXlO;RLCICLu3VDg=55k*HzIr*Vjy`ToD?FG%c_x9X>M=y&9L!R#p%W^ zgn;&FE?z@offL7i)+OY_G5I(4rJ4ol1^QK0GsPj27Twul^72U%8=;WIk};i!Wy2{@ z|IHv2u7qyuQj+fS2Qr$t3l=?1_2RD1eMuZ2hP}1k22(6?Q!h{~rP3~3S~4c6vPrDC zBzALwNNDzaC{OO3SAXfk&{Vm7dEW5F#DZjbn`mrZCme8LoePw zI$3k?%FC@AwY4<0wT@T5`i|ZD;d428UcX3@-ey@d&`qbPU7x#-?n6C&>}WW_D8Z=g zQoe35ky%D#Ns+QvOr3GQIvl~=D5XJCLLMgKq#A51{EWk@S7R+{dwXQ$1n+?KQ@qm~ zuD;UJ!IaQE<%{bQArx5xUfa*fU&qLCHGIupMBe3} zEM9~ko-QScUF+v>4L?4Q&u|F38F{QsCVqhI?QHl*?rki{?`;VQ4c}bKt7a9_OH4HE zw%Zy`EWUaE`uetmkv5TxmZXMd znD?#Q$xklqepDt?m)eP(;PVuZv+Of7XieIRi%W3nRA9xNiPnNQ%=qlfrW`sllrF5M zkxr9NTg=SR(vO$qmZVOII=1*_5_BO(g|kNsIw<)WGWfidDHJYeHLd*}V@Ig(E2hg3 zDBWE50R@MkASb>ijU+ubpnj-$Pw}O)&*y9fb|>9?y4F7E;ODVvx0$uBvamun676D* z)C749jnCE2MH4iBl#Dt%YFSd`z_nx`Q<$Rp^v9B$jI2~)D$LTXo70cOGVH$9$3TZz zS*s?3E|Z)1%9MsGR9O{C<3iHr1s<=YU^3u8IXQf)bNB=V9~YNuM5R5nAM?ryo~z?4 zE~#UnQZcA|I#T=mTJpDcL;r}ssq2DH)TzH&mQX<$v^>97Sy3q}kuiD`CBV(l^rELZ zrKo)*f+EuM1XgL#$5d_cVl%Tajr;Y-ZmrKZZ z@fq@@Rh%%jaHmKKUA=xDYh(z|lK=U>;+ea5A64LV^%y)CWMbO+#Qfrg3c$6bX_ zy54(_2Km>2coM&|Pd z1P95#Y!6$qhn-(;@?W|{OpJ`Ws)8g^LlRQm(bjfNS#c3_U2R{QZn{AqtP*$IsVFsb zY0Pi5m`i1qK8ws;J}xuIEIr4}JpGPm=B|vAh_up!nW+zvw`6lnV)`^=`ujDwXJ8sTzeA{RDkCH8*d!;;_!|M$h|_e6j0EGWm>ep7BZn`JHh#zUer| z(Fb-pa}DBcRxEy>ijda7|#Zr@~g(No)~b@7mZEd6POkmF~2hrnIt!bRk2! zg$K}wMThV)Wu;N*h2`*=GMvmZO+U1DlSZv1dYb zEjsy_u4rVuW>C?jAXFukE(*Cu!w5QXznCLbHe5Gc-)t~sacW3$DnYXg0x~#?zmj)p z;#goBGLXg;N}*(bytimZpMnyI2J9XZyuli%ub#0swi{%wG$)RvZ&)Ku2Fx&<%%X- z0Bog-&E**`JZrjZW##FqQwd+1?M&o@v?)LNzK+!7cq{{(xGAlot`HgyNt{5>Iej&b zK~9TE!(gyXNu|K&&rO2^VrL(kD9bOAj$P1Rfs|@WM-Na@QQ4ICk5l($*hdT7*)6F! zn|(VMUi#z9mq(9|2?q}~1ns)%4PhEN@F>?bVOu8{ZNK64KZS-4=G%SQbsUg&YT+~A`h?}*M zWAB+_AwrBg*OcI)_9;a#GLvRS$HQVCz%m&xsZrd~_FVbC=wC1@0Sk$UqU6_xYv{tE zub>1&XYI~~Ak(4D*$VbW+3E0)$zmS_w6h1jQ&RMo^rVBKGz?0q+8Qi0e6HK3Rw_n= zeh*f;>dE9(6Ep9$tE+V=doMYN%te3LG``Y4rIcer+Qxm}w>8efN^rOv{V;b`c&j&H zvdz({NUzMcYQ{jqdGfD>+}5Fa>EMLiD&4ONZFdtNyz)*mnppb&?agW* z#K-S$ki{+g8gH(0jG}1!uGlm%!(*JFW}~m&GhW=ig+3KpL7H~ zA_M_7tzAkKP+)YtYIKgELy?MZFJrEMa!j1J)^kGU!GmO`ifnyXS644DFA#^m)Z_@w zh&&4`4DT{0^z%y<)z$PpelLn#1KE-9hPw2!drD5cwW+D8wY9aevHd+t1>kG)C+})& z$6aWt%EYw$GQ@c`8x?2gN{1swp3|}9tWP*lX=d=Ji{6%wWD4si*7I204>ZOj)P`Iq zDP9Jn$s}@gv`S3rGlfM?u5Pk@4U*J*8Xg@J6B&ubr%Kf4_)!1;y|`F39!@efN8gKp zpkTzMOAqtgmo$WFo;SWqHAZR8O+|hzy6RrW#dGTh*pfkCs~T!S+%;xma&^)qikMhc zg)%oMS3pH;u&>irj;VdXWzC_swqsX!u1z26g?LrurPA&jTlUFsx1m05PtWhwE)Q3#*hd21Ft6_8`Ju zGviUiE~6J}LjK;^Ss&grU7aqb^7>Kdy}MioJgMNWOUoIm?MWf3T%E#+j$#YJEz3Ez zp+p<)z41sJp3S+>o3-oZk5BAen%$zNaquph{}dwbxgFBZEsZ!!&&prO#*>wOv$~+7 zX!_d~>U+`;YTtBs5cg@8vBZ&mni)t5g|lk#mBO zyA-;;yLZU#t9EnUnkvaRKJOCgjUM|u#Qp9@V*ztI6jt~oO1s5Mm6a~J0ntPE+H{aNh14!N+Hu*zW^sMF?elqOsGj9 zf>lhiaikH^9FrjEsac}s=;$aWCU) z=JPAnav9(5GE|oX!6*x3`&5BZbAro=AJ9qF+q9S6HpZj&P~Dj-du~&xC|%bnRL}0t zLXV#JP7C<61@c3llR3`AIy*J)3tm5l+^Np{3T}Q04-wj20e^N3TZm@_HTE{jE)3~e z4!zzjXCB^M7${-Ym;bR_`RvKd{AVJI`OmHvHb%yT#@}yjYrWanCJ5J5S9$n)?MM5E z@GfTA)k&>bmf}RhWxO@*GJ!AGC>#PWtm=@EDA>7vpKO1*7kr_4PCn|)c*5dWFTX%G zzRt9Pi+n7XR$$_r?$5T$AR@uJHAB+pa@{z!bwY1HRf(VEf;wi|qF*^ol}Klpj|fog za}5_tjhc!=7}MSl`}8dn`Jt;UsaxKBXS+}|V=r@6$b2VHv+vH5{Pf>TfBV%p&3*oC z6rnjCrM|go$lKMOEm!O+-JP9Wxcs8)M65%)!&EAYvShS?(B*e z@Tyq){uK=(phcCKO`T(_jEPcGQn-G84{>o*sk}M;3j+NM9m2wz#(6r=+nmbKs~Z?! z$n#idW3z4ZIq8l%r9;MJtzEtr&oex>^(+^{r&-~$Xy0~+o^x|jXfH!2Pvp@`pGBTo zizwAiW?`UB4uiyr-gJw*Bg?BpdR}uo5wjBG|eK2u4l|C4P&)vlqAj;zk0Utb>qy}W8qCpo{@wyBxf z%R%c~vEH3CH!hK%?FB)9By((c-rmx3n~)yZ9ouhHougA|Q5Mf(RczRZ`0G4zu6n+3 zM|<_|YMz>|>-c`+b8lx|X#0C@h|sS3%yhN&U>``kuAEnq(92oh-OO4gtKOZCy^xfA zA-1abb?;;>b8OY>;B28)K%3LB?6B1!6W>z*eECdy&I#JR`2OnQ)xk^U&a>w~Q+O2r64>}LK&E$Zzu0}cHyF>H%S{KmuNEV&Vv2c0+umta2S5#EHmQ7=~3rGnH z{`hi|9dXQTuCI8cQC?_ASsyC1xzxQZ0|)M_ik#y(F~#EjgqpHAP4ZR&<0$&M`=IM+XA&k)6FABzn)BS?I6q zw^^Q$?K2Y4bDt}YU`%uenN0vI>PTGuPTu<>w7YoeKDsG_5u~$?<|dyGxy>*KNoiW3 z=l11t<(v3V*>v!gHfu{5>@Tqze0Bec%NO9UymwZ6imgBPg(yk31U4rKt$Y#z!tk1H zD%vDLqu9KQF|Q)Yu`9A`pTKF-V4CfzKRGEmWgUhFCX`O{@~ywgMb84g-QJwZ1Aonz zCt7BD@~YkQ)OXjb_dFLz>ZHM5>wJScAeng{^?Ey8=Imb`q#Cc01RqMpfo&>RgfWn* zp2sV(>MwD&(RXqA4ANBFJ3G}|^ZX?D%et1cq#v#P7!9#V>whZM7ZC=GwD%qfywCsl zJ0Kxph)>_%`kZ|DFtvy?tIM1{+Q6~wdyZD=5HtN~B$Eb*_wF_jh#a5@Tbp|UtW`hI z(yTkK@R3=vpC%HLGNuSWcj1DpB-`ZpI3>SRQSQ8`nVF)t_P|i3`+^74ogZJGoF`_{ zE_0abkQd6)F(KP$odXZfAqVF@pyQL1@dB>G6X-6-m-+ekC@HU8c}V|Ys$GIgr^vLO zKwf}aM)Qpw%Bgpb9|nu_6#2=Wr%2=HNEU5VDiRW;cEx91W#wyRWaSU)gZW>@u0K9~ zo`_Yq!ee78Ex~OXFvk^0S=hcecD6Z`)F~DOdc0XgXooh-NrOl}H8M2xmHYZUf96B8 z-R%vv=#@4ANrEHrdz41pevg=m^xAdRw%*#JC{R;plB%iMb#6G#007KaU@y*vt7fY& zu5`%XK$XiK5z!bDIQkXm?aw`(o%+S8`$_rZ$B%b3r$|t`iauX?Patn9q-0kr=~rm8 z&)5UqM+YJiV@(n5FJJCXOwa{Dj6e~f<8#3ZPyiP7SNc*G!s})JP}h%EYE_C_g4QXkW?_(_9)ff-Tf7{q+CB7ONSY9L0Uv) z$E1~0GY1N`S-)wasGxHD_OhPRU1lpEG2R?C%nTnX|2;i~ucTD-7k%#s4@B(j-T^FV zLl#b{WYL}^1|YmfiDj=2EyT@Xd64Iq9ixPx7}do0$#z3bf~;zHbEf}oiZ7*`l1_W z^Yh!;6})@*Zntv==Ob7)kRd`kX5ETw`()*O^5jtTZ%M%r`T1dMYuwRwJ|~ZRqix~` zy!Up1eRg(-+xMC?!0cA**PPg29XjyRp(?Zp zKy}`50MM?Y{@nT7r^2`;`xxZ$5 zI27j-6m8gQLI15AG&EijNK>UlNO`bc1ihr0{#)wu#74uiIs#jRl&$&l1)npN&w*tn zwmVSi!-)mv={Yzx71_|xpl7LYWZ6LU zZvv6#T3#yf&d)+;YZQuNC~+u4LMo%Wx->icHWWHF0gt)kUgG3;42UL%@j-vl*Rz`Q z)2rB}JyevRbT|Vub8vW_oIGgCnX6m5Nxb!s#vRPT6?vd1eRXwpo12?Me@od`(fwXg|1$Qh46G9RF z^3|)L>_|&b55_4pZdtkv)d(NKxJkPY=^t>OiKtmNWsG|Gh`$8tXcq+sIJm|5w-Y_k zQI;#vhzLRxW8)!7Sf70KpAo&Y8PmWE9!;d&#aNm*) z^unb}+&qcF{%DYlIzr$5$0r*cTI2aGIH#X7Voj4bIk}dCV$QA7YjwH{`!^ucIy%In zFySkh+B>%NgznCrC{Y+k9u)PSb?mnh-B*;9ofm#J`j>++=tK>1hSt5mR#{nz!HrNv zb8qR;Q10v3pUHHRF_|2W8nbnP(7tbG!lFYgvW$SBWp{TMYrb={TF!QM1_}z7kCOX< zt>)%-rltqx@E0}rFC)6laq;j(VHoeR-a)!?a9C1PQ)66~Y^;=Uc5`!cak-8CcEn&p zZpReXB+HQn1+(JGS1`HzMp8A~Z2nH!`Sa%y;o&x&SjrWS0zN=LUmfE` zp@?!MOgg}l`!|3+&_G=s*LMV1AT?M~Jp$3sq4@ zYUQY6Ne>NbcXuc=v+4bNQIK@U`jH6*T#MBlZg?ZDJr-wL;o#^58_R5-Yj_6N{&)-k zk%@^8MMXYVR#xmEA<@cOT3J9S^D$^m4KaZR1z&7F6(qhh-IawUnT5y?AH>VbSV-}3 z+JAzMUutC+i4g5>H|=c3R?z^YAy<%i@}pB&tdnf~`YqUx-Ob(ow@*KyRFoI2vQlSp zkzE^0`gQhMDlA;_@if+}q%!!~+h-RRLXa4&8)&U^q^GCHIeq%qB!BuAXDBL_&i5J4 zYso2A?~U`A!dsxp?BnBeglFKPDL1H&)9ruPfgLv(4eI-MTPy;zpgw-Yi6G5zK4o3#hR_RSSiTi~BY?i7npMThB11)S3qM;>C3= znt81;Lm<%W*MEmN2SWO0FGkAToCA|GF-xAm?~5PgWQHwQGN4PHzB(j5NkQkEIDp+rqgFC^oEF)1fG1TZr)Se}xV|37i{+ zHd29gH%MaL&Vrg>alm#OVF=L_WEeHvAIpwg!>9B6t-gN!in+o@F<3z=2?;m0&y;<* z#>~hllGcG`Dln(uFk>=2>x6YJnHy5xZi+QL=BQKMdHA8>;lHX8Ki4^cqRom6f4~#H zf_XQ9b#LBi(1jn>PjJVZbxboN4C9$j1K`z&TLM!QA?t-UuC8y43rVo7dZK6eIF^#~ zAntxX{#-)nAD!P{$i6D6DBKOPK1wGPG!Ori zjxy2)%Q>Q;Daz{Vcd_0;wxYBo3MIKwi=jAPi=>0Vq*A)99fZrj)N)ESMHxg^f1r%5 zUY=rEY#K^uq@|>MGM2`$;Q+#z48vgle?k(WEmciTED5*1j!Nq6#8QW`A$h43WV9b9 zc~VW47#JB_KYqlL4yAZcMmcF|Y$b`uj1+`nN_vnN+1a%G7?>3oDoc&3^_2#d!qA@q z!lBTjmEjCnW?cz3)eu&zp`r1Igh_-%_Rsw*XliOYmqmyvIbc8lrN+h#|AbO3D1fkz zavJ0@XaKyb_ajij#l`(&TrRFI07N+SFduQKL~fc}Sct+#h%kQ`V?x!`RBdjCv$JEp zN(Bb;WodFhVgOxwzboK;Od} znhteOL$XqLVSF4*apO>&92}qf`p5}USS*|eEhZM+q>diz7$OR+4oA&_mwbdNAixAj z=l0B~tI5GR9kE7#V0j? zjNaMhcrULfK#9*KqTO_5Z4KK=!TtT%FUAW|A;OR210+^vwfA9JD<{Mn39NL zUw~L_Zc%`89zE^z*Grh0pID?@Rwe@h0fDE72i8&pkPM6=>N(x+bmuWgG7D2-VP%z; zmzRKH%xxYHjAmm)!$FGtH}hEFcDLO?;MjpiV~qf0$0(}xqYReu1MgvGhJnNh#@m(R zJQ-P73VIP(FL95BKYZv@XMjcX`C(5bl;IjDRE**rhO%!$egXeKy>CHjY|GL57?^-8 z6eZAy#26D~|CmA=4Y6I(owDU6J6=rK$7vJ`x3=c~RkHo*`jkqb<71y?>F!`L-9l*^ z^!{*?24O5*@&Nm2XhhS6U&LetKo$l49gcihidM%u);Cx3XCO9|iVV9S5EzK%)PQu7 zkv+WaCJOsAtsw>j2}$l)E+!^Ctf3_{N=q4;TS&>tv7rTsHMMdwTH%{BdV5DJW?+__ zPzZ=ZPo2V4cSvcW%^(yib?@Fi%!QjZaYKZJgfN!}BB+!U7d<^JPc%k{%6mUn+S7JfY+e+oFHBS?E{}w4Gq7OxEIS-4% z!otEZSihfDc<`XfdDxO$OHvXmEmo!ryHOBhW|r|sP6^nzixQ<>F~FA0(m=dgF!Eyn zog)xeFJJxx0wJH9t}QQPn05fXVU0aKSl|cfX|rW;_#2G%QbS4?svJQ&;m403SU;>= zIMja-cmE?B=L{8-kieD15H(O$$cuIW-DG|uSl28UOMnXjj&MJO3md-+)Ccbc7`BP>j%Gqaf?bH# zZ{NTF8)|8(ATSWm8QK!VH8bSCfZ^9cMHgsN0a+Rfh4~bO2fB)kBr-Bi#R6yR+$aP> zIJN~Vy#gZIgOv3Eic^ajgMODH;qv$I-?PIGjqPld7#NyL)jwhpMhABKv@3AYgYFBJ z7(Y?6peicJ!yA7Eus@Y>U<*1vZWP_pJ`ajptN)aD4<2m;RWVCBxyZ&8Y^-Dg(u04N z0AwL3nLkpcAip{DJUZH%^BFc`;YO`EXc-z}X_{R)Tun0u@~6*^_nZMaU9hngV_Beh zkqH0S8puK#E&SYBEI6km357yy+S)E*dBgQ@ax$D-o156|@`5ccrY=SZW+aIXE~N<-iyJ1xp2aO)M=_3JYuX z+5U!ODXl#K_ic$nX+1Ni*|2ED%MlN%o}@v1f8hSsh6a6$8MDgW(5R@MpcGC}+r^w8 z68%ZRTS-YoS-Ddd%O`_^4$hga=^6PC@81uM9cc{$GKSbM1r96f=ooQC8#-Z5XFm#{ z6w)=zr;U+O5}rx`qKaYl8gHR!Ei@G$el{7nMn-62ng7h$q^Ex}$RCh|B`jOe zMZUj{F%KT-ekm49qD#GCg9YKSEyftPrf^0e?ZU%l!Hg@-G0X&@pCP+7I`t2t%SXWF zt*uL@#H)=kvXo;ra0FLNYst*28|DyWAQj8lYz->Sv=Da8@TndKy>$zu7zagRluH&r z8-{)wf%zTetdo|D%MaO16X<>ejvpBgJLWHJ_0u(is_a^Q(VgT@vKj0PJ4*nYE+5tkLW#UF4Gq&{FU_}#m2TTq}|gyHxaF_T8YOnfKd<;^QfBaTiO6UZiyW z!3FRV&>Lc5o+(2&niqkd?JZoW-rGGx<$)2;nu)^>TFsPIBX_`l&uV|E^>q3#pt(x$ zsGUSbGoaer?`t%?e*GHsy6$R1&D3LfY$%V0S)c(E{r1u5_pgZO&!1~;Tp?IT=MrLg zf6nC;pzRu})Lh_$m)F1WuuYj4qD3yi%DFgO_RcyPwTk+tJY^H8s^)_oT7_rEEb^oQ~Sy8gh2xX`_>L&nnlwqM>-y-UebcUx(f*jp>D9`u2i ztsd!K1=4Q_4GPhV?8->Lo!v17P9)jA3pMMR@d6E;2eOfH`H(mU{Y^;22%Y;t3 z(~ge}8kVx({2WvOBJ(OcJIw>mI~+<)7S+?k4oLWE$`Q3-O}ZT z>q%k(^DNMZ5yyU~?0_*S(j9Pg$$nP}!+6oYAi*n#+OYZ9rfU$%8GqnFj_6FV8n ztTpko01?A}=$ufX^Y&c|XnY2J$yr?>+Vvo-nq3P}*95)VOXJN8G|=`VeI9_nXt}a@ zLC+?0*$cS1(N1(`T%f1CE`a!aBxuZrra1IS`7Qj@EC)KJ%j}GbK<`*pRkwjuZ|Q=Q zHs2H=$~#1NfkQnE-1@tre!oTdd1rsWBlz0P*x1;YFJH`NV;z$Bg|ayB-JR7=B}TQ} z0~YryF(t3keK( zBA<%$_7BAX2!w{_U0a(?8HGbuG1%^al8zGG7z=N^vp%rD$%J1P>^=Amn)cgL!)pF;Bst0Ya2h)i%RztkEAB;CeJVx=~0}UQY|5O^$gDj}I{!-tkPp{#* z#k1HAS5+QAUhcG@>)pdHm1ShktW)Mt=TFF5@%`~L6#vVAp4)dA&dEqa7qAxrwEGT# zZ6Kw?UR&c)dN`*l_y&hIDgoO(YCw*^2ke{3GdMuW4)j0uZJrZa2^_%VGbBGiGxzvf zxV)h2YFGJ?WNWeQSK$`vHi6|pm#N|&-SAaZB0By$;YHL5yPV`)xiqi97Q7?c@%w)gJv-O8>}Xb*X^Qz75`4N<$L16qH`dkj;ck3eq38=Kv}ZVY(=V*7HnPhF zJKQ)I`7HOonf5DA@HfV;E}4T_fQ(c*g|<{JD1`%b>rGhGMo1Z?P&?l+lR>Pz^d@g2 z0i_)zB+bsTLJi^5ZmbvdmJz~qsMIC23db8aGqj{o)}Ejgt%{^UN`8KGxJ(Qs6gONh z(c08Bl)k7ebpjmsL}+9rMna+*KmTQYc*~}@U~0JyoCmeOIFnahWl-nOKTU6)R+-?n zIR$o_m{sR)y*tk;u(!P|oT{ehx!S^`r&sB=8pB29y*X9JD!4bW)y!J8v^$cuIz-mv z?p=6)rih&zG}gl z>NBzJ_eYOWpVKAnv)Q?*S?+ML^Vh+v?kb{zWMKtWOk*zYyI^cEg1xu_T<&k^9il$k7%DW+$@rh%9qEvC<$ zHe3Xompcc=Yv(B@X({HcD3oH;#JEECPmGvmNyPDc zmw@AECu(gQ5#shk(Dj|Hpo-n=s8O#7|HRBui4dxAWpaLo_OawIlYiqA;*ZBLUVV`M z`O|hXO^SML2ts%L@UPiKuzJE_7-Tpd?~kd6gT z2z5tcCVC^Tbd*5dl4#a@b9{qAbq&poZga;H)qY@*LeJ)3HG-m`(u^h+&;fXs7PEmsw?~DaXUZ7%SNeYbmIc^LtDi6to%?dy4*h+ zH#cL-$_R>!lafaX34Q0*R^Gq=0Zv8}6;%f@4cOLGYS}w7I$CHw=x+DzjAXSs=)g;& zn=^6JQvut!BZfn?ip?W7D|yHHPTEv&Y?d!ntj+@?ww{Z)G!$O36*l%{y<1YyZ6Q2F z@P}c`nVD{nmEJNgJ+G?y8CIdawHa0(@A8NJ6SDlJRzro$<&W<0KRHn~Om+2gnb0={ zm-Kms*NSPk>aLB*vP&(}Ny8quAPh=T<9$||1rQQ5%`va?mL%F11Um_do^%Yvj0TE} zAB}`Sy=ZV3p_(J3Ml726Bi^0(HfVf;z2x`lbyt(?z9%aN$Vms@rz!X>K1j`sqw|zV zBi>K+sT{4qN@(P#oh#wEmo8i!&J*Q+C;Iqg@$99TYYGdOR6oSIAUUo?$8g9R5nbUk z3g(y*X+m5>zHb;YlO}tBeD0;(BdJyHqEu1Pw1`MK1%XQ8;!DF2AZj)UQ%BPl-048m zl5qRAB-}6TAJ^$ikhPXCNTUY33HbP6*2P8&i4VC*@U@;18F@<l}UHB-$u=HZx0^OueqDG>|$U*$#$B-I)6b&Ry3F6|v-PAW1GpIBcX%S#iA`=$d z?beg+yxUQn8@p7zF_fK~qxQX+c{_m6bxz}jvB&A=nsuDERY%rJp`2WI_FZ1bIl|2| zU1M2}J1bEgu^$pu1p&odA#kF;o;%AzZ<`%zuz4M z|6udw2*6$oG{igJL{B|8|Lr8s{nIsneuf%sz2Lb0>nKhRHnyL?2nbwf{dpKC2OB%M z_#gXhGv-&DdH);VY<{3`VDuo3NdJM6fxbQwhn;N-kuBR56C-_|_*eE+5pRcdI^tYO zc;lQsH}5fjf9QQ(=tgYIhY;`G5ghNok5^NFnG7&;io;{lj3-X4eEOKUEg{K=K7=aC z=gj)Tpx8-g>%mh#WRpF#&G~F>xaB;paVJj~rpn$s8NTK2u5iy;!s0xGsdaV^j!zRg ztJpE6qa;ot#!q)~aOj9sZ|hT^XA?P2 z@LAv(JzS6KPre;8;wRtOdH*>;_17osF?a^Pz5c(=v;XI(ryj~39OLxV!HDV*>igH~ zci8=9uc}-AP1XJ*-{E4!V6i{r_H;JtwPbghX=J%5d*FRtPMQLGVd|Hm*#xA2RT{F= zD7L4s%tuqudwraJ(_bzQ)FPyZ;4BVJ*xBuyM4y z9>Q3X@+Azl^rqwZ%#=f!2M&zs>bW|De0avw`DbW7J{Gm^1?bGxgrw{%jiJNF@%QDP z@w#8mx{TLIy)w01wfz12>XaEM(ofpInpkx45Twc`JoguvV{D64`QV(B-kIFm(yu>! zT{t41vbM*}5^0qW4vgrP4B6nlVu@;=bJ}Vi9W~^5$?u_K@d|WkrShaM2iQk7kFRgp zyyMAt!IL)VoKRd7vmo-y=%(E$)3iA`&JY1>F}7#Bb{Cu=%k1`oBA%QgkzB;rqF6J$ z(ZT8AgacpRwwk^takW+t>GHsfp@h7%HP3vu5fNNRD7Pp3^Dt0*qy^e9nh>YiD( zF6E~T>3Kljbm4(EOOypC>8p}nO9hL>HsZ1ibq4Hswfc&;E8l3(n@rNr9)EUUFp+-g zR7CCFvo!%(<)aFS%bKp)&i1=l{O`{J;86{r_z9z}Lo|fzit~Ypn<*57rvqdqMQW zP|4#l14fplu88ht;k4k<+u}62Dec^+v~RvPCz1{N`|AW~ad_j{#AHid zX#kDJdv@|>gO9ey>Oi(jz`aBhH@(fE*N}rG_^BtA$Go$3KUr+M=_!l9;K#d#UxwC? z`mEaCekwk^TUNRIP$#cPJ|NBIV%vRQVYViB`!epM--XC^P+{)=+>oaB} z<N00&(bQ`r(f75SaI*>Hcni2 z?zPSN+nxH{DM;|>P5%#qirr@<&d8;8SaL5+JF75s1$&&y-Y^g>5C@K;SQ7=u&5mC0 zf(wKwAYR?pSAM@4O-1#@<`E{;3IHa75=O5+a zVEb3NaCmz8{(0u&W|j^{cHm#j`wm8;Mh|QZjSeuHva7ApbyjtG19PJX4hL7191R=} zF8*=eI?uuHl164GrViI{|Fo-1rXn6a!L6lBk{5aURg?CJtZAt#$X#C3*0m8Af^ZYVUxBtyR?O*(l87Q9r z28G!Vxhi|#-s1Y9m|$9{ti4O8sq_Q)g#I?_s?}JtRXV0#A)E1UWcft^Ko$ z`xSN^HQem`5yyXyE*$?0k~i@s>8fo3J3Cu|x{Hej$qOwwvGLlx5c2#zN`KJgKgVfCr`p7SJzAV_|Z6jb|Wh9 zs*gO6W><7{L_ld`x#X4GOzOk;ix2_lWEI9=^ImPVU?5w4gWp)k|GtQq*VASApxW|%@-S10=P>8TBu*KZ!F+S(P|Vz=#Iv+k>SxYO6w9L20tU^_Ixdn-*o zp2O9^TTf5kL_$JK+FnV-Q`S*d#Z^N?O3_PKSI$`6P18=;!_vV8)F`V@Fo@4Fy}Y&~4zbua*nj)3?4K<}+Ixdd=}^pC{{;Hw?H zc0Vp(CO`G~r-vg(~b7PY*ohW6rIY4DC&T=y+jZ$d8OQM;W_0g%b6>d8R z2L$^3xNxe%b8Bs|e0@R4;~446#;wn%UR=4G<-N1H15P9ZLkLFOG}bUptMXXXysHBT zcx#n8Y``w7S32!%I?i;1Tr&9Pi>y|Ob$^*veXCA6IPT8&`}eR1_3{aP_VZvowY@gIj8I9$KJxUNcHn<>}+iL1@?A!K5zn7 zDk>qN>PL@Wgo0!D{(gS@vLsAOTDrNRsgdy}12iK&Gb6*o)YRO}V&>boZ_~$psuHSv zz&_H<>$gsx(-%D}*Sgw-<5r&pns%nYv0_dqO7h*rt|9`M+7BUw8`W z6gSsDVbi}ti~ozZ_l$~a3EG806a$VRCL9n18DIcGl1K&tfguk$2SJkLoKX}+G7OS4 zLr#)2Dw33(L86jDaz^C#;PD*cJ>R$PTKBwvU{CMv>guZM>e{_~KgImt#;*T&v+w_5 z*MaHRGsvG|mcN3UG*sZ~mex*}H}4KVE6r;K)&{)S4HTPQ_bD`ub+5kQWi8Mq!_E>* z_P8%=wy@a7urnS%D{WF6S;&=Z809AMCX&VANt=CJ3=0p>DI6Re@OkBX?R(dKZ{50O z1fa`xRQkSu|DJrBbDQ+X$M!Q%=ERLJyg6;!Yattak9!9u@EPyrDI2%ScR`cxlouE} zmUr=6z*oTd_<{cZFY6`@S)qZA010H^ns2>v@sM#b(c}Ce>q{(8zocF&j4+!|J?*vK z$79oBaR1I3{+v^mO!X1D3#>0l3R|BPj+iBP--AkyrYLlLOq}g8W|K(7ca7O!S;0F0 zYJt$+-d-8+><9Uvk+HG(Fo!#d1Dji0mo8m;ek)a%O!v!|FU{Xl-t;33&cBdR+E8ceZYjaRRF{s}Xb`FZoj9S>qwabxX|Wf2t186yd~6q&Nn5LQZB&3UlKkfra7)P7oLB1i_+TKT3*4zTe|2+bIE+}s=*4a?_x@Sy2Qp|&?O!vIs{P)T|y zY8)l7acvGj?(*Ew@6Ny2Z3j{iIMOnf7-rr>Dp(qyu{ZV|dc&FYK&~}W!EA!?Ez8Y; zk>O!=b@j>G85S*Ar8KdxukUSUPR`dh>%0($#W&&MeBvFUXP<98O?*DV^YBdSS-d>_ zTm5r3Lbh&K$%s7R4#}|9+t}xO-Jgk!8gnh<@jzr2L}yFPY%X$N=yO<;nJ+limBETC#5 z^U}(~nTi)hKo4{_7TX<(WeI-T=`H(sg5>tf|Kj70{MKKOPaGWo?1VG_Te!vipT0?A z{}ojHwKep=_4aRS{A7r60Y|_5!HF0n(gPD@5D_VV^ovzjkBQZYi6x1R`TvSDF8#{Ms`i)vT9xUizr?UFNo&A-G z@8~CY6`#mfe*BU2wQDUiYG|*aVY;s*pe;A9=I8lPD(Og0*Xb4&>lsGne2eBT{m+WI zDwSp<4Xx3oPe*F3`zb@H+M>S*F_rXHNlq4@+6M`!ec} zas0}#u5e;e-@wI6TO4fvw~6t40|6}lY;1pTu`vC97XCBzX8v#Y75+Eo#j!n>qse{z zF$8SrVdE!k9FpB@AmjFPBB~=z^?mm2X3GOCtQS_|&i^K$-;w|VVqw8lz_<~xsQtAc zb4)=0=_?twU%ujh)p6+QejA?zp5y4*eB%+8P=@eFC__ zEiGUZh01h#a&dBUadC2Xc5)W$w4GgvUCI5v`-*SClKCVxmFkff?%rMnCrFJnZ=6Ys zxUgnb&=vCh>BSE<-KAzcrjZemDvoik7^X!(HS=Zw!`$*fxAG_eompcG)n^C>$^yyy? zVQ3S8jgQt?&n#7+{mUVQrnSeZ$LX~+&@M!3Dyt(EWi{l~#s&t4yZS~u2S@t*`7FCo za5;mP7&hmn9{^070iZh9XBIE?nGRGre(w9uRm#|me4?Xw1*Is1M9TJe^mKLhvfpF9 z&&E<(R8sP`*xtedyhXOP-d@?**w|WKUESQ?#=m&!{H620=hl0s_4Ty1^`7A3vJ(>n z)aJ9Sas0s_KYs?Fy0kL_69k`uebBy5Nl!sRPfJDHgza}L+v75|_VZH-6j;t0B^UqA zf`4z+faa|C|33M`^sg5DpYGrMuUPQ$DgJ98?$7xC|97W>`OjUKe|8#}e{Vn>o6Z02 z`-|hJfS6f+J^KinKQ*_Kv(R}A-ZTm6+ZjF9|9^TX{(Z#J=GxRvkJVyn#&U&1~kFEVCpnmD-1W#;dGFDm-}_AM4MK?Dn_kF-=<4F^jW^T@?_)52Gd;mX1p^P-hQUcI+T>oS#ikZ+bKP zLHcrRR{6WW)?%NwG+P_iv>+lQGA(a+j|g?9yhPKP9=6oZ>4*l^Is*I1n1C9by!%h| zKN@o6e48p7Wmb_gN#e*6v-UTNuDxBZuNt1G{8(bj$y&A4O!|u5BI1Uf0SPzdj~NF= zMY{l0H1*UCA}P_A!pK#zj1+m=a9Ub)rg27tjG94uSnYlH%1=K8uT4ism}~0R6zZ;P z+=wC*b!%~1$10z;EGSfG4uqcNiFo_vf!$v2t%fn3eZ@N!k_-CQCW`dtJ`9fUUA}>| zKVtX8X`;m=Tzvh^sxFVrUM?ulI=fXI#bRPTHJy3)L*`w1A*!wmEB3Gas<;*KW%eh@ z8%Enn_HQ$7P3Vr+D}5^)Rl0Q3(e(#vu8=gQbT$$dW|Ga}suVCMwYyyH93RtN*O+5z z$da?0lh(_YYnoP^-CCr`hHoO7!;x#d3Gr&660>)ga_o5IIPc}OzAW>Fwj%R>XIODS zuBkP1#gF@)KGV#BMDa_4XL-Zp4`QE~ntu{0gM6L1t8cXSBV~{!wIPt0O;0<1DJeE$ zR+%W<^8{1Fc$AZSe~)k8WY+!D;kP!wHh^Q_x1IZlt7hC6)2d46)ii@uMUJoKjud2 zyP!(+4~DM6#c#AlTPuA?Isf?4#hU{x4EL!x5sHL_!|FatXR8TWQb(2is+l(5llS#B zR;0RFebBJ>%g}mjcX0jje4xJm%%``E_Zw;+s!P9mmS?W_jtk2`?s4_2`lgiZq7-HB zC89_@1Gj2+*YNDg!FoLPFm9a)E^NkV_dJ+fE z>)Tc34kc4f=6zp(k*Jp2Dg;#Tyhx0l^!&7SZm<-stQx&mR?x54m5bG z$$T(lse`R~Lwu;oXJ4zWyjVwlz42Yh2kMmNk%db)6xlL= z5}z_aXH?A2rtY78xgVP+PK7Trxl+IXI(WH*lJgaKA3Onh+i?~ zTrT6-|6H!Y-#DJlxh9lnT^+l1u4*sr)Y6R(OV(?(EG3^gc(@%NwGPNN3lnk@8hm%3 zvE}n#=5^Rqf76?=xAM-hPkzP9eXP*`ed!@xJ@>tYZ|**OX#kU1}Wz3WxqS4cvyd~mMrjnVI$pCrt}4M3pVrZ{Z8{b zMAlPo{5`o;3`XWptwIp<7XUWbBTp%q1OX_bmr z!%=m%go__l9NcHRxmh;`J_S<0*M!#2y3e2WmfE(!gH*y*2&^)RxSd^FSon0FkpKZ zFwZypbHrS9{~}L=AkI^``B(c|@>?5*8S{eJ2>BYKy;$ej++|CAh_msqyW^LA!}#Dq zb(;67QWBfy&WT0&5}UzT!kIruw~+9?1E*e*Q&)|C%y;!2W=*nX#M)Yt-i#*YmMe>&O>q|K-6cNzdoGuq z>TSfnN*gy=kX+VXO|3w7Rwn&N^Y}FMdHj>hOpDo08p_s?31Wx$xC1J6jh%N7(H~io zbWGaJzebtNI^~OPT4IG+sm5Iz`c^hyhlQBZcx>9XvKXJdch3WP=3BP;0|)%ia;`-D z86TSaTIWZ8kk`NYP}as z(8v`EV~=WuyyCcVg0+j%ThFR{v++xfwcRg1&86xcBJZ9;BaUc{K<6^aZEV9ZocDfz zWz|d2;H&((*)(tYf^N*%K!FMzlnz9Pd~Qo{K_le4)h?Jp4JLv zXJi(Iss#JSc~Iz&`CKM<-?lTZV@k7W-eCpXv9I@;4lz@-!Rh;t{@NM^XV2nN znuyu&@Tqh{DosQKp9r(xRuQiNzm)&@I~!>UDoW(SM!>)9KmMx!QR&YH|9X93rYFp< z%`gZ0(7rpjRU3P4gnzE84a0)97&~1Bw#k3+*M5=<5Nv^s$a1A)TaYrnu@R|m|KRj) zw>W!3&={-bhQ+HPVTi~27qbT6NS6=3kyuWt*%K_rSR3@;>RprUG<21jCxjJY*^EHwe@;3;FcDH@oYu>4S~}eF{5!+lr*=eHrR|G2thpJy0v-;oFkxE zJTnMJO$KPtB;KP&QZz1q`>m%vD-bp;rzM5asJ`!I^N+F2ZkxZ76-+(4T87FBZqxTR zVh!_;-ZO9gMre#>!{h!UaJrL4ZIcO$J?IcmR*=ycO9+ze!rD%kj@_~OoT(e=y3f;f2-vWayrP95o*AIhM=sXoEDVVc zK1p8Wj+uejWzRl*5rPO}Zc11g^44X5n@JfzquO7&9MSLmp5ztWgY^nZ2pGWh^W#4M zdUY;8hQ5qTTKa?&hBZLV5>shuK4sURFL95^gZP1CVERNqrtpam)GQTnwzALPdRZFc zksChDXdI!Oj;TfCDATh-j3FWREb34XjJfduJR-=phg0=mK$u8GB~%5 z9au&2B4o3Vn(l|DPuOERxDL3(41oJ`ifu(S6ib6q`cfa~h%@qt$r_=ad!SIZuKT^} zxN8sAtW$lwV9~p?2zfFb3!H18g&@{P;}Y&!Ig-^(rC}@?T*39?JBWPhE9f*5)2(dJ zy?6`_Ey3c1#!p8r73hQ@fpXxcGR#<66ylMtW1D`x>J{idPm?(H40U)GFYY*Qrq(q! zZeVZeI9US!*e<_@D#~JLkY>EBmH^`Iuf2hOnUkZ489|Rb zVBR0Yxs+@jC#HKcVUvjklcT1P_*c-M0)RJijh_5qOr;qn)sNGvM~eSODq9zg>GkJb zZVx;vYwV1k{k(j~lp@d5;g;QH5$12P?+@_YZb zN$~q!J7$~f{y)b&{`Hgx^MCse{{QyL`2XQO;L!vA@vXq`Bl}A7{kx5;KW}O5z7InR zP#G2!K~1`)qVH!(cC(h?ov*v+;{thfXH=JU)Vus%-N7Z}kP;(ZKj`XnilpJojC1p< zyX1VEfvfwA)$Js0G1j;%7alAdxH@qc-oh$qAJR^Hm zSXR7ja;C|Ja$MIVFJrs7#(dGT?DYn`-_F`6@}uw;s&WT_jZ%yc!#;=cwh4OoiU0wRAb|cO{Fp2JQ{o`b|g4 zNc_wG10qU}@r;e`9G_egZhzvSxieiVG3d!)A34+1tQ0`V+g!G8H0H7y#tHTyj6{4s zf~;VV%V4!J9LW^l){4w;!D^i+KFo<5w5d1Au1OzQ*)@-|NzaY#PB-}T8l>Rj7OeD* zjg8G@064U)IB2!Q>Jz*3=hB94RakfG{ImB!4!b+?`ka-1#Ic(oznJ;E&H7j_YBH{Q z_)Yuj^V;IClj1C!xd6&!#uehb&Rb2gMYlyRKje&k6Dm&&YvcrZAhqr0p}pR-LJA?? zmtdjIUWTl65Xd~+_nxeNX-dMq;k2meD{JJr0F+O;&&U_ z_Vgxo5A{$sPJ4MxKcTyOSF*L$f1YwZ=FOXilKbzaLQ{&%%ZqzoUo0uTZ{PH`nk}>> z0HofXTQn@}?(7^L9PAq$jJi1|Gq*Uqv^YEew0{nj?yd1%Lt{Qgji+aBetv05-g88Q zhqIbzPbh%rdD4<*s2RuB#+Kazc`IOa=ESCe8 z{VUV-jL%$NetRBzLpb-c7S}z3) z!C4af$-QsAq8gi{*O}|Ny zJgI6tkS_p}#_$x!&G7eR?ms#c+I~=fd06{W?kbyFv%8vpker5`Trx4$b*qYE9tpwv z+l>zzseY0K)fS{g!Sjg&-9(Np~VS$i|BRtu!zgd)9ksANo zTfOW)saU8VOhT8lxHv?Qep({7>Uls_fsad9kxPRfGny})GFC!0gC!%2T};JD6g@AO z;k6+lBm}u2Jl7x*1)Yakbq&kpbt#W^4QO}KH&TW5r9KLMGu_ZP-B2=3MVCXH^C9KU zlQ2Kjkb>$ErK#f37gZs|chj6t;&vBLr}{LJ^g&tHN|aUaB63f4 zZBq$XG)+1>=I5j0K#3P-#x(pinVPrXKlhSA~l?@8wRhBIHLf@rcgVuuoY;&@50d*e!)oe!1w zdgNvM$SmXH7?il2EtBOw=Tm0h`$^2aoJ_n=m^pOxjje_!w|YK){}S3Al5xH{c1|p` z(mr)bN*bJ8+Fyz_3f;F)TOO&j)|wgBXf9$|d%+cAw6JS$lR9-RRbPggEw=eP*xRC# z>?z~@RF3+=$&p)gPq^&M1uN!scXJ727Z-KX3#CG4k0iUh>u`;%%!sI{pXa`RFW||L z7{x6hWj0)<^HIOT_OlUS?_rEECLx>IU6r7b4neMMQ4)CZx4UZ(YqV23u!Sf44s z=WnLpT-z)sWD(0OOOaouM&kyepbLe%AlLAt_sBYlD0$V7qExN8;*yH0+2Dj(R#BT! zO3&z_ z2!h?q93u9}%RI_&I;3l$>BWbT*R`mRqPXIv^`dfAL!z`LFP97=^u(LllKk~tdv1l! zeYwfi>L($MhoUMDr&37G9ehYZ{NK9)l(H z@pbfRZ;+_$ac1>>-poc35`Ae#aFE6~*2~N5g@P3YzJGy`B7N zK+J*0Q|2(XKYH60Sl(bGS@A zp+}Xex|or!{y~<`6xzd-DDFwEdV`BLEyJORfnhB}lIn4Y(8GXYrv`*@T*6)XXo+;k ztQ2mE*>ydM*`&a?^0BWYMDRr77iKMedEm)+!d{Rpbe~`E;LL~?Gk!xkbLkiQ*WLQK zuCKu%pCSs2P*uJ?uBMaTFfDlNE0d=!n<3L5HwUYv3v0?cWp^v4^d-->z!(yH@)?{F zov%K}aP?c>wB+cwB+q@B)76D6oL9b8S$Lfo&v~)FA&MPR;hh}CO%dbeP*uYl7ZTs| zR+*dB-{6JZjXeMQNgY#eH+oItu%13r-}-W@k19iK?JW!)$DfzLO+BK3>9@}10= zf3ycCd0M#md3=jcJ&-9!h!H_6>2GMW_GHwP%RO~(){_^l_w}w@4!Va(ggNi0**+!eIH`u_+;KJ=;-F|URyQ&FjVhy7#lp5y+RBfHF-9noRm9< z;gpgDB095_)cDR#IPBJCIIQQ4hA!n5wnKd}cyNSH$QvXpPD=Kt2Mli5v8}N z3pLX-GQ`+?J__sJxr`J{-i4X^_oT6e5yEcLpywriq@e!5m&MqRKTHjQE1vok?)cVb z^{a4j*Y5hvlry3Rd)+uBx1yq=xLAQP-ps6nGbBY=7{a+(k*EhdN(iP4l0&?eIuD;p zM7cr)8%9}7N~6HL}cR{xC;*G0CN2%K8NR8 zDC$VYVt-A`aFJUV#O4X9sZW;E;+Mv14?#Bf&d0w%-+nhF)j+J>GOpR48W9^En{>@9 zEbLySukKiJEDK?D09Xy+TV15Y->NujjHYHlkB(~If$1Q@DkCl3PGQc_9A0YDpKJQX zZgGGdIdm-d$wm>nr?qTGpiJ2hmJXtZxA65?3W2T zeFb2}#?0FX%JSV7Xf%4l0)xEu2tj7{G8FQ^C_Y5A=cc8Y-Hw*RyGrQuB8Hwm6d^7?=DMx%+dp8$kFKXeJ8fbN9`L4O2FjDwo@6VRq+%8hn5y686_Hfpikr`4M8+&*D6| z+FbNAPPv67H&w&qSAT1VAbGt!Zq#Dxm4AiyzBg=04U&eS<{*u^lbjBhN9#}>!mp!kWnwZVi zi@0b0Mo@i|gu4EP6Jt%+w}#j&(~7_x0XldUPAUfg{{Yf||8E5yF~9Lc%m_@ohp~-D zG#H+1cU#R#1rh4M^>bux!nEi>-aS#Q^(G{EGkojU68pJUT5L&CB14 ziZh3UoZXW78~IsbAa&06d{!Rw-~9PhM&3rF8DRacV=ib)FGm`<=|H}~abVaD7jYnR zg?>TF>gvp6`4Q&I!;!YO#YB(fSq?KwwSIiP@w?L_9vvw#gKKd=B^6Qhr1e-r3iOZQ zkREPyk==LIW9gMX(ZO4-PnjL;ZJP9DJ6a*X)|mey35>j=qABGg1GeZ~q!=82JHj^H zBPt4-hRU>Qg`>l@+#Eq>TcE9DfVY60DFFPGf=7ZBkid-omMqE~=>)K5r%_#Wc~u1` zaQe|Mp-4)?NY@PHZGzu^bc0*W=xq)L@YQH_xb-6p4HC-xqMp>A9R_eT$K<^xhd>sJ zi}~p({t1f=7PDv+Ma3U10EpBO``E7iiYLJ#SQsaFgqeB-UkcW}`{tuR0K)$Hr%!^r z=#Do79fXC2bsAp%)9L{XG5V^H(DV1&4DcNF@-?wMxxZz1L|7Gp{8Wq%IfsbYNO49S z)06lk48ii0tLIKD=BNt)UT%KrkPfYKKc1e3#zEy+Vk6`zBBP+7O9=r!u%Ls(e?bWT z<%K_~!CRU4OWY3j6tWaC>-aBY$4Gw{4to!di)UnJu7!b7+y2Q2XcjqG`ug<+EqG4P zF~@}}1t~?cTZ)so2+sXRl>H^BLKH=?Xs%lAwd>daF>25unmZgxb9D`D^$B42|Bb8( z+Q8${@+vCuxJZ3r_LDb&{9Mo*07S9y7|)IjAn$?IAL;?anG8cdAZaUJ*Ao*vPxohf zOTa2&i~Rgr7@>XBAEt=p6>nDGe`B&`3hfa6krv%F!ZMtkfU8d zLKH6P*TF~2>u)h4@!LyjR_ zeyD8N5h zhDa*TAHQP&7dr#K_(zoqGWM>&F+E+v(KO8yW-@Q+jqdrXJ zdoaVLMoV-#1W?`PxvJTd3lh+@;G`w+Oe%B426Nc z{KpC~oVSIJRz^ll4Ig9jNJwjljP&$ZCvpn`z1hcxlpjy^20WF0oXb?0lJcJ#gQdvJ z%91NviTUjRIbF}gBjZ9=8er&fo8yBlN72&KR&hyNeLt3tG$c5rG_6Rt{=x~-PFR!y z2U3|7eH3K<&3?$BG>A|+(M86+v?p3npk-(#D-zEia}wv_gZ(wYrqlkgX|%y@SREx0 zR2&);uWg;J-5m+cL(d;$Y!+>HTqxDP*K{JQ z3ow$0$^5sE>GlPx3VC7n*yMYNm^PzoGa0*Z;leR%4+;qeIld!f29T;HPgN`}nf{zo zM~RWc!?_H`G#w_+{Gofmm!3Fq+MmjkP9(w{TtH3ER?U5ReU0u!KlWR9Pk3u`@I2TS zOARuWpD>B$I9Kr9O`FE4**_(49=_XFQ@!)m_iuF_t>4XWz~cNCP04vuU~#Tjj?V;g zGzTWBDB_s=#EcQRf#9wNf8yB6)A{Siv*?Y;S&eSzq^FbZz8V$_^kJ4m736Oxy8f*~cXYkkR3=nPT(d^!amgXS&?+*b4}U=g%b* zP{Rzh1oehdD*$y&28$Y}V%S-a1s4wyQt+1#$-xXfF<%_L)lW>}8cY^LJY3I5!0Da1 z)%HI*&^YxJZt1Q5hi0Y_h@@M&$Mf4-A;b_*?;tPWdLD};z(PEf{N)XJ>N>Upls_4J`p>iHFB=0Z zHWkCkp322N$`gHpL+)jil@T4E(&ct>S8rUqcI^*OhcRv~IEdhmWq!aoi{~WRfz<+k zMoPdstdIlSItuTZ8|jlTHkTDkp*olW-4F%44}> zUZ7l@5mQrB6lehJ{r9fTN$-3#7f2C^hj&g`RgAOEm&(&96zb$Eg)x%qIBQ06_AKzO6Z7gR{Jd3*8{!cn`*?ER6Uta0`y&Iw z(Y>jmWar(rsm0@A-(=V@!$#5ldbQ(3<_s0IB zdWC~*y+bpa%2xs*sdUhz7uuYWO8guan@Eg9#qOOO4czO7P|D=#ki6jB*$T?T?3s{| zDz4^zwZI?V=qm3v7#e*4NXqM?%*yNw)*_JY#f_5C64AVYS{y9pzpX89gvrF$m-8iG z$FnqTV>;Tr2BaWxKUmNbMm*X7B=dlt(Ilm4$`c=;9hA842Si0_fOp*^rRHPLaL)27 z@SyJiH1WU&-LDa-AJ`}q)F0KQ2$k=G7}Z*d!i_>SZr+AHR%GV;_>K1Aoh!Xuucuy_ zCpSmx4M(O+ht&8CinWH>80S(NFwbPQ#_73`HcKXmNN~S--Dr^1djAeg390x4J&6#s zgLbPRyNpbq7InqMD$;?s9yUcKc18MWb;RK)PI*r2R5i3U)kt|#W+Qli=Q97I`8=0m zGx6)HjFv`WJQ}pYbQT9%FT9G*89kZZohDh30)CW#Ca&_i3%ivyY2fjLBuM>Uxy5KO zo-36rZMX!3#=Vgg3F*0zPgB_&S?O^hu_i2YwRWwq!6q zn(ULLyQA1}TAZ^4)zFwD5fB(j1kaGjkdT&)8oqWXa=2JmZFb+;{`+vHbN^i!ot#Q! zoDU2Qr>mek2;Ci``tFxCNuve#Pv?&Fy`E1hiO9WSd9xW+7_IjS29rAosGvVYO~pHx zpeDK6M4MffzaW`;(3cz;%}h+fO09(P^v{3uRHnb~|0s}*&ukm@0`@!<97ym*fvs^N zgj%WD!8lOg(?Q*B)M?QV(FFwsGBg`kG@iqBLI$&)bJ8^1bNvUet@elv+IFbe;vvu8 zVC@OXU>LJ$z4=K)3%Q=fD;Cd!Cs(>SyfzK*sezz|0JLJJm=b(n@?ou&=2%qT)^@C z<};vLEV^)>^zIpwTe6wT0iQHz0dcpdvv)Y5@(SI&U1DT@ok*jUUn^L$D&Vg^%g06gTzTNGOaJC zSjc%YXn=LSqe3BX!k_Bsa!)g$$t4VmC22B$`D- z7*pu6e5=}v1A-y?uCxW#6^H35DtwmhN0R2&O^-9IjBSK%jo_4OQEET4@cbRyqni5# znsqIzn4ZQDB)vo(Jup4Fh~-VhL65qBz^*|l4NgvWL*vA*1T^;^@%%H~2@(np!q2Yc6@lgD!QK?xs!EjWlk<~9_ z5d_7`dHPE7)sKVNf@Q2px?3dKI?~>YTv)q^v-RhLx6iX-4K@FKm^YDZchuA7&YwqaAfB}-h&9K_$7Z|(6pp#vo?KwlGf%-y z_!i1tjk~Q{izyvCH0#NK4fWX4Ag#vjzYu>^Rzl2HHA25nz+X{fTJ8i2WQ7T74qH11%kdd>JjQx!i0s<{&xtkt-Uff?B8?jJJxgIE(07_zp3 zxF(`M1kjk#7#pPGnv`v#j;@!*J55A^viVy#^s2pfqG|QWPKhe<3?}w#*Vd?Gnkv{s z+0@mjFx_Nwg=|2dD#_x=I65b33Jy=9F)VShQ3>P;Z1BM`RbEH?Lti6K6)W`J2F=-kbgYOgamvp_id<3cF($hNCWVgng>{SIg z|HLJG)la~|uHSt*#tXH zo^euLI=Hyay5F!utld@v+6p}xBXYxO8D#ew!?NCzeDxu@2dn<2!PpC$ofyz0chOj_ z%nJu_WQq2yW1Bqm&7h-MntWF#1Nsnfq~3d}3wrp(V(=#w{|WYYF@JIR!Xi&+2V!h; z7_EYX8O)cnq=jCkH{CpkK%e9V*X3|}`u1jGEFh72%s+68BMZ#|@6(IKb>i3iLaV3Mz8%j2I7m0u1$C zi*&t0VZg%1uOGX=b_X~My&VXx?~y)wg)yS^oKHHUW&2mtS&TqrG;Dx^{LWxV{@fff zcJP^CPj9LHbSs10^%78hqXiOoX^C{}OunEwR@&BOykWw0ro1Q(9 zQ6vfxv%hD1Cam{>k_{>Nfd-c(p=@RS&Y%AOSuu<5;%6 zJkyJco~|@%N;3UM?%LOqEXeRK$ta9FZ1chA0y{rD_<3axl{i*3-bOCXaE-_)Y@6pp z@h{Z{u)H`YtRR%yUAI=kG=artOIk+1v;pm!S-Hb36S{1l+x?i}d~(fX4k1e3G5nh! zREX4dLwzpfJg9bJwD$DUz{F7n(D&Fa9ncrynDu{ zig)^_ws*P`Y9F{PTWgYlyd=$YhlPoieg?)n{Ll+VE<7_NjF5)|xTdDTu4F6za|1jr zZn;D+M4|gyqjUn-o~`X8+i!WkvTir%Kb>i)IkK*$bZ0rNW>cxA>MWbh;>|dV8lsJD zMCp%8!L6`&>+~!e&aGh@G!(|sNSIK zmB#n@0O{}bf`So`H$>b<>B%1z--;MtbiL?wiQUYU^6bYXkHh$H479ihgA-9~#giTb zS5|&bO;7sz3Y^=Y@}=FuCDWBmu&c}0{K=NVr8W^NvTLgN@lC)Lyu8`onTrNf{xP&BPGB)RpTjrsqCFn z8RN>@ILX=vSu*qRj+x@H9MZ_uYhy5BEz*L9Y({hR*$w??C7JlClUiMPg37uRMR)aG zSp9kFIuy&lB|f`xKrYz+H3W}3o2Roy+98>7eof(OJ5hvFhIvTEW)RALKl*Hz3%5+N z`T3&0TN)f0vlKPS{aK`h8lGu2*4cfHbf@=TOS!u??-zRMbJdJqzgRN4sKXMzd^c;o zc%1;-1kYw?fsR*ge`kez#?g&$v1>q1LpYgKPIgM~vdLDTQn>r- z>il5oB@3?FuF`u>j12GR)-IOmeEqh5{jSEk*{a<;&e!aDYBdg{i_Ld%r^~wu5An@| zoFphlCt8}U%B`(XNueem52quehb=%Xi=lOKzy$q_dazFYlClD5W=miMTuKljY9EaI9r zf603SvRI*48Y5*y7qLkePtOR)Q)@9B7}(pvY_KnXldn2h772eDAy7LX7Z(|JQ8FMf zkdNi9v2NuZMd$j$8m7@}2ZxNSL9=m#lhS7GOngr%zP8&m2jX10LB+dodHK;w;8}FY z0-L_^PV>%WPs^gZnI%VUNzJaY^Na|e-RKVA_-0l(BS0qW>+kPt!Ec>e4=8-9Yh+|; zX{keQpljCV-mY?m#Z5w5I?Xd8KsS}{N#)ne)E2p1Ryg$!^N1GFmNvEajpqG48zr-G z8Cwxc*X(Ok+&2zxnYHW2!&NUPAJW?f{Cp-@?cA~|LO-%4wm=eb>*I%z!itjBwasX< zv7dSJTgIDp$=!vYvlar`-G_f{t?tdQt^HV>9O)FOR2~+_-5pfQyeJ@=NFX6X5m} zKpsHFv&n1sJ{S%h`n{xKPr!zZ`QaL% z1?%Ppg~jWp>UZ~*1&y@4Iz4b%2Zrx)zs6-vNc{Tdv%*anrmlb)P4nz5z9Byj^c3Xr zuYb7`GVnxfNDXf3q6yI>9B7BOm7uKGET-&{U^%6rJi?IQQ$yHY+U%%RTuKL^Ed)(R zf&Z1SNy#yE-_s8D-}|scjA>jK=f@-Pi;MylN8~e1Wo6-HY>3@R(1ac?sN#$`OiX)$ z%X*q!;Pcw8FhXbt!K7Ek#b2%ZAhuH9LEnj92NcvS9Ufj~X(-)o2*fa-U7-AiKQ8MF zc7Z_3Iu00X0{LvdnV8owW~d|V-XrXwr0ZStMb?D(aYLbG7&aqp>&nml)xqHGWrt^VnL!DY|h~Yix@SR%Z!(R-`Q3|8My@=uQSNUVV=-y1l+-!04R1pp(#thkP z+znHi)j@LW*KdMgCRQK=DvTfuU-dzbD!q&W!}Lx`V4lu%#CcHQVAg6# zBnUVdUm}Lc{ZbCQi!_GqfjB_a12>eoC8N5B26NeNdU^&$1uizB>g(fTH;=?Fw4F4E z(XN}>I2;>rwx7Xc_B;t_yDqr%T?K|gwg?3qFI&tg<8O!F!Hnx#I~%kH)2qyCRYji8 zD-0|7mF9~Wy-vp>hLVePJRoX$8qzMhRM}VeYM4NA5EV33!i?I#NqM)a?>$3T9T6 z?LYIIee@TS**%+;^z)U5FfD)((<$)IClAcvz0tFh(ruf@~FI_gJOC9GHTB{lW|X z#Rw^n`bCU^-F16@5l}>#7;+Vd0}CoLc|{BJ26F{vlCJa^VstcuzG}mp$;gL57QO4D zbr|_*2wujtPAA_RV!!N!01T7!7E`+{6GNShBPw|`eEPn*IFi^XiU>zFc2p>Xnyb1S7KwquUOPMd< zc(L-J8#_9_Ro9wAZgq#LLpD_lC6Aogt4p-N$z-w>UHa}bdBofBeFz?q$rFfaBT9$_ zV~p7o`IbYe0$nPAgFG+KbvuZ3GbAv9+;ShH%E}rL{T*rrCKyehMMr=DMx2_EQaspY zS{UnWuZ8+zM-cExMaJo)4Y%7t2gOk6EhzI(A|SOe=p`;|&j;(`pv^-_+VZHa?n)@| z9SO2^&8v>#xQ+q1tm!=#Uu{e*K*N{NHmM3cSS>getqE4HA|r>xToZ_?ZWx#m;GUBX z0d>6lGcU$YFwD*s#{QMhM(sVf3j~0@nL^tboF5Yy*qY)%8@tKBht)IWP(s;!I^ogqkhYjav@@^<6dGIjGaxHle8jKg`UQX2-B_dMOk%nW+?rV5%IfrbuQrj;g-WhUV9>g3KlbLPN9~YwBvv?3 z!t9B?{^@Zdp-eS!56PzP_MkeR-&t?;sd?hFeaQJ93pY!ql_>JpUoVwE8xG=zh)^4( z;n;-^CGSEZhN3ZE-@3b}>zH=lzI}5VnnMp-OrT&ftX+a9BI4p>U`0Ckkf8i-qx7YA;L*(=dh)#KFNP6Gb+9?hS~a?eE~(_zC4qnrZyH z6wb{r*r=7X-Ll!;VNbeu$@!g@wFP8Vyntnp06WJ^p%R6?>ZHOam;B>OV{%-}$-!0}i z^}+v%gMv=}Z|B$?KcV!0W6SxOK98F(ClJ(i;>ziB=l;1-S^Z42MYike z%2juF2j%4FTTjopDQ(#jaal45O@GY0s!ONSr|~`A-Cvs*3t-##>DQ5<#Hk}%%>-4cMUV@3^V@V3no7}w5gP4E|>`y#~O^8MT|~1xMdz51#jzz z?>gbwmSvId0$$vo?7%mFxt5|Go_O4Ol1iPUd^TMilV59AAmAjtW5=Hoy~Kib{lCkM$>6L`)rVa5c75~h$VyTxz*7pGr()$36ZFKDKjTO) zGq2h*j52TL_;r1KuN!yREbm@9>9(B(MiW_7Dg@#9SFlHKWH3p0UEr4 z`BeUx@piH&y>Q{G$4s}W>$_Cxwh|Az{!12k1wE}Z>bJVy$K*Ha!ZLMwu1{~KE>;K% zs;NA)wr+@Q6y?*Ns)TC;m}K(PcOFLhd+nOqm<^%1?iRLjHUz!)Nfmr-GJlD#D6T!% zJ@m({VEvcChDAT-lLBq|erNW2byE@!PCOwvkW*k}X{ffqKU`=gQEok&89_W6Rr4y` zNEv(+aXxD5m&N2w!QCUp3udNSHQ?d1>%yOptzb)34bNGa3HDC4EOA$1)W>8PXIqfK zkqJ%a;I)Bb-?@G^*!5W5Z;3&RexCl89RKADwJ}swApz{+tc33m3=SrZc0xfU?+WBM z=-Npk(1zBn>Qwyv*+~*Pn` z1eACUa<_0z*6?R>_JZ!Th8M2R^etAsHF*8O1MC+43kfmM(BEvNslVK&uIDlPCrU!* z!7GO8Ci|8!32DO9UF}qAumpzgR4I7n$$hv#LL$McfBJ{lMZRjKh5*-VyW`7Dw}i=K zk3L&m$gi;4nWzqr?g+x1;Zs(zKE6t}L_Yh!54 z`%gum?o;dy#WLQtDH(k3vR{_Xm-l}s676GF2ru9d@ zXLMu@uWaZssV+7B3HJ{iB`KUD4DFbTHTIQdY!Zwe^;zlnpD`eH-7QLMTj_E(w3sTq zuV-9$weCi=Y@J~sUWl}~BK!xZw>)a|3VUsN=by+!iNTjtuWiJ7z5AJe<&W-6x@?=! zAO8ojE|fde@yVE5guq`(8g8sV8wn2><+t_EO*c<>7h5a~RBjP~7EJ2}8`U4&>U7)U z`*V=2JWY4ri9O28$Q8gIO;USsRpZ-y#m{8RUCIW@BJ^p4u0p4eR_E1kCP_GFHtK~T zEz&=_m5=4;xgENi>i*s=+&pilH5&|Iw5B_>RvOqyWk}r%{c$ z?r%D!)adjp89rmDbCc&TXvocO`Ey4{}r-gZj*0I zL075lA4EhU=>rxcyXL31Zc!M-E0b@e}Sau5X3b8%V^PE9Y+! z@cpUceMa>t?5*u_tH7zhhyeC$%R6jZcCWmwIM?pum4;45>0rSLO0I6t!vpzpak6I3 zDupo#IfGcYwM$C^VU3?9ZiX^$;D4u4vxn{EEpxqV`XB2=NEp{Nx*XggN>%fGAF7nC za>Lbhtm95*vh>#_Sk|b7@ikd^zvH^k7mejiGmUaRS{hr7pe<-`$ZyTdug<1=_#Cg% zcC+dXV7?yxaqiHT%jaTw7aw8bo744Q>MOutmz)!X(6m$X@R!{xd3b7UzOJqQ&i2x8 z(9EX(bqk&GV!70ZB>zF><2mm4ma{s)co47U8o6NICl{Ldq;4zVf=PxoFs&h8s7=&X zubDEzm3;JWuz&Wuj9&$g_5;>O||g11+dKvn<%&@lG6U(B>y4dy3vf9r_6EK z`li8MAMLbb_(}n^7@s8k;N-F2*Q1A0q?0M7_wLOsoj#p^si>Qc6MUE)5aRKDD8GA) z`Iq6wJ}Sm4+Cb^feV!*3=%K39&u!B7*PQ=erXKHjmodzqnh-Zv70zsV zF!GhRTxwg+#R&tJ3LCq1z_)YT^M>Ei!~NJ&f>>6_01s++!yhBa`WA9le~k}IJNDOp@s-5FmC40}4+ce> zHQ_s*Zd%&+8#5AvMFi<9b$I93?720a7Nktym33MPuGtqH+MCYfj!T?|nl>zcxmfAoI5ksBp` zB*_0#m9rrH=iIeek(J5%0@nbWMbkS}@iiJ}L;Xe{9hmvPd_;@C#9r|<96&>#1 zWSy3Iy0BFArB&DGh6nrCGO=xLy2k;jvvZv&qVZTrZ4#p?kmYBt?I%?!lh8J0k3&7T z`$N8*>ZLzEvhCO~F4>|t|6OjEGOI(m&f=K;SdQIi;NJ3pTCru&o^|8V70c@)wp=cxpbqsKb8a78uqkvs!a}fsqjh zb%sM#mX7#yX`s{TGiFOkO}wARlvXEaB9o(>bKVr&RYcRC$&By4mb~57+jZ4|j{C+| zJgRUNzZB5yB{s>Iw6A_U5tG!}S+O9Ojf{(_y`1_^H`?I>pEeE=BhKPy&08kOoC_vC z3_Z2w1E$HXk=q6+dsEBQurhC+E)&16wkbbYnkikree-~ezm{FdSH|PS2us1^uJ<#T{_S^5xf#5vnZJb)w+H znaQ5(LQ_=bHe{^h$JeV3PdeTy-J|hI$k-A}zP)q4CdWJDi%}z5_MF*1{|Y;hi!HT?21=gls#97p291dT5C#Ii}UjgZ}T_xMFx1} zT$#dDH{54M@xZGiAyPd)u>~h?P*!)2W*xmp3BA+1x`yY>WMV}{#>h3&Oag@!sX;rk znaRszH)H%K1=ST0H5C^XDi3uqhm#Ct&uR7C~=0 zt0^q6N(y`~Q*-eOGiC>@_cj=(OTKp!_=9K2_Bq<^{JywuSK!OIRle9lV`M;=T>BmV z!Oor!!n`?sfgh_{_AEses;RGt3>Li3(_E4;$y ztKX(hQyQBfB!B0K;PIzli%J`KHU2O~oeIXQWwAyLXJa2DN`cvc+tYMy66zqQ%v@q_RUEMng^XFT#_ef$U*Ph#O zQ7TbYB>%=3{#wyYw~kjS_NvsrCoU7ynZHOERyXT!kHT)1+K26F&n&t>u1EQuF`V{% zUl~R0>DCt&50(x(WY$wk7h|uE2;SHrOZHqoWRt=ORO8LCvMAK3m{VOVe5O8B!@r^P zkmgX;kCJmM5)4D!p0gLci?bn9H5=sQd!Jdq2;B0zLxF#c`PRo4#w~Ox<;l0&t?+Y3 z{Fp7cnP%wslOMA(SGcl&f$tEbp4xnAOFcZ(u(=oAG>m9Hq5s}U@s#wNKLM@=<`vdx z8(nu&pAu8K0WYs8*J3_wZS9x9SX5k0AX$&z)|s!<)(WEkib>9~ZrcWxRn>}Ll}aOF zHQpBFhU`Vv+jJzL&?x0MkH}?u2EWQC#MCYlXCA=;8x*A%;6JP*&tScUc1h^aTJd15 zbvTvRSvOTigor}qTSG#%Tb14&X>ywW)QH7>tD|b}f!>^He7Yq$b2syklB>hfnKS!N zZVA|=s5CaIj;*Sd!4)OBZsaf23W{e=u+~C!ksnA)6aQ5M6r9u%?P_JZha?7|u7LreGnV;~VgRJiT15&1{j zjcg0h^9-YUW{<J3U05RVpIK;g4|6Z!z ze7&A@%k6OQTG@Ap5#-aGGX}^k4~PGeje;F{gVIFsx6dE082*2M0!O|i{jQb=G)PK~ zGH3hWI}0oU+Lt~kb7=p6|7@PAr}qQ{GR}WIg%E+A}y{ha#K(k>)on!b{eQ^chMR#cpTv${$9Rgr@dDdoHShXUS_6 zClfK!epCD-^Kgwc^yVS}rxV|eEUo>%N^GrM#H2Suol*DTKcWY(p`8u2Z-0NO@M`6K zzBkQb0Rv_bQJm=uQT**o*nMbAm3jX|5j~_>4q>VF&kLkpm}7iCGCHR=vUP#apb~hF zjv@Im9I!VQ&AIkFyL6!N+r!;Wc;7DLo$gynQ~ar4V07oTm{Ghvj?m0ABA7al^T1qd zyH*eFS>QAKqbnFhA3f^6wsIa0)@Am@h=0K-8Eb87Kx^mg4G^1E>(R~j+YBhX#f-Xm zq=U7hY)6`ZrBf`yIA37McmzMy>Zu@-9Izu9%@%$SH!M~CP-*_j_Y2C5@7b`5Xg#;3 zP}1Dz`WWtD=krnM-cd4T4U<>J01-}wX}*OeF&CaIV2dsA zT{1y@SD6PFDM3I-Qlsk{D6v%BXF0$oxWJ0NHbSuh{}^~7{;9D1w^FCg=Mk-q4N&1r z()ahCRQX!Wg>44ObF&uRK~!9x5Vu>YPs~?EEx^YCh(9|bk$6A~+7mcR%C);F{`jUk zs>kW`qQV4eH$Ws#J^|PPE~e;gltuSSoDAAm@5bWcfjzyDz8Gd9W&R%~@BT9jxifvw z%%z|=7u3)PQy5?ypi8Es;)virhf!S7Oo`6MTFi#qO#IAHW+NmI=nWic&P@6yzwC`T zx2vDylB`R8rw%QiIgEOZ2nNo>YO;&?Z>-a0HybB({+TCkdy(uiJMsh$*q03HDDcao zZwyz4ZE7*&TVI?xDZ98LVCFriw7_>}sWP85+=X&%cSM-jCOuoaQ!!z~4x5pr* zm52Katw0d^xqxfcPJlpM$OED7v%~e;n^EXcBH(eGDUx9>x1iAJ*V3e)P>ZR(#iZbb zQ-7iB0d40JjF2Xgz0eyDQWSoTNk4|J>);HxheX@bg^L4r4@!!zke3;B6+wr1NqDl#&ql9J}>h5`<_g9q|V`<7+@cu&_Zkr{lnXPvgbh z{J)dL7xjXqz_y*cX^K-UumL;k%nR%hp>| ze*J(a8(t%2x>&zg{WhD!P}uIZdfn2&@kQ&bzFz6w3+(~jJ6HG&zD}>M0*3&j9RDGKartM5gMU$! zDG$jTOghL^sE|=xt7k@>wjZN6sQYCpTzzo@^80+^`HNBOOpsXpTp*RIUriukfsKE! zMO8T}?6Qj`aa7G6Alv?ZEon~!3S3du1X=mRR6dJnU22C#`+-LSm4d|LRVw`W22%mZ zXk!EVT@@V*bphl7jRH%$v4P2Z{@u-JlJ8=bvNf2nd;$7Wl79>p3B^~{KgT`?rvBwK zQ-NzOke;{=!UOn?l2O0en)c<%F|-E|(K3RcmHe^;K+|C~zaG{wL0p054l)Z3$0+v! zf%<}Z>RzCixR|Q^0Pq&Au6Qm90{Ct=a`7;vAd8+koiPi-$ewc-HgyHU z0SAF!XTqagk52x?@qHey;U)qH0nU6>O4i*?MnP8=J?UtIsIVWdLDbINACJ9q-Ww5l z((~Cn{vjN&6?n75Xm-&Gd4lhsdCDM#b!eex3ek!fs&C?C~<=N zTd9d+KlVP7L!}bd0@wU`51CT=ubppIvd;Ro=oY;|HpVX$3r+y{2Z`8YJ7w1sqfE7q z1g|j-p!LeI$T-`R_4rS5y5v*%OxN_iKx9(3=Pcvfe^doh=WbXxhIl$~`nFN2*-Cbc_plTDnGjBFYH=`B@S(7v-J)w z@Exnn^OULnbMM6hc}9&f;0Sp0XI;ASu;zxtn3@rGqR zbUW^Sma{Wd>zc)m!ll`-Cys9fP;;h!vG1F1&%p(SZrAG@0Q;Q0Mnl(3e8h@rzQchu z=(_ho)yW_Xt2iG*#7E9@n$J~uOg#e-VIfrS+5jILXzb6oPAjXT%}T{-wSa;__M63n?Tx1 z1gN@nV+3yo%9}QOkkNxmrbm}o{Ux*XWPpIzbY%@@4O7^d1xm%xVvADjAc8ZJZ?|_`KJU2B;Iho`(voZZ|3r6AB zbM5~7w1mP}*7{c5etXIKnPd)CSK4$iHI3rWrP82NY9C!RZ4mEI5e#1Ld*!}An z9KKsl5c?=WdCyr+4VZNR<2}q&y8#P>n}Xx%vyAb{E1>j{6HtB1;rN2@YR%J6-aDA$ z-JEns%~&hwxd`EomyPB^^Ekfw=Mh$He^Q}()i2?zQmN{cwv3nI0mq>1 zE#e%WH`Lu$^LYuFPE9C$F!i^ET;L&Z`@WuZFY!dYH}A2))O2%IIdDf(#+#Ux9Jh5h zK+Pwv=Jj!LWy4K^C?NX@2+gbq&!Utymxd+3fO>L)Z!b4ej6P=?eyjhD{XtuBDt;8(5%>? zu`C?u>}t7Af0}Y*c0Hx@<5;IqXYty-K&m@NYZLR_4E_J)6au(ymh_H(ko5_Eumdpk z55`+OdpD=y&}OwTpsO>NLrj@xI1K9O z-0-+T#Tyr(nvG>V+qlaUhyF5s%pctIpPIBOv!3H4AwZQs-Yn3cC14!JGSzJRA8wKw z9sQ2j%=}@R3r~GL0RVrq-$H_#WHV+d z`KVKqnBQJXPjK`QD3YdB0naK<`?+IzVAN7-0;SBjX_UfM0vfdtY z&6Q|QZXcKV78u{Az?Y(>t1k=Mev#~J^rS%4<*bF!4}Y{Q9#S(t-;MtPU}g_kGwIJP zig|!M>B*|%Hau|wskmkFPhik{_dRi%G&!z|Bxf4+f~!~efU5ni|2F=ae<2pMc;y*6 zj_AGecKpt;Jsd>PTJcv|I52aQsZbOFOj?Um`JMqcbQdoq`kvUud^{_}T_^CmQ%3<| z^cLWU$I5oPsj7*~&><*AEKYMT)a-9%+qk?Aap`6z79EfGkp!Z87%%4UkwvuSYC&z{ zFp%&XMd`_f&(&Go%*CXPXu$PaMt$3#^+zU?gqoTK7x<9hyd-Ho1G|Zth|ZM_UMoAC zj@kW#q?^oe_su?55M;X0q3nr2i5}AI+U35xbeWWY_`{d?0T0;4OP3egce@?lja^yS zcOdor>x7$>svB5GB$VD<;pgGyosGn`JW0Q%Ou!8@iE5j?A4Lv*Z z>wV^={qsD+qk?h!hZh7@FJIVQ1>gCv*gTlhIj)(h3OQBdVbi#$p`O zw@Xj;*DTV49X}v7I+KuqB*)?i!x?38+{D*O+Z(Dbkd{n{n4+gL{nLOwO!dV~EXEu~|z-@fE#=XP~iE_8fnD>s;bXHTc-TN!}9>#rqCu1^2?nH6&r z89JdqgES>I6ebep33t81DtSKHWA;yogtdmr>xyGccbOn9w-NZcNY zm7VN*?|fag?cg2!t3H-D%6$a1oRF)=FuikTm)e?BJo9e13pFM}u934POindthlS?n z5DKP@d)IW88Vl_FYLA<5T_IjSHUjQk+`7)&_O9QZ&iu0t1pZG32MfLFE~~kkJR`JE zBFEj!vlay{b!1X)=c#LU^DrG7kU_y@78ix zp0BafYsu__*A2h>K4~|9h&@CN%lu*qK9|lkmNqBK6#NqJPBWtUolL{}Oc-nM?0jWL zl{d(7C~V;`WV?OM{+9DA@K)q2f5_K~P;oK0H#ff|T4KUo(ZtrizC*H-pP zIT8(?Wsy#;IbamAPPao~T;*;9=dT~@xdl$ZDC zWols2xZofe(|5|#zF}x1`_UxJOVtz&XS@eb+-^C!P^V4Pf*`6?v`AKu|43s@PvjXQ zX%n=9oE@q8@WKA!?j6F*iVGF1o`c!AK+O`j<>{6_aS=VqZuvJ?iuWF&iyVLy2vt0{ z^m#-cc=zev_}o)=mNF~rG@%2C3@xsbM2nZ^DV}n-FnQ-UnM5&6#trmU@70}V$Ia_AGMv8m6bd8 z)Z}ap4-XUAEU<(&Es##F+r(O679JOH(_h`-aE+56DH>efIt_ z^BSp;U-B6Ft^dt%zm(PnsZEDt9#n~JKZX3J_)Ol$OFgp`9KJtHCSs@DJ14&UzTI3K z@p*|hjfd+Zvl0FBW@yLYUFYF?Z4&Wm)HY{qT@G__;`p740$it;*O$YT!WrX}$;n^` z(a|otxH#FVIn&uUxdu7u8_zyMS;0t3cH)FcsxOD5H#18|(ateQ^I|X~-I#bI-bh~3 z(8T5oUGB@J$M#M4_TMuwgK~IJ%MC9e$uq6`ITWqnhW)EKRI1KNLY+TrR4}iBU|&a| zCpdSpomT0rGnKh~{c-M;sh<1AegtnD5}W-*;+s5?*-jvM-!|{LJ^VytzU1a_Qm+Rt zly1?nc`aSEQ~g~?gB+DnnTga*i`OS}e}~oUf1I}4Wc$Zhy5)CHfEO>G zSlhHMQQAZGJ*GBCl}I(o7YVIOytAAv;bLMFES5nc^ik43Yko-~E?GxL3I^K4e(pzvwU2j}i#NxwcD_k2n{!8Z7MnRQIj02i5xA2j60liAdPGy@;->)Px z=^<`ce0Rg{ar*z1V^fmw6b6qBu3x8%>MUCT-;#CdY&2O&dHR4H*n$s2)=l&|m z9`8cRsN^asPM@#aiN3r0tJvwq^3j^CnnGAs+eL#cYR;lNy9Vp_X!SOqd_&QS{A$hG zoQ!!kvE%&o?9ni1LdDqDzWjG}70G_gJmwdNdbmINC~?X|)%uWLeD;AJkyApA?8L;i zD&p1mE|}S>>+d69k3MC2*jA~0(MnS$Ia5u0NPo(uyxDgCYm;VSRrVS+x`m2DcsMu)@p<4>G(6jK)w>3<`9DKFX zYC&aO)ptg6+2eaMow?s$qByJhi+koNz1vx9yuseqMolM+{KV zzQnRs|CSo;Jw1BaOK%0&pv|+~TCQltNmiBA)cS z2@TAjS_8HG`f~U+8U?tie9pt0_1V{#r!97dg+!r3N0nWOZ^c-EW&tKR%Xh*z_=e zdFfU{uGm@PbKLw~ahXMJlb_TnedVEzT0bE>iJhKn(J=U1P6HH#B?{OeSoOO+ z=9vY^{^nXVbewb&wPE1)u{*{{0%$iJH;79_Rc9#`#8m?IRERN6hmn(|#?#K``$>?R zCfB?RLo=o@v~+n|`VrKSMh+k*3U0(=ma?5Y-cpV>)>%bGDKLYPx9Ivw$a7O|L(KTe zO$4IlqZt|NpXBl8_$E<92IsQeBzhDDwXD(FAxIOe@3;1gfaBNrxew@Jz=F=IVK%h6 z8}H0^LySY5*2ul$m-)7}ov80UgnJ!?9TFVUmmVT(qZ^wZdkLR^u)JpJj%lvd%2~7- zGG8Kz$*J-!nMR@cHvJM-7*;T1o`wcyZ8pnUzq{LTyf8hqv|>Jm-Cl*6G5&^tXJKht zU$cIoKC0F!mB>@gLQP8~)`g!7h-2b*q_1sUoAZJL5c71X4mrd;^#NUWFYnZE693awxf6 zkd1qU9)nv5ZBtMwdx5t4@f2dR6mbOMn-QhykQmZL-k}dik7`IC;v=-UQ$yG`>Pxd%-WPdsd!OVvWE0}K0$H-V<9Nz6>)Ui2JVbEpeXs*<0VS1)Oj>n1MxRhq>5@kD^ zxbU44`I;@u!UO@bwga1wr27ssa-SKaPScRJWW9zx=_!^~MU205LYE7F)YRucTy^a#Wu?h?8Kf_Ff^F3rm>`NL4kQY1aY5`C4AbL}#J`F-9-Z0z$= zCAtl$ZX49S12S4ljyuX!@XT>@@t3P4rqy7^ap&QS6_K}-L$E-cg%{B>c>RRAB}+tC zvl$8n!}+?fB9-x8(+Z7UcOD2pdAMbk4$OSV5UROGzn!k!>a+(rE`w;Hajn>4Yy+Y^ zcE^Z^OPV(7v^Ev9>?oe=Ap9RS1A|wlQI)<;4mv0%y_SILfvcT|9ZX=;{TMN1@nZf` zB%}2OgO`mN#9n!~uL4rdsO6C5_zpdFiB@>PbSW5FZpL=wRnUyKN#fBeN@LxB6q5N2 zTX(2}65n)VJ`(7|t%~6mi-@rcDj`+7M!5?pNAx1>?4ih|GOXiwq5WL-WPd;xyYVlN zEZJTz{3_Tzx1XU<0aQ{#({ZQltD?NVlCj7ctaX7=fgRfKTR41AF+p|+o#b}bA0xJq zE*af_o3UJx1;2&HadzxzIA#3okUo_y#bE6G(4}{@PvwqJrp zqw4}V)^QHCC&?@j_eCktD5N32nUzz(6=ou^8Evhzn+iGL)z^%*SkCRY7!(1WOW&dA zESI$8de5NEq)Tk&@9YB?4~sH;%?3qgjJE;YPhp>wLQ)x+qA?yCAC1bQQB_&wOxMzH zKjp!6o~O}kCDobv=oK6=b@UJ$m(D)my04=se~aa!TN=WFBfym@E6%aktlG&ylV>Zm z6*AijU1@=~pT8g8GvRkPb`e?z_H-5%?LdPoiAF_FfGM_5p*xV=6E2%yKox%-#-7yE zW}M}!E7zM`0f}*87b_o{(6<5!ckVhaRt|zunU@eA?KHtlT#Sx5gBIT*{g;2)_``Lr*6nON$KL*UH9&bV za-xG2zXpC6EN-m~YXLRiWh-Z}wG&UcI6UdO{;zO5BCvjI@4-|d4}cw~VTZ?v_sVFf zpQhf*0EdabW%2MPj=lB5F2EB>x~#~Q=b-zJ2GVU7C!C`$g_NTU4&goS zPt5ahmBcGm#69m$xCCn}!X=d$U|tICSYUXjf9*B}^2t~YPBI@fGG?c+KXpJoJ^0<) zR^dIpn+iFKkqE&ml6rD|PFmm8K%Zipq3C5YW$rvsZjgiICXTgarz5h=;M-Qt+4uO_ zxYIzLlgrQ{R558K{e(-QQPKHT4IU8IPu5`S(f(IPMJJkG!P3Z0WdNj;L;5>|^Qtp* zj&e8&Wq}S=Ysvd*7#2Q)V%9NkRtrG^1MMX=36e%OgUFxmNYfd>mYfJ1o)P7AZiRNc!r?nO z=s))y89w+qf{TG%33?zECIk3aK_T=|M(bNfu6JQv)K|(Uu5a3n6NmMQ&UVxZ&a79) ziT#t3>*|gmGcDZyp6TrEh-*AtGf%t$vL=vmL^Go0-L3Qw#4vS$FM^0rgB@e&bHrs0 z5_dPfVf_fwt0jsnS9$1Y_nd81MV*rx_!o!{0~NvkKOs$}jA4#XO}&94pjsN`mnKJa zBxECcbm>a<-%JX`I&3vm@ST(|#L1zCfXI^>(L#|>MQk$+B)2qEXQ zS%hm`Ov{+ShOs?lxki+YtV3ESPP2f{e*j428t`+}em_k?btV!hF~t)Ofk$>CGhB3p zwxid!-iPhnC#lT>4}ni>EbA+*-iJqJ5({o}tv}m!^?hhRfe0W4fRg#Jeh~U$dJIm&as-&p%0ZHx$Uf-v&B4o$F9pqX8b|`W$TgUa_ymBN+g+WXY zVz|9P_9F)dp?xUG+)1{q$h9Hp%*-{eCN{IO8=)QR$}bJ!ciR1z@ry${k++qUqg*_v zr8~3iDux;Qzksy>^`}Aff1VHGIoRIOjo&@p2{MVb+~jW6gBI+83m}<>bF@w@s3Gn~ z0)C(lcMlD4dV>1ksuV}&l=W12@g^NfYF{s zRbaf_@L&AKZg{a5R{JX~JZ?3Hfw#kOFz!et#%%ccJbJSK=F&sZ$@3iQG%U*P#G1l} z?L)?{fLiE(YWEKs^#iTG#gGHG22>V7InD2a(?w2C-@}_K|l9Yp#{(X;})2r_Y96w+F7Cu@|Hjjq8K*;D>QZ{5uQQl z9$=2kAa`^oz%-x%X#_Ovf{r}nSdg+gDux8-a`T^0=;2k$<(2-KCvh0ax@{Hg$ke*OP&^7i=~9or-+gNn(OR~LQt)0fZONZAg%n# zO+73QiIDCxP8i+tH@!;iC**qi_C)~y0(ouAQDlUs;J;Q2_|}O(q)NzXcR6R4Jy%vYR|udzO23eoTnlgQWJu2|??i@mli0vT_aNh+(ELhBJqTcm%LIiofZtgI zB7f;;NTO$MJ!(E&_HU3CjljNDpkdx~#gQk49Q+M2K5pQM4xfbh6X(&`zcBR%+CO7F zq)(jo`j1R>R@t8z!*&e2d9ENOp&5?vT_Vw zky!&2@0bZu1a;@Gn*aCKv+L)8LUFa@`GWlo^UdXz5d|l}BF=aNW&^%@1dC z<}8^a^~`icGxWC%{D;Bt5Uk}Mn(`*gl{1_|@jhJq6>(#T{^r>7t|?TVoA2i!**%2E zDgOpn8ZCHsCE~x(r36vnLYlG}YWaK!zpF}yz^PB=S=a>V1*sDK;Q%ZE)TSU$Lr?VJ zg<%e!FNI;nVO<^IG=L-GcIe38Axu%rs~b`JUn^U7CRq;LgJqc*&1FtFO|gMLa!udy z1G*=YWB8uBzz3|g(ewY>M*R{_nCn_>u#QHZ&(1_6KXHE57rsTcv9YK*VM90qifaDt{_QL7fN7#FSzq_ABzvG1vc5ebF=*>Mt zG{~cjR=z|4zo;n-Z@RkKi;=St&B=Ms^)rAKw_w`#pOntG94Jj+rcpm2%n)+myz)jb z&H%9pFLr3B^Jxt;~Iwzeq&w_kXO6LxU3}TBlITkaFk3UcU*UB%> zbgXF9h%yAhvC|yLIfZy7Psz9sCQB4QcIo%Uz4KHV_KF?XPd-B(>4sSa zvEGl7#7{svqpZUH$QWWMXiu`^6b(cAXNMx?M7)O^%7i&k*}{pmd6vMKXv*s=*fAUr#Tm0(WlFuS*x!R^ z>Yk27Mic9oxg#Cw&L)%LGSjuF3TYty0n9CBjA0tn+}}9>Wz7xRo4EX^4o|1AlwBC0 zOhwkDNXu}m6AU|=Z9zR-HrXS-tD;4byNm(W2MY7ptnX#xZ|&fnNj2Ow>nT<*3_DFW z8^WfJM>5qp4A+1qwI9Ocz4k9mG8o)I#2;*q|-}2@Xyt?EPhg}Ob?2dSk zf=rbIuwNO&cNl^}71!3G(tj6e?5Z)iBMa?Q{tcYM3w0T%tUMAxTeh)>xxR{Mz%F$GtvKr49&RO* z`4me{MGFPcag)dwH$}r76U}go}pAuHV42(aE6FL9l%BH$C(H z#u(m)Ua?AL=+j5I5zQH;K|LOk-Hm6~QkU(;Uv5>5LYRIc=6KS1(O#^NZg#%`1v`E`XaXyw}9Uks;YMF#ScBQl~ zkae~|xrgC5Y)dUJ`r#6Q3Byh?azW@yIb$FJ!^w-Ms)-rn*zN)RvS11)&UQ~wJlIY# z89%vXp$$tAjjoHC1S>ShcS@E`QV;(%((bup)=E74taJtCv2va# z_WtH8?Px>Kb0aEF8}*A)?)fzcogGZ)7OEZRP)X8AQxC^k*QY4`UHj)Oa(eDVrrY}u z183Qc53Z0N73CD3k)VF7q2b&Z;#h4R8eX4^LJJIiQFST}BM`w|P%#@P5*fXp0T}8{ zLj@5h!# z+*OdgOQ@5RQSm#EtYZvLX#{k-^eH>0hSD3zantO_kZ-qw#X_w4NcbSdZjfXKXaB7a z!9qbBX?Tn_CwPC5kFzNEiALpLni~aU+4Qe}{0Zjdycx@6eZM1%4Dsq%HW(d!#UlBv zdRQpe4Ws_LAn7^*@?U3N*t=mEznO4wh!b(C&sffnu3Ft>(jmZaGitar zr@BQW9y>=ueA8C}7;{#T{s(n$0TgG}_50%PF2NFlySuvt4esvl4#C|C?oQ+GF2RGl zg#>rk)0z45elvAbr@mWfrtZ0to_^nWd+Y)2VNR4r-?7vC2L-_|`-@<%O-Ki+cTaHApRey_`S`w!Zl z>pHg1yuprGJ-L5H`}1nlZ=m0~-edAl4r0A@_+h6XN>b4!d`*|%6 zvIoEFoGxzQWCs7S=gGg)S@XDxzjUmBbE!WC?#EbvAZk_hbF1bkcLXD=&(YE!klJ=< zSoiIlVbqP>tHA5R zpOWzk=M8~Jx~ETAxs%$Uwcvx`PZiA|MdFdl^chG=RWLi1_)6i&&-cqJeV0bafV-(>FJ*RUmAcW(X|M@f2!^qBi3g7 z@KZ$9xMMGSj=x(SN56Owre|XicgCF zoPS;O67jf+5cuA@gud&P*9i}6Qdi6`#gHj{KTj<63@;q!XTF~068zc^`~@@F`GO~J zL(74H3*3)#e3829oU#BrE&K$7h=vb=#&SO?JoTY?=XUq24^`*bWp{NX1<&sQ1L_|Dt2-ZHQpIi)jb`^Dc84ATrJOH8uB4_C|Z!hSihGc4@t@cCB!S ze{K?d-AC`{?wF94*66?~hR8mG&DkKD!OY3;F(W?qb%Xl30ij<_66*C%X5PR)91aIc%6!}TQ>N?efU5h`uOTzk#A`1#2!FjxHdPY>i8X8 z@3Yp7xlbn^zn*K;bHe-ZAy_hJQvmb&Fap4@p=Chr|%rO6)iwvB8Le1A=N#X~;uc5x6Poq1p zTlTmQmfOBiuZ5Ai#7{KL>$}V#eLm(9+{rd5OE<7pjs)4D^BV{+L{0hrZi0SO#nSH@ zvk;JCYOj>o4tNV?gp;d_`Jho_e$9;42UuC!K@2HDX1z(M($%bf@TMTG@!72eQbB#WLxO0PN)0gpt!Juq`P z{O%_ROr2`X1Q+wK97IVF@+;b2z6$G`h@$)mYPi>=hYh9RUCp@81|gMRw5=)0oKg#L z2b=*EGXo=~#D-;&K{P7o2=WJ%ywlVc*J#ma0ebWWvLyv7%mvtsUrKfyZ4OAP=r%>@ z*xMzncvSMGkZVHJtvQm0N@RQKN0T!9(`;p;4(!@^tsxFU%M2Gl8oyi!Jzs&E>*N`< z#lj_p&VjfmxCP*`8xqZR~(v>L8=C=u; zF8RJUfJCB$sg#1Mm?#+pVvwDX8tsR?sl_p-TWlVC1X&%eSNvHjTcg7eN^{XiE(fGB zr0;P+nKF9KL#as0u+sG05Yllx)AF69n%~;KV@)g^s?2Kd!r1+%7NI2;F=?~?qt+MY zHJUjun`4(4MyjI9XAyEo5T5|JU09LpeFoV*dpujWeF~&yoFth;I7vY! zqj@Ga5*rM~T=?_CkHr&vVZwQ@NjKHIPnrHND?_Ved&*jAGldjUAnEUdEed9&lCq{N ztCuiE->R>kL?>R#=H{IdA=}`DrF5-a>XxlPnrpvm%kKlyRJ3?1UYV{iQ2;@>zq<{8 z<*x#BLD|?Cf8B+wzw%xG)*+MQ{}(smU$a_&`jWqQ_@7IZ{s7L15bS-GRh+U3w(5^q zRx%}HW%`AU!*`t-b&XgGASJs!gw1_}!ka=9{MWF?!<~tEg3X}_dR+S}7 z^|gS`XEsGz)sOPI_2Z@;d9`qprG&l<{ShbM_r5D9UA*DNqzrOUE)SfIYW+~kxTMq% z07PD@@kLWAzGV^Ga^~Xs$^R&6| zF10sKiuj~!(L}-9y!E#fPh(PSfxt*Ei*-;Y@EyC)mU_i}s)OhiE|H_&*pzn>{hjsw zw5b2u1eiG(epw$A^RFRue>Fdrp9ALpu|0s9;jdc&3lrPFu?LK&n>!^qV-0SQ$~HM| zEI8$g#zuF;z&YW#;F_SIh{hU&2x3tyf(o)>%2SxdIpf6jIY0zEch_(+5$78qYoabm z&#;)Mk(tMnnWq6H)0o*GSSK?bmywyDA2QnAS8iXQP8?6YsbMz7Nij(zQA7(y3nehf zlj&##%j)&k{YTC>zr=yx=;*}LAw4He3x8N&%YYVH8m6BM@dyd(w3-dImDxxR4#Dcn z<}_`2m9jEptoRn%Vs34+w}Sb@dO;HzIFhh4Kd~0-_8Jv6w~9L5ZZuy#4dbEp>x(Yu zv3NwcZCb;?UI#B5nwIN@aJG-E#onQmN49Hg*+XEbE{T2Vd{qV}x<=wv$C3F;HZ-B; zHeAQ;gxOhnxTp5TXKJQyaYGZ!c2?mj{SnS(o24|Q{^}lNuZH~YCb)BH&5YtHM0if} zH?+I30>HO8EPo_uE#9M)&60-P>m4~ww{DvzfL|JV6a4;Mg0_8ojt7~rf_PtbrPK|N zhnvJfE5EA2|X^&wI|;f z@hN&LacS-)9nQi`ighvE zGUW-eX^!(t7g$Vjv6{Q{^x?u5>!L9>NPbbo-(EN8J_I3mowdp_lfaeo`rMRf3yTX= z_+ZE*iq2zQt3V`z#|`yAAApC)Pbrh(@s=aZ-iYW@6OHO^p;;u6>-kXLNL)sN<9<+!?d;zgzaaj0!_#K>Zi4?|MkwaTD@TJz1XXg}NXB;@4$BIy^u? z%sh)k*y81uU^yjM0j}~PjZ82fWBv~RHSkN6yi*f8x(Y=lVoC5Pf$NAUJUv-#{*RNN zWtaqTOHQF>*_ugm+|X*cy*^W&;b<@z)VE&p(Zt31T3x+DAmXt~?zDj-;_-?eKG%Sh z*5Zy6q+G^HVO?qY-9%~TxT^M~p}q$9T)UcW1RB#$BusUNl}8?D_jx4LuUqlMjAypj zBr&=&Fl<63YM3{u2ptxm)~ZwGw2X8D(sNpvk(b9$g&a-2*KItY)3_fC>Wpz&TqiiO z6PCYuWj>~e-%=rP-fuXwKveS1*R{A<3;bRL zcK`_f9-Rs}yrUy3t*P2iU4El#V&@BK>FDJiamZ887bN+E(&{8hj7)~Cl8rHm+dL{P zEDa*K(R*sO=Q}jCLT|7$cfHRSXn>52>{9Q?=UG7Vd=v^oDUtfvsSvAm+gv@C!8_}a zq!EbyHtWG%6#RWpYg%a%Hl~{f+%Lqyho*gOA=XPjZFXd#_m{C9?recl^KmX@awue} zo3h6OGZAXMTT?QD0$(_fjlM!Ppy5aeop7djV1UKPJ|d@B;3&gRA{N>yzke;p-=SK} zrP3cIkTJRTMy(8d8YKwlv-1<%9AZF+t8|*}B~1Jx1Ut;cGK!NIE z=SqFmeB47B0vC<{NuHwh$6zL7(mQrSIr({~EiAD;^&vgQ+42c@C^Aw7qM#j!z>+)m z@SA*;yzS0w1d&pNWn?{PzxWZkS&8Kvflx)T#uGo3q+~WVY7&vcE>+;Q#^ckPdjJ)o zNzyH<$%C4&Clq2au*x@Q4WxK)Ya$^sPMTp#a!H3VXVBwqLMj1R>D}P z=FC<+*jctSd+#9@r8!&{ff$LWJ6LAh$Y3GFSx(2!WU;+c(HgEqIc#^p^+DEWa;y}e zgVk7xy4dFX>?|C7vCU!dg97_(3_x3zx~;OvS$u6B@jBsE+F6`^HnXv^ysfpe$W?r8 z4bge>Rbp)g@tWRRTlLmidwi3Bbp6to6Tf0KR8?lJI5=hmp(c8n1OMSc8YnXbB` za~iX%DD@;ocN0HR3Zu00L}bm>CG4K))N}^82t03TE0b7g=5HKd6XBzU<4nM2&Q zX^sOS?r=fHzRm|Ror4D|nCdt`Qo&Lu$Avc}h+#tD$ncn0@$OibUO?W2u%5Z9*2rtQ zC=*FgvZd;N5+x|H%gK=hj?#A@TOcXN(2XE~X|cEyRxow!rg@f^S@^P`foujZROnzo zRo}bU;a$QJj2Z&P&L{%#8`eG`TR?trVu3LyGBw{&fHHk)%ukU`cGNFkZ^$nm4J+Z1 zLZ2~*6oV-z5+~n80GCf_&RHJGM37T{q(DgW)nnr$Rz3%_V(`UAZ_bhW57VOW5b7Be zL3y4&?H(8&t2d6Z9a}p$AgUdA)*+j1M0c{VB&V9lbxXvWE zjMpV#ZL-gL)8&Ur+v+pfz{L~~RNxc3;@Ll^PP?927kW3dYFg>7e|qc5OpCUQ`duId zS;=`lC`9n9~Qu}>uN8Ysxb`RlxYU_vhbUl!- zCk*YN+4>KJ=>$!~iIhOOu9?$w&$fF`+h@?cmo<#bbwT~Ew%TbJeB)iSFvc#SwJ8*C z&1HRMnUIsYy<~%U*mz>?h}8;s`KS6T@=1b4R=9mklgp6mf}oUjyR`s%&WQLF^RXn( zv&M)RHH+fj9Zb%$A2&sU0gfZkh z=)rB@*4TcsV!=FUexhLh$HPfq5bDemir;|nA8h+;)EXBya@WeaIMDNpuk}4^y2i-n+Ao zbpV^3eE;sTC8f5wcK@_L^D^fGzv9`}*0%CPb%mE>k$-VxR2Q-7QrAq|Pgd^YzOS#Z z%WthNKR^G8Gd3#|`0smFaBs@!<>lo}S5?$vx*d!M_-S8T8=IFGtZDX^RbQVFKHHAmAVvBvV69~n;mZZ3gbHS`s3jEaU%?oFylmoJkIwCBb9GkGf1v&c}6X#E}*7qn!6!L`mo@V zsy`5#ZV;!LXec|5m0OuWdK6N?t+V%0&}6XYnSX{P`&g|i1Ai-v{!v~XGto&*UARyo zN1ieq#w=P5ugEOD1KEjcG!Jx?DutwY0Y$c$0B5$Og)8e|Y0SVNFlFh8T$K$NE7TfNHMW05to(yPc?HGijr{hB;$)>Rf-JcOs7!CraMbN zy15oBmXgx6(j2D+G=00H3e)#6j^F+&L9R4n1UDT;S_rB!q41(89ZI%{-(w5qp41O* z9CR~Km>aAAChFRVsRgb>Lq}b5o1+*u-zBZKn}R2YnR;||bjsA--Pj%0BE^ihw=YwR z433$Co{o;T_YEzocEFH?PAoPSx_n!8bu~;rBX!+C4b7<1)I|mlKXikmqvPe}ncXNt z-1ic1FeHV;%|zO2B4r(jy*96B74gY@gv2c zb0+)q6l9>Gp>=~$q7V=ekb2cnk7Igo-!E<;%dvk#MV(&f)0q09^Yuo++L!d}3jFPR zyq?EkPtUi{B}%BhMmWhyC`bGI`$6?pP2>oDG*{PwLJYA&&E#*84DpbH7@`7&a*2zy z*VfeV4}b$hdRcG~wr`J*4i4gpkIAgr3$#VRVXz7WOvxh)C?G#&%2T^Q7l3%_wlJf> zxRD@A#CM@<+(^blG~`W^-|J(s@QwVqB*DA9^YW1p?V3EqB)RtJAS{_fz2440b#7bp zF7r!u{GxF9JY1ain1J9jln5av z_wvdLXML0~z}njS&B3O^^p=^hZv(l-4~6u#lRE_qvxcU|ZSR))Ig>hjGwPVMih72I zGc)S!i;hBe};|uaSH{+|z&A}J6j{B^0KIl@WvC{6vZO>4Nwk=Vv z<%_mLE4BjMZtPpEiJlP`rMHE{Ege<4tEauJSMN_F`ikG)YJSJe}wB;syV8+0^*q}Kxy#a(2V`}qQ``tKuRvX7a zTYf6I60(l1CoCzP7(eu1MrlaU$q+;~UyGIEvF;zAYjxL{2lvcXd3XQhvwB%~gWEV< zn_U9`Qrjc#-9}_CTBUp8J|#y62io=RmIN>*Ia?(>D>oBJgcO(wnq^#s*xkrCOk+rk z-X~ZX@jah-Rtglaa#NRq2Q(PfxGo7|V?kIgpwH;@k(6D@p^=7~nobwd4^^02gkFgU zFbrBR{b`91Xy)t`?pf5GZ=q4vcfA)=;~?gNVOuEpXRVwXTu<%PBfDE#l2%&%(+t(p zSeE7}&Vps{C|?-*wLU~AzbeFOAGLut94SFJfMvJB3XN`14l&VIydPd_iV7paDxEeL zSIyldUPXGXAnW`lS3^K>e3oJw?J~c7PUG4g@l_D!&p_1K}~(PM7TGZE#X0;Hp) z0fXR%T=QJx01ajZHT>Gr0jmIY`IWKnSQ4TgOIE?t6lyYL%wqw1EU7Y|*-(R$AwP|n z_16#Ru^5a($a+YOi}jxQ!i#snY zXA#iqA=98?-4QBliQm8w zQCeA67NAV3p$^&iQ9=EFPXY6)yf!Z{5ANaP`Po(<^jv5e(UhX_Iqx-igGNw^n$PQt zH>OitQAK-u`w>>JF;!AoyG&r#no{W(s?B+ek4tMzpG_McPBOp7zctcQPWq}S__Svu zIWqa$8dR}CMN8SD9m!7L;n;S^rVKw&*c9PAs766W_3%Rur`)$ywO;}LEwYd9E3_s# zVD@)d_>=U0VIecqf3T2=<=1Gdzj5K8Jsf^=*FP}9is{d&*nh>ySeX6{nF-rk**YlM z=^Gjo(~B6pm>U|4JLtRrp`A+FI2k+G*;?s48527>I2-@*q>#Cjqr9<$u&uS7t&Opb z6EO$eUwce=r@Ok%I1>&fL_4LNbgVd4iz`$T6NkcN@Iu2N2Rwja3K~Vg@S-kh#%}4k zt->yVM^hf6&;@coX3!9at0@hxV zyx71PUu3As1$^Cvy@a}(DqJ(TY>a}>lWrSj#~KSIrNVc(8VulY&EYeg;Mc-MR>r%V zSc~7Su`@Qm>#dEy-x64hcb&tOg%6bb#(7nLvTSDSrsUHS<0SrdUse=Q`jH+n1m5$C zTfhAlPkWKQY0*yPLpHfdok|A)m;La&c$q$alw^ zsig4ZYnhw(?FYXaR&dsmgrYcB{d!GIkVAU>Vc}A+VE5Z70cQT5jl^9Fzyi(t+J1

!ev_o=0pVSBPEU}un!_Chq?}@ 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 IxkB}S0M<&hSO5S3 diff --git a/manual/rockbox_interface/images/zenvision-front.png b/manual/rockbox_interface/images/zenvision-front.png deleted file mode 100644 index 5b35fd01f12b0c2505992335e13f623dfd4d8f10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90707 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Menu - - Back - - Play - - Down - - Select - - Left - - Right - - Up - - Power - Vol -/+ - Hold - Next - - Prev - - - - - diff --git a/manual/rockbox_interface/images/zenvisionm-front.pdf b/manual/rockbox_interface/images/zenvisionm-front.pdf deleted file mode 100644 index db4d73032ede8930830f953b8c1cca021cbd82ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85097 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 R6oG(0brl`#2PMmp{{v~jyAS{X diff --git a/manual/rockbox_interface/images/zenvisionm-front.svg b/manual/rockbox_interface/images/zenvisionm-front.svg deleted file mode 100644 index 9218ad2417..0000000000 --- a/manual/rockbox_interface/images/zenvisionm-front.svg +++ /dev/null @@ -1,1368 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Menu - Left - Right - Down - Up - Power - Play - Shortcut - Back - - - - - - - - - Hold - - - - - - - - - - - - - - - - - - diff --git a/tools/builds.pm b/tools/builds.pm index 157720a0d8..1a283dd9b1 100644 --- a/tools/builds.pm +++ b/tools/builds.pm @@ -318,21 +318,6 @@ $releasenotes="/wiki/ReleaseNotes400"; name => 'Packard Bell Vibe 500', status => 3, }, - 'zenvision' => { - name => 'Creative Zen Vision', - status => 1, - sim => 1, - }, - 'zenvisionm30gb' => { - name => 'Creative Zen Vision:M 30GB', - status => 1, - sim => 1, - }, - 'zenvisionm60gb' => { - name => 'Creative Zen Vision:M 60GB', - status => 1, - sim => 1, - }, 'mpiohd200' => { name => 'MPIO HD200', status => 2, diff --git a/tools/configure b/tools/configure index 09178d0426..4afaa15a7d 100755 --- a/tools/configure +++ b/tools/configure @@ -1691,47 +1691,47 @@ cat < Date: Tue, 27 Jan 2026 14:50:44 -0500 Subject: [PATCH 46/75] bootloaders: Don't build usb_core without HAVE_BOOTLOADER_USB_MODE This way we don't need to stub out a bunch of functionality when we don't have any actual USB class drivers enabled. Change-Id: Ia0ecf5be4bb41bebfcd347090959f3204a2aba59 --- firmware/SOURCES | 5 +++-- firmware/storage.c | 2 +- firmware/usb.c | 28 +--------------------------- 3 files changed, 5 insertions(+), 30 deletions(-) diff --git a/firmware/SOURCES b/firmware/SOURCES index c992b2010c..7d1b582c64 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -947,8 +947,7 @@ target/arm/s5l8702/lcd-asm-s5l8702.S #endif /* USB Stack */ -// TODO: This needs to be HAVE_USBSTACK && (!BOOTLOADER || HAVE_USB_BOOTLOADER_MODE) -#ifdef HAVE_USBSTACK +#if defined(HAVE_USBSTACK) && (!defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)) usbstack/usb_core.c #ifdef USB_ENABLE_STORAGE usbstack/usb_storage.c @@ -985,6 +984,8 @@ target/arm/rk27xx/usb-drv-rk27xx.c drivers/isp1362.c #elif CONFIG_USBOTG == USBOTG_M5636 drivers/m5636.c +#elif CONFIG_USBOTG == USBOTG_ARC +target/arm/usb-drv-arc.c #endif #endif /* !defined(HAVE_USBSTACK) */ diff --git a/firmware/storage.c b/firmware/storage.c index 5134e0f0e3..f6a168dabb 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -229,7 +229,7 @@ static void NORETURN_ATTR storage_thread(void) break; #endif /* HAVE_HOTSWAP */ -#ifndef USB_NONE +#if !defined(USB_NONE) && (!defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)) case SYS_USB_CONNECTED: case SYS_USB_DISCONNECTED: bdcast = 0; diff --git a/firmware/usb.c b/firmware/usb.c index e1d0909613..2645d3b290 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -705,33 +705,7 @@ void usb_acknowledge(long id, intptr_t seqnum) { queue_post(&usb_queue, id, seqnum); } -#else /* !USB_FULL_INIT */ -/* TODO: All of this can go away once usb_core.c is no longer built - with BOOTLOADER && !HAVE_USB_BOOTLOADER_MODE */ -#ifdef HAVE_USBSTACK -void usb_signal_transfer_completion( - struct usb_transfer_completion_event_data* event_data) -{ - (void)event_data; -} -#endif -void usb_clear_pending_transfer_completion_events(void) -{ -} -void usb_release_exclusive_storage(void) -{ -} -void usb_signal_notify(long id, intptr_t data) -{ - (void)id; - (void)data; -} -void usb_acknowledge(long id, intptr_t seqnum) -{ - (void)id; - (void)seqnum; -} -#endif /* !USB_FULL_INIT */ +#endif /* USB_FULL_INIT */ void usb_init(void) { From b722e3c83a694c2accf053332265d11491825a19 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sat, 7 Feb 2026 09:29:16 -0500 Subject: [PATCH 47/75] mrobe500: define HAVE_BOOTLOADER_USB_MODE Fixes red, and will restore USB functionality that was effectively broken from earlier commits. Change-Id: I98150a81e3f73131bfedccdaf3de740a091debf9 --- firmware/export/config/mrobe500.h | 1 + tools/configure | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/export/config/mrobe500.h b/firmware/export/config/mrobe500.h index dc39754742..04570411b8 100644 --- a/firmware/export/config/mrobe500.h +++ b/firmware/export/config/mrobe500.h @@ -210,6 +210,7 @@ #define CONFIG_USBOTG USBOTG_M66591 #define HAVE_USBSTACK +#define HAVE_BOOTLOADER_USB_MODE //#define HAVE_USB_POWER //#define USBPOWER_BUTTON BUTTON_POWER //#define USBPOWER_BTN_IGNORE BUTTON_TOUCH diff --git a/tools/configure b/tools/configure index 4afaa15a7d..8d7739f0cc 100755 --- a/tools/configure +++ b/tools/configure @@ -1687,7 +1687,7 @@ cat < Date: Sat, 7 Feb 2026 10:48:22 -0500 Subject: [PATCH 48/75] mrobe500: Allow bootloader build without HAVE_BOOTLOADER_USB_MODE I'm leaving it enabled because that's clearly the intent of the bootloader, but at least there's now an easy path to disabling it if so desired. Change-Id: I4f4ecc9a453d376f92e411e0544b587fe4b4c864 --- bootloader/mrobe500.c | 4 ++++ firmware/SOURCES | 2 ++ 2 files changed, 6 insertions(+) diff --git a/bootloader/mrobe500.c b/bootloader/mrobe500.c index 245bd51c9b..57356ab71d 100644 --- a/bootloader/mrobe500.c +++ b/bootloader/mrobe500.c @@ -61,7 +61,9 @@ void main(void) backlight_init(); font_init(); button_init(); +#ifdef HAVE_BOOTLOADER_USB_MODE usb_init(); +#endif power_init(); @@ -79,6 +81,7 @@ void main(void) printf("Rockbox boot loader"); printf("Version %s", rbversion); +#ifdef HAVE_BOOTLOADER_USB_MODE /* Enter USB mode without USB thread */ if(usb_detect() == USB_INSERTED) { @@ -104,6 +107,7 @@ void main(void) reset_screen(); lcd_update(); } +#endif sleep(50); diff --git a/firmware/SOURCES b/firmware/SOURCES index 7d1b582c64..fbd92742ba 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1302,7 +1302,9 @@ target/arm/tms320dm320/mrobe-500/lcd-remote-mr500.c target/arm/tms320dm320/mrobe-500/pcm-mr500.c target/arm/tms320dm320/mrobe-500/powermgmt-mr500.c target/arm/tms320dm320/mrobe-500/power-mr500.c +#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE) target/arm/tms320dm320/mrobe-500/usb-mr500.c +#endif #endif /* MROBE_500 */ #if defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(CREATIVE_ZENMOZAIC) \ From ef7739160b0d1d1c125d4d753827ce7b4216b171 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 8 Feb 2026 13:58:36 -0500 Subject: [PATCH 49/75] [BugFix] open_plugins allow more than one entry with a plugin / parameter you should be able to have multiple parameters to a single plugin you can do this from outsid the plugin, but not from within the plugin this makes it possible to have several entries with the same plugin and a different parameter for each entry it now also updates the name of the entry to the name of the parameter instead of the name of the plugin (unless user edited it) Change-Id: Ifb52b21e3b8ed3257364635b5d92e7c21a35a199 --- apps/plugins/open_plugins.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/plugins/open_plugins.c b/apps/plugins/open_plugins.c index c7007b1bd0..edf4273a3c 100644 --- a/apps/plugins/open_plugins.c +++ b/apps/plugins/open_plugins.c @@ -176,12 +176,18 @@ static void op_entry_set_checksum(void) (op_entry.lang_id <= OPEN_PLUGIN_LANG_INVALID ? 0 : LANG_LAST_INDEX_IN_ARRAY); } -static void op_entry_set_name(void) +static bool op_entry_set_name(void) { char tmp_buf[OPEN_PLUGIN_NAMESZ+1]; rb->strlcpy(tmp_buf, op_entry.name, OPEN_PLUGIN_NAMESZ); + uint32_t crc = rb->crc_32(tmp_buf, sizeof(tmp_buf), 0xffffffff); + if (rb->kbd_input(tmp_buf, OPEN_PLUGIN_NAMESZ, NULL) >= 0) + { rb->strlcpy(op_entry.name, tmp_buf, OPEN_PLUGIN_NAMESZ); + return crc != rb->crc_32(tmp_buf, sizeof(tmp_buf), 0xffffffff); + } + return false; } static int op_entry_set_path(void) @@ -392,10 +398,10 @@ static uint32_t op_entry_add_path(const char *key, const char *plugin, const cha rb->strlcpy(op_entry.param, parameter, OPEN_PLUGIN_BUFSZ); /* hash on the parameter path if it is a file */ - if (op_entry.lang_id <0 && key == op_entry.path && + if (op_entry.lang_id <0 && (key == op_entry.path || key == NULL) && rb->file_exists(op_entry.param)) { - open_plugin_get_hash(op_entry.path, &newhash); + open_plugin_get_hash(op_entry.param, &newhash); op_entry.hash = newhash; } } @@ -692,6 +698,7 @@ static void edit_menu(int selection) { int selected_item; bool exit = false; + bool name_set = false; int action = 0; if (!op_entry_read(fd_dat, selection, op_entry_sz)) @@ -713,11 +720,22 @@ static void edit_menu(int selection) { case ACTION_STD_OK: if (selected_item == 0) - op_entry_set_name(); + { + name_set = op_entry_set_name(); + } else if (selected_item == 2) op_entry_set_path(); else if (selected_item == 4) + { op_entry_set_param(); + /* if user already set the name they probably don't want us to change it */ + if (!name_set && op_entry.lang_id < 0 && rb->file_exists(op_entry.param)) + { + char *slash=strrchr(op_entry.param, '/'); + if(slash) + rb->strlcpy(op_entry.name, slash+1, OPEN_PLUGIN_NAMESZ); + } + } else exit = true; From ed84047884afd4efcd6268879030307dcbb6bebd Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 8 Feb 2026 14:39:17 -0500 Subject: [PATCH 50/75] [Fix Red] open_plugins rb-> is required Change-Id: I1f1a7e487d46a0427be7cebd319c65b848b4a9fb --- apps/plugins/open_plugins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/plugins/open_plugins.c b/apps/plugins/open_plugins.c index edf4273a3c..e90d2d95de 100644 --- a/apps/plugins/open_plugins.c +++ b/apps/plugins/open_plugins.c @@ -731,7 +731,7 @@ static void edit_menu(int selection) /* if user already set the name they probably don't want us to change it */ if (!name_set && op_entry.lang_id < 0 && rb->file_exists(op_entry.param)) { - char *slash=strrchr(op_entry.param, '/'); + char *slash = rb->strrchr(op_entry.param, '/'); if(slash) rb->strlcpy(op_entry.name, slash+1, OPEN_PLUGIN_NAMESZ); } From 7c00a059ffe52b021915f906c0dea39a9b9d08cf Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 8 Feb 2026 17:29:21 -0500 Subject: [PATCH 51/75] =?UTF-8?q?FS#13781=20-=20Updated=20Hungarian=20Tran?= =?UTF-8?q?slation=20(Gy=C3=BAr=C3=B3czki=20Norbert)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I59c57b025c4afdfd5b66ffc63f5316da1d86c657 --- apps/lang/magyar.lang | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/lang/magyar.lang b/apps/lang/magyar.lang index e054ff7e24..4eb911dabc 100644 --- a/apps/lang/magyar.lang +++ b/apps/lang/magyar.lang @@ -14784,7 +14784,7 @@ user: core *: "Press LEFT to cancel." - android,hifietma*,zenvision: "Press BACK to cancel." + android,hifietma*: "Press BACK to cancel." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Press POWER to cancel." ihifi760,ihifi960: "Double tap RETURN to cancel." ihifi770,ihifi770c,ihifi800: "Press HOME to cancel." @@ -14799,7 +14799,7 @@ *: "Nyomja meg a LEFT gombot a megszakításhoz." - android,hifietma*,zenvision: "Nyomja meg a BACK gombot a megszakításhoz." + android,hifietma*: "Nyomja meg a BACK gombot a megszakításhoz." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Nyomja meg a POWER gombot a megszakításhoz." ihifi760,ihifi960: "Duplán koppintson a RETURN-re megszakításhoz." ihifi770,ihifi770c,ihifi800: "Nyomja meg a HOME gombot a megszakításhoz." @@ -14814,7 +14814,7 @@ *: "Nyomja meg a LEFT gombot a megszakításhoz." - android,hifietma*,zenvision: "Nyomja meg a BACK gombot a megszakításhoz." + android,hifietma*: "Nyomja meg a BACK gombot a megszakításhoz." cowond2,creativezenxfi2,ibassodx50,ibassodx90,mrobe500,ondavx747: "Nyomja meg a POWER gombot a megszakításhoz." ihifi760,ihifi960: "Duplán koppintson a RETURN-re megszakításhoz." ihifi770,ihifi770c,ihifi800: "Nyomja meg a HOME gombot a megszakításhoz." @@ -16948,3 +16948,17 @@ general_purpose_led: "LED jelzőfények használata" + + id: LANG_ANNOUNCE_STATUS + desc: announnnce_status plugin + user: core + + *: "Announce Status" + + + *: "Állapot bejelentése" + + + *: "Állapot bejelentése" + + From 3629a765d241359f7c2a0aa54d5e5950c1d723ce Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 8 Feb 2026 20:02:38 -0500 Subject: [PATCH 52/75] FS13774 - Translate units in file operation splash messages 'MiB' and 'KiB' were hardcoded; use LANG_MEBIBYTE/KIBIBYTE instead. Change-Id: I456521a222e213379f929e4d1113e084f87a3ac4 --- apps/fileop.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/fileop.c b/apps/fileop.c index e24761be58..54c9b14f52 100644 --- a/apps/fileop.c +++ b/apps/fileop.c @@ -97,19 +97,23 @@ static bool poll_cancel_action(int operation, struct file_op_params *param) { int total_shft = (int) (param->total_size >> 15); int current_shft = (int) (param->processed_size >> 15); + const char *unit_str = str(LANG_MEBIBYTE); splash_progress(current_shft, total_shft, - "%s %s (%d MiB)\n%d MiB", + "%s %s (%d %s)\n%d %s", op_str, param->toplevel_name, - total_shft >> 5, current_shft >> 5); + total_shft >> 5, unit_str, + current_shft >> 5, unit_str); } else if (param->total_size >= 1024) { int total_kib = (int) (param->total_size >> 10); int current_kib = (int) (param->processed_size >> 10); + const char *unit_str = str(LANG_KIBIBYTE); splash_progress(current_kib, total_kib, - "%s %s (%d KiB)\n%d KiB", + "%s %s (%d %s)\n%d %s", op_str, param->toplevel_name, - total_kib, current_kib); + total_kib, unit_str, + current_kib, unit_str); } } return ACTION_STD_CANCEL == get_action(CONTEXT_STD, TIMEOUT_NOBLOCK); From f5be6cd10c4d35a6c383e8d36a923e02d5a1130c Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Sun, 8 Feb 2026 20:13:57 -0500 Subject: [PATCH 53/75] rbutil: Add support for Vietnamese to the SAPI TTS glue code Change-Id: I2cd7f8540717a95b3d05e836c5502313a9db6b50 --- tools/sapi_voice.vbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/sapi_voice.vbs b/tools/sapi_voice.vbs index c6c2c69372..515252f8b3 100644 --- a/tools/sapi_voice.vbs +++ b/tools/sapi_voice.vbs @@ -392,6 +392,8 @@ Function LangIDs(ByRef sLanguage) LangIDs = Array(&h41f) Case "ukrainian" LangIDs = Array(&h422) + Case "vietnamese" + LangIDs = Array(&h42a) Case "wallisertitsch" LangIDs = Array(&h807) ' Swiss German Case "walon" From c390467d1903c926116a918a09875477d25f19d8 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Fri, 6 Feb 2026 11:53:20 +0000 Subject: [PATCH 54/75] stm32h7: sdmmc: don't panic on spurious IRQs When doing I/O, the interrupt can rarely fire with no active command and no status bits set. This is probably because the interrupt is set pending by the NVIC while the handler is already running, so should be harmless. Change-Id: I0c2570abe6e3c85ddbfa2ebe0afcf8677b77408f --- firmware/target/arm/stm32/sdmmc-stm32h7.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/firmware/target/arm/stm32/sdmmc-stm32h7.c b/firmware/target/arm/stm32/sdmmc-stm32h7.c index 0fdad1156a..b61c778376 100644 --- a/firmware/target/arm/stm32/sdmmc-stm32h7.c +++ b/firmware/target/arm/stm32/sdmmc-stm32h7.c @@ -407,7 +407,12 @@ void stm32h7_sdmmc_irq_handler(struct stm32h7_sdmmc_controller *ctl) uint32_t icr = 0; if (!ctl->cmd_wait) - panicf("sdmmc_irq: not waiting: %08lx", star); + { + if (star != 0) + panicf("sdmmc_irq: not waiting: %08lx", star); + + return; + } /* * Ignore interrupts which we haven't enabled; this is needed From 06c9d87f534ed67f13bb6b5ad830ba750f2296f4 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Mon, 9 Feb 2026 14:01:46 +0000 Subject: [PATCH 55/75] stm32h7: sdmmc: implement missing R1b response handling The driver didn't handle the busy signal at the end of some command responses (R1b response type), notably the CMD12 (STOP_TRANSMISSION) sent after a multiblock write would time out because DTIMER==0 and leave the DPSM in an incorrect state for the next command, causing a hang. Change-Id: I406337a7612f759418a4872979aa2de5aa2244c7 --- firmware/target/arm/stm32/sdmmc-stm32h7.c | 51 ++++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/firmware/target/arm/stm32/sdmmc-stm32h7.c b/firmware/target/arm/stm32/sdmmc-stm32h7.c index b61c778376..56e7d70e4c 100644 --- a/firmware/target/arm/stm32/sdmmc-stm32h7.c +++ b/firmware/target/arm/stm32/sdmmc-stm32h7.c @@ -28,6 +28,7 @@ /* cmd_wait flags */ #define WAIT_CMD 0x01 #define WAIT_DATA 0x02 +#define WAIT_BUSY 0x04 /* Maximum number of bytes for 1 transfer */ #define MAX_DATA_LEN \ @@ -49,6 +50,14 @@ #define DATA_END_BITS \ (DATA_SUCCESS_BITS | DATA_ERROR_BITS) +/* IRQs for busy wait phase */ +#define BUSY_SUCCESS_BITS \ + __reg_orm(SDMMC_STAR, BUSYD0END) +#define BUSY_ERROR_BITS \ + __reg_orm(SDMMC_STAR, DTIMEOUT) +#define BUSY_END_BITS \ + (BUSY_SUCCESS_BITS | DATA_ERROR_BITS) + static size_t get_sdmmc_bus_freq(uint32_t clock) { switch (clock) @@ -262,6 +271,13 @@ int stm32h7_sdmmc_submit_command(void *controller, break; } + /* For R1b responses we need to wait for the busy signal. */ + if (cmd->flags & SDMMC_RESP_BUSY) + { + maskr |= BUSY_END_BITS; + cmd_wait |= WAIT_BUSY; + } + /* * Handle commands with data transfers */ @@ -313,9 +329,14 @@ int stm32h7_sdmmc_submit_command(void *controller, { /* Disable data transfer */ reg_assignlf(ctl->regs, SDMMC_IDMACTRLR, IDMAEN(0)); - reg_varl(ctl->regs, SDMMC_DTIMER) = 0; reg_varl(ctl->regs, SDMMC_DLENR) = 0; reg_varl(ctl->regs, SDMMC_DCTRL) = 0; + + /* DTIMER is the wait time for the busy signal */ + if (cmd->flags & SDMMC_RESP_BUSY) + reg_varl(ctl->regs, SDMMC_DTIMER) = 1 * ctl->bus_freq; + else + reg_varl(ctl->regs, SDMMC_DTIMER) = 0; } /* @@ -419,7 +440,7 @@ void stm32h7_sdmmc_irq_handler(struct stm32h7_sdmmc_controller *ctl) * to ensure the correct interrupt is used to detect command * completion (CMDSENT or CMDREND). */ - star &= maskr; + star &= maskr | __reg_orm(SDMMC_STAR, BUSYD0); if (ctl->cmd_wait & WAIT_CMD) { @@ -478,6 +499,32 @@ void stm32h7_sdmmc_irq_handler(struct stm32h7_sdmmc_controller *ctl) } } + if (ctl->cmd_wait & WAIT_BUSY) + { + if (reg_vreadf(star, SDMMC_STAR, CMDREND) && + !reg_vreadf(star, SDMMC_STAR, BUSYD0)) + { + /* + * Skip waiting if the busy signal is not asserted by + * the card when the command ends; in this case we'll + * never receive a BUSYD0END interrupt because it is + * only raised on a transition from busy -> not busy. + */ + ctl->cmd_wait &= ~WAIT_BUSY; + } + else if ((star & BUSY_END_BITS) || ctl->cmd_error) + { + if (!ctl->cmd_error) + { + if (reg_vreadf(star, SDMMC_STAR, DTIMEOUT)) + ctl->cmd_error = SDMMC_STATUS_TIMEOUT; + } + + ctl->cmd_wait &= ~WAIT_BUSY; + icr |= BUSY_END_BITS; + } + } + /* * Each interrupt should complete at least one phase * but in error cases we can get spurious interrupts. From ea5b0fb33a8cf84c80844560df9b64e5ff272480 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 8 Feb 2026 18:41:35 -0500 Subject: [PATCH 56/75] Clip Plus, Zip, Xduoo X3 Reconfigure keyboard to better use screen Someone opened a bug, its not a bug but it is annoying these are the smallest screens so the 18 character width ends up wasting lines that could be displaying characters this layout repeats some but should be more ergonomic Change-Id: I2ed4c0887477aac49821c4edb6f3bf174e38d36e --- apps/recorder/keyboard.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c index 9ed8f3f12f..22fbbb2395 100644 --- a/apps/recorder/keyboard.c +++ b/apps/recorder/keyboard.c @@ -472,6 +472,37 @@ int kbd_input(char* text, int buflen, ucschar_t *kbd) } else #endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */ +#if (LCD_WIDTH == 128 && LCD_HEIGHT == 64) || (LCD_WIDTH == 96 && LCD_HEIGHT == 96) +/* CLIP PLUS & XDUOO X3 || CLIP ZIP*/ + { + p = "ABCDEFG !?\" $%+'\n" + "HIJKLMN 789 &_-`\n" + "OPQRSTU 456 §|/\n" + "VWXYZ.,0123 ~=*#\n" + + "abcdefg ¢£¤¥¦§©®\n" + "hijklmn «»ºª¹²³\n" + "opqrstu ¯±×÷¡¿µ·\n" + "vwxyz.,¨:;¼½¾¬¶°\n" + + "< ({[-*?\"!'@#$%\n" + "> )}]+/\\=& 789_`\n" + "¢£¤¥¦§©®¬§ 456x|\n" + "«»°ºª¹²³¶.,0123~\n" + + "ÀÁÂÃÄÅÆ ÌÍÎÏÈÉÊË\n" + "àáâãäåæ ìíîïèéêë\n" + "ÓÒÔÕÖØ ÇÐÞÝßÙÚÛÜ\n" + "òóôõöø çðþýÿùúûü"; + +#if ((LCD_WIDTH == 128 && LCD_HEIGHT == 64)) + pm->default_lines = 4; +#else + pm->default_lines = 8; +#endif + pm->max_line_len = 16; + } +#else { p = "ABCDEFG !?\" @#$%+'\n" "HIJKLMN 789 &_()-`\n" @@ -491,7 +522,7 @@ int kbd_input(char* text, int buflen, ucschar_t *kbd) pm->default_lines = 4; pm->max_line_len = 18; } - +#endif pbuf = pm->kbd_buf; while (*p) { From 7327d9fb6cd4d8083777819ae7b5fb22763f7d53 Mon Sep 17 00:00:00 2001 From: Ingmar Steen Date: Sun, 8 Feb 2026 00:05:31 +0100 Subject: [PATCH 57/75] Implement set block count (CMD23) for x1000 target. I have a 1TB SD card that gets filesystem corruption when writing large amounts of data when using Rockbox in USB storage mode. The card doesn't show this behaviour when using the original firmware or when using an external SD card writer. This is on an Aigo Eros Q device. Same brand 512GB card does not exhibit this behaviour. Whether this specific SD card explicitly requires CMD23 or if there's a problem with the controller's timing of auto-CMD12 in combination with this card is currently unknown, but implementing it does solve the problem. This change request implements CMD23 by first probing if SBC is supported by the SD card and then using it instead of AUTO_CMD12. Change-Id: Ib2dc8e179b0fab98ca59c348061cb7d5850884dd --- docs/CREDITS | 1 + .../target/mips/ingenic_x1000/msc-x1000.h | 1 + firmware/target/mips/ingenic_x1000/sd-x1000.c | 51 ++++++++++++++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/docs/CREDITS b/docs/CREDITS index b2e8465938..6088aac312 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -754,6 +754,7 @@ Melissa Autumn Sho Tanimoto Nyx Guan Arin Kim +Ingmar Steen The libmad team The wavpack team diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h index 3ebdd3adc3..119b754358 100644 --- a/firmware/target/mips/ingenic_x1000/msc-x1000.h +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h @@ -48,6 +48,7 @@ #define MSC_DF_READY (1 << 1) #define MSC_DF_HCS_CARD (1 << 2) #define MSC_DF_V2_CARD (1 << 3) +#define MSC_DF_HAS_SBC (1 << 4) /* Request status codes */ #define MSC_REQ_SUCCESS 0 diff --git a/firmware/target/mips/ingenic_x1000/sd-x1000.c b/firmware/target/mips/ingenic_x1000/sd-x1000.c index c1aec59aa3..f7313cebfa 100644 --- a/firmware/target/mips/ingenic_x1000/sd-x1000.c +++ b/firmware/target/mips/ingenic_x1000/sd-x1000.c @@ -19,6 +19,7 @@ * ****************************************************************************/ +#include "system.h" #include "storage.h" #include "sdmmc.h" #include "sd.h" @@ -32,6 +33,25 @@ static msc_drv* sd_to_msc[MSC_COUNT]; static long _sd_last_disk_activity = 0; +static void sd_probe_set_block_count(msc_drv* d) +{ + uint8_t scr[CACHEALIGN_SIZE] CACHEALIGN_ATTR; + msc_req req = {0}; + req.command = SD_SEND_SCR; + req.resptype = MSC_RESP_R1; + req.flags = MSC_RF_DATA; + req.data = scr; + req.nr_blocks = 1; + req.block_len = 8; + + if(msc_app_cmd_exec(d, &req) == MSC_REQ_SUCCESS) { + if(scr[3] & 0x02) + d->driver_flags |= MSC_DF_HAS_SBC; + else + d->driver_flags &= ~MSC_DF_HAS_SBC; + } +} + static int sd_init_card(msc_drv* d) { int s; @@ -45,6 +65,7 @@ static int sd_init_card(msc_drv* d) if(s = msc_cmd_set_clr_card_detect(d, 0)) return -170 - s; if(s = msc_cmd_set_bus_width(d, 4)) return -180 - s; if(s = msc_cmd_switch_freq(d)) return -190 - s; + sd_probe_set_block_count(d); d->driver_flags |= MSC_DF_READY; d->cardinfo.initialized = 1; return 0; @@ -92,19 +113,35 @@ static int sd_transfer(msc_drv* d, bool write, if(status = msc_cmd_set_block_len(d, SD_BLOCK_SIZE)) goto _exit; - /* TODO - look into using CMD23 to improve transfer performance. - * This specifies the number of blocks ahead of time, instead of - * relying on CMD12 to stop transmission. CMD12 is still needed - * in the event of errors though. - */ + bool use_sbc = false; + if(xfer_count > 1 && (d->driver_flags & MSC_DF_HAS_SBC)) { + msc_req sbc_req = {0}; + sbc_req.command = 23; /* CMD23: SET_BLOCK_COUNT (SBC) */ + sbc_req.argument = xfer_count; + sbc_req.resptype = MSC_RESP_R1; + status = msc_cmd_exec(d, &sbc_req); + if(status == MSC_REQ_SUCCESS) { + use_sbc = true; + } else if(status == MSC_REQ_CARD_ERR && + (sbc_req.response[0] & SD_R1_ILLEGAL_COMMAND)) { + d->driver_flags &= ~MSC_DF_HAS_SBC; + } else { + goto _exit; + } + } + msc_req req = {0}; req.data = buf; req.nr_blocks = xfer_count; req.block_len = SD_BLOCK_SIZE; req.resptype = MSC_RESP_R1; req.flags = MSC_RF_DATA; - if(xfer_count > 1) - req.flags |= MSC_RF_AUTO_CMD12; + if(xfer_count > 1) { + if(use_sbc) + req.flags |= MSC_RF_ERR_CMD12; + else + req.flags |= MSC_RF_AUTO_CMD12; + } if(write) { req.command = xfer_count == 1 ? SD_WRITE_BLOCK : SD_WRITE_MULTIPLE_BLOCK; From 46d644fcd792f581c89597227ad2e5d3fae4dac8 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Mon, 12 Jan 2026 01:22:07 -0500 Subject: [PATCH 58/75] stars.lua screen does not update int the sim SDL needs to do lcd_update from the main thread stars.lua uses an event that runs in a timer thread so in the sim the screen never updates Change-Id: I6002525363010c3133ebbfb490763f747c5d773a --- apps/plugins/lua/rocklib.c | 5 +++++ apps/plugins/lua_scripts/stars.lua | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 4d7c5e8f04..4404598ad3 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -1052,6 +1052,11 @@ LUALIB_API int luaopen_rock(lua_State *L) { luaL_register(L, LUA_ROCKLIBNAME, rocklib); luaL_register(L, LUA_ROCKLIBNAME, rocklib_aux); +#ifdef SIMULATOR /* rb.SIMULATOR = true allows checking for the SIM in lua */ + lua_pushboolean(L, 1); + luaS_newlloc(L, "SIMULATOR", TSTR_INBIN); + lua_setfield(L, -2, "SIMULATOR"); +#endif lua_getglobal(L, "require"); lua_pushstring(L, "rb_defines"); if (lua_pcall (L, 1, 0, 0)) diff --git a/apps/plugins/lua_scripts/stars.lua b/apps/plugins/lua_scripts/stars.lua index e05007afb6..2a46b00707 100644 --- a/apps/plugins/lua_scripts/stars.lua +++ b/apps/plugins/lua_scripts/stars.lua @@ -414,7 +414,11 @@ action_event(rb.actions.ACTION_NONE) -- we can call this now but not after regis local eva = rockev.register("action", action_event) local evc = rockev.register("timer", action_drift, rb.HZ/7) +if not rb.SIMULATOR then while not action_quit() do rb.sleep(rb.HZ) end +else -- the SIM requires lcd_update to be called from the main thread +while not action_quit() do _lcd:update(); rb.sleep(10) end +end if start_x and start_y then file = io.open(fname, "w") From 006859f16b2a2b7ec9528f0fd55e04ccb036291a Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Thu, 1 Jan 2026 18:22:26 +0000 Subject: [PATCH 59/75] stm32h7: spi: fix incorrect early transfer completion The semaphore was released after all bytes were read/written without waiting for the EOT event, which is why the delay at the end of the transfer needed to be longer than expected. Change-Id: I6b48fc01cda69564c0ec8f843afd1b0c3a9c5a3c --- firmware/target/arm/stm32/spi-stm32h7.c | 19 ++++++++++++++----- firmware/target/arm/stm32/spi-stm32h7.h | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/firmware/target/arm/stm32/spi-stm32h7.c b/firmware/target/arm/stm32/spi-stm32h7.c index fc4d87eafc..b7741e0182 100644 --- a/firmware/target/arm/stm32/spi-stm32h7.c +++ b/firmware/target/arm/stm32/spi-stm32h7.c @@ -130,6 +130,7 @@ void stm_spi_init(struct stm_spi *spi, spi->clock = config->clock; spi->mode = config->mode; spi->set_cs = config->set_cs; + spi->eot_delay_us = 1 + (1000000 / config->freq); semaphore_init(&spi->sem, 1, 0); @@ -164,7 +165,6 @@ void stm_spi_init(struct stm_spi *spi, stm32_clock_enable(spi->clock); - /* TODO: allow setting MBR here */ reg_writelf(spi->regs, SPI_CFG1, MBR(mbr), CRCEN(0), @@ -225,6 +225,8 @@ int stm_spi_xfer(struct stm_spi *spi, size_t size, spi->rx_buf = rx_buf; spi->rx_size = rx_buf ? size : 0; + membarrier(); + stm_spi_enable(spi, hd_tx, size); semaphore_wait(&spi->sem, TIMEOUT_BLOCK); @@ -236,10 +238,8 @@ int stm_spi_xfer(struct stm_spi *spi, size_t size, * For 2.22.2 we need to wait at least 1 SCK cycle before starting the * next transaction. For 2.22.6, waiting 1/2 SCK cycle should be enough * since the EOT event is raised on a clock edge. - * - * TODO: calculate this delay time. doesn't seem to match assumptions above */ - udelay(5); + udelay(spi->eot_delay_us); stm_spi_disable(spi); return 0; @@ -251,9 +251,13 @@ void stm_spi_irq_handler(struct stm_spi *spi) { uint32_t sr = reg_readl(spi->regs, SPI_SR); - if (spi->tx_size == 0 && spi->rx_size == 0) + if (spi->tx_size == 0 && + spi->rx_size == 0 && + reg_vreadf(sr, SPI_SR, EOT)) { semaphore_release(&spi->sem); + + reg_writelf(spi->regs, SPI_IFCR, EOTC(1)); reg_varl(spi->regs, SPI_IER) = 0; return; } @@ -261,6 +265,8 @@ void stm_spi_irq_handler(struct stm_spi *spi) if (spi->tx_size > 0 && reg_vreadf(sr, SPI_SR, TXP)) { uint32_t data = stm_spi_pack(&spi->tx_buf, &spi->tx_size); + if (spi->tx_size == 0) + reg_writelf(spi->regs, SPI_IER, TXPIE(0)); reg_varl(spi->regs, SPI_DR) = data; continue; @@ -272,6 +278,9 @@ void stm_spi_irq_handler(struct stm_spi *spi) uint32_t data = reg_readl(spi->regs, SPI_DR); stm_spi_unpack(&spi->rx_buf, &spi->rx_size, data); + if (spi->rx_size == 0) + reg_writelf(spi->regs, SPI_IER, RXPIE(0)); + continue; } diff --git a/firmware/target/arm/stm32/spi-stm32h7.h b/firmware/target/arm/stm32/spi-stm32h7.h index a6b0ef11d0..f7871a3969 100644 --- a/firmware/target/arm/stm32/spi-stm32h7.h +++ b/firmware/target/arm/stm32/spi-stm32h7.h @@ -81,6 +81,7 @@ struct stm_spi enum stm_spi_mode mode; stm_spi_set_cs_t set_cs; uint32_t frame_size; + uint32_t eot_delay_us; const void *tx_buf; size_t tx_size; From dd21a1d1d9ae4f314eb16d4813414ee72e2aa0de Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 10 Feb 2026 15:43:18 +0000 Subject: [PATCH 60/75] echoplayer: reduce LCD RGB & SPI output speed Low speed works for 50pF loads up to 12 MHz. LCD signals fall well within those limits so there's no reason to use any higher speed. Change-Id: I6dab899fac316bb02572174ef13a98cccbf4ae66 --- firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c | 9 ++------- firmware/target/arm/stm32/echoplayer/system-echoplayer.c | 6 +++--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c index bf83ad4937..e68b0d9b0e 100644 --- a/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/lcd-echoplayer.c @@ -35,13 +35,8 @@ #define MS_TO_TICKS(x) \ (((x) + (1000 / HZ - 1)) / (1000 / HZ)) -/* - * ILI9342C specifies 10 MHz max - * - * Use 12MHz for now -- for some reason using 6 MHz doesn't work - * to enable RGB mode, but works fine to send graphics in SPI mode? - */ -#define LCD_SPI_FREQ 12000000 +/* ILI9342C specifies 10 MHz max */ +#define LCD_SPI_FREQ 10000000 #define ili_cmd(cmd, ...) \ do { \ diff --git a/firmware/target/arm/stm32/echoplayer/system-echoplayer.c b/firmware/target/arm/stm32/echoplayer/system-echoplayer.c index 88f7b27720..284f7bc2ab 100644 --- a/firmware/target/arm/stm32/echoplayer/system-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/system-echoplayer.c @@ -44,9 +44,9 @@ #define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP) #define F_SDMMC1CK GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) #define F_SAI1 GPIOF_FUNCTION(6, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) -#define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) -#define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) -#define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) +#define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) +#define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) +#define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) #define F_LPTIM4_OUT GPIOF_FUNCTION(3, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) #define F_LPTIM1_OUT GPIOF_FUNCTION(1, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) From aea9e1b63fc957355ba3447c9551d567c710d56b Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Mon, 16 Feb 2026 11:11:19 +0200 Subject: [PATCH 61/75] configure: add ability to select plugins to build in --plugins flag Use ":" as the separator. Useful for plugin development and debugging. Example: ../tools/configure --target=hibyr1 --type=ADS --plugins="properties.c:imageviewer" This creates a debug simulator build for Hiby R1 with the properties.c file and the imageviewer directory plugins enabled. Change-Id: If974cfb0c54bd2c1a53ae11cc3f942c698ef2fe4 --- apps/plugins/plugins.make | 8 ++++++++ tools/configure | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make index 8620d3f9c0..55a6946c61 100644 --- a/apps/plugins/plugins.make +++ b/apps/plugins/plugins.make @@ -20,11 +20,15 @@ ifeq ($(APP_TYPE),ctru-app) is_app_build = endif +ifdef SELECTED_PLUGINS_SRC +PLUGINS_SRC = $(SELECTED_PLUGINS_SRC) +else ifdef is_app_build PLUGINS_SRC = $(call preprocess, $(APPSDIR)/plugins/SOURCES.app_build) else PLUGINS_SRC = $(call preprocess, $(APPSDIR)/plugins/SOURCES) endif +endif # ifdef SELECTED_PLUGINS_SRC OTHER_SRC += $(PLUGINS_SRC) ROCKS1 := $(PLUGINS_SRC:.c=.rock) ROCKS1 := $(call full_path_subst,$(ROOTDIR)/%,$(BUILDDIR)/%,$(ROCKS1)) @@ -58,11 +62,15 @@ endif OTHER_SRC += $(ROOTDIR)/apps/plugins/plugin_crt0.c PLUGIN_CRT0 := $(BUILDDIR)/apps/plugins/plugin_crt0.o # multifile plugins (subdirs): +ifdef SELECTED_PLUGINS_SUBDIRS +PLUGINSUBDIRS := $(SELECTED_PLUGINS_SUBDIRS) +else ifdef is_app_build PLUGINSUBDIRS := $(call preprocess, $(APPSDIR)/plugins/SUBDIRS.app_build) else PLUGINSUBDIRS := $(call preprocess, $(APPSDIR)/plugins/SUBDIRS) endif +endif # ifdef SELECTED_PLUGINS_SUBDIRS PLUGIN_LIBS := $(PLUGINLIB) $(PLUGINBITMAPLIB) $(SETJMPLIB) $(FIXEDPOINTLIB) diff --git a/tools/configure b/tools/configure index 8d7739f0cc..b68709b90a 100755 --- a/tools/configure +++ b/tools/configure @@ -1557,6 +1557,7 @@ ARG_THREAD_SUPPORT= ARG_32BIT= ARG_ADDR_SAN= ARG_UBSAN= +ARG_PLUGINS= err= for arg in "$@"; do case "$arg" in @@ -1573,6 +1574,7 @@ for arg in "$@"; do --ttsopts=*) ARG_TTSOPTS=`echo "$arg" | cut -d = -f 2`;; --type=*) ARG_TYPE=`echo "$arg" | cut -d = -f 2`;; --voice=*) ARG_VOICE=`echo "$arg" | cut -d = -f 2`;; + --plugins=*) ARG_PLUGINS=`echo "$arg" | cut -d = -f 2`;; --thumb) ARG_ARM_THUMB=1;; --no-thumb) ARG_ARM_THUMB=0;; --32-bit) ARG_32BIT=1;; @@ -4828,11 +4830,34 @@ cmdline=`echo $cmdline | sed -e s,--target=[a-zA-Z_0-9]\*,,g \ -e s,--type=[a-zA-Z0-9]\*,,g` cmdline="$cmdline --target=\$(MODELNAME) --ram=\$(MEMORYSIZE) --rbdir=\$(RBDIR) --type=$btype$advopts" +if [ -n "$ARG_PLUGINS" ]; then + echo "Selected plugins: $ARG_PLUGINS" + plugins="yes" + + selected_src="" + selected_subdirs="" + chk_plugin_dir="${rootdir}/apps/plugins" + + IFS=":" + for p in $ARG_PLUGINS; do + if [ -d "$chk_plugin_dir/$p" ]; then + selected_subdirs="$selected_subdirs \$(ROOTDIR)/apps/plugins/$p" + elif [ -f "$chk_plugin_dir/$p" ]; then + selected_src="$selected_src \$(ROOTDIR)/apps/plugins/$p" + else + echo "Warning: Plugin '$p' found neither as file nor directory in $chk_plugin_dir. Use ':' as the separator." + fi + done +fi + ### end of cmdline cat > Makefile < Date: Mon, 16 Feb 2026 18:10:06 -0500 Subject: [PATCH 62/75] jz4760: Correct typo in SoC header for MSC_CMDAT_RESPONSE_R7 Change-Id: I71226d1adb03a56cfea314ddd7af4f198a008986 --- firmware/export/jz4760b.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/export/jz4760b.h b/firmware/export/jz4760b.h index 14b5a71097..5f83887b99 100644 --- a/firmware/export/jz4760b.h +++ b/firmware/export/jz4760b.h @@ -6741,7 +6741,7 @@ static __inline__ int __mdmac_get_irq(void) #define MSC_CMDAT_RESPONSE_R4 (0x4 << MSC_CMDAT_RESPONSE_BIT) /* Format R4 */ #define MSC_CMDAT_RESPONSE_R5 (0x5 << MSC_CMDAT_RESPONSE_BIT) /* Format R5 */ #define MSC_CMDAT_RESPONSE_R6 (0x6 << MSC_CMDAT_RESPONSE_BIT) /* Format R6 */ - #define MSC_CMDAT_RESRONSE_R7 (0x7 << MSC_CMDAT_RESPONSE_BIT) /* Format R7 */ + #define MSC_CMDAT_RESPONSE_R7 (0x7 << MSC_CMDAT_RESPONSE_BIT) /* Format R7 */ #define CMDAT_DMA_EN (1 << 8) #define CMDAT_INIT (1 << 7) From 101f5cffe6d517d455fe22bf58906ec36cac49e0 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 16 Feb 2026 18:10:50 -0500 Subject: [PATCH 63/75] jz4740: NAND address needs to be 'unsigned long' not sector_t Change-Id: I58ec94710b938306385df2482bd9279d09fb5362 --- firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index 3187c28952..8d928ff27e 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c @@ -84,7 +84,7 @@ struct nand_param * */ -static volatile sector_t nand_address; +static volatile unsigned long nand_address; #define NAND_DATAPORT (nand_address) #define NAND_ADDRPORT (nand_address+0x10000) #define NAND_COMMPORT (nand_address+0x08000) From 478303346c4156612033cc0a7cbc7e2b2ec7f2aa Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 16 Feb 2026 18:12:32 -0500 Subject: [PATCH 64/75] sd: Add definition for SET_BLOCK_COUNT command Change-Id: Ib9cdc8e8bb7a43a4642be8cf88a1d734a6ae4808 --- firmware/export/sd.h | 1 + firmware/export/sdmmc.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/export/sd.h b/firmware/export/sd.h index 01ad760f86..3895fdc0c9 100644 --- a/firmware/export/sd.h +++ b/firmware/export/sd.h @@ -93,6 +93,7 @@ int sd_num_drives(int first_drive); #define SD_READ_MULTIPLE_BLOCK 18 #define SD_SEND_NUM_WR_BLOCKS 22 /* acmd22 */ #define SD_UC_ADDRESS_EXTENSION 22 +#define SD_SET_BLOCK_COUNT 23 #define SD_SET_WR_BLK_ERASE_COUNT 23 /* acmd23 */ #define SD_WRITE_BLOCK 24 #define SD_WRITE_MULTIPLE_BLOCK 25 diff --git a/firmware/export/sdmmc.h b/firmware/export/sdmmc.h index ed075f82a3..01158a0061 100644 --- a/firmware/export/sdmmc.h +++ b/firmware/export/sdmmc.h @@ -51,7 +51,7 @@ typedef struct unsigned int current_bank; #endif - unsigned int sd2plus; /* SD 2.0 or better */ + unsigned int sd2plus; /* SD 2.0 or better */ } tCardInfo; #if (CONFIG_STORAGE & STORAGE_SD) From 59f78841fd82169870c83d7f11b1150e42fe9a9b Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 16 Feb 2026 21:53:23 -0500 Subject: [PATCH 65/75] jz47xx: Numerous enhancements to the SD driver * Rework logf/DEBUG distinction * Don't try to init a card that isn't detected * Inform card that host supports SDUC * Implement CMD22 (SET_UPPER_ADDR) * Implement CMD23 (SET_BLOCK_COUNT) * Disable DMA for transfers under 512 bytes * Created ACMD+data xfer command path * Incorrect handling of RESPONSE_R7 * Clean up 4bit stuff, only turn it on after we enable it in the card. * Clear END_CMD_RES bit _after_ we check the status * Probe SCR <-- NOT YET WORKING, DISABLED jz4740 had these additional improvements: * Restructuring to bring it closer to 4760 driver * Unified read/write setup code * IRQ handling and polling improvements Change-Id: I47379f097af4bf50177499b3d80a6c9c42d48057 --- .../mips/ingenic_jz47xx/ata-sd-jz4740.c | 483 +++++++++--------- .../mips/ingenic_jz47xx/ata-sd-jz4760.c | 352 +++++++------ 2 files changed, 428 insertions(+), 407 deletions(-) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c index 066be4e987..e20c681c1e 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c @@ -41,7 +41,7 @@ static struct mutex sd_mtx; //static struct semaphore sd_wakeup; static int use_4bit; -static int num_6; +static int use_sbc; //#define SD_DMA_ENABLE #define SD_DMA_INTERRUPT 0 @@ -84,6 +84,7 @@ enum sd_result_t SD_ERROR_TIMEOUT, SD_ERROR_CRC, SD_ERROR_DRIVER_FAILURE, + SD_ERROR_ACMD_REJECT, }; /* Standard MMC/SD clock speeds */ @@ -109,19 +110,17 @@ enum sd_result_t /* class 9 */ #define SD_GO_IRQ_STATE 40 /* bcr R5 */ -/* Don't change the order of these; they are used in dispatch tables */ enum sd_rsp_t { RESPONSE_NONE = 0, RESPONSE_R1 = 1, RESPONSE_R1B = 2, - RESPONSE_R2_CID = 3, - RESPONSE_R2_CSD = 4, - RESPONSE_R3 = 5, - RESPONSE_R4 = 6, - RESPONSE_R5 = 7, - RESPONSE_R6 = 8, - RESPONSE_R7 = 9, + RESPONSE_R2 = 3, + RESPONSE_R3 = 4, + RESPONSE_R4 = 5, + RESPONSE_R5 = 6, + RESPONSE_R6 = 7, + RESPONSE_R7 = 8, }; /* @@ -179,10 +178,9 @@ struct sd_response_r3 struct sd_request { - int index; /* Slot index - used for CS lines */ int cmd; /* Command to send */ unsigned int arg; /* Argument to send */ - enum sd_rsp_t rtype; /* Response type expected */ + enum sd_rsp_t rtype; /* Response type expected */ /* Data transfer (these may be modified at the low level) */ unsigned short nob; /* Number of blocks to transfer*/ @@ -195,16 +193,6 @@ struct sd_request enum sd_result_t result; }; -#define SD_OCR_ARG 0x00ff8000 /* Argument of OCR */ - -/*********************************************************************** - * SD Events - */ -#define SD_EVENT_NONE 0x00 /* No events */ -#define SD_EVENT_RX_DATA_DONE 0x01 /* Rx data done */ -#define SD_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ -#define SD_EVENT_PROG_DONE 0x04 /* Programming is done */ - /************************************************************************** * Utility functions **************************************************************************/ @@ -262,6 +250,9 @@ static int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, u if (request->result) return request->result; + if (buf[0] != 0x03) + return SD_ERROR_HEADER_MISMATCH; + *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */ *(buf+1) = 0; @@ -298,7 +289,7 @@ static inline int jz_sd_stop_clock(void) timeout--; if (timeout == 0) { - DEBUG("Timeout on stop clock waiting"); + logf("Timeout on stop clock waiting"); return SD_ERROR_TIMEOUT; } udelay(1); @@ -322,7 +313,7 @@ static int jz_sd_check_status(struct sd_request *request) /* Checking for response or data timeout */ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) { - DEBUG("SD timeout, MSC_STAT 0x%x CMD %d", status, + logf("SD timeout, MSC_STAT 0x%x CMD %d", status, request->cmd); return SD_ERROR_TIMEOUT; } @@ -332,7 +323,7 @@ static int jz_sd_check_status(struct sd_request *request) (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) { - DEBUG("SD CRC error, MSC_STAT 0x%x", status); + logf("SD CRC error, MSC_STAT 0x%x", status); return SD_ERROR_CRC; } @@ -341,7 +332,7 @@ static int jz_sd_check_status(struct sd_request *request) /* Checking for FIFO empty */ /*if(status & MSC_STAT_DATA_FIFO_EMPTY && request->rtype != RESPONSE_NONE) { - DEBUG("SD FIFO empty, MSC_STAT 0x%x", status); + logf("SD FIFO empty, MSC_STAT 0x%x", status); return SD_ERROR_UNDERRUN; }*/ @@ -360,16 +351,14 @@ static void jz_sd_get_response(struct sd_request *request) buf = request->response; request->result = SD_NO_ERROR; - switch (request->rtype) - { + switch (request->rtype) { case RESPONSE_R1: case RESPONSE_R1B: - case RESPONSE_R7: - case RESPONSE_R6: case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5: - { + case RESPONSE_R6: + case RESPONSE_R7: data = REG_MSC_RES; buf[0] = (data >> 8) & 0xff; buf[1] = data & 0xff; @@ -383,10 +372,7 @@ static void jz_sd_get_response(struct sd_request *request) request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]); break; - } - case RESPONSE_R2_CID: - case RESPONSE_R2_CSD: - { + case RESPONSE_R2: for (i = 0; i < 16; i += 2) { data = REG_MSC_RES; @@ -395,7 +381,6 @@ static void jz_sd_get_response(struct sd_request *request) } DEBUG("request %d, response []", request->rtype); break; - } case RESPONSE_NONE: DEBUG("No response"); break; @@ -441,6 +426,9 @@ static void jz_sd_receive_data_dma(struct sd_request *req) /* clear status and disable channel */ REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; + + /* flush dcache again */ + discard_dcache_range(req->buffer, req->cnt); } static void jz_mmc_transmit_data_dma(struct mmc_request *req) @@ -488,6 +476,12 @@ static int jz_sd_receive_data(struct sd_request *req) unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ unsigned int stat, timeout, data, cnt; +#ifdef SD_DMA_ENABLE + if (waligned) + jz_sd_reveive_data_dma(request); + return SD_NO_ERROR; +#endif + for (; nob >= 1; nob--) { timeout = 0x3FFFFFF; @@ -546,6 +540,12 @@ static int jz_sd_transmit_data(struct sd_request *req) unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ unsigned int stat, timeout, data, cnt; +#ifdef SD_DMA_ENABLE + if (waligned) + jz_sd_transmit_data_dma(request); + return SD_NO_ERROR; +#endif + for (; nob >= 1; nob--) { timeout = 0x3FFFFFF; @@ -640,12 +640,16 @@ static void jz_sd_set_clock(unsigned int rate) ********************************************************************************************************************/ static int jz_sd_exec_cmd(struct sd_request *request) { - unsigned int cmdat = 0, events = 0; + unsigned int cmdat = 0; int retval, timeout = 0x3fffff; + bool has_data = (request->buffer != NULL); /* Indicate we have no result yet */ request->result = SD_NO_RESPONSE; + /* Stop clock when programming things */ + jz_sd_stop_clock(); /* stop SD clock */ + if (request->cmd == SD_CIM_RESET) { /* On reset, 1-bit bus width */ use_4bit = 0; @@ -659,31 +663,30 @@ static int jz_sd_exec_cmd(struct sd_request *request) /* On reset, stop SD clock */ jz_sd_stop_clock(); } - if (request->cmd == SD_SET_BUS_WIDTH) - { - if (request->arg == 0x2) - { - DEBUG("Use 4-bit bus width"); - use_4bit = 1; - } - else - { - DEBUG("Use 1-bit bus width"); - use_4bit = 0; - } + + /* Generic handling for all requests with data rx/tx */ + if (has_data) { + cmdat |= MSC_CMDAT_DATA_EN; +// if (request->nob > 1 && use_sbc[drive]) +// cmdat |= MSC_CMDAT_SEND_AS_STOP; +#ifdef SD_DMA_ENABLE + if (request->cnt >= 512) + cmdat |= MSC_CMDAT_DMA_EN; +#endif } /* mask all interrupts */ - //REG_MSC_IMASK = 0xffff; + REG_MSC_IMASK = 0xffff; /* clear status */ REG_MSC_IREG = 0xffff; - /*open interrupt */ - REG_MSC_IMASK = (~7); + /* unmask interrupts we care about */ + REG_MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); + /* use 4-bit bus width when possible */ if (use_4bit) cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; - /* Set command type and events */ + /* Per-command type handling */ switch (request->cmd) { /* SD core extra command */ @@ -706,27 +709,8 @@ static int jz_sd_exec_cmd(struct sd_request *request) case SD_READ_SINGLE_BLOCK: case SD_READ_MULTIPLE_BLOCK: case SD_SEND_SCR: -#if defined(SD_DMA_ENABLE) - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; -#endif - events = SD_EVENT_RX_DATA_DONE; - break; - case SD_SWITCH_FUNC: - if (num_6 < 2) - { -#if defined(SD_DMA_ENABLE) - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | - MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; -#endif - events = SD_EVENT_RX_DATA_DONE; - } + /* These READ data */ break; case SD_WRITE_DAT_UNTIL_STOP: @@ -734,18 +718,14 @@ static int jz_sd_exec_cmd(struct sd_request *request) case SD_WRITE_MULTIPLE_BLOCK: case SD_PROGRAM_CID: case SD_PROGRAM_CSD: - case SD_LOCK_UNLOCK: -#if defined(SD_DMA_ENABLE) - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE; -#endif - events = SD_EVENT_TX_DATA_DONE | SD_EVENT_PROG_DONE; + /* These WRITE data */ + cmdat |= MSC_CMDAT_WRITE; break; +// case SD_LOCK_UNLOCK: // can be a read or write, needs busy too. + case SD_STOP_TRANSMISSION: - events = SD_EVENT_PROG_DONE; + // cmdat |= MSC_CMDAT_STOP_ABORT; break; /* ac - no data transfer */ @@ -762,11 +742,9 @@ static int jz_sd_exec_cmd(struct sd_request *request) cmdat |= MSC_CMDAT_BUSY; /* FALLTHRU */ case RESPONSE_R1: - case RESPONSE_R7: cmdat |= MSC_CMDAT_RESPONSE_R1; break; - case RESPONSE_R2_CID: - case RESPONSE_R2_CSD: + case RESPONSE_R2: cmdat |= MSC_CMDAT_RESPONSE_R2; break; case RESPONSE_R3: @@ -781,6 +759,9 @@ static int jz_sd_exec_cmd(struct sd_request *request) case RESPONSE_R6: cmdat |= MSC_CMDAT_RESPONSE_R6; break; + case RESPONSE_R7: + cmdat |= MSC_CMDAT_RESPONSE_R1; /* 4740 lacks R7 */ + break; default: break; } @@ -794,14 +775,8 @@ static int jz_sd_exec_cmd(struct sd_request *request) /* Set argument */ REG_MSC_ARG = request->arg; - /* Set block length and nob */ - if (request->cmd == SD_SEND_SCR) - { /* get SCR from DataFIFO */ - REG_MSC_BLKLEN = 8; - REG_MSC_NOB = 1; - } - else - { + /* Set block length and nob if there is data */ + if (has_data) { REG_MSC_BLKLEN = request->block_len; REG_MSC_NOB = request->nob; } @@ -816,18 +791,15 @@ static int jz_sd_exec_cmd(struct sd_request *request) jz_sd_start_clock(); /* Wait for command completion */ - //__intc_unmask_irq(IRQ_MSC); //semaphore_wait(&sd_wakeup, 100); while (timeout-- && !(REG_MSC_STAT & MSC_STAT_END_CMD_RES)); - if (timeout == 0) return SD_ERROR_TIMEOUT; - REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */ - /* Check for status */ retval = jz_sd_check_status(request); + REG_MSC_IREG = MSC_IREG_END_CMD_RES; /* clear flag */ if (retval) return retval; @@ -839,46 +811,28 @@ static int jz_sd_exec_cmd(struct sd_request *request) jz_sd_get_response(request); /* Start data operation */ - if (events & (SD_EVENT_RX_DATA_DONE | SD_EVENT_TX_DATA_DONE)) - { - if (events & SD_EVENT_RX_DATA_DONE) - { - if (request->cmd == SD_SEND_SCR) - { - /* SD card returns SCR register as data. - SD core expect it in the response buffer, - after normal response. */ - request->buffer = - (unsigned char *) ((unsigned int) request->response + 5); - } -#ifdef SD_DMA_ENABLE - jz_sd_receive_data_dma(request); -#else - jz_sd_receive_data(request); -#endif + if (has_data) { + if (cmdat & MSC_CMDAT_WRITE) { + retval = jz_sd_transmit_data(request); + } else { + retval = jz_sd_receive_data(request); } + if (retval) + return retval; - if (events & SD_EVENT_TX_DATA_DONE) - { -#ifdef SD_DMA_ENABLE - jz_sd_transmit_data_dma(request); -#else - jz_sd_transmit_data(request); -#endif - } - //__intc_unmask_irq(IRQ_MSC); //semaphore_wait(&sd_wakeup, 100); /* Wait for Data Done */ - while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)); + while (!(REG_MSC_IREG & MSC_IREG_DATA_TRAN_DONE)) + yield(); REG_MSC_IREG = MSC_IREG_DATA_TRAN_DONE; /* clear status */ } - /* Wait for Prog Done event */ - if (events & SD_EVENT_PROG_DONE) + /* Wait for Prog Done event if necessary */ + if (cmdat & (MSC_CMDAT_BUSY | MSC_CMDAT_WRITE)) { - //__intc_unmask_irq(IRQ_MSC); //semaphore_wait(&sd_wakeup, 100); - while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)); + while (!(REG_MSC_IREG & MSC_IREG_PRG_DONE)) + yield(); REG_MSC_IREG = MSC_IREG_PRG_DONE; /* clear status */ } @@ -904,7 +858,7 @@ static void jz_sd_tx_handler(unsigned int arg) { if (__dmac_channel_address_error_detected(arg)) { - DEBUG("%s: DMAC address error.", __FUNCTION__); + logf("%s: DMAC address error.", __FUNCTION__); __dmac_channel_clear_address_error(arg); } if (__dmac_channel_transmit_end_detected(arg)) @@ -918,7 +872,7 @@ static void jz_sd_rx_handler(unsigned int arg) { if (__dmac_channel_address_error_detected(arg)) { - DEBUG("%s: DMAC address error.", __FUNCTION__); + logf("%s: DMAC address error.", __FUNCTION__); __dmac_channel_clear_address_error(arg); } if (__dmac_channel_transmit_end_detected(arg)) @@ -976,10 +930,12 @@ static void jz_sd_hardware_init(void) #endif } -static int sd_send_cmd(struct sd_request *request, int cmd, unsigned int arg, +static void sd_send_cmd(struct sd_request *request, int cmd, unsigned int arg, unsigned short nob, unsigned short block_len, enum sd_rsp_t rtype, unsigned char* buffer) { + int retval; + request->cmd = cmd; request->arg = arg; request->rtype = rtype; @@ -987,8 +943,13 @@ static int sd_send_cmd(struct sd_request *request, int cmd, unsigned int arg, request->block_len = block_len; request->buffer = buffer; request->cnt = nob * block_len; + memset(&request->response, 0xa5, sizeof(request->response)); + request->result = SD_NO_RESPONSE; + + retval = jz_sd_exec_cmd(request); + if (retval) + request->result = retval; - return jz_sd_exec_cmd(request); } static void sd_simple_cmd(struct sd_request *request, int cmd, unsigned int arg, @@ -997,6 +958,46 @@ static void sd_simple_cmd(struct sd_request *request, int cmd, unsigned int arg, sd_send_cmd(request, cmd, arg, 0, 0, rtype, NULL); } +static int sd_exec_acmd(struct sd_request *request, int cmd, unsigned int arg) +{ + struct sd_response_r1 r1; + int retval; + + sd_simple_cmd(request, SD_APP_CMD, card.rca, RESPONSE_R1); + retval = sd_unpack_r1(request, &r1); + + if (retval) + return retval; + + if (!(r1.status & SD_R1_APP_CMD)) { + logf("ACMD not accepted\n"); + return SD_ERROR_ACMD_REJECT; + } + + sd_simple_cmd(request, cmd, arg, RESPONSE_R1); + return sd_unpack_r1(request, &r1); +} + +static int sd_exec_acmd_buf(struct sd_request *request, int cmd, unsigned int arg, enum sd_rsp_t rtype, unsigned short nob, unsigned short block_len, unsigned char *buffer) +{ + struct sd_response_r1 r1; + int retval; + + sd_simple_cmd(request, SD_APP_CMD, card.rca, RESPONSE_R1); + retval = sd_unpack_r1(request, &r1); + if (retval) + return retval; + + if (!(r1.status & SD_R1_APP_CMD)) { + logf("ACMD not accepted\n"); + return SD_ERROR_ACMD_REJECT; + } + + sd_send_cmd(request, cmd, arg, + nob, block_len, rtype, buffer); + return SD_NO_ERROR; +} + #define SD_INIT_DOING 0 #define SD_INIT_PASSED 1 #define SD_INIT_FAILED 2 @@ -1004,59 +1005,50 @@ static int sd_init_card_state(struct sd_request *request) { struct sd_response_r1 r1; struct sd_response_r3 r3; - int retval, i, ocr = 0x40300000, limit_41 = 0; + int retval, i, ocr = 0x40300000 /* SDXC, 3.2-3.4v */; + +#ifdef HAVE_SDUC + ocr |= 0x08000000; /* Add on SDUC */ +#endif switch (request->cmd) { case SD_GO_IDLE_STATE: /* No response to parse */ sd_simple_cmd(request, SD_SEND_IF_COND, 0x1AA, RESPONSE_R1); break; - case SD_SEND_IF_COND: retval = sd_unpack_r1(request, &r1); - sd_simple_cmd(request, SD_APP_CMD, 0, RESPONSE_R1); - break; +// if (retval) +// return SD_INIT_FAILED; - case SD_APP_CMD: - retval = sd_unpack_r1(request, &r1); - if (retval & (limit_41 < 100)) - { - DEBUG("sd_init_card_state: unable to SD_APP_CMD error=%d", - retval); - limit_41++; - sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3); - } - else if (limit_41 < 100) - { - limit_41++; - sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3); - } - else - /* reset the card to idle*/ - sd_simple_cmd(request, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); + retval = sd_exec_acmd_buf(request, SD_APP_OP_COND, ocr, + RESPONSE_R3, 0, 0, NULL); + if (retval) + return SD_INIT_FAILED; break; - case SD_APP_OP_COND: retval = sd_unpack_r3(request, &r3); if (retval) - break; + return SD_INIT_FAILED; - DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr); + DEBUG("read ocr value = 0x%08x", r3.ocr); card.ocr = r3.ocr; + // XXX for SDUC, check that B27+B30 of OCR are set. if(!(r3.ocr & SD_CARD_BUSY || ocr == 0)) { + /* Re-issue AP_OP_COND */ sleep(HZ / 100); - sd_simple_cmd(request, SD_APP_CMD, 0, RESPONSE_R1); + retval = sd_exec_acmd_buf(request, SD_APP_OP_COND, ocr, + RESPONSE_R3, 0, 0, NULL); + if (retval) + return SD_INIT_FAILED; } else { - /* Set the data bus width to 4 bits */ - use_4bit = 1; - sd_simple_cmd(request, SD_ALL_SEND_CID, 0, RESPONSE_R2_CID); + sd_simple_cmd(request, SD_ALL_SEND_CID, 0, RESPONSE_R2); } break; - case SD_ALL_SEND_CID: for(i=0; i<4; i++) card.cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | @@ -1067,16 +1059,16 @@ static int sd_init_card_state(struct sd_request *request) break; case SD_SEND_RELATIVE_ADDR: retval = sd_unpack_r6(request, &r1, &card.rca); - card.rca = card.rca << 16; DEBUG("sd_init_card_state: Get RCA from SD: 0x%04lx Status: %x", card.rca, r1.status); + card.rca = card.rca << 16; if (retval) { - DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", + logf("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", retval); return SD_INIT_FAILED; } - sd_simple_cmd(request, SD_SEND_CSD, card.rca, RESPONSE_R2_CSD); + sd_simple_cmd(request, SD_SEND_CSD, card.rca, RESPONSE_R2); break; case SD_SEND_CSD: @@ -1087,12 +1079,31 @@ static int sd_init_card_state(struct sd_request *request) sd_parse_csd(&card); logf("CSD: %08lx%08lx%08lx%08lx", card.csd[0], card.csd[1], card.csd[2], card.csd[3]); + +#if 0 // XXX SCR is not working yet + retval = sd_exec_acmd_buf(request, SD_SEND_SCR, 0, RESPONSE_R1, + 1, 8, &request->response[5]); + if (!retval) + retval = sd_unpack_r1(request, &r1); + // XXX check retval? + break; + case SD_SEND_SCR: +// if (request->result) +// return SD_INIT_FAILED; + for(i=0; i<2; i++) + card.scr[i] = ((request->buffer[0+i*4]<<24) | (request->buffer[1+i*4]<<16) | + (request->buffer[2+i*4]<< 8) | request->buffer[3+i*4]); + + logf("SCR: %08lx%08lx", card.scr[0], card.scr[1]); + + use_sbc = card.scr[0] & 2; +#endif DEBUG("SD card is ready"); jz_sd_set_clock(SD_CLOCK_FAST); return SD_INIT_PASSED; default: - DEBUG("sd_init_card_state: error! Illegal last cmd %d", request->cmd); + logf("sd_init_card_state: error! Illegal last cmd %d", request->cmd); return SD_INIT_FAILED; } @@ -1107,8 +1118,11 @@ static int sd_switch(struct sd_request *request, int mode, int group, mode = !!mode; value &= 0xF; arg = (mode << 31 | 0x00FFFFFF); - arg &= ~(0xF << (group * 4)); - arg |= value << (group * 4); + if (mode) { + group--; + arg &= ~(0xF << (group * 4)); + arg |= value << (group * 4); + } sd_send_cmd(request, 6, arg, 1, 64, RESPONSE_R1, resp); return 0; @@ -1137,7 +1151,7 @@ static int sd_switch_hs(struct sd_request *request) { unsigned int status[64 / 4]; - sd_switch(request, 1, 0, 1, (unsigned char*) status); + sd_switch(request, 1, 1, 1, (unsigned char*) status); return 0; } @@ -1162,14 +1176,17 @@ static int sd_select_card(void) jz_sd_set_clock(SD_CLOCK_HIGH); } } - num_6 = 3; - sd_simple_cmd(&request, SD_APP_CMD, card.rca, - RESPONSE_R1); - retval = sd_unpack_r1(&request, &r1); - if (retval) - return retval; - sd_simple_cmd(&request, SD_SET_BUS_WIDTH, 2, RESPONSE_R1); - retval = sd_unpack_r1(&request, &r1); + + bool sup_4bit = 1; // XXX check against SCR + + if (sup_4bit) { + retval = sd_exec_acmd(&request, SD_SET_BUS_WIDTH, 2); + if (retval) + return retval; + use_4bit = 2; + DEBUG("Use 4-bit bus width"); + } + retval = sd_exec_acmd(&request, SD_SET_CLR_CARD_DETECT, 0); if (retval) return retval; @@ -1178,6 +1195,11 @@ static int sd_select_card(void) return 0; } +static inline bool card_detect_target(void) +{ + return (jz_sd_chkcard() == 1); +} + static int __sd_init_device(void) { int retval; @@ -1186,12 +1208,14 @@ static int __sd_init_device(void) /* Initialise card data as blank */ memset(&card, 0, sizeof(tCardInfo)); - num_6 = 0; use_4bit = 0; /* reset mmc/sd controller */ jz_sd_hardware_init(); + if (!card_detect_target()) + return 0; + sd_simple_cmd(&init_req, SD_CIM_RESET, 0, RESPONSE_NONE); sd_simple_cmd(&init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); @@ -1211,6 +1235,7 @@ int sd_init(void) if(!inited) { // semaphore_init(&sd_wakeup, 1, 0); + //__intc_unmask_irq(IRQ_MSC); mutex_init(&sd_mtx); inited = true; } @@ -1222,11 +1247,6 @@ int sd_init(void) return ret; } -static inline bool card_detect_target(void) -{ - return (jz_sd_chkcard() == 1); -} - tCardInfo* card_get_info_target(int card_no) { (void)card_no; @@ -1247,7 +1267,7 @@ static inline void sd_stop_transfer(void) mutex_unlock(&sd_mtx); } -int sd_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf) +int sd_transfer_sectors(IF_MD(int drive,) sector_t start, int count, void* buf, bool write) { #ifdef HAVE_MULTIDRIVE (void)drive; @@ -1273,26 +1293,35 @@ int sd_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf) if ((retval = sd_unpack_r1(&request, &r1))) goto err; - // XXX 64-bit - if (card.sd2plus) - { - sd_send_cmd(&request, SD_READ_MULTIPLE_BLOCK, start, - count, SD_BLOCK_SIZE, RESPONSE_R1, buf); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; - } - else - { - sd_send_cmd(&request, SD_READ_MULTIPLE_BLOCK, - start * SD_BLOCK_SIZE, count, - SD_BLOCK_SIZE, RESPONSE_R1, buf); + if (use_sbc && count > 1) { + sd_simple_cmd(&request, SD_SET_BLOCK_COUNT, count, RESPONSE_R1); if ((retval = sd_unpack_r1(&request, &r1))) goto err; } - sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; +#ifdef STORAGE_64BIT_SECTOR + // XXX check card[drive].ocr, b27+b30 == 11 + if (card.numblocks > 0xffffffffULL) { + uint32_t upper = start >> 32; + sd_simple_cmd(&request, SD_UC_ADDRESS_EXTENSION, upper, RESPONSE_R1); + if ((retval = sd_unpack_r1(&request, &r1))) + goto err; + } +#endif + + sd_send_cmd(&request, + (count > 1) ? + (write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK) : + (write ? SD_WRITE_BLOCK : SD_READ_SINGLE_BLOCK), + card.sd2plus ? start : (start * SD_BLOCK_SIZE), + count, SD_BLOCK_SIZE, RESPONSE_R1, buf); + retval = sd_unpack_r1(&request, &r1); + + if (retval || (!use_sbc && count > 1)) { + sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); + if ((retval = sd_unpack_r1(&request, &r1))) + goto err; + } err: last_disk_activity = current_tick; @@ -1301,60 +1330,14 @@ err: return retval; } +int sd_read_sectors(IF_MD(int drive,) sector_t start, int count, void* buf) +{ + return sd_transfer_sectors(IF_MD(drive,) start, count, buf, false); +} + int sd_write_sectors(IF_MD(int drive,) sector_t start, int count, const void* buf) { -#ifdef HAVE_MULTIDRIVE - (void)drive; -#endif - sd_start_transfer(); - - struct sd_request request; - struct sd_response_r1 r1; - int retval = -1; - - if (!card_detect_target() || count == 0 || start > card.numblocks) - goto err; - - if(card.initialized == 0 && !__sd_init_device()) - goto err; - - sd_simple_cmd(&request, SD_SEND_STATUS, card.rca, RESPONSE_R1); - retval = sd_unpack_r1(&request, &r1); - if (retval && (retval != SD_ERROR_STATE_MISMATCH)) - goto err; - - sd_simple_cmd(&request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; - - // XXX 64-bit - if (card.sd2plus) - { - sd_send_cmd(&request, SD_WRITE_MULTIPLE_BLOCK, start, - count, SD_BLOCK_SIZE, RESPONSE_R1, - (void*)buf); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; - } - else - { - sd_send_cmd(&request, SD_WRITE_MULTIPLE_BLOCK, - start * SD_BLOCK_SIZE, count, - SD_BLOCK_SIZE, RESPONSE_R1, (void*)buf); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; - } - - last_disk_activity = current_tick; - - sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; - -err: - sd_stop_transfer(); - - return retval; + return sd_transfer_sectors(IF_MD(drive,) start, count, (void*)buf, true); } long sd_last_disk_activity(void) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index db09c740cf..7a3b450e65 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c @@ -56,7 +56,7 @@ static struct semaphore sd_wakeup[NUM_DRIVES]; #endif static int use_4bit[NUM_DRIVES]; -static int num_6[NUM_DRIVES]; +static int use_sbc[NUM_DRIVES]; //#define DEBUG(x...) logf(x) #define DEBUG(x, ...) @@ -99,6 +99,7 @@ enum sd_result_t SD_ERROR_TIMEOUT, SD_ERROR_CRC, SD_ERROR_DRIVER_FAILURE, + SD_ERROR_ACMD_REJECT, }; /* Standard MMC/SD clock speeds */ @@ -124,19 +125,17 @@ enum sd_result_t /* class 9 */ #define SD_GO_IRQ_STATE 40 /* bcr R5 */ -/* Don't change the order of these; they are used in dispatch tables */ enum sd_rsp_t { RESPONSE_NONE = 0, RESPONSE_R1 = 1, RESPONSE_R1B = 2, - RESPONSE_R2_CID = 3, - RESPONSE_R2_CSD = 4, - RESPONSE_R3 = 5, - RESPONSE_R4 = 6, - RESPONSE_R5 = 7, - RESPONSE_R6 = 8, - RESPONSE_R7 = 9, + RESPONSE_R2 = 3, + RESPONSE_R3 = 4, + RESPONSE_R4 = 5, + RESPONSE_R5 = 6, + RESPONSE_R6 = 7, + RESPONSE_R7 = 8, }; /* These are unpacked versions of the actual responses */ @@ -155,10 +154,9 @@ struct sd_response_r3 struct sd_request { - int index; /* Slot index - used for CS lines */ int cmd; /* Command to send */ unsigned int arg; /* Argument to send */ - enum sd_rsp_t rtype; /* Response type expected */ + enum sd_rsp_t rtype; /* Response type expected */ /* Data transfer (these may be modified at the low level) */ unsigned short nob; /* Number of blocks to transfer*/ @@ -171,16 +169,6 @@ struct sd_request enum sd_result_t result; }; -#define SD_OCR_ARG 0x00ff8000 /* Argument of OCR */ - -/*********************************************************************** - * SD Events - */ -#define SD_EVENT_NONE 0x00 /* No events */ -#define SD_EVENT_RX_DATA_DONE 0x01 /* Rx data done */ -#define SD_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ -#define SD_EVENT_PROG_DONE 0x04 /* Programming is done */ - /************************************************************************** * Utility functions **************************************************************************/ @@ -238,6 +226,9 @@ static int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, u if (request->result) return request->result; + if (buf[0] != 0x03) + return SD_ERROR_HEADER_MISMATCH; + *rca = PARSE_U16(buf,1); /* Save RCA returned by the SD Card */ *(buf+1) = 0; @@ -282,7 +273,7 @@ static inline int jz_sd_stop_clock(const int drive) timeout--; if (timeout == 0) { - DEBUG("Timeout on stop clock waiting"); + logf("Timeout on stop clock waiting"); return SD_ERROR_TIMEOUT; } udelay(1); @@ -311,7 +302,7 @@ static int jz_sd_check_status(const int drive, struct sd_request *request) /* Checking for response or data timeout */ if (status & (MSC_STAT_TIME_OUT_RES | MSC_STAT_TIME_OUT_READ)) { - DEBUG("SD timeout, MSC_STAT 0x%x CMD %d", status, + logf("%d SD timeout, MSC_STAT 0x%x CMD %d", drive, status, request->cmd); return SD_ERROR_TIMEOUT; } @@ -321,14 +312,14 @@ static int jz_sd_check_status(const int drive, struct sd_request *request) (MSC_STAT_CRC_READ_ERROR | MSC_STAT_CRC_WRITE_ERROR | MSC_STAT_CRC_RES_ERR)) { - DEBUG("SD CRC error, MSC_STAT 0x%x", status); + logf("SD CRC error, MSC_STAT 0x%x", status); return SD_ERROR_CRC; } /* Checking for FIFO empty */ /*if(status & MSC_STAT_DATA_FIFO_EMPTY && request->rtype != RESPONSE_NONE) { - DEBUG("SD FIFO empty, MSC_STAT 0x%x", status); + logf("SD FIFO empty, MSC_STAT 0x%x", status); return SD_ERROR_UNDERRUN; }*/ @@ -350,16 +341,14 @@ static void jz_sd_get_response(const int drive, struct sd_request *request) buf = request->response; request->result = SD_NO_ERROR; - switch (request->rtype) - { + switch (request->rtype) { case RESPONSE_R1: case RESPONSE_R1B: - case RESPONSE_R7: - case RESPONSE_R6: case RESPONSE_R3: case RESPONSE_R4: case RESPONSE_R5: - { + case RESPONSE_R6: + case RESPONSE_R7: data = REG_MSC_RES(MSC_CHN(drive)); buf[0] = (data >> 8) & 0xff; buf[1] = data & 0xff; @@ -369,14 +358,11 @@ static void jz_sd_get_response(const int drive, struct sd_request *request) data = REG_MSC_RES(MSC_CHN(drive)); buf[4] = data & 0xff; - DEBUG("request %d, response [%02x %02x %02x %02x %02x]", + DEBUG("%d request %d, response [%02x %02x %02x %02x %02x]", drive, request->rtype, buf[0], buf[1], buf[2], buf[3], buf[4]); break; - } - case RESPONSE_R2_CID: - case RESPONSE_R2_CSD: - { + case RESPONSE_R2: for (i = 0; i < 16; i += 2) { data = REG_MSC_RES(MSC_CHN(drive)); @@ -385,7 +371,6 @@ static void jz_sd_get_response(const int drive, struct sd_request *request) } DEBUG("request %d, response []", request->rtype); break; - } case RESPONSE_NONE: DEBUG("No response"); break; @@ -413,7 +398,7 @@ static int jz_sd_receive_data(const int drive, struct sd_request *req) #if SD_DMA_ENABLE /* Use DMA if we can */ - if ((int)req->buffer & 0x3 == 0) + if ((int)req->buffer & 0x3 == 0 && req->cnt >= 512) return jz_sd_receive_data_dma(drive, req); #endif @@ -476,7 +461,7 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) #if SD_DMA_ENABLE /* Use DMA if we can */ - if ((int)req->buffer & 0x3 == 0) + if ((int)req->buffer & 0x3 == 0 && req->cnt >= 512) return jz_sd_transmit_data_dma(drive, req); #endif @@ -559,6 +544,9 @@ static int jz_sd_receive_data_dma(const int drive, struct sd_request *req) /* clear status and disable channel */ REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = 0; + /* flush dcache again */ + discard_dcache_range(req->buffer, req->cnt); + return SD_NO_ERROR; } @@ -726,15 +714,21 @@ static void jz_sd_set_clock(const int drive, unsigned int rate) ********************************************************************************************************************/ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) { - unsigned int cmdat = 0, events = 0; + unsigned int cmdat = 0; int retval; #if !SD_INTERRUPT long deadline = current_tick + (HZ * 5); #endif + bool has_data = (request->buffer != NULL); /* Indicate we have no result yet */ request->result = SD_NO_RESPONSE; +#if !SD_AUTO_CLOCK + /* Stop clock when programming things */ + jz_sd_stop_clock(drive); /* stop SD clock */ +#endif + if (request->cmd == SD_CIM_RESET) { /* On reset, 1-bit bus width */ use_4bit[drive] = 0; @@ -755,13 +749,26 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) #endif } + /* Generic handling for all requests with data rx/tx */ + if (has_data) { + cmdat |= MSC_CMDAT_DATA_EN; +// if (request->nob > 1 && use_sbc[drive]) +// cmdat |= MSC_CMDAT_SEND_AS_STOP; +#if SD_DMA_ENABLE + if (request->cnt >= 512) + cmdat |= MSC_CMDAT_DMA_EN; +#endif + } + /* mask all interrupts and clear status */ SD_IRQ_MASK(MSC_CHN(drive)); - /* open interrupt */ +#if SD_INTERRUPT + /* unmask interrupts we care about */ REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); +#endif - /* Set command type and events */ + /* Per-command type handling */ switch (request->cmd) { /* SD core extra command */ @@ -781,48 +788,11 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) /* adtc - addressed with data transfer */ case SD_SEND_SCR: - /* SD card returns SCR register as data. - SD core expect it in the response buffer, - after normal response. */ - request->buffer = - (unsigned char *) ((unsigned int) request->response + 5); - request->block_len = 8; - request->nob = 1; - /* fallthrough */ case SD_READ_DAT_UNTIL_STOP: case SD_READ_SINGLE_BLOCK: case SD_READ_MULTIPLE_BLOCK: -#if SD_DMA_ENABLE - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; -#endif - events = SD_EVENT_RX_DATA_DONE; - break; - case SD_SWITCH_FUNC: - if (request->arg == 0x2) - { - DEBUG("Use 4-bit bus width"); - use_4bit[drive] = 1; - } - else - { - DEBUG("Use 1-bit bus width"); - use_4bit[drive] = 0; - } - if (num_6[drive] < 2) - { -#if SD_DMA_ENABLE - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | - MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_READ; -#endif - events = SD_EVENT_RX_DATA_DONE; - } + /* These READ data */ break; case SD_WRITE_DAT_UNTIL_STOP: @@ -830,18 +800,14 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) case SD_WRITE_MULTIPLE_BLOCK: case SD_PROGRAM_CID: case SD_PROGRAM_CSD: -// case SD_LOCK_UNLOCK: -#if SD_DMA_ENABLE - cmdat |= - MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; -#else - cmdat |= MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE; -#endif - events = SD_EVENT_TX_DATA_DONE | SD_EVENT_PROG_DONE; + /* These WRITE data */ + cmdat |= MSC_CMDAT_WRITE; break; +// case SD_LOCK_UNLOCK: // can be a read or write, needs busy too. + case SD_STOP_TRANSMISSION: - events = SD_EVENT_PROG_DONE; + // cmdat |= MSC_CMDAT_STOP_ABORT; break; /* ac - no data transfer */ @@ -858,11 +824,9 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) cmdat |= MSC_CMDAT_BUSY; /* FALLTHRU */ case RESPONSE_R1: - case RESPONSE_R7: cmdat |= MSC_CMDAT_RESPONSE_R1; break; - case RESPONSE_R2_CID: - case RESPONSE_R2_CSD: + case RESPONSE_R2: cmdat |= MSC_CMDAT_RESPONSE_R2; break; case RESPONSE_R3: @@ -877,6 +841,9 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) case RESPONSE_R6: cmdat |= MSC_CMDAT_RESPONSE_R6; break; + case RESPONSE_R7: + cmdat |= MSC_CMDAT_RESPONSE_R7; + break; default: break; } @@ -885,6 +852,12 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) if (use_4bit[drive]) cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; + /* Set block length and nob if there is data */ + if (has_data) { + REG_MSC_BLKLEN(MSC_CHN(drive)) = request->block_len; + REG_MSC_NOB(MSC_CHN(drive)) = request->nob; + } + /* Set command index */ if (request->cmd == SD_CIM_RESET) REG_MSC_CMD(MSC_CHN(drive)) = SD_GO_IDLE_STATE; @@ -894,14 +867,10 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) /* Set argument */ REG_MSC_ARG(MSC_CHN(drive)) = request->arg; - /* Set block length and nob */ - REG_MSC_BLKLEN(MSC_CHN(drive)) = request->block_len; - REG_MSC_NOB(MSC_CHN(drive)) = request->nob; - /* Set command */ REG_MSC_CMDAT(MSC_CHN(drive)) = cmdat; - DEBUG("Send cmd %d cmdat: %x arg: %x resp %d", request->cmd, + DEBUG("%d Send cmd %d cmdat: %x arg: %x resp %d", drive, request->cmd, cmdat, request->arg, request->rtype); /* Start SD clock and send command to card */ @@ -917,11 +886,13 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) return SD_ERROR_TIMEOUT; yield(); } - REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ #endif /* Check for status */ retval = jz_sd_check_status(drive, request); +#if SD_INTERRUPT + REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ +#endif if (retval) return retval; @@ -933,18 +904,11 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) jz_sd_get_response(drive, request); /* Start data operation */ - if (events & (SD_EVENT_RX_DATA_DONE | SD_EVENT_TX_DATA_DONE)) - { - if (events & SD_EVENT_RX_DATA_DONE) - { - retval = jz_sd_receive_data(drive, request); - } - if (retval) - return retval; - - if (events & SD_EVENT_TX_DATA_DONE) - { + if (has_data) { + if (cmdat & MSC_CMDAT_WRITE) { retval = jz_sd_transmit_data(drive, request); + } else { + retval = jz_sd_receive_data(drive, request); } if (retval) return retval; @@ -959,8 +923,8 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) #endif } - /* Wait for Prog Done event */ - if (events & SD_EVENT_PROG_DONE) + /* Wait for Prog Done event if necessary */ + if (cmdat & (MSC_CMDAT_BUSY | MSC_CMDAT_WRITE)) { #if SD_INTERRUPT semaphore_wait(&sd_wakeup[drive], HZ * 5); @@ -994,7 +958,7 @@ static int jz_sd_chkcard(const int drive) #if SD_INTERRUPT void MSC2(void) /* SD_SLOT_1 */ { - logf("MSC2 interrupt"); + DEBUG("MSC2 interrupt"); if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_END_CMD_RES) { REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) = MSC_IREG_END_CMD_RES; /* clear flag */ @@ -1013,7 +977,7 @@ void MSC2(void) /* SD_SLOT_1 */ /* MSC interrupt handlers */ void MSC1(void) /* SD_SLOT_2 */ { - logf("MSC1 interrupt"); + DEBUG("MSC1 interrupt"); if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_END_CMD_RES) { REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) = MSC_IREG_END_CMD_RES; /* clear flag */ semaphore_release(&sd_wakeup[SD_SLOT_2]); @@ -1080,10 +1044,12 @@ static void sd_send_cmd(const int drive, struct sd_request *request, int cmd, un request->block_len = block_len; request->buffer = buffer; request->cnt = nob * block_len; + memset(&request->response, 0xa5, sizeof(request->response)); + request->result = SD_NO_RESPONSE; retval = jz_sd_exec_cmd(drive, request); if (retval) - request->result = retval; + request->result = retval; } static void sd_simple_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, @@ -1099,14 +1065,36 @@ static int sd_exec_acmd(const int drive, struct sd_request *request, int cmd, un sd_simple_cmd(drive, request, SD_APP_CMD, card[drive].rca, RESPONSE_R1); retval = sd_unpack_r1(request, &r1); + if (retval) + return retval; - if (!retval) - { - sd_simple_cmd(drive, request, cmd, arg, RESPONSE_R1); - retval = sd_unpack_r1(request, &r1); + if (!(r1.status & SD_R1_APP_CMD)) { + logf("ACMD not accepted\n"); + return SD_ERROR_ACMD_REJECT; } - return retval; + sd_simple_cmd(drive, request, cmd, arg, RESPONSE_R1); + return sd_unpack_r1(request, &r1); +} + +static int sd_exec_acmd_buf(const int drive, struct sd_request *request, int cmd, unsigned int arg, enum sd_rsp_t rtype, unsigned short nob, unsigned short block_len, unsigned char *buffer) +{ + struct sd_response_r1 r1; + int retval; + + sd_simple_cmd(drive, request, SD_APP_CMD, card[drive].rca, RESPONSE_R1); + retval = sd_unpack_r1(request, &r1); + if (retval) + return retval; + + if (!(r1.status & SD_R1_APP_CMD)) { + logf("ACMD not accepted\n"); + return SD_ERROR_ACMD_REJECT; + } + + sd_send_cmd(drive, request, cmd, arg, + nob, block_len, rtype, buffer); + return SD_NO_ERROR; } #define SD_INIT_DOING 0 @@ -1116,7 +1104,11 @@ static int sd_init_card_state(const int drive, struct sd_request *request) { struct sd_response_r1 r1; struct sd_response_r3 r3; - int retval, i, ocr = 0x40300000; + int retval, i, ocr = 0x40300000; /* SDXC, 3.2-3.4v */ + +#ifdef HAVE_SDUC + ocr |= 0x08000000; /* Add on SDUC */ +#endif switch (request->cmd) { @@ -1126,36 +1118,37 @@ static int sd_init_card_state(const int drive, struct sd_request *request) case SD_SEND_IF_COND: retval = sd_unpack_r1(request, &r1); - sd_simple_cmd(drive, request, SD_APP_CMD, 0, RESPONSE_R1); - break; +// if (retval) +// return SD_INIT_FAILED; - case SD_APP_CMD: - if (sd_unpack_r1(request, &r1)) + retval = sd_exec_acmd_buf(drive, request, SD_APP_OP_COND, ocr, + RESPONSE_R3, 0, 0, NULL); + if (retval) return SD_INIT_FAILED; - sd_simple_cmd(drive, request, SD_APP_OP_COND, ocr, RESPONSE_R3); break; - case SD_APP_OP_COND: retval = sd_unpack_r3(request, &r3); if (retval) return SD_INIT_FAILED; - DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr); + DEBUG("%d: read ocr value = 0x%08x", drive, r3.ocr); card[drive].ocr = r3.ocr; + // XXX for SDUC, check that B27+B30 of OCR are set. if(!(r3.ocr & SD_CARD_BUSY || ocr == 0)) { + /* Re-issue AP_OP_COND */ sleep(HZ / 100); - sd_simple_cmd(drive, request, SD_APP_CMD, 0, RESPONSE_R1); + retval = sd_exec_acmd_buf(drive, request, SD_APP_OP_COND, ocr, + RESPONSE_R3, 0, 0, NULL); + if (retval) + return SD_INIT_FAILED; } else { - /* Set the data bus width to 4 bits */ - use_4bit[drive] = 1; - sd_simple_cmd(drive, request, SD_ALL_SEND_CID, 0, RESPONSE_R2_CID); + sd_simple_cmd(drive, request, SD_ALL_SEND_CID, 0, RESPONSE_R2); } break; - case SD_ALL_SEND_CID: if (request->result) return SD_INIT_FAILED; @@ -1164,22 +1157,22 @@ static int sd_init_card_state(const int drive, struct sd_request *request) card[drive].cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | (request->response[3+i*4]<< 8) | request->response[4+i*4]); - logf("CID: %08lx%08lx%08lx%08lx", card[drive].cid[0], card[drive].cid[1], card[drive].cid[2], card[drive].cid[3]); + logf("%d CID: %08lx%08lx%08lx%08lx", drive, card[drive].cid[0], card[drive].cid[1], card[drive].cid[2], card[drive].cid[3]); sd_simple_cmd(drive, request, SD_SEND_RELATIVE_ADDR, 0, RESPONSE_R6); break; case SD_SEND_RELATIVE_ADDR: retval = sd_unpack_r6(request, &r1, &card[drive].rca); - card[drive].rca = card[drive].rca << 16; DEBUG("sd_init_card_state: Get RCA from SD: 0x%04lx Status: %x", card[drive].rca, r1.status); + card[drive].rca = card[drive].rca << 16; if (retval) { - DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", + logf("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", retval); return SD_INIT_FAILED; } - sd_simple_cmd(drive, request, SD_SEND_CSD, card[drive].rca, RESPONSE_R2_CSD); + sd_simple_cmd(drive, request, SD_SEND_CSD, card[drive].rca, RESPONSE_R2); break; case SD_SEND_CSD: @@ -1191,13 +1184,33 @@ static int sd_init_card_state(const int drive, struct sd_request *request) sd_parse_csd(&card[drive]); - logf("CSD: %08lx%08lx%08lx%08lx", card[drive].csd[0], card[drive].csd[1], card[drive].csd[2], card[drive].csd[3]); - DEBUG("SD card is ready"); + logf("%d CSD: %08lx%08lx%08lx%08lx", drive, card[drive].csd[0], card[drive].csd[1], card[drive].csd[2], card[drive].csd[3]); + +#if 0 // XXX SCR is not working yet + retval = sd_exec_acmd_buf(drive, request, SD_SEND_SCR, 0, + RESPONSE_R1, + 1, 8, &request->response[5]); + if (!retval) + retval = sd_unpack_r1(request, &r1); + // XXX check retval? + break; + case SD_SEND_SCR: +// if (request->result) +// return SD_INIT_FAILED; + for(i=0; i<2; i++) + card[drive].scr[i] = ((request->buffer[0+i*4]<<24) | (request->buffer[1+i*4]<<16) | + (request->buffer[2+i*4]<< 8) | request->buffer[3+i*4]); + + DEBUG("%d SCR: %08lx%08lx", drive, card[drive].scr[0], card[drive].scr[1]); + + use_sbc[drive] = card[drive].scr[0] & 2; +#endif + + logf("SD card %d is ready", drive); jz_sd_set_clock(drive, SD_CLOCK_FAST); return SD_INIT_PASSED; - default: - DEBUG("sd_init_card_state: error! Illegal last cmd %d", request->cmd); + logf("sd_init_card_state: error! Illegal last cmd %d", request->cmd); return SD_INIT_FAILED; } @@ -1212,8 +1225,11 @@ static int sd_switch(const int drive, struct sd_request *request, int mode, int mode = !!mode; value &= 0xF; arg = (mode << 31 | 0x00FFFFFF); - arg &= ~(0xF << (group * 4)); - arg |= value << (group * 4); + if (mode) { + group--; + arg &= ~(0xF << (group * 4)); + arg |= value << (group * 4); + } sd_send_cmd(drive, request, SD_SWITCH_FUNC, arg, 1, 64, RESPONSE_R1, resp); return 0; @@ -1242,7 +1258,7 @@ static int sd_switch_hs(const int drive, struct sd_request *request) { unsigned int status[64 / 4]; - sd_switch(drive, request, 1, 0, 1, (unsigned char*) status); + sd_switch(drive, request, 1, 1, 1, (unsigned char*) status); return 0; } @@ -1267,10 +1283,16 @@ static int sd_select_card(const int drive) jz_sd_set_clock(drive, SD_CLOCK_HIGH); } } - num_6[drive] = 3; - retval = sd_exec_acmd(drive, &request, SD_SET_BUS_WIDTH, 2); - if (retval) - return retval; + + bool sup_4bit = 1; // XXX check against SCR + + if (sup_4bit) { + retval = sd_exec_acmd(drive, &request, SD_SET_BUS_WIDTH, 2); + if (retval) + return retval; + use_4bit[drive] = 2; + DEBUG("Use 4-bit bus width"); + } retval = sd_exec_acmd(drive, &request, SD_SET_CLR_CARD_DETECT, 0); if (retval) return retval; @@ -1280,6 +1302,11 @@ static int sd_select_card(const int drive) return 0; } +static inline bool card_detect_target(const int drive) +{ + return (jz_sd_chkcard(drive) == 1); +} + static int __sd_init_device(const int drive) { int retval = 0; @@ -1289,13 +1316,16 @@ static int __sd_init_device(const int drive) /* Initialise card data as blank */ memset(&card[drive], 0, sizeof(tCardInfo)); - num_6[drive] = 0; use_4bit[drive] = 0; active[drive] = 0; /* reset mmc/sd controller */ jz_sd_hardware_init(drive); + /* Don't bother if card isn't present */ + if (!card_detect_target(drive)) + return 0; + sd_simple_cmd(drive, &init_req, SD_CIM_RESET, 0, RESPONSE_NONE); sd_simple_cmd(drive, &init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); @@ -1364,11 +1394,6 @@ int sd_init(void) return 0; } -static inline bool card_detect_target(const int drive) -{ - return (jz_sd_chkcard(drive) == 1); -} - tCardInfo* card_get_info_target(const int drive) { return &card[drive]; @@ -1423,18 +1448,31 @@ int sd_transfer_sectors(IF_MD(const int drive,) sector_t start, int count, void* if ((retval = sd_unpack_r1(&request, &r1))) goto err; - // XXX 64-bit + if (use_sbc[drive] && count > 1) { + sd_simple_cmd(drive, &request, SD_SET_BLOCK_COUNT, count, RESPONSE_R1); + if ((retval = sd_unpack_r1(&request, &r1))) + goto err; + } + +#ifdef STORAGE_64BIT_SECTOR + // XXX check card[drive].ocr, b27+b30 == 11 + if (card[drive].numblocks > 0xffffffffULL) { + uint32_t upper = start >> 32; + sd_simple_cmd(drive, &request, SD_UC_ADDRESS_EXTENSION, upper, RESPONSE_R1); + if ((retval = sd_unpack_r1(&request, &r1))) + goto err; + } +#endif + sd_send_cmd(drive, &request, (count > 1) ? (write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK) : (write ? SD_WRITE_BLOCK : SD_READ_SINGLE_BLOCK), card[drive].sd2plus ? start : (start * SD_BLOCK_SIZE), count, SD_BLOCK_SIZE, RESPONSE_R1, buf); - if ((retval = sd_unpack_r1(&request, &r1))) - goto err; + retval = sd_unpack_r1(&request, &r1); - if (count > 1) - { + if (retval || (!use_sbc[drive] && count > 1)) { sd_simple_cmd(drive, &request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); retval = sd_unpack_r1(&request, &r1); if (!write && retval == SD_ERROR_OUT_OF_RANGE) From e8b75a52aba3af6b606d5f5fda0bb5cf3a6afa90 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 17 Feb 2026 14:36:39 -0500 Subject: [PATCH 66/75] sansafuzeplus: Support up to 96KHz playback. It was limited to 48KHz due to insufficient IRAM but at some point in the last five years or so that must have changed. Change-Id: Ia893ed5e1f3026158daad77991c3d9cca2fed97c --- firmware/export/config/sansafuzeplus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/export/config/sansafuzeplus.h b/firmware/export/config/sansafuzeplus.h index 190d5a61b8..f8e05be108 100644 --- a/firmware/export/config/sansafuzeplus.h +++ b/firmware/export/config/sansafuzeplus.h @@ -19,7 +19,7 @@ // HW can do it but we don't have the IRAM for mix buffers //#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192 -#define HW_SAMPR_CAPS SAMPR_CAP_ALL_48 +#define HW_SAMPR_CAPS SAMPR_CAP_ALL_96 /* define this if you have recording possibility */ #define HAVE_RECORDING From 41567532a1da82d25a70553a5b1f3e6e35c82490 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Tue, 17 Feb 2026 17:32:03 -0500 Subject: [PATCH 67/75] jz47xx: Further SD driver improvements * Get rid of the SD_CIM_RESET meta-command and put all reset/init logic into one place * Don't double-issue the SD_GO_IDLE_STATE command * Explicitly set lowest speed upon reset Change-Id: I5abfe9f64997e39087b8a77d525f90c77733a1a8 --- .../mips/ingenic_jz47xx/ata-sd-jz4740.c | 34 +++------------ .../mips/ingenic_jz47xx/ata-sd-jz4760.c | 41 ++++--------------- 2 files changed, 13 insertions(+), 62 deletions(-) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c index e20c681c1e..9883f2bf39 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4740.c @@ -92,10 +92,6 @@ enum sd_result_t #define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ #define SD_CLOCK_HIGH 48000000 /* 48 MHz for SD Cards */ -/* Extra commands for state control */ -/* Use negative numbers to disambiguate */ -#define SD_CIM_RESET -1 - /* Proprietary commands, illegal/reserved according to SD Specification 2.00 */ /* class 1 */ #define SD_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ @@ -650,24 +646,10 @@ static int jz_sd_exec_cmd(struct sd_request *request) /* Stop clock when programming things */ jz_sd_stop_clock(); /* stop SD clock */ - if (request->cmd == SD_CIM_RESET) { - /* On reset, 1-bit bus width */ - use_4bit = 0; - - /* Reset MMC/SD controller */ - __msc_reset(); - - /* On reset, drop SD clock down */ - jz_sd_set_clock(MMC_CLOCK_SLOW); - - /* On reset, stop SD clock */ - jz_sd_stop_clock(); - } - /* Generic handling for all requests with data rx/tx */ if (has_data) { cmdat |= MSC_CMDAT_DATA_EN; -// if (request->nob > 1 && use_sbc[drive]) +// if (request->nob > 1 && use_sbc) // cmdat |= MSC_CMDAT_SEND_AS_STOP; #ifdef SD_DMA_ENABLE if (request->cnt >= 512) @@ -689,12 +671,10 @@ static int jz_sd_exec_cmd(struct sd_request *request) /* Per-command type handling */ switch (request->cmd) { - /* SD core extra command */ - case SD_CIM_RESET: - cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ - break; /* bc - broadcast - no response */ case SD_GO_IDLE_STATE: + cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ + /* Intentional Fallthrough */ case SD_SET_DSR: break; @@ -767,10 +747,7 @@ static int jz_sd_exec_cmd(struct sd_request *request) } /* Set command index */ - if (request->cmd == SD_CIM_RESET) - REG_MSC_CMD = SD_GO_IDLE_STATE; - else - REG_MSC_CMD = request->cmd; + REG_MSC_CMD = request->cmd; /* Set argument */ REG_MSC_ARG = request->arg; @@ -915,6 +892,7 @@ static void jz_sd_hardware_init(void) SD_RESET(); /* reset mmc/sd controller */ SD_IRQ_MASK(); /* mask all IRQs */ jz_sd_stop_clock(); /* stop SD clock */ + jz_sd_set_clock(MMC_CLOCK_SLOW); /* Drop to lowest speed */ #ifdef SD_DMA_ENABLE // __cpm_start_dmac(); // __dmac_enable_module(); @@ -1209,6 +1187,7 @@ static int __sd_init_device(void) memset(&card, 0, sizeof(tCardInfo)); use_4bit = 0; + use_sbc = 0; /* reset mmc/sd controller */ jz_sd_hardware_init(); @@ -1216,7 +1195,6 @@ static int __sd_init_device(void) if (!card_detect_target()) return 0; - sd_simple_cmd(&init_req, SD_CIM_RESET, 0, RESPONSE_NONE); sd_simple_cmd(&init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); sleep(HZ/2); /* Give the card/controller some rest */ diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index 7a3b450e65..4b9e0387b2 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c @@ -107,10 +107,6 @@ enum sd_result_t #define SD_CLOCK_FAST 24000000 /* 24 MHz for SD Cards */ #define SD_CLOCK_HIGH 48000000 /* 48 MHz for SD Cards */ -/* Extra commands for state control */ -/* Use negative numbers to disambiguate */ -#define SD_CIM_RESET -1 - /* Proprietary commands, illegal/reserved according to SD Specification 2.00 */ /* class 1 */ #define SD_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ @@ -729,26 +725,6 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) jz_sd_stop_clock(drive); /* stop SD clock */ #endif - if (request->cmd == SD_CIM_RESET) { - /* On reset, 1-bit bus width */ - use_4bit[drive] = 0; - - /* On reset, stop SD clock */ - jz_sd_stop_clock(drive); - - /* Reset MMC/SD controller */ - __msc_reset(MSC_CHN(drive)); - - /* Drop SD clock down to lowest speed */ - jz_sd_set_clock(drive, MMC_CLOCK_SLOW); - -#if SD_AUTO_CLOCK - /* Re-enable clocks */ - REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_START; - REG_MSC_LPM(drive) = MSC_SET_LPM; -#endif - } - /* Generic handling for all requests with data rx/tx */ if (has_data) { cmdat |= MSC_CMDAT_DATA_EN; @@ -771,12 +747,11 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) /* Per-command type handling */ switch (request->cmd) { - /* SD core extra command */ - case SD_CIM_RESET: - cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ - break; /* bc - broadcast - no response */ case SD_GO_IDLE_STATE: + cmdat |= MSC_CMDAT_INIT; /* Initialization sequence sent prior to command */ + /* Intentional Fallthrough */ + case SD_SET_DSR: break; @@ -792,7 +767,7 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) case SD_READ_SINGLE_BLOCK: case SD_READ_MULTIPLE_BLOCK: case SD_SWITCH_FUNC: - /* These READ data */ + /* These READ data */ break; case SD_WRITE_DAT_UNTIL_STOP: @@ -859,10 +834,7 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) } /* Set command index */ - if (request->cmd == SD_CIM_RESET) - REG_MSC_CMD(MSC_CHN(drive)) = SD_GO_IDLE_STATE; - else - REG_MSC_CMD(MSC_CHN(drive)) = request->cmd; + REG_MSC_CMD(MSC_CHN(drive)) = request->cmd; /* Set argument */ REG_MSC_ARG(MSC_CHN(drive)) = request->arg; @@ -1029,6 +1001,7 @@ static void jz_sd_hardware_init(const int drive) #else jz_sd_stop_clock(drive); /* stop SD clock */ #endif + jz_sd_set_clock(drive, MMC_CLOCK_SLOW); /* Drop to lowest speed */ } static void sd_send_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, @@ -1317,6 +1290,7 @@ static int __sd_init_device(const int drive) memset(&card[drive], 0, sizeof(tCardInfo)); use_4bit[drive] = 0; + use_sbc[drive] = 0; active[drive] = 0; /* reset mmc/sd controller */ @@ -1326,7 +1300,6 @@ static int __sd_init_device(const int drive) if (!card_detect_target(drive)) return 0; - sd_simple_cmd(drive, &init_req, SD_CIM_RESET, 0, RESPONSE_NONE); sd_simple_cmd(drive, &init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); sleep(HZ/2); /* Give the card/controller some rest */ From c199d9a3692574dc3cfe328d793c5498338470d8 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 18 Feb 2026 14:53:52 +0200 Subject: [PATCH 68/75] playback: fix single mode briefly plays audio from the next track before pausing Change-Id: Iab82427d5429210701e65103325f72c7919685e1 --- apps/pcmbuf.c | 11 ++++++++++- apps/playback.c | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index b32cb4c429..6bd39d4dc0 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c @@ -799,8 +799,10 @@ static void pcmbuf_pcm_callback(const void **start, size_t *size) if (desc) { + bool track_change = index == chunk_transidx; + /* If last chunk in the track, notify of track change */ - if (index == chunk_transidx) + if (track_change) { chunk_transidx = INVALID_BUF_INDEX; audio_pcmbuf_track_change(true); @@ -808,6 +810,13 @@ static void pcmbuf_pcm_callback(const void **start, size_t *size) /* Free it for reuse */ chunk_ridx = index = index_next(index); + + if (track_change && !audio_pcmbuf_may_play()) + { + current_desc = NULL; + *size = 0; + return; + } } /*- Process the new one -*/ diff --git a/apps/playback.c b/apps/playback.c index 22c19c4755..bdd2cfe14f 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -325,6 +325,7 @@ static unsigned int track_event_flags = TEF_NONE; /* (A, O-) */ static int skip_offset = 0; /* (A, O) */ static bool track_skip_is_manual = false; +static bool pause_on_track_change = false; /* Track change notification */ static struct @@ -1502,7 +1503,7 @@ static bool halt_decoding_track(bool stop) codec_skip_pending = false; codec_seeking = false; - + pause_on_track_change = false; return retval; } @@ -2733,12 +2734,6 @@ static void audio_finalise_track_change(void) { buf_read_cuesheet(info.cuesheet_hid); track_id3 = bufgetid3(info.id3_hid); - - if (single_mode_do_pause(info.id3_hid)) - { - play_status = PLAY_PAUSED; - pcmbuf_pause(true); - } } /* Sync the next track information */ have_info = track_list_current(1, &info); @@ -2934,8 +2929,9 @@ static void audio_on_codec_complete(int status) int id3_hid = 0; if (audio_can_change_track(&trackstat, &id3_hid)) { + pause_on_track_change = single_mode_do_pause(id3_hid); audio_begin_track_change( - single_mode_do_pause(id3_hid) + pause_on_track_change ? TRACK_CHANGE_END_OF_DATA : TRACK_CHANGE_AUTO, trackstat); } @@ -2954,6 +2950,12 @@ static void audio_on_codec_seek_complete(void) (Q_AUDIO_TRACK_CHANGED) */ static void audio_on_track_changed(void) { + if (pause_on_track_change) + { + play_status = PLAY_PAUSED; + pause_on_track_change = false; + } + /* Finish whatever is pending so that the WPS is in sync */ audio_finalise_track_change(); @@ -3850,7 +3852,7 @@ void audio_pcmbuf_track_change(bool pcmbuf) /* May pcmbuf start PCM playback when the buffer is full enough? */ bool audio_pcmbuf_may_play(void) { - return play_status == PLAY_PLAYING && !ff_rw_mode; + return play_status == PLAY_PLAYING && !ff_rw_mode && !pause_on_track_change; } From e5e82820f64cd3a3075260af3a5fc6e9006d5afe Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 15 Feb 2026 21:14:41 +0000 Subject: [PATCH 69/75] echoplayer: re-enable 50 MHZ SDMMC bus The problem with drive strength and things not working reliably at 50 MHz turned out to be entirely caused by the ESD diodes on the data/command/clock lines, which have a whopping 200-300 pF junction capacitance -- 6-10x higher than the 30 pF limit given by the MMC spec. After desoldering the diodes the bus seems stable at 50 MHz and with any drive strength (note MEDIUM is still fast enough even for 50 MHz, so the drive strength is unchanged). Change-Id: If9847ee4145f5ed2f7e172cfa89acad0737a897f --- firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c index 3b3b860680..803b7cae2b 100644 --- a/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c @@ -46,7 +46,8 @@ static const struct sdmmc_host_config sdmmc_config INITDATA_ATTR = { .bus_widths = SDMMC_BUS_WIDTH_1BIT | SDMMC_BUS_WIDTH_4BIT, .bus_clocks = SDMMC_BUS_CLOCK_400KHZ | - SDMMC_BUS_CLOCK_25MHZ, + SDMMC_BUS_CLOCK_25MHZ | + SDMMC_BUS_CLOCK_50MHZ, .max_nr_blocks = 65535, .is_removable = true, }; From af9a9bd9d494e5b291ad9004d6a8033ff43f94ef Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Wed, 11 Feb 2026 10:10:07 +0000 Subject: [PATCH 70/75] echoplayer: increase LCD RGB & SPI output speed to medium At low speed there's some occasional corrupted pixels, most visible on album art and such; this goes away at medium speed. Change-Id: Ice4eaec4284023d2d3f5c571b242cb27ebc26da9 --- firmware/target/arm/stm32/echoplayer/system-echoplayer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/target/arm/stm32/echoplayer/system-echoplayer.c b/firmware/target/arm/stm32/echoplayer/system-echoplayer.c index 284f7bc2ab..0dc45ecbda 100644 --- a/firmware/target/arm/stm32/echoplayer/system-echoplayer.c +++ b/firmware/target/arm/stm32/echoplayer/system-echoplayer.c @@ -44,9 +44,9 @@ #define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP) #define F_SDMMC1CK GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) #define F_SAI1 GPIOF_FUNCTION(6, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) -#define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) -#define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) -#define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) +#define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) +#define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) +#define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) #define F_LPTIM4_OUT GPIOF_FUNCTION(3, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) #define F_LPTIM1_OUT GPIOF_FUNCTION(1, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) From 6f302083b58841d4270faecd8e368becf04de4d8 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 19 Feb 2026 07:24:52 -0500 Subject: [PATCH 71/75] cleanup: Get rid of erroneous execututable bit on various source files Change-Id: I6382ba56dc6d99189c8647b010208c33fc2da7ca --- apps/plugins/pacbox/pacbox.c | 0 apps/plugins/picross/picross_default.picross | 0 lib/rbcodec/codecs/libwma/wmadata.h | 0 lib/rbcodec/codecs/libwma/wmadeci.c | 0 lib/rbcodec/codecs/libwmapro/quant.h | 0 lib/rbcodec/codecs/libwmapro/wmaprodec.c | 0 utils/cmake/QtTest.cmake | 0 utils/cmake/QtTestAddTests.cmake | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 apps/plugins/pacbox/pacbox.c mode change 100755 => 100644 apps/plugins/picross/picross_default.picross mode change 100755 => 100644 lib/rbcodec/codecs/libwma/wmadata.h mode change 100755 => 100644 lib/rbcodec/codecs/libwma/wmadeci.c mode change 100755 => 100644 lib/rbcodec/codecs/libwmapro/quant.h mode change 100755 => 100644 lib/rbcodec/codecs/libwmapro/wmaprodec.c mode change 100755 => 100644 utils/cmake/QtTest.cmake mode change 100755 => 100644 utils/cmake/QtTestAddTests.cmake diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c old mode 100755 new mode 100644 diff --git a/apps/plugins/picross/picross_default.picross b/apps/plugins/picross/picross_default.picross old mode 100755 new mode 100644 diff --git a/lib/rbcodec/codecs/libwma/wmadata.h b/lib/rbcodec/codecs/libwma/wmadata.h old mode 100755 new mode 100644 diff --git a/lib/rbcodec/codecs/libwma/wmadeci.c b/lib/rbcodec/codecs/libwma/wmadeci.c old mode 100755 new mode 100644 diff --git a/lib/rbcodec/codecs/libwmapro/quant.h b/lib/rbcodec/codecs/libwmapro/quant.h old mode 100755 new mode 100644 diff --git a/lib/rbcodec/codecs/libwmapro/wmaprodec.c b/lib/rbcodec/codecs/libwmapro/wmaprodec.c old mode 100755 new mode 100644 diff --git a/utils/cmake/QtTest.cmake b/utils/cmake/QtTest.cmake old mode 100755 new mode 100644 diff --git a/utils/cmake/QtTestAddTests.cmake b/utils/cmake/QtTestAddTests.cmake old mode 100755 new mode 100644 From 5cf3c6bf9ac612ad0fca58a6d71f3cda0c9bb237 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Mon, 16 Feb 2026 21:14:38 +0200 Subject: [PATCH 72/75] Add ability to specify autostart plugin path and argument Extend AUTOROCK define functionality to allow specifying both the autostart plugin path and its argument. Example: #define AUTOROCK VIEWERS_DATA_DIR "/imageviewer.rock" #define AUTOROCK_ARG "/jpegs/sample.jpg" Change-Id: Icc41bceac676e8db17d3a63baefdf96e3023c181 --- apps/main.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/apps/main.c b/apps/main.c index c25847430f..009f2e96ac 100644 --- a/apps/main.c +++ b/apps/main.c @@ -153,7 +153,10 @@ #endif #endif /* SDL */ -/*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */ +// #define AUTOROCK /* define this to check for "autostart.rock" on boot */ +/* Alternatively, you can define autostart plugin path and its argument: */ +// #define AUTOROCK VIEWERS_DATA_DIR"/imageviewer.rock" +// #define AUTOROCK_ARG "/jpegs/sample.jpg" static void init(void); /* main(), and various functions called by main() and init() may be @@ -214,17 +217,25 @@ int main(void) #ifdef AUTOROCK { - char filename[MAX_PATH]; - const char *file = + const char *file = ""AUTOROCK; + file = *file + ? file + : #ifdef APPLICATION ROCKBOX_DIR #else PLUGIN_APPS_DIR #endif "/autostart.rock"; - if(file_exists(file)) /* no complaint if it doesn't exist */ + if (file_exists(file)) /* no complaint if it doesn't exist */ { - plugin_load(file, NULL); /* start if it does */ + plugin_load(file, +#ifdef AUTOROCK_ARG + AUTOROCK_ARG +#else + NULL +#endif + ); /* start if it does */ } } #endif /* #ifdef AUTOROCK */ From 3373ed674421e6c917bcece4f2c524e28f0a56e1 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Thu, 19 Feb 2026 12:28:19 +0200 Subject: [PATCH 73/75] playback: fix single mode handling with auto frequency switch enabled Fix single mode fails to pause between tracks with different sample rates with auto frequency switch enabled. Fixup for c199d9a3 Change-Id: I51bbd33a15be16b711b3a8e46c0cab1b15a93705 --- apps/playback.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/apps/playback.c b/apps/playback.c index bdd2cfe14f..0e8871c96c 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -2734,6 +2734,16 @@ static void audio_finalise_track_change(void) { buf_read_cuesheet(info.cuesheet_hid); track_id3 = bufgetid3(info.id3_hid); + + /* When pause_on_track_change is calculated, next track_info may be missing + * (due to a low buffer or an automatic directory change), + * so we need to recalculate it. */ + if (pause_on_track_change || single_mode_do_pause(info.id3_hid)) + { + play_status = PLAY_PAUSED; + pcmbuf_pause(true); + pause_on_track_change = false; + } } /* Sync the next track information */ have_info = track_list_current(1, &info); @@ -2810,11 +2820,16 @@ static void audio_monitor_end_of_playlist(void) } /* Does this track have an entry allocated? */ -static bool audio_can_change_track(int *trackstat, int *id3_hid) +static bool audio_can_change_track(int *trackstat, enum pcm_track_change_type *type) { struct track_info info; bool have_track = track_list_advance_current(1, &info); - *id3_hid = info.id3_hid; + + pause_on_track_change = have_track && single_mode_do_pause(info.id3_hid); + *type = pause_on_track_change + ? TRACK_CHANGE_END_OF_DATA + : TRACK_CHANGE_AUTO; + if (!have_track || info.audio_hid < 0) { bool end_of_playlist = false; @@ -2823,8 +2838,8 @@ static bool audio_can_change_track(int *trackstat, int *id3_hid) { if (filling == STATE_STOPPED) { - audio_begin_track_change(TRACK_CHANGE_END_OF_DATA, *trackstat); - return false; + *type = TRACK_CHANGE_END_OF_DATA; + return true; } /* Track load is not complete - it might have stopped on a @@ -2926,14 +2941,10 @@ static void audio_on_codec_complete(int status) track_event_flags = TEF_AUTO_SKIP; skip_pending = TRACK_SKIP_AUTO; - int id3_hid = 0; - if (audio_can_change_track(&trackstat, &id3_hid)) + enum pcm_track_change_type type; + if (audio_can_change_track(&trackstat, &type)) { - pause_on_track_change = single_mode_do_pause(id3_hid); - audio_begin_track_change( - pause_on_track_change - ? TRACK_CHANGE_END_OF_DATA - : TRACK_CHANGE_AUTO, trackstat); + audio_begin_track_change(type, trackstat); } } @@ -2950,12 +2961,6 @@ static void audio_on_codec_seek_complete(void) (Q_AUDIO_TRACK_CHANGED) */ static void audio_on_track_changed(void) { - if (pause_on_track_change) - { - play_status = PLAY_PAUSED; - pause_on_track_change = false; - } - /* Finish whatever is pending so that the WPS is in sync */ audio_finalise_track_change(); From 8013aa2370108771bac4085c674fb87fda590f22 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Wed, 18 Feb 2026 10:47:12 +0000 Subject: [PATCH 74/75] audio: remove pcm_sw_volume include from sound.c Drop the include because nothing here needs it. Change-Id: Iad7ada127589c649359b3eea8bf2a21f5f00a344 --- firmware/sound.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/firmware/sound.c b/firmware/sound.c index 6f6a37cca3..0e43f38f5a 100644 --- a/firmware/sound.c +++ b/firmware/sound.c @@ -30,10 +30,6 @@ #include "settings.h" /* sound_current */ #endif -#ifdef HAVE_SW_VOLUME_CONTROL -#include "pcm_sw_volume.h" -#endif /* HAVE_SW_VOLUME_CONTROL */ - /* Define sound_setting_entries table */ #define AUDIOHW_SOUND_SETTINGS_ENTRIES #include "audiohw_settings.h" From 0b3a5ab1e663f96ca02b39b99f18fc857224eac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louren=C3=A7o=20Soares?= Date: Thu, 19 Feb 2026 20:02:12 +0000 Subject: [PATCH 75/75] plugin lrcplayer: Added manual scrolling feature lrcplayer currently automatically scrolls the lyrics for you, as it assumes that there is sync information in the lyrics. In the case where there aren't (like for ID3V2 USLT tags), the plugin will automatically assume timestamps and will scroll automatically. This commit adds an option in the Display Menu to allow automatic scrolling to be disabled. When disabled, you can scroll the lyrics using the volume keys (like you would on the iPod's OS). Change-Id: I87ef27fd2b84c97374bdfd0e47f4c00ddb4bc85e --- apps/plugins/lrcplayer.c | 105 +++++++++++++++++++++++++++------------ docs/CREDITS | 1 + 2 files changed, 74 insertions(+), 32 deletions(-) diff --git a/apps/plugins/lrcplayer.c b/apps/plugins/lrcplayer.c index 9102f03264..c357ff1b57 100644 --- a/apps/plugins/lrcplayer.c +++ b/apps/plugins/lrcplayer.c @@ -74,6 +74,7 @@ struct preferences { bool wrap; bool wipe; bool active_one_line; + bool autoscroll; int align; /* 0: left, 1: center, 2: right */ bool statusbar_on; bool display_title; @@ -99,6 +100,7 @@ static const char *extentions[NUM_TYPES] = { static struct lrc_info { struct mp3entry *id3; long elapsed; + long scroll; long length; long ff_rewind; int audio_status; @@ -1643,21 +1645,25 @@ static int display_lrc_line(struct lrc_line *lrc_line, int ypos, int i) struct screen *display = rb->screens[i]; struct lrc_word *lrc_word; struct lrc_brpos *lrc_brpos; - long time_start, time_end, elapsed; + long time_start, time_end, time_elapsed, elapsed; int count, width, nword; int xpos; const char *str; bool active_line; + if (!prefs.autoscroll) + time_elapsed = current.scroll; + else + time_elapsed = current.elapsed; time_start = get_time_start(lrc_line); time_end = get_time_start(lrc_line->next); - active_line = (time_start <= current.elapsed - && time_end > current.elapsed); + active_line = (time_start <= time_elapsed + && time_end > time_elapsed); if (!lrc_line->width) { /* empty line. draw bar during interval. */ - long rin = current.elapsed - time_start; + long rin = time_elapsed - time_start; long len = time_end - time_start; if (current.wipe && active_line && len >= 3500) { @@ -1697,12 +1703,12 @@ static int display_lrc_line(struct lrc_line *lrc_line, int ypos, int i) else time_end = get_time_start(lrc_line->next); - if (time_start > current.elapsed || !active_line) + if (time_start > time_elapsed || !active_line) { /* inactive */ elapsed = 0; } - else if (!current.wipe || time_end <= current.elapsed) + else if (!current.wipe || time_end <= time_elapsed) { /* active whole word */ elapsed = lrc_word->width; @@ -1710,7 +1716,7 @@ static int display_lrc_line(struct lrc_line *lrc_line, int ypos, int i) else { /* wipe word */ - long rin = current.elapsed - time_start; + long rin = time_elapsed - time_start; long len = time_end - time_start; elapsed = rin * lrc_word->width / len; } @@ -1727,27 +1733,30 @@ static int display_lrc_line(struct lrc_line *lrc_line, int ypos, int i) c = word_count; w = word_width; } - if (elapsed <= 0) + if (prefs.autoscroll) { - set_to_inactive(display); - } - else if (elapsed < w) - { - /* wipe text */ - display->fillrect(xpos, ypos, elapsed, font_ui_height); - set_to_inactive(display); - display->fillrect(xpos+elapsed, ypos, - w-elapsed, font_ui_height); + if (elapsed <= 0) + { + set_to_inactive(display); + } + else if (elapsed < w) + { + /* wipe text */ + display->fillrect(xpos, ypos, elapsed, font_ui_height); + set_to_inactive(display); + display->fillrect(xpos+elapsed, ypos, + w-elapsed, font_ui_height); #if (LCD_DEPTH > 1) #ifdef HAVE_REMOTE_LCD - if (display->screen_type == SCREEN_REMOTE) - display->set_drawmode(DRMODE_INVERSEVID); - else + if (display->screen_type == SCREEN_REMOTE) + display->set_drawmode(DRMODE_INVERSEVID); + else #endif - display->set_drawmode(DRMODE_BG); + display->set_drawmode(DRMODE_BG); #else - display->set_drawmode(DRMODE_INVERSEVID); + display->set_drawmode(DRMODE_INVERSEVID); #endif + } } rb->strlcpy(temp_buf, str, c+1); display->putsxy(xpos, ypos, temp_buf); @@ -1777,13 +1786,18 @@ static int display_lrc_line(struct lrc_line *lrc_line, int ypos, int i) static void display_lrcs(void) { - long time_start, time_end, rin, len; + long time_start, time_end, time_elapsed, rin, len; int nline[NB_SCREENS] = {0}; struct lrc_line *lrc_center = current.ll_head; if (!lrc_center) return; - while (get_time_start(lrc_center->next) <= current.elapsed) + if (!prefs.autoscroll) + time_elapsed = current.scroll; + else + time_elapsed = current.elapsed; + + while (get_time_start(lrc_center->next) <= time_elapsed) { nline[SCREEN_MAIN] += lrc_center->nline[SCREEN_MAIN]; #ifdef HAVE_REMOTE_LCD @@ -1794,7 +1808,7 @@ static void display_lrcs(void) time_start = get_time_start(lrc_center); time_end = get_time_start(lrc_center->next); - rin = current.elapsed - time_start; + rin = time_elapsed - time_start; len = time_end - time_start; struct screen *display; @@ -1810,9 +1824,9 @@ static void display_lrcs(void) y = (nblines-1)/2; if (rin < 0) { - /* current.elapsed < time of first lrc */ + /* time_elapsed < time of first lrc */ if (!current.wipe) - ypos = (time_start - current.elapsed) + ypos = (time_start - time_elapsed) * font_ui_height / time_start; else y++; @@ -1849,7 +1863,7 @@ static void display_lrcs(void) ypos = display_lrc_line(lrc_line, ypos, i); lrc_line = lrc_line->next; } - if (!lrc_line && ypos < vp_lyrics[i].height) + if (!lrc_line && ypos < vp_lyrics[i].height && prefs.autoscroll) display->putsxy(0, ypos, "[end]"); display->update_viewport(); @@ -2150,6 +2164,7 @@ static void load_or_save_settings(bool save) { TYPE_BOOL, 0, 1, { .bool_p = &prefs.wipe }, "wipe", NULL }, { TYPE_BOOL, 0, 1, { .bool_p = &prefs.active_one_line }, "active one line", NULL }, + { TYPE_BOOL, 0, 1, { .bool_p = &prefs.autoscroll }, "autoscroll", NULL }, { TYPE_INT, 0, 2, { .int_p = &prefs.align }, "align", NULL }, { TYPE_BOOL, 0, 1, { .bool_p = &prefs.statusbar_on }, "statusbar on", NULL }, @@ -2179,6 +2194,7 @@ static void load_or_save_settings(bool save) prefs.wrap = true; prefs.wipe = true; prefs.active_one_line = false; + prefs.autoscroll = true; prefs.align = 1; /* center */ prefs.statusbar_on = false; prefs.display_title = true; @@ -2264,6 +2280,7 @@ static bool lrc_display_menu(void) LRC_MENU_WIPE, LRC_MENU_ALIGN, LRC_MENU_LINE_MODE, + LRC_MENU_SCROLL_MODE, }; int selected = 0; @@ -2271,7 +2288,8 @@ static bool lrc_display_menu(void) MENUITEM_STRINGLIST(menu, "Display Settings", NULL, "Wrap", "Wipe", "Alignment", - "Activate Only Current Line"); + "Activate Only Current Line", + "Automatic Scrolling"); struct opt_items align_names[] = { {"Left", -1}, {"Centre", -1}, {"Right", -1}, @@ -2295,6 +2313,9 @@ static bool lrc_display_menu(void) usb = rb->set_bool("Activate Only Current Line", &prefs.active_one_line); break; + case LRC_MENU_SCROLL_MODE: + usb = rb->set_bool("Automatic Scrolling", &prefs.autoscroll); + break; case MENU_ATTACHED_USB: usb = true; break; @@ -2619,10 +2640,28 @@ static int handle_button(void) } break; case ACTION_WPS_VOLDOWN: - rb->adjust_volume(-1); + if (!prefs.autoscroll) + { + current.scroll -= 3000; + if (current.scroll < 0) + current.scroll = 0; + } + else + { + rb->adjust_volume(-1); + } break; case ACTION_WPS_VOLUP: - rb->adjust_volume(1); + if (!prefs.autoscroll) + { + current.scroll += 3000; + if (current.scroll > current.length) + current.scroll = current.length; + } + else + { + rb->adjust_volume(1); + } break; case ACTION_WPS_CONTEXT: ret = LRC_GOTO_EDITOR; @@ -2705,6 +2744,7 @@ static int lrc_main(void) { current.elapsed = 0; current.length = 1; + current.scroll = 0; } if (current.id3 && id3_timeout && @@ -2782,6 +2822,7 @@ enum plugin_status plugin_start(const void* parameter) current.lrc_file[0] = 0; current.ff_rewind = -1; current.found_lrc = false; + current.scroll = 0; if (parameter && check_audio_status()) { const char *ext; @@ -2790,7 +2831,7 @@ enum plugin_status plugin_start(const void* parameter) rb->strcpy(current.lrc_file, parameter); if (!rb->file_exists(current.lrc_file)) { - rb->splash(HZ, "Specified file dose not exist."); + rb->splash(HZ, "Specified file does not exist."); return PLUGIN_ERROR; } ext = rb->strrchr(current.lrc_file, '.'); diff --git a/docs/CREDITS b/docs/CREDITS index 6088aac312..20c4874544 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -755,6 +755,7 @@ Sho Tanimoto Nyx Guan Arin Kim Ingmar Steen +Lourenço Soares The libmad team The wavpack team