Title: VGA_Switcheroo (ou le changement de carte graphique à chaud sous GNU/Linux)
Date: 2011-04-16
Tags: Tablet PC, linux, geekeries, asrall
Authors: alex
url: vga-switcheroo
slug: vga-switcheroo


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)](http://en.wikipedia.org/wiki/Arrandale_%28microprocessor%29)

[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 <[email protected]>
   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](http://people.freedesktop.org/%7Eairlied/vgaswitcheroo/0001-vga_switcheroo-initial-implementation-v11.patch)