Chibi-nah::blog

Des geekeries, de la MAO, de tout et de rien…

Archives

VGA_Switcheroo (ou le changement de carte graphique à chaud sous GNU/Linux)

Attention : ce qui suit est totalement discutable, et n'est pas à prendre tel- quel. Un minimum de connaissances peut être nécessaire à la compréhension de cet article (genre, savoir compiler un noyau Linux, et plus important : faire en sorte qu'il fonctionne). De plus, un seul type de configuration a été testé et il n'est aucunement garanti que cela refonctionnera, y compris sur la même machine. Inutile de préciser que la ligne de commande sera le seul moyen de parvenir à nos fins.

Si vous êtes encore là, vous pouvez lire la suite…

Commençons par définir le contexte :

J'ai un Tablet PC HP TouchSmart TM2 1050ef (france), doté de deux cartes graphiques, une Intel GMA 4500MHD (consommant peu mais au niveau performances lamentables [1]) et une ATI/AMD Radeon HD4550M (consommant laaargement plus, mais plus performante [2]).

À noter que le CPU est un Intel Core2Duo ULV [3] (donc, pas un i3/5/7) et ne comprend pas de partie graphique intégrée, Cf. http://ark.intel.com/Product.aspx?spec=SLGYV

Confirmons les dires via une petite commande.

alex@yue ~> lspci | grep VGA
00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
01:00.0 VGA compatible controller: ATI Technologies Inc M93 [Mobility Radeon HD 4500 Series] (rev ff)

Deux cartes graphiques, situées sur le bus PCI aux adresses "00:02.0" et "01:00.0". Cette information est importante et sera réutilisée par la suite.

Par défaut, les deux cartes sont alimentées, et fonctionnent (enfin, fonctionnent, façon de parler, l'une des deux tourne à vide). Résultat : la consommation d'énergie explose (autonomie estimée à environ une heure), et le pc chauffe pas mal (~ 60°C au lieu de 40°C… oui, je SAIS, mon MBU [4] tourne, lui, entre 50 et 78°C, donc le "pas mal", c'est par rapport à Windows sur cette même machine).

Commençons donc les choses sérieuses.

Tout d'abord, vérifier que vga_switcheroo n'est pas déjà présent (j'ai eu cette bonne surprise sur une OpenSuse, en testant SMEEGOL), via cette petite commande :

alex@yue ~> ls /sys/kernel/debug/vgaswitcheroo/switch
/sys/kernel/debug/vgaswitcheroo/switch

Si "switch" est présent, c'est tout bon, et vous pouvez ignorer la suite et passer directement à la partie amusante.

Sinon, il va falloir compiler le noyau Linux. Récupérez le code source d'un noyau récent (2.6.37 ou supérieur), éventuellement celui utilisé par votre distrib accompagné de ses patches [5].

NOTE IMPORTANTE : Si vous ne savez pas ce que signifie "patch", "compiler", "noyau", mais connaissez le sens de "pépin", arrêtez tout de suite avant de faire une grosse erreur. Normalement, vous auriez du vous arrêter au chapô au lieu de continuer de lire cet article.

Configurer le noyau comme suit :

Device Drivers  --->
Graphics support.
<*> /dev/agpgart (AGP Support)  --->
<*>   Intel 440LX/BX/GX, I8xx and E7x05 chipset support
(16)  Maximum number of GPUs
[*] Laptop Hybrid Graphics - GPU switching support
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)  --->
<M>   ATI Radeon
[*]     Enable modesetting on radeon by default - NEW DRIVER
<*>   Intel 8xx/9xx/G3x/G4x/HD Graphics
[*]     Enable modesetting on intel by default

Explications rapide :

Je suis obligé d'activer le support AGP pour le driver Intel, sinon il refuse de fonctionner.

Le nombre maximum de GPU a été laissé à 16 par défaut, il faudra que je regarde ce qu'il se passe si je change cette valeur, par exemple avec les valeurs "1" ou "2".

Le support du changement de GPU est actif.

Je laisse le driver radeon en tant que module, et colle le driver intel en dur. La raison est simple : je veux que par défaut, ça soit la carte graphique Intel qui soit utilisée, puis la radeon au besoin et non l'inverse. Ce n'est pas du tout à cause du fait que la sortie vidéo soit reliée à un "multiplexeur" et que la carte intel est la carte par défaut :D [6]

Tant qu'on y est, on active le support KMS.

À ne pas oublier : Dans Kernel Hacking, activer "Debug Filesystem" pour pouvoir accéder à /sys/kernel/debug/.

Compiler et installer le noyau, rebooter dessus.

Tout s'est bien passé ? alors on peut alors attaquer la partie amusante.

À partir de maintenant, on peut jouer avec le changement de carte à chaud.

Monter (si ce n'est pas déjà fait) le système de fichiers debug (en root, bien entendu) via

mount -t debugfs none /sys/kernel/debug

Vérifier le contenu de switch :

alex@yue ~> cat /sys/kernel/debug/vgaswitcheroo/switch
0:IGD:+:Pwr:0000:00:02.0
1:DIS: :Off:0000:01:00.0

Là, j'avoue, j'ai effectué le "cat" alors que tout est configuré et fonctionnel. Normalement, à ce stade, les deux cartes devraient être sur "Pwr". Le '+' indiquant la carte active.

Notez le "00:02.0" et "01:00.0". Cela ressemble bizarrement à

00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
01:00.0 VGA compatible controller: ATI Technologies Inc M93 [Mobility Radeon HD 4500 Series] (rev ff)

Et cela est confirmé par IGD et DIS : IGD désignant la carte Intégrée (soudée sur la carte mère), et DIS la carte Discrète (non, pas discrète dans le sens "ne se fait pas remarquer", mais dans le sens "Carte externe branchée sur un port d'extension").

Pour éteindre la carte inutilisée, il suffit (en root) d'écrire la valeur "OFF" :

echo OFF > /sys/kernel/debug/vgaswitcheroo/switch

Vérifier que "Off" est bien en face de la carte non utilisée. Si vous êtes sur batterie, l'estimation de l'autonomie devrait être réévaluée.

Un moyen simple pour vérifier quelle carte est active (sous Xorg) :

alex@yue ~> glxinfo | grep OpenGL
OpenGL vendor string: Tungsten Graphics, Inc
OpenGL renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset
OpenGL version string: 2.1 Mesa 7.11-devel
OpenGL shading language version string: 1.20
OpenGL extensions:

Bon, là, c'est confirmé, c'est bien la carte Intel.

Et là, comment faire pour passer sur la radeon ?

Il suffit alors de dire au système : « bascule sur la radeon », simplement via la commande :

echo DDIS > /sys/kernel/debug/vgaswitcheroo/switch

et pour revenir sur la carte Intel :

echo DIGD > /sys/kernel/debug/vgaswitcheroo/switch

À noter que le changement de carte n'est pas géré à chaud avec Xorg. Il faudra fermer sa session pour que le changement de carte soit effectif.

alex@yue ~> glxinfo | grep OpenGL
OpenGL vendor string: X.Org
OpenGL renderer string: Gallium 0.4 on AMD RV710
OpenGL version string: 2.1 Mesa 7.11-devel
OpenGL shading language version string: 1.20
OpenGL extensions:

Récapitulons :

Pour le changement de carte à chaud, il faut :

  • Avoir les droits root sur sa machine.
  • Les bonnes options dans le noyau Linux (debug, vga_switcheroo, driver intel et radeon).
  • Écrire les mots magiques dans /sys/kernel/debug/vgaswitcheroo/switch.
  • Espérer que l'ACPI ne soit pas complètement foireux.
  • Redémarrer Xorg.

Il est donc temps de scripter un peu pour automatiser tout ça.

Le "choix" de la carte par défaut étant effectué via la différenciation entre "compilé en dur" et "compilé en tant que module", c'est déjà une contrainte en moins.

Pendant la séquence de démarrage, il faut donc, après le chargement du module "radeon", monter le système de fichiers du noyau "debug", et éteindre la radeon. À noter qu'il faut que le module radeon soit chargé, sinon une seule carte apparaîtra et il ne sera pas possible de l'éteindre.

Sous ArchLinux :

Dans /etc/rc.conf, ajouter "radeon" dans la liste des modules si le module ne se charge pas automatiquement. (Je ne l'ai pas dans mon /etc/rc.conf en tout cas).

Récupérer le fichier vga_switch-init disponible dans la section "vrac", le lire puis le coller dans /etc/rc.d.

Récupérer également le fichier vga_switch, le lire puis le coller dans /usr/local/bin.

Rendre les deux scripts exécutable, et ajouter "vga_switch-init" dans la liste des démons à lancer au démarrage.

Sur son environnement de bureau (Gnome, KDE, WindowMaker, …), on peut ajouter des entrées de menu ou définir des raccourcis clavier pour changer de carte graphique sans à avoir à taper la moindre ligne de commande. Utiliser simplement le script "vga_switch", éventuellement via sudo.

Sous WindowMaker, j'ai ajouté deux entrées de menu comme suit :

Écran -> Choix de la carte graphique -> Intel GMA 4500
Écran -> Choix de la carte graphique -> ATI/AMD Radeon HD 4550

avec l'exécution de

xterm -e "/usr/bin/sudo /usr/local/bin/vga_switch intel"

pour basculer sur la carte Intel, et

xterm -e "/usr/bin/sudo /usr/local/bin/vga_switch radeon"

pour basculer sur la carte ATI.

Bien entendu, j'ai modifié mon sudoers pour exécuter ce script sans demander de mot de passe. Le fait de lancer un xterm m'a servi pour tester le script. Il est tout à fait possible d'afficher une boîte de dialogue, via zenity par exemple, pour inviter à se déconnecter pour que le changement de carte soit effectif.


[1] : Peu importe les progrès effectués, une carte Intel sera toujours merdique au niveau performances (à noter que ceci est MON PROPRE AVIS, et ne reflète en rien une quelconque vérité, mon avis étant basé sur mon expérience utilisateur)

[2] : La comparaison effectuée entre les deux cartes a été effectuée via une unité pifométrique et avec un outil de benchmark totalement discutable, puisqu'il s'agit du (vieux) jeu Unreal Tournament 2004 sous Windows 7, avec toutes les options graphiques activées, et avec une résolution de 1920x1200. La radeon fait tourner le jeu sans broncher, l'intel par contre, ¬_¬'

[3] : ULV pour Ultra Low Voltage… Les processeurs basse consommation d'Intel. Consommant peu, et étant moins performant que les modèles classique (compter environ 12-13 minutes pour compiler un noyau Linux 2.6.38 avec un make -j 4). Je précise pour le CPU, car sur les dernières architectures des CPU Intel, notamment à partir des Core i3/5/7, la puce "northbridge" (comprenant le contrôleur de mémoire, la gestion du PCI Express et éventuellement la puce graphique intégrée) est désormais sur le CPU. Du coup, la partie graphique qui se trouvait sur la puce sur la carte mère se retrouve maintenant directement sur le processeur. Cf. http://en.wikipedia.org/wiki/Arrandale_(microprocessor)

[4] : MBU pour MacBook Unibody, le prédécesseur du MacBook Pro 13"

[5] : Avis personnel : je préfère utiliser la version vanilla, sans aucun patch provenant de kernel.org, et patcher moi-même si nécessaire. Cela évite des effets de bord avec un noyau déja patché sur lequel on veut ajouter des patches récupérés sur la liste de diffusion du noyau). À noter la présence d'un patch pour le noyau qui agit au niveau de l'ACPI pour éteindre la carte graphique inutilisée. Ce patch est surtout utilisé avec la techno Optimus de nVidia, car à l'heure actuelle, cette techno ne fonctionne pas sous Linux. Ce patch ne DOIT PAS être appliqué pour faire fonctionner vga_switcheroo.

[6] : extrait du patch initial :

From: Dave Airlie <airlied@linux.ie>
Date: Mon, 1 Feb 2010 15:38:10 +1000
Subject: [PATCH] vga_switcheroo: initial implementation (v11)

Many new laptops now come with 2 gpus, one to be used for low power modes and one for gaming/on-ac applications. These GPUs are typically wired to the laptop panel and VGA ports via a multiplexer unit which is controlled via ACPI methods.

Source : http://people.freedesktop.org/~airlied/vgaswitcheroo/0001-vga_switcheroo-initial-implementation-v11.patch