Merge branch 'patch/pinenote' into 'master'
Draft: Add support Pine64 mobile devices See merge request nonguix/nonguix!206
This commit is contained in:
commit
d6a944fe04
5853
nongnu/configs/pinenote_config
Normal file
5853
nongnu/configs/pinenote_config
Normal file
File diff suppressed because it is too large
Load Diff
6026
nongnu/configs/pinenote_defconfig
Normal file
6026
nongnu/configs/pinenote_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
7916
nongnu/configs/quartz64_defconfig
Normal file
7916
nongnu/configs/quartz64_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
9690
nongnu/configs/quartz64b_defconfig
Normal file
9690
nongnu/configs/quartz64b_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
261
nongnu/packages/bootloaders.scm
Normal file
261
nongnu/packages/bootloaders.scm
Normal file
|
@ -0,0 +1,261 @@
|
|||
;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
|
||||
;;;
|
||||
;;; This program is free software: you can redistribute it and/or modify
|
||||
;;; it under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation, either version 3 of the License, or
|
||||
;;; (at your option) any later version.
|
||||
;;;
|
||||
;;; This program is distributed in the hope that it will be useful,
|
||||
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (nongnu packages bootloaders)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu bootloader extlinux)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu packages base)
|
||||
#:use-module (gnu packages bash)
|
||||
#:use-module (gnu packages bootloaders)
|
||||
#:use-module (gnu packages compression)
|
||||
#:use-module (gnu packages python)
|
||||
#:use-module (gnu packages python-xyz)
|
||||
#:use-module (gnu packages tls)
|
||||
#:use-module (guix download)
|
||||
#:use-module (guix git-download)
|
||||
#:use-module (ice-9 ftw)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (nonguix build-system binary)
|
||||
#:use-module ((nonguix licenses)
|
||||
#:prefix license:)
|
||||
#:export (u-boot-quartz64a-rk3566-bootloader
|
||||
u-boot-pinephone-pro-rk3399-bootloader
|
||||
u-boot-pinenote-rk3566-bootloader))
|
||||
|
||||
(define %u-boot-quartz64-nvme-configs
|
||||
'("CONFIG_CMD_NVME=y"
|
||||
"CONFIG_CMD_PCI=y"
|
||||
"CONFIG_NVME=y"
|
||||
"CONFIG_NVME_PCI=y"
|
||||
"CONFIG_PCI=y"
|
||||
"CONFIG_PCI_PNP=y"
|
||||
"CONFIG_LOG_MAX_LEVEL=7"
|
||||
"CONFIG_LOG=y"
|
||||
"CONFIG_LOG_CONSOLE=y"
|
||||
; "CONFIG_PCI_ENHANCED_ALLOCATION=y"
|
||||
"CONFIG_PCIE_DW_COMMON=y"
|
||||
"CONFIG_PCIE_DW_ROCKCHIP=y"
|
||||
"CONFIG_PHY=y"
|
||||
"CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y"))
|
||||
|
||||
(define-public u-boot-pinephone-pro-rk3399
|
||||
(make-u-boot-package "pinephone-pro-rk3399" "aarch64-linux-gnu"))
|
||||
|
||||
(define (u-boot-rk3566 board configs)
|
||||
(let ((commit "58040d305147b8608f5766a49d63e863ba163937")
|
||||
(revision "1")
|
||||
(base (make-u-boot-package board "aarch64-linux-gnu"
|
||||
#:configs configs)))
|
||||
(package
|
||||
(inherit base)
|
||||
(version "2022.07")
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
;; Using rebased version which is compatible with Guix disable
|
||||
;; OpenSSL patch
|
||||
(url "https://gitlab.com/phodina/u-boot-quartz64")
|
||||
(commit commit)))
|
||||
(patches
|
||||
(search-patches "u-boot-allow-disabling-openssl.patch"))
|
||||
(sha256
|
||||
(base32
|
||||
"0w2yzvfvvydv26dm043jw24r7qkzc3j8jhcrc487pdm79icgfib8"))))
|
||||
(arguments
|
||||
(substitute-keyword-arguments (package-arguments base)
|
||||
((#:phases phases)
|
||||
#~(modify-phases #$phases
|
||||
; (add-after 'configure 'fix-config
|
||||
; (lambda* _
|
||||
; (substitute* ".config"
|
||||
; (("CONFIG_ARM=y")
|
||||
; "CONFIG_ARM=y\nCONFIG_LOG_MAX_LEVEL=7\nCONFIG_LOG=y\nCONFIG_LOG_CONSOLE=y"))))
|
||||
(add-after 'unpack 'download-rockchip-firmware
|
||||
(lambda* _
|
||||
(let* ((ram-init-dl #$(origin
|
||||
(method url-fetch)
|
||||
(uri
|
||||
"https://github.com/JeffyCN/rockchip_mirrors/raw/47404a141a1acb7555906b5e3b097b5f1045cc21/bin/rk35/rk3568_ddr_1560MHz_v1.11.bin")
|
||||
(file-name "ram_init.bin")
|
||||
(sha256 (base32
|
||||
"02rj8spdbq250wcrkkscmjz4jmwba8yfmv90kkbd5wspmk9bq0cj"))))
|
||||
(bl31-dl #$(origin
|
||||
(method url-fetch)
|
||||
(uri
|
||||
"https://github.com/JeffyCN/rockchip_mirrors/raw/6186debcac95553f6b311cee10669e12c9c9963d/bin/rk35/rk3568_bl31_v1.28.elf")
|
||||
(file-name "rk3568_bl31_v1.28.elf")
|
||||
(sha256 (base32
|
||||
"0ji53ggmmf9qwrvs06ashydvaw8d9w4byzsvypqy4imndxb1kgv7"))))
|
||||
(bl31
|
||||
"rk3568_bl31_v1.28.elf")
|
||||
(ram-init
|
||||
"ram_init.bin"))
|
||||
(setenv "BL31" "rk3568_bl31_v1.28.elf")
|
||||
(for-each make-file-writable (find-files "."))
|
||||
(copy-file ram-init-dl ram-init)
|
||||
(copy-file bl31-dl bl31)))))))))))
|
||||
|
||||
(define-public u-boot-rk3566-quartz64-downstream
|
||||
(let ((commit "7df3eae9f756665e01016a182d33ddf9dd244b1d")
|
||||
(revision "1")
|
||||
(base (make-u-boot-package "rk3566-quartz64" "aarch64-linux-gnu")))
|
||||
(package
|
||||
(inherit base)
|
||||
(version "2017")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append
|
||||
"https://github.com/JoshuaMulliken/u-boot-rockchip/archive/"
|
||||
commit ".tar.gz"))
|
||||
; (patches
|
||||
; (parameterize
|
||||
; ((%patch-path
|
||||
; (map (lambda (directory)
|
||||
; (string-append directory "/nongnu/packages/patches"))
|
||||
; %load-path)))
|
||||
; (search-patches ;"u-boot-dont-block-reads-above-32mb.patch"
|
||||
; ;"u-boot-pyelftools.patch"
|
||||
; "u-boot-pyelftools.patch")))
|
||||
(sha256
|
||||
(base32
|
||||
"0dsi48ay06ciqcvlrbjwm90wvvs3wf65nbgjsc46wkkx9c6r1rj2"))))
|
||||
(arguments
|
||||
(substitute-keyword-arguments (package-arguments base)
|
||||
((#:phases phases)
|
||||
#~(modify-phases #$phases
|
||||
(add-after 'unpack 'download-rockchip-firmware
|
||||
(lambda* _
|
||||
(let* ((rkbin-dl #$(origin
|
||||
(method url-fetch)
|
||||
(uri
|
||||
"https://github.com/JeffyCN/rockchip_mirrors/archive/refs/heads/rkbin.zip")
|
||||
(file-name "rkbin.zip")
|
||||
(sha256 (base32
|
||||
"0wpli41046kppm873n5h410ljrvzjf219gzb7n0jc3qpghyl9cvw")))))
|
||||
(invoke "unzip" "-q" rkbin-dl)
|
||||
(rename-file "rockchip_mirrors-rkbin" "../rkbin")
|
||||
; (patch-shebang "make.sh")
|
||||
;(substitute* "scripts/fit.sh"
|
||||
;(("./make.sh loader") "bash -x ./make.sh loader"))
|
||||
;(substitute* "scripts/loader.sh"
|
||||
;(("set -e") "set -e\nset -x"))
|
||||
; (("boot_merger") "boot_merger --verbose"))
|
||||
(substitute* "Makefile"
|
||||
(("HOSTCC = cc") (string-append "HOSTCC = "
|
||||
#$(cc-for-target))))
|
||||
;(substitute* "make.sh"
|
||||
;(("python") "python3")
|
||||
;(("..SCRIPT_LOADER. --ini ..INI_LOADER.") "bash -x ${SCRIPT_LOADER} --ini
|
||||
;${INI_LOADER}")
|
||||
;(("..SCRIPT_FIT. ..ARG_LIST_FIT.") "bash -x ${SCRIPT_FIT} ${ARG_LIST_FIT}"))
|
||||
;(("^make.*") "make HOSTCC=gcc CROSS_COMPILE=aarch64-linux-gnu- all\n"))
|
||||
)))
|
||||
(delete 'disable-tools-libcrypto)
|
||||
(delete 'configure)
|
||||
(replace 'build
|
||||
(lambda* (#:key outputs inputs make-flags #:allow-other-keys)
|
||||
; (setenv "PATH" (string-append (dirname (which "sed")) ":" (dirname
|
||||
; (which "grep")) ":" (dirname (which "awk")) ":"
|
||||
; ;#$(this-package-input "coreutils") "/bin" ":"
|
||||
; #$coreutils "/bin" ":"
|
||||
; (getenv "PATH")))
|
||||
; (setenv "cc=" #$(cc-for-target))
|
||||
; (setenv "CROSS_COMPILE" "aarch64-linux-gnu-")
|
||||
(invoke "make" "clean")
|
||||
(invoke "make" "mrproper")
|
||||
(invoke "make" "V=1" ;(string-append "CC=" "gcc");#$(cc-for-target))
|
||||
"rk3566-eink_defconfig")
|
||||
(invoke "./make.sh")
|
||||
(invoke "./make.sh" "trust")))
|
||||
;(invoke "make" "HOSTCC=gcc" "CROSS_COMPILE=aarch64-linux-gnu-" "rk3566-quartz64_defconfig")))
|
||||
(add-after 'build 'build-binaries
|
||||
(lambda* (#:key outputs make-flags #:allow-other-keys)
|
||||
;; Failing at
|
||||
;; https://gitlab.com/pgwipeout/u-boot-rockchip/-/blob/quartz64/make.sh#L774
|
||||
(invoke "bash" "-x" "./make.sh")
|
||||
(invoke "./tools/resource_tool" "--pack" "arch/arm/dts/rk3566-quartz64.dtb")
|
||||
))))))
|
||||
(native-inputs `(("which" ,which) ("coreutils" ,coreutils) ("dtc" ,dtc)
|
||||
("python-pyelftools" ,python-pyelftools) ("bash" ,bash-minimal) ("unzip" ,unzip) ,@(package-native-inputs base))))))
|
||||
|
||||
(define-public u-boot-rk3566-evb
|
||||
(u-boot-rk3566 "evb-rk3566" '()))
|
||||
|
||||
(define-public u-boot-rk3566-pinenote
|
||||
(u-boot-rk3566 "pinenote-rk3566" '()))
|
||||
|
||||
(define-public u-boot-rk3566-quartz64a
|
||||
(u-boot-rk3566 "quartz64-a-rk3566" %u-boot-quartz64-nvme-configs))
|
||||
|
||||
(define-public u-boot-rk3566-quartz64b
|
||||
(u-boot-rk3566 "quartz64-b-rk3566" '()))
|
||||
|
||||
(define-public u-boot-rk3566-soquartz
|
||||
(u-boot-rk3566 "soquartz-rk3566" '()))
|
||||
|
||||
(define install-u-boot
|
||||
#~(lambda (bootloader root-index image)
|
||||
(if bootloader
|
||||
(error "Failed to install U-Boot"))))
|
||||
|
||||
(define install-rk3566-u-boot
|
||||
#~(lambda (bootloader root-index image)
|
||||
(let ((idb (string-append bootloader "/libexec/idbloader.img"))
|
||||
(u-boot (string-append bootloader "/libexec/u-boot.itb")))
|
||||
(write-file-on-device idb (stat:size (stat idb))
|
||||
image (* 64 512))
|
||||
(write-file-on-device u-boot (stat:size (stat u-boot))
|
||||
image (* 16384 512)))))
|
||||
|
||||
(define install-pinephone-pro-rk3399-u-boot
|
||||
#~(lambda (bootloader root-index image)
|
||||
(let ((idb (string-append bootloader "/libexec/idbloader.img"))
|
||||
(u-boot (string-append bootloader "/libexec/u-boot.itb")))
|
||||
(write-file-on-device idb (stat:size (stat idb))
|
||||
image (* 64 512))
|
||||
(write-file-on-device u-boot (stat:size (stat u-boot))
|
||||
image (* 16384 512)))))
|
||||
|
||||
(define u-boot-bootloader
|
||||
(bootloader
|
||||
(inherit extlinux-bootloader)
|
||||
(name 'u-boot)
|
||||
(package #f)
|
||||
(installer #f)
|
||||
(disk-image-installer install-u-boot)))
|
||||
|
||||
(define u-boot-pinephone-pro-rk3399-bootloader
|
||||
;; SD and eMMC use the same format
|
||||
(bootloader
|
||||
(inherit u-boot-bootloader)
|
||||
(package u-boot-pinephone-pro-rk3399)
|
||||
(disk-image-installer install-pinephone-pro-rk3399-u-boot)))
|
||||
|
||||
(define u-boot-quartz64a-rk3566-bootloader
|
||||
;; SD and eMMC use the same format
|
||||
(bootloader
|
||||
(inherit u-boot-bootloader)
|
||||
(package u-boot-rk3566-quartz64a)
|
||||
(disk-image-installer install-rk3566-u-boot)))
|
||||
|
||||
(define u-boot-pinenote-rk3566-bootloader
|
||||
;; SD and eMMC use the same format
|
||||
(bootloader
|
||||
(inherit u-boot-bootloader)
|
||||
(package u-boot-rk3566-pinenote)
|
||||
(disk-image-installer install-rk3566-u-boot)))
|
|
@ -8,6 +8,7 @@
|
|||
#:use-module (guix build-system copy)
|
||||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix download)
|
||||
#:use-module (guix git-download)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix git-download)
|
||||
#:use-module ((guix licenses) #:prefix guix-license:)
|
||||
|
@ -36,6 +37,32 @@
|
|||
#$output "/libexec")
|
||||
"-Dsupported_build=true"))))))
|
||||
|
||||
;; Firmware for Eink display
|
||||
(define-public pinenote-firmware
|
||||
(let ((commit "f47f34b968cb6d9385ed4c15c6a7af236227f5f0")
|
||||
(revision "1"))
|
||||
(package
|
||||
(name "pinenote-firmware")
|
||||
(version "")
|
||||
(home-page "https://gitlab.com/phodina/pinenote-firmware")
|
||||
(source (origin
|
||||
(method git-fetch)
|
||||
(uri (git-reference
|
||||
(url home-page)
|
||||
(commit commit)))
|
||||
(file-name (git-file-name name version))
|
||||
(sha256
|
||||
(base32
|
||||
"06wpqalz57wd6av8yz77gyq4j3hiwx76hanm3bag22b6hda23zgb"))))
|
||||
(build-system copy-build-system)
|
||||
;; (arguments
|
||||
;; `(#:install-plan
|
||||
;; (list (list ".*" "lib/firmware/"))))
|
||||
(synopsis "Firmware for the PineNote")
|
||||
(description
|
||||
"This package contains dump of the firmware from the PineNote.")
|
||||
(license (nonfree (string-append "unknown"))))))
|
||||
|
||||
(define-public ov5640-firmware
|
||||
(let ((commit "6e8e591e17e207644dfe747e51026967bb1edab5")
|
||||
(revision "1"))
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#:use-module (guix build-system linux-module)
|
||||
#:use-module (guix build-system trivial)
|
||||
#:use-module (ice-9 match)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:use-module (nonguix licenses)
|
||||
#:use-module (srfi srfi-1)
|
||||
#:export (corrupt-linux))
|
||||
|
@ -47,6 +48,19 @@
|
|||
"/linux/kernel/v" (version-major version) ".x"
|
||||
"/linux-" version ".tar.xz"))
|
||||
|
||||
(define (linux-pinenote-urls commit)
|
||||
"Return a list of URLS for Linux VERSION."
|
||||
(list (string-append
|
||||
"https://gitlab.com/pgwipeout/linux-next/-/archive/"
|
||||
commit "/linux-next-" commit ".tar.gz")))
|
||||
; "https://github.com/m-weigand/linux/archive/refs/heads/mw/rk35/pinenote-next-t1.tar.gz")))
|
||||
|
||||
(define (linux-pinephone-urls version commit)
|
||||
"Return a list of URLS for Linux VERSION."
|
||||
(list (string-append
|
||||
"https://github.com/megous/linux/archive/refs/tags/orange-pi-"
|
||||
(version-major+minor version) "-" commit ".tar.gz")))
|
||||
|
||||
(define* (corrupt-linux freedo #:key (name "linux"))
|
||||
|
||||
;; TODO: This very directly depends on guix internals.
|
||||
|
@ -86,6 +100,78 @@
|
|||
"The unmodified Linux kernel, including nonfree blobs, for running Guix System
|
||||
on hardware which requires nonfree software to function."))))
|
||||
|
||||
;; Linux kernel fork for PinePhone and PinePhone Pro
|
||||
(define* (pinephone-linux freedo version-megi release defconfig #:key (name "linux"))
|
||||
(package
|
||||
(inherit
|
||||
(customize-linux
|
||||
#:name name
|
||||
#:defconfig defconfig
|
||||
#:source (origin (inherit (package-source freedo))
|
||||
(method url-fetch)
|
||||
(file-name (string-append name "-" (version-major+minor
|
||||
version-megi)
|
||||
"-guix.tar.gz"))
|
||||
(uri (linux-pinephone-urls version-megi
|
||||
release))
|
||||
(patches
|
||||
(parameterize
|
||||
((%patch-path
|
||||
(map (lambda (directory)
|
||||
(string-append directory "/nongnu/packages/patches"))
|
||||
%load-path)))
|
||||
(search-patches
|
||||
"linux-pinephone-pro-defconfig-guix-fix.patch"))))))
|
||||
; ;; Port bootsplash patches
|
||||
;;;"pinephone-0001-bootsplash.patch"
|
||||
;;;"pinephone-0002-bootsplash.patch"
|
||||
;;"pinephone-revert-fbcon-remove-now-unusued-softback_lines-cursor-argument.patch"
|
||||
;;;"pinephone-0003-bootsplash.patch"
|
||||
;;"pinephone-fbcon-remove-no-op-fbcon_set_origin.patch"
|
||||
;;;"pinephone-0004-bootsplash.patch"
|
||||
;;"pinephone-revert-fbcon-remove-soft-scrollback-code.patch"
|
||||
;;;"pinephone-0005-bootsplash.patch"
|
||||
;;;"pinephone-0004-bootsplash.patch"
|
||||
;;;"pinephone-0006-bootsplash.patch"
|
||||
;;;"pinephone-0007-bootsplash.patch"
|
||||
;;;"pinephone-0008-bootsplash.patch"
|
||||
;;;"pinephone-0009-bootsplash.patch"
|
||||
;;;"pinephone-0010-bootsplash.patch"
|
||||
;;;"pinephone-0011-bootsplash.patch"
|
||||
;;"pinephone-drop-modem-power-node.patch"
|
||||
;;"pinephone-pro-add-modem-ri.patch.patch"
|
||||
;;"pinephone-pro-remove-modem-node.patch"
|
||||
; ))))))
|
||||
(version (package-version freedo))
|
||||
(home-page "https://www.kernel.org/")
|
||||
(synopsis "Linux kernel with nonfree binary blobs included")
|
||||
(description
|
||||
"The unmodified Linux kernel, including nonfree blobs, for running Guix
|
||||
System on hardware which requires nonfree software to function.")))
|
||||
|
||||
; TODO: Power supply fix
|
||||
; https://github.com/DorianRudolph/linux/commit/822294664906499682b55264ae0553ee05caa352
|
||||
;; Linux kernel fork for PineNote
|
||||
(define* (pinenote-linux freedo commit defconfig #:key (name "linux"))
|
||||
(package
|
||||
(inherit
|
||||
(customize-linux
|
||||
#:name name
|
||||
#:defconfig (local-file
|
||||
(string-append "nongnu/configs/" defconfig))
|
||||
#:source (origin (inherit (package-source freedo))
|
||||
(method url-fetch)
|
||||
(file-name (string-append name "-" version
|
||||
"-guix.tar.gz"))
|
||||
(uri (linux-pinenote-urls commit))
|
||||
(patches '()))))
|
||||
(version (package-version freedo))
|
||||
(home-page "https://www.kernel.org/")
|
||||
(synopsis "Linux kernel with nonfree binary blobs included")
|
||||
(description
|
||||
"The unmodified Linux kernel, including nonfree blobs, for running Guix
|
||||
System on hardware which requires nonfree software to function.")))
|
||||
|
||||
(define-public linux-6.1
|
||||
(corrupt-linux linux-libre-6.1))
|
||||
|
||||
|
@ -118,6 +204,25 @@ on hardware which requires nonfree software to function."))))
|
|||
|
||||
(define-public linux-arm64-generic-lts linux-arm64-generic-5.15)
|
||||
|
||||
(define-public linux-pinephone-pro
|
||||
(pinephone-linux linux-libre-arm64-generic "6.1" "20230104-1712" "pinephone_pro_defconfig"
|
||||
#:name "linux-pinephone-pro"))
|
||||
|
||||
(define-public linux-pinephone
|
||||
(pinephone-linux linux-libre-arm64-generic "6.1" "20230104-1712" "pinephone_defconfig"
|
||||
#:name "linux-pinephone"))
|
||||
|
||||
;; pinenote-next-t1 branch
|
||||
(define-public linux-pinenote
|
||||
(pinenote-linux linux-arm64-generic
|
||||
"7a28914fbf71b1a04e5484ec04205b20c8abe34c" "pinenote_defconfig"
|
||||
#:name "linux-pinenote"))
|
||||
|
||||
(define-public linux-quartz64
|
||||
(pinenote-linux linux-arm64-generic
|
||||
"9abf2313adc1ca1b6180c508c25f22f9395cc780" "quartz64_defconfig"
|
||||
#:name "linux-quartz64"))
|
||||
|
||||
(define-public linux-firmware
|
||||
(package
|
||||
(name "linux-firmware")
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
From 34054942047728627c9f5aad92e85669c4bb34e8 Mon Sep 17 00:00:00 2001
|
||||
From: hrdl <7808331-hrdl@users.noreply.gitlab.com>
|
||||
Date: Sun, 12 Jun 2022 15:47:20 +0000
|
||||
Subject: [PATCH] Rudimentary attempt to keep PMIC usable after suspend
|
||||
|
||||
---
|
||||
drivers/regulator/tps65185-regulator.c | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/regulator/tps65185-regulator.c b/drivers/regulator/tps65185-regulator.c
|
||||
index d7730ff98c13..59327f41c8e2 100644
|
||||
--- a/drivers/regulator/tps65185-regulator.c
|
||||
+++ b/drivers/regulator/tps65185-regulator.c
|
||||
@@ -664,6 +664,24 @@ static int tps65185_probe(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __maybe_unused tps65185_resume(struct device *dev)
|
||||
+{
|
||||
+ struct i2c_client *client = to_i2c_client(dev);
|
||||
+
|
||||
+ struct tps65185 *tps;
|
||||
+ int ret;
|
||||
+
|
||||
+ tps = i2c_get_clientdata(client);
|
||||
+
|
||||
+ ret = tps65185_set_config(dev, tps);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "Failed to set config at resume\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static SIMPLE_DEV_PM_OPS(tps65185_pm, NULL, tps65185_resume);
|
||||
+
|
||||
static const struct of_device_id tps65185_of_match[] = {
|
||||
{ .compatible = "ti,tps65185" },
|
||||
{}
|
||||
@@ -674,6 +692,7 @@ static struct i2c_driver tps65185_driver = {
|
||||
.probe_new = tps65185_probe,
|
||||
.driver = {
|
||||
.name = "tps65185",
|
||||
+ .pm = &tps65185_pm,
|
||||
.of_match_table = tps65185_of_match,
|
||||
},
|
||||
};
|
||||
--
|
||||
2.36.1
|
||||
|
62
nongnu/packages/patches/battery-level.patch
Normal file
62
nongnu/packages/patches/battery-level.patch
Normal file
|
@ -0,0 +1,62 @@
|
|||
From 822294664906499682b55264ae0553ee05caa352 Mon Sep 17 00:00:00 2001
|
||||
From: Dorian Rudolph <mail@dorianrudolph.com>
|
||||
Date: Sat, 14 May 2022 14:28:37 +0200
|
||||
Subject: [PATCH] fix power_supply_temp2resist_simple and
|
||||
power_supply_ocv2cap_simple
|
||||
|
||||
---
|
||||
drivers/power/supply/power_supply_core.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
|
||||
index ec838c9bcc0a5e..3828ba9d0eab90 100644
|
||||
--- a/drivers/power/supply/power_supply_core.c
|
||||
+++ b/drivers/power/supply/power_supply_core.c
|
||||
@@ -801,17 +801,17 @@ int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *t
|
||||
{
|
||||
int i, high, low;
|
||||
|
||||
- /* Break loop at table_len - 1 because that is the highest index */
|
||||
- for (i = 0; i < table_len - 1; i++)
|
||||
+ for (i = 0; i < table_len; i++)
|
||||
if (temp > table[i].temp)
|
||||
break;
|
||||
|
||||
/* The library function will deal with high == low */
|
||||
- if ((i == 0) || (i == (table_len - 1)))
|
||||
- high = i;
|
||||
+ if (i == 0)
|
||||
+ high = low = i;
|
||||
+ else if (i == table_len)
|
||||
+ high = low = i - 1;
|
||||
else
|
||||
- high = i - 1;
|
||||
- low = i;
|
||||
+ high = (low = i) - 1;
|
||||
|
||||
return fixp_linear_interpolate(table[low].temp,
|
||||
table[low].resistance,
|
||||
@@ -838,17 +838,17 @@ int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
|
||||
{
|
||||
int i, high, low;
|
||||
|
||||
- /* Break loop at table_len - 1 because that is the highest index */
|
||||
- for (i = 0; i < table_len - 1; i++)
|
||||
+ for (i = 0; i < table_len; i++)
|
||||
if (ocv > table[i].ocv)
|
||||
break;
|
||||
|
||||
/* The library function will deal with high == low */
|
||||
- if ((i == 0) || (i == (table_len - 1)))
|
||||
- high = i - 1;
|
||||
+ if (i == 0)
|
||||
+ high = low = i;
|
||||
+ else if (i == table_len)
|
||||
+ high = low = i - 1;
|
||||
else
|
||||
- high = i; /* i.e. i == 0 */
|
||||
- low = i;
|
||||
+ high = (low = i) - 1;
|
||||
|
||||
return fixp_linear_interpolate(table[low].ocv,
|
||||
table[low].capacity,
|
|
@ -0,0 +1,13 @@
|
|||
--- a/arch/arm64/configs/pinephone_pro_defconfig.orig 2023-01-14 08:25:28.004411948 +0100
|
||||
+++ b/arch/arm64/configs/pinephone_pro_defconfig 2023-01-14 08:47:08.696514744 +0100
|
||||
@@ -252,8 +252,8 @@
|
||||
CONFIG_UEVENT_HELPER=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
-#CONFIG_EXTRA_FIRMWARE="regulatory.db regulatory.db.p7s brcm/brcmfmac43455-sdio.bin brcm/brcmfmac43455-sdio.pine64,pinephone-pro.txt brcm/brcmfmac43455-sdio.clm_blob brcm/BCM4345C0.hcd rockchip/dptx.bin"
|
||||
-#CONFIG_EXTRA_FIRMWARE_DIR="/workspace/megous.com/orangepi-pc/firmware"
|
||||
+CONFIG_EXTRA_FIRMWARE=""
|
||||
+# CONFIG_EXTRA_FIRMWARE_DIR is not set
|
||||
CONFIG_ARM_SCMI_PROTOCOL=y
|
||||
CONFIG_ARM_SCPI_PROTOCOL=y
|
||||
CONFIG_MTD=y
|
62
nongnu/packages/patches/pinenote-battery-level.patch
Normal file
62
nongnu/packages/patches/pinenote-battery-level.patch
Normal file
|
@ -0,0 +1,62 @@
|
|||
From 822294664906499682b55264ae0553ee05caa352 Mon Sep 17 00:00:00 2001
|
||||
From: Dorian Rudolph <mail@dorianrudolph.com>
|
||||
Date: Sat, 14 May 2022 14:28:37 +0200
|
||||
Subject: [PATCH] fix power_supply_temp2resist_simple and
|
||||
power_supply_ocv2cap_simple
|
||||
|
||||
---
|
||||
drivers/power/supply/power_supply_core.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
|
||||
index ec838c9bcc0a5e..3828ba9d0eab90 100644
|
||||
--- a/drivers/power/supply/power_supply_core.c
|
||||
+++ b/drivers/power/supply/power_supply_core.c
|
||||
@@ -801,17 +801,17 @@ int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *t
|
||||
{
|
||||
int i, high, low;
|
||||
|
||||
- /* Break loop at table_len - 1 because that is the highest index */
|
||||
- for (i = 0; i < table_len - 1; i++)
|
||||
+ for (i = 0; i < table_len; i++)
|
||||
if (temp > table[i].temp)
|
||||
break;
|
||||
|
||||
/* The library function will deal with high == low */
|
||||
- if ((i == 0) || (i == (table_len - 1)))
|
||||
- high = i;
|
||||
+ if (i == 0)
|
||||
+ high = low = i;
|
||||
+ else if (i == table_len)
|
||||
+ high = low = i - 1;
|
||||
else
|
||||
- high = i - 1;
|
||||
- low = i;
|
||||
+ high = (low = i) - 1;
|
||||
|
||||
return fixp_linear_interpolate(table[low].temp,
|
||||
table[low].resistance,
|
||||
@@ -838,17 +838,17 @@ int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
|
||||
{
|
||||
int i, high, low;
|
||||
|
||||
- /* Break loop at table_len - 1 because that is the highest index */
|
||||
- for (i = 0; i < table_len - 1; i++)
|
||||
+ for (i = 0; i < table_len; i++)
|
||||
if (ocv > table[i].ocv)
|
||||
break;
|
||||
|
||||
/* The library function will deal with high == low */
|
||||
- if ((i == 0) || (i == (table_len - 1)))
|
||||
- high = i - 1;
|
||||
+ if (i == 0)
|
||||
+ high = low = i;
|
||||
+ else if (i == table_len)
|
||||
+ high = low = i - 1;
|
||||
else
|
||||
- high = i; /* i.e. i == 0 */
|
||||
- low = i;
|
||||
+ high = (low = i) - 1;
|
||||
|
||||
return fixp_linear_interpolate(table[low].ocv,
|
||||
table[low].capacity,
|
2852
nongnu/packages/patches/pinenote-rockchip-ebc-patches-mw.patch
Normal file
2852
nongnu/packages/patches/pinenote-rockchip-ebc-patches-mw.patch
Normal file
File diff suppressed because it is too large
Load Diff
976
nongnu/packages/patches/pinenote-touchscreen-1.patch
Normal file
976
nongnu/packages/patches/pinenote-touchscreen-1.patch
Normal file
|
@ -0,0 +1,976 @@
|
|||
From a24cb29eca1a72afb1037f5468d3036b34ea1b66 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= <mylene.josserand@bootlin.com>
|
||||
Date: Sun, 9 Jan 2022 21:53:28 +1000
|
||||
Subject: [PATCH] Input: Add driver for Cypress Generation 5 touchscreen
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is the basic driver for the Cypress TrueTouch Gen5 touchscreen
|
||||
controllers. This driver supports only the I2C bus but it uses regmap
|
||||
so SPI support could be added later.
|
||||
The touchscreen can retrieve some defined zone that are handled as
|
||||
buttons (according to the hardware). That is why it handles
|
||||
button and multitouch events.
|
||||
|
||||
Reviewed-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Signed-off-by: Mylène Josserand <mylene.josserand@bootlin.com>
|
||||
Signed-off-by: Alistair Francis <alistair@alistair23.me>
|
||||
Tested-by: Andreas Kemnade <andreas@kemnade.info> # Kobo Clara HD
|
||||
---
|
||||
drivers/input/touchscreen/Kconfig | 16 +
|
||||
drivers/input/touchscreen/Makefile | 1 +
|
||||
drivers/input/touchscreen/cyttsp5.c | 902 ++++++++++++++++++++++++++++
|
||||
3 files changed, 919 insertions(+)
|
||||
create mode 100644 drivers/input/touchscreen/cyttsp5.c
|
||||
|
||||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
|
||||
index 2f6adfb7b938..eb4e1b156683 100644
|
||||
--- a/drivers/input/touchscreen/Kconfig
|
||||
+++ b/drivers/input/touchscreen/Kconfig
|
||||
@@ -284,6 +284,22 @@ config TOUCHSCREEN_CYTTSP4_SPI
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp4_spi.
|
||||
|
||||
+config TOUCHSCREEN_CYTTSP5
|
||||
+ tristate "Cypress TrueTouch Gen5 Touchscreen Driver"
|
||||
+ depends on I2C
|
||||
+ select REGMAP_I2C
|
||||
+ select CRC_ITU_T
|
||||
+ help
|
||||
+ Driver for Parade TrueTouch Standard Product Generation 5
|
||||
+ touchscreen controllers. I2C bus interface support only.
|
||||
+
|
||||
+ Say Y here if you have a Cypress Gen5 touchscreen.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called cyttsp5.
|
||||
+
|
||||
config TOUCHSCREEN_DA9034
|
||||
tristate "Touchscreen support for Dialog Semiconductor DA9034"
|
||||
depends on PMIC_DA903X
|
||||
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
|
||||
index 39a8127cf6a5..0ea5c47f7fd9 100644
|
||||
--- a/drivers/input/touchscreen/Makefile
|
||||
+++ b/drivers/input/touchscreen/Makefile
|
||||
@@ -30,6 +30,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o
|
||||
+obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
|
||||
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
|
||||
new file mode 100644
|
||||
index 000000000000..3ac45108090c
|
||||
--- /dev/null
|
||||
+++ b/drivers/input/touchscreen/cyttsp5.c
|
||||
@@ -0,0 +1,902 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Parade TrueTouch(TM) Standard Product V5 Module.
|
||||
+ *
|
||||
+ * Copyright (C) 2015 Parade Technologies
|
||||
+ * Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
+ * Copyright (C) 2018 Bootlin
|
||||
+ *
|
||||
+ * Authors: Mylène Josserand <mylene.josserand@bootlin.com>
|
||||
+ * Alistair Francis <alistair@alistair23.me>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/crc-itu-t.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
+#include <linux/input/mt.h>
|
||||
+#include <linux/input/touchscreen.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+#define CYTTSP5_NAME "cyttsp5"
|
||||
+#define CY_I2C_DATA_SIZE (2 * 256)
|
||||
+#define HID_VERSION 0x0100
|
||||
+#define CY_MAX_INPUT 512
|
||||
+#define CYTTSP5_PREALLOCATED_CMD_BUFFER 32
|
||||
+#define CY_BITS_PER_BTN 1
|
||||
+#define CY_NUM_BTN_EVENT_ID GENMASK(CY_BITS_PER_BTN, 0)
|
||||
+
|
||||
+#define MAX_AREA 255
|
||||
+#define HID_OUTPUT_BL_SOP 0x1
|
||||
+#define HID_OUTPUT_BL_EOP 0x17
|
||||
+#define HID_OUTPUT_BL_LAUNCH_APP 0x3B
|
||||
+#define HID_OUTPUT_BL_LAUNCH_APP_SIZE 11
|
||||
+#define HID_OUTPUT_GET_SYSINFO 0x2
|
||||
+#define HID_OUTPUT_GET_SYSINFO_SIZE 5
|
||||
+#define HID_OUTPUT_MAX_CMD_SIZE 12
|
||||
+
|
||||
+#define HID_DESC_REG 0x1
|
||||
+#define HID_INPUT_REG 0x3
|
||||
+#define HID_OUTPUT_REG 0x4
|
||||
+
|
||||
+#define REPORT_ID_TOUCH 0x1
|
||||
+#define REPORT_ID_BTN 0x3
|
||||
+#define REPORT_SIZE_5 5
|
||||
+#define REPORT_SIZE_8 8
|
||||
+#define REPORT_SIZE_16 16
|
||||
+
|
||||
+/* Touch reports offsets */
|
||||
+/* Header offsets */
|
||||
+#define TOUCH_REPORT_DESC_HDR_CONTACTCOUNT 16
|
||||
+/* Record offsets */
|
||||
+#define TOUCH_REPORT_DESC_CONTACTID 8
|
||||
+#define TOUCH_REPORT_DESC_X 16
|
||||
+#define TOUCH_REPORT_DESC_Y 32
|
||||
+#define TOUCH_REPORT_DESC_P 48
|
||||
+#define TOUCH_REPORT_DESC_MAJ 56
|
||||
+#define TOUCH_REPORT_DESC_MIN 64
|
||||
+
|
||||
+/* HID */
|
||||
+#define HID_TOUCH_REPORT_ID 0x1
|
||||
+#define HID_BTN_REPORT_ID 0x3
|
||||
+#define HID_APP_RESPONSE_REPORT_ID 0x1F
|
||||
+#define HID_APP_OUTPUT_REPORT_ID 0x2F
|
||||
+#define HID_BL_RESPONSE_REPORT_ID 0x30
|
||||
+#define HID_BL_OUTPUT_REPORT_ID 0x40
|
||||
+
|
||||
+#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2
|
||||
+#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4
|
||||
+#define HID_OUTPUT_RESPONSE_CMD_MASK GENMASK(6, 0)
|
||||
+
|
||||
+#define HID_SYSINFO_SENSING_OFFSET 33
|
||||
+#define HID_SYSINFO_BTN_OFFSET 48
|
||||
+#define HID_SYSINFO_BTN_MASK GENMASK(7, 0)
|
||||
+#define HID_SYSINFO_MAX_BTN 8
|
||||
+
|
||||
+#define CY_HID_OUTPUT_TIMEOUT_MS 200
|
||||
+#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000
|
||||
+#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000
|
||||
+
|
||||
+/* maximum number of concurrent tracks */
|
||||
+#define TOUCH_REPORT_SIZE 10
|
||||
+#define TOUCH_INPUT_HEADER_SIZE 7
|
||||
+#define BTN_REPORT_SIZE 9
|
||||
+#define BTN_INPUT_HEADER_SIZE 5
|
||||
+
|
||||
+#define MAX_CY_TCH_T_IDS 32
|
||||
+
|
||||
+/* All usage pages for Touch Report */
|
||||
+#define TOUCH_REPORT_USAGE_PG_X 0x00010030
|
||||
+#define TOUCH_REPORT_USAGE_PG_Y 0x00010031
|
||||
+#define TOUCH_REPORT_USAGE_PG_P 0x000D0030
|
||||
+#define TOUCH_REPORT_USAGE_PG_CONTACTID 0x000D0051
|
||||
+#define TOUCH_REPORT_USAGE_PG_CONTACTCOUNT 0x000D0054
|
||||
+#define TOUCH_REPORT_USAGE_PG_MAJ 0xFF010062
|
||||
+#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063
|
||||
+#define TOUCH_COL_USAGE_PG 0x000D0022
|
||||
+
|
||||
+/* System Information interface definitions */
|
||||
+struct cyttsp5_sensing_conf_data_dev {
|
||||
+ u8 electrodes_x;
|
||||
+ u8 electrodes_y;
|
||||
+ __le16 len_x;
|
||||
+ __le16 len_y;
|
||||
+ __le16 res_x;
|
||||
+ __le16 res_y;
|
||||
+ __le16 max_z;
|
||||
+ u8 origin_x;
|
||||
+ u8 origin_y;
|
||||
+ u8 btn;
|
||||
+ u8 scan_mode;
|
||||
+ u8 max_num_of_tch_per_refresh_cycle;
|
||||
+} __packed;
|
||||
+
|
||||
+struct cyttsp5_sensing_conf_data {
|
||||
+ u16 res_x;
|
||||
+ u16 res_y;
|
||||
+ u16 max_z;
|
||||
+ u16 len_x;
|
||||
+ u16 len_y;
|
||||
+ u8 origin_x;
|
||||
+ u8 origin_y;
|
||||
+ u8 max_tch;
|
||||
+};
|
||||
+
|
||||
+enum cyttsp5_tch_abs { /* for ordering within the extracted touch data array */
|
||||
+ CY_TCH_X, /* X */
|
||||
+ CY_TCH_Y, /* Y */
|
||||
+ CY_TCH_P, /* P (Z) */
|
||||
+ CY_TCH_T, /* TOUCH ID */
|
||||
+ CY_TCH_MAJ, /* TOUCH_MAJOR */
|
||||
+ CY_TCH_MIN, /* TOUCH_MINOR */
|
||||
+ CY_TCH_NUM_ABS
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_tch_abs_params {
|
||||
+ size_t ofs; /* abs byte offset */
|
||||
+ size_t size; /* size in bits */
|
||||
+ size_t min; /* min value */
|
||||
+ size_t max; /* max value */
|
||||
+ size_t bofs; /* bit offset */
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_touch {
|
||||
+ int abs[CY_TCH_NUM_ABS];
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_sysinfo {
|
||||
+ struct cyttsp5_sensing_conf_data sensing_conf_data;
|
||||
+ int num_btns;
|
||||
+ struct cyttsp5_tch_abs_params tch_hdr;
|
||||
+ struct cyttsp5_tch_abs_params tch_abs[CY_TCH_NUM_ABS];
|
||||
+ u32 key_code[HID_SYSINFO_MAX_BTN];
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_hid_desc {
|
||||
+ __le16 hid_desc_len;
|
||||
+ u8 packet_id;
|
||||
+ u8 reserved_byte;
|
||||
+ __le16 bcd_version;
|
||||
+ __le16 report_desc_len;
|
||||
+ __le16 report_desc_register;
|
||||
+ __le16 input_register;
|
||||
+ __le16 max_input_len;
|
||||
+ __le16 output_register;
|
||||
+ __le16 max_output_len;
|
||||
+ __le16 command_register;
|
||||
+ __le16 data_register;
|
||||
+ __le16 vendor_id;
|
||||
+ __le16 product_id;
|
||||
+ __le16 version_id;
|
||||
+ u8 reserved[4];
|
||||
+} __packed;
|
||||
+
|
||||
+struct cyttsp5 {
|
||||
+ struct device *dev;
|
||||
+ struct completion cmd_done;
|
||||
+ struct cyttsp5_sysinfo sysinfo;
|
||||
+ struct cyttsp5_hid_desc hid_desc;
|
||||
+ u8 cmd_buf[CYTTSP5_PREALLOCATED_CMD_BUFFER];
|
||||
+ u8 input_buf[CY_MAX_INPUT];
|
||||
+ u8 response_buf[CY_MAX_INPUT];
|
||||
+ struct gpio_desc *reset_gpio;
|
||||
+ struct input_dev *input;
|
||||
+ char phys[NAME_MAX];
|
||||
+ int num_prv_rec;
|
||||
+ struct regmap *regmap;
|
||||
+ struct touchscreen_properties prop;
|
||||
+ struct regulator *vdd;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * For what is understood in the datasheet, the register does not
|
||||
+ * matter. For consistency, use the Input Register address
|
||||
+ * but it does mean anything to the device. The important data
|
||||
+ * to send is the I2C address
|
||||
+ */
|
||||
+static int cyttsp5_read(struct cyttsp5 *ts, u8 *buf, u32 max)
|
||||
+{
|
||||
+ int error;
|
||||
+ u32 size;
|
||||
+ u8 temp[2];
|
||||
+
|
||||
+ /* Read the frame to retrieve the size */
|
||||
+ error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, temp, sizeof(temp));
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+
|
||||
+ size = get_unaligned_le16(temp);
|
||||
+ if (!size || size == 2)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (size > max)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Get the real value */
|
||||
+ return regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, size);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_write(struct cyttsp5 *ts, unsigned int reg, u8 *data,
|
||||
+ size_t size)
|
||||
+{
|
||||
+ u8 cmd[HID_OUTPUT_MAX_CMD_SIZE];
|
||||
+
|
||||
+ if (size + 1 > HID_OUTPUT_MAX_CMD_SIZE)
|
||||
+ return -E2BIG;
|
||||
+
|
||||
+ /* High bytes of register address needed as first byte of cmd */
|
||||
+ cmd[0] = (reg >> 8) & 0xFF ;
|
||||
+
|
||||
+ /* Copy the rest of the data */
|
||||
+ if (data)
|
||||
+ memcpy(&cmd[1], data, size);
|
||||
+
|
||||
+ /*
|
||||
+ * The hardware wants to receive a frame with the address register
|
||||
+ * contained in the first two bytes. As the regmap_write function
|
||||
+ * add the register adresse in the frame, we use the low byte as
|
||||
+ * first frame byte for the address register and the first
|
||||
+ * data byte is the high register + left of the cmd to send
|
||||
+ */
|
||||
+ return regmap_bulk_write(ts->regmap, reg & 0xFF, cmd, size + 1);
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_touch_axis(int *axis, int size, int max, u8 *xy_data,
|
||||
+ int bofs)
|
||||
+{
|
||||
+ int nbyte;
|
||||
+
|
||||
+ for (nbyte = 0, *axis = 0; nbyte < size; nbyte++)
|
||||
+ *axis += ((xy_data[nbyte] >> bofs) << (nbyte * 8));
|
||||
+
|
||||
+ *axis &= max - 1;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_touch_record(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_touch *touch, u8 *xy_data)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ enum cyttsp5_tch_abs abs;
|
||||
+
|
||||
+ for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++)
|
||||
+ cyttsp5_get_touch_axis(&touch->abs[abs],
|
||||
+ si->tch_abs[abs].size,
|
||||
+ si->tch_abs[abs].max,
|
||||
+ xy_data + si->tch_abs[abs].ofs,
|
||||
+ si->tch_abs[abs].bofs);
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_mt_touches(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_touch *tch, int num_cur_tch)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int i, t = 0, offset = 0;
|
||||
+ DECLARE_BITMAP(ids, MAX_CY_TCH_T_IDS);
|
||||
+ u8 *tch_addr;
|
||||
+ int tmp;
|
||||
+
|
||||
+ bitmap_zero(ids, MAX_CY_TCH_T_IDS);
|
||||
+ memset(tch->abs, 0, sizeof(tch->abs));
|
||||
+
|
||||
+ switch (ts->input_buf[2]) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ offset = TOUCH_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ offset = BTN_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num_cur_tch; i++) {
|
||||
+ tch_addr = ts->input_buf + offset + (i * TOUCH_REPORT_SIZE);
|
||||
+ cyttsp5_get_touch_record(ts, tch, tch_addr);
|
||||
+
|
||||
+ /* Convert MAJOR/MINOR from mm to resolution */
|
||||
+ tmp = tch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
|
||||
+ tch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
|
||||
+ tmp = tch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
|
||||
+ tch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
|
||||
+
|
||||
+ t = tch->abs[CY_TCH_T];
|
||||
+ input_mt_slot(ts->input, t);
|
||||
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
|
||||
+ __set_bit(t, ids);
|
||||
+
|
||||
+ /* position and pressure fields */
|
||||
+ touchscreen_report_pos(ts->input, &ts->prop,
|
||||
+ tch->abs[CY_TCH_X], tch->abs[CY_TCH_Y],
|
||||
+ true);
|
||||
+ input_report_abs(ts->input, ABS_MT_PRESSURE,
|
||||
+ tch->abs[CY_TCH_P]);
|
||||
+
|
||||
+ /* Get the extended touch fields */
|
||||
+ input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
|
||||
+ tch->abs[CY_TCH_MAJ]);
|
||||
+ input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
|
||||
+ tch->abs[CY_TCH_MIN]);
|
||||
+ }
|
||||
+
|
||||
+ ts->num_prv_rec = num_cur_tch;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_mt_attention(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int max_tch = si->sensing_conf_data.max_tch;
|
||||
+ struct cyttsp5_touch tch;
|
||||
+ u8 num_cur_tch;
|
||||
+
|
||||
+ cyttsp5_get_touch_axis((int *) &num_cur_tch, si->tch_hdr.size,
|
||||
+ si->tch_hdr.max,
|
||||
+ ts->input_buf + 3 + si->tch_hdr.ofs,
|
||||
+ si->tch_hdr.bofs);
|
||||
+
|
||||
+ if (num_cur_tch > max_tch) {
|
||||
+ dev_err(dev, "Num touch err detected (n=%d)\n", num_cur_tch);
|
||||
+ num_cur_tch = max_tch;
|
||||
+ }
|
||||
+
|
||||
+ if (num_cur_tch == 0 && ts->num_prv_rec == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* extract xy_data for all currently reported touches */
|
||||
+ if (num_cur_tch)
|
||||
+ cyttsp5_get_mt_touches(ts, &tch, num_cur_tch);
|
||||
+
|
||||
+ input_mt_sync_frame(ts->input);
|
||||
+ input_sync(ts->input);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_setup_input_device(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int max_x, max_y, max_p;
|
||||
+ int max_x_tmp, max_y_tmp;
|
||||
+ int error;
|
||||
+
|
||||
+ max_x_tmp = si->sensing_conf_data.res_x;
|
||||
+ max_y_tmp = si->sensing_conf_data.res_y;
|
||||
+ max_x = max_x_tmp - 1;
|
||||
+ max_y = max_y_tmp - 1;
|
||||
+ max_p = si->sensing_conf_data.max_z;
|
||||
+
|
||||
+ input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, max_p, 0, 0);
|
||||
+
|
||||
+ input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, MAX_AREA, 0, 0);
|
||||
+
|
||||
+ error = input_mt_init_slots(ts->input, si->tch_abs[CY_TCH_T].max,
|
||||
+ INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT);
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ error = input_register_device(ts->input);
|
||||
+ if (error < 0)
|
||||
+ dev_err(dev, "Error, failed register input device r=%d\n", error);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_parse_dt_key_code(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+
|
||||
+ if (!si->num_btns)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Initialize the button to RESERVED */
|
||||
+ memset32(si->key_code, KEY_RESERVED, si->num_btns);
|
||||
+
|
||||
+ return device_property_read_u32_array(dev, "linux,keycodes",
|
||||
+ si->key_code, si->num_btns);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_btn_attention(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int cur_btn, offset = 0;
|
||||
+ int cur_btn_state;
|
||||
+
|
||||
+ switch (ts->input_buf[2]) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ offset = TOUCH_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ offset = BTN_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (ts->input_buf[2] != HID_BTN_REPORT_ID || !si->num_btns)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* extract button press/release touch information */
|
||||
+ for (cur_btn = 0; cur_btn < si->num_btns; cur_btn++) {
|
||||
+ /* Get current button state */
|
||||
+ cur_btn_state = (ts->input_buf[offset] >> (cur_btn * CY_BITS_PER_BTN))
|
||||
+ & CY_NUM_BTN_EVENT_ID;
|
||||
+
|
||||
+ input_report_key(ts->input, si->key_code[cur_btn],
|
||||
+ cur_btn_state);
|
||||
+ input_sync(ts->input);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_validate_cmd_response(struct cyttsp5 *ts, u8 code)
|
||||
+{
|
||||
+ u16 size, crc;
|
||||
+ u8 status, report_id;
|
||||
+ int command_code;
|
||||
+
|
||||
+ size = get_unaligned_le16(&ts->response_buf[0]);
|
||||
+
|
||||
+ if (!size)
|
||||
+ return 0;
|
||||
+
|
||||
+ report_id = ts->response_buf[HID_OUTPUT_RESPONSE_REPORT_OFFSET];
|
||||
+
|
||||
+ switch (report_id) {
|
||||
+ case HID_BL_RESPONSE_REPORT_ID: {
|
||||
+ if (ts->response_buf[4] != HID_OUTPUT_BL_SOP) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong SOP\n");
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ if (ts->response_buf[size - 1] != HID_OUTPUT_BL_EOP) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong EOP\n");
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ crc = crc_itu_t(0xFFFF, &ts->response_buf[4], size - 7);
|
||||
+ if (get_unaligned_le16(&ts->response_buf[size - 3]) != crc) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong CRC 0x%X\n",
|
||||
+ crc);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ status = ts->response_buf[5];
|
||||
+ if (status) {
|
||||
+ dev_err(ts->dev, "HID output response, ERROR:%d\n",
|
||||
+ status);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case HID_APP_RESPONSE_REPORT_ID: {
|
||||
+ command_code = ts->response_buf[HID_OUTPUT_RESPONSE_CMD_OFFSET]
|
||||
+ & HID_OUTPUT_RESPONSE_CMD_MASK;
|
||||
+ if (command_code != code) {
|
||||
+ dev_err(ts->dev,
|
||||
+ "HID output response, wrong command_code:%X\n",
|
||||
+ command_code);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_si_get_btn_data(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ unsigned int btns = ts->response_buf[HID_SYSINFO_BTN_OFFSET]
|
||||
+ & HID_SYSINFO_BTN_MASK;
|
||||
+
|
||||
+ si->num_btns = hweight8(btns);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sensing_conf_data *scd = &ts->sysinfo.sensing_conf_data;
|
||||
+ struct cyttsp5_sensing_conf_data_dev *scd_dev =
|
||||
+ (struct cyttsp5_sensing_conf_data_dev *)
|
||||
+ &ts->response_buf[HID_SYSINFO_SENSING_OFFSET];
|
||||
+
|
||||
+ cyttsp5_si_get_btn_data(ts);
|
||||
+
|
||||
+ scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle;
|
||||
+ scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
+ scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
+ scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
+ scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
+ scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int rc;
|
||||
+ u8 cmd[HID_OUTPUT_GET_SYSINFO_SIZE];
|
||||
+
|
||||
+ /* HI bytes of Output register address */
|
||||
+ put_unaligned_le16(HID_OUTPUT_GET_SYSINFO_SIZE, cmd);
|
||||
+ cmd[2] = HID_APP_OUTPUT_REPORT_ID;
|
||||
+ cmd[3] = 0x0; /* Reserved */
|
||||
+ cmd[4] = HID_OUTPUT_GET_SYSINFO;
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd,
|
||||
+ HID_OUTPUT_GET_SYSINFO_SIZE);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Failed to write command %d", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID output cmd execution timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_GET_SYSINFO);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Validation of the response failed\n");
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ return cyttsp5_get_sysinfo_regs(ts);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int rc;
|
||||
+ u8 cmd[HID_OUTPUT_BL_LAUNCH_APP];
|
||||
+ u16 crc;
|
||||
+
|
||||
+ put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd);
|
||||
+ cmd[2] = HID_BL_OUTPUT_REPORT_ID;
|
||||
+ cmd[3] = 0x0; /* Reserved */
|
||||
+ cmd[4] = HID_OUTPUT_BL_SOP;
|
||||
+ cmd[5] = HID_OUTPUT_BL_LAUNCH_APP;
|
||||
+ put_unaligned_le16(0x00, &cmd[6]);
|
||||
+ crc = crc_itu_t(0xFFFF, &cmd[4], 4);
|
||||
+ put_unaligned_le16(crc, &cmd[8]);
|
||||
+ cmd[10] = HID_OUTPUT_BL_EOP;
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd,
|
||||
+ HID_OUTPUT_BL_LAUNCH_APP_SIZE);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Failed to write command %d", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_OUTPUT_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID output cmd execution timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_BL_LAUNCH_APP);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Validation of the response failed\n");
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_hid_desc *desc)
|
||||
+{
|
||||
+ struct device *dev = ts->dev;
|
||||
+ __le16 hid_desc_register = HID_DESC_REG;
|
||||
+ int rc;
|
||||
+ u8 cmd[2];
|
||||
+
|
||||
+ /* Set HID descriptor register */
|
||||
+ memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register));
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0);
|
||||
+ if (rc) {
|
||||
+ dev_err(dev, "Failed to get HID descriptor, rc=%d\n", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID get descriptor timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(desc, ts->response_buf, sizeof(*desc));
|
||||
+
|
||||
+ /* Check HID descriptor length and version */
|
||||
+ if (le16_to_cpu(desc->hid_desc_len) != sizeof(*desc) ||
|
||||
+ le16_to_cpu(desc->bcd_version) != HID_VERSION) {
|
||||
+ dev_err(dev, "Unsupported HID version\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fill_tch_abs(struct cyttsp5_tch_abs_params *tch_abs, int report_size,
|
||||
+ int offset)
|
||||
+{
|
||||
+ tch_abs->ofs = offset / 8;
|
||||
+ tch_abs->size = report_size / 8;
|
||||
+ if (report_size % 8)
|
||||
+ tch_abs->size += 1;
|
||||
+ tch_abs->min = 0;
|
||||
+ tch_abs->max = 1 << report_size;
|
||||
+ tch_abs->bofs = offset - (tch_abs->ofs << 3);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t cyttsp5_handle_irq(int irq, void *handle)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = handle;
|
||||
+ int report_id;
|
||||
+ int size;
|
||||
+ int error;
|
||||
+
|
||||
+ error = cyttsp5_read(ts, ts->input_buf, CY_MAX_INPUT);
|
||||
+ if (error)
|
||||
+ return IRQ_HANDLED;
|
||||
+
|
||||
+ size = get_unaligned_le16(&ts->input_buf[0]);
|
||||
+ if (size == 0) {
|
||||
+ /* reset */
|
||||
+ report_id = 0;
|
||||
+ size = 2;
|
||||
+ } else {
|
||||
+ report_id = ts->input_buf[2];
|
||||
+ }
|
||||
+
|
||||
+ switch (report_id) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ cyttsp5_mt_attention(ts->dev);
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ cyttsp5_btn_attention(ts->dev);
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* It is not an input but a command response */
|
||||
+ memcpy(ts->response_buf, ts->input_buf, size);
|
||||
+ complete(&ts->cmd_done);
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_deassert_int(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ u16 size;
|
||||
+ u8 buf[2];
|
||||
+ int error;
|
||||
+
|
||||
+ error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, sizeof(buf));
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ size = get_unaligned_le16(&buf[0]);
|
||||
+ if (size == 2 || size == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_fill_all_touch(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_X], REPORT_SIZE_16,
|
||||
+ TOUCH_REPORT_DESC_X);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_Y], REPORT_SIZE_16,
|
||||
+ TOUCH_REPORT_DESC_Y);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_P], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_P);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_T], REPORT_SIZE_5,
|
||||
+ TOUCH_REPORT_DESC_CONTACTID);
|
||||
+ fill_tch_abs(&si->tch_hdr, REPORT_SIZE_5,
|
||||
+ TOUCH_REPORT_DESC_HDR_CONTACTCOUNT);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_MAJ], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_MAJ);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_MIN], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_MIN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_startup(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ error = cyttsp5_deassert_int(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Error on deassert int r=%d\n", error);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Launch the application as the device starts in bootloader mode
|
||||
+ * because of a power-on-reset
|
||||
+ */
|
||||
+ error = cyttsp5_hid_output_bl_launch_app(ts);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on launch app r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_get_hid_descriptor(ts, &ts->hid_desc);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on getting HID descriptor r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_fill_all_touch(ts);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on report descriptor r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_hid_output_get_sysinfo(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Error on getting sysinfo r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_cleanup(void *data)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = data;
|
||||
+
|
||||
+ regulator_disable(ts->vdd);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
+ const char *name)
|
||||
+{
|
||||
+ struct cyttsp5 *ts;
|
||||
+ struct cyttsp5_sysinfo *si;
|
||||
+ int error, i;
|
||||
+
|
||||
+ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
|
||||
+ if (!ts)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Initialize device info */
|
||||
+ ts->regmap = regmap;
|
||||
+ ts->dev = dev;
|
||||
+ si = &ts->sysinfo;
|
||||
+ dev_set_drvdata(dev, ts);
|
||||
+
|
||||
+ init_completion(&ts->cmd_done);
|
||||
+
|
||||
+ /* Power up the device */
|
||||
+ ts->vdd = devm_regulator_get(dev, "vdd");
|
||||
+ if (IS_ERR(ts->vdd)) {
|
||||
+ error = PTR_ERR(ts->vdd);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = devm_add_action_or_reset(dev, cyttsp5_cleanup, ts);
|
||||
+ if (error) {
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = regulator_enable(ts->vdd);
|
||||
+ if (error) {
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ ts->input = devm_input_allocate_device(dev);
|
||||
+ if (!ts->input) {
|
||||
+ dev_err(dev, "Error, failed to allocate input device\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ ts->input->name = "cyttsp5";
|
||||
+ scnprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
|
||||
+ ts->input->phys = ts->phys;
|
||||
+ input_set_drvdata(ts->input, ts);
|
||||
+
|
||||
+ /* Reset the gpio to be in a reset state */
|
||||
+ ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
+ if (IS_ERR(ts->reset_gpio)) {
|
||||
+ error = PTR_ERR(ts->reset_gpio);
|
||||
+ dev_err(dev, "Failed to request reset gpio, error %d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+ gpiod_set_value(ts->reset_gpio, 0);
|
||||
+
|
||||
+ /* Need a delay to have device up */
|
||||
+ msleep(20);
|
||||
+
|
||||
+ error = devm_request_threaded_irq(dev, irq, NULL, cyttsp5_handle_irq,
|
||||
+ IRQF_ONESHOT, name, ts);
|
||||
+ if (error) {
|
||||
+ dev_err(dev, "unable to request IRQ\n");
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_startup(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Fail initial startup r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_parse_dt_key_code(dev);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error while parsing dts %d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ touchscreen_parse_properties(ts->input, true, &ts->prop);
|
||||
+
|
||||
+ __set_bit(EV_KEY, ts->input->evbit);
|
||||
+ for (i = 0; i < si->num_btns; i++)
|
||||
+ __set_bit(si->key_code[i], ts->input->keybit);
|
||||
+
|
||||
+ return cyttsp5_setup_input_device(dev);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_i2c_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ struct regmap *regmap;
|
||||
+ static const struct regmap_config config = {
|
||||
+ .reg_bits = 8,
|
||||
+ .val_bits = 8,
|
||||
+ };
|
||||
+
|
||||
+ regmap = devm_regmap_init_i2c(client, &config);
|
||||
+ if (IS_ERR(regmap)) {
|
||||
+ dev_err(&client->dev, "regmap allocation failed: %ld\n",
|
||||
+ PTR_ERR(regmap));
|
||||
+ return PTR_ERR(regmap);
|
||||
+ }
|
||||
+
|
||||
+ return cyttsp5_probe(&client->dev, regmap, client->irq, client->name);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id cyttsp5_of_match[] = {
|
||||
+ { .compatible = "cypress,tt21000", },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
|
||||
+
|
||||
+static const struct i2c_device_id cyttsp5_i2c_id[] = {
|
||||
+ { CYTTSP5_NAME, 0, },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
|
||||
+
|
||||
+static struct i2c_driver cyttsp5_i2c_driver = {
|
||||
+ .driver = {
|
||||
+ .name = CYTTSP5_NAME,
|
||||
+ .of_match_table = cyttsp5_of_match,
|
||||
+ },
|
||||
+ .probe = cyttsp5_i2c_probe,
|
||||
+ .id_table = cyttsp5_i2c_id,
|
||||
+};
|
||||
+module_i2c_driver(cyttsp5_i2c_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("Touchscreen driver for Cypress TrueTouch Gen 5 Product");
|
||||
+MODULE_AUTHOR("Mylène Josserand <mylene.josserand@bootlin.com>");
|
||||
--
|
||||
GitLab
|
||||
|
108
nongnu/packages/patches/pinenote-touchscreen-2.patch
Normal file
108
nongnu/packages/patches/pinenote-touchscreen-2.patch
Normal file
|
@ -0,0 +1,108 @@
|
|||
From d6bb8a6b5a5210fea70bc590350bfca3a9e3a7a2 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Geis <pgwipeout@gmail.com>
|
||||
Date: Sat, 15 Jan 2022 21:50:45 -0500
|
||||
Subject: [PATCH] Input: cyttsp5: support touchscreen device tree overrides
|
||||
|
||||
It is possible for the cyttsp5 chip to not have a configuration burned
|
||||
to it.
|
||||
This leads to a sitatuion where all calibration values return zero,
|
||||
leading to a broken touchscreen configuration.
|
||||
|
||||
The current driver does not support utilizing overrides from the device
|
||||
tree.
|
||||
Extend the driver to support this, and permit it to do some basic sanity
|
||||
checking of the values for the touchscreen and abort if they are
|
||||
invalid.
|
||||
|
||||
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
|
||||
---
|
||||
drivers/input/touchscreen/cyttsp5.c | 62 ++++++++++++++++++++++++++---
|
||||
1 file changed, 57 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
|
||||
index 3ac45108090c..e837985d199a 100644
|
||||
--- a/drivers/input/touchscreen/cyttsp5.c
|
||||
+++ b/drivers/input/touchscreen/cyttsp5.c
|
||||
@@ -507,15 +507,66 @@ static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts)
|
||||
struct cyttsp5_sensing_conf_data_dev *scd_dev =
|
||||
(struct cyttsp5_sensing_conf_data_dev *)
|
||||
&ts->response_buf[HID_SYSINFO_SENSING_OFFSET];
|
||||
+ u32 tmp;
|
||||
|
||||
cyttsp5_si_get_btn_data(ts);
|
||||
|
||||
scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle;
|
||||
- scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
- scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
- scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
- scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
- scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+
|
||||
+ if (scd->max_tch == 0) {
|
||||
+ dev_dbg(ts->dev, "Max touch points cannot be zero\n");
|
||||
+ scd->max_tch = 2;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-size-x", &tmp))
|
||||
+ scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
+ else
|
||||
+ scd->res_x = tmp;
|
||||
+
|
||||
+ if (scd->res_x == 0) {
|
||||
+ dev_err(ts->dev, "ABS_X cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-size-y", &tmp))
|
||||
+ scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
+ else
|
||||
+ scd->res_y = tmp;
|
||||
+
|
||||
+ if (scd->res_y == 0) {
|
||||
+ dev_err(ts->dev, "ABS_Y cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-max-pressure", &tmp))
|
||||
+ scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
+ else
|
||||
+ scd->max_z = tmp;
|
||||
+
|
||||
+ if (scd->max_z == 0) {
|
||||
+ dev_err(ts->dev, "ABS_PRESSURE cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-x-mm", &tmp))
|
||||
+ scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
+ else
|
||||
+ scd->len_x = tmp;
|
||||
+
|
||||
+ if (scd->len_x == 0) {
|
||||
+ dev_dbg(ts->dev, "Touchscreen size x cannot be zero\n");
|
||||
+ scd->len_x = scd->res_x + 1;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-y-mm", &tmp))
|
||||
+ scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+ else
|
||||
+ scd->len_y = tmp;
|
||||
+
|
||||
+ if (scd->len_y == 0) {
|
||||
+ dev_dbg(ts->dev, "Touchscreen size y cannot be zero\n");
|
||||
+ scd->len_y = scd->res_y + 1;
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -877,6 +928,7 @@ static int cyttsp5_i2c_probe(struct i2c_client *client,
|
||||
|
||||
static const struct of_device_id cyttsp5_of_match[] = {
|
||||
{ .compatible = "cypress,tt21000", },
|
||||
+ { .compatible = "cypress,tma448", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
|
||||
--
|
||||
GitLab
|
||||
|
48
nongnu/packages/patches/pinenote_defconfig.patch
Normal file
48
nongnu/packages/patches/pinenote_defconfig.patch
Normal file
|
@ -0,0 +1,48 @@
|
|||
diff --git a/arch/arm64/configs/pinenote_defconfig b/arch/arm64/configs/pinenote_defconfig
|
||||
index bea435dc92c4..86cdaa92cc2f 100644
|
||||
--- a/arch/arm64/configs/pinenote_defconfig
|
||||
+++ b/arch/arm64/configs/pinenote_defconfig
|
||||
@@ -86,6 +86,7 @@ CONFIG_ARCH_ROCKCHIP=y
|
||||
# CONFIG_NVIDIA_CARMEL_CNP_ERRATUM is not set
|
||||
# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set
|
||||
CONFIG_SCHED_MC=y
|
||||
+CONFIG_SCHED_SMT=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_HZ_1000=y
|
||||
# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
|
||||
@@ -155,7 +156,7 @@ CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_BT=m
|
||||
CONFIG_BT_RFCOMM=y
|
||||
CONFIG_BT_RFCOMM_TTY=y
|
||||
-CONFIG_BT_HIDP=y
|
||||
+CONFIG_BT_HIDP=m
|
||||
CONFIG_BT_HS=y
|
||||
CONFIG_BT_LEDS=y
|
||||
CONFIG_BT_HCIUART=m
|
||||
@@ -223,14 +224,16 @@ CONFIG_BRCMFMAC=m
|
||||
# CONFIG_WLAN_VENDOR_TI is not set
|
||||
# CONFIG_WLAN_VENDOR_ZYDAS is not set
|
||||
# CONFIG_WLAN_VENDOR_QUANTENNA is not set
|
||||
+CONFIG_INPUT_MOUSEDEV=m
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_KEYBOARD_ADC=m
|
||||
# CONFIG_KEYBOARD_ATKBD is not set
|
||||
CONFIG_KEYBOARD_GPIO=y
|
||||
-# CONFIG_INPUT_MOUSE is not set
|
||||
+CONFIG_INPUT_MOUSE=y
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
|
||||
CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
|
||||
+CONFIG_TOUCHSCREEN_CYTTSP5=m
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_RK805_PWRKEY=y
|
||||
CONFIG_INPUT_WS8100_PEN=m
|
||||
@@ -459,6 +462,8 @@ CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
|
||||
CONFIG_SND_SIMPLE_CARD=m
|
||||
CONFIG_HID_BATTERY_STRENGTH=y
|
||||
CONFIG_HIDRAW=y
|
||||
+CONFIG_UHID=m
|
||||
+CONFIG_HID_MICROSOFT=y
|
||||
CONFIG_USB_HIDDEV=y
|
||||
CONFIG_I2C_HID_OF=m
|
||||
CONFIG_I2C_HID_OF_GOODIX=m
|
750
nongnu/packages/patches/pinephone-0001-bootsplash.patch
Normal file
750
nongnu/packages/patches/pinephone-0001-bootsplash.patch
Normal file
|
@ -0,0 +1,750 @@
|
|||
diff --git a/MAINTAINERS b/MAINTAINERS
|
||||
index a74227ad082e..b5633b56391e 100644
|
||||
--- a/MAINTAINERS
|
||||
+++ b/MAINTAINERS
|
||||
@@ -3582,6 +3614,18 @@ F: drivers/net/bonding/
|
||||
F: include/net/bond*
|
||||
F: include/uapi/linux/if_bonding.h
|
||||
|
||||
+BOOTSPLASH
|
||||
+M: Max Staudt <mstaudt@suse.de>
|
||||
+L: linux-fbdev@vger.kernel.org
|
||||
+S: Maintained
|
||||
+F: Documentation/ABI/testing/sysfs-platform-bootsplash
|
||||
+F: Documentation/bootsplash.rst
|
||||
+F: drivers/video/fbdev/core/bootsplash*.*
|
||||
+F: drivers/video/fbdev/core/dummycon.c
|
||||
+F: include/linux/bootsplash.h
|
||||
+F: include/uapi/linux/bootsplash_file.h
|
||||
+F: tools/bootsplash/*
|
||||
+
|
||||
BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
|
||||
M: Dan Robertson <dan@dlrobertson.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
|
||||
index 7f1f1fbcef9e..f3ff976266fe 100644
|
||||
--- a/drivers/video/console/Kconfig
|
||||
+++ b/drivers/video/console/Kconfig
|
||||
@@ -151,6 +151,30 @@ config FRAMEBUFFER_CONSOLE_ROTATION
|
||||
such that other users of the framebuffer will remain normally
|
||||
oriented.
|
||||
|
||||
+config BOOTSPLASH
|
||||
+ bool "Bootup splash screen"
|
||||
+ depends on FRAMEBUFFER_CONSOLE
|
||||
+ help
|
||||
+ This option enables the Linux bootsplash screen.
|
||||
+
|
||||
+ The bootsplash is a full-screen logo or animation indicating a
|
||||
+ booting system. It replaces the classic scrolling text with a
|
||||
+ graphical alternative, similar to other systems.
|
||||
+
|
||||
+ Since this is technically implemented as a hook on top of fbcon,
|
||||
+ it can only work if the FRAMEBUFFER_CONSOLE is enabled and a
|
||||
+ framebuffer driver is active. Thus, to get a text-free boot,
|
||||
+ the system needs to boot with vesafb, efifb, or similar.
|
||||
+
|
||||
+ Once built into the kernel, the bootsplash needs to be enabled
|
||||
+ with bootsplash.enabled=1 and a splash file needs to be supplied.
|
||||
+
|
||||
+ Further documentation can be found in:
|
||||
+ Documentation/fb/bootsplash.txt
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+ This is typically used by distributors and system integrators.
|
||||
+
|
||||
config STI_CONSOLE
|
||||
bool "STI text console"
|
||||
depends on PARISC
|
||||
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
|
||||
index 73493bbd7a15..66895321928e 100644
|
||||
--- a/drivers/video/fbdev/core/Makefile
|
||||
+++ b/drivers/video/fbdev/core/Makefile
|
||||
@@ -29,3 +29,6 @@ obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o
|
||||
obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o
|
||||
obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
||||
+
|
||||
+obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
|
||||
+ dummyblit.o
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
||||
new file mode 100644
|
||||
index 000000000000..e449755af268
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
||||
@@ -0,0 +1,294 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (Main file: Glue code, workers, timer, PM, kernel and userland API)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
||||
+
|
||||
+
|
||||
+#include <linux/atomic.h>
|
||||
+#include <linux/bootsplash.h>
|
||||
+#include <linux/console.h>
|
||||
+#include <linux/device.h> /* dev_warn() */
|
||||
+#include <linux/fb.h>
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/printk.h>
|
||||
+#include <linux/selection.h> /* console_blanked */
|
||||
+#include <linux/stringify.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+#include <linux/vt_kern.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+
|
||||
+#include "bootsplash_internal.h"
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * We only have one splash screen, so let's keep a single
|
||||
+ * instance of the internal state.
|
||||
+ */
|
||||
+static struct splash_priv splash_state;
|
||||
+
|
||||
+
|
||||
+static void splash_callback_redraw_vc(struct work_struct *ignored)
|
||||
+{
|
||||
+ if (console_blanked)
|
||||
+ return;
|
||||
+
|
||||
+ console_lock();
|
||||
+ if (vc_cons[fg_console].d)
|
||||
+ update_screen(vc_cons[fg_console].d);
|
||||
+ console_unlock();
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool is_fb_compatible(const struct fb_info *info)
|
||||
+{
|
||||
+ if (!(info->flags & FBINFO_BE_MATH)
|
||||
+ != !fb_be_math((struct fb_info *)info)) {
|
||||
+ dev_warn(info->device,
|
||||
+ "Can't draw on foreign endianness framebuffer.\n");
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (info->flags & FBINFO_MISC_TILEBLITTING) {
|
||||
+ dev_warn(info->device,
|
||||
+ "Can't draw splash on tiling framebuffer.\n");
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (info->fix.type != FB_TYPE_PACKED_PIXELS
|
||||
+ || (info->fix.visual != FB_VISUAL_TRUECOLOR
|
||||
+ && info->fix.visual != FB_VISUAL_DIRECTCOLOR)) {
|
||||
+ dev_warn(info->device,
|
||||
+ "Can't draw splash on non-packed or non-truecolor framebuffer.\n");
|
||||
+
|
||||
+ dev_warn(info->device,
|
||||
+ " type: %u visual: %u\n",
|
||||
+ info->fix.type, info->fix.visual);
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (info->var.bits_per_pixel != 16
|
||||
+ && info->var.bits_per_pixel != 24
|
||||
+ && info->var.bits_per_pixel != 32) {
|
||||
+ dev_warn(info->device,
|
||||
+ "We only support drawing on framebuffers with 16, 24, or 32 bpp, not %d.\n",
|
||||
+ info->var.bits_per_pixel);
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Called by fbcon_switch() when an instance is activated or refreshed.
|
||||
+ */
|
||||
+void bootsplash_render_full(struct fb_info *info)
|
||||
+{
|
||||
+ if (!is_fb_compatible(info))
|
||||
+ return;
|
||||
+
|
||||
+ bootsplash_do_render_background(info);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * External status enquiry and on/off switch
|
||||
+ */
|
||||
+bool bootsplash_would_render_now(void)
|
||||
+{
|
||||
+ return !oops_in_progress
|
||||
+ && !console_blanked
|
||||
+ && bootsplash_is_enabled();
|
||||
+}
|
||||
+
|
||||
+bool bootsplash_is_enabled(void)
|
||||
+{
|
||||
+ bool was_enabled;
|
||||
+
|
||||
+ /* Make sure we have the newest state */
|
||||
+ smp_rmb();
|
||||
+
|
||||
+ was_enabled = test_bit(0, &splash_state.enabled);
|
||||
+
|
||||
+ return was_enabled;
|
||||
+}
|
||||
+
|
||||
+void bootsplash_disable(void)
|
||||
+{
|
||||
+ int was_enabled;
|
||||
+
|
||||
+ was_enabled = test_and_clear_bit(0, &splash_state.enabled);
|
||||
+
|
||||
+ if (was_enabled) {
|
||||
+ if (oops_in_progress) {
|
||||
+ /* Redraw screen now so we can see a panic */
|
||||
+ if (vc_cons[fg_console].d)
|
||||
+ update_screen(vc_cons[fg_console].d);
|
||||
+ } else {
|
||||
+ /* No urgency, redraw at next opportunity */
|
||||
+ schedule_work(&splash_state.work_redraw_vc);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void bootsplash_enable(void)
|
||||
+{
|
||||
+ bool was_enabled;
|
||||
+
|
||||
+ if (oops_in_progress)
|
||||
+ return;
|
||||
+
|
||||
+ was_enabled = test_and_set_bit(0, &splash_state.enabled);
|
||||
+
|
||||
+ if (!was_enabled)
|
||||
+ schedule_work(&splash_state.work_redraw_vc);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Userland API via platform device in sysfs
|
||||
+ */
|
||||
+static ssize_t splash_show_enabled(struct device *dev,
|
||||
+ struct device_attribute *attr, char *buf)
|
||||
+{
|
||||
+ return sprintf(buf, "%d\n", bootsplash_is_enabled());
|
||||
+}
|
||||
+
|
||||
+static ssize_t splash_store_enabled(struct device *device,
|
||||
+ struct device_attribute *attr,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ bool enable;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!buf || !count)
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ err = kstrtobool(buf, &enable);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (enable)
|
||||
+ bootsplash_enable();
|
||||
+ else
|
||||
+ bootsplash_disable();
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static DEVICE_ATTR(enabled, 0644, splash_show_enabled, splash_store_enabled);
|
||||
+
|
||||
+
|
||||
+static struct attribute *splash_dev_attrs[] = {
|
||||
+ &dev_attr_enabled.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+ATTRIBUTE_GROUPS(splash_dev);
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Power management fixup via platform device
|
||||
+ *
|
||||
+ * When the system is woken from sleep or restored after hibernating, we
|
||||
+ * cannot expect the screen contents to still be present in video RAM.
|
||||
+ * Thus, we have to redraw the splash if we're currently active.
|
||||
+ */
|
||||
+static int splash_resume(struct device *device)
|
||||
+{
|
||||
+ if (bootsplash_would_render_now())
|
||||
+ schedule_work(&splash_state.work_redraw_vc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int splash_suspend(struct device *device)
|
||||
+{
|
||||
+ cancel_work_sync(&splash_state.work_redraw_vc);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static const struct dev_pm_ops splash_pm_ops = {
|
||||
+ .thaw = splash_resume,
|
||||
+ .restore = splash_resume,
|
||||
+ .resume = splash_resume,
|
||||
+ .suspend = splash_suspend,
|
||||
+ .freeze = splash_suspend,
|
||||
+};
|
||||
+
|
||||
+static struct platform_driver splash_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "bootsplash",
|
||||
+ .pm = &splash_pm_ops,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Main init
|
||||
+ */
|
||||
+void bootsplash_init(void)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Initialized already? */
|
||||
+ if (splash_state.splash_device)
|
||||
+ return;
|
||||
+
|
||||
+
|
||||
+ /* Register platform device to export user API */
|
||||
+ ret = platform_driver_register(&splash_driver);
|
||||
+ if (ret) {
|
||||
+ pr_err("platform_driver_register() failed: %d\n", ret);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ splash_state.splash_device
|
||||
+ = platform_device_alloc("bootsplash", 0);
|
||||
+
|
||||
+ if (!splash_state.splash_device)
|
||||
+ goto err_driver;
|
||||
+
|
||||
+ splash_state.splash_device->dev.groups = splash_dev_groups;
|
||||
+
|
||||
+ ret = platform_device_add(splash_state.splash_device);
|
||||
+ if (ret) {
|
||||
+ pr_err("platform_device_add() failed: %d\n", ret);
|
||||
+ goto err_device;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+err_device:
|
||||
+ platform_device_put(splash_state.splash_device);
|
||||
+ splash_state.splash_device = NULL;
|
||||
+err_driver:
|
||||
+ platform_driver_unregister(&splash_driver);
|
||||
+err:
|
||||
+ pr_err("Failed to initialize.\n");
|
||||
+}
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
new file mode 100644
|
||||
index 000000000000..b11da5cb90bf
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
@@ -0,0 +1,55 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (Internal data structures used at runtime)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#ifndef __BOOTSPLASH_INTERNAL_H
|
||||
+#define __BOOTSPLASH_INTERNAL_H
|
||||
+
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/fb.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Runtime types
|
||||
+ */
|
||||
+struct splash_priv {
|
||||
+ /*
|
||||
+ * Enabled/disabled state, to be used with atomic bit operations.
|
||||
+ * Bit 0: 0 = Splash hidden
|
||||
+ * 1 = Splash shown
|
||||
+ *
|
||||
+ * Note: fbcon.c uses this twice, by calling
|
||||
+ * bootsplash_would_render_now() in set_blitting_type() and
|
||||
+ * in fbcon_switch().
|
||||
+ * This is racy, but eventually consistent: Turning the
|
||||
+ * splash on/off will cause a redraw, which calls
|
||||
+ * fbcon_switch(), which calls set_blitting_type().
|
||||
+ * So the last on/off toggle will make things consistent.
|
||||
+ */
|
||||
+ unsigned long enabled;
|
||||
+
|
||||
+ /* Our gateway to userland via sysfs */
|
||||
+ struct platform_device *splash_device;
|
||||
+
|
||||
+ struct work_struct work_redraw_vc;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Rendering functions
|
||||
+ */
|
||||
+void bootsplash_do_render_background(struct fb_info *info);
|
||||
+
|
||||
+#endif
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
new file mode 100644
|
||||
index 000000000000..4d7e0117f653
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
@@ -0,0 +1,93 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (Rendering functions)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
||||
+
|
||||
+
|
||||
+#include <linux/bootsplash.h>
|
||||
+#include <linux/fb.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/printk.h>
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+#include "bootsplash_internal.h"
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Rendering: Internal drawing routines
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Pack pixel into target format and do Big/Little Endian handling.
|
||||
+ * This would be a good place to handle endianness conversion if necessary.
|
||||
+ */
|
||||
+static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
|
||||
+ u8 red, u8 green, u8 blue)
|
||||
+{
|
||||
+ u32 dstpix;
|
||||
+
|
||||
+ /* Quantize pixel */
|
||||
+ red = red >> (8 - dst_var->red.length);
|
||||
+ green = green >> (8 - dst_var->green.length);
|
||||
+ blue = blue >> (8 - dst_var->blue.length);
|
||||
+
|
||||
+ /* Pack pixel */
|
||||
+ dstpix = red << (dst_var->red.offset)
|
||||
+ | green << (dst_var->green.offset)
|
||||
+ | blue << (dst_var->blue.offset);
|
||||
+
|
||||
+ /*
|
||||
+ * Move packed pixel to the beginning of the memory cell,
|
||||
+ * so we can memcpy() it out easily
|
||||
+ */
|
||||
+#ifdef __BIG_ENDIAN
|
||||
+ switch (dst_var->bits_per_pixel) {
|
||||
+ case 16:
|
||||
+ dstpix <<= 16;
|
||||
+ break;
|
||||
+ case 24:
|
||||
+ dstpix <<= 8;
|
||||
+ break;
|
||||
+ case 32:
|
||||
+ break;
|
||||
+ }
|
||||
+#else
|
||||
+ /* This is intrinsically unnecessary on Little Endian */
|
||||
+#endif
|
||||
+
|
||||
+ return dstpix;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void bootsplash_do_render_background(struct fb_info *info)
|
||||
+{
|
||||
+ unsigned int x, y;
|
||||
+ u32 dstpix;
|
||||
+ u32 dst_octpp = info->var.bits_per_pixel / 8;
|
||||
+
|
||||
+ dstpix = pack_pixel(&info->var,
|
||||
+ 0,
|
||||
+ 0,
|
||||
+ 0);
|
||||
+
|
||||
+ for (y = 0; y < info->var.yres_virtual; y++) {
|
||||
+ u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
|
||||
+
|
||||
+ for (x = 0; x < info->var.xres_virtual; x++) {
|
||||
+ memcpy(dstline, &dstpix, dst_octpp);
|
||||
+
|
||||
+ dstline += dst_octpp;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/drivers/video/fbdev/core/dummyblit.c b/drivers/video/fbdev/core/dummyblit.c
|
||||
new file mode 100644
|
||||
index 000000000000..8c22ff92ce24
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/fbdev/core/dummyblit.c
|
||||
@@ -0,0 +1,89 @@
|
||||
+/*
|
||||
+ * linux/drivers/video/fbdev/core/dummyblit.c -- Dummy Blitting Operation
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * These functions are used in place of blitblit/tileblit to suppress
|
||||
+ * fbcon's text output while a splash is shown.
|
||||
+ *
|
||||
+ * Only suppressing actual rendering keeps the text buffer in the VC layer
|
||||
+ * intact and makes it easy to switch back from the bootsplash to a full
|
||||
+ * text console with a simple redraw (with the original functions in place).
|
||||
+ *
|
||||
+ * Based on linux/drivers/video/fbdev/core/bitblit.c
|
||||
+ * and linux/drivers/video/fbdev/core/tileblit.c
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/fb.h>
|
||||
+#include <linux/vt_kern.h>
|
||||
+#include <linux/console.h>
|
||||
+#include <asm/types.h>
|
||||
+#include "fbcon.h"
|
||||
+
|
||||
+static void dummy_bmove(struct vc_data *vc, struct fb_info *info, int sy,
|
||||
+ int sx, int dy, int dx, int height, int width)
|
||||
+{
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static void dummy_clear(struct vc_data *vc, struct fb_info *info, int sy,
|
||||
+ int sx, int height, int width)
|
||||
+{
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static void dummy_putcs(struct vc_data *vc, struct fb_info *info,
|
||||
+ const unsigned short *s, int count, int yy, int xx,
|
||||
+ int fg, int bg)
|
||||
+{
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static void dummy_clear_margins(struct vc_data *vc, struct fb_info *info,
|
||||
+ int color, int bottom_only)
|
||||
+{
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static void dummy_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
+{
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+static int dummy_update_start(struct fb_info *info)
|
||||
+{
|
||||
+ /*
|
||||
+ * Copied from bitblit.c and tileblit.c
|
||||
+ *
|
||||
+ * As of Linux 4.12, nobody seems to care about our return value.
|
||||
+ */
|
||||
+ struct fbcon_ops *ops = info->fbcon_par;
|
||||
+ int err;
|
||||
+
|
||||
+ err = fb_pan_display(info, &ops->var);
|
||||
+ ops->var.xoffset = info->var.xoffset;
|
||||
+ ops->var.yoffset = info->var.yoffset;
|
||||
+ ops->var.vmode = info->var.vmode;
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+void fbcon_set_dummyops(struct fbcon_ops *ops)
|
||||
+{
|
||||
+ ops->bmove = dummy_bmove;
|
||||
+ ops->clear = dummy_clear;
|
||||
+ ops->putcs = dummy_putcs;
|
||||
+ ops->clear_margins = dummy_clear_margins;
|
||||
+ ops->cursor = dummy_cursor;
|
||||
+ ops->update_start = dummy_update_start;
|
||||
+ ops->rotate_font = NULL;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(fbcon_set_dummyops);
|
||||
+
|
||||
+MODULE_AUTHOR("Max Staudt <mstaudt@suse.de>");
|
||||
+MODULE_DESCRIPTION("Dummy Blitting Operation");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
||||
index 04612f938bab..9a39a6fcfe98 100644
|
||||
--- a/drivers/video/fbdev/core/fbcon.c
|
||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
||||
@@ -80,6 +80,7 @@
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include "fbcon.h"
|
||||
+#include <linux/bootsplash.h>
|
||||
|
||||
#ifdef FBCONDEBUG
|
||||
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
|
||||
@@ -542,6 +543,8 @@ static int do_fbcon_takeover(int show_logo)
|
||||
for (i = first_fb_vc; i <= last_fb_vc; i++)
|
||||
con2fb_map[i] = info_idx;
|
||||
|
||||
+ bootsplash_init();
|
||||
+
|
||||
err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
|
||||
fbcon_is_default);
|
||||
|
||||
@@ -661,6 +664,9 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
|
||||
else {
|
||||
fbcon_set_rotation(info);
|
||||
fbcon_set_bitops(ops);
|
||||
+
|
||||
+ if (bootsplash_would_render_now())
|
||||
+ fbcon_set_dummyops(ops);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,6 +689,19 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
|
||||
ops->p = &fb_display[vc->vc_num];
|
||||
fbcon_set_rotation(info);
|
||||
fbcon_set_bitops(ops);
|
||||
+
|
||||
+ /*
|
||||
+ * Note:
|
||||
+ * This is *eventually correct*.
|
||||
+ * Setting the fbcon operations and drawing the splash happen at
|
||||
+ * different points in time. If the splash is enabled/disabled
|
||||
+ * in between, then bootsplash_{en,dis}able will schedule a
|
||||
+ * redraw, which will again render the splash (or not) and set
|
||||
+ * the correct fbcon ops.
|
||||
+ * The last run will then be the right one.
|
||||
+ */
|
||||
+ if (bootsplash_would_render_now())
|
||||
+ fbcon_set_dummyops(ops);
|
||||
}
|
||||
|
||||
static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
|
||||
@@ -2184,6 +2203,9 @@ static int fbcon_switch(struct vc_data *vc)
|
||||
info = registered_fb[con2fb_map[vc->vc_num]];
|
||||
ops = info->fbcon_par;
|
||||
|
||||
+ if (bootsplash_would_render_now())
|
||||
+ bootsplash_render_full(info);
|
||||
+
|
||||
if (softback_top) {
|
||||
if (softback_lines)
|
||||
fbcon_set_origin(vc);
|
||||
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
|
||||
index 18f3ac144237..45f94347fe5e 100644
|
||||
--- a/drivers/video/fbdev/core/fbcon.h
|
||||
+++ b/drivers/video/fbdev/core/fbcon.h
|
||||
@@ -214,6 +214,11 @@ static inline int attr_col_ec(int shift, struct vc_data *vc,
|
||||
#define SCROLL_REDRAW 0x004
|
||||
#define SCROLL_PAN_REDRAW 0x005
|
||||
|
||||
+#ifdef CONFIG_BOOTSPLASH
|
||||
+extern void fbcon_set_dummyops(struct fbcon_ops *ops);
|
||||
+#else /* CONFIG_BOOTSPLASH */
|
||||
+#define fbcon_set_dummyops(x)
|
||||
+#endif /* CONFIG_BOOTSPLASH */
|
||||
#ifdef CONFIG_FB_TILEBLITTING
|
||||
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
|
||||
#endif
|
||||
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
|
||||
new file mode 100644
|
||||
index 000000000000..c6dd0b43180d
|
||||
--- /dev/null
|
||||
+++ b/include/linux/bootsplash.h
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#ifndef __LINUX_BOOTSPLASH_H
|
||||
+#define __LINUX_BOOTSPLASH_H
|
||||
+
|
||||
+#include <linux/fb.h>
|
||||
+
|
||||
+
|
||||
+#ifdef CONFIG_BOOTSPLASH
|
||||
+
|
||||
+extern void bootsplash_render_full(struct fb_info *info);
|
||||
+
|
||||
+extern bool bootsplash_would_render_now(void);
|
||||
+
|
||||
+extern bool bootsplash_is_enabled(void);
|
||||
+extern void bootsplash_disable(void);
|
||||
+extern void bootsplash_enable(void);
|
||||
+
|
||||
+extern void bootsplash_init(void);
|
||||
+
|
||||
+#else /* CONFIG_BOOTSPLASH */
|
||||
+
|
||||
+#define bootsplash_render_full(x)
|
||||
+
|
||||
+#define bootsplash_would_render_now() (false)
|
||||
+
|
||||
+#define bootsplash_is_enabled() (false)
|
||||
+#define bootsplash_disable()
|
||||
+#define bootsplash_enable()
|
||||
+
|
||||
+#define bootsplash_init()
|
||||
+
|
||||
+#endif /* CONFIG_BOOTSPLASH */
|
||||
+
|
||||
+
|
||||
+#endif
|
657
nongnu/packages/patches/pinephone-0002-bootsplash.patch
Normal file
657
nongnu/packages/patches/pinephone-0002-bootsplash.patch
Normal file
|
@ -0,0 +1,657 @@
|
|||
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
|
||||
index 66895321928e..6a8d1bab8a01 100644
|
||||
--- a/drivers/video/fbdev/core/Makefile
|
||||
+++ b/drivers/video/fbdev/core/Makefile
|
||||
@@ -31,4 +31,4 @@ obj-$(CONFIG_FB_SVGALIB) += svgalib.o
|
||||
obj-$(CONFIG_FB_DDC) += fb_ddc.o
|
||||
|
||||
obj-$(CONFIG_BOOTSPLASH) += bootsplash.o bootsplash_render.o \
|
||||
- dummyblit.o
|
||||
+ bootsplash_load.o dummyblit.o
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
||||
index e449755af268..843c5400fefc 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "bootsplash_internal.h"
|
||||
+#include "uapi/linux/bootsplash_file.h"
|
||||
|
||||
|
||||
/*
|
||||
@@ -102,10 +103,17 @@ static bool is_fb_compatible(const struct fb_info *info)
|
||||
*/
|
||||
void bootsplash_render_full(struct fb_info *info)
|
||||
{
|
||||
+ mutex_lock(&splash_state.data_lock);
|
||||
+
|
||||
if (!is_fb_compatible(info))
|
||||
- return;
|
||||
+ goto out;
|
||||
+
|
||||
+ bootsplash_do_render_background(info, splash_state.file);
|
||||
+
|
||||
+ bootsplash_do_render_pictures(info, splash_state.file);
|
||||
|
||||
- bootsplash_do_render_background(info);
|
||||
+out:
|
||||
+ mutex_unlock(&splash_state.data_lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +124,7 @@ bool bootsplash_would_render_now(void)
|
||||
{
|
||||
return !oops_in_progress
|
||||
&& !console_blanked
|
||||
+ && splash_state.file
|
||||
&& bootsplash_is_enabled();
|
||||
}
|
||||
|
||||
@@ -252,6 +261,7 @@ static struct platform_driver splash_driver = {
|
||||
void bootsplash_init(void)
|
||||
{
|
||||
int ret;
|
||||
+ struct splash_file_priv *fp;
|
||||
|
||||
/* Initialized already? */
|
||||
if (splash_state.splash_device)
|
||||
@@ -280,8 +290,26 @@ void bootsplash_init(void)
|
||||
}
|
||||
|
||||
|
||||
+ mutex_init(&splash_state.data_lock);
|
||||
+ set_bit(0, &splash_state.enabled);
|
||||
+
|
||||
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
||||
|
||||
+
|
||||
+ if (!splash_state.bootfile || !strlen(splash_state.bootfile))
|
||||
+ return;
|
||||
+
|
||||
+ fp = bootsplash_load_firmware(&splash_state.splash_device->dev,
|
||||
+ splash_state.bootfile);
|
||||
+
|
||||
+ if (!fp)
|
||||
+ goto err;
|
||||
+
|
||||
+ mutex_lock(&splash_state.data_lock);
|
||||
+ splash_state.splash_fb = NULL;
|
||||
+ splash_state.file = fp;
|
||||
+ mutex_unlock(&splash_state.data_lock);
|
||||
+
|
||||
return;
|
||||
|
||||
err_device:
|
||||
@@ -292,3 +320,7 @@ void bootsplash_init(void)
|
||||
err:
|
||||
pr_err("Failed to initialize.\n");
|
||||
}
|
||||
+
|
||||
+
|
||||
+module_param_named(bootfile, splash_state.bootfile, charp, 0444);
|
||||
+MODULE_PARM_DESC(bootfile, "Bootsplash file to load on boot");
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
index b11da5cb90bf..71e2a27ac0b8 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
@@ -15,15 +15,43 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/fb.h>
|
||||
+#include <linux/firmware.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
+#include "uapi/linux/bootsplash_file.h"
|
||||
+
|
||||
|
||||
/*
|
||||
* Runtime types
|
||||
*/
|
||||
+struct splash_blob_priv {
|
||||
+ struct splash_blob_header *blob_header;
|
||||
+ const void *data;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+struct splash_pic_priv {
|
||||
+ const struct splash_pic_header *pic_header;
|
||||
+
|
||||
+ struct splash_blob_priv *blobs;
|
||||
+ u16 blobs_loaded;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+struct splash_file_priv {
|
||||
+ const struct firmware *fw;
|
||||
+ const struct splash_file_header *header;
|
||||
+
|
||||
+ struct splash_pic_priv *pics;
|
||||
+};
|
||||
+
|
||||
+
|
||||
struct splash_priv {
|
||||
+ /* Bootup and runtime state */
|
||||
+ char *bootfile;
|
||||
+
|
||||
/*
|
||||
* Enabled/disabled state, to be used with atomic bit operations.
|
||||
* Bit 0: 0 = Splash hidden
|
||||
@@ -43,6 +71,13 @@ struct splash_priv {
|
||||
struct platform_device *splash_device;
|
||||
|
||||
struct work_struct work_redraw_vc;
|
||||
+
|
||||
+ /* Splash data structures including lock for everything below */
|
||||
+ struct mutex data_lock;
|
||||
+
|
||||
+ struct fb_info *splash_fb;
|
||||
+
|
||||
+ struct splash_file_priv *file;
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +85,14 @@ struct splash_priv {
|
||||
/*
|
||||
* Rendering functions
|
||||
*/
|
||||
-void bootsplash_do_render_background(struct fb_info *info);
|
||||
+void bootsplash_do_render_background(struct fb_info *info,
|
||||
+ const struct splash_file_priv *fp);
|
||||
+void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
+ const struct splash_file_priv *fp);
|
||||
+
|
||||
+
|
||||
+void bootsplash_free_file(struct splash_file_priv *fp);
|
||||
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
+ const char *path);
|
||||
|
||||
#endif
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
|
||||
new file mode 100644
|
||||
index 000000000000..fd807571ab7d
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_load.c
|
||||
@@ -0,0 +1,225 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (Loading and freeing functions)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#define pr_fmt(fmt) "bootsplash: " fmt
|
||||
+
|
||||
+
|
||||
+#include <linux/bootsplash.h>
|
||||
+#include <linux/fb.h>
|
||||
+#include <linux/firmware.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/printk.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/vmalloc.h>
|
||||
+
|
||||
+#include "bootsplash_internal.h"
|
||||
+#include "uapi/linux/bootsplash_file.h"
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Free all vmalloc()'d resources describing a splash file.
|
||||
+ */
|
||||
+void bootsplash_free_file(struct splash_file_priv *fp)
|
||||
+{
|
||||
+ if (!fp)
|
||||
+ return;
|
||||
+
|
||||
+ if (fp->pics) {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+
|
||||
+ if (pp->blobs)
|
||||
+ vfree(pp->blobs);
|
||||
+ }
|
||||
+
|
||||
+ vfree(fp->pics);
|
||||
+ }
|
||||
+
|
||||
+ release_firmware(fp->fw);
|
||||
+ vfree(fp);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Load a splash screen from a "firmware" file.
|
||||
+ *
|
||||
+ * Parsing, and sanity checks.
|
||||
+ */
|
||||
+#ifdef __BIG_ENDIAN
|
||||
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_BE
|
||||
+#else
|
||||
+ #define BOOTSPLASH_MAGIC BOOTSPLASH_MAGIC_LE
|
||||
+#endif
|
||||
+
|
||||
+struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
+ const char *path)
|
||||
+{
|
||||
+ const struct firmware *fw;
|
||||
+ struct splash_file_priv *fp;
|
||||
+ unsigned int i;
|
||||
+ const u8 *walker;
|
||||
+
|
||||
+ if (request_firmware(&fw, path, device))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (fw->size < sizeof(struct splash_file_header)
|
||||
+ || memcmp(fw->data, BOOTSPLASH_MAGIC, sizeof(fp->header->id))) {
|
||||
+ pr_err("Not a bootsplash file.\n");
|
||||
+
|
||||
+ release_firmware(fw);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ fp = vzalloc(sizeof(struct splash_file_priv));
|
||||
+ if (!fp) {
|
||||
+ release_firmware(fw);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ pr_info("Loading splash file (%li bytes)\n", fw->size);
|
||||
+
|
||||
+ fp->fw = fw;
|
||||
+ fp->header = (struct splash_file_header *)fw->data;
|
||||
+
|
||||
+ /* Sanity checks */
|
||||
+ if (fp->header->version != BOOTSPLASH_VERSION) {
|
||||
+ pr_err("Loaded v%d file, but we only support version %d\n",
|
||||
+ fp->header->version,
|
||||
+ BOOTSPLASH_VERSION);
|
||||
+
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (fw->size < sizeof(struct splash_file_header)
|
||||
+ + fp->header->num_pics
|
||||
+ * sizeof(struct splash_pic_header)
|
||||
+ + fp->header->num_blobs
|
||||
+ * sizeof(struct splash_blob_header)) {
|
||||
+ pr_err("File incomplete.\n");
|
||||
+
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Read picture headers */
|
||||
+ if (fp->header->num_pics) {
|
||||
+ fp->pics = vzalloc(fp->header->num_pics
|
||||
+ * sizeof(struct splash_pic_priv));
|
||||
+ if (!fp->pics)
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ walker = fw->data + sizeof(struct splash_file_header);
|
||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+ struct splash_pic_header *ph = (void *)walker;
|
||||
+
|
||||
+ pr_debug("Picture %u: Size %ux%u\n", i, ph->width, ph->height);
|
||||
+
|
||||
+ if (ph->num_blobs < 1) {
|
||||
+ pr_err("Picture %u: Zero blobs? Aborting load.\n", i);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ pp->pic_header = ph;
|
||||
+ pp->blobs = vzalloc(ph->num_blobs
|
||||
+ * sizeof(struct splash_blob_priv));
|
||||
+ if (!pp->blobs)
|
||||
+ goto err;
|
||||
+
|
||||
+ walker += sizeof(struct splash_pic_header);
|
||||
+ }
|
||||
+
|
||||
+ /* Read blob headers */
|
||||
+ for (i = 0; i < fp->header->num_blobs; i++) {
|
||||
+ struct splash_blob_header *bh = (void *)walker;
|
||||
+ struct splash_pic_priv *pp;
|
||||
+
|
||||
+ if (walker + sizeof(struct splash_blob_header)
|
||||
+ > fw->data + fw->size)
|
||||
+ goto err;
|
||||
+
|
||||
+ walker += sizeof(struct splash_blob_header);
|
||||
+
|
||||
+ if (walker + bh->length > fw->data + fw->size)
|
||||
+ goto err;
|
||||
+
|
||||
+ if (bh->picture_id >= fp->header->num_pics)
|
||||
+ goto nextblob;
|
||||
+
|
||||
+ pp = &fp->pics[bh->picture_id];
|
||||
+
|
||||
+ pr_debug("Blob %u, pic %u, blobs_loaded %u, num_blobs %u.\n",
|
||||
+ i, bh->picture_id,
|
||||
+ pp->blobs_loaded, pp->pic_header->num_blobs);
|
||||
+
|
||||
+ if (pp->blobs_loaded >= pp->pic_header->num_blobs)
|
||||
+ goto nextblob;
|
||||
+
|
||||
+ switch (bh->type) {
|
||||
+ case 0:
|
||||
+ /* Raw 24-bit packed pixels */
|
||||
+ if (bh->length != pp->pic_header->width
|
||||
+ * pp->pic_header->height * 3) {
|
||||
+ pr_err("Blob %u, type 1: Length doesn't match picture.\n",
|
||||
+ i);
|
||||
+
|
||||
+ goto err;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ pr_warn("Blob %u, unknown type %u.\n", i, bh->type);
|
||||
+ goto nextblob;
|
||||
+ }
|
||||
+
|
||||
+ pp->blobs[pp->blobs_loaded].blob_header = bh;
|
||||
+ pp->blobs[pp->blobs_loaded].data = walker;
|
||||
+ pp->blobs_loaded++;
|
||||
+
|
||||
+nextblob:
|
||||
+ walker += bh->length;
|
||||
+ if (bh->length % 16)
|
||||
+ walker += 16 - (bh->length % 16);
|
||||
+ }
|
||||
+
|
||||
+ if (walker != fw->data + fw->size)
|
||||
+ pr_warn("Trailing data in splash file.\n");
|
||||
+
|
||||
+ /* Walk over pictures and ensure all blob slots are filled */
|
||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+
|
||||
+ if (pp->blobs_loaded != pp->pic_header->num_blobs) {
|
||||
+ pr_err("Picture %u doesn't have all blob slots filled.\n",
|
||||
+ i);
|
||||
+
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
|
||||
+ fw->size,
|
||||
+ fp->header->num_pics,
|
||||
+ fp->header->num_blobs);
|
||||
+
|
||||
+ return fp;
|
||||
+
|
||||
+
|
||||
+err:
|
||||
+ bootsplash_free_file(fp);
|
||||
+ return NULL;
|
||||
+}
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
index 4d7e0117f653..2ae36949d0e3 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "bootsplash_internal.h"
|
||||
+#include "uapi/linux/bootsplash_file.h"
|
||||
|
||||
|
||||
|
||||
@@ -70,16 +71,69 @@ static inline u32 pack_pixel(const struct fb_var_screeninfo *dst_var,
|
||||
}
|
||||
|
||||
|
||||
-void bootsplash_do_render_background(struct fb_info *info)
|
||||
+/*
|
||||
+ * Copy from source and blend into the destination picture.
|
||||
+ * Currently assumes that the source picture is 24bpp.
|
||||
+ * Currently assumes that the destination is <= 32bpp.
|
||||
+ */
|
||||
+static int splash_convert_to_fb(u8 *dst,
|
||||
+ const struct fb_var_screeninfo *dst_var,
|
||||
+ unsigned int dst_stride,
|
||||
+ unsigned int dst_xoff,
|
||||
+ unsigned int dst_yoff,
|
||||
+ const u8 *src,
|
||||
+ unsigned int src_width,
|
||||
+ unsigned int src_height)
|
||||
+{
|
||||
+ unsigned int x, y;
|
||||
+ unsigned int src_stride = 3 * src_width; /* Assume 24bpp packed */
|
||||
+ u32 dst_octpp = dst_var->bits_per_pixel / 8;
|
||||
+
|
||||
+ dst_xoff += dst_var->xoffset;
|
||||
+ dst_yoff += dst_var->yoffset;
|
||||
+
|
||||
+ /* Copy with stride and pixel size adjustment */
|
||||
+ for (y = 0;
|
||||
+ y < src_height && y + dst_yoff < dst_var->yres_virtual;
|
||||
+ y++) {
|
||||
+ const u8 *srcline = src + (y * src_stride);
|
||||
+ u8 *dstline = dst + ((y + dst_yoff) * dst_stride)
|
||||
+ + (dst_xoff * dst_octpp);
|
||||
+
|
||||
+ for (x = 0;
|
||||
+ x < src_width && x + dst_xoff < dst_var->xres_virtual;
|
||||
+ x++) {
|
||||
+ u8 red, green, blue;
|
||||
+ u32 dstpix;
|
||||
+
|
||||
+ /* Read pixel */
|
||||
+ red = *srcline++;
|
||||
+ green = *srcline++;
|
||||
+ blue = *srcline++;
|
||||
+
|
||||
+ /* Write pixel */
|
||||
+ dstpix = pack_pixel(dst_var, red, green, blue);
|
||||
+ memcpy(dstline, &dstpix, dst_octpp);
|
||||
+
|
||||
+ dstline += dst_octpp;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void bootsplash_do_render_background(struct fb_info *info,
|
||||
+ const struct splash_file_priv *fp)
|
||||
{
|
||||
unsigned int x, y;
|
||||
u32 dstpix;
|
||||
u32 dst_octpp = info->var.bits_per_pixel / 8;
|
||||
|
||||
dstpix = pack_pixel(&info->var,
|
||||
- 0,
|
||||
- 0,
|
||||
- 0);
|
||||
+ fp->header->bg_red,
|
||||
+ fp->header->bg_green,
|
||||
+ fp->header->bg_blue);
|
||||
|
||||
for (y = 0; y < info->var.yres_virtual; y++) {
|
||||
u8 *dstline = info->screen_buffer + (y * info->fix.line_length);
|
||||
@@ -91,3 +145,44 @@ void bootsplash_do_render_background(struct fb_info *info)
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+
|
||||
+void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
+ const struct splash_file_priv *fp)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
||||
+ struct splash_blob_priv *bp;
|
||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+ long dst_xoff, dst_yoff;
|
||||
+
|
||||
+ if (pp->blobs_loaded < 1)
|
||||
+ continue;
|
||||
+
|
||||
+ bp = &pp->blobs[0];
|
||||
+
|
||||
+ if (!bp || bp->blob_header->type != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
|
||||
+ dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
|
||||
+
|
||||
+ if (dst_xoff < 0
|
||||
+ || dst_yoff < 0
|
||||
+ || dst_xoff + pp->pic_header->width > info->var.xres
|
||||
+ || dst_yoff + pp->pic_header->height > info->var.yres) {
|
||||
+ pr_info_once("Picture %u is out of bounds at current resolution: %dx%d\n"
|
||||
+ "(this will only be printed once every reboot)\n",
|
||||
+ i, info->var.xres, info->var.yres);
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* Draw next splash frame */
|
||||
+ splash_convert_to_fb(info->screen_buffer, &info->var,
|
||||
+ info->fix.line_length, dst_xoff, dst_yoff,
|
||||
+ bp->data,
|
||||
+ pp->pic_header->width, pp->pic_header->height);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
||||
new file mode 100644
|
||||
index 000000000000..89dc9cca8f0c
|
||||
--- /dev/null
|
||||
+++ b/include/uapi/linux/bootsplash_file.h
|
||||
@@ -0,0 +1,118 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (File format)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
|
||||
+ */
|
||||
+
|
||||
+#ifndef __BOOTSPLASH_FILE_H
|
||||
+#define __BOOTSPLASH_FILE_H
|
||||
+
|
||||
+
|
||||
+#define BOOTSPLASH_VERSION 55561
|
||||
+
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * On-disk types
|
||||
+ *
|
||||
+ * A splash file consists of:
|
||||
+ * - One single 'struct splash_file_header'
|
||||
+ * - An array of 'struct splash_pic_header'
|
||||
+ * - An array of raw data blocks, each padded to 16 bytes and
|
||||
+ * preceded by a 'struct splash_blob_header'
|
||||
+ *
|
||||
+ * A single-frame splash may look like this:
|
||||
+ *
|
||||
+ * +--------------------+
|
||||
+ * | |
|
||||
+ * | splash_file_header |
|
||||
+ * | -> num_blobs = 1 |
|
||||
+ * | -> num_pics = 1 |
|
||||
+ * | |
|
||||
+ * +--------------------+
|
||||
+ * | |
|
||||
+ * | splash_pic_header |
|
||||
+ * | |
|
||||
+ * +--------------------+
|
||||
+ * | |
|
||||
+ * | splash_blob_header |
|
||||
+ * | -> type = 0 |
|
||||
+ * | -> picture_id = 0 |
|
||||
+ * | |
|
||||
+ * | (raw RGB data) |
|
||||
+ * | (pad to 16 bytes) |
|
||||
+ * | |
|
||||
+ * +--------------------+
|
||||
+ *
|
||||
+ * All multi-byte values are stored on disk in the native format
|
||||
+ * expected by the system the file will be used on.
|
||||
+ */
|
||||
+#define BOOTSPLASH_MAGIC_BE "Linux bootsplash"
|
||||
+#define BOOTSPLASH_MAGIC_LE "hsalpstoob xuniL"
|
||||
+
|
||||
+struct splash_file_header {
|
||||
+ uint8_t id[16]; /* "Linux bootsplash" (no trailing NUL) */
|
||||
+
|
||||
+ /* Splash file format version to avoid clashes */
|
||||
+ uint16_t version;
|
||||
+
|
||||
+ /* The background color */
|
||||
+ uint8_t bg_red;
|
||||
+ uint8_t bg_green;
|
||||
+ uint8_t bg_blue;
|
||||
+ uint8_t bg_reserved;
|
||||
+
|
||||
+ /*
|
||||
+ * Number of pic/blobs so we can allocate memory for internal
|
||||
+ * structures ahead of time when reading the file
|
||||
+ */
|
||||
+ uint16_t num_blobs;
|
||||
+ uint8_t num_pics;
|
||||
+
|
||||
+ uint8_t padding[103];
|
||||
+} __attribute__((__packed__));
|
||||
+
|
||||
+
|
||||
+struct splash_pic_header {
|
||||
+ uint16_t width;
|
||||
+ uint16_t height;
|
||||
+
|
||||
+ /*
|
||||
+ * Number of data packages associated with this picture.
|
||||
+ * Currently, the only use for more than 1 is for animations.
|
||||
+ */
|
||||
+ uint8_t num_blobs;
|
||||
+
|
||||
+ uint8_t padding[27];
|
||||
+} __attribute__((__packed__));
|
||||
+
|
||||
+
|
||||
+struct splash_blob_header {
|
||||
+ /* Length of the data block in bytes. */
|
||||
+ uint32_t length;
|
||||
+
|
||||
+ /*
|
||||
+ * Type of the contents.
|
||||
+ * 0 - Raw RGB data.
|
||||
+ */
|
||||
+ uint16_t type;
|
||||
+
|
||||
+ /*
|
||||
+ * Picture this blob is associated with.
|
||||
+ * Blobs will be added to a picture in the order they are
|
||||
+ * found in the file.
|
||||
+ */
|
||||
+ uint8_t picture_id;
|
||||
+
|
||||
+ uint8_t padding[9];
|
||||
+} __attribute__((__packed__));
|
||||
+
|
||||
+#endif
|
66
nongnu/packages/patches/pinephone-0003-bootsplash.patch
Normal file
66
nongnu/packages/patches/pinephone-0003-bootsplash.patch
Normal file
|
@ -0,0 +1,66 @@
|
|||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
||||
index 843c5400fefc..815b007f81ca 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
||||
@@ -112,6 +112,8 @@ void bootsplash_render_full(struct fb_info *info)
|
||||
|
||||
bootsplash_do_render_pictures(info, splash_state.file);
|
||||
|
||||
+ bootsplash_do_render_flush(info);
|
||||
+
|
||||
out:
|
||||
mutex_unlock(&splash_state.data_lock);
|
||||
}
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
index 71e2a27ac0b8..0acb383aa4e3 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
@@ -89,6 +89,7 @@ void bootsplash_do_render_background(struct fb_info *info,
|
||||
const struct splash_file_priv *fp);
|
||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
const struct splash_file_priv *fp);
|
||||
+void bootsplash_do_render_flush(struct fb_info *info);
|
||||
|
||||
|
||||
void bootsplash_free_file(struct splash_file_priv *fp);
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
index 2ae36949d0e3..8c09c306ff67 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
@@ -186,3 +186,36 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
pp->pic_header->width, pp->pic_header->height);
|
||||
}
|
||||
}
|
||||
+
|
||||
+
|
||||
+void bootsplash_do_render_flush(struct fb_info *info)
|
||||
+{
|
||||
+ /*
|
||||
+ * FB drivers using deferred_io (such as Xen) need to sync the
|
||||
+ * screen after modifying its contents. When the FB is mmap()ed
|
||||
+ * from userspace, this happens via a dirty pages callback, but
|
||||
+ * when modifying the FB from the kernel, there is no such thing.
|
||||
+ *
|
||||
+ * So let's issue a fake fb_copyarea (copying the FB onto itself)
|
||||
+ * to trick the FB driver into syncing the screen.
|
||||
+ *
|
||||
+ * A few DRM drivers' FB implementations are broken by not using
|
||||
+ * deferred_io when they really should - we match on the known
|
||||
+ * bad ones manually for now.
|
||||
+ */
|
||||
+ if (info->fbdefio
|
||||
+ || !strcmp(info->fix.id, "astdrmfb")
|
||||
+ || !strcmp(info->fix.id, "cirrusdrmfb")
|
||||
+ || !strcmp(info->fix.id, "mgadrmfb")) {
|
||||
+ struct fb_copyarea area;
|
||||
+
|
||||
+ area.dx = 0;
|
||||
+ area.dy = 0;
|
||||
+ area.width = info->var.xres;
|
||||
+ area.height = info->var.yres;
|
||||
+ area.sx = 0;
|
||||
+ area.sy = 0;
|
||||
+
|
||||
+ info->fbops->fb_copyarea(info, &area);
|
||||
+ }
|
||||
+}
|
215
nongnu/packages/patches/pinephone-0004-bootsplash.patch
Normal file
215
nongnu/packages/patches/pinephone-0004-bootsplash.patch
Normal file
|
@ -0,0 +1,215 @@
|
|||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
index 8c09c306ff67..07e3a4eab811 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
@@ -155,6 +155,7 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
for (i = 0; i < fp->header->num_pics; i++) {
|
||||
struct splash_blob_priv *bp;
|
||||
struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+ const struct splash_pic_header *ph = pp->pic_header;
|
||||
long dst_xoff, dst_yoff;
|
||||
|
||||
if (pp->blobs_loaded < 1)
|
||||
@@ -165,8 +166,139 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
if (!bp || bp->blob_header->type != 0)
|
||||
continue;
|
||||
|
||||
- dst_xoff = (info->var.xres - pp->pic_header->width) / 2;
|
||||
- dst_yoff = (info->var.yres - pp->pic_header->height) / 2;
|
||||
+ switch (ph->position) {
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_LEFT:
|
||||
+ dst_xoff = 0;
|
||||
+ dst_yoff = 0;
|
||||
+
|
||||
+ dst_xoff += ph->position_offset;
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = 0;
|
||||
+
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_TOP_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_yoff = 0;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ dst_yoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+
|
||||
+ dst_yoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_BOTTOM_LEFT:
|
||||
+ dst_xoff = 0 + ph->position_offset;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height
|
||||
+ - ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_POS_FLAG_CORNER | SPLASH_CORNER_LEFT:
|
||||
+ dst_xoff = 0;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff += ph->position_offset;
|
||||
+ break;
|
||||
+
|
||||
+ case SPLASH_CORNER_TOP_LEFT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ dst_yoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_TOP:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_yoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_TOP_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff += ph->position_offset;
|
||||
+ dst_yoff -= ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_BOTTOM_RIGHT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff += ph->position_offset;
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_BOTTOM:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_BOTTOM_LEFT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ dst_yoff += ph->position_offset;
|
||||
+ break;
|
||||
+ case SPLASH_CORNER_LEFT:
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+
|
||||
+ dst_xoff -= ph->position_offset;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ /* As a fallback, center the picture. */
|
||||
+ dst_xoff = info->var.xres - pp->pic_header->width;
|
||||
+ dst_xoff /= 2;
|
||||
+ dst_yoff = info->var.yres - pp->pic_header->height;
|
||||
+ dst_yoff /= 2;
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
if (dst_xoff < 0
|
||||
|| dst_yoff < 0
|
||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
||||
index 89dc9cca8f0c..71cedcc68933 100644
|
||||
--- a/include/uapi/linux/bootsplash_file.h
|
||||
+++ b/include/uapi/linux/bootsplash_file.h
|
||||
@@ -91,7 +91,32 @@ struct splash_pic_header {
|
||||
*/
|
||||
uint8_t num_blobs;
|
||||
|
||||
- uint8_t padding[27];
|
||||
+ /*
|
||||
+ * Corner to move the picture to / from.
|
||||
+ * 0x00 - Top left
|
||||
+ * 0x01 - Top
|
||||
+ * 0x02 - Top right
|
||||
+ * 0x03 - Right
|
||||
+ * 0x04 - Bottom right
|
||||
+ * 0x05 - Bottom
|
||||
+ * 0x06 - Bottom left
|
||||
+ * 0x07 - Left
|
||||
+ *
|
||||
+ * Flags:
|
||||
+ * 0x10 - Calculate offset from the corner towards the center,
|
||||
+ * rather than from the center towards the corner
|
||||
+ */
|
||||
+ uint8_t position;
|
||||
+
|
||||
+ /*
|
||||
+ * Pixel offset from the selected position.
|
||||
+ * Example: If the picture is in the top right corner, it will
|
||||
+ * be placed position_offset pixels from the top and
|
||||
+ * position_offset pixels from the right margin.
|
||||
+ */
|
||||
+ uint16_t position_offset;
|
||||
+
|
||||
+ uint8_t padding[24];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
@@ -115,4 +140,22 @@ struct splash_blob_header {
|
||||
uint8_t padding[9];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
+
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Enums for on-disk types
|
||||
+ */
|
||||
+enum splash_position {
|
||||
+ SPLASH_CORNER_TOP_LEFT = 0,
|
||||
+ SPLASH_CORNER_TOP = 1,
|
||||
+ SPLASH_CORNER_TOP_RIGHT = 2,
|
||||
+ SPLASH_CORNER_RIGHT = 3,
|
||||
+ SPLASH_CORNER_BOTTOM_RIGHT = 4,
|
||||
+ SPLASH_CORNER_BOTTOM = 5,
|
||||
+ SPLASH_CORNER_BOTTOM_LEFT = 6,
|
||||
+ SPLASH_CORNER_LEFT = 7,
|
||||
+ SPLASH_POS_FLAG_CORNER = 0x10,
|
||||
+};
|
||||
+
|
||||
#endif
|
327
nongnu/packages/patches/pinephone-0005-bootsplash.patch
Normal file
327
nongnu/packages/patches/pinephone-0005-bootsplash.patch
Normal file
|
@ -0,0 +1,327 @@
|
|||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
||||
index 815b007f81ca..c8642142cfea 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
||||
@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
+static void splash_callback_animation(struct work_struct *ignored)
|
||||
+{
|
||||
+ if (bootsplash_would_render_now()) {
|
||||
+ /* This will also re-schedule this delayed worker */
|
||||
+ splash_callback_redraw_vc(ignored);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
|
||||
static bool is_fb_compatible(const struct fb_info *info)
|
||||
{
|
||||
@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)
|
||||
*/
|
||||
void bootsplash_render_full(struct fb_info *info)
|
||||
{
|
||||
+ bool is_update = false;
|
||||
+
|
||||
mutex_lock(&splash_state.data_lock);
|
||||
|
||||
- if (!is_fb_compatible(info))
|
||||
- goto out;
|
||||
+ /*
|
||||
+ * If we've painted on this FB recently, we don't have to do
|
||||
+ * the sanity checks and background drawing again.
|
||||
+ */
|
||||
+ if (splash_state.splash_fb == info)
|
||||
+ is_update = true;
|
||||
+
|
||||
+
|
||||
+ if (!is_update) {
|
||||
+ /* Check whether we actually support this FB. */
|
||||
+ splash_state.splash_fb = NULL;
|
||||
+
|
||||
+ if (!is_fb_compatible(info))
|
||||
+ goto out;
|
||||
+
|
||||
+ /* Draw the background only once */
|
||||
+ bootsplash_do_render_background(info, splash_state.file);
|
||||
|
||||
- bootsplash_do_render_background(info, splash_state.file);
|
||||
+ /* Mark this FB as last seen */
|
||||
+ splash_state.splash_fb = info;
|
||||
+ }
|
||||
|
||||
- bootsplash_do_render_pictures(info, splash_state.file);
|
||||
+ bootsplash_do_render_pictures(info, splash_state.file, is_update);
|
||||
|
||||
bootsplash_do_render_flush(info);
|
||||
|
||||
+ bootsplash_do_step_animations(splash_state.file);
|
||||
+
|
||||
+ /* Schedule update for animated splash screens */
|
||||
+ if (splash_state.file->frame_ms > 0)
|
||||
+ schedule_delayed_work(&splash_state.dwork_animation,
|
||||
+ msecs_to_jiffies(
|
||||
+ splash_state.file->frame_ms));
|
||||
+
|
||||
out:
|
||||
mutex_unlock(&splash_state.data_lock);
|
||||
}
|
||||
@@ -169,8 +204,14 @@ void bootsplash_enable(void)
|
||||
|
||||
was_enabled = test_and_set_bit(0, &splash_state.enabled);
|
||||
|
||||
- if (!was_enabled)
|
||||
+ if (!was_enabled) {
|
||||
+ /* Force a full redraw when the splash is re-activated */
|
||||
+ mutex_lock(&splash_state.data_lock);
|
||||
+ splash_state.splash_fb = NULL;
|
||||
+ mutex_unlock(&splash_state.data_lock);
|
||||
+
|
||||
schedule_work(&splash_state.work_redraw_vc);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -227,6 +268,14 @@ ATTRIBUTE_GROUPS(splash_dev);
|
||||
*/
|
||||
static int splash_resume(struct device *device)
|
||||
{
|
||||
+ /*
|
||||
+ * Force full redraw on resume since we've probably lost the
|
||||
+ * framebuffer's contents meanwhile
|
||||
+ */
|
||||
+ mutex_lock(&splash_state.data_lock);
|
||||
+ splash_state.splash_fb = NULL;
|
||||
+ mutex_unlock(&splash_state.data_lock);
|
||||
+
|
||||
if (bootsplash_would_render_now())
|
||||
schedule_work(&splash_state.work_redraw_vc);
|
||||
|
||||
@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)
|
||||
|
||||
static int splash_suspend(struct device *device)
|
||||
{
|
||||
+ cancel_delayed_work_sync(&splash_state.dwork_animation);
|
||||
cancel_work_sync(&splash_state.work_redraw_vc);
|
||||
|
||||
return 0;
|
||||
@@ -296,6 +346,8 @@ void bootsplash_init(void)
|
||||
set_bit(0, &splash_state.enabled);
|
||||
|
||||
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
|
||||
+ INIT_DELAYED_WORK(&splash_state.dwork_animation,
|
||||
+ splash_callback_animation);
|
||||
|
||||
|
||||
if (!splash_state.bootfile || !strlen(splash_state.bootfile))
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
index 0acb383aa4e3..b3a74835d90f 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
|
||||
@@ -37,6 +37,8 @@ struct splash_pic_priv {
|
||||
|
||||
struct splash_blob_priv *blobs;
|
||||
u16 blobs_loaded;
|
||||
+
|
||||
+ u16 anim_nextframe;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,6 +47,12 @@ struct splash_file_priv {
|
||||
const struct splash_file_header *header;
|
||||
|
||||
struct splash_pic_priv *pics;
|
||||
+
|
||||
+ /*
|
||||
+ * A local copy of the frame delay in the header.
|
||||
+ * We modify it to keep the code simple.
|
||||
+ */
|
||||
+ u16 frame_ms;
|
||||
};
|
||||
|
||||
|
||||
@@ -71,6 +79,7 @@ struct splash_priv {
|
||||
struct platform_device *splash_device;
|
||||
|
||||
struct work_struct work_redraw_vc;
|
||||
+ struct delayed_work dwork_animation;
|
||||
|
||||
/* Splash data structures including lock for everything below */
|
||||
struct mutex data_lock;
|
||||
@@ -88,8 +97,10 @@ struct splash_priv {
|
||||
void bootsplash_do_render_background(struct fb_info *info,
|
||||
const struct splash_file_priv *fp);
|
||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
- const struct splash_file_priv *fp);
|
||||
+ const struct splash_file_priv *fp,
|
||||
+ bool is_update);
|
||||
void bootsplash_do_render_flush(struct fb_info *info);
|
||||
+void bootsplash_do_step_animations(struct splash_file_priv *fp);
|
||||
|
||||
|
||||
void bootsplash_free_file(struct splash_file_priv *fp);
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
|
||||
index fd807571ab7d..1f661b2d4cc9 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_load.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_load.c
|
||||
@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
{
|
||||
const struct firmware *fw;
|
||||
struct splash_file_priv *fp;
|
||||
+ bool have_anim = false;
|
||||
unsigned int i;
|
||||
const u8 *walker;
|
||||
|
||||
@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ if (ph->anim_type > SPLASH_ANIM_LOOP_FORWARD) {
|
||||
+ pr_warn("Picture %u: Unsupported animation type %u.\n",
|
||||
+ i, ph->anim_type);
|
||||
+
|
||||
+ ph->anim_type = SPLASH_ANIM_NONE;
|
||||
+ }
|
||||
+
|
||||
pp->pic_header = ph;
|
||||
pp->blobs = vzalloc(ph->num_blobs
|
||||
* sizeof(struct splash_blob_priv));
|
||||
@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
/* Walk over pictures and ensure all blob slots are filled */
|
||||
for (i = 0; i < fp->header->num_pics; i++) {
|
||||
struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+ const struct splash_pic_header *ph = pp->pic_header;
|
||||
|
||||
if (pp->blobs_loaded != pp->pic_header->num_blobs) {
|
||||
pr_err("Picture %u doesn't have all blob slots filled.\n",
|
||||
@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
|
||||
|
||||
goto err;
|
||||
}
|
||||
+
|
||||
+ if (ph->anim_type
|
||||
+ && ph->num_blobs > 1
|
||||
+ && ph->anim_loop < pp->blobs_loaded)
|
||||
+ have_anim = true;
|
||||
}
|
||||
|
||||
+ if (!have_anim)
|
||||
+ /* Disable animation timer if there is nothing to animate */
|
||||
+ fp->frame_ms = 0;
|
||||
+ else
|
||||
+ /* Enforce minimum delay between frames */
|
||||
+ fp->frame_ms = max((u16)20, fp->header->frame_ms);
|
||||
+
|
||||
pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
|
||||
fw->size,
|
||||
fp->header->num_pics,
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
index 07e3a4eab811..76033606ca8a 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash_render.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash_render.c
|
||||
@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,
|
||||
|
||||
|
||||
void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
- const struct splash_file_priv *fp)
|
||||
+ const struct splash_file_priv *fp,
|
||||
+ bool is_update)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -161,7 +162,11 @@ void bootsplash_do_render_pictures(struct fb_info *info,
|
||||
if (pp->blobs_loaded < 1)
|
||||
continue;
|
||||
|
||||
- bp = &pp->blobs[0];
|
||||
+ /* Skip static pictures when refreshing animations */
|
||||
+ if (ph->anim_type == SPLASH_ANIM_NONE && is_update)
|
||||
+ continue;
|
||||
+
|
||||
+ bp = &pp->blobs[pp->anim_nextframe];
|
||||
|
||||
if (!bp || bp->blob_header->type != 0)
|
||||
continue;
|
||||
@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)
|
||||
info->fbops->fb_copyarea(info, &area);
|
||||
}
|
||||
}
|
||||
+
|
||||
+
|
||||
+void bootsplash_do_step_animations(struct splash_file_priv *fp)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* Step every animation once */
|
||||
+ for (i = 0; i < fp->header->num_pics; i++) {
|
||||
+ struct splash_pic_priv *pp = &fp->pics[i];
|
||||
+
|
||||
+ if (pp->blobs_loaded < 2
|
||||
+ || pp->pic_header->anim_loop > pp->blobs_loaded)
|
||||
+ continue;
|
||||
+
|
||||
+ if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {
|
||||
+ pp->anim_nextframe++;
|
||||
+ if (pp->anim_nextframe >= pp->pic_header->num_blobs)
|
||||
+ pp->anim_nextframe = pp->pic_header->anim_loop;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
|
||||
index 71cedcc68933..b3af0a3c6487 100644
|
||||
--- a/include/uapi/linux/bootsplash_file.h
|
||||
+++ b/include/uapi/linux/bootsplash_file.h
|
||||
@@ -77,7 +77,17 @@ struct splash_file_header {
|
||||
uint16_t num_blobs;
|
||||
uint8_t num_pics;
|
||||
|
||||
- uint8_t padding[103];
|
||||
+ uint8_t unused_1;
|
||||
+
|
||||
+ /*
|
||||
+ * Milliseconds to wait before painting the next frame in
|
||||
+ * an animation.
|
||||
+ * This is actually a minimum, as the system is allowed to
|
||||
+ * stall for longer between frames.
|
||||
+ */
|
||||
+ uint16_t frame_ms;
|
||||
+
|
||||
+ uint8_t padding[100];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
@@ -116,7 +126,23 @@ struct splash_pic_header {
|
||||
*/
|
||||
uint16_t position_offset;
|
||||
|
||||
- uint8_t padding[24];
|
||||
+ /*
|
||||
+ * Animation type.
|
||||
+ * 0 - off
|
||||
+ * 1 - forward loop
|
||||
+ */
|
||||
+ uint8_t anim_type;
|
||||
+
|
||||
+ /*
|
||||
+ * Animation loop point.
|
||||
+ * Actual meaning depends on animation type:
|
||||
+ * Type 0 - Unused
|
||||
+ * 1 - Frame at which to restart the forward loop
|
||||
+ * (allowing for "intro" frames)
|
||||
+ */
|
||||
+ uint8_t anim_loop;
|
||||
+
|
||||
+ uint8_t padding[22];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
@@ -158,4 +184,9 @@ enum splash_position {
|
||||
SPLASH_POS_FLAG_CORNER = 0x10,
|
||||
};
|
||||
|
||||
+enum splash_anim_type {
|
||||
+ SPLASH_ANIM_NONE = 0,
|
||||
+ SPLASH_ANIM_LOOP_FORWARD = 1,
|
||||
+};
|
||||
+
|
||||
#endif
|
82
nongnu/packages/patches/pinephone-0006-bootsplash.patch
Normal file
82
nongnu/packages/patches/pinephone-0006-bootsplash.patch
Normal file
|
@ -0,0 +1,82 @@
|
|||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
|
||||
index 2ebaba16f785..416735ab6dc1 100644
|
||||
--- a/drivers/tty/vt/vt.c
|
||||
+++ b/drivers/tty/vt/vt.c
|
||||
@@ -105,6 +105,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/gcd.h>
|
||||
+#include <linux/bootsplash.h>
|
||||
|
||||
#define MAX_NR_CON_DRIVER 16
|
||||
|
||||
@@ -4235,6 +4236,7 @@ void do_unblank_screen(int leaving_gfx)
|
||||
}
|
||||
|
||||
console_blanked = 0;
|
||||
+ bootsplash_mark_dirty();
|
||||
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
|
||||
/* Low-level driver cannot restore -> do it ourselves */
|
||||
update_screen(vc);
|
||||
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
|
||||
index c8642142cfea..13fcaabbc2ca 100644
|
||||
--- a/drivers/video/fbdev/core/bootsplash.c
|
||||
+++ b/drivers/video/fbdev/core/bootsplash.c
|
||||
@@ -165,6 +165,13 @@ bool bootsplash_would_render_now(void)
|
||||
&& bootsplash_is_enabled();
|
||||
}
|
||||
|
||||
+void bootsplash_mark_dirty(void)
|
||||
+{
|
||||
+ mutex_lock(&splash_state.data_lock);
|
||||
+ splash_state.splash_fb = NULL;
|
||||
+ mutex_unlock(&splash_state.data_lock);
|
||||
+}
|
||||
+
|
||||
bool bootsplash_is_enabled(void)
|
||||
{
|
||||
bool was_enabled;
|
||||
@@ -206,9 +213,7 @@ void bootsplash_enable(void)
|
||||
|
||||
if (!was_enabled) {
|
||||
/* Force a full redraw when the splash is re-activated */
|
||||
- mutex_lock(&splash_state.data_lock);
|
||||
- splash_state.splash_fb = NULL;
|
||||
- mutex_unlock(&splash_state.data_lock);
|
||||
+ bootsplash_mark_dirty();
|
||||
|
||||
schedule_work(&splash_state.work_redraw_vc);
|
||||
}
|
||||
@@ -272,9 +277,7 @@ static int splash_resume(struct device *device)
|
||||
* Force full redraw on resume since we've probably lost the
|
||||
* framebuffer's contents meanwhile
|
||||
*/
|
||||
- mutex_lock(&splash_state.data_lock);
|
||||
- splash_state.splash_fb = NULL;
|
||||
- mutex_unlock(&splash_state.data_lock);
|
||||
+ bootsplash_mark_dirty();
|
||||
|
||||
if (bootsplash_would_render_now())
|
||||
schedule_work(&splash_state.work_redraw_vc);
|
||||
diff --git a/include/linux/bootsplash.h b/include/linux/bootsplash.h
|
||||
index c6dd0b43180d..4075098aaadd 100644
|
||||
--- a/include/linux/bootsplash.h
|
||||
+++ b/include/linux/bootsplash.h
|
||||
@@ -19,6 +19,8 @@ extern void bootsplash_render_full(struct fb_info *info);
|
||||
|
||||
extern bool bootsplash_would_render_now(void);
|
||||
|
||||
+extern void bootsplash_mark_dirty(void);
|
||||
+
|
||||
extern bool bootsplash_is_enabled(void);
|
||||
extern void bootsplash_disable(void);
|
||||
extern void bootsplash_enable(void);
|
||||
@@ -31,6 +33,8 @@ extern void bootsplash_init(void);
|
||||
|
||||
#define bootsplash_would_render_now() (false)
|
||||
|
||||
+#define bootsplash_mark_dirty()
|
||||
+
|
||||
#define bootsplash_is_enabled() (false)
|
||||
#define bootsplash_disable()
|
||||
#define bootsplash_enable()
|
42
nongnu/packages/patches/pinephone-0007-bootsplash.patch
Normal file
42
nongnu/packages/patches/pinephone-0007-bootsplash.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
|
||||
index f4166263bb3a..a248429194bb 100644
|
||||
--- a/drivers/tty/vt/keyboard.c
|
||||
+++ b/drivers/tty/vt/keyboard.c
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
#include <asm/irq_regs.h>
|
||||
|
||||
+#include <linux/bootsplash.h>
|
||||
+
|
||||
/*
|
||||
* Exported functions/variables
|
||||
*/
|
||||
@@ -1413,6 +1415,28 @@ static void kbd_keycode(unsigned int key
|
||||
}
|
||||
#endif
|
||||
|
||||
+ /* Trap keys when bootsplash is shown */
|
||||
+ if (bootsplash_would_render_now()) {
|
||||
+ /* Deactivate bootsplash on ESC or Alt+Fxx VT switch */
|
||||
+ if (keycode >= KEY_F1 && keycode <= KEY_F12) {
|
||||
+ bootsplash_disable();
|
||||
+
|
||||
+ /*
|
||||
+ * No return here since we want to actually
|
||||
+ * perform the VT switch.
|
||||
+ */
|
||||
+ } else {
|
||||
+ if (keycode == KEY_ESC)
|
||||
+ bootsplash_disable();
|
||||
+
|
||||
+ /*
|
||||
+ * Just drop any other keys.
|
||||
+ * Their effect would be hidden by the splash.
|
||||
+ */
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (kbd->kbdmode == VC_MEDIUMRAW) {
|
||||
/*
|
||||
* This is extended medium raw mode, with keys above 127
|
21
nongnu/packages/patches/pinephone-0008-bootsplash.patch
Normal file
21
nongnu/packages/patches/pinephone-0008-bootsplash.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
|
||||
index 3ffc1ce29023..bc6a24c9dfa8 100644
|
||||
--- a/drivers/tty/sysrq.c
|
||||
+++ b/drivers/tty/sysrq.c
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/rcupdate.h>
|
||||
+#include <linux/bootsplash.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/irq_regs.h>
|
||||
@@ -104,6 +105,8 @@ static void sysrq_handle_SAK(int key)
|
||||
{
|
||||
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
|
||||
schedule_work(SAK_work);
|
||||
+
|
||||
+ bootsplash_disable();
|
||||
}
|
||||
static struct sysrq_key_op sysrq_SAK_op = {
|
||||
.handler = sysrq_handle_SAK,
|
21
nongnu/packages/patches/pinephone-0009-bootsplash.patch
Normal file
21
nongnu/packages/patches/pinephone-0009-bootsplash.patch
Normal file
|
@ -0,0 +1,21 @@
|
|||
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
|
||||
index 9a39a6fcfe98..8a9c67e1c5d8 100644
|
||||
--- a/drivers/video/fbdev/core/fbcon.c
|
||||
+++ b/drivers/video/fbdev/core/fbcon.c
|
||||
@@ -1343,6 +1343,16 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
|
||||
int y;
|
||||
int c = scr_readw((u16 *) vc->vc_pos);
|
||||
|
||||
+ /*
|
||||
+ * Disable the splash here so we don't have to hook into
|
||||
+ * vt_console_print() in drivers/tty/vt/vt.c
|
||||
+ *
|
||||
+ * We'd disable the splash just before the call to
|
||||
+ * hide_cursor() anyway, so this spot is just fine.
|
||||
+ */
|
||||
+ if (oops_in_progress)
|
||||
+ bootsplash_disable();
|
||||
+
|
||||
ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
|
||||
|
||||
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
|
308
nongnu/packages/patches/pinephone-0010-bootsplash.patch
Normal file
308
nongnu/packages/patches/pinephone-0010-bootsplash.patch
Normal file
|
@ -0,0 +1,308 @@
|
|||
diff --git a/Documentation/ABI/testing/sysfs-platform-bootsplash b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
||||
new file mode 100644
|
||||
index 000000000000..742c7b035ded
|
||||
--- /dev/null
|
||||
+++ b/Documentation/ABI/testing/sysfs-platform-bootsplash
|
||||
@@ -0,0 +1,11 @@
|
||||
+What: /sys/devices/platform/bootsplash.0/enabled
|
||||
+Date: Oct 2017
|
||||
+KernelVersion: 4.14
|
||||
+Contact: Max Staudt <mstaudt@suse.de>
|
||||
+Description:
|
||||
+ Can be set and read.
|
||||
+
|
||||
+ 0: Splash is disabled.
|
||||
+ 1: Splash is shown whenever fbcon would show a text console
|
||||
+ (i.e. no graphical application is running), and a splash
|
||||
+ file is loaded.
|
||||
diff --git a/Documentation/bootsplash.rst b/Documentation/bootsplash.rst
|
||||
new file mode 100644
|
||||
index 000000000000..611f0c558925
|
||||
--- /dev/null
|
||||
+++ b/Documentation/bootsplash.rst
|
||||
@@ -0,0 +1,285 @@
|
||||
+====================
|
||||
+The Linux bootsplash
|
||||
+====================
|
||||
+
|
||||
+:Date: November, 2017
|
||||
+:Author: Max Staudt <mstaudt@suse.de>
|
||||
+
|
||||
+
|
||||
+The Linux bootsplash is a graphical replacement for the '``quiet``' boot
|
||||
+option, typically showing a logo and a spinner animation as the system starts.
|
||||
+
|
||||
+Currently, it is a part of the Framebuffer Console support, and can be found
|
||||
+as ``CONFIG_BOOTSPLASH`` in the kernel configuration. This means that as long
|
||||
+as it is enabled, it hijacks fbcon's output and draws a splash screen instead.
|
||||
+
|
||||
+Purely compiling in the bootsplash will not render it functional - to actually
|
||||
+render a splash, you will also need a splash theme file. See the example
|
||||
+utility and script in ``tools/bootsplash`` for a live demo.
|
||||
+
|
||||
+
|
||||
+
|
||||
+Motivation
|
||||
+==========
|
||||
+
|
||||
+- The '``quiet``' boot option only suppresses most messages during boot, but
|
||||
+ errors are still shown.
|
||||
+
|
||||
+- A user space implementation can only show a logo once user space has been
|
||||
+ initialized far enough to allow this. A kernel splash can display a splash
|
||||
+ immediately as soon as fbcon can be displayed.
|
||||
+
|
||||
+- Implementing a splash screen in user space (e.g. Plymouth) is problematic
|
||||
+ due to resource conflicts.
|
||||
+
|
||||
+ For example, if Plymouth is keeping ``/dev/fb0`` (provided via vesafb/efifb)
|
||||
+ open, then most DRM drivers can't replace it because the address space is
|
||||
+ still busy - thus leading to a VRAM reservation error.
|
||||
+
|
||||
+ See: https://bugzilla.opensuse.org/show_bug.cgi?id=980750
|
||||
+
|
||||
+
|
||||
+
|
||||
+Command line arguments
|
||||
+======================
|
||||
+
|
||||
+``bootsplash.bootfile``
|
||||
+ Which file in the initramfs to load.
|
||||
+
|
||||
+ The splash theme is loaded via request_firmware(), thus to load
|
||||
+ ``/lib/firmware/bootsplash/mytheme`` pass the command line:
|
||||
+
|
||||
+ ``bootsplash.bootfile=bootsplash/mytheme``
|
||||
+
|
||||
+ Note: The splash file *has to be* in the initramfs, as it needs to be
|
||||
+ available when the splash is initialized early on.
|
||||
+
|
||||
+ Default: none, i.e. a non-functional splash, falling back to showing text.
|
||||
+
|
||||
+
|
||||
+
|
||||
+sysfs run-time configuration
|
||||
+============================
|
||||
+
|
||||
+``/sys/devices/platform/bootsplash.0/enabled``
|
||||
+ Enable/disable the bootsplash.
|
||||
+ The system boots with this set to 1, but will not show a splash unless
|
||||
+ a splash theme file is also loaded.
|
||||
+
|
||||
+
|
||||
+
|
||||
+Kconfig
|
||||
+=======
|
||||
+
|
||||
+``BOOTSPLASH``
|
||||
+ Whether to compile in bootsplash support
|
||||
+ (depends on fbcon compiled in, i.e. ``FRAMEBUFFER_CONSOLE=y``)
|
||||
+
|
||||
+
|
||||
+
|
||||
+Bootsplash file format
|
||||
+======================
|
||||
+
|
||||
+A file specified in the kernel configuration as ``CONFIG_BOOTSPLASH_FILE``
|
||||
+or specified on the command line as ``bootsplash.bootfile`` will be loaded
|
||||
+and displayed as soon as fbcon is initialized.
|
||||
+
|
||||
+
|
||||
+Main blocks
|
||||
+-----------
|
||||
+
|
||||
+There are 3 main blocks in each file:
|
||||
+
|
||||
+ - one File header
|
||||
+ - n Picture headers
|
||||
+ - m (Blob header + payload) blocks
|
||||
+
|
||||
+
|
||||
+Structures
|
||||
+----------
|
||||
+
|
||||
+The on-disk structures are defined in
|
||||
+``drivers/video/fbdev/core/bootsplash_file.h`` and represent these blocks:
|
||||
+
|
||||
+ - ``struct splash_file_header``
|
||||
+
|
||||
+ Represents the file header, with splash-wide information including:
|
||||
+
|
||||
+ - The magic string "``Linux bootsplash``" on big-endian platforms
|
||||
+ (the reverse on little endian)
|
||||
+ - The file format version (for incompatible updates, hopefully never)
|
||||
+ - The background color
|
||||
+ - Number of picture and blob blocks
|
||||
+ - Animation speed (we only allow one delay for all animations)
|
||||
+
|
||||
+ The file header is followed by the first picture header.
|
||||
+
|
||||
+
|
||||
+ - ``struct splash_picture_header``
|
||||
+
|
||||
+ Represents an object (picture) drawn on screen, including its immutable
|
||||
+ properties:
|
||||
+ - Width, height
|
||||
+ - Positioning relative to screen corners or in the center
|
||||
+ - Animation, if any
|
||||
+ - Animation type
|
||||
+ - Number of blobs
|
||||
+
|
||||
+ The picture header is followed by another picture header, up until n
|
||||
+ picture headers (as defined in the file header) have been read. Then,
|
||||
+ the (blob header, payload) pairs follow.
|
||||
+
|
||||
+
|
||||
+ - ``struct splash_blob_header``
|
||||
+ (followed by payload)
|
||||
+
|
||||
+ Represents one raw data stream. So far, only picture data is defined.
|
||||
+
|
||||
+ The blob header is followed by a payload, then padding to n*16 bytes,
|
||||
+ then (if further blobs are defined in the file header) a further blob
|
||||
+ header.
|
||||
+
|
||||
+
|
||||
+Alignment
|
||||
+---------
|
||||
+
|
||||
+The bootsplash file is designed to be loaded into memory as-is.
|
||||
+
|
||||
+All structures are a multiple of 16 bytes long, all elements therein are
|
||||
+aligned to multiples of their length, and the payloads are always padded
|
||||
+up to multiples of 16 bytes. This is to allow aligned accesses in all
|
||||
+cases while still simply mapping the structures over an in-memory copy of
|
||||
+the bootsplash file.
|
||||
+
|
||||
+
|
||||
+Further information
|
||||
+-------------------
|
||||
+
|
||||
+Please see ``drivers/video/fbdev/core/bootsplash_file.h`` for further
|
||||
+details and possible values in the file.
|
||||
+
|
||||
+
|
||||
+
|
||||
+Hooks - how the bootsplash is integrated
|
||||
+========================================
|
||||
+
|
||||
+``drivers/video/fbdev/core/fbcon.c``
|
||||
+ ``fbcon_init()`` calls ``bootsplash_init()``, which loads the default
|
||||
+ bootsplash file or the one specified on the kernel command line.
|
||||
+
|
||||
+ ``fbcon_switch()`` draws the bootsplash when it's active, and is also
|
||||
+ one of the callers of ``set_blitting_type()``.
|
||||
+
|
||||
+ ``set_blitting_type()`` calls ``fbcon_set_dummyops()`` when the
|
||||
+ bootsplash is active, overriding the text rendering functions.
|
||||
+
|
||||
+ ``fbcon_cursor()`` will call ``bootsplash_disable()`` when an oops is
|
||||
+ being printed in order to make a kernel panic visible.
|
||||
+
|
||||
+``drivers/video/fbdev/core/dummyblit.c``
|
||||
+ This contains the dummy text rendering functions used to suppress text
|
||||
+ output while the bootsplash is shown.
|
||||
+
|
||||
+``drivers/tty/vt/keyboard.c``
|
||||
+ ``kbd_keycode()`` can call ``bootsplash_disable()`` when the user
|
||||
+ presses ESC or F1-F12 (changing VT). This is to provide a built-in way
|
||||
+ of disabling the splash manually at any time.
|
||||
+
|
||||
+
|
||||
+
|
||||
+FAQ: Frequently Asked Questions
|
||||
+===============================
|
||||
+
|
||||
+I want to see the log! How do I show the log?
|
||||
+---------------------------------------------
|
||||
+
|
||||
+Press ESC while the splash is shown, or remove the ``bootsplash.bootfile``
|
||||
+parameter from the kernel cmdline. Without that parameter, the bootsplash
|
||||
+will boot disabled.
|
||||
+
|
||||
+
|
||||
+Why use FB instead of modern DRM/KMS?
|
||||
+-------------------------------------
|
||||
+
|
||||
+This is a semantic problem:
|
||||
+ - What memory to draw the splash to?
|
||||
+ - And what mode will the screen be set to?
|
||||
+
|
||||
+Using the fbdev emulation solves these issues.
|
||||
+
|
||||
+Let's start from a bare KMS system, without fbcon, and without fbdev
|
||||
+emulation. In this case, as long as userspace doesn't open the KMS
|
||||
+device, the state of the screen is undefined. No framebuffer is
|
||||
+allocated in video RAM, and no particular mode is set.
|
||||
+
|
||||
+In this case, we'd have to allocate a framebuffer to show the splash,
|
||||
+and set our mode ourselves. This either wastes a screenful of video RAM
|
||||
+if the splash is to co-exist with the userspace program's own allocated
|
||||
+framebuffer, or there is a flicker as we deactivate and delete the
|
||||
+bootsplash's framebuffer and hand control over to userspace. Since we
|
||||
+may set a different mode than userspace, we'd also have flicker due
|
||||
+to mode switching.
|
||||
+
|
||||
+This logic is already contained in every KMS driver that performs fbdev
|
||||
+emulation. So we might as well use that. And the correct API to do so is
|
||||
+fbdev. Plus, we get compatibility with old, pure fbdev drivers for free.
|
||||
+With the fbdev emulation, there is *always* a well-defined framebuffer
|
||||
+to draw on. And the selection of mode has already been done by the
|
||||
+graphics driver, so we don't need to reinvent that wheel, either.
|
||||
+Finally, if userspace decides to use /dev/fbX, we don't have to worry
|
||||
+about wasting video RAM, either.
|
||||
+
|
||||
+
|
||||
+Why is the bootsplash integrated in fbcon?
|
||||
+------------------------------------------
|
||||
+
|
||||
+Right now, the bootsplash is drawn from within fbcon, as this allows us
|
||||
+to easily know *when* to draw - i.e. when we're safe from fbcon and
|
||||
+userspace drawing all over our beautiful splash logo.
|
||||
+
|
||||
+Separating them is not easy - see the to-do list below.
|
||||
+
|
||||
+
|
||||
+
|
||||
+TO DO list for future development
|
||||
+=================================
|
||||
+
|
||||
+Second enable/disable switch for the system
|
||||
+-------------------------------------------
|
||||
+
|
||||
+It may be helpful to differentiate between the system and the user
|
||||
+switching off the bootsplash. Thus, the system may make it disappear and
|
||||
+reappear e.g. for a password prompt, yet once the user has pressed ESC,
|
||||
+it could stay gone.
|
||||
+
|
||||
+
|
||||
+Fix buggy DRM/KMS drivers
|
||||
+-------------------------
|
||||
+
|
||||
+Currently, the splash code manually checks for fbdev emulation provided by
|
||||
+the ast, cirrus, and mgag200 DRM/KMS drivers.
|
||||
+These drivers use a manual mechanism similar to deferred I/O for their FB
|
||||
+emulation, and thus need to be manually flushed onto the screen in the same
|
||||
+way.
|
||||
+
|
||||
+This may be improved upon in several ways:
|
||||
+
|
||||
+1. Changing these drivers to expose the fbdev BO's memory directly, like
|
||||
+ bochsdrmfb does.
|
||||
+2. Creating a new fb_ops->fb_flush() API to allow the kernel to flush the
|
||||
+ framebuffer once the bootsplash has been drawn into it.
|
||||
+
|
||||
+
|
||||
+Separating from fbcon
|
||||
+---------------------
|
||||
+
|
||||
+Separating these two components would yield independence from fbcon being
|
||||
+compiled into the kernel, and thus lowering code size in embedded
|
||||
+applications.
|
||||
+
|
||||
+To do this cleanly will involve a clean separation of users of an FB device
|
||||
+within the kernel, i.e. fbcon, bootsplash, and userspace. Right now, the
|
||||
+legacy fbcon code and VT code co-operate to switch between fbcon and
|
||||
+userspace (by setting the VT into KD_GRAPHICS mode). Installing a muxer
|
||||
+between these components ensues refactoring of old code and checking for
|
||||
+correct locking.
|
499
nongnu/packages/patches/pinephone-0011-bootsplash.patch
Normal file
499
nongnu/packages/patches/pinephone-0011-bootsplash.patch
Normal file
|
@ -0,0 +1,499 @@
|
|||
diff --git a/tools/bootsplash/.gitignore b/tools/bootsplash/.gitignore
|
||||
new file mode 100644
|
||||
index 000000000000..091b99a17567
|
||||
--- /dev/null
|
||||
+++ b/tools/bootsplash/.gitignore
|
||||
@@ -0,0 +1 @@
|
||||
+bootsplash-packer
|
||||
diff --git a/tools/bootsplash/Makefile b/tools/bootsplash/Makefile
|
||||
new file mode 100644
|
||||
index 000000000000..0ad8e8a84942
|
||||
--- /dev/null
|
||||
+++ b/tools/bootsplash/Makefile
|
||||
@@ -0,0 +1,9 @@
|
||||
+CC := $(CROSS_COMPILE)gcc
|
||||
+CFLAGS := -I../../usr/include
|
||||
+
|
||||
+PROGS := bootsplash-packer
|
||||
+
|
||||
+all: $(PROGS)
|
||||
+
|
||||
+clean:
|
||||
+ rm -fr $(PROGS)
|
||||
diff --git a/tools/bootsplash/bootsplash-packer.c b/tools/bootsplash/bootsplash-packer.c
|
||||
new file mode 100644
|
||||
index 000000000000..ffb6a8b69885
|
||||
--- /dev/null
|
||||
+++ b/tools/bootsplash/bootsplash-packer.c
|
||||
@@ -0,0 +1,471 @@
|
||||
+/*
|
||||
+ * Kernel based bootsplash.
|
||||
+ *
|
||||
+ * (Splash file packer tool)
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Max Staudt <mstaudt@suse.de>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0
|
||||
+ */
|
||||
+
|
||||
+#include <endian.h>
|
||||
+#include <getopt.h>
|
||||
+#include <stdint.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <linux/bootsplash_file.h>
|
||||
+
|
||||
+
|
||||
+static void print_help(char *progname)
|
||||
+{
|
||||
+ printf("Usage: %s [OPTIONS] outfile\n", progname);
|
||||
+ printf("\n"
|
||||
+ "Options, executed in order given:\n"
|
||||
+ " -h, --help Print this help message\n"
|
||||
+ "\n"
|
||||
+ " --bg_red <u8> Background color (red part)\n"
|
||||
+ " --bg_green <u8> Background color (green part)\n"
|
||||
+ " --bg_blue <u8> Background color (blue part)\n"
|
||||
+ " --bg_reserved <u8> (do not use)\n"
|
||||
+ " --frame_ms <u16> Minimum milliseconds between animation steps\n"
|
||||
+ "\n"
|
||||
+ " --picture Start describing the next picture\n"
|
||||
+ " --pic_width <u16> Picture width in pixels\n"
|
||||
+ " --pic_height <u16> Picture height in pixels\n"
|
||||
+ " --pic_position <u8> Coarse picture placement:\n"
|
||||
+ " 0x00 - Top left\n"
|
||||
+ " 0x01 - Top\n"
|
||||
+ " 0x02 - Top right\n"
|
||||
+ " 0x03 - Right\n"
|
||||
+ " 0x04 - Bottom right\n"
|
||||
+ " 0x05 - Bottom\n"
|
||||
+ " 0x06 - Bottom left\n"
|
||||
+ " 0x07 - Left\n"
|
||||
+ "\n"
|
||||
+ " Flags:\n"
|
||||
+ " 0x10 - Calculate offset from corner towards center,\n"
|
||||
+ " rather than from center towards corner\n"
|
||||
+ " --pic_position_offset <u16> Distance from base position in pixels\n"
|
||||
+ " --pic_anim_type <u8> Animation type:\n"
|
||||
+ " 0 - None\n"
|
||||
+ " 1 - Forward loop\n"
|
||||
+ " --pic_anim_loop <u8> Loop point for animation\n"
|
||||
+ "\n"
|
||||
+ " --blob <filename> Include next data stream\n"
|
||||
+ " --blob_type <u16> Type of data\n"
|
||||
+ " --blob_picture_id <u8> Picture to associate this blob with, starting at 0\n"
|
||||
+ " (default: number of last --picture)\n"
|
||||
+ "\n");
|
||||
+ printf("This tool will write %s files.\n\n",
|
||||
+#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
+ "Big Endian (BE)");
|
||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
+ "Little Endian (LE)");
|
||||
+#else
|
||||
+#error
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
+struct blob_entry {
|
||||
+ struct blob_entry *next;
|
||||
+
|
||||
+ char *fn;
|
||||
+
|
||||
+ struct splash_blob_header header;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static void dump_file_header(struct splash_file_header *h)
|
||||
+{
|
||||
+ printf(" --- File header ---\n");
|
||||
+ printf("\n");
|
||||
+ printf(" version: %5u\n", h->version);
|
||||
+ printf("\n");
|
||||
+ printf(" bg_red: %5u\n", h->bg_red);
|
||||
+ printf(" bg_green: %5u\n", h->bg_green);
|
||||
+ printf(" bg_blue: %5u\n", h->bg_blue);
|
||||
+ printf(" bg_reserved: %5u\n", h->bg_reserved);
|
||||
+ printf("\n");
|
||||
+ printf(" num_blobs: %5u\n", h->num_blobs);
|
||||
+ printf(" num_pics: %5u\n", h->num_pics);
|
||||
+ printf("\n");
|
||||
+ printf(" frame_ms: %5u\n", h->frame_ms);
|
||||
+ printf("\n");
|
||||
+}
|
||||
+
|
||||
+static void dump_pic_header(struct splash_pic_header *ph)
|
||||
+{
|
||||
+ printf(" --- Picture header ---\n");
|
||||
+ printf("\n");
|
||||
+ printf(" width: %5u\n", ph->width);
|
||||
+ printf(" height: %5u\n", ph->height);
|
||||
+ printf("\n");
|
||||
+ printf(" num_blobs: %5u\n", ph->num_blobs);
|
||||
+ printf("\n");
|
||||
+ printf(" position: %0x3x\n", ph->position);
|
||||
+ printf(" position_offset: %5u\n", ph->position_offset);
|
||||
+ printf("\n");
|
||||
+ printf(" anim_type: %5u\n", ph->anim_type);
|
||||
+ printf(" anim_loop: %5u\n", ph->anim_loop);
|
||||
+ printf("\n");
|
||||
+}
|
||||
+
|
||||
+static void dump_blob(struct blob_entry *b)
|
||||
+{
|
||||
+ printf(" --- Blob header ---\n");
|
||||
+ printf("\n");
|
||||
+ printf(" length: %7u\n", b->header.length);
|
||||
+ printf(" type: %7u\n", b->header.type);
|
||||
+ printf("\n");
|
||||
+ printf(" picture_id: %7u\n", b->header.picture_id);
|
||||
+ printf("\n");
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#define OPT_MAX(var, max) \
|
||||
+ do { \
|
||||
+ if ((var) > max) { \
|
||||
+ fprintf(stderr, "--%s: Invalid value\n", \
|
||||
+ long_options[option_index].name); \
|
||||
+ break; \
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+static struct option long_options[] = {
|
||||
+ {"help", 0, 0, 'h'},
|
||||
+ {"bg_red", 1, 0, 10001},
|
||||
+ {"bg_green", 1, 0, 10002},
|
||||
+ {"bg_blue", 1, 0, 10003},
|
||||
+ {"bg_reserved", 1, 0, 10004},
|
||||
+ {"frame_ms", 1, 0, 10005},
|
||||
+ {"picture", 0, 0, 20000},
|
||||
+ {"pic_width", 1, 0, 20001},
|
||||
+ {"pic_height", 1, 0, 20002},
|
||||
+ {"pic_position", 1, 0, 20003},
|
||||
+ {"pic_position_offset", 1, 0, 20004},
|
||||
+ {"pic_anim_type", 1, 0, 20005},
|
||||
+ {"pic_anim_loop", 1, 0, 20006},
|
||||
+ {"blob", 1, 0, 30000},
|
||||
+ {"blob_type", 1, 0, 30001},
|
||||
+ {"blob_picture_id", 1, 0, 30002},
|
||||
+ {NULL, 0, NULL, 0}
|
||||
+};
|
||||
+
|
||||
+
|
||||
+int main(int argc, char **argv)
|
||||
+{
|
||||
+ FILE *of;
|
||||
+ char *ofn;
|
||||
+ int c;
|
||||
+ int option_index = 0;
|
||||
+
|
||||
+ unsigned long ul;
|
||||
+ struct splash_file_header fh = {};
|
||||
+ struct splash_pic_header ph[255];
|
||||
+ struct blob_entry *blob_first = NULL;
|
||||
+ struct blob_entry *blob_last = NULL;
|
||||
+ struct blob_entry *blob_cur = NULL;
|
||||
+
|
||||
+ if (argc < 2) {
|
||||
+ print_help(argv[0]);
|
||||
+ return EXIT_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* Parse and and execute user commands */
|
||||
+ while ((c = getopt_long(argc, argv, "h",
|
||||
+ long_options, &option_index)) != -1) {
|
||||
+ switch (c) {
|
||||
+ case 10001: /* bg_red */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ fh.bg_red = ul;
|
||||
+ break;
|
||||
+ case 10002: /* bg_green */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ fh.bg_green = ul;
|
||||
+ break;
|
||||
+ case 10003: /* bg_blue */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ fh.bg_blue = ul;
|
||||
+ break;
|
||||
+ case 10004: /* bg_reserved */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ fh.bg_reserved = ul;
|
||||
+ break;
|
||||
+ case 10005: /* frame_ms */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 65535);
|
||||
+ fh.frame_ms = ul;
|
||||
+ break;
|
||||
+
|
||||
+
|
||||
+ case 20000: /* picture */
|
||||
+ if (fh.num_pics >= 255) {
|
||||
+ fprintf(stderr, "--%s: Picture array full\n",
|
||||
+ long_options[option_index].name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ fh.num_pics++;
|
||||
+ break;
|
||||
+
|
||||
+ case 20001: /* pic_width */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 65535);
|
||||
+ ph[fh.num_pics - 1].width = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 20002: /* pic_height */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 65535);
|
||||
+ ph[fh.num_pics - 1].height = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 20003: /* pic_position */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ ph[fh.num_pics - 1].position = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 20004: /* pic_position_offset */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ ph[fh.num_pics - 1].position_offset = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 20005: /* pic_anim_type */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ ph[fh.num_pics - 1].anim_type = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 20006: /* pic_anim_loop */
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ ph[fh.num_pics - 1].anim_loop = ul;
|
||||
+ break;
|
||||
+
|
||||
+
|
||||
+ case 30000: /* blob */
|
||||
+ if (fh.num_blobs >= 65535) {
|
||||
+ fprintf(stderr, "--%s: Blob array full\n",
|
||||
+ long_options[option_index].name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ blob_cur = calloc(1, sizeof(struct blob_entry));
|
||||
+ if (!blob_cur) {
|
||||
+ fprintf(stderr, "--%s: Out of memory\n",
|
||||
+ long_options[option_index].name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ blob_cur->fn = optarg;
|
||||
+ if (fh.num_pics)
|
||||
+ blob_cur->header.picture_id = fh.num_pics - 1;
|
||||
+
|
||||
+ if (!blob_first)
|
||||
+ blob_first = blob_cur;
|
||||
+ if (blob_last)
|
||||
+ blob_last->next = blob_cur;
|
||||
+ blob_last = blob_cur;
|
||||
+ fh.num_blobs++;
|
||||
+ break;
|
||||
+
|
||||
+ case 30001: /* blob_type */
|
||||
+ if (!blob_cur) {
|
||||
+ fprintf(stderr, "--%s: No blob selected\n",
|
||||
+ long_options[option_index].name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ blob_cur->header.type = ul;
|
||||
+ break;
|
||||
+
|
||||
+ case 30002: /* blob_picture_id */
|
||||
+ if (!blob_cur) {
|
||||
+ fprintf(stderr, "--%s: No blob selected\n",
|
||||
+ long_options[option_index].name);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ul = strtoul(optarg, NULL, 0);
|
||||
+ OPT_MAX(ul, 255);
|
||||
+ blob_cur->header.picture_id = ul;
|
||||
+ break;
|
||||
+
|
||||
+
|
||||
+
|
||||
+ case 'h':
|
||||
+ case '?':
|
||||
+ default:
|
||||
+ print_help(argv[0]);
|
||||
+ goto EXIT;
|
||||
+ } /* switch (c) */
|
||||
+ } /* while ((c = getopt_long(...)) != -1) */
|
||||
+
|
||||
+ /* Consume and drop lone arguments */
|
||||
+ while (optind < argc) {
|
||||
+ ofn = argv[optind];
|
||||
+ optind++;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* Read file lengths */
|
||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
|
||||
+ FILE *f;
|
||||
+ long pos;
|
||||
+ int i;
|
||||
+
|
||||
+ if (!blob_cur->fn)
|
||||
+ continue;
|
||||
+
|
||||
+ f = fopen(blob_cur->fn, "rb");
|
||||
+ if (!f)
|
||||
+ goto ERR_FILE_LEN;
|
||||
+
|
||||
+ if (fseek(f, 0, SEEK_END))
|
||||
+ goto ERR_FILE_LEN;
|
||||
+
|
||||
+ pos = ftell(f);
|
||||
+ if (pos < 0 || pos > (1 << 30))
|
||||
+ goto ERR_FILE_LEN;
|
||||
+
|
||||
+ blob_cur->header.length = pos;
|
||||
+
|
||||
+ fclose(f);
|
||||
+ continue;
|
||||
+
|
||||
+ERR_FILE_LEN:
|
||||
+ fprintf(stderr, "Error getting file length (or too long): %s\n",
|
||||
+ blob_cur->fn);
|
||||
+ if (f)
|
||||
+ fclose(f);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* Set magic headers */
|
||||
+#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_BE, 16);
|
||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
+ memcpy(&fh.id[0], BOOTSPLASH_MAGIC_LE, 16);
|
||||
+#else
|
||||
+#error
|
||||
+#endif
|
||||
+ fh.version = BOOTSPLASH_VERSION;
|
||||
+
|
||||
+ /* Set blob counts */
|
||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next) {
|
||||
+ if (blob_cur->header.picture_id < fh.num_pics)
|
||||
+ ph[blob_cur->header.picture_id].num_blobs++;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ /* Dump structs */
|
||||
+ dump_file_header(&fh);
|
||||
+
|
||||
+ for (ul = 0; ul < fh.num_pics; ul++)
|
||||
+ dump_pic_header(&ph[ul]);
|
||||
+
|
||||
+ for (blob_cur = blob_first; blob_cur; blob_cur = blob_cur->next)
|
||||
+ dump_blob(blob_cur);
|
||||
+
|
||||
+
|
||||
+ /* Write to file */
|
||||
+ printf("Writing splash to file: %s\n", ofn);
|
||||
+ of = fopen(ofn, "wb");
|
||||
+ if (!of)
|
||||
+ goto ERR_WRITING;
|
||||
+
|
||||
+ if (fwrite(&fh, sizeof(struct splash_file_header), 1, of) != 1)
|
||||
+ goto ERR_WRITING;
|
||||
+
|
||||
+ for (ul = 0; ul < fh.num_pics; ul++) {
|
||||
+ if (fwrite(&ph[ul], sizeof(struct splash_pic_header), 1, of)
|
||||
+ != 1)
|
||||
+ goto ERR_WRITING;
|
||||
+ }
|
||||
+
|
||||
+ blob_cur = blob_first;
|
||||
+ while (blob_cur) {
|
||||
+ struct blob_entry *blob_old = blob_cur;
|
||||
+ FILE *f;
|
||||
+ char *buf[256];
|
||||
+ uint32_t left;
|
||||
+
|
||||
+ if (fwrite(&blob_cur->header,
|
||||
+ sizeof(struct splash_blob_header), 1, of) != 1)
|
||||
+ goto ERR_WRITING;
|
||||
+
|
||||
+ if (!blob_cur->header.length || !blob_cur->fn)
|
||||
+ continue;
|
||||
+
|
||||
+ f = fopen(blob_cur->fn, "rb");
|
||||
+ if (!f)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+
|
||||
+ left = blob_cur->header.length;
|
||||
+ while (left >= sizeof(buf)) {
|
||||
+ if (fread(buf, sizeof(buf), 1, f) != 1)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+ if (fwrite(buf, sizeof(buf), 1, of) != 1)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+ left -= sizeof(buf);
|
||||
+ }
|
||||
+ if (left) {
|
||||
+ if (fread(buf, left, 1, f) != 1)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+ if (fwrite(buf, left, 1, of) != 1)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+ }
|
||||
+
|
||||
+ /* Pad data stream to 16 bytes */
|
||||
+ if (left % 16) {
|
||||
+ if (fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
|
||||
+ 16 - (left % 16), 1, of) != 1)
|
||||
+ goto ERR_FILE_COPY;
|
||||
+ }
|
||||
+
|
||||
+ fclose(f);
|
||||
+ blob_cur = blob_cur->next;
|
||||
+ free(blob_old);
|
||||
+ continue;
|
||||
+
|
||||
+ERR_FILE_COPY:
|
||||
+ if (f)
|
||||
+ fclose(f);
|
||||
+ goto ERR_WRITING;
|
||||
+ }
|
||||
+
|
||||
+ fclose(of);
|
||||
+
|
||||
+EXIT:
|
||||
+ return EXIT_SUCCESS;
|
||||
+
|
||||
+
|
||||
+ERR_WRITING:
|
||||
+ fprintf(stderr, "Error writing splash.\n");
|
||||
+ fprintf(stderr, "The output file is probably corrupt.\n");
|
||||
+ if (of)
|
||||
+ fclose(of);
|
||||
+
|
||||
+ while (blob_cur) {
|
||||
+ struct blob_entry *blob_old = blob_cur;
|
||||
+
|
||||
+ blob_cur = blob_cur->next;
|
||||
+ free(blob_old);
|
||||
+ }
|
||||
+
|
||||
+ return EXIT_FAILURE;
|
||||
+}
|
175
nongnu/packages/patches/pinephone-drop-modem-power-node.patch
Normal file
175
nongnu/packages/patches/pinephone-drop-modem-power-node.patch
Normal file
|
@ -0,0 +1,175 @@
|
|||
From 602d05e416ae0d0fba3022fa2c3d195164b406c6 Mon Sep 17 00:00:00 2001
|
||||
From: Clayton Craft <clayton@craftyguy.net>
|
||||
Date: Wed, 16 Dec 2020 20:16:14 -0800
|
||||
Subject: [PATCH] dts: pinephone: drop modem-power node
|
||||
|
||||
---
|
||||
.../allwinner/sun50i-a64-pinephone-1.0.dts | 26 +++---------------
|
||||
.../allwinner/sun50i-a64-pinephone-1.1.dts | 27 +++----------------
|
||||
.../allwinner/sun50i-a64-pinephone-1.2.dts | 27 +++----------------
|
||||
.../dts/allwinner/sun50i-a64-pinephone.dtsi | 12 +++++++++
|
||||
4 files changed, 24 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
index a21c6d78a..7f0cfdafe 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.0.dts
|
||||
@@ -86,28 +86,6 @@ ®_drivevbus {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
-
|
||||
- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */
|
||||
-
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
@@ -118,6 +96,10 @@ usb0_drd_sw: endpoint {
|
||||
};
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
enable-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
flash-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
index 61ff56b17..5e85ddc12 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.1.dts
|
||||
@@ -109,34 +109,15 @@ ®_drivevbus {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&pio 1 2 GPIO_ACTIVE_LOW>; /* PB2 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
- //status-pwrkey-multiplexed; /* status acts as pwrkey */
|
||||
-
|
||||
- sleep-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-RI */
|
||||
-
|
||||
- dtr-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-DTR */
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
index fe7d567a8..f4b9b0991 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone-1.2.dts
|
||||
@@ -101,34 +101,15 @@ ®_anx1v0 {
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
+&ring_indicator {
|
||||
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_LOW>; /* PL6 */
|
||||
+};
|
||||
+
|
||||
&sgm3140 {
|
||||
enable-gpios = <&pio 3 24 GPIO_ACTIVE_HIGH>; /* PD24 */
|
||||
flash-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; /* PC3 */
|
||||
};
|
||||
|
||||
-&uart3 {
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- power-supply = <®_vbat_bb>; /* PL7 */
|
||||
-
|
||||
- enable-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */
|
||||
- reset-gpios = <&pio 2 4 GPIO_ACTIVE_HIGH>; /* PC4 */
|
||||
- status-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
|
||||
- pwrkey-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
|
||||
-
|
||||
- host-ready-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
|
||||
- wakeup-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6-RI */
|
||||
-
|
||||
- dtr-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2-DTR */
|
||||
- cts-gpios = <&pio 3 5 GPIO_ACTIVE_HIGH>; /* PD5-CTS */
|
||||
- rts-gpios = <&pio 3 4 GPIO_ACTIVE_HIGH>; /* PD4-RTS */
|
||||
-
|
||||
- quectel,qdai = "1,1,0,1,0,0,1,1";
|
||||
- };
|
||||
-};
|
||||
-
|
||||
&usbphy {
|
||||
usb-role-switch;
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
index 346113382..7b48126d1 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi
|
||||
@@ -192,6 +192,17 @@ ec25_codec: ec25-codec {
|
||||
sound-name-prefix = "Modem";
|
||||
};
|
||||
|
||||
+ gpio-keys {
|
||||
+ compatible = "gpio-keys";
|
||||
+
|
||||
+ ring_indicator: ring-indicator {
|
||||
+ label = "Ring Indicator";
|
||||
+ linux,can-disable;
|
||||
+ linux,code = <KEY_WAKEUP>;
|
||||
+ wakeup-source;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
i2c_csi: i2c-csi {
|
||||
compatible = "i2c-gpio";
|
||||
sda-gpios = <&pio 4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; /* PE13 */
|
||||
@@ -264,6 +275,7 @@ reg_usb_5v: usb-5v {
|
||||
reg_vbat_bb: vbat-bb {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-bb";
|
||||
+ regulator-always-on;
|
||||
regulator-min-microvolt = <3500000>;
|
||||
regulator-max-microvolt = <3500000>;
|
||||
gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
|
||||
--
|
||||
2.31.1
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
--- b/drivers/video/fbdev/core/fbcon.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon.c
|
||||
@@ -163,6 +163,8 @@
|
||||
|
||||
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
|
||||
|
||||
+static int fbcon_set_origin(struct vc_data *);
|
||||
+
|
||||
static int fbcon_cursor_noblink;
|
||||
|
||||
#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
|
||||
@@ -2633,6 +2635,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
+static int fbcon_set_origin(struct vc_data *vc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void fbcon_suspended(struct fb_info *info)
|
||||
{
|
||||
struct vc_data *vc = NULL;
|
||||
@@ -3103,6 +3110,7 @@
|
||||
.con_font_default = fbcon_set_def_font,
|
||||
.con_font_copy = fbcon_copy_font,
|
||||
.con_set_palette = fbcon_set_palette,
|
||||
+ .con_set_origin = fbcon_set_origin,
|
||||
.con_invert_region = fbcon_invert_region,
|
||||
.con_screen_pos = fbcon_screen_pos,
|
||||
.con_getxy = fbcon_getxy,
|
|
@ -0,0 +1,52 @@
|
|||
From fc38b73e2556211d698849b78a4623dc163b7d49 Mon Sep 17 00:00:00 2001
|
||||
From: Arnaud Ferraris <arnaud.ferraris@gmail.com>
|
||||
Date: Wed, 8 Dec 2021 23:43:08 +0100
|
||||
Subject: [PATCH 3/4] arm64: dts: rk3399-pinephone-pro: add modem RI pin
|
||||
|
||||
Taht way the modem can wake the phone on incoming calls/messages.
|
||||
|
||||
Signed-off-by: Arnaud Ferraris <arnaud.ferraris@gmail.com>
|
||||
---
|
||||
.../dts/rockchip/rk3399-pinephone-pro.dts | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
index c9365e604..b3b091ea7 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
@@ -160,6 +160,21 @@ power {
|
||||
};
|
||||
};
|
||||
|
||||
+ gpio-key-ri {
|
||||
+ compatible = "gpio-keys";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&ri_pin>;
|
||||
+
|
||||
+ ring_indicator: ring-indicator {
|
||||
+ label = "ring-indicator";
|
||||
+ linux,can-disable;
|
||||
+ linux,code = <KEY_WAKEUP>;
|
||||
+ gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>;
|
||||
+ wakeup-event-action = <EV_ACT_ASSERTED>;
|
||||
+ wakeup-source;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
// in1 - digital mic daughhterboard
|
||||
// in2 - headset mic
|
||||
// in3 - modem output (muxed with mono)
|
||||
@@ -1150,6 +1165,10 @@ flash_pins: flash-pins {
|
||||
};
|
||||
|
||||
modem {
|
||||
+ ri_pin: ri-pin {
|
||||
+ rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
+ };
|
||||
+
|
||||
vcc_4g_5v_en: vcc-4g-5v-en-pin {
|
||||
rockchip,pins = <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
From 60d8aedea7c8c390ee744730ab3e565ea84496fb Mon Sep 17 00:00:00 2001
|
||||
From: Danct12 <danct12@disroot.org>
|
||||
Date: Fri, 10 Dec 2021 23:01:34 +0700
|
||||
Subject: [PATCH] arm64: dts: rk3399-pinephone-pro: Remove modem node
|
||||
|
||||
Since we don't use modem-power driver, this can be removed
|
||||
for eg25-manager.
|
||||
---
|
||||
.../dts/rockchip/rk3399-pinephone-pro.dts | 40 +------------------
|
||||
1 file changed, 2 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
index 61c990764..13141c643 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
|
||||
@@ -326,6 +326,7 @@ vcc_4g_5v: vcc-4g-5v {
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
+ regulator-always-on;
|
||||
};
|
||||
|
||||
vcc_4g: vcc-4g {
|
||||
@@ -338,6 +339,7 @@ vcc_4g: vcc-4g {
|
||||
regulator-min-microvolt = <3800000>;
|
||||
regulator-max-microvolt = <3800000>;
|
||||
vin-supply = <&vcc_sysin>;
|
||||
+ regulator-always-on;
|
||||
};
|
||||
|
||||
vcc1v8_codec: vcc1v8-codec-regulator {
|
||||
@@ -1058,31 +1060,6 @@ mipi_in_panel: endpoint {
|
||||
|
||||
&uart3 {
|
||||
status = "okay";
|
||||
-
|
||||
- modem {
|
||||
- compatible = "quectel,eg25";
|
||||
- char-device-name = "modem-power";
|
||||
-
|
||||
- pinctrl-names = "default";
|
||||
- pinctrl-0 = <&modem_control_pins>;
|
||||
-
|
||||
- power-supply = <&vcc_4g>;
|
||||
- vbus-supply = <&vcc_4g_5v>;
|
||||
-
|
||||
- enable-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; // W_DISABLE#
|
||||
- reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
|
||||
- status-gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>;
|
||||
- pwrkey-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
|
||||
-
|
||||
- host-ready-gpios = <&gpio0 RK_PB4 GPIO_ACTIVE_HIGH>; // apready
|
||||
- wakeup-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; // ri
|
||||
-
|
||||
- dtr-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
|
||||
- cts-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
|
||||
- rts-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
|
||||
-
|
||||
- quectel,qdai = "3,0,0,4,0,0,1,1";
|
||||
- };
|
||||
};
|
||||
|
||||
&pmu_io_domains {
|
||||
@@ -1153,19 +1130,6 @@ vcc_4g_5v_en: vcc-4g-5v-en-pin {
|
||||
vcc_4g_en: vcc-4g-en-pin {
|
||||
rockchip,pins = <4 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
-
|
||||
- modem_control_pins: modem-control-pins {
|
||||
- rockchip,pins =
|
||||
- <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <3 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
- <3 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
- };
|
||||
};
|
||||
|
||||
pmic {
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
--- b/drivers/video/fbdev/core/bitblit.c
|
||||
+++ a/drivers/video/fbdev/core/bitblit.c
|
||||
@@ -234,7 +234,7 @@
|
||||
}
|
||||
|
||||
static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
- int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
@@ -247,6 +247,15 @@
|
||||
|
||||
cursor.set = 0;
|
||||
|
||||
+ if (softback_lines) {
|
||||
+ if (y + softback_lines >= vc->vc_rows) {
|
||||
+ mode = CM_ERASE;
|
||||
+ ops->cursor_flash = 0;
|
||||
+ return;
|
||||
+ } else
|
||||
+ y += softback_lines;
|
||||
+ }
|
||||
+
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
attribute = get_attribute(info, c);
|
||||
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
|
||||
--- b/drivers/video/fbdev/core/fbcon.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon.c
|
||||
@@ -394,7 +394,7 @@
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
|
||||
CM_ERASE : CM_DRAW;
|
||||
+ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
||||
- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
console_unlock();
|
||||
}
|
||||
@@ -1345,7 +1345,7 @@
|
||||
|
||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
||||
|
||||
+ ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
||||
- ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
}
|
||||
|
||||
--- b/drivers/video/fbdev/core/fbcon.h
|
||||
+++ a/drivers/video/fbdev/core/fbcon.h
|
||||
@@ -62,7 +62,7 @@
|
||||
void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
|
||||
int color, int bottom_only);
|
||||
void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg);
|
||||
- int fg, int bg);
|
||||
int (*update_start)(struct fb_info *info);
|
||||
int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
|
||||
struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
|
||||
--- b/drivers/video/fbdev/core/fbcon_ccw.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon_ccw.c
|
||||
@@ -219,7 +219,7 @@
|
||||
}
|
||||
|
||||
static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
- int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
@@ -236,6 +236,15 @@
|
||||
|
||||
cursor.set = 0;
|
||||
|
||||
+ if (softback_lines) {
|
||||
+ if (y + softback_lines >= vc->vc_rows) {
|
||||
+ mode = CM_ERASE;
|
||||
+ ops->cursor_flash = 0;
|
||||
+ return;
|
||||
+ } else
|
||||
+ y += softback_lines;
|
||||
+ }
|
||||
+
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
attribute = get_attribute(info, c);
|
||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
|
||||
--- b/drivers/video/fbdev/core/fbcon_cw.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon_cw.c
|
||||
@@ -202,7 +202,7 @@
|
||||
}
|
||||
|
||||
static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
- int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
@@ -219,6 +219,15 @@
|
||||
|
||||
cursor.set = 0;
|
||||
|
||||
+ if (softback_lines) {
|
||||
+ if (y + softback_lines >= vc->vc_rows) {
|
||||
+ mode = CM_ERASE;
|
||||
+ ops->cursor_flash = 0;
|
||||
+ return;
|
||||
+ } else
|
||||
+ y += softback_lines;
|
||||
+ }
|
||||
+
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
attribute = get_attribute(info, c);
|
||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
|
||||
--- b/drivers/video/fbdev/core/fbcon_ud.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon_ud.c
|
||||
@@ -249,7 +249,7 @@
|
||||
}
|
||||
|
||||
static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
- int fg, int bg)
|
||||
{
|
||||
struct fb_cursor cursor;
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
@@ -267,6 +267,15 @@
|
||||
|
||||
cursor.set = 0;
|
||||
|
||||
+ if (softback_lines) {
|
||||
+ if (y + softback_lines >= vc->vc_rows) {
|
||||
+ mode = CM_ERASE;
|
||||
+ ops->cursor_flash = 0;
|
||||
+ return;
|
||||
+ } else
|
||||
+ y += softback_lines;
|
||||
+ }
|
||||
+
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
attribute = get_attribute(info, c);
|
||||
src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
|
||||
--- b/drivers/video/fbdev/core/tileblit.c
|
||||
+++ a/drivers/video/fbdev/core/tileblit.c
|
||||
@@ -80,7 +80,7 @@
|
||||
}
|
||||
|
||||
static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
|
||||
+ int softback_lines, int fg, int bg)
|
||||
- int fg, int bg)
|
||||
{
|
||||
struct fb_tilecursor cursor;
|
||||
int use_sw = (vc->vc_cursor_type & 0x10);
|
|
@ -0,0 +1,500 @@
|
|||
--- b/drivers/video/fbdev/core/fbcon.c
|
||||
+++ a/drivers/video/fbdev/core/fbcon.c
|
||||
@@ -124,6 +124,12 @@ static int logo_lines;
|
||||
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
|
||||
enums. */
|
||||
static int logo_shown = FBCON_LOGO_CANSHOW;
|
||||
+/* Software scrollback */
|
||||
+static int fbcon_softback_size = 32768;
|
||||
+static unsigned long softback_buf, softback_curr;
|
||||
+static unsigned long softback_in;
|
||||
+static unsigned long softback_top, softback_end;
|
||||
+static int softback_lines;
|
||||
/* console mappings */
|
||||
static unsigned int first_fb_vc;
|
||||
static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1;
|
||||
@@ -163,6 +169,8 @@ static int margin_color;
|
||||
|
||||
static const struct consw fb_con;
|
||||
|
||||
+#define CM_SOFTBACK (8)
|
||||
+
|
||||
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
|
||||
|
||||
static int fbcon_set_origin(struct vc_data *);
|
||||
@@ -347,6 +355,18 @@ static int get_color(struct vc_data *vc,
|
||||
return color;
|
||||
}
|
||||
|
||||
+static void fbcon_update_softback(struct vc_data *vc)
|
||||
+{
|
||||
+ int l = fbcon_softback_size / vc->vc_size_row;
|
||||
+
|
||||
+ if (l > 5)
|
||||
+ softback_end = softback_buf + l * vc->vc_size_row;
|
||||
+ else
|
||||
+ /* Smaller scrollback makes no sense, and 0 would screw
|
||||
+ the operation totally */
|
||||
+ softback_top = 0;
|
||||
+}
|
||||
+
|
||||
static void fb_flashcursor(struct work_struct *work)
|
||||
{
|
||||
struct fbcon_ops *ops = container_of(work, struct fbcon_ops, cursor_work.work);
|
||||
@@ -379,7 +399,7 @@ static void fb_flashcursor(struct work_s
|
||||
c = scr_readw((u16 *) vc->vc_pos);
|
||||
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
|
||||
CM_ERASE : CM_DRAW;
|
||||
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
||||
+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
console_unlock();
|
||||
|
||||
@@ -419,7 +439,13 @@ static int __init fb_console_setup(char
|
||||
}
|
||||
|
||||
if (!strncmp(options, "scrollback:", 11)) {
|
||||
- pr_warn("Ignoring scrollback size option\n");
|
||||
+ options += 11;
|
||||
+ if (*options) {
|
||||
+ fbcon_softback_size = simple_strtoul(options, &options, 0);
|
||||
+ if (*options == 'k' || *options == 'K') {
|
||||
+ fbcon_softback_size *= 1024;
|
||||
+ }
|
||||
+ }
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -959,6 +985,31 @@ static const char *fbcon_startup(void)
|
||||
|
||||
set_blitting_type(vc, info);
|
||||
|
||||
+ if (info->fix.type != FB_TYPE_TEXT) {
|
||||
+ if (fbcon_softback_size) {
|
||||
+ if (!softback_buf) {
|
||||
+ softback_buf =
|
||||
+ (unsigned long)
|
||||
+ kvmalloc(fbcon_softback_size,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!softback_buf) {
|
||||
+ fbcon_softback_size = 0;
|
||||
+ softback_top = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (softback_buf) {
|
||||
+ kvfree((void *) softback_buf);
|
||||
+ softback_buf = 0;
|
||||
+ softback_top = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ if (softback_buf)
|
||||
+ softback_in = softback_top = softback_curr =
|
||||
+ softback_buf;
|
||||
+ softback_lines = 0;
|
||||
+ }
|
||||
+
|
||||
/* Setup default font */
|
||||
if (!p->fontdata && !vc->vc_font.data) {
|
||||
if (!fontname[0] || !(font = find_font(fontname)))
|
||||
@@ -1129,6 +1180,9 @@ static void fbcon_init(struct vc_data *v
|
||||
if (logo)
|
||||
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
|
||||
|
||||
+ if (vc == svc && softback_buf)
|
||||
+ fbcon_update_softback(vc);
|
||||
+
|
||||
if (ops->rotate_font && ops->rotate_font(info, vc)) {
|
||||
ops->rotate = FB_ROTATE_UR;
|
||||
set_blitting_type(vc, info);
|
||||
@@ -1152,6 +1206,9 @@ static void fbcon_release_all(void)
|
||||
struct fb_info *info;
|
||||
int i, j, mapped;
|
||||
|
||||
+ kvfree((void *)softback_buf);
|
||||
+ softback_buf = 0UL;
|
||||
+
|
||||
fbcon_for_each_registered_fb(i) {
|
||||
mapped = 0;
|
||||
info = fbcon_registered_fb[i];
|
||||
@@ -1312,6 +1369,7 @@ static void fbcon_cursor(struct vc_data
|
||||
{
|
||||
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
|
||||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
+ int y;
|
||||
int c = scr_readw((u16 *) vc->vc_pos);
|
||||
|
||||
ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
|
||||
@@ -1325,11 +1383,19 @@ static void fbcon_cursor(struct vc_data
|
||||
fbcon_add_cursor_work(info);
|
||||
|
||||
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
|
||||
+ if (mode & CM_SOFTBACK) {
|
||||
+ mode &= ~CM_SOFTBACK;
|
||||
+ y = softback_lines;
|
||||
+ } else {
|
||||
+ if (softback_lines)
|
||||
+ fbcon_set_origin(vc);
|
||||
+ y = 0;
|
||||
+ }
|
||||
|
||||
if (!ops->cursor)
|
||||
return;
|
||||
|
||||
- ops->cursor(vc, info, mode, 0, get_color(vc, info, c, 1),
|
||||
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
|
||||
get_color(vc, info, c, 0));
|
||||
}
|
||||
|
||||
@@ -1399,6 +1465,8 @@ static void fbcon_set_disp(struct fb_inf
|
||||
|
||||
if (con_is_visible(vc)) {
|
||||
update_screen(vc);
|
||||
+ if (softback_buf)
|
||||
+ fbcon_update_softback(vc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,6 +1604,99 @@ static __inline__ void ypan_down_redraw(
|
||||
scrollback_current = 0;
|
||||
}
|
||||
|
||||
+static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
|
||||
+ long delta)
|
||||
+{
|
||||
+ int count = vc->vc_rows;
|
||||
+ unsigned short *d, *s;
|
||||
+ unsigned long n;
|
||||
+ int line = 0;
|
||||
+
|
||||
+ d = (u16 *) softback_curr;
|
||||
+ if (d == (u16 *) softback_in)
|
||||
+ d = (u16 *) vc->vc_origin;
|
||||
+ n = softback_curr + delta * vc->vc_size_row;
|
||||
+ softback_lines -= delta;
|
||||
+ if (delta < 0) {
|
||||
+ if (softback_curr < softback_top && n < softback_buf) {
|
||||
+ n += softback_end - softback_buf;
|
||||
+ if (n < softback_top) {
|
||||
+ softback_lines -=
|
||||
+ (softback_top - n) / vc->vc_size_row;
|
||||
+ n = softback_top;
|
||||
+ }
|
||||
+ } else if (softback_curr >= softback_top
|
||||
+ && n < softback_top) {
|
||||
+ softback_lines -=
|
||||
+ (softback_top - n) / vc->vc_size_row;
|
||||
+ n = softback_top;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (softback_curr > softback_in && n >= softback_end) {
|
||||
+ n += softback_buf - softback_end;
|
||||
+ if (n > softback_in) {
|
||||
+ n = softback_in;
|
||||
+ softback_lines = 0;
|
||||
+ }
|
||||
+ } else if (softback_curr <= softback_in && n > softback_in) {
|
||||
+ n = softback_in;
|
||||
+ softback_lines = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ if (n == softback_curr)
|
||||
+ return;
|
||||
+ softback_curr = n;
|
||||
+ s = (u16 *) softback_curr;
|
||||
+ if (s == (u16 *) softback_in)
|
||||
+ s = (u16 *) vc->vc_origin;
|
||||
+ while (count--) {
|
||||
+ unsigned short *start;
|
||||
+ unsigned short *le;
|
||||
+ unsigned short c;
|
||||
+ int x = 0;
|
||||
+ unsigned short attr = 1;
|
||||
+
|
||||
+ start = s;
|
||||
+ le = advance_row(s, 1);
|
||||
+ do {
|
||||
+ c = scr_readw(s);
|
||||
+ if (attr != (c & 0xff00)) {
|
||||
+ attr = c & 0xff00;
|
||||
+ if (s > start) {
|
||||
+ fbcon_putcs(vc, start, s - start,
|
||||
+ line, x);
|
||||
+ x += s - start;
|
||||
+ start = s;
|
||||
+ }
|
||||
+ }
|
||||
+ if (c == scr_readw(d)) {
|
||||
+ if (s > start) {
|
||||
+ fbcon_putcs(vc, start, s - start,
|
||||
+ line, x);
|
||||
+ x += s - start + 1;
|
||||
+ start = s + 1;
|
||||
+ } else {
|
||||
+ x++;
|
||||
+ start++;
|
||||
+ }
|
||||
+ }
|
||||
+ s++;
|
||||
+ d++;
|
||||
+ } while (s < le);
|
||||
+ if (s > start)
|
||||
+ fbcon_putcs(vc, start, s - start, line, x);
|
||||
+ line++;
|
||||
+ if (d == (u16 *) softback_end)
|
||||
+ d = (u16 *) softback_buf;
|
||||
+ if (d == (u16 *) softback_in)
|
||||
+ d = (u16 *) vc->vc_origin;
|
||||
+ if (s == (u16 *) softback_end)
|
||||
+ s = (u16 *) softback_buf;
|
||||
+ if (s == (u16 *) softback_in)
|
||||
+ s = (u16 *) vc->vc_origin;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
|
||||
int line, int count, int dy)
|
||||
{
|
||||
@@ -1740,6 +1901,31 @@ static void fbcon_bmove(struct vc_data *
|
||||
p->vrows - p->yscroll);
|
||||
}
|
||||
|
||||
+static inline void fbcon_softback_note(struct vc_data *vc, int t,
|
||||
+ int count)
|
||||
+{
|
||||
+ unsigned short *p;
|
||||
+
|
||||
+ if (vc->vc_num != fg_console)
|
||||
+ return;
|
||||
+ p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
|
||||
+
|
||||
+ while (count) {
|
||||
+ scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
|
||||
+ count--;
|
||||
+ p = advance_row(p, 1);
|
||||
+ softback_in += vc->vc_size_row;
|
||||
+ if (softback_in == softback_end)
|
||||
+ softback_in = softback_buf;
|
||||
+ if (softback_in == softback_top) {
|
||||
+ softback_top += vc->vc_size_row;
|
||||
+ if (softback_top == softback_end)
|
||||
+ softback_top = softback_buf;
|
||||
+ }
|
||||
+ }
|
||||
+ softback_curr = softback_in;
|
||||
+}
|
||||
+
|
||||
static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
|
||||
enum con_scroll dir, unsigned int count)
|
||||
{
|
||||
@@ -1762,6 +1948,8 @@ static bool fbcon_scroll(struct vc_data
|
||||
case SM_UP:
|
||||
if (count > vc->vc_rows) /* Maximum realistic size */
|
||||
count = vc->vc_rows;
|
||||
+ if (softback_top)
|
||||
+ fbcon_softback_note(vc, t, count);
|
||||
switch (fb_scrollmode(p)) {
|
||||
case SCROLL_MOVE:
|
||||
fbcon_redraw_blit(vc, info, p, t, b - t - count,
|
||||
@@ -2076,6 +2264,14 @@ static int fbcon_switch(struct vc_data *
|
||||
info = fbcon_info_from_console(vc->vc_num);
|
||||
ops = info->fbcon_par;
|
||||
|
||||
+ if (softback_top) {
|
||||
+ if (softback_lines)
|
||||
+ fbcon_set_origin(vc);
|
||||
+ softback_top = softback_curr = softback_in = softback_buf;
|
||||
+ softback_lines = 0;
|
||||
+ fbcon_update_softback(vc);
|
||||
+ }
|
||||
+
|
||||
if (logo_shown >= 0) {
|
||||
struct vc_data *conp2 = vc_cons[logo_shown].d;
|
||||
|
||||
@@ -2406,6 +2602,9 @@ static int fbcon_do_set_font(struct vc_d
|
||||
int resize;
|
||||
char *old_data = NULL;
|
||||
|
||||
+ if (con_is_visible(vc) && softback_lines)
|
||||
+ fbcon_set_origin(vc);
|
||||
+
|
||||
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
|
||||
if (p->userfont)
|
||||
old_data = vc->vc_font.data;
|
||||
@@ -2428,6 +2627,8 @@ static int fbcon_do_set_font(struct vc_d
|
||||
cols /= w;
|
||||
rows /= h;
|
||||
vc_resize(vc, cols, rows);
|
||||
+ if (con_is_visible(vc) && softback_buf)
|
||||
+ fbcon_update_softback(vc);
|
||||
} else if (con_is_visible(vc)
|
||||
&& vc->vc_mode == KD_TEXT) {
|
||||
fbcon_clear_margins(vc, 0);
|
||||
@@ -2582,7 +2783,19 @@ static void fbcon_set_palette(struct vc_
|
||||
|
||||
static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset)
|
||||
{
|
||||
- return (u16 *) (vc->vc_origin + offset);
|
||||
+ unsigned long p;
|
||||
+ int line;
|
||||
+
|
||||
+ if (vc->vc_num != fg_console || !softback_lines)
|
||||
+ return (u16 *) (vc->vc_origin + offset);
|
||||
+ line = offset / vc->vc_size_row;
|
||||
+ if (line >= softback_lines)
|
||||
+ return (u16 *) (vc->vc_origin + offset -
|
||||
+ softback_lines * vc->vc_size_row);
|
||||
+ p = softback_curr + offset;
|
||||
+ if (p >= softback_end)
|
||||
+ p += softback_buf - softback_end;
|
||||
+ return (u16 *) p;
|
||||
}
|
||||
|
||||
static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos,
|
||||
@@ -2596,7 +2809,22 @@ static unsigned long fbcon_getxy(struct
|
||||
|
||||
x = offset % vc->vc_cols;
|
||||
y = offset / vc->vc_cols;
|
||||
+ if (vc->vc_num == fg_console)
|
||||
+ y += softback_lines;
|
||||
+ ret = pos + (vc->vc_cols - x) * 2;
|
||||
+ } else if (vc->vc_num == fg_console && softback_lines) {
|
||||
+ unsigned long offset = pos - softback_curr;
|
||||
+
|
||||
+ if (pos < softback_curr)
|
||||
+ offset += softback_end - softback_buf;
|
||||
+ offset /= 2;
|
||||
+ x = offset % vc->vc_cols;
|
||||
+ y = offset / vc->vc_cols;
|
||||
ret = pos + (vc->vc_cols - x) * 2;
|
||||
+ if (ret == softback_end)
|
||||
+ ret = softback_buf;
|
||||
+ if (ret == softback_in)
|
||||
+ ret = vc->vc_origin;
|
||||
} else {
|
||||
/* Should not happen */
|
||||
x = y = 0;
|
||||
@@ -2624,11 +2852,106 @@ static void fbcon_invert_region(struct v
|
||||
a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) |
|
||||
(((a) & 0x0700) << 4);
|
||||
scr_writew(a, p++);
|
||||
+ if (p == (u16 *) softback_end)
|
||||
+ p = (u16 *) softback_buf;
|
||||
+ if (p == (u16 *) softback_in)
|
||||
+ p = (u16 *) vc->vc_origin;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void fbcon_scrolldelta(struct vc_data *vc, int lines)
|
||||
+{
|
||||
+ struct fb_info *info = registered_fb[con2fb_map[fg_console]];
|
||||
+ struct fbcon_ops *ops = info->fbcon_par;
|
||||
+ struct fbcon_display *disp = &fb_display[fg_console];
|
||||
+ int offset, limit, scrollback_old;
|
||||
+
|
||||
+ if (softback_top) {
|
||||
+ if (vc->vc_num != fg_console)
|
||||
+ return;
|
||||
+ if (vc->vc_mode != KD_TEXT || !lines)
|
||||
+ return;
|
||||
+ if (logo_shown >= 0) {
|
||||
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
|
||||
+
|
||||
+ if (conp2->vc_top == logo_lines
|
||||
+ && conp2->vc_bottom == conp2->vc_rows)
|
||||
+ conp2->vc_top = 0;
|
||||
+ if (logo_shown == vc->vc_num) {
|
||||
+ unsigned long p, q;
|
||||
+ int i;
|
||||
+
|
||||
+ p = softback_in;
|
||||
+ q = vc->vc_origin +
|
||||
+ logo_lines * vc->vc_size_row;
|
||||
+ for (i = 0; i < logo_lines; i++) {
|
||||
+ if (p == softback_top)
|
||||
+ break;
|
||||
+ if (p == softback_buf)
|
||||
+ p = softback_end;
|
||||
+ p -= vc->vc_size_row;
|
||||
+ q -= vc->vc_size_row;
|
||||
+ scr_memcpyw((u16 *) q, (u16 *) p,
|
||||
+ vc->vc_size_row);
|
||||
+ }
|
||||
+ softback_in = softback_curr = p;
|
||||
+ update_region(vc, vc->vc_origin,
|
||||
+ logo_lines * vc->vc_cols);
|
||||
+ }
|
||||
+ logo_shown = FBCON_LOGO_CANSHOW;
|
||||
+ }
|
||||
+ fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
|
||||
+ fbcon_redraw_softback(vc, disp, lines);
|
||||
+ fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
|
||||
+ return;
|
||||
}
|
||||
+
|
||||
+ if (!scrollback_phys_max)
|
||||
+ return;
|
||||
+
|
||||
+ scrollback_old = scrollback_current;
|
||||
+ scrollback_current -= lines;
|
||||
+ if (scrollback_current < 0)
|
||||
+ scrollback_current = 0;
|
||||
+ else if (scrollback_current > scrollback_max)
|
||||
+ scrollback_current = scrollback_max;
|
||||
+ if (scrollback_current == scrollback_old)
|
||||
+ return;
|
||||
+
|
||||
+ if (fbcon_is_inactive(vc, info))
|
||||
+ return;
|
||||
+
|
||||
+ fbcon_cursor(vc, CM_ERASE);
|
||||
+
|
||||
+ offset = disp->yscroll - scrollback_current;
|
||||
+ limit = disp->vrows;
|
||||
+ switch (disp->scrollmode) {
|
||||
+ case SCROLL_WRAP_MOVE:
|
||||
+ info->var.vmode |= FB_VMODE_YWRAP;
|
||||
+ break;
|
||||
+ case SCROLL_PAN_MOVE:
|
||||
+ case SCROLL_PAN_REDRAW:
|
||||
+ limit -= vc->vc_rows;
|
||||
+ info->var.vmode &= ~FB_VMODE_YWRAP;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (offset < 0)
|
||||
+ offset += limit;
|
||||
+ else if (offset >= limit)
|
||||
+ offset -= limit;
|
||||
+
|
||||
+ ops->var.xoffset = 0;
|
||||
+ ops->var.yoffset = offset * vc->vc_font.height;
|
||||
+ ops->update_start(info);
|
||||
+
|
||||
+ if (!scrollback_current)
|
||||
+ fbcon_cursor(vc, CM_DRAW);
|
||||
}
|
||||
|
||||
static int fbcon_set_origin(struct vc_data *vc)
|
||||
{
|
||||
+ if (softback_lines)
|
||||
+ fbcon_scrolldelta(vc, softback_lines);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2692,6 +3015,8 @@ static void fbcon_modechanged(struct fb_
|
||||
|
||||
fbcon_set_palette(vc, color_table);
|
||||
update_screen(vc);
|
||||
+ if (softback_buf)
|
||||
+ fbcon_update_softback(vc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3154,6 +3479,7 @@ static const struct consw fb_con = {
|
||||
.con_font_get = fbcon_get_font,
|
||||
.con_font_default = fbcon_set_def_font,
|
||||
.con_set_palette = fbcon_set_palette,
|
||||
+ .con_scrolldelta = fbcon_scrolldelta,
|
||||
.con_set_origin = fbcon_set_origin,
|
||||
.con_invert_region = fbcon_invert_region,
|
||||
.con_screen_pos = fbcon_screen_pos,
|
167
nongnu/packages/patches/rk3566-pinenote_dtsi.patch
Normal file
167
nongnu/packages/patches/rk3566-pinenote_dtsi.patch
Normal file
|
@ -0,0 +1,167 @@
|
|||
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
index 59ac178881b3..ec7183330b40 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
@@ -51,11 +51,11 @@ battery_cell: battery-cell {
|
||||
|
||||
ocv-capacity-celsius = <20>;
|
||||
ocv-capacity-table-0 = <4168000 100>,
|
||||
- <4109000 95>, <4066000 90>, <4023000 85>, <3985000 80>,
|
||||
- <3954000 75>, <3924000 70>, <3897000 65>, <3866000 60>,
|
||||
- <3826000 55>, <3804000 50>, <3789000 45>, <3777000 40>,
|
||||
- <3770000 35>, <3763000 30>, <3750000 25>, <3732000 20>,
|
||||
- <3710000 15>, <3680000 10>, <3670000 5>, <3500000 0>;
|
||||
+ <4109000 95>, <4066000 90>, <4023000 85>, <3985000 80>,
|
||||
+ <3954000 75>, <3924000 70>, <3897000 65>, <3866000 60>,
|
||||
+ <3826000 55>, <3804000 50>, <3789000 45>, <3777000 40>,
|
||||
+ <3770000 35>, <3763000 30>, <3750000 25>, <3732000 20>,
|
||||
+ <3710000 15>, <3680000 10>, <3670000 5>, <3500000 0>;
|
||||
};
|
||||
|
||||
bt_sco_codec: bt-sco-codec {
|
||||
@@ -63,26 +63,26 @@ bt_sco_codec: bt-sco-codec {
|
||||
#sound-dai-cells = <1>;
|
||||
};
|
||||
|
||||
- bt-sound {
|
||||
- compatible = "simple-audio-card";
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
- simple-audio-card,name = "PineNote Bluetooth";
|
||||
-
|
||||
- simple-audio-card,dai-link@0 {
|
||||
- format = "i2s";
|
||||
- frame-master = <&bt_link0_cpu>;
|
||||
- bitclock-master = <&bt_link0_cpu>;
|
||||
-
|
||||
- bt_link0_cpu: cpu {
|
||||
- sound-dai = <&i2s2_2ch>;
|
||||
- };
|
||||
-
|
||||
- bt_link0_codec: codec {
|
||||
- sound-dai = <&bt_sco_codec 0>;
|
||||
- };
|
||||
- };
|
||||
- };
|
||||
+ // bt-sound {
|
||||
+ // compatible = "simple-audio-card";
|
||||
+ // #address-cells = <1>;
|
||||
+ // #size-cells = <0>;
|
||||
+ // simple-audio-card,name = "PineNote Bluetooth";
|
||||
+//
|
||||
+ // simple-audio-card,dai-link@0 {
|
||||
+ // format = "i2s";
|
||||
+ // frame-master = <&bt_link0_cpu>;
|
||||
+ // bitclock-master = <&bt_link0_cpu>;
|
||||
+//
|
||||
+ // bt_link0_cpu: cpu {
|
||||
+ // sound-dai = <&i2s2_2ch>;
|
||||
+ // };
|
||||
+//
|
||||
+ // bt_link0_codec: codec {
|
||||
+ // sound-dai = <&bt_sco_codec 0>;
|
||||
+ // };
|
||||
+ // };
|
||||
+ // };
|
||||
|
||||
dmic_codec: dmic-codec {
|
||||
compatible = "dmic-codec";
|
||||
@@ -95,15 +95,15 @@ gpio-keys {
|
||||
pinctrl-0 = <&hall_int_l>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
- cover {
|
||||
- label = "cover";
|
||||
- gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_LOW>;
|
||||
- linux,input-type = <EV_SW>;
|
||||
- linux,code = <SW_MACHINE_COVER>;
|
||||
- linux,can-disable;
|
||||
- wakeup-event-action = <EV_ACT_DEASSERTED>;
|
||||
- wakeup-source;
|
||||
- };
|
||||
+ /* cover { */
|
||||
+ /* label = "cover"; */
|
||||
+ /* gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_LOW>; */
|
||||
+ /* linux,input-type = <EV_SW>; */
|
||||
+ /* linux,code = <SW_MACHINE_COVER>; */
|
||||
+ /* linux,can-disable; */
|
||||
+ /* wakeup-event-action = <EV_ACT_DEASSERTED>; */
|
||||
+ /* wakeup-source; */
|
||||
+ /* }; */
|
||||
};
|
||||
|
||||
gpio-leds {
|
||||
@@ -166,13 +166,13 @@ sound {
|
||||
simple-audio-card,name = "PineNote";
|
||||
simple-audio-card,aux-devs = <&spk_amp>;
|
||||
simple-audio-card,widgets = "Headphone", "Headphones",
|
||||
- "Speaker", "Internal Speakers";
|
||||
+ "Speaker", "Internal Speakers";
|
||||
simple-audio-card,routing = "Headphones", "HPOL",
|
||||
- "Headphones", "HPOR",
|
||||
- "Internal Speakers", "Speaker Amp OUTL",
|
||||
- "Internal Speakers", "Speaker Amp OUTR",
|
||||
- "Speaker Amp INL", "HPOL",
|
||||
- "Speaker Amp INR", "HPOR";
|
||||
+ "Headphones", "HPOR",
|
||||
+ "Internal Speakers", "Speaker Amp OUTL",
|
||||
+ "Internal Speakers", "Speaker Amp OUTR",
|
||||
+ "Speaker Amp INL", "HPOL",
|
||||
+ "Speaker Amp INR", "HPOR";
|
||||
simple-audio-card,pin-switches = "Internal Speakers";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@@ -340,7 +340,7 @@ &eink {
|
||||
|
||||
&gpu {
|
||||
mali-supply = <&vdd_gpu_npu>;
|
||||
- // status = "okay";
|
||||
+ status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
@@ -669,19 +669,31 @@ accelerometer@18 {
|
||||
st,drdy-int-pin = <1>;
|
||||
vdd-supply = <&vcc_3v3>;
|
||||
vddio-supply = <&vcc_3v3>;
|
||||
- };
|
||||
-
|
||||
- touchscreen@24 {
|
||||
- compatible = "cypress,tt21000";
|
||||
- hid-descr-addr = <0x1>;
|
||||
- reg = <0x24>;
|
||||
- interrupt-parent = <&gpio0>;
|
||||
- interrupts = <RK_PA6 IRQ_TYPE_LEVEL_LOW>;
|
||||
- pinctrl-0 = <&ts_int_l>, <&ts_rst_l>;
|
||||
- pinctrl-names = "default";
|
||||
- reset-gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
|
||||
- vdd-supply = <&vcc_3v3_pmu>;
|
||||
- };
|
||||
+ mount-matrix = "-1", "0", "0",
|
||||
+ "0", "1", "0",
|
||||
+ "0", "0", "1";
|
||||
+ };
|
||||
+
|
||||
+ // from pgwipeouts dtsi
|
||||
+ touchscreen@24 {
|
||||
+ compatible = "cypress,tma448";
|
||||
+// compatible = "cypress,tt21000";
|
||||
+ hid-descr-addr = <0x1>;
|
||||
+ reg = <0x24>;
|
||||
+ interrupt-parent = <&gpio0>;
|
||||
+ interrupts = <RK_PA6 IRQ_TYPE_LEVEL_LOW>;
|
||||
+ pinctrl-0 = <&ts_int_l>, <&ts_rst_l>;
|
||||
+ pinctrl-names = "default";
|
||||
+ reset-gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
|
||||
+ vdd-supply = <&vcc_3v3_pmu>;
|
||||
+ touchscreen-max-pressure = <46>;
|
||||
+ touchscreen-min-x = <10>;
|
||||
+ touchscreen-min-y = <5>;
|
||||
+ touchscreen-size-x = <1863>;
|
||||
+ touchscreen-size-y = <1399>;
|
||||
+ touchscreen-x-mm = <1864>;
|
||||
+ touchscreen-y-mm = <1400>;
|
||||
+ };
|
||||
};
|
||||
|
||||
&i2s1_8ch {
|
205
nongnu/packages/patches/rockchip_ebc_addition_extract_fbs.patch
Normal file
205
nongnu/packages/patches/rockchip_ebc_addition_extract_fbs.patch
Normal file
|
@ -0,0 +1,205 @@
|
|||
From c8d0d07432bd3cac0f5574165d132ec92754bb54 Mon Sep 17 00:00:00 2001
|
||||
From: Maximilian Weigand <mweigand@mweigand.net>
|
||||
Date: Mon, 20 Jun 2022 13:19:31 +0200
|
||||
Subject: [PATCH] [rockchip_ebc] * add a sysfs handler
|
||||
(/sys/module/rockchip_ebc/parameters/limit_fb_blits) to limit the numbers of
|
||||
framebuffer blits. The default value of -1 does not limit blits at all. Can
|
||||
be used to investigate the buffer contents while debugging complex drawing
|
||||
chains. * add an ioctl to retrieve the final, next, prev buffer
|
||||
contents to user space.
|
||||
|
||||
---
|
||||
drivers/gpu/drm/rockchip/rockchip_ebc.c | 120 +++++++++++++++---------
|
||||
include/uapi/drm/rockchip_ebc_drm.h | 10 +-
|
||||
2 files changed, 86 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/rockchip/rockchip_ebc.c b/drivers/gpu/drm/rockchip/rockchip_ebc.c
|
||||
index 15b14acbfd2b..66cc052cddcb 100644
|
||||
--- a/drivers/gpu/drm/rockchip/rockchip_ebc.c
|
||||
+++ b/drivers/gpu/drm/rockchip/rockchip_ebc.c
|
||||
@@ -197,6 +197,10 @@ static int split_area_limit = 12;
|
||||
module_param(split_area_limit, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(split_area_limit, "how many areas to split in each scheduling call");
|
||||
|
||||
+static int limit_fb_blits = -1;
|
||||
+module_param(limit_fb_blits, int, S_IRUGO|S_IWUSR);
|
||||
+MODULE_PARM_DESC(split_area_limit, "how many fb blits to allow. -1 does not limit");
|
||||
+
|
||||
DEFINE_DRM_GEM_FOPS(rockchip_ebc_fops);
|
||||
|
||||
static int ioctl_trigger_global_refresh(struct drm_device *dev, void *data,
|
||||
@@ -228,11 +232,72 @@ static int ioctl_set_off_screen(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+/**
|
||||
+ * struct rockchip_ebc_ctx - context for performing display refreshes
|
||||
+ *
|
||||
+ * @kref: Reference count, maintained as part of the CRTC's atomic state
|
||||
+ * @queue: Queue of damaged areas to be refreshed
|
||||
+ * @queue_lock: Lock protecting access to @queue
|
||||
+ * @prev: Display contents (Y4) before this refresh
|
||||
+ * @next: Display contents (Y4) after this refresh
|
||||
+ * @final: Display contents (Y4) after all pending refreshes
|
||||
+ * @phase: Buffers for selecting a phase from the EBC's LUT, 1 byte/pixel
|
||||
+ * @gray4_pitch: Horizontal line length of a Y4 pixel buffer in bytes
|
||||
+ * @gray4_size: Size of a Y4 pixel buffer in bytes
|
||||
+ * @phase_pitch: Horizontal line length of a phase buffer in bytes
|
||||
+ * @phase_size: Size of a phase buffer in bytes
|
||||
+ */
|
||||
+struct rockchip_ebc_ctx {
|
||||
+ struct kref kref;
|
||||
+ struct list_head queue;
|
||||
+ spinlock_t queue_lock;
|
||||
+ u8 *prev;
|
||||
+ u8 *next;
|
||||
+ u8 *final;
|
||||
+ u8 *phase[2];
|
||||
+ u32 gray4_pitch;
|
||||
+ u32 gray4_size;
|
||||
+ u32 phase_pitch;
|
||||
+ u32 phase_size;
|
||||
+ u64 area_count;
|
||||
+};
|
||||
+
|
||||
+struct ebc_crtc_state {
|
||||
+ struct drm_crtc_state base;
|
||||
+ struct rockchip_ebc_ctx *ctx;
|
||||
+};
|
||||
+
|
||||
+static inline struct ebc_crtc_state *
|
||||
+to_ebc_crtc_state(struct drm_crtc_state *crtc_state)
|
||||
+{
|
||||
+ return container_of(crtc_state, struct ebc_crtc_state, base);
|
||||
+}
|
||||
+static int ioctl_extract_fbs(struct drm_device *dev, void *data,
|
||||
+ struct drm_file *file_priv)
|
||||
+{
|
||||
+ struct drm_rockchip_ebc_extract_fbs *args = data;
|
||||
+ struct rockchip_ebc *ebc = dev_get_drvdata(dev->dev);
|
||||
+ int copy_result = 0;
|
||||
+ struct rockchip_ebc_ctx * ctx;
|
||||
+
|
||||
+ // todo: use access_ok here
|
||||
+ access_ok(args->ptr_next, 1313144);
|
||||
+ ctx = to_ebc_crtc_state(READ_ONCE(ebc->crtc.state))->ctx;
|
||||
+ copy_result |= copy_to_user(args->ptr_prev, ctx->prev ,1313144);
|
||||
+ copy_result |= copy_to_user(args->ptr_next, ctx->next ,1313144);
|
||||
+ copy_result |= copy_to_user(args->ptr_final, ctx->final ,1313144);
|
||||
+
|
||||
+ return copy_result;
|
||||
+}
|
||||
+
|
||||
static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
|
||||
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_GLOBAL_REFRESH, ioctl_trigger_global_refresh,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_OFF_SCREEN, ioctl_set_off_screen,
|
||||
DRM_RENDER_ALLOW),
|
||||
+ DRM_IOCTL_DEF_DRV(ROCKCHIP_EBC_EXTRACT_FBS, ioctl_extract_fbs,
|
||||
+ DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static const struct drm_driver rockchip_ebc_drm_driver = {
|
||||
@@ -268,36 +333,6 @@ struct rockchip_ebc_area {
|
||||
u32 frame_begin;
|
||||
};
|
||||
|
||||
-/**
|
||||
- * struct rockchip_ebc_ctx - context for performing display refreshes
|
||||
- *
|
||||
- * @kref: Reference count, maintained as part of the CRTC's atomic state
|
||||
- * @queue: Queue of damaged areas to be refreshed
|
||||
- * @queue_lock: Lock protecting access to @queue
|
||||
- * @prev: Display contents (Y4) before this refresh
|
||||
- * @next: Display contents (Y4) after this refresh
|
||||
- * @final: Display contents (Y4) after all pending refreshes
|
||||
- * @phase: Buffers for selecting a phase from the EBC's LUT, 1 byte/pixel
|
||||
- * @gray4_pitch: Horizontal line length of a Y4 pixel buffer in bytes
|
||||
- * @gray4_size: Size of a Y4 pixel buffer in bytes
|
||||
- * @phase_pitch: Horizontal line length of a phase buffer in bytes
|
||||
- * @phase_size: Size of a phase buffer in bytes
|
||||
- */
|
||||
-struct rockchip_ebc_ctx {
|
||||
- struct kref kref;
|
||||
- struct list_head queue;
|
||||
- spinlock_t queue_lock;
|
||||
- u8 *prev;
|
||||
- u8 *next;
|
||||
- u8 *final;
|
||||
- u8 *phase[2];
|
||||
- u32 gray4_pitch;
|
||||
- u32 gray4_size;
|
||||
- u32 phase_pitch;
|
||||
- u32 phase_size;
|
||||
- u64 area_count;
|
||||
-};
|
||||
-
|
||||
static void rockchip_ebc_ctx_free(struct rockchip_ebc_ctx *ctx)
|
||||
{
|
||||
struct rockchip_ebc_area *area;
|
||||
@@ -360,17 +395,6 @@ static void rockchip_ebc_ctx_release(struct kref *kref)
|
||||
* CRTC
|
||||
*/
|
||||
|
||||
-struct ebc_crtc_state {
|
||||
- struct drm_crtc_state base;
|
||||
- struct rockchip_ebc_ctx *ctx;
|
||||
-};
|
||||
-
|
||||
-static inline struct ebc_crtc_state *
|
||||
-to_ebc_crtc_state(struct drm_crtc_state *crtc_state)
|
||||
-{
|
||||
- return container_of(crtc_state, struct ebc_crtc_state, base);
|
||||
-}
|
||||
-
|
||||
static void rockchip_ebc_global_refresh(struct rockchip_ebc *ebc,
|
||||
struct rockchip_ebc_ctx *ctx,
|
||||
dma_addr_t next_handle,
|
||||
@@ -1551,8 +1575,18 @@ static void rockchip_ebc_plane_atomic_update(struct drm_plane *plane,
|
||||
dst_clip->x2 = plane_state->dst.x2 - x1;
|
||||
}
|
||||
|
||||
- clip_changed_fb = rockchip_ebc_blit_fb(ctx, dst_clip, vaddr,
|
||||
- plane_state->fb, &src_clip, adjust_x1, adjust_x2);
|
||||
+ if (limit_fb_blits != 0){
|
||||
+ printk(KERN_INFO "atomic update: blitting: %i\n", limit_fb_blits);
|
||||
+ clip_changed_fb = rockchip_ebc_blit_fb(ctx, dst_clip, vaddr,
|
||||
+ plane_state->fb, &src_clip, adjust_x1, adjust_x2);
|
||||
+ // the counter should only reach 0 here, -1 can only be externally set
|
||||
+ limit_fb_blits -= (limit_fb_blits > 0) ? 1 : 0;
|
||||
+ } else {
|
||||
+ // we do not want to blit anything
|
||||
+ printk(KERN_INFO "atomic update: not blitting: %i\n", limit_fb_blits);
|
||||
+ clip_changed_fb = false;
|
||||
+ }
|
||||
+
|
||||
|
||||
// reverse coordinates
|
||||
dst_clip->x1 += adjust_x1;
|
||||
diff --git a/include/uapi/drm/rockchip_ebc_drm.h b/include/uapi/drm/rockchip_ebc_drm.h
|
||||
index befa62a68be0..93289acf6d87 100644
|
||||
--- a/include/uapi/drm/rockchip_ebc_drm.h
|
||||
+++ b/include/uapi/drm/rockchip_ebc_drm.h
|
||||
@@ -17,9 +17,17 @@ struct drm_rockchip_ebc_off_screen {
|
||||
char * ptr_screen_content;
|
||||
};
|
||||
|
||||
-#define DRM_ROCKCHIP_EBC_NUM_IOCTLS 0x02
|
||||
+struct drm_rockchip_ebc_extract_fbs {
|
||||
+ char * ptr_prev;
|
||||
+ char * ptr_next;
|
||||
+ char * ptr_final;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+#define DRM_ROCKCHIP_EBC_NUM_IOCTLS 0x03
|
||||
|
||||
#define DRM_IOCTL_ROCKCHIP_EBC_GLOBAL_REFRESH DRM_IOWR(DRM_COMMAND_BASE + 0x00, struct drm_rockchip_ebc_trigger_global_refresh)
|
||||
#define DRM_IOCTL_ROCKCHIP_EBC_OFF_SCREEN DRM_IOWR(DRM_COMMAND_BASE + 0x01, struct drm_rockchip_ebc_off_screen)
|
||||
+#define DRM_IOCTL_ROCKCHIP_EBC_EXTRACT_FBS DRM_IOWR(DRM_COMMAND_BASE + 0x02, struct drm_rockchip_ebc_extract_fbs)
|
||||
|
||||
#endif /* __ROCKCHIP_EBC_DRM_H__*/
|
||||
--
|
||||
2.30.2
|
||||
|
2934
nongnu/packages/patches/rockchip_ebc_mw_20220624.patch
Normal file
2934
nongnu/packages/patches/rockchip_ebc_mw_20220624.patch
Normal file
File diff suppressed because it is too large
Load Diff
2999
nongnu/packages/patches/rockchip_ebc_patches_mw_20220712.patch
Normal file
2999
nongnu/packages/patches/rockchip_ebc_patches_mw_20220712.patch
Normal file
File diff suppressed because it is too large
Load Diff
3027
nongnu/packages/patches/rockchip_ebc_patches_mw_20220730.patch
Normal file
3027
nongnu/packages/patches/rockchip_ebc_patches_mw_20220730.patch
Normal file
File diff suppressed because it is too large
Load Diff
3152
nongnu/packages/patches/rockchip_ebc_patches_mw_20220804.patch
Normal file
3152
nongnu/packages/patches/rockchip_ebc_patches_mw_20220804.patch
Normal file
File diff suppressed because it is too large
Load Diff
3202
nongnu/packages/patches/rockchip_ebc_patches_mw_20220808.patch
Normal file
3202
nongnu/packages/patches/rockchip_ebc_patches_mw_20220808.patch
Normal file
File diff suppressed because it is too large
Load Diff
67
nongnu/packages/patches/sdbus-cpp-remove-systemd.patch
Normal file
67
nongnu/packages/patches/sdbus-cpp-remove-systemd.patch
Normal file
|
@ -0,0 +1,67 @@
|
|||
From 9f7400d32229c0a1d32349cf0a61900a50f0437a Mon Sep 17 00:00:00 2001
|
||||
From: Petr Hodina <phodina@protonmail.com>
|
||||
Date: Sun, 29 May 2022 06:09:27 +0200
|
||||
Subject: [PATCH] Remove systemd.
|
||||
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index be4e836..97f5aef 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -12,27 +12,6 @@ include(GNUInstallDirs) # Installation directories for `install` command and pkg
|
||||
# PERFORMING CHECKS & PREPARING THE DEPENDENCIES
|
||||
#-------------------------------
|
||||
|
||||
-option(BUILD_LIBSYSTEMD "Build libsystemd static library and incorporate it into libsdbus-c++" OFF)
|
||||
-
|
||||
-if(NOT BUILD_LIBSYSTEMD)
|
||||
- find_package(PkgConfig REQUIRED)
|
||||
- pkg_check_modules(Systemd IMPORTED_TARGET GLOBAL libsystemd>=236)
|
||||
- if(NOT TARGET PkgConfig::Systemd)
|
||||
- message(FATAL_ERROR "libsystemd of version at least 236 is required, but was not found "
|
||||
- "(if you have systemd in your OS, you may want to install package containing pkgconfig "
|
||||
- " files for libsystemd library. On Ubuntu, that is libsystemd-dev. "
|
||||
- " Alternatively, you may turn BUILD_LIBSYSTEMD on for sdbus-c++ to download, build "
|
||||
- "and incorporate libsystemd as embedded library within sdbus-c++)")
|
||||
- endif()
|
||||
- add_library(Systemd::Libsystemd ALIAS PkgConfig::Systemd)
|
||||
- string(REGEX MATCHALL "([0-9]+)" SYSTEMD_VERSION_LIST "${Systemd_VERSION}")
|
||||
- list(GET SYSTEMD_VERSION_LIST 0 LIBSYSTEMD_VERSION)
|
||||
- message(STATUS "Building with libsystemd v${LIBSYSTEMD_VERSION}")
|
||||
-else()
|
||||
- # Build static libsystemd library as an external project
|
||||
- include(cmake/LibsystemdExternalProject.cmake)
|
||||
-endif()
|
||||
-
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
#-------------------------------
|
||||
@@ -104,18 +83,13 @@ endif()
|
||||
|
||||
# Having an object target allows unit tests to reuse already built sources without re-building
|
||||
add_library(sdbus-c++-objlib OBJECT ${SDBUSCPP_SRCS})
|
||||
-target_compile_definitions(sdbus-c++-objlib PRIVATE BUILD_LIB=1 LIBSYSTEMD_VERSION=${LIBSYSTEMD_VERSION})
|
||||
target_include_directories(sdbus-c++-objlib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
|
||||
if(DEFINED BUILD_SHARED_LIBS)
|
||||
set_target_properties(sdbus-c++-objlib PROPERTIES POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS})
|
||||
endif()
|
||||
-if(BUILD_LIBSYSTEMD)
|
||||
- add_dependencies(sdbus-c++-objlib LibsystemdBuildProject)
|
||||
-endif()
|
||||
target_link_libraries(sdbus-c++-objlib
|
||||
PUBLIC
|
||||
- Systemd::Libsystemd
|
||||
Threads::Threads)
|
||||
|
||||
add_library(sdbus-c++)
|
||||
@@ -231,6 +205,5 @@ set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "libs")
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS ON)
|
||||
-set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "libsystemd-dev (>=236)")
|
||||
|
||||
include(CPack)
|
||||
--
|
||||
2.35.1
|
||||
|
976
nongnu/packages/patches/touchscreen-driver-01.patch
Normal file
976
nongnu/packages/patches/touchscreen-driver-01.patch
Normal file
|
@ -0,0 +1,976 @@
|
|||
From a24cb29eca1a72afb1037f5468d3036b34ea1b66 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Myl=C3=A8ne=20Josserand?= <mylene.josserand@bootlin.com>
|
||||
Date: Sun, 9 Jan 2022 21:53:28 +1000
|
||||
Subject: [PATCH] Input: Add driver for Cypress Generation 5 touchscreen
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This is the basic driver for the Cypress TrueTouch Gen5 touchscreen
|
||||
controllers. This driver supports only the I2C bus but it uses regmap
|
||||
so SPI support could be added later.
|
||||
The touchscreen can retrieve some defined zone that are handled as
|
||||
buttons (according to the hardware). That is why it handles
|
||||
button and multitouch events.
|
||||
|
||||
Reviewed-by: Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
Signed-off-by: Mylène Josserand <mylene.josserand@bootlin.com>
|
||||
Signed-off-by: Alistair Francis <alistair@alistair23.me>
|
||||
Tested-by: Andreas Kemnade <andreas@kemnade.info> # Kobo Clara HD
|
||||
---
|
||||
drivers/input/touchscreen/Kconfig | 16 +
|
||||
drivers/input/touchscreen/Makefile | 1 +
|
||||
drivers/input/touchscreen/cyttsp5.c | 902 ++++++++++++++++++++++++++++
|
||||
3 files changed, 919 insertions(+)
|
||||
create mode 100644 drivers/input/touchscreen/cyttsp5.c
|
||||
|
||||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
|
||||
index 2f6adfb7b938..eb4e1b156683 100644
|
||||
--- a/drivers/input/touchscreen/Kconfig
|
||||
+++ b/drivers/input/touchscreen/Kconfig
|
||||
@@ -284,6 +284,22 @@ config TOUCHSCREEN_CYTTSP4_SPI
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called cyttsp4_spi.
|
||||
|
||||
+config TOUCHSCREEN_CYTTSP5
|
||||
+ tristate "Cypress TrueTouch Gen5 Touchscreen Driver"
|
||||
+ depends on I2C
|
||||
+ select REGMAP_I2C
|
||||
+ select CRC_ITU_T
|
||||
+ help
|
||||
+ Driver for Parade TrueTouch Standard Product Generation 5
|
||||
+ touchscreen controllers. I2C bus interface support only.
|
||||
+
|
||||
+ Say Y here if you have a Cypress Gen5 touchscreen.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called cyttsp5.
|
||||
+
|
||||
config TOUCHSCREEN_DA9034
|
||||
tristate "Touchscreen support for Dialog Semiconductor DA9034"
|
||||
depends on PMIC_DA903X
|
||||
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
|
||||
index 39a8127cf6a5..0ea5c47f7fd9 100644
|
||||
--- a/drivers/input/touchscreen/Makefile
|
||||
+++ b/drivers/input/touchscreen/Makefile
|
||||
@@ -30,6 +30,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o
|
||||
+obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
|
||||
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
|
||||
new file mode 100644
|
||||
index 000000000000..3ac45108090c
|
||||
--- /dev/null
|
||||
+++ b/drivers/input/touchscreen/cyttsp5.c
|
||||
@@ -0,0 +1,902 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Parade TrueTouch(TM) Standard Product V5 Module.
|
||||
+ *
|
||||
+ * Copyright (C) 2015 Parade Technologies
|
||||
+ * Copyright (C) 2012-2015 Cypress Semiconductor
|
||||
+ * Copyright (C) 2018 Bootlin
|
||||
+ *
|
||||
+ * Authors: Mylène Josserand <mylene.josserand@bootlin.com>
|
||||
+ * Alistair Francis <alistair@alistair23.me>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/crc-itu-t.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/gpio/consumer.h>
|
||||
+#include <linux/input/mt.h>
|
||||
+#include <linux/input/touchscreen.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+#define CYTTSP5_NAME "cyttsp5"
|
||||
+#define CY_I2C_DATA_SIZE (2 * 256)
|
||||
+#define HID_VERSION 0x0100
|
||||
+#define CY_MAX_INPUT 512
|
||||
+#define CYTTSP5_PREALLOCATED_CMD_BUFFER 32
|
||||
+#define CY_BITS_PER_BTN 1
|
||||
+#define CY_NUM_BTN_EVENT_ID GENMASK(CY_BITS_PER_BTN, 0)
|
||||
+
|
||||
+#define MAX_AREA 255
|
||||
+#define HID_OUTPUT_BL_SOP 0x1
|
||||
+#define HID_OUTPUT_BL_EOP 0x17
|
||||
+#define HID_OUTPUT_BL_LAUNCH_APP 0x3B
|
||||
+#define HID_OUTPUT_BL_LAUNCH_APP_SIZE 11
|
||||
+#define HID_OUTPUT_GET_SYSINFO 0x2
|
||||
+#define HID_OUTPUT_GET_SYSINFO_SIZE 5
|
||||
+#define HID_OUTPUT_MAX_CMD_SIZE 12
|
||||
+
|
||||
+#define HID_DESC_REG 0x1
|
||||
+#define HID_INPUT_REG 0x3
|
||||
+#define HID_OUTPUT_REG 0x4
|
||||
+
|
||||
+#define REPORT_ID_TOUCH 0x1
|
||||
+#define REPORT_ID_BTN 0x3
|
||||
+#define REPORT_SIZE_5 5
|
||||
+#define REPORT_SIZE_8 8
|
||||
+#define REPORT_SIZE_16 16
|
||||
+
|
||||
+/* Touch reports offsets */
|
||||
+/* Header offsets */
|
||||
+#define TOUCH_REPORT_DESC_HDR_CONTACTCOUNT 16
|
||||
+/* Record offsets */
|
||||
+#define TOUCH_REPORT_DESC_CONTACTID 8
|
||||
+#define TOUCH_REPORT_DESC_X 16
|
||||
+#define TOUCH_REPORT_DESC_Y 32
|
||||
+#define TOUCH_REPORT_DESC_P 48
|
||||
+#define TOUCH_REPORT_DESC_MAJ 56
|
||||
+#define TOUCH_REPORT_DESC_MIN 64
|
||||
+
|
||||
+/* HID */
|
||||
+#define HID_TOUCH_REPORT_ID 0x1
|
||||
+#define HID_BTN_REPORT_ID 0x3
|
||||
+#define HID_APP_RESPONSE_REPORT_ID 0x1F
|
||||
+#define HID_APP_OUTPUT_REPORT_ID 0x2F
|
||||
+#define HID_BL_RESPONSE_REPORT_ID 0x30
|
||||
+#define HID_BL_OUTPUT_REPORT_ID 0x40
|
||||
+
|
||||
+#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2
|
||||
+#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4
|
||||
+#define HID_OUTPUT_RESPONSE_CMD_MASK GENMASK(6, 0)
|
||||
+
|
||||
+#define HID_SYSINFO_SENSING_OFFSET 33
|
||||
+#define HID_SYSINFO_BTN_OFFSET 48
|
||||
+#define HID_SYSINFO_BTN_MASK GENMASK(7, 0)
|
||||
+#define HID_SYSINFO_MAX_BTN 8
|
||||
+
|
||||
+#define CY_HID_OUTPUT_TIMEOUT_MS 200
|
||||
+#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000
|
||||
+#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000
|
||||
+
|
||||
+/* maximum number of concurrent tracks */
|
||||
+#define TOUCH_REPORT_SIZE 10
|
||||
+#define TOUCH_INPUT_HEADER_SIZE 7
|
||||
+#define BTN_REPORT_SIZE 9
|
||||
+#define BTN_INPUT_HEADER_SIZE 5
|
||||
+
|
||||
+#define MAX_CY_TCH_T_IDS 32
|
||||
+
|
||||
+/* All usage pages for Touch Report */
|
||||
+#define TOUCH_REPORT_USAGE_PG_X 0x00010030
|
||||
+#define TOUCH_REPORT_USAGE_PG_Y 0x00010031
|
||||
+#define TOUCH_REPORT_USAGE_PG_P 0x000D0030
|
||||
+#define TOUCH_REPORT_USAGE_PG_CONTACTID 0x000D0051
|
||||
+#define TOUCH_REPORT_USAGE_PG_CONTACTCOUNT 0x000D0054
|
||||
+#define TOUCH_REPORT_USAGE_PG_MAJ 0xFF010062
|
||||
+#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063
|
||||
+#define TOUCH_COL_USAGE_PG 0x000D0022
|
||||
+
|
||||
+/* System Information interface definitions */
|
||||
+struct cyttsp5_sensing_conf_data_dev {
|
||||
+ u8 electrodes_x;
|
||||
+ u8 electrodes_y;
|
||||
+ __le16 len_x;
|
||||
+ __le16 len_y;
|
||||
+ __le16 res_x;
|
||||
+ __le16 res_y;
|
||||
+ __le16 max_z;
|
||||
+ u8 origin_x;
|
||||
+ u8 origin_y;
|
||||
+ u8 btn;
|
||||
+ u8 scan_mode;
|
||||
+ u8 max_num_of_tch_per_refresh_cycle;
|
||||
+} __packed;
|
||||
+
|
||||
+struct cyttsp5_sensing_conf_data {
|
||||
+ u16 res_x;
|
||||
+ u16 res_y;
|
||||
+ u16 max_z;
|
||||
+ u16 len_x;
|
||||
+ u16 len_y;
|
||||
+ u8 origin_x;
|
||||
+ u8 origin_y;
|
||||
+ u8 max_tch;
|
||||
+};
|
||||
+
|
||||
+enum cyttsp5_tch_abs { /* for ordering within the extracted touch data array */
|
||||
+ CY_TCH_X, /* X */
|
||||
+ CY_TCH_Y, /* Y */
|
||||
+ CY_TCH_P, /* P (Z) */
|
||||
+ CY_TCH_T, /* TOUCH ID */
|
||||
+ CY_TCH_MAJ, /* TOUCH_MAJOR */
|
||||
+ CY_TCH_MIN, /* TOUCH_MINOR */
|
||||
+ CY_TCH_NUM_ABS
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_tch_abs_params {
|
||||
+ size_t ofs; /* abs byte offset */
|
||||
+ size_t size; /* size in bits */
|
||||
+ size_t min; /* min value */
|
||||
+ size_t max; /* max value */
|
||||
+ size_t bofs; /* bit offset */
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_touch {
|
||||
+ int abs[CY_TCH_NUM_ABS];
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_sysinfo {
|
||||
+ struct cyttsp5_sensing_conf_data sensing_conf_data;
|
||||
+ int num_btns;
|
||||
+ struct cyttsp5_tch_abs_params tch_hdr;
|
||||
+ struct cyttsp5_tch_abs_params tch_abs[CY_TCH_NUM_ABS];
|
||||
+ u32 key_code[HID_SYSINFO_MAX_BTN];
|
||||
+};
|
||||
+
|
||||
+struct cyttsp5_hid_desc {
|
||||
+ __le16 hid_desc_len;
|
||||
+ u8 packet_id;
|
||||
+ u8 reserved_byte;
|
||||
+ __le16 bcd_version;
|
||||
+ __le16 report_desc_len;
|
||||
+ __le16 report_desc_register;
|
||||
+ __le16 input_register;
|
||||
+ __le16 max_input_len;
|
||||
+ __le16 output_register;
|
||||
+ __le16 max_output_len;
|
||||
+ __le16 command_register;
|
||||
+ __le16 data_register;
|
||||
+ __le16 vendor_id;
|
||||
+ __le16 product_id;
|
||||
+ __le16 version_id;
|
||||
+ u8 reserved[4];
|
||||
+} __packed;
|
||||
+
|
||||
+struct cyttsp5 {
|
||||
+ struct device *dev;
|
||||
+ struct completion cmd_done;
|
||||
+ struct cyttsp5_sysinfo sysinfo;
|
||||
+ struct cyttsp5_hid_desc hid_desc;
|
||||
+ u8 cmd_buf[CYTTSP5_PREALLOCATED_CMD_BUFFER];
|
||||
+ u8 input_buf[CY_MAX_INPUT];
|
||||
+ u8 response_buf[CY_MAX_INPUT];
|
||||
+ struct gpio_desc *reset_gpio;
|
||||
+ struct input_dev *input;
|
||||
+ char phys[NAME_MAX];
|
||||
+ int num_prv_rec;
|
||||
+ struct regmap *regmap;
|
||||
+ struct touchscreen_properties prop;
|
||||
+ struct regulator *vdd;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * For what is understood in the datasheet, the register does not
|
||||
+ * matter. For consistency, use the Input Register address
|
||||
+ * but it does mean anything to the device. The important data
|
||||
+ * to send is the I2C address
|
||||
+ */
|
||||
+static int cyttsp5_read(struct cyttsp5 *ts, u8 *buf, u32 max)
|
||||
+{
|
||||
+ int error;
|
||||
+ u32 size;
|
||||
+ u8 temp[2];
|
||||
+
|
||||
+ /* Read the frame to retrieve the size */
|
||||
+ error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, temp, sizeof(temp));
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+
|
||||
+ size = get_unaligned_le16(temp);
|
||||
+ if (!size || size == 2)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (size > max)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Get the real value */
|
||||
+ return regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, size);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_write(struct cyttsp5 *ts, unsigned int reg, u8 *data,
|
||||
+ size_t size)
|
||||
+{
|
||||
+ u8 cmd[HID_OUTPUT_MAX_CMD_SIZE];
|
||||
+
|
||||
+ if (size + 1 > HID_OUTPUT_MAX_CMD_SIZE)
|
||||
+ return -E2BIG;
|
||||
+
|
||||
+ /* High bytes of register address needed as first byte of cmd */
|
||||
+ cmd[0] = (reg >> 8) & 0xFF ;
|
||||
+
|
||||
+ /* Copy the rest of the data */
|
||||
+ if (data)
|
||||
+ memcpy(&cmd[1], data, size);
|
||||
+
|
||||
+ /*
|
||||
+ * The hardware wants to receive a frame with the address register
|
||||
+ * contained in the first two bytes. As the regmap_write function
|
||||
+ * add the register adresse in the frame, we use the low byte as
|
||||
+ * first frame byte for the address register and the first
|
||||
+ * data byte is the high register + left of the cmd to send
|
||||
+ */
|
||||
+ return regmap_bulk_write(ts->regmap, reg & 0xFF, cmd, size + 1);
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_touch_axis(int *axis, int size, int max, u8 *xy_data,
|
||||
+ int bofs)
|
||||
+{
|
||||
+ int nbyte;
|
||||
+
|
||||
+ for (nbyte = 0, *axis = 0; nbyte < size; nbyte++)
|
||||
+ *axis += ((xy_data[nbyte] >> bofs) << (nbyte * 8));
|
||||
+
|
||||
+ *axis &= max - 1;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_touch_record(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_touch *touch, u8 *xy_data)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ enum cyttsp5_tch_abs abs;
|
||||
+
|
||||
+ for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++)
|
||||
+ cyttsp5_get_touch_axis(&touch->abs[abs],
|
||||
+ si->tch_abs[abs].size,
|
||||
+ si->tch_abs[abs].max,
|
||||
+ xy_data + si->tch_abs[abs].ofs,
|
||||
+ si->tch_abs[abs].bofs);
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_get_mt_touches(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_touch *tch, int num_cur_tch)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int i, t = 0, offset = 0;
|
||||
+ DECLARE_BITMAP(ids, MAX_CY_TCH_T_IDS);
|
||||
+ u8 *tch_addr;
|
||||
+ int tmp;
|
||||
+
|
||||
+ bitmap_zero(ids, MAX_CY_TCH_T_IDS);
|
||||
+ memset(tch->abs, 0, sizeof(tch->abs));
|
||||
+
|
||||
+ switch (ts->input_buf[2]) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ offset = TOUCH_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ offset = BTN_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < num_cur_tch; i++) {
|
||||
+ tch_addr = ts->input_buf + offset + (i * TOUCH_REPORT_SIZE);
|
||||
+ cyttsp5_get_touch_record(ts, tch, tch_addr);
|
||||
+
|
||||
+ /* Convert MAJOR/MINOR from mm to resolution */
|
||||
+ tmp = tch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
|
||||
+ tch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
|
||||
+ tmp = tch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
|
||||
+ tch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
|
||||
+
|
||||
+ t = tch->abs[CY_TCH_T];
|
||||
+ input_mt_slot(ts->input, t);
|
||||
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true);
|
||||
+ __set_bit(t, ids);
|
||||
+
|
||||
+ /* position and pressure fields */
|
||||
+ touchscreen_report_pos(ts->input, &ts->prop,
|
||||
+ tch->abs[CY_TCH_X], tch->abs[CY_TCH_Y],
|
||||
+ true);
|
||||
+ input_report_abs(ts->input, ABS_MT_PRESSURE,
|
||||
+ tch->abs[CY_TCH_P]);
|
||||
+
|
||||
+ /* Get the extended touch fields */
|
||||
+ input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
|
||||
+ tch->abs[CY_TCH_MAJ]);
|
||||
+ input_report_abs(ts->input, ABS_MT_TOUCH_MINOR,
|
||||
+ tch->abs[CY_TCH_MIN]);
|
||||
+ }
|
||||
+
|
||||
+ ts->num_prv_rec = num_cur_tch;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_mt_attention(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int max_tch = si->sensing_conf_data.max_tch;
|
||||
+ struct cyttsp5_touch tch;
|
||||
+ u8 num_cur_tch;
|
||||
+
|
||||
+ cyttsp5_get_touch_axis((int *) &num_cur_tch, si->tch_hdr.size,
|
||||
+ si->tch_hdr.max,
|
||||
+ ts->input_buf + 3 + si->tch_hdr.ofs,
|
||||
+ si->tch_hdr.bofs);
|
||||
+
|
||||
+ if (num_cur_tch > max_tch) {
|
||||
+ dev_err(dev, "Num touch err detected (n=%d)\n", num_cur_tch);
|
||||
+ num_cur_tch = max_tch;
|
||||
+ }
|
||||
+
|
||||
+ if (num_cur_tch == 0 && ts->num_prv_rec == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* extract xy_data for all currently reported touches */
|
||||
+ if (num_cur_tch)
|
||||
+ cyttsp5_get_mt_touches(ts, &tch, num_cur_tch);
|
||||
+
|
||||
+ input_mt_sync_frame(ts->input);
|
||||
+ input_sync(ts->input);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_setup_input_device(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int max_x, max_y, max_p;
|
||||
+ int max_x_tmp, max_y_tmp;
|
||||
+ int error;
|
||||
+
|
||||
+ max_x_tmp = si->sensing_conf_data.res_x;
|
||||
+ max_y_tmp = si->sensing_conf_data.res_y;
|
||||
+ max_x = max_x_tmp - 1;
|
||||
+ max_y = max_y_tmp - 1;
|
||||
+ max_p = si->sensing_conf_data.max_z;
|
||||
+
|
||||
+ input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, max_x, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, max_y, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, max_p, 0, 0);
|
||||
+
|
||||
+ input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, MAX_AREA, 0, 0);
|
||||
+ input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, MAX_AREA, 0, 0);
|
||||
+
|
||||
+ error = input_mt_init_slots(ts->input, si->tch_abs[CY_TCH_T].max,
|
||||
+ INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT);
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ error = input_register_device(ts->input);
|
||||
+ if (error < 0)
|
||||
+ dev_err(dev, "Error, failed register input device r=%d\n", error);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_parse_dt_key_code(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+
|
||||
+ if (!si->num_btns)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Initialize the button to RESERVED */
|
||||
+ memset32(si->key_code, KEY_RESERVED, si->num_btns);
|
||||
+
|
||||
+ return device_property_read_u32_array(dev, "linux,keycodes",
|
||||
+ si->key_code, si->num_btns);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_btn_attention(struct device *dev)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ int cur_btn, offset = 0;
|
||||
+ int cur_btn_state;
|
||||
+
|
||||
+ switch (ts->input_buf[2]) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ offset = TOUCH_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ offset = BTN_INPUT_HEADER_SIZE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (ts->input_buf[2] != HID_BTN_REPORT_ID || !si->num_btns)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* extract button press/release touch information */
|
||||
+ for (cur_btn = 0; cur_btn < si->num_btns; cur_btn++) {
|
||||
+ /* Get current button state */
|
||||
+ cur_btn_state = (ts->input_buf[offset] >> (cur_btn * CY_BITS_PER_BTN))
|
||||
+ & CY_NUM_BTN_EVENT_ID;
|
||||
+
|
||||
+ input_report_key(ts->input, si->key_code[cur_btn],
|
||||
+ cur_btn_state);
|
||||
+ input_sync(ts->input);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_validate_cmd_response(struct cyttsp5 *ts, u8 code)
|
||||
+{
|
||||
+ u16 size, crc;
|
||||
+ u8 status, report_id;
|
||||
+ int command_code;
|
||||
+
|
||||
+ size = get_unaligned_le16(&ts->response_buf[0]);
|
||||
+
|
||||
+ if (!size)
|
||||
+ return 0;
|
||||
+
|
||||
+ report_id = ts->response_buf[HID_OUTPUT_RESPONSE_REPORT_OFFSET];
|
||||
+
|
||||
+ switch (report_id) {
|
||||
+ case HID_BL_RESPONSE_REPORT_ID: {
|
||||
+ if (ts->response_buf[4] != HID_OUTPUT_BL_SOP) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong SOP\n");
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ if (ts->response_buf[size - 1] != HID_OUTPUT_BL_EOP) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong EOP\n");
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ crc = crc_itu_t(0xFFFF, &ts->response_buf[4], size - 7);
|
||||
+ if (get_unaligned_le16(&ts->response_buf[size - 3]) != crc) {
|
||||
+ dev_err(ts->dev, "HID output response, wrong CRC 0x%X\n",
|
||||
+ crc);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+
|
||||
+ status = ts->response_buf[5];
|
||||
+ if (status) {
|
||||
+ dev_err(ts->dev, "HID output response, ERROR:%d\n",
|
||||
+ status);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ case HID_APP_RESPONSE_REPORT_ID: {
|
||||
+ command_code = ts->response_buf[HID_OUTPUT_RESPONSE_CMD_OFFSET]
|
||||
+ & HID_OUTPUT_RESPONSE_CMD_MASK;
|
||||
+ if (command_code != code) {
|
||||
+ dev_err(ts->dev,
|
||||
+ "HID output response, wrong command_code:%X\n",
|
||||
+ command_code);
|
||||
+ return -EPROTO;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_si_get_btn_data(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+ unsigned int btns = ts->response_buf[HID_SYSINFO_BTN_OFFSET]
|
||||
+ & HID_SYSINFO_BTN_MASK;
|
||||
+
|
||||
+ si->num_btns = hweight8(btns);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sensing_conf_data *scd = &ts->sysinfo.sensing_conf_data;
|
||||
+ struct cyttsp5_sensing_conf_data_dev *scd_dev =
|
||||
+ (struct cyttsp5_sensing_conf_data_dev *)
|
||||
+ &ts->response_buf[HID_SYSINFO_SENSING_OFFSET];
|
||||
+
|
||||
+ cyttsp5_si_get_btn_data(ts);
|
||||
+
|
||||
+ scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle;
|
||||
+ scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
+ scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
+ scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
+ scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
+ scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int rc;
|
||||
+ u8 cmd[HID_OUTPUT_GET_SYSINFO_SIZE];
|
||||
+
|
||||
+ /* HI bytes of Output register address */
|
||||
+ put_unaligned_le16(HID_OUTPUT_GET_SYSINFO_SIZE, cmd);
|
||||
+ cmd[2] = HID_APP_OUTPUT_REPORT_ID;
|
||||
+ cmd[3] = 0x0; /* Reserved */
|
||||
+ cmd[4] = HID_OUTPUT_GET_SYSINFO;
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd,
|
||||
+ HID_OUTPUT_GET_SYSINFO_SIZE);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Failed to write command %d", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID output cmd execution timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_GET_SYSINFO);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Validation of the response failed\n");
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ return cyttsp5_get_sysinfo_regs(ts);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int rc;
|
||||
+ u8 cmd[HID_OUTPUT_BL_LAUNCH_APP];
|
||||
+ u16 crc;
|
||||
+
|
||||
+ put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd);
|
||||
+ cmd[2] = HID_BL_OUTPUT_REPORT_ID;
|
||||
+ cmd[3] = 0x0; /* Reserved */
|
||||
+ cmd[4] = HID_OUTPUT_BL_SOP;
|
||||
+ cmd[5] = HID_OUTPUT_BL_LAUNCH_APP;
|
||||
+ put_unaligned_le16(0x00, &cmd[6]);
|
||||
+ crc = crc_itu_t(0xFFFF, &cmd[4], 4);
|
||||
+ put_unaligned_le16(crc, &cmd[8]);
|
||||
+ cmd[10] = HID_OUTPUT_BL_EOP;
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_OUTPUT_REG, cmd,
|
||||
+ HID_OUTPUT_BL_LAUNCH_APP_SIZE);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Failed to write command %d", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_OUTPUT_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID output cmd execution timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = cyttsp5_validate_cmd_response(ts, HID_OUTPUT_BL_LAUNCH_APP);
|
||||
+ if (rc) {
|
||||
+ dev_err(ts->dev, "Validation of the response failed\n");
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts,
|
||||
+ struct cyttsp5_hid_desc *desc)
|
||||
+{
|
||||
+ struct device *dev = ts->dev;
|
||||
+ __le16 hid_desc_register = HID_DESC_REG;
|
||||
+ int rc;
|
||||
+ u8 cmd[2];
|
||||
+
|
||||
+ /* Set HID descriptor register */
|
||||
+ memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register));
|
||||
+
|
||||
+ rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0);
|
||||
+ if (rc) {
|
||||
+ dev_err(dev, "Failed to get HID descriptor, rc=%d\n", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
+ msecs_to_jiffies(CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS));
|
||||
+ if (rc <= 0) {
|
||||
+ dev_err(ts->dev, "HID get descriptor timed out\n");
|
||||
+ rc = -ETIMEDOUT;
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(desc, ts->response_buf, sizeof(*desc));
|
||||
+
|
||||
+ /* Check HID descriptor length and version */
|
||||
+ if (le16_to_cpu(desc->hid_desc_len) != sizeof(*desc) ||
|
||||
+ le16_to_cpu(desc->bcd_version) != HID_VERSION) {
|
||||
+ dev_err(dev, "Unsupported HID version\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fill_tch_abs(struct cyttsp5_tch_abs_params *tch_abs, int report_size,
|
||||
+ int offset)
|
||||
+{
|
||||
+ tch_abs->ofs = offset / 8;
|
||||
+ tch_abs->size = report_size / 8;
|
||||
+ if (report_size % 8)
|
||||
+ tch_abs->size += 1;
|
||||
+ tch_abs->min = 0;
|
||||
+ tch_abs->max = 1 << report_size;
|
||||
+ tch_abs->bofs = offset - (tch_abs->ofs << 3);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t cyttsp5_handle_irq(int irq, void *handle)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = handle;
|
||||
+ int report_id;
|
||||
+ int size;
|
||||
+ int error;
|
||||
+
|
||||
+ error = cyttsp5_read(ts, ts->input_buf, CY_MAX_INPUT);
|
||||
+ if (error)
|
||||
+ return IRQ_HANDLED;
|
||||
+
|
||||
+ size = get_unaligned_le16(&ts->input_buf[0]);
|
||||
+ if (size == 0) {
|
||||
+ /* reset */
|
||||
+ report_id = 0;
|
||||
+ size = 2;
|
||||
+ } else {
|
||||
+ report_id = ts->input_buf[2];
|
||||
+ }
|
||||
+
|
||||
+ switch (report_id) {
|
||||
+ case HID_TOUCH_REPORT_ID:
|
||||
+ cyttsp5_mt_attention(ts->dev);
|
||||
+ break;
|
||||
+ case HID_BTN_REPORT_ID:
|
||||
+ cyttsp5_btn_attention(ts->dev);
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* It is not an input but a command response */
|
||||
+ memcpy(ts->response_buf, ts->input_buf, size);
|
||||
+ complete(&ts->cmd_done);
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_deassert_int(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ u16 size;
|
||||
+ u8 buf[2];
|
||||
+ int error;
|
||||
+
|
||||
+ error = regmap_bulk_read(ts->regmap, HID_INPUT_REG, buf, sizeof(buf));
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ size = get_unaligned_le16(&buf[0]);
|
||||
+ if (size == 2 || size == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_fill_all_touch(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ struct cyttsp5_sysinfo *si = &ts->sysinfo;
|
||||
+
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_X], REPORT_SIZE_16,
|
||||
+ TOUCH_REPORT_DESC_X);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_Y], REPORT_SIZE_16,
|
||||
+ TOUCH_REPORT_DESC_Y);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_P], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_P);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_T], REPORT_SIZE_5,
|
||||
+ TOUCH_REPORT_DESC_CONTACTID);
|
||||
+ fill_tch_abs(&si->tch_hdr, REPORT_SIZE_5,
|
||||
+ TOUCH_REPORT_DESC_HDR_CONTACTCOUNT);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_MAJ], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_MAJ);
|
||||
+ fill_tch_abs(&si->tch_abs[CY_TCH_MIN], REPORT_SIZE_8,
|
||||
+ TOUCH_REPORT_DESC_MIN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_startup(struct cyttsp5 *ts)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ error = cyttsp5_deassert_int(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Error on deassert int r=%d\n", error);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Launch the application as the device starts in bootloader mode
|
||||
+ * because of a power-on-reset
|
||||
+ */
|
||||
+ error = cyttsp5_hid_output_bl_launch_app(ts);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on launch app r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_get_hid_descriptor(ts, &ts->hid_desc);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on getting HID descriptor r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_fill_all_touch(ts);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error on report descriptor r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_hid_output_get_sysinfo(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Error on getting sysinfo r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static void cyttsp5_cleanup(void *data)
|
||||
+{
|
||||
+ struct cyttsp5 *ts = data;
|
||||
+
|
||||
+ regulator_disable(ts->vdd);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq,
|
||||
+ const char *name)
|
||||
+{
|
||||
+ struct cyttsp5 *ts;
|
||||
+ struct cyttsp5_sysinfo *si;
|
||||
+ int error, i;
|
||||
+
|
||||
+ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
|
||||
+ if (!ts)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Initialize device info */
|
||||
+ ts->regmap = regmap;
|
||||
+ ts->dev = dev;
|
||||
+ si = &ts->sysinfo;
|
||||
+ dev_set_drvdata(dev, ts);
|
||||
+
|
||||
+ init_completion(&ts->cmd_done);
|
||||
+
|
||||
+ /* Power up the device */
|
||||
+ ts->vdd = devm_regulator_get(dev, "vdd");
|
||||
+ if (IS_ERR(ts->vdd)) {
|
||||
+ error = PTR_ERR(ts->vdd);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = devm_add_action_or_reset(dev, cyttsp5_cleanup, ts);
|
||||
+ if (error) {
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = regulator_enable(ts->vdd);
|
||||
+ if (error) {
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ ts->input = devm_input_allocate_device(dev);
|
||||
+ if (!ts->input) {
|
||||
+ dev_err(dev, "Error, failed to allocate input device\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ ts->input->name = "cyttsp5";
|
||||
+ scnprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
|
||||
+ ts->input->phys = ts->phys;
|
||||
+ input_set_drvdata(ts->input, ts);
|
||||
+
|
||||
+ /* Reset the gpio to be in a reset state */
|
||||
+ ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
+ if (IS_ERR(ts->reset_gpio)) {
|
||||
+ error = PTR_ERR(ts->reset_gpio);
|
||||
+ dev_err(dev, "Failed to request reset gpio, error %d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+ gpiod_set_value(ts->reset_gpio, 0);
|
||||
+
|
||||
+ /* Need a delay to have device up */
|
||||
+ msleep(20);
|
||||
+
|
||||
+ error = devm_request_threaded_irq(dev, irq, NULL, cyttsp5_handle_irq,
|
||||
+ IRQF_ONESHOT, name, ts);
|
||||
+ if (error) {
|
||||
+ dev_err(dev, "unable to request IRQ\n");
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_startup(ts);
|
||||
+ if (error) {
|
||||
+ dev_err(ts->dev, "Fail initial startup r=%d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = cyttsp5_parse_dt_key_code(dev);
|
||||
+ if (error < 0) {
|
||||
+ dev_err(ts->dev, "Error while parsing dts %d\n", error);
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ touchscreen_parse_properties(ts->input, true, &ts->prop);
|
||||
+
|
||||
+ __set_bit(EV_KEY, ts->input->evbit);
|
||||
+ for (i = 0; i < si->num_btns; i++)
|
||||
+ __set_bit(si->key_code[i], ts->input->keybit);
|
||||
+
|
||||
+ return cyttsp5_setup_input_device(dev);
|
||||
+}
|
||||
+
|
||||
+static int cyttsp5_i2c_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *id)
|
||||
+{
|
||||
+ struct regmap *regmap;
|
||||
+ static const struct regmap_config config = {
|
||||
+ .reg_bits = 8,
|
||||
+ .val_bits = 8,
|
||||
+ };
|
||||
+
|
||||
+ regmap = devm_regmap_init_i2c(client, &config);
|
||||
+ if (IS_ERR(regmap)) {
|
||||
+ dev_err(&client->dev, "regmap allocation failed: %ld\n",
|
||||
+ PTR_ERR(regmap));
|
||||
+ return PTR_ERR(regmap);
|
||||
+ }
|
||||
+
|
||||
+ return cyttsp5_probe(&client->dev, regmap, client->irq, client->name);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id cyttsp5_of_match[] = {
|
||||
+ { .compatible = "cypress,tt21000", },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
|
||||
+
|
||||
+static const struct i2c_device_id cyttsp5_i2c_id[] = {
|
||||
+ { CYTTSP5_NAME, 0, },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
|
||||
+
|
||||
+static struct i2c_driver cyttsp5_i2c_driver = {
|
||||
+ .driver = {
|
||||
+ .name = CYTTSP5_NAME,
|
||||
+ .of_match_table = cyttsp5_of_match,
|
||||
+ },
|
||||
+ .probe = cyttsp5_i2c_probe,
|
||||
+ .id_table = cyttsp5_i2c_id,
|
||||
+};
|
||||
+module_i2c_driver(cyttsp5_i2c_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_DESCRIPTION("Touchscreen driver for Cypress TrueTouch Gen 5 Product");
|
||||
+MODULE_AUTHOR("Mylène Josserand <mylene.josserand@bootlin.com>");
|
||||
--
|
||||
GitLab
|
||||
|
108
nongnu/packages/patches/touchscreen-driver-02.patch
Normal file
108
nongnu/packages/patches/touchscreen-driver-02.patch
Normal file
|
@ -0,0 +1,108 @@
|
|||
From d6bb8a6b5a5210fea70bc590350bfca3a9e3a7a2 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Geis <pgwipeout@gmail.com>
|
||||
Date: Sat, 15 Jan 2022 21:50:45 -0500
|
||||
Subject: [PATCH] Input: cyttsp5: support touchscreen device tree overrides
|
||||
|
||||
It is possible for the cyttsp5 chip to not have a configuration burned
|
||||
to it.
|
||||
This leads to a sitatuion where all calibration values return zero,
|
||||
leading to a broken touchscreen configuration.
|
||||
|
||||
The current driver does not support utilizing overrides from the device
|
||||
tree.
|
||||
Extend the driver to support this, and permit it to do some basic sanity
|
||||
checking of the values for the touchscreen and abort if they are
|
||||
invalid.
|
||||
|
||||
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
|
||||
---
|
||||
drivers/input/touchscreen/cyttsp5.c | 62 ++++++++++++++++++++++++++---
|
||||
1 file changed, 57 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
|
||||
index 3ac45108090c..e837985d199a 100644
|
||||
--- a/drivers/input/touchscreen/cyttsp5.c
|
||||
+++ b/drivers/input/touchscreen/cyttsp5.c
|
||||
@@ -507,15 +507,66 @@ static int cyttsp5_get_sysinfo_regs(struct cyttsp5 *ts)
|
||||
struct cyttsp5_sensing_conf_data_dev *scd_dev =
|
||||
(struct cyttsp5_sensing_conf_data_dev *)
|
||||
&ts->response_buf[HID_SYSINFO_SENSING_OFFSET];
|
||||
+ u32 tmp;
|
||||
|
||||
cyttsp5_si_get_btn_data(ts);
|
||||
|
||||
scd->max_tch = scd_dev->max_num_of_tch_per_refresh_cycle;
|
||||
- scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
- scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
- scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
- scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
- scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+
|
||||
+ if (scd->max_tch == 0) {
|
||||
+ dev_dbg(ts->dev, "Max touch points cannot be zero\n");
|
||||
+ scd->max_tch = 2;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-size-x", &tmp))
|
||||
+ scd->res_x = get_unaligned_le16(&scd_dev->res_x);
|
||||
+ else
|
||||
+ scd->res_x = tmp;
|
||||
+
|
||||
+ if (scd->res_x == 0) {
|
||||
+ dev_err(ts->dev, "ABS_X cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-size-y", &tmp))
|
||||
+ scd->res_y = get_unaligned_le16(&scd_dev->res_y);
|
||||
+ else
|
||||
+ scd->res_y = tmp;
|
||||
+
|
||||
+ if (scd->res_y == 0) {
|
||||
+ dev_err(ts->dev, "ABS_Y cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-max-pressure", &tmp))
|
||||
+ scd->max_z = get_unaligned_le16(&scd_dev->max_z);
|
||||
+ else
|
||||
+ scd->max_z = tmp;
|
||||
+
|
||||
+ if (scd->max_z == 0) {
|
||||
+ dev_err(ts->dev, "ABS_PRESSURE cannot be zero\n");
|
||||
+ return -ENODATA;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-x-mm", &tmp))
|
||||
+ scd->len_x = get_unaligned_le16(&scd_dev->len_x);
|
||||
+ else
|
||||
+ scd->len_x = tmp;
|
||||
+
|
||||
+ if (scd->len_x == 0) {
|
||||
+ dev_dbg(ts->dev, "Touchscreen size x cannot be zero\n");
|
||||
+ scd->len_x = scd->res_x + 1;
|
||||
+ }
|
||||
+
|
||||
+ if(device_property_read_u32(ts->dev, "touchscreen-y-mm", &tmp))
|
||||
+ scd->len_y = get_unaligned_le16(&scd_dev->len_y);
|
||||
+ else
|
||||
+ scd->len_y = tmp;
|
||||
+
|
||||
+ if (scd->len_y == 0) {
|
||||
+ dev_dbg(ts->dev, "Touchscreen size y cannot be zero\n");
|
||||
+ scd->len_y = scd->res_y + 1;
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -877,6 +928,7 @@ static int cyttsp5_i2c_probe(struct i2c_client *client,
|
||||
|
||||
static const struct of_device_id cyttsp5_of_match[] = {
|
||||
{ .compatible = "cypress,tt21000", },
|
||||
+ { .compatible = "cypress,tma448", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
|
||||
--
|
||||
GitLab
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote-v1.2.dts b/arch/arm64/boot/dts/rockchip/rk3566-pinenote-v1.2.dts
|
||||
index 6bbc4c675d..92ef19676e 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote-v1.2.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote-v1.2.dts
|
||||
@@ -16,3 +16,39 @@ &pmu_io_domains {
|
||||
&spk_amp {
|
||||
VCC-supply = <&vcc_bat>;
|
||||
};
|
||||
+
|
||||
+&usb2phy0_otg {
|
||||
+ port {
|
||||
+ usb2phy0_typec_hs: endpoint {
|
||||
+ remote-endpoint = <&usbc_hs>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+&wusb3801 {
|
||||
+ status = "okay";
|
||||
+
|
||||
+ connector {
|
||||
+ compatible = "usb-c-connector";
|
||||
+ label = "USB-C";
|
||||
+ vbus-supply = <&otg_switch>;
|
||||
+ power-role = "dual";
|
||||
+ try-power-role = "sink";
|
||||
+ data-role = "dual";
|
||||
+ typec-power-opmode = "default";
|
||||
+ pd-disable;
|
||||
+
|
||||
+ ports {
|
||||
+ #address-cells = <0x01>;
|
||||
+ #size-cells = <0x00>;
|
||||
+
|
||||
+ port@0 {
|
||||
+ reg = <0x00>;
|
||||
+
|
||||
+ usbc_hs: endpoint {
|
||||
+ remote-endpoint = <&usb2phy0_typec_hs>;
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
index 59ac178881..e5ab58cbc0 100644
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3566-pinenote.dtsi
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include <dt-bindings/pinctrl/rockchip.h>
|
||||
#include <dt-bindings/suspend/rockchip-rk3568.h>
|
||||
+#include <dt-bindings/usb/pd.h>
|
||||
|
||||
#include "rk3566.dtsi"
|
||||
|
||||
@@ -611,7 +612,7 @@ wusb3801: tcpc@60 {
|
||||
interrupts = <RK_PA4 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-0 = <&tcpc_int_l>;
|
||||
pinctrl-names = "default";
|
||||
- status = "disabled";
|
||||
+ status = "okay";
|
||||
};
|
||||
|
||||
/* TODO: write binding */
|
89
nongnu/system/images/pinenote.scm
Normal file
89
nongnu/system/images/pinenote.scm
Normal file
|
@ -0,0 +1,89 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix 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 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (nongnu system images pinenote)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu bootloader u-boot)
|
||||
#:use-module (gnu image)
|
||||
#:use-module (gnu packages certs)
|
||||
#:use-module (gnu packages ssh)
|
||||
#:use-module (gnu packages wm)
|
||||
#:use-module (nongnu packages linux)
|
||||
#:use-module (nongnu packages firmware)
|
||||
#:use-module (nongnu packages bootloaders)
|
||||
#:use-module (guix platforms arm)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services base)
|
||||
#:use-module (gnu services desktop)
|
||||
#:use-module (gnu services sddm)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (gnu system image)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:export (pinenote-raw-image
|
||||
pinenote-image-type
|
||||
pinenote-barebones-raw-image))
|
||||
|
||||
(define pinenote-barebone-os
|
||||
(operating-system
|
||||
(host-name "viso")
|
||||
(timezone "Europe/Prague")
|
||||
(locale "en_US.utf8")
|
||||
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader u-boot-pinenote-rk3566-bootloader)
|
||||
(targets '("/dev/vda"))))
|
||||
(initrd-modules '())
|
||||
|
||||
(firmware (list pinenote-firmware))
|
||||
(kernel linux-pinenote)
|
||||
(file-systems (cons (file-system
|
||||
(device (file-system-label "my-root"))
|
||||
(mount-point "/")
|
||||
(type "ext4"))
|
||||
%base-file-systems))
|
||||
|
||||
(packages (append (list nss-certs
|
||||
openssh
|
||||
sway)
|
||||
%base-packages))
|
||||
|
||||
(services (cons (service agetty-service-type
|
||||
(agetty-configuration
|
||||
(extra-options '("-L")) ; no carrier detect
|
||||
(baud-rate "1500000")
|
||||
(term "vt100")
|
||||
(tty "ttyS2"))))
|
||||
%base-services)))
|
||||
|
||||
(define pinenote-image-type
|
||||
(image-type
|
||||
(name 'pinenote-raw)
|
||||
(constructor (cut image-with-os
|
||||
(raw-with-offset-disk-image (* 32 (expt 2 20))) ; 32MiB
|
||||
<>))))
|
||||
|
||||
(define pinenote-barebones-raw-image
|
||||
(image
|
||||
(inherit
|
||||
(os+platform->image pinenote-barebone-os aarch64-linux
|
||||
#:type pinenote-image-type))
|
||||
(name 'pinenote-barebones-raw-image)))
|
||||
|
||||
;; Return the default image.
|
||||
pinenote-barebones-raw-image
|
88
nongnu/system/images/pinephone-pro.scm
Normal file
88
nongnu/system/images/pinephone-pro.scm
Normal file
|
@ -0,0 +1,88 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix 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 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (nongnu system images pinephone-pro)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu bootloader u-boot)
|
||||
#:use-module (gnu image)
|
||||
#:use-module (nongnu packages linux)
|
||||
#:use-module (nongnu packages bootloaders)
|
||||
#:use-module (guix platforms arm)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services base)
|
||||
#:use-module (gnu services networking)
|
||||
#:use-module (gnu services ssh)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (gnu system image)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:export (quartz64-a-raw-image
|
||||
quartz64-image-type
|
||||
quartz64-barebones-raw-image))
|
||||
|
||||
(define pinephone-pro-barebone-os
|
||||
(operating-system
|
||||
(host-name "viso")
|
||||
(timezone "Europe/Paris")
|
||||
(locale "en_US.utf8")
|
||||
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader u-boot-pinephone-pro-rk3399-bootloader)
|
||||
(targets '("/dev/vda"))))
|
||||
(initrd-modules '())
|
||||
(kernel linux-pinephone-pro)
|
||||
(file-systems (append (list
|
||||
(file-system
|
||||
(device (file-system-label "root"))
|
||||
(mount-point "/")
|
||||
(type "ext4")))
|
||||
%base-file-systems))
|
||||
|
||||
(swap-devices (list (swap-space
|
||||
(target "/run/swapfile"))))
|
||||
|
||||
(services (append (list (service agetty-service-type
|
||||
(agetty-configuration
|
||||
(extra-options '("-L")) ; no carrier detect
|
||||
(baud-rate "1500000")
|
||||
(term "vt100")
|
||||
(tty "ttyS2")))
|
||||
(service dhcp-client-service-type)
|
||||
(service ntp-service-type)
|
||||
(service openssh-service-type))
|
||||
%base-services))))
|
||||
|
||||
(define pinephone-pro-image-type
|
||||
(image-type
|
||||
(name 'pinephone-pro-raw)
|
||||
(constructor (lambda (os)
|
||||
(image
|
||||
(inherit
|
||||
(raw-with-offset-disk-image (* 32 (expt 2 20)))) ; 32MiB
|
||||
(operating-system os)
|
||||
(platform aarch64-linux))))))
|
||||
|
||||
(define pinephone-pro-barebones-raw-image
|
||||
(image
|
||||
(inherit
|
||||
(os+platform->image pinephone-pro-barebone-os aarch64-linux
|
||||
#:type pinephone-pro-image-type))
|
||||
(name 'quartz-barebones-raw-image)))
|
||||
|
||||
;; Return the default image.
|
||||
pinephone-pro-barebones-raw-image
|
291
nongnu/system/images/quartz64a-desktop.scm
Normal file
291
nongnu/system/images/quartz64a-desktop.scm
Normal file
|
@ -0,0 +1,291 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2022 Petr Hodina <phodina@protonmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix 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 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (nongnu system images quartz64a-desktop)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu bootloader u-boot)
|
||||
#:use-module (gnu image)
|
||||
#:use-module (nongnu packages linux)
|
||||
#:use-module (nongnu packages bootloaders)
|
||||
#:use-module (gnu packages)
|
||||
#:use-module (gnu packages glib)
|
||||
#:use-module (gnu packages compression)
|
||||
#:use-module (gnu packages certs)
|
||||
#:use-module (gnu packages gnome)
|
||||
#:use-module (gnu packages vim)
|
||||
#:use-module (gnu packages ssh)
|
||||
#:use-module (gnu packages bison)
|
||||
#:use-module (gnu packages libffi)
|
||||
#:use-module (gnu packages xorg)
|
||||
#:use-module (gnu packages flex)
|
||||
#:use-module (gnu packages pkg-config)
|
||||
#:use-module (gnu packages python)
|
||||
#:use-module (guix platforms arm)
|
||||
#:use-module (guix download)
|
||||
#:use-module (guix packages)
|
||||
#:use-module (guix gexp)
|
||||
#:use-module (guix utils)
|
||||
#:use-module (guix build utils)
|
||||
#:use-module ((guix licenses) #:prefix license:)
|
||||
#:use-module (guix build emacs-build-system)
|
||||
#:use-module (guix build-system gnu)
|
||||
#:use-module (guix build-system meson)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services desktop)
|
||||
#:use-module (gnu services sddm)
|
||||
#:use-module (gnu services ssh)
|
||||
#:use-module (gnu services xorg)
|
||||
#:use-module (gnu services base)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu system accounts)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (gnu system image)
|
||||
#:use-module (gnu system keyboard)
|
||||
#:use-module (gnu system nss)
|
||||
#:use-module (gnu system shadow)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:use-module (srfi srfi-1) ;for the remove function
|
||||
#:export (quartz64-a-raw-image
|
||||
quartz64-image-type
|
||||
quartz64-desktop-raw-image))
|
||||
|
||||
(define (python-extension-suffix python triplet)
|
||||
"Determine the suffix for C extensions for PYTHON when compiled
|
||||
for TRIPLET."
|
||||
;; python uses strings like 'x86_64-linux-gnu' instead of
|
||||
;; 'x86_64-unknown-linux-gnu'.
|
||||
(define normalised-system
|
||||
(string-replace-substring triplet "-unknown-" "-"))
|
||||
(define major.minor (version-major+minor (package-version python)))
|
||||
(define majorminor (string-delete #\. major.minor))
|
||||
(string-append
|
||||
;; If guix' python package used "--with-pydebug", a #\d would
|
||||
;; need to be added, likewise "--with-pymalloc" and "--with-wide-unicode"
|
||||
;; would require a #\m and #\u, see cpython's configure.ac.
|
||||
".cpython-" majorminor "-" normalised-system
|
||||
(if (target-mingw? triplet)
|
||||
".dll"
|
||||
".so")))
|
||||
|
||||
(define (correct-library-name-phase python name)
|
||||
"Return a G-exp evaluating to a phase renaming the python extension NAME
|
||||
from what Meson thinks its name should be to what python expects its name
|
||||
to be. NAME must not include the platform-specific suffix. This can only
|
||||
be used when cross-compiling."
|
||||
#~(lambda _
|
||||
(define name #$name)
|
||||
(define native-suffix
|
||||
#$(python-extension-suffix python
|
||||
(nix-system->gnu-triplet (%current-system))))
|
||||
(define target-suffix
|
||||
#$(python-extension-suffix python (%current-target-system)))
|
||||
(define native-name
|
||||
(string-append name native-suffix))
|
||||
(define target-name
|
||||
(string-append name target-suffix))
|
||||
(rename-file native-name target-name)))
|
||||
|
||||
(define gobject-introspection
|
||||
(package
|
||||
(name "gobject-introspection")
|
||||
(version "1.66.1")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "mirror://gnome/sources/"
|
||||
"gobject-introspection/" (version-major+minor version)
|
||||
"/gobject-introspection-" version ".tar.xz"))
|
||||
(sha256
|
||||
(base32 "078n0q7b6z682mf4irclrksm73cyixq295mqnqifl9plwmgaai6x"))
|
||||
(patches (search-patches
|
||||
"gobject-introspection-cc.patch"
|
||||
"gobject-introspection-girepository.patch"
|
||||
"gobject-introspection-absolute-shlib-path.patch"))))
|
||||
(build-system meson-build-system)
|
||||
(arguments
|
||||
`(,@(if (%current-target-system)
|
||||
`(#:configure-flags
|
||||
'("-Dgi_cross_use_prebuilt_gi=true"
|
||||
;; Building introspection data requires running binaries
|
||||
;; for ‘host’ on ‘build’, so don't do that.
|
||||
;;
|
||||
;; TODO: it would be nice to have introspection data anyways
|
||||
;; as discussed here: https://issues.guix.gnu.org/50201#60.
|
||||
"-Dbuild_introspection_data=false"))
|
||||
'())
|
||||
#:phases
|
||||
,#~
|
||||
(modify-phases %standard-phases
|
||||
#$@(if (%current-target-system)
|
||||
;; 'typelibs' is undefined.
|
||||
`((add-after 'unpack 'set-typelibs
|
||||
(lambda _
|
||||
(substitute* "meson.build"
|
||||
; (("python3") "python")
|
||||
(("\\bsources: typelibs\\b")
|
||||
"sources: []")))))
|
||||
'())
|
||||
(add-after 'unpack 'do-not-use-/usr/bin/env
|
||||
(lambda _
|
||||
(substitute* "tools/g-ir-tool-template.in"
|
||||
(("#!@PYTHON_CMD@")
|
||||
(string-append "#!" #$(this-package-input "python")
|
||||
"/bin/python3")))))
|
||||
#$@(if (%current-target-system)
|
||||
;; Meson gives python extensions an incorrect name, see
|
||||
;; <https://github.com/mesonbuild/meson/issues/7049>.
|
||||
#~((add-after 'install 'rename-library
|
||||
#$(correct-library-name-phase
|
||||
(this-package-input "python")
|
||||
#~(string-append #$output
|
||||
"/lib/gobject-introspection/giscanner"
|
||||
"/_giscanner"))))
|
||||
#~()))))
|
||||
(native-inputs
|
||||
(list `(,glib "bin")
|
||||
pkg-config
|
||||
bison
|
||||
flex))
|
||||
(inputs
|
||||
(list ;,@(if (%current-target-system)
|
||||
python
|
||||
bison
|
||||
flex
|
||||
zlib))
|
||||
(propagated-inputs
|
||||
(list glib
|
||||
;; In practice, GIR users will need libffi when using
|
||||
;; gobject-introspection.
|
||||
libffi))
|
||||
(native-search-paths
|
||||
(list
|
||||
(search-path-specification
|
||||
(variable "GI_TYPELIB_PATH")
|
||||
(files '("lib/girepository-1.0")))))
|
||||
(search-paths native-search-paths)
|
||||
(synopsis "GObject introspection tools and libraries")
|
||||
(description "GObject introspection is a middleware layer between
|
||||
C libraries (using GObject) and language bindings. The C library can be scanned
|
||||
at compile time and generate metadata files, in addition to the actual native
|
||||
C library. Then language bindings can read this metadata and automatically
|
||||
provide bindings to call into the C library.")
|
||||
(home-page "https://wiki.gnome.org/Projects/GObjectIntrospection")
|
||||
(license
|
||||
(list
|
||||
;; For library.
|
||||
license:lgpl2.0+
|
||||
;; For tools.
|
||||
license:gpl2+))))
|
||||
;; Fails to cross-compile - rewrite using gexp
|
||||
(define-public slock
|
||||
(package
|
||||
(name "slock")
|
||||
(version "1.4")
|
||||
(source (origin
|
||||
(method url-fetch)
|
||||
(uri (string-append "https://dl.suckless.org/tools/slock-"
|
||||
version ".tar.gz"))
|
||||
(sha256
|
||||
(base32
|
||||
"0sif752303dg33f14k6pgwq2jp1hjyhqv6x4sy3sj281qvdljf5m"))))
|
||||
(build-system gnu-build-system)
|
||||
(arguments
|
||||
(list #:tests? #f ; no tests
|
||||
#:make-flags
|
||||
#~(list (string-append "CC=" #$(cc-for-target))
|
||||
(string-append "PREFIX=" #$output))
|
||||
#:phases #~(modify-phases %standard-phases (delete 'configure))))
|
||||
(inputs
|
||||
(list libx11 libxext libxinerama libxrandr))
|
||||
(home-page "https://tools.suckless.org/slock/")
|
||||
(synopsis "Simple X session lock")
|
||||
(description
|
||||
"Simple X session lock with trivial feedback on password entry.")
|
||||
(license license:x11)))
|
||||
|
||||
(define quartz64a-desktop-os
|
||||
(operating-system
|
||||
(host-name "quartz64a")
|
||||
(timezone "Europe/Prague")
|
||||
(locale "en_US.utf8")
|
||||
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader u-boot-quartz64a-rk3566-bootloader)
|
||||
(targets '("/dev/vda"))))
|
||||
(initrd-modules '())
|
||||
(kernel linux-quartz64)
|
||||
(file-systems (append (list
|
||||
(file-system
|
||||
(device (file-system-label "EFI"))
|
||||
(mount-point "/boot/efi")
|
||||
(type "vfat"))
|
||||
(file-system
|
||||
(device (file-system-label "root"))
|
||||
(mount-point "/")
|
||||
(type "ext4")))
|
||||
%base-file-systems))
|
||||
|
||||
(swap-devices (list (swap-space
|
||||
(target "/run/swapfile"))))
|
||||
|
||||
(users (cons* (user-account
|
||||
(name "pine")
|
||||
(group "users")
|
||||
(supplementary-groups '("wheel" "netdev" "audio" "video"))
|
||||
(password (crypt "quartz64" "$6$abc"))
|
||||
(home-directory "/home/pine"))
|
||||
%base-user-accounts))
|
||||
|
||||
;; Add GNOME desktop
|
||||
(services
|
||||
(append (list (service mate-desktop-service-type)
|
||||
(service xfce-desktop-service-type)
|
||||
(service openssh-service-type)
|
||||
(service agetty-service-type
|
||||
(agetty-configuration
|
||||
(extra-options '("-L")) ; no carrier detect
|
||||
(baud-rate "1500000")
|
||||
(term "vt100")
|
||||
(tty "ttyS2"))))
|
||||
%desktop-services))
|
||||
|
||||
(packages (cons* nss-certs
|
||||
openssh
|
||||
gvfs
|
||||
%base-packages))
|
||||
|
||||
(name-service-switch %mdns-host-lookup-nss)))
|
||||
|
||||
(define quartz64-image-type
|
||||
(image-type
|
||||
(name 'quartz-raw)
|
||||
(constructor (lambda (os)
|
||||
(image
|
||||
(inherit
|
||||
(raw-with-offset-disk-image (* 32 (expt 2 20)))) ; 32MiB
|
||||
(operating-system os)
|
||||
(platform aarch64-linux))))))
|
||||
|
||||
(define quartz64-desktop-raw-image
|
||||
(image
|
||||
(inherit
|
||||
(os+platform->image quartz64a-desktop-os aarch64-linux
|
||||
#:type quartz64-image-type))
|
||||
(name 'quartz-desktop-raw-image)))
|
||||
|
||||
;; Return the default image.
|
||||
quartz64-desktop-raw-image
|
110
nongnu/system/images/quartz64a.scm
Normal file
110
nongnu/system/images/quartz64a.scm
Normal file
|
@ -0,0 +1,110 @@
|
|||
;;; GNU Guix --- Functional package management for GNU
|
||||
;;; Copyright © 2020 Mathieu Othacehe <m.othacehe@gmail.com>
|
||||
;;;
|
||||
;;; This file is part of GNU Guix.
|
||||
;;;
|
||||
;;; GNU Guix 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 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (nongnu system images quartz64a)
|
||||
#:use-module (gnu bootloader)
|
||||
#:use-module (gnu bootloader u-boot)
|
||||
#:use-module (gnu image)
|
||||
#:use-module (nongnu packages linux)
|
||||
#:use-module (nongnu packages bootloaders)
|
||||
#:use-module (guix platforms arm)
|
||||
#:use-module (gnu packages certs)
|
||||
#:use-module (gnu packages ssh)
|
||||
#:use-module (gnu services)
|
||||
#:use-module (gnu services avahi)
|
||||
#:use-module (gnu services base)
|
||||
#:use-module (gnu services desktop)
|
||||
#:use-module (gnu services networking)
|
||||
#:use-module (gnu services ssh)
|
||||
#:use-module (gnu system)
|
||||
#:use-module (gnu system accounts)
|
||||
#:use-module (gnu system file-systems)
|
||||
#:use-module (gnu system image)
|
||||
#:use-module (gnu system nss)
|
||||
#:use-module (gnu system shadow)
|
||||
#:use-module (srfi srfi-26)
|
||||
#:export (quartz64-a-raw-image
|
||||
quartz64-image-type
|
||||
quartz64-barebones-raw-image))
|
||||
|
||||
(define quartz64-a-barebone-os
|
||||
(operating-system
|
||||
(host-name "viso")
|
||||
(timezone "Europe/Prague")
|
||||
(locale "en_US.utf8")
|
||||
|
||||
(bootloader (bootloader-configuration
|
||||
(bootloader u-boot-quartz64a-rk3566-bootloader)
|
||||
(targets '("/dev/vda"))))
|
||||
(initrd-modules '())
|
||||
(kernel linux-quartz64)
|
||||
(file-systems (append (list
|
||||
(file-system
|
||||
(device (file-system-label "root"))
|
||||
(mount-point "/")
|
||||
(type "ext4")))
|
||||
%base-file-systems))
|
||||
|
||||
(swap-devices (list (swap-space
|
||||
(target "/run/swapfile"))))
|
||||
|
||||
(users (cons* (user-account
|
||||
(name "pine")
|
||||
(group "users")
|
||||
(supplementary-groups '("wheel" "netdev" "audio" "video"))
|
||||
(password (crypt "quartz64" "$6$abc"))
|
||||
(home-directory "/home/pine"))
|
||||
%base-user-accounts))
|
||||
|
||||
(services (append (list (service agetty-service-type
|
||||
(agetty-configuration
|
||||
(extra-options '("-L")) ; no carrier detect
|
||||
(baud-rate "1500000")
|
||||
(term "vt100")
|
||||
(tty "ttyS2")))
|
||||
(service avahi-service-type)
|
||||
(service dhcp-client-service-type)
|
||||
(service ntp-service-type)
|
||||
(service openssh-service-type))
|
||||
%base-services))
|
||||
|
||||
(packages (cons* nss-certs
|
||||
openssh
|
||||
%base-packages))
|
||||
|
||||
(name-service-switch %mdns-host-lookup-nss)))
|
||||
|
||||
(define quartz64-image-type
|
||||
(image-type
|
||||
(name 'quartz-raw)
|
||||
(constructor (lambda (os)
|
||||
(image
|
||||
(inherit
|
||||
(raw-with-offset-disk-image (* 32 (expt 2 20)))) ; 32MiB
|
||||
(operating-system os)
|
||||
(platform aarch64-linux))))))
|
||||
|
||||
(define quartz64-barebones-raw-image
|
||||
(image
|
||||
(inherit
|
||||
(os+platform->image quartz64-a-barebone-os aarch64-linux
|
||||
#:type quartz64-image-type))
|
||||
(name 'quartz-barebones-raw-image)))
|
||||
|
||||
;; Return the default image.
|
||||
quartz64-barebones-raw-image
|
Loading…
Reference in New Issue
Block a user