From 526a1fb7276468137045d6227c8f62b58c75daa3 Mon Sep 17 00:00:00 2001 From: Valentin Dubois Date: Thu, 9 May 2024 03:27:37 +0200 Subject: [PATCH] Initial support for new Kobo (Clara B/W + Colour, Libra Colour) (#11737) * Support the Clara B&W, Clara Colour & Libra Colour * Enable HW dithering on *all* the Kobo MTK devices * Enforce 32bpp instead of 8bpp for Kobo devices with a color panel (the driver doesn't actually support 8bpp anyway) * Enable standby support on MTK (whenever possible, i.e., not when plugged in, as that is horribly, horribly broken). * Enforce the dedicated "color" waveform mode for image content in ScreenSaver, ImageViewer & Reader. * Fix charging LED support on MTK * Tweak the frontlight ramp on MTK + LM3630 so that it actually ramps smoothly --- base | 2 +- frontend/apps/reader/modules/readerview.lua | 8 ++ frontend/device/generic/device.lua | 1 + frontend/device/kobo/device.lua | 129 ++++++++++++++++++-- frontend/device/kobo/powerd.lua | 31 ++++- frontend/ui/screensaver.lua | 2 +- frontend/ui/uimanager.lua | 16 ++- frontend/ui/widget/imageviewer.lua | 3 +- frontend/ui/widget/screensaverwidget.lua | 2 +- platform/android/luajit-launcher | 2 +- platform/kobo/koreader.sh | 13 +- 11 files changed, 181 insertions(+), 28 deletions(-) diff --git a/base b/base index 9a90ea881..979545147 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit 9a90ea881201ae64f188150b4e3c02daeb3901bc +Subproject commit 9795451470c1e3b622d1ceac09d9aa4f53455394 diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index ee2d77eee..af6bfb1ef 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -260,6 +260,10 @@ function ReaderView:paintTo(bb, x, y) if self.ui.paging then if self.document.hw_dithering then self.dialog.dithered = true + -- Assume we're going to be showing colorful stuff on kaleido panels... + if Device:hasKaleidoWfm() then + UIManager:setDirty(nil, "color") + end end else -- Whereas for CRe, @@ -275,6 +279,10 @@ function ReaderView:paintTo(bb, x, y) if self.state.drawn == false and G_reader_settings:nilOrTrue("refresh_on_pages_with_images") then UIManager:setDirty(nil, "full") end + -- On Kaleido panels, we'll want to use GCC16 on the actual image, always... + if Device:hasKaleidoWfm() and img_coverage >= 0.075 then + UIManager:setDirty(nil, "color") + end end self.state.drawn = true end diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index a2f24426c..eb45d1cc0 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -62,6 +62,7 @@ local Device = { hasExternalSD = no, -- or other storage volume that cannot be accessed using the File Manager canHWDither = no, canHWInvert = no, + hasKaleidoWfm = no, canDoSwipeAnimation = no, canModifyFBInfo = no, -- some NTX boards do wonky things with the rotate flag after a FBIOPUT_VSCREENINFO ioctl canUseCBB = yes, -- The C BB maintains a 1:1 feature parity with the Lua BB, except that is has NO support for BB4, and limited support for BBRGB24 diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index 5df59a953..4cc84f9c5 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -31,7 +31,7 @@ local function koboEnableWifi(toggle) end -- checks if standby is available on the device -local function checkStandby() +local function checkStandby(target_state) logger.dbg("Kobo: checking if standby is possible ...") local f = io.open("/sys/power/state") if not f then @@ -40,11 +40,11 @@ local function checkStandby() local mode = f:read() f:close() logger.dbg("Kobo: available power states:", mode) - if mode and mode:find("standby") then - logger.dbg("Kobo: standby state is supported") + if mode and mode:find(target_state) then + logger.dbg("Kobo: target standby state '" .. target_state .. "' is supported") return yes end - logger.dbg("Kobo: standby state is unsupported") + logger.dbg("Kobo: target standby state '" .. target_state .. "' is unsupported") return no end @@ -152,6 +152,8 @@ local Kobo = Generic:extend{ hasEclipseWfm = no, -- Device ships with various hardware revisions under the same device code, requiring automatic hardware detection... automagic_sysfs = false, + -- The standard "standby" power state + standby_state = "standby", unexpected_wakeup_count = 0, } @@ -534,6 +536,74 @@ local KoboCondor = Kobo:extend{ isSMP = yes, } +-- Kobo Libra Colour: +local KoboMonza = Kobo:extend{ + model = "Kobo_monza", + isMTK = yes, + hasEclipseWfm = yes, + canToggleChargingLED = yes, + hasFrontlight = yes, + hasKeys = yes, + hasGSensor = yes, + display_dpi = 300, + pressure_event = C.ABS_MT_PRESSURE, + touch_mirrored_x = false, + touch_mirrored_y = true, + hasNaturalLight = yes, + frontlight_settings = { + frontlight_white = "/sys/class/backlight/mxc_msp430.0/brightness", + frontlight_mixer = "/sys/class/backlight/lm3630a_led/color", + nl_min = 0, + nl_max = 10, + nl_inverted = true, + }, + isSMP = yes, + hasColorScreen = yes, + automagic_sysfs = true, +} + +-- Kobo Clara B/W: +local KoboSpaBW = Kobo:extend{ + model = "Kobo_spaBW", + isMTK = yes, + hasEclipseWfm = yes, + canToggleChargingLED = yes, + hasFrontlight = yes, + touch_snow_protocol = true, + display_dpi = 300, + hasNaturalLight = yes, + frontlight_settings = { + frontlight_white = "/sys/class/backlight/mxc_msp430.0/brightness", + frontlight_mixer = "/sys/class/backlight/lm3630a_led/color", + nl_min = 0, + nl_max = 10, + nl_inverted = true, + }, + automagic_sysfs = true, +} + +-- Kobo Clara Colour: +local KoboSpaColour = Kobo:extend{ + model = "Kobo_spaColour", + isMTK = yes, + hasEclipseWfm = yes, + canToggleChargingLED = yes, + hasFrontlight = yes, + touch_snow_protocol = true, + display_dpi = 300, + hasNaturalLight = yes, + frontlight_settings = { + frontlight_white = "/sys/class/backlight/mxc_msp430.0/brightness", + frontlight_mixer = "/sys/class/backlight/lm3630a_led/color", + nl_min = 0, + nl_max = 10, + nl_inverted = true, + }, + isSMP = yes, + hasColorScreen = yes, + automagic_sysfs = true, +} + function Kobo:setupChargingLED() if G_reader_settings:nilOrTrue("enable_charging_led") then if self:hasAuxBattery() and self.powerd:isAuxBatteryConnected() then @@ -638,7 +708,7 @@ function Kobo:init() is_always_portrait = self.isAlwaysPortrait(), mxcfb_bypass_wait_for = mxcfb_bypass_wait_for, } - if self.screen.fb_bpp == 32 then + if self.screen.fb_bpp == 32 and not self:hasColorScreen() then -- Ensure we decode images properly, as our framebuffer is BGRA... logger.info("Enabling Kobo @ 32bpp BGR tweaks") self.hasBGRFrameBuffer = yes @@ -669,6 +739,8 @@ function Kobo:init() if util.pathExists("/sys/class/power_supply/battery") then -- Newer devices (circa sunxi) self.battery_sysfs = "/sys/class/power_supply/battery" + elseif util.fileExists("/sys/class/power_supply/bd71827_bat") then + self.battery_sysfs = "/sys/class/power_supply/bd71827_bat" else self.battery_sysfs = "/sys/class/power_supply/mc13892_bat" end @@ -722,6 +794,9 @@ function Kobo:init() elseif util.fileExists("/dev/input/by-path/platform-bd71828-pwrkey.4.auto-event") then -- Sage w/ a BD71828 PMIC self.power_dev = "/dev/input/by-path/platform-bd71828-pwrkey.4.auto-event" + elseif util.fileExists("/dev/input/by-path/platform-bd71828-pwrkey.6.auto-event") then + -- MTK w/ a BD71828 PMIC + self.power_dev = "/dev/input/by-path/platform-bd71828-pwrkey.6.auto-event" end end @@ -759,10 +834,15 @@ function Kobo:init() self.hasNaturalLightMixer = yes end -- Ditto - if self:isMk7() then + if self:isMk7() or self:isMTK() then self.canHWDither = yes end + -- Enable Kaleido waveform modes on supported devices + if self:hasColorScreen() and self:isMTK() then + self.hasKaleidoWfm = yes + end + -- NOTE: Devices with an AW99703 frontlight PWM controller feature a hardware smooth ramp when setting the frontlight intensity. --- A side-effect of this behavior is that if you queue a series of intensity changes ending at 0, --- it won't ramp *at all*, jumping straight to zero instead. @@ -771,6 +851,14 @@ function Kobo:init() self.frontlight_settings.ramp_off_delay = 0.5 end + -- I don't know how this PWM controller behaves on earlier devices, but it's... not great here. + if self:hasNaturalLightMixer() and self:isMTK() and self.frontlight_settings.frontlight_mixer:find("lm3630a_led", 12, true) then + -- First, we need a delay between ioctls + self.frontlight_settings.ramp_delay = 0.025 + -- Second, it *really* doesn't like being interleaved with screen refreshes + self.frontlight_settings.delay_ramp_start = true + end + self.powerd = require("device/kobo/powerd"):new{ device = self, battery_sysfs = self.battery_sysfs, @@ -844,9 +932,12 @@ function Kobo:init() end -- Detect the NTX charging LED sysfs knob - if util.pathExists("/sys/class/leds/bd71828-green-led") then - -- Standard Linux LED class, wheee! - self.charging_led_sysfs_knob = "/sys/class/leds/bd71828-green-led" + if util.pathExists("/sys/class/leds/LED") then + self.charging_led_sysfs_knob = "/sys/class/leds/LED/brightness" + elseif util.pathExists("/sys/class/leds/GLED") then + self.charging_led_sysfs_knob = "/sys/class/leds/GLED/brightness" + elseif util.pathExists("/sys/class/leds/bd71828-green-led") then + self.charging_led_sysfs_knob = "/sys/class/leds/bd71828-green-led/brightness" elseif util.pathExists("/sys/devices/platform/ntx_led/lit") then self.ntx_lit_sysfs_knob = "/sys/devices/platform/ntx_led/lit" elseif util.pathExists("/sys/devices/platform/pmic_light.1/lit") then @@ -876,8 +967,15 @@ function Kobo:init() -- Only enable a single core on startup self:enableCPUCores(1) - self.canStandby = checkStandby() - if self.canStandby() and (self:isMk7() or self:isSunxi() or self:isMTK()) then + -- On MTK, the "standby" power state is unavailable, and Nickel instead uses "mem" (and /sys/power/mem_sleep doesn't exist either) + if self:isMTK() then + self.standby_state = "mem" + end + + self.canStandby = checkStandby(self.standby_state) + if self.canStandby() and (self:isMk7() or self:isSunxi()) then + -- NOTE: Do *NOT* enable this on MTK. What happens if you do can only be described as "shit hits the fan". + -- (Nickel doesn't). self.canPowerSaveWhileCharging = yes end @@ -1182,7 +1280,7 @@ function Kobo:standby(max_duration) -- WiFi toggle, but (almost) everywhere. ffiUtil.usleep(90000) -- sleep 0.09s (0.08s would also work) - local ret = ffiUtil.writeToSysfs("standby", "/sys/power/state") + local ret = ffiUtil.writeToSysfs(self.standby_state, "/sys/power/state") self.last_standby_time = time.boottime_or_realtime_coarse() - standby_time self.total_standby_time = self.total_standby_time + self.last_standby_time @@ -1446,6 +1544,7 @@ function Kobo:_NTXChargingLEDToggle(toggle) end function Kobo:_LinuxChargingLEDToggle(toggle) + -- max_brightness usually says 255 for those, but 1 does the same (and matches Nickel's behavior) ffiUtil.writeToSysfs(toggle and "1" or "0", self.charging_led_sysfs_knob) end @@ -1678,6 +1777,12 @@ elseif codename == "goldfinch" then return KoboGoldfinch elseif codename == "condor" then return KoboCondor +elseif codename == "monza" or codename == "monzaTolino" then + return KoboMonza +elseif codename == "spaBW" or codename == "spaTolinoBW" then + return KoboSpaBW +elseif codename == "spaColour" or codename == "spaTolinoColour" then + return KoboSpaColour else error("unrecognized Kobo model ".. codename .. " with device id " .. product_id) end diff --git a/frontend/device/kobo/powerd.lua b/frontend/device/kobo/powerd.lua index b5a92e2f4..8280e38a6 100644 --- a/frontend/device/kobo/powerd.lua +++ b/frontend/device/kobo/powerd.lua @@ -136,8 +136,12 @@ function KoboPowerD:init() self.device.frontlight_settings = self.device.frontlight_settings or {} -- Does this device require non-standard ramping behavior? self.device.frontlight_settings.ramp_off_delay = self.device.frontlight_settings.ramp_off_delay or 0.0 - --- @note: Newer devices appear to block slightly longer on FL ioctls/sysfs, so we only really need a delay on older devices. + --- @note: Newer devices (or at least some PWM controllers) appear to block slightly longer on FL ioctls/sysfs, + --- so we only really need a delay on older devices. self.device.frontlight_settings.ramp_delay = self.device.frontlight_settings.ramp_delay or (self.device:hasNaturalLight() and 0.0 or 0.025) + -- Some PWM controllers *really* don't like being interleaved between screen refreshes, + -- so we delay the *start* of the ramp on these. + self.device.frontlight_settings.delay_ramp_start = self.device.frontlight_settings.delay_ramp_start or false -- If this device has natural light, use the sysfs interface, and ioctl otherwise. -- NOTE: On the Forma, nickel still appears to prefer using ntx_io to handle the FL, @@ -364,8 +368,17 @@ function KoboPowerD:turnOffFrontlightHW(done_callback) if self.device.frontlight_settings.ramp_off_delay > 0.0 and self.fl_intensity <= 2 then UIManager:scheduleIn(self.device.frontlight_settings.ramp_delay, self._endRampDown, self, self.fl_min, done_callback) else - self:turnOffFrontlightRamp(self.fl_intensity, self.fl_min, done_callback) - self.fl_ramp_down_running = true + -- NOTE: Similarly, some controllers *really* don't like to be interleaved with screen refreshes, + -- so we wait until the next UI frame for the refreshes to go through first... + if self.device.frontlight_settings.delay_ramp_start then + UIManager:nextTick(function() + self:turnOffFrontlightRamp(self.fl_intensity, self.fl_min, done_callback) + self.fl_ramp_down_running = true + end) + else + self:turnOffFrontlightRamp(self.fl_intensity, self.fl_min, done_callback) + self.fl_ramp_down_running = true + end end end else @@ -422,8 +435,16 @@ function KoboPowerD:turnOnFrontlightHW(done_callback) -- NOTE: Match the ramp down behavior on devices with a ramp_off_delay: jump straight to 1 or 2% intensity. UIManager:scheduleIn(self.device.frontlight_settings.ramp_delay, self._endRampUp, self, self.fl_intensity, done_callback) else - self:turnOnFrontlightRamp(self.fl_min, self.fl_intensity, done_callback) - self.fl_ramp_up_running = true + -- Same deal as in turnOffFrontlightHW + if self.device.frontlight_settings.delay_ramp_start then + UIManager:nextTick(function() + self:turnOnFrontlightRamp(self.fl_min, self.fl_intensity, done_callback) + self.fl_ramp_up_running = true + end) + else + self:turnOnFrontlightRamp(self.fl_min, self.fl_intensity, done_callback) + self.fl_ramp_up_running = true + end end end else diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index 6b3415f83..8f68df1ee 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -692,7 +692,7 @@ function Screensaver:show() self.screensaver_widget.modal = true self.screensaver_widget.dithered = true - UIManager:show(self.screensaver_widget, "full") + UIManager:show(self.screensaver_widget, Device:hasKaleidoWfm() and "color" or "full") end -- Setup the gesture lock through an additional invisible widget, so that it works regardless of the configuration. diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 2bae82064..3e643ac4c 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -134,7 +134,7 @@ For more details about refreshtype, refreshregion & refreshdither see the descri If refreshtype is omitted, no refresh will be enqueued at this time. @param widget a @{ui.widget.widget|widget} object -@string refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) +@string refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set) @int x horizontal screen offset (optional, `0` if omitted) @int y vertical screen offset (optional, `0` if omitted) @@ -191,7 +191,7 @@ For more details about refreshtype, refreshregion & refreshdither see the descri If refreshtype is omitted, no extra refresh will be enqueued at this time, leaving only those from the uncovered widgets. @param widget a @{ui.widget.widget|widget} object -@string refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) +@string refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (optional) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, requires refreshtype to be set) @bool refreshdither `true` if the refresh requires dithering (optional, requires refreshtype to be set) @see setDirty @@ -460,6 +460,10 @@ It just appends stuff to the paint and/or refresh queues. Here's a quick rundown of what each refreshtype should be used for: +* `color`: high-fidelity flashing refresh for color image content on Kaleido panels. + Maps to partial on unsupported devices, as such, better used conditionally behind a Device:hasKaleidoWfm check. +* `colortext`: REAGL refresh for color text (e.g., highlights) on Kaleido panels. + Maps to partial on unsupported devices, as such, better used conditionally behind a Device:hasKaleidoWfm check. * `full`: high-fidelity flashing refresh (e.g., large images). Highest quality, but highest latency. Don't abuse if you only want a flash (in this case, prefer `flashui` or `flashpartial`). @@ -558,7 +562,7 @@ UIManager:setDirty(self.widget, "partial", Geom:new{x=10,y=10,w=100,h=50}) UIManager:setDirty(self.widget, function() return "ui", self.someelement.dimen end) @param widget a window-level widget object, `"all"`, or `nil` -@param refreshtype `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (or a lambda, see description above) +@param refreshtype `"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"` (or a lambda, see description above) @param refreshregion a rectangle @{ui.geometry.Geom|Geom} object (optional, omitting it means the region will cover the full screen) @bool refreshdither `true` if widget requires dithering (optional) ]] @@ -1050,7 +1054,7 @@ function UIManager:getElapsedTimeSinceBoot() end -- precedence of refresh modes: -local refresh_modes = { a2 = 1, fast = 2, ui = 3, partial = 4, ["[ui]"] = 5, ["[partial]"] = 6, flashui = 7, flashpartial = 8, full = 9 } +local refresh_modes = { a2 = 1, fast = 2, ui = 3, partial = 4, ["[ui]"] = 5, ["[partial]"] = 6, flashui = 7, flashpartial = 8, full = 9, colortext = 10, color = 11 } -- NOTE: We might want to introduce a "force_a2" that points to fast, but has the highest priority, -- for the few cases where we might *really* want to enforce fast (for stuff like panning or skimming?). -- refresh methods in framebuffer implementation @@ -1064,6 +1068,8 @@ local refresh_methods = { flashui = Screen.refreshFlashUI, flashpartial = Screen.refreshFlashPartial, full = Screen.refreshFull, + colortext = Screen.refreshColorText, + color = Screen.refreshColor, } --[[ @@ -1101,7 +1107,7 @@ Widgets call this in their `paintTo()` method in order to notify UIManager that a certain part of the screen is to be refreshed. @string mode - refresh mode (`"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"`) + refresh mode (`"color"`, `"colortext"`, `"full"`, `"flashpartial"`, `"flashui"`, `"[partial]"`, `"[ui]"`, `"partial"`, `"ui"`, `"fast"`, `"a2"`) @param region A rectangle @{ui.geometry.Geom|Geom} object that specifies the region to be updated. Optional, update will affect whole screen if not specified. diff --git a/frontend/ui/widget/imageviewer.lua b/frontend/ui/widget/imageviewer.lua index ae69cfbd6..ccba02649 100644 --- a/frontend/ui/widget/imageviewer.lua +++ b/frontend/ui/widget/imageviewer.lua @@ -369,13 +369,14 @@ function ImageViewer:update() self.main_frame.radius = not self.fullscreen and 8 or nil -- NOTE: We use UI instead of partial, because we do NOT want to end up using a REAGL waveform... + local wfm_mode = Device:hasKaleidoWfm() and "color" or "ui" -- NOTE: Disabling dithering here makes for a perfect test-case of how well it works: -- page turns will show color quantization artefacts (i.e., banding) like crazy, -- while a long touch will trigger a dithered, flashing full-refresh that'll make everything shiny :). self.dithered = true UIManager:setDirty(self, function() local update_region = self.main_frame.dimen:combine(orig_dimen) - return "ui", update_region, true + return wfm_mode, update_region, true end) end diff --git a/frontend/ui/widget/screensaverwidget.lua b/frontend/ui/widget/screensaverwidget.lua index 473f5cc05..ec88637f8 100644 --- a/frontend/ui/widget/screensaverwidget.lua +++ b/frontend/ui/widget/screensaverwidget.lua @@ -54,7 +54,7 @@ end function ScreenSaverWidget:onShow() UIManager:setDirty(self, function() - return "full", self.main_frame.dimen + return Device:hasKaleidoWfm() and "color" or "full", self.main_frame.dimen end) return true end diff --git a/platform/android/luajit-launcher b/platform/android/luajit-launcher index c1c82a5db..987f37ce3 160000 --- a/platform/android/luajit-launcher +++ b/platform/android/luajit-launcher @@ -1 +1 @@ -Subproject commit c1c82a5db3d0989adf92140092108c55c110e1c6 +Subproject commit 987f37ce34388d75e35f09227c0230b3f226c6f8 diff --git a/platform/kobo/koreader.sh b/platform/kobo/koreader.sh index bb7d43a38..6f8c7630b 100755 --- a/platform/kobo/koreader.sh +++ b/platform/kobo/koreader.sh @@ -99,7 +99,7 @@ ko_update_check() { export FBINK_NAMED_PIPE="/tmp/koreader.fbink" rm -f "${FBINK_NAMED_PIPE}" # We'll want to use REAGL on sunxi, because AUTO is slow, and fast merges are extremely broken outside of REAGL... - eval "$(fbink -e | tr ';' '\n' | grep -e isSunxi | tr '\n' ';')" + eval "$(./fbink -e | tr ';' '\n' | grep -e isSunxi | tr '\n' ';')" # shellcheck disable=SC2154 if [ "${isSunxi}" = "1" ]; then PBAR_WFM="REAGL" @@ -334,6 +334,17 @@ ko_do_fbdepth() { return fi + # On color panels, we target 32bpp for, well, color, and sane addressing (it also happens to be their default) ;o). + # Also, the current lineup of MTK + Kaleido devices doesn't even *support* switching to 8bpp anymore. + eval "$(./fbink -e | tr ';' '\n' | grep -e hasColorPanel | tr '\n' ';')" + # shellcheck disable=SC2154 + if [ "${hasColorPanel}" = "1" ]; then + echo "Switching fb bitdepth to 32bpp & rotation to Portrait" >>crash.log 2>&1 + ./fbdepth -d 32 -R UR >>crash.log 2>&1 + + return + fi + # Check if the swap has been disabled... if grep -q '\["dev_startup_no_fbdepth"\] = true' 'settings.reader.lua' 2>/dev/null; then # Swap back to the original bitdepth (in case this was a restart)