mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Rebootless graphics switching
This changes out how the current graphics switching works, enabling asusd to stop/start the display-manager to enable/disable PCI devices and add/remove drivers as required. All existing graphics modes and commands still work as normal. G-Sync enable is now only through the bios setting, and on reboot will set all relevant settings to Nvidia mode.
This commit is contained in:
@@ -12,6 +12,8 @@ pub enum GfxError {
|
||||
Module(String, std::io::Error),
|
||||
Bus(String, std::io::Error),
|
||||
Command(String, std::io::Error),
|
||||
Modprobe(String),
|
||||
DisplayManager(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for GfxError {
|
||||
@@ -25,6 +27,8 @@ impl fmt::Display for GfxError {
|
||||
GfxError::Module(func, error) => write!(f, "Module error: {}: {}", func, error),
|
||||
GfxError::Bus(func, error) => write!(f, "Bus error: {}: {}", func, error),
|
||||
GfxError::Command(func, error) => write!(f, "Command exec error: {}: {}", func, error),
|
||||
GfxError::Modprobe(detail) => write!(f, "Modprobe error: {}", detail),
|
||||
GfxError::DisplayManager(detail) => write!(f, "Display manager: {}", detail),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
use ctrl_gfx::error::GfxError;
|
||||
use ctrl_gfx::*;
|
||||
use ctrl_rog_bios::CtrlRogBios;
|
||||
use log::{error, info, warn};
|
||||
use rog_types::gfx_vendors::{GfxCtrlAction, GfxVendors};
|
||||
use rog_types::gfx_vendors::GfxVendors;
|
||||
use std::io::Write;
|
||||
use std::iter::FromIterator;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::str::FromStr;
|
||||
use std::{sync::Arc, sync::Mutex};
|
||||
use sysfs_class::{PciDevice, SysClass};
|
||||
use system::{GraphicsDevice, Module, PciBus};
|
||||
use system::{GraphicsDevice, PciBus};
|
||||
use zbus::dbus_interface;
|
||||
|
||||
use crate::*;
|
||||
@@ -22,7 +20,6 @@ pub struct CtrlGraphics {
|
||||
nvidia: Vec<GraphicsDevice>,
|
||||
#[allow(dead_code)]
|
||||
other: Vec<GraphicsDevice>,
|
||||
initfs_cmd: Option<Command>,
|
||||
config: Arc<Mutex<Config>>,
|
||||
}
|
||||
|
||||
@@ -39,7 +36,9 @@ use std::convert::TryInto;
|
||||
#[dbus_interface(name = "org.asuslinux.Daemon")]
|
||||
impl Dbus for CtrlGraphics {
|
||||
fn vendor(&self) -> String {
|
||||
Self::get_vendor().unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
||||
self.get_gfx_mode()
|
||||
.map(|gfx| gfx.into())
|
||||
.unwrap_or_else(|err| format!("Get vendor failed: {}", err))
|
||||
}
|
||||
|
||||
fn power(&self) -> String {
|
||||
@@ -48,13 +47,13 @@ impl Dbus for CtrlGraphics {
|
||||
|
||||
fn set_vendor(&mut self, vendor: String) {
|
||||
if let Ok(tmp) = GfxVendors::from_str(&vendor) {
|
||||
let action = self.set(tmp).unwrap_or_else(|err| {
|
||||
let msg = self.set_gfx_config(tmp).unwrap_or_else(|err| {
|
||||
warn!("{}", err);
|
||||
format!("Failed: {}", err.to_string())
|
||||
});
|
||||
self.notify_gfx(&vendor)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
self.notify_action(&action)
|
||||
self.notify_action(&msg)
|
||||
.unwrap_or_else(|err| warn!("{}", err));
|
||||
}
|
||||
}
|
||||
@@ -86,7 +85,7 @@ impl ZbusAdd for CtrlGraphics {
|
||||
impl Reloadable for CtrlGraphics {
|
||||
fn reload(&mut self) -> Result<(), RogError> {
|
||||
self.auto_power()?;
|
||||
info!("Reloaded gfx mode: {:?}", CtrlGraphics::get_vendor()?);
|
||||
info!("Reloaded gfx mode: {:?}", self.get_gfx_mode()?);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -143,161 +142,42 @@ impl CtrlGraphics {
|
||||
}
|
||||
}
|
||||
|
||||
let mut initfs_cmd = None;
|
||||
|
||||
if Path::new(INITRAMFS_PATH).exists() {
|
||||
let mut cmd = Command::new("update-initramfs");
|
||||
cmd.arg("-u");
|
||||
initfs_cmd = Some(cmd);
|
||||
info!("Using initramfs update command 'update-initramfs'");
|
||||
} else if Path::new(DRACUT_PATH).exists() {
|
||||
let mut cmd = Command::new("dracut");
|
||||
cmd.arg("-f");
|
||||
initfs_cmd = Some(cmd);
|
||||
info!("Using initramfs update command 'dracut'");
|
||||
}
|
||||
|
||||
Ok(CtrlGraphics {
|
||||
bus,
|
||||
_amd: amd,
|
||||
_intel: intel,
|
||||
nvidia,
|
||||
other,
|
||||
initfs_cmd,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_prime_discrete() -> Result<String, RogError> {
|
||||
let s = std::fs::read_to_string(PRIME_DISCRETE_PATH)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?
|
||||
.trim()
|
||||
.to_owned();
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn set_prime_discrete(mode: &str) -> Result<(), RogError> {
|
||||
std::fs::write(PRIME_DISCRETE_PATH, mode)
|
||||
.map_err(|err| GfxError::Read(PRIME_DISCRETE_PATH.into(), err))?;
|
||||
fn save_gfx_mode(&self, vendor: GfxVendors) -> Result<(), RogError> {
|
||||
if let Ok(mut config) = self.config.lock() {
|
||||
config.gfx_mode = vendor.clone();
|
||||
config.write();
|
||||
return Ok(());
|
||||
}
|
||||
// TODO: Error here
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Associated method to get which vendor mode is set
|
||||
pub fn get_vendor() -> Result<String, RogError> {
|
||||
let mode = match Self::get_prime_discrete() {
|
||||
Ok(m) => m,
|
||||
Err(_) => "nvidia".to_string(),
|
||||
};
|
||||
let modules = Module::all().map_err(|err| GfxError::Read("get_vendor".into(), err))?;
|
||||
|
||||
let driver_loaded = modules
|
||||
.iter()
|
||||
.any(|module| module.name == "nouveau" || module.name == "nvidia");
|
||||
|
||||
let vendor = if mode == "off" {
|
||||
if driver_loaded {
|
||||
info!("dGPU driver loaded for compute mode");
|
||||
"compute".to_string()
|
||||
} else {
|
||||
info!("No dGPU driver loaded");
|
||||
"integrated".to_string()
|
||||
}
|
||||
} else {
|
||||
info!("Assuming dGPU driver loaded");
|
||||
if mode == "on-demand" {
|
||||
"hybrid".to_string()
|
||||
} else {
|
||||
"nvidia".to_string()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(vendor)
|
||||
pub fn get_gfx_mode(&self) -> Result<GfxVendors, RogError> {
|
||||
if let Ok(config) = self.config.lock() {
|
||||
return Ok(config.gfx_mode.clone());
|
||||
}
|
||||
// TODO: Error here
|
||||
Ok(GfxVendors::Hybrid)
|
||||
}
|
||||
|
||||
fn is_switching_prime_modes(&self, vendor: &GfxVendors) -> Result<bool, RogError> {
|
||||
let prev_mode = GfxVendors::from_str(&Self::get_vendor()?)?;
|
||||
if prev_mode == GfxVendors::Integrated
|
||||
&& (*vendor == GfxVendors::Hybrid || *vendor == GfxVendors::Nvidia)
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
if (prev_mode == GfxVendors::Hybrid || prev_mode == GfxVendors::Nvidia)
|
||||
&& *vendor == GfxVendors::Integrated
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
if let Ok(config) = self.config.clone().try_lock() {
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() && config.gfx_nv_mode_is_dedicated {
|
||||
if prev_mode == GfxVendors::Hybrid && *vendor == GfxVendors::Nvidia {
|
||||
return Ok(true);
|
||||
}
|
||||
if *vendor == GfxVendors::Hybrid && prev_mode == GfxVendors::Nvidia {
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
fn get_runtime_status() -> Result<String, RogError> {
|
||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
pub fn set_gfx_config(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let mode = if vendor == GfxVendors::Hybrid {
|
||||
"on-demand\n"
|
||||
} else if vendor == GfxVendors::Nvidia {
|
||||
"on\n"
|
||||
} else {
|
||||
// Integrated or Compute
|
||||
"off\n"
|
||||
};
|
||||
|
||||
info!("Setting {} to {}", PRIME_DISCRETE_PATH, mode);
|
||||
Self::set_prime_discrete(mode)?;
|
||||
|
||||
{
|
||||
info!("Writing {}", MODPROBE_PATH);
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(MODPROBE_PATH)
|
||||
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
let text = if vendor == GfxVendors::Hybrid {
|
||||
MODPROBE_HYBRID
|
||||
} else if vendor == GfxVendors::Compute {
|
||||
MODPROBE_COMPUTE
|
||||
} else if vendor == GfxVendors::Nvidia {
|
||||
MODPROBE_NVIDIA
|
||||
} else {
|
||||
MODPROBE_INTEGRATED
|
||||
};
|
||||
|
||||
file.write_all(text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
}
|
||||
|
||||
info!("Writing {}", PRIMARY_GPU_XORG_PATH);
|
||||
|
||||
// begin section for non-separated Nvidia xorg modules
|
||||
// eg, not put in their own directory
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(PRIMARY_GPU_XORG_PATH)
|
||||
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?;
|
||||
|
||||
let text = if vendor == GfxVendors::Nvidia {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||
} else {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||
};
|
||||
|
||||
file.write_all(&text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
fn toggle_fallback_service(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let action = if vendor == GfxVendors::Nvidia {
|
||||
info!("Enabling nvidia-fallback.service");
|
||||
"enable"
|
||||
@@ -319,92 +199,180 @@ impl CtrlGraphics {
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write out config files if required, enable/disable relevant services, and update the ramdisk
|
||||
fn set(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||
// Switching from hybrid to/from nvidia shouldn't require a ramdisk update
|
||||
// or a reboot.
|
||||
let reboot = self.is_switching_prime_modes(&vendor)?;
|
||||
|
||||
if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
if let Ok(config) = self.config.clone().try_lock() {
|
||||
// Switch to dedicated if config says to do so
|
||||
if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
|
||||
CtrlRogBios::set_gfx_mode(true)
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
} else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
// otherwise if switching to non-Nvidia mode turn off dedicated mode
|
||||
if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||
CtrlRogBios::set_gfx_mode(false)
|
||||
.unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self::set_gfx_config(vendor.clone())?;
|
||||
|
||||
let mut required_action = GfxCtrlAction::None;
|
||||
if reboot {
|
||||
info!("Updating initramfs");
|
||||
if let Some(cmd) = self.initfs_cmd.as_mut() {
|
||||
// If switching to Nvidia dedicated we need these modules included
|
||||
if Path::new(DRACUT_PATH).exists() && vendor == GfxVendors::Nvidia {
|
||||
cmd.arg("--add-drivers");
|
||||
cmd.arg("nvidia nvidia-drm nvidia-modeset nvidia-uvm");
|
||||
info!("System uses dracut, forcing nvidia modules to be included in init");
|
||||
}
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| GfxError::Write(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
error!("Ram disk update failed");
|
||||
return Ok("Ram disk update failed".into());
|
||||
} else {
|
||||
info!("Successfully updated iniramfs");
|
||||
}
|
||||
}
|
||||
required_action = GfxCtrlAction::Reboot;
|
||||
} else if !reboot {
|
||||
required_action = GfxCtrlAction::RestartX;
|
||||
}
|
||||
|
||||
Ok(required_action.into())
|
||||
}
|
||||
|
||||
fn get_runtime_status() -> Result<String, RogError> {
|
||||
const PATH: &str = "/sys/bus/pci/devices/0000:01:00.0/power/runtime_status";
|
||||
let buf = std::fs::read_to_string(PATH).map_err(|err| GfxError::Read(PATH.into(), err))?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn set_power(&self, power: bool) -> Result<(), RogError> {
|
||||
if power {
|
||||
info!("Enabling graphics power");
|
||||
self.bus
|
||||
.rescan()
|
||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
||||
fn write_xorg_conf(vendor: GfxVendors) -> Result<(), RogError> {
|
||||
let text = if vendor == GfxVendors::Nvidia {
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_NVIDIA, PRIMARY_GPU_END].concat()
|
||||
} else {
|
||||
info!("Disabling graphics power");
|
||||
[PRIMARY_GPU_BEGIN, PRIMARY_GPU_END].concat()
|
||||
};
|
||||
|
||||
// Unbind NVIDIA graphics devices and their functions
|
||||
let unbinds = self.nvidia.iter().map(|dev| dev.unbind());
|
||||
info!("Writing {}", PRIMARY_GPU_XORG_PATH);
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(PRIMARY_GPU_XORG_PATH)
|
||||
.map_err(|err| GfxError::Write(PRIMARY_GPU_XORG_PATH.into(), err))?;
|
||||
|
||||
// Remove NVIDIA graphics devices and their functions
|
||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
||||
file.write_all(&text)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Result::from_iter(unbinds.chain(removes))
|
||||
.map_err(|err| GfxError::Command("device unbind error".into(), err))?;
|
||||
}
|
||||
fn write_modprobe_conf() -> Result<(), RogError> {
|
||||
info!("Writing {}", MODPROBE_PATH);
|
||||
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(MODPROBE_PATH)
|
||||
.map_err(|err| GfxError::Path(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
file.write_all(MODPROBE_BASE)
|
||||
.and_then(|_| file.sync_all())
|
||||
.map_err(|err| GfxError::Write(MODPROBE_PATH.into(), err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn auto_power(&self) -> Result<(), RogError> {
|
||||
let vendor = CtrlGraphics::get_vendor()?;
|
||||
self.set_power(vendor != "integrated")
|
||||
fn unbind_remove_nvidia(&self) -> Result<(), RogError> {
|
||||
// Unbind NVIDIA graphics devices and their functions
|
||||
let unbinds = self.nvidia.iter().map(|dev| dev.unbind());
|
||||
|
||||
// Remove NVIDIA graphics devices and their functions
|
||||
let removes = self.nvidia.iter().map(|dev| dev.remove());
|
||||
|
||||
Result::from_iter(unbinds.chain(removes))
|
||||
.map_err(|err| GfxError::Command("device unbind error".into(), err))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_driver_action(driver: &str, action: &str) -> Result<(), RogError> {
|
||||
let mut cmd = Command::new(action);
|
||||
cmd.arg(driver);
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
let msg = format!("{} {} failed: {:?}", action, driver, status);
|
||||
error!("{}", msg);
|
||||
return Err(GfxError::Modprobe(msg).into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_display_manager_action(action: &str) -> Result<(), RogError> {
|
||||
let service = "display-manager.service";
|
||||
let mut cmd = Command::new("systemctl");
|
||||
cmd.arg(action);
|
||||
cmd.arg(service);
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
||||
if !status.success() {
|
||||
let msg = format!("systemctl {} {} failed: {:?}", action, service, status);
|
||||
error!("{}", msg);
|
||||
return Err(GfxError::DisplayManager(msg).into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wait_display_manager_inactive() -> Result<(), RogError> {
|
||||
let service = "display-manager.service";
|
||||
let mut cmd = Command::new("systemctl");
|
||||
cmd.arg("is-active");
|
||||
cmd.arg(service);
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
while count <= 4 {
|
||||
let output = cmd
|
||||
.output()
|
||||
.map_err(|err| GfxError::Command(format!("{:?}", cmd), err))?;
|
||||
if output.stdout.starts_with("inactive".as_bytes()) {
|
||||
return Ok(());
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
count += 1;
|
||||
}
|
||||
return Err(
|
||||
GfxError::DisplayManager("display-manager did not completely stop".into()).into(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn do_vendor_tasks(&mut self, vendor: GfxVendors) -> Result<(), RogError> {
|
||||
Self::write_xorg_conf(vendor)?;
|
||||
Self::write_modprobe_conf()?; // TODO: Not required here, should put in startup?
|
||||
|
||||
// Rescan before doing remove or add drivers
|
||||
self.bus
|
||||
.rescan()
|
||||
.map_err(|err| GfxError::Bus("bus rescan error".into(), err))?;
|
||||
|
||||
let drivers = vec!["nvidia_drm", "nvidia_modeset", "nvidia"]; // i2c_nvidia_gpu?
|
||||
|
||||
match vendor {
|
||||
GfxVendors::Nvidia | GfxVendors::Hybrid | GfxVendors::Compute => {
|
||||
for driver in drivers {
|
||||
Self::do_driver_action(driver, "modprobe")?;
|
||||
}
|
||||
}
|
||||
// TODO: compute mode, needs different setup
|
||||
// GfxVendors::Compute => {}
|
||||
GfxVendors::Integrated => {
|
||||
for driver in drivers {
|
||||
Self::do_driver_action(driver, "rmmod")?;
|
||||
}
|
||||
self.unbind_remove_nvidia()?;
|
||||
}
|
||||
}
|
||||
|
||||
self.save_gfx_mode(vendor)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// For manually calling (not on boot/startup)
|
||||
///
|
||||
/// Will stop and start display manager without warning
|
||||
pub fn set_gfx_config(&mut self, vendor: GfxVendors) -> Result<String, RogError> {
|
||||
Self::do_display_manager_action("stop")?;
|
||||
Self::wait_display_manager_inactive()?;
|
||||
self.do_vendor_tasks(vendor)?;
|
||||
Self::do_display_manager_action("start")?;
|
||||
// TODO: undo if failed? Save last mode, catch errors...
|
||||
let v: &str = vendor.into();
|
||||
Ok(format!("Graphics mode changed to {} successfully", v))
|
||||
}
|
||||
|
||||
// if CtrlRogBios::has_dedicated_gfx_toggle() {
|
||||
// if let Ok(config) = self.config.clone().try_lock() {
|
||||
// // Switch to dedicated if config says to do so
|
||||
// if config.gfx_nv_mode_is_dedicated && vendor == GfxVendors::Nvidia {
|
||||
// CtrlRogBios::set_gfx_mode(true)
|
||||
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
// } else if let Ok(ded) = CtrlRogBios::get_gfx_mode() {
|
||||
// // otherwise if switching to non-Nvidia mode turn off dedicated mode
|
||||
// if ded == 1 && vendor != GfxVendors::Nvidia {
|
||||
// CtrlRogBios::set_gfx_mode(false)
|
||||
// .unwrap_or_else(|err| warn!("Gfx controller: {}", err));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn auto_power(&mut self) -> Result<(), RogError> {
|
||||
let vendor = self.get_gfx_mode()?;
|
||||
self.do_vendor_tasks(vendor)?;
|
||||
Self::toggle_fallback_service(vendor)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,40 +4,17 @@ pub mod gfx;
|
||||
|
||||
pub mod system;
|
||||
|
||||
const PRIME_DISCRETE_PATH: &str = "/etc/prime-discrete";
|
||||
const MODPROBE_PATH: &str = "/etc/modprobe.d/asusd.conf";
|
||||
const INITRAMFS_PATH: &str = "/usr/sbin/update-initramfs";
|
||||
const DRACUT_PATH: &str = "/usr/bin/dracut";
|
||||
|
||||
static MODPROBE_NVIDIA: &[u8] = MODPROBE_HYBRID;
|
||||
|
||||
static MODPROBE_HYBRID: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
alias i2c_nvidia_gpu off
|
||||
static MODPROBE_BASE: &[u8] = br#"# Automatically generated by asusd
|
||||
#blacklist i2c_nvidia_gpu
|
||||
#alias i2c_nvidia_gpu off
|
||||
blacklist nouveau
|
||||
alias nouveau off
|
||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||
options nvidia-drm modeset=1
|
||||
"#;
|
||||
|
||||
static MODPROBE_COMPUTE: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
alias i2c_nvidia_gpu off
|
||||
options nvidia NVreg_DynamicPowerManagement=0x02
|
||||
options nvidia-drm modeset=0
|
||||
"#;
|
||||
|
||||
static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by asusd
|
||||
blacklist i2c_nvidia_gpu
|
||||
blacklist nouveau
|
||||
blacklist nvidia
|
||||
blacklist nvidia-drm
|
||||
blacklist nvidia-modeset
|
||||
alias i2c_nvidia_gpu off
|
||||
alias nouveau off
|
||||
alias nvidia off
|
||||
alias nvidia-drm off
|
||||
alias nvidia-modeset off
|
||||
"#;
|
||||
|
||||
const PRIMARY_GPU_XORG_PATH: &str = "/etc/X11/xorg.conf.d/90-nvidia-primary.conf";
|
||||
|
||||
static PRIMARY_GPU_BEGIN: &[u8] = br#"# Automatically generated by asusd
|
||||
|
||||
@@ -50,6 +50,7 @@ impl PciBus {
|
||||
}
|
||||
}
|
||||
|
||||
/// Will rescan the device tree, which adds all removed devices back
|
||||
pub fn rescan(&self) -> io::Result<()> {
|
||||
write(self.path.join("rescan"), "1")
|
||||
}
|
||||
@@ -95,6 +96,32 @@ impl GraphicsDevice {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rebind(&self) -> Result<(), std::io::Error> {
|
||||
for func in self.functions.iter() {
|
||||
if func.path().exists() {
|
||||
match func.driver() {
|
||||
Ok(driver) => {
|
||||
info!("{}: Binding {}", driver.id(), func.id());
|
||||
unsafe {
|
||||
driver.bind(&func).map_err(|err| {
|
||||
error!("gfx bind: {}", err);
|
||||
err
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::NotFound => (),
|
||||
_ => {
|
||||
error!("gfx driver: {:?}, {}", func.path(), err);
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove(&self) -> Result<(), std::io::Error> {
|
||||
for func in self.functions.iter() {
|
||||
if func.path().exists() {
|
||||
|
||||
Reference in New Issue
Block a user