diff --git a/hosts/by-name/moby/bootloader.nix b/hosts/by-name/moby/bootloader.nix deleted file mode 100644 index 14a9c8d0..00000000 --- a/hosts/by-name/moby/bootloader.nix +++ /dev/null @@ -1,22 +0,0 @@ -# tow-boot: -# docs (pinephone specific): -# LED and button behavior is defined here: -# - hold VOLDOWN: enter recovery mode -# - LED will turn aqua instead of yellow -# - recovery mode would ordinarily allow a selection of entries, but for pinephone i guess it doesn't do anything? -# - hold VOLUP: force it to load the OS from eMMC? -# - LED will turn blue instead of yellow -# boot LEDs: -# - yellow = entered tow-boot -# - 10 red flashes => poweroff means tow-boot couldn't boot into the next stage (i.e. distroboot) -# - distroboot: ) -{ config, pkgs, ... }: -{ - # we need space in the GPT header to place tow-boot. - # only actually need 1 MB, but better to over-allocate than under-allocate - sane.image.extraGPTPadding = 16 * 1024 * 1024; - sane.image.firstPartGap = 0; - sane.image.installBootloader = '' - dd if=${pkgs.tow-boot-pinephone}/Tow-Boot.noenv.bin of=$out/nixos.img bs=1024 seek=8 conv=notrunc - ''; -} diff --git a/hosts/by-name/moby/default.nix b/hosts/by-name/moby/default.nix index cd939736..eba1c85c 100644 --- a/hosts/by-name/moby/default.nix +++ b/hosts/by-name/moby/default.nix @@ -9,13 +9,12 @@ { config, pkgs, lib, ... }: { imports = [ - ./bootloader.nix ./fs.nix ./gps.nix - ./kernel.nix ./polyfill.nix ]; + sane.hal.pine64.enable = true; sane.roles.client = true; sane.roles.handheld = true; sane.programs.zsh.config.showDeadlines = false; # unlikely to act on them when in shell @@ -76,49 +75,6 @@ # /boot space is at a premium. default was 20. # even 10 can be too much boot.loader.generic-extlinux-compatible.configurationLimit = 8; - # mobile.bootloader.enable = false; - # mobile.boot.stage-1.enable = false; - # boot.initrd.systemd.enable = false; - # boot.initrd.services.swraid.enable = false; # attempt to fix dm_mod stuff - - # hardware.firmware makes the referenced files visible to the kernel, for whenever a driver explicitly asks for them. - # these files are visible from userspace by following `/sys/module/firmware_class/parameters/path` - # - # mobile-nixos' /lib/firmware includes: - # rtl_bt (bluetooth) - # anx7688-fw.bin (USB-C chip: power negotiation, HDMI/dock) - # ov5640_af.bin (camera module) - # hardware.firmware = [ config.mobile.device.firmware ]; - # hardware.firmware = [ pkgs.rtl8723cs-firmware ]; - hardware.firmware = [ - (pkgs.linux-firmware-megous.override { - # rtl_bt = false probably means no bluetooth connectivity. - # N.B.: DON'T RE-ENABLE without first confirming that wake-on-lan works during suspend (rtcwake). - # it seems the rtl_bt stuff ("bluetooth coexist") might make wake-on-LAN radically more flaky. - rtl_bt = false; - }) - ]; system.stateVersion = "21.11"; - - # defined: https://www.freedesktop.org/software/systemd/man/machine-info.html - # XXX colin: not sure which, if any, software makes use of this - environment.etc."machine-info".text = '' - CHASSIS="handset" - ''; - - # enable rotation sensor - # hardware.sensor.iio.enable = true; - - services.udev.extraRules = let - chmod = "${pkgs.coreutils}/bin/chmod"; - chown = "${pkgs.coreutils}/bin/chown"; - in '' - # make Pinephone flashlight writable by user. - # taken from postmarketOS: - SUBSYSTEM=="leds", DEVPATH=="*/*:flash", RUN+="${chmod} g+w /sys%p/brightness /sys%p/flash_strobe", RUN+="${chown} :video /sys%p/brightness /sys%p/flash_strobe" - - # make Pinephone front LEDs writable by user. - SUBSYSTEM=="leds", DEVPATH=="*/*:indicator", RUN+="${chmod} g+w /sys%p/brightness", RUN+="${chown} :video /sys%p/brightness" - ''; } diff --git a/hosts/by-name/moby/kernel.nix b/hosts/by-name/moby/kernel.nix deleted file mode 100644 index e8454382..00000000 --- a/hosts/by-name/moby/kernel.nix +++ /dev/null @@ -1,271 +0,0 @@ -{ pkgs, ... }: -let - dmesg = "${pkgs.util-linux}/bin/dmesg"; - grep = "${pkgs.gnugrep}/bin/grep"; - modprobe = "${pkgs.kmod}/bin/modprobe"; - ensureHWReady = '' - # common boot failure: - # blank screen (no backlight even), with the following log: - # ```syslog - # sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get the HDMI PHY - # ... - # sun4i-drm display-engine: Couldn't bind all pipelines components - # ... - # sun8i-dw-hdmi: probe of 1ee0000.hdmi failed with error -17 - # ``` - # - # in particular, that `probe ... failed` occurs *only* on failed boots - # (the other messages might sometimes occur even on successful runs?) - # - # reloading the sun8i hdmi driver usually gets the screen on, showing boot text. - # then restarting display-manager.service gets us to the login. - # - # NB: the above log is default level. though less specific, there's a `err` level message that also signals this: - # sun4i-drm display-engine: failed to bind 1ee0000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -17 - # NB: this is the most common, but not the only, failure mode for `display-manager`. - # another error seems characterized by these dmesg logs, in which reprobing sun8i_drm_hdmi does not fix: - # ```syslog - # sun6i-mipi-dsi 1ca0000.dsi: Couldn't get the MIPI D-PHY - # sun4i-drm display-engine: Couldn't bind all pipelines components - # sun6i-mipi-dsi 1ca0000.dsi: Couldn't register our component - # ``` - - if (${dmesg} --kernel --level err --color=never --notime | ${grep} -q 'sun4i-drm display-engine: failed to bind 1ee0000.hdmi') - then - echo "reprobing sun8i_drm_hdmi" - # if a command here fails it errors the whole service, so prefer to log instead - ${modprobe} -r sun8i_drm_hdmi || echo "failed to unload sun8i_drm_hdmi" - ${modprobe} sun8i_drm_hdmi || echo "failed to load sub8i_drm_hdmi" - fi - ''; -in -{ - # kernel compatibility (2024/05/22: 03dab630) - # - linux-megous: boots to ssh, desktop - # - camera apps: megapixels (no cameras found), snapshot (no cameras found) - # - linux-postmarketos: boots to ssh. desktop ONLY if "anx7688" is in the initrd.availableKernelModules. - # - camera apps: megapixels (both rear and front cameras work), `cam -l` (finds only the rear camera), snapshot (no cameras found) - # - linux-megous.override { withMegiPinephoneConfig = true; }: NO SSH, NO SIGNS OF LIFE - # - linux-megous.override { withFullConfig = false; }: boots to ssh, no desktop - # - boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-postmarketos.override { - withModemPower = true; - }); - # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous; - # boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override { - # withFullConfig = false; - # }); - # boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override { - # withMegiPinephoneConfig = true; #< N.B.: does not boot as of 2024/05/22! - # }); - # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-manjaro; - # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_latest; - - # nixpkgs.hostPlatform.linux-kernel becomes stdenv.hostPlatform.linux-kernel - nixpkgs.hostPlatform.linux-kernel = { - # defaults: - name = "aarch64-multiplatform"; - # baseConfig: defaults to "defconfig"; - # baseConfig = "pinephone_defconfig"; #< N.B.: ignored by `pkgs.linux-megous` - DTB = true; #< DTB: compile device tree blobs - # autoModules (default: true): for config options not manually specified, answer `m` to anything which supports it. - # - this effectively builds EVERY MODULE SUPPORTED. - autoModules = true; #< N.B.: ignored by `pkgs.linux-megous` - # preferBuiltin (default: false; true for rpi): for config options which default to `Y` upstream, build them as `Y` (overriding `autoModules`) - # preferBuiltin = false; - - # build a compressed kernel image: without this i run out of /boot space in < 10 generations - # target = "Image"; # <-- default - target = "Image.gz"; # <-- compress the kernel image - # target = "zImage"; # <-- confuses other parts of nixos :-( - }; - - # boot.initrd.kernelModules = [ - # "drm" #< force drm to be plugged - # ]; - boot.initrd.availableKernelModules = [ - # see - # - they include sun6i_mipi_dsi sun4i_drm pwm_sun4i sun8i_mixer anx7688 gpio_vibra pinephone_keyboard - "anx7688" #< required for display initialization and functional cameras - # full list of modules active post-boot with the linux-megous kernel + autoModules=true: - # - `lsmod | sort | cut -d ' ' -f 1` - # "8723cs" - # "axp20x_adc" #< NOT FOUND in megous-no-autoModules - # "axp20x_battery" - # "axp20x_pek" - # "axp20x_usb_power" - # "backlight" - # "blake2b_generic" - # "bluetooth" - # "bridge" - # "btbcm" - # "btqca" - # "btrfs" - # "btrtl" - # "cec" - # "cfg80211" - # "chacha_neon" - # "crc_ccitt" - # "crct10dif_ce" - # "crypto_engine" - # "display_connector" #< NOT FOUND in pmos - # "drm" - # "drm_display_helper" - # "drm_dma_helper" - # "drm_kms_helper" - # "drm_shmem_helper" - # "dw_hdmi" - # "dw_hdmi_cec" #< NOT FOUND in pmos - # "dw_hdmi_i2s_audio" - # "ecc" - # "ecdh_generic" - # "fuse" - # "gc2145" #< NOT FOUND in megous-no-autoModules - # "goodix_ts" - # "gpio_vibra" #< NOT FOUND in megous-no-autoModules - # "gpu_sched" - # "hci_uart" - # "i2c_gpio" - # "inv_mpu6050" #< NOT FOUND in megous-no-autoModules - # "inv_mpu6050_i2c" #< NOT FOUND in megous-no-autoModules - # "inv_sensors_timestamp" #< NOT FOUND in megous-no-autoModules - # "ip6t_rpfilter" - # "ip6_udp_tunnel" - # "ip_set" - # "ip_set_hash_ipport" - # "ip_tables" - # "ipt_rpfilter" - # "joydev" - # "led_class_flash" #< NOT FOUND in megous-no-autoModules - # "leds_sgm3140" #< NOT FOUND in megous-no-autoModules - # "ledtrig_pattern" #< NOT FOUND in megous-no-autoModules - # "libarc4" - # "libchacha" - # "libchacha20poly1305" - # "libcrc32c" - # "libcurve25519_generic" - # "lima" - # "llc" - # "mac80211" - # "macvlan" - # "mc" - # "modem_power" - # "mousedev" - # "nf_conntrack" - # "nf_defrag_ipv4" - # "nf_defrag_ipv6" - # "nf_log_syslog" - # "nf_nat" - # "nfnetlink" - # "nf_tables" - # "nft_chain_nat" - # "nft_compat" - # "nls_cp437" - # "nls_iso8859_1" - # "nvmem_reboot_mode" - # "ov5640" - # "panel_sitronix_st7703" - # "phy_sun6i_mipi_dphy" - # "pinctrl_axp209" #< NOT FOUND in pmos - # "pinephone_keyboard" #< NOT FOUND in megous-no-autoModules - # "poly1305_neon" - # "polyval_ce" - # "polyval_generic" - # "ppkb_manager" #< NOT FOUND in megous-no-autoModules - # "pwm_bl" - # "pwm_sun4i" - # "qrtr" - # "raid6_pq" - # "rfkill" - # "rtw88_8703b" - # "rtw88_8723cs" - # "rtw88_8723x" - # "rtw88_core" - # "rtw88_sdio" - # "sch_fq_codel" - # "sm4" - # "snd_soc_bt_sco" - # "snd_soc_ec25" #< NOT FOUND in megous-no-autoModules - # "snd_soc_hdmi_codec" - # "snd_soc_simple_amplifier" - # "snd_soc_simple_card" - # "snd_soc_simple_card_utils" - # "stk3310" #< NOT FOUND in megous-no-autoModules - # "st_magn" - # "st_magn_i2c" - # "st_magn_spi" #< NOT FOUND in pmos - # "stp" - # "st_sensors" - # "st_sensors_i2c" - # "st_sensors_spi" #< NOT FOUND in pmos - # "sun4i_drm" - # "sun4i_i2s" - # "sun4i_lradc_keys" #< NOT FOUND in megous-no-autoModules - # "sun4i_tcon" - # "sun50i_codec_analog" - # "sun6i_csi" - # "sun6i_dma" - # "sun6i_mipi_dsi" - # "sun8i_a33_mbus" #< NOT FOUND in megous-no-autoModules - # "sun8i_adda_pr_regmap" - # "sun8i_ce" #< NOT FOUND in pmos - # "sun8i_codec" #< NOT FOUND in megous-no-autoModules - # "sun8i_di" #< NOT FOUND in megous-no-autoModules - # "sun8i_drm_hdmi" - # "sun8i_mixer" - # "sun8i_rotate" #< NOT FOUND in megous-no-autoModules - # "sun8i_tcon_top" - # "sun9i_hdmi_audio" #< NOT FOUND in megous-no-autoModules - # "sunxi_wdt" #< NOT FOUND in pmos - # "tap" - # "typec" #< NOT FOUND in pmos - # "udp_tunnel" - # "uio" #< NOT FOUND in pmos - # "uio_pdrv_genirq" - # "v4l2_async" - # "v4l2_cci" #< NOT FOUND in pmos - # "v4l2_flash_led_class" #< NOT FOUND in megous-no-autoModules - # "v4l2_fwnode" - # "v4l2_mem2mem" - # "videobuf2_common" - # "videobuf2_dma_contig" - # "videobuf2_memops" - # "videobuf2_v4l2" - # "videodev" - # "wireguard" - # "xor" - # "x_tables" - # "xt_conntrack" - # "xt_LOG" - # "xt_nat" - # "xt_pkttype" - # "xt_set" - # "xt_tcpudp" - # "zram" - ]; - - # disable proximity sensor. - # the filtering/calibration is bad that it causes the screen to go fully dark at times. - # boot.blacklistedKernelModules = [ "stk3310" ]; - - boot.kernelParams = [ - # without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory` - # this is because they can't allocate enough video ram. - # see related nixpkgs issue: - # TODO(2023/12/03): remove once mesa 23.3.1 lands: - # - # the default CMA seems to be 32M. - # i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep (phosh): maybe a memory leak? - # bumped to 512M on 2023/01 - # bumped to 1536M on 2024/05 - # `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this. - # kernel param mentioned here: - # i think cma mem isn't exclusive -- it can be used as ordinary `malloc`, still. i heard someone suggest the OS default should just be 50% memory to CMA. - "cma=1536M" - # 2023/10/20: potential fix for the lima (GPU) timeout bugs: - # - - "lima.sched_timeout_ms=2000" - ]; - - systemd.services.unl0kr.preStart = ensureHWReady; -} diff --git a/hosts/modules/hal/default.nix b/hosts/modules/hal/default.nix index d68e3691..c846ad58 100644 --- a/hosts/modules/hal/default.nix +++ b/hosts/modules/hal/default.nix @@ -1,6 +1,7 @@ { ... }: { imports = [ + ./pine64.nix ./x86_64.nix ]; } diff --git a/hosts/modules/hal/pine64.nix b/hosts/modules/hal/pine64.nix new file mode 100644 index 00000000..4616bd87 --- /dev/null +++ b/hosts/modules/hal/pine64.nix @@ -0,0 +1,338 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.sane.hal.pine64; +in +{ + options = { + sane.hal.pine64.enable = lib.mkEnableOption "pine64-specific hardware support"; + }; + + config = lib.mkIf cfg.enable { + # kernel compatibility (2024/05/22: 03dab630) + # - linux-megous: boots to ssh, desktop + # - camera apps: megapixels (no cameras found), snapshot (no cameras found) + # - linux-postmarketos: boots to ssh. desktop ONLY if "anx7688" is in the initrd.availableKernelModules. + # - camera apps: megapixels (both rear and front cameras work), `cam -l` (finds only the rear camera), snapshot (no cameras found) + # - linux-megous.override { withMegiPinephoneConfig = true; }: NO SSH, NO SIGNS OF LIFE + # - linux-megous.override { withFullConfig = false; }: boots to ssh, no desktop + # + boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-postmarketos.override { + withModemPower = true; + }); + # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-megous; + # boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override { + # withFullConfig = false; + # }); + # boot.kernelPackages = pkgs.linuxPackagesFor (pkgs.linux-megous.override { + # withMegiPinephoneConfig = true; #< N.B.: does not boot as of 2024/05/22! + # }); + # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux-manjaro; + # boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_latest; + + # nixpkgs.hostPlatform.linux-kernel becomes stdenv.hostPlatform.linux-kernel + nixpkgs.hostPlatform.linux-kernel = { + # defaults: + name = "aarch64-multiplatform"; + # baseConfig: defaults to "defconfig"; + # baseConfig = "pinephone_defconfig"; #< N.B.: ignored by `pkgs.linux-megous` + DTB = true; #< DTB: compile device tree blobs + # autoModules (default: true): for config options not manually specified, answer `m` to anything which supports it. + # - this effectively builds EVERY MODULE SUPPORTED. + autoModules = true; #< N.B.: ignored by `pkgs.linux-megous` + # preferBuiltin (default: false; true for rpi): for config options which default to `Y` upstream, build them as `Y` (overriding `autoModules`) + # preferBuiltin = false; + + # build a compressed kernel image: without this i run out of /boot space in < 10 generations + # target = "Image"; # <-- default + target = "Image.gz"; # <-- compress the kernel image + # target = "zImage"; # <-- confuses other parts of nixos :-( + }; + + # boot.initrd.kernelModules = [ + # "drm" #< force drm to be plugged + # ]; + boot.initrd.availableKernelModules = [ + # see + # - they include sun6i_mipi_dsi sun4i_drm pwm_sun4i sun8i_mixer anx7688 gpio_vibra pinephone_keyboard + "anx7688" #< required for display initialization and functional cameras + # full list of modules active post-boot with the linux-megous kernel + autoModules=true: + # - `lsmod | sort | cut -d ' ' -f 1` + # "8723cs" + # "axp20x_adc" #< NOT FOUND in megous-no-autoModules + # "axp20x_battery" + # "axp20x_pek" + # "axp20x_usb_power" + # "backlight" + # "blake2b_generic" + # "bluetooth" + # "bridge" + # "btbcm" + # "btqca" + # "btrfs" + # "btrtl" + # "cec" + # "cfg80211" + # "chacha_neon" + # "crc_ccitt" + # "crct10dif_ce" + # "crypto_engine" + # "display_connector" #< NOT FOUND in pmos + # "drm" + # "drm_display_helper" + # "drm_dma_helper" + # "drm_kms_helper" + # "drm_shmem_helper" + # "dw_hdmi" + # "dw_hdmi_cec" #< NOT FOUND in pmos + # "dw_hdmi_i2s_audio" + # "ecc" + # "ecdh_generic" + # "fuse" + # "gc2145" #< NOT FOUND in megous-no-autoModules + # "goodix_ts" + # "gpio_vibra" #< NOT FOUND in megous-no-autoModules + # "gpu_sched" + # "hci_uart" + # "i2c_gpio" + # "inv_mpu6050" #< NOT FOUND in megous-no-autoModules + # "inv_mpu6050_i2c" #< NOT FOUND in megous-no-autoModules + # "inv_sensors_timestamp" #< NOT FOUND in megous-no-autoModules + # "ip6t_rpfilter" + # "ip6_udp_tunnel" + # "ip_set" + # "ip_set_hash_ipport" + # "ip_tables" + # "ipt_rpfilter" + # "joydev" + # "led_class_flash" #< NOT FOUND in megous-no-autoModules + # "leds_sgm3140" #< NOT FOUND in megous-no-autoModules + # "ledtrig_pattern" #< NOT FOUND in megous-no-autoModules + # "libarc4" + # "libchacha" + # "libchacha20poly1305" + # "libcrc32c" + # "libcurve25519_generic" + # "lima" + # "llc" + # "mac80211" + # "macvlan" + # "mc" + # "modem_power" + # "mousedev" + # "nf_conntrack" + # "nf_defrag_ipv4" + # "nf_defrag_ipv6" + # "nf_log_syslog" + # "nf_nat" + # "nfnetlink" + # "nf_tables" + # "nft_chain_nat" + # "nft_compat" + # "nls_cp437" + # "nls_iso8859_1" + # "nvmem_reboot_mode" + # "ov5640" + # "panel_sitronix_st7703" + # "phy_sun6i_mipi_dphy" + # "pinctrl_axp209" #< NOT FOUND in pmos + # "pinephone_keyboard" #< NOT FOUND in megous-no-autoModules + # "poly1305_neon" + # "polyval_ce" + # "polyval_generic" + # "ppkb_manager" #< NOT FOUND in megous-no-autoModules + # "pwm_bl" + # "pwm_sun4i" + # "qrtr" + # "raid6_pq" + # "rfkill" + # "rtw88_8703b" + # "rtw88_8723cs" + # "rtw88_8723x" + # "rtw88_core" + # "rtw88_sdio" + # "sch_fq_codel" + # "sm4" + # "snd_soc_bt_sco" + # "snd_soc_ec25" #< NOT FOUND in megous-no-autoModules + # "snd_soc_hdmi_codec" + # "snd_soc_simple_amplifier" + # "snd_soc_simple_card" + # "snd_soc_simple_card_utils" + # "stk3310" #< NOT FOUND in megous-no-autoModules + # "st_magn" + # "st_magn_i2c" + # "st_magn_spi" #< NOT FOUND in pmos + # "stp" + # "st_sensors" + # "st_sensors_i2c" + # "st_sensors_spi" #< NOT FOUND in pmos + # "sun4i_drm" + # "sun4i_i2s" + # "sun4i_lradc_keys" #< NOT FOUND in megous-no-autoModules + # "sun4i_tcon" + # "sun50i_codec_analog" + # "sun6i_csi" + # "sun6i_dma" + # "sun6i_mipi_dsi" + # "sun8i_a33_mbus" #< NOT FOUND in megous-no-autoModules + # "sun8i_adda_pr_regmap" + # "sun8i_ce" #< NOT FOUND in pmos + # "sun8i_codec" #< NOT FOUND in megous-no-autoModules + # "sun8i_di" #< NOT FOUND in megous-no-autoModules + # "sun8i_drm_hdmi" + # "sun8i_mixer" + # "sun8i_rotate" #< NOT FOUND in megous-no-autoModules + # "sun8i_tcon_top" + # "sun9i_hdmi_audio" #< NOT FOUND in megous-no-autoModules + # "sunxi_wdt" #< NOT FOUND in pmos + # "tap" + # "typec" #< NOT FOUND in pmos + # "udp_tunnel" + # "uio" #< NOT FOUND in pmos + # "uio_pdrv_genirq" + # "v4l2_async" + # "v4l2_cci" #< NOT FOUND in pmos + # "v4l2_flash_led_class" #< NOT FOUND in megous-no-autoModules + # "v4l2_fwnode" + # "v4l2_mem2mem" + # "videobuf2_common" + # "videobuf2_dma_contig" + # "videobuf2_memops" + # "videobuf2_v4l2" + # "videodev" + # "wireguard" + # "xor" + # "x_tables" + # "xt_conntrack" + # "xt_LOG" + # "xt_nat" + # "xt_pkttype" + # "xt_set" + # "xt_tcpudp" + # "zram" + ]; + + # disable proximity sensor. + # the filtering/calibration is bad that it causes the screen to go fully dark at times. + # boot.blacklistedKernelModules = [ "stk3310" ]; + + boot.kernelParams = [ + # without this some GUI apps fail: `DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory` + # this is because they can't allocate enough video ram. + # see related nixpkgs issue: + # TODO(2023/12/03): remove once mesa 23.3.1 lands: + # + # the default CMA seems to be 32M. + # i was running fine with 256MB from 2022/07-ish through 2022/12-ish, but then the phone quit reliably coming back from sleep (phosh): maybe a memory leak? + # bumped to 512M on 2023/01 + # bumped to 1536M on 2024/05 + # `cat /proc/meminfo` to see CmaTotal/CmaFree if interested in tuning this. + # kernel param mentioned here: + # i think cma mem isn't exclusive -- it can be used as ordinary `malloc`, still. i heard someone suggest the OS default should just be 50% memory to CMA. + "cma=1536M" + # 2023/10/20: potential fix for the lima (GPU) timeout bugs: + # - + "lima.sched_timeout_ms=2000" + ]; + + # defined: https://www.freedesktop.org/software/systemd/man/machine-info.html + # XXX colin: diabled until/unless it's actually needed. + # environment.etc."machine-info".text = '' + # CHASSIS="handset" + # ''; + + # hardware.firmware makes the referenced files visible to the kernel, for whenever a driver explicitly asks for them. + # these files are visible from userspace by following `/sys/module/firmware_class/parameters/path` + # + # mobile-nixos' /lib/firmware includes: + # rtl_bt (bluetooth) + # anx7688-fw.bin (USB-C chip: power negotiation, HDMI/dock) + # ov5640_af.bin (camera module) + # hardware.firmware = [ config.mobile.device.firmware ]; + # hardware.firmware = [ pkgs.rtl8723cs-firmware ]; + hardware.firmware = [ + (pkgs.linux-firmware-megous.override { + # rtl_bt = false probably means no bluetooth connectivity. + # N.B.: DON'T RE-ENABLE without first confirming that wake-on-lan works during suspend (rtcwake). + # it seems the rtl_bt stuff ("bluetooth coexist") might make wake-on-LAN radically more flaky. + rtl_bt = false; + }) + ]; + + # enable rotation sensor + # hardware.sensor.iio.enable = true; + + ## TOW-BOOT: + # docs (pinephone specific): + # LED and button behavior is defined here: + # - hold VOLDOWN: enter recovery mode + # - LED will turn aqua instead of yellow + # - recovery mode would ordinarily allow a selection of entries, but for pinephone i guess it doesn't do anything? + # - hold VOLUP: force it to load the OS from eMMC? + # - LED will turn blue instead of yellow + # boot LEDs: + # - yellow = entered tow-boot + # - 10 red flashes => poweroff means tow-boot couldn't boot into the next stage (i.e. distroboot) + # - distroboot: ) + # we need space in the GPT header to place tow-boot. + # only actually need 1 MB, but better to over-allocate than under-allocate + sane.image.extraGPTPadding = 16 * 1024 * 1024; + sane.image.firstPartGap = 0; + sane.image.installBootloader = '' + dd if=${pkgs.tow-boot-pinephone}/Tow-Boot.noenv.bin of=$out/nixos.img bs=1024 seek=8 conv=notrunc + ''; + + services.udev.extraRules = let + chmod = "${pkgs.coreutils}/bin/chmod"; + chown = "${pkgs.coreutils}/bin/chown"; + in '' + # make Pinephone flashlight writable by user. + # taken from postmarketOS: + SUBSYSTEM=="leds", DEVPATH=="*/*:flash", RUN+="${chmod} g+w /sys%p/brightness /sys%p/flash_strobe", RUN+="${chown} :video /sys%p/brightness /sys%p/flash_strobe" + + # make Pinephone front LEDs writable by user. + SUBSYSTEM=="leds", DEVPATH=="*/*:indicator", RUN+="${chmod} g+w /sys%p/brightness", RUN+="${chown} :video /sys%p/brightness" + ''; + + systemd.services.unl0kr.preStart = let + dmesg = "${pkgs.util-linux}/bin/dmesg"; + grep = "${pkgs.gnugrep}/bin/grep"; + modprobe = "${pkgs.kmod}/bin/modprobe"; + in '' + # common boot failure: + # blank screen (no backlight even), with the following log: + # ```syslog + # sun8i-dw-hdmi 1ee0000.hdmi: Couldn't get the HDMI PHY + # ... + # sun4i-drm display-engine: Couldn't bind all pipelines components + # ... + # sun8i-dw-hdmi: probe of 1ee0000.hdmi failed with error -17 + # ``` + # + # in particular, that `probe ... failed` occurs *only* on failed boots + # (the other messages might sometimes occur even on successful runs?) + # + # reloading the sun8i hdmi driver usually gets the screen on, showing boot text. + # then restarting display-manager.service gets us to the login. + # + # NB: the above log is default level. though less specific, there's a `err` level message that also signals this: + # sun4i-drm display-engine: failed to bind 1ee0000.hdmi (ops sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -17 + # NB: this is the most common, but not the only, failure mode for `display-manager`. + # another error seems characterized by these dmesg logs, in which reprobing sun8i_drm_hdmi does not fix: + # ```syslog + # sun6i-mipi-dsi 1ca0000.dsi: Couldn't get the MIPI D-PHY + # sun4i-drm display-engine: Couldn't bind all pipelines components + # sun6i-mipi-dsi 1ca0000.dsi: Couldn't register our component + # ``` + + if (${dmesg} --kernel --level err --color=never --notime | ${grep} -q 'sun4i-drm display-engine: failed to bind 1ee0000.hdmi') + then + echo "reprobing sun8i_drm_hdmi" + # if a command here fails it errors the whole service, so prefer to log instead + ${modprobe} -r sun8i_drm_hdmi || echo "failed to unload sun8i_drm_hdmi" + ${modprobe} sun8i_drm_hdmi || echo "failed to load sub8i_drm_hdmi" + fi + ''; + }; +} +