nixos-hardware
                                
                                
                                
                                    nixos-hardware copied to clipboard
                            
                            
                            
                        Surface Pro 6 volume and power buttons don't without reloading the kernel module manually
@NobbZ @mexisme
Have you seen this issue elsewhere?
Basically after every reboot the buttons don't work until I run sudo modprobe -r soc_button_array && sudo modprobe soc_button_array
That solves the problem temporarily. Is there a way to automate this?
Also, just running modprobe without -r does not fix the issue.
Not only this problem. When I set config of iptsd, then touchscreen in gtk won't function.
I have the same issue. For me buttons will work roughly half the time and have to be reset. I submitted the bug at Linux on Surface here and somebody commented the drivers need to be built into the kernel option.
You can automate that command by creating a systemd service.
  systemd.services.surfaceButtonsFix = {
    script = "modprobe -r soc_button_array && modprobe soc_button_array";
    after = [ "system.slice" ];
  };
This creates a systemd service called surfaceButtonsFix that runs the command after loading(?) the unit system.slice. System.slice was kind of an arbitrary guess so it may not work every time but I did several restarts and it seems to have fixed it for me. This was all a bit of guesswork as I'm no expert so use at your own risk.
System.slice was kind of an arbitrary guess so it may not work every time but I did several restarts and it seems to have fixed it for me. This was all a bit of guesswork as I'm no expert so use at your own risk.
Update: it does not work every time but definitely improves things for me.
Also I forgot to say, my issue is on Surface Pro 7
systemd.services.surfaceButtonsFix = { script = "modprobe -r soc_button_array && modprobe soc_button_array"; after = [ "system.slice" ]; };
There is a more reliable way to do this with a timer. The name of the service may also require quotes (that's how it is used on the community wiki page) although I'm sure I've used this option before without quotes and got it to run scripts.
  systemd.services."surfaceButtonsFix" = {
    script = "modprobe -r soc_button_array && modprobe soc_button_array";
    serviceConfig = {
      Type = "oneshot";
    };
  };
  systemd.timers."surfaceButtonsFix" = {
    wantedBy = [ "timers.target" ];
    timerConfig = {
      OnBootSec = "30s";
      Unit = "surfaceButtonsFix.service";
    };
  };
30 seconds after boot it runs the command.
OK I got around to working out a proper solution.
Find out what your pinctrl driver is for your Surface model by running lsmod and looking for "pinctrl". For my SP7 it's "pinctrl_icelake" – replace that with yours in the examples below.
Then you can load it before soc_button array with:
  boot.extraModprobeConfig = ''
    softdep soc_button_array pre: pinctrl_icelake
  '';
It seems like another option recommended here would be to add the pinctrl drivers to initrd with:
  boot.initrd.kernelModules = [ "pinctrl_icelake" ]; – I haven't tested that, but I wanted to suggest it in case somebody who knows more than me can let us know if it is better for some reason.
I wouldn't know how to add that to the nixos-hardware module since you'd need to make sure it uses the correct drivers for the model in question.