Using Both Integrated And Discrete Graphics Cards

Setting up Arch Linux to use both integrated (on-board, Intel) and discrete GFX (Radeon) cards.


15 minute read

tldr; Lots of trial and error with Xorg, and some BIOS setting finangling and I got my computer to use both the onboard GFX and discrete graphics card to output video. Skip to the end for the boiled down list of steps and links that helped along the way.

Around the house, I still haven’t solved the problem of very easily moving video streams from one display to another – meaning I still have HDMI wires running around my house. As far as I’m concerned, we’re not in the future until I can very easily broadcast ANY activity from my computer or phone to any other screen in my house (including TV to computer) without disconnecting/connecting any cords. Since I’m still not there yet, this post is about getting video working from both my integrated and discrete graphics cards on my computer.

Why would I ever want to use the onboard GFX? – well I recently bought a new monitor which is a bit gaming-oriented (faster response rate, 75hz, FreeSync compatability), and I realized that for some reason, the monitor only has VGA and HDMI ports on it. This put me in a bit of a pickle because I already use the one HDMI port on my GFX card for the TV. Somehow, I didn’t expect to buy a monitor that wouldn’t have DVI ports for connection to a computer, and my discrete graphics card actually doesn’t even have a VGA port. The monitor of course also comes with speakers inside (which I 100% don’t want or need), so maybe that explains some of it. The only game I play with any consistency is Counter Strike: Global Offensive, so basically this whole upgrade was just for the sake of popping more heads in-game (I also got a monitor arm which freed up a lot of desk space).

One of the thing about running a linux distribution or many other Windows/Mac setups is that questions like “how many graphics cards are connected” are not necessarily easy to get the answers to. There often isn’t a go-to program that has the settings for the machine catalogged at that level of abstraction, so the right question (that you can get answers to) looks more like “how many block level hardware devices are connected to PCI slots with labels/drivers that indicate they are capable of acting as a display adapter”. That’s a bit of a mouthful, but smarter minds have made it much easier to find out – enter tools like lspci and lsblk.

In this post I’ll detail my notes during the process of getting this setup working, from connecting the HDMI sources (TV -> Integrated, Monitor -> Discrete), all the way to actually getting video output on both simultaneously.

Step 0: RTFM, kind of

“RTFM” is a bit of a hard term in this context because there are so manuals I could start reading – should I start with linux graphics architecture? drivers? graphics cards in general? how HDMI works? my motherboard manual? There’s a lot of possible answers. What I found most helpful was to familiarize myself with the commands and programs that seemed related to the task I was trying to perform (getting video showing on both GFX devices). This meant reading up on:

While I’m not new person jumping in, I still find it hard to be very concrete in my knowledge of so many systems and how to fit together, along with how to diagnose them, and how to affect change (so I can even attempt to do trial and error based debugging). One could read for days and not make a dent in the amount of knowledge required to fully understand all the interacting systems on a modern linux system – especially if you jumped into the wrong topic.

This means that while trying to figure this out, there was a LOT of googling, and trying to build a mental model of how everything was working in my head, finding out what was wrong, and course correcting.

Step 1: Correctly configure your BIOS

The first thing I noticed was that I wasn’t getting ANY video output through the integrated gfx at all, so I suspected immediately that the BIOS was to blame. Surely it was just prioritizing the discrete card since people rarely use both. I suspected this mostly due to a bit of a history “building” computers. I put building in quotes because building a computer is not too much more complicated than building IKEA furniture these days – if you get the right parts, you literally just put the square pegs in the square holes and the circular pegs in the circular holes and you’re off to the races.

I run a ASUS P8H61-I (I have a weird amount of ASUS devices), which has a delightfully straight-to-the-point product/support page. At first I looked through the manual, to find the page that described the BIOS settings that were relevant to me. Weirdly enough, Graphics stuff was under the Advanced Configuration > Agent Settings menu, which I didn’t expect at all. I needed to change the setting from auto to iGPU (I expect the “i” stands for “Integrated”) to force the motherboard to use the onboard graphics. I had expected auto would ensure that if either was connected they’d turn on, but it looks like auto disables the onboard graphics completley in the presence of a discrete graphics card. I was worried for a bit that switching to iGPU would disable the discrete graphics card completely, but it didn’t, which is nice. One downside was that now, every time my computer started up, it output graphics to the TV by default. Having to have the TV on while I login instead of my monitor is a little ridiculous, but I figured I could deal with that later somehow, and plowed forwards.

So like normal, I started my computer, logged in watching the TV, and ran my usual startx command to start my window manager (bspwm). I noticed that the TV was stuck on the command line where I entered startx (it didn’t wipe, didn’t do anything), while the monitor was showing the actual window manager. This immediately told me that xorg + bswpm don’t know about the TV screen exists/is manageable. If Xorg had tried to display on it, it would have at least turned all black (instead of just showing the prompt where I had entered startx). This takes me into the next step, which is to…

Step 2: Find/Identify the integrated card

The next step was to find the integrated graphics card so I could get Xorg to start managing it. lspci | grep VGA was the key here, more importantly I noted that there was as SECOND VGA adapter available to me now, along with the one I recognized as my discrete card (a Radeon R7 360 / R9 360 OEM). The output looked like this:

$ lspci | grep VGA
00:02.0 VGA compatible controller: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (rev 09)
01:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Tobago PRO [Radeon R7 360 / R9 360 OEM] (rev 81)

This output tells me a few things, but most importantly it tells me the bus locations of the cards. That is often useful when configuring Xorg (or anything else graphics related) because now we’ve finally answered the question (kind of) of where the GFX card(s) are.

Step 3: Configure Xorg

Now that I know that the card is showing up and displays, it’s time to tell Xorg about it so that it can manage it. This meant looking through the appropriate documentation for how to configure Xorg. I ended up at a Archlinux BBS thread at the start, trying to write the configuration I thought would work into /ect/X11/xorg.conf.d/30-onboard-gfx.conf (a new file I created). I’ve messed with Xorg configuration once before, when configuring my radeon card and switching draphics drivers.

I also found it really useful to read a bit on how intel graphics work on Arch. Here’s what the configuration ended up looking like:

Section "Device"
  # Options @
  Identifier "Onboard"
  Driver "intel"
  Option "AccelMethod" "uxa"
  Option "TearFree" "true"
  BusID   "PCI:0:2:0"

Note the All important BusID is the ID we got out of lspci.

Step 4: Restart startx to see if the Xorg config took

Just by adding the Device Xorg configuration (without configuring a Screen, or trying to place the monitor anywhere in relation to the existing configuration), when I restart bspwm (via startx), I can see that the TV screen now goes black. This means that Xorg seems to know about the screen now, and is at least clearing it (so I can’t see the prompt where I ran startx. This is a good sign, and a step in teh right direction.

If you’re more on the hard-data side of things, I could confirm the configuration was working properly with a quick check to xrandr --query (or just xrandr). Even more information is listed there that I can use for Xorg configurations.

Here’s what the Xorg configuration for my new screen looked like:

Section	"Monitor"
  Identifier	"TV"
  Option        "LeftOf" "Acer"

Section	"Screen"
  Identifier	"Big"
  Device	"Radeon"
  Monitor	"TV"
  DefaultDepth	24
  SubSection	"Display"
    Depth	24
    Modes	"1920x1080i"

Section "ServerLayout"
  Identifier "Main Layout"
  Option "StandbyTime" "0"
  Option "SuspendTime" "0"
  Option "OffTime" "0"
  Option "BlankTime" "0"

Note that I’ve left out the configuration for the other screen, just enought o show the big TV configuration.

Step 6: Add bspwm configuration that uses the TV

Not that Xorg is properly using the TV, it’s time to put some screens from bspwm on it so that I can move over to them. I actually make exactly one screen (linked to Super+9) for the TV, so I can throw windows over there when I want to.

Here’s what the added lines to ~/.bspwm/bspwmrc looked like:

bspc monitor HDMI-0 -d 1 2 3 4 5 6 7 8
bspc monitor HDMI-1 -d 9

I got the display names from xrandr, so feel free to look there.

Unfortunately, this configuration which seemed right didn’t take – bspwmdidn’t seem to recognize the xrandr-provided name of the display. Turns out bspc didn’t actually know that the monitor existed.

$ bspc query -M --names

I was very confused for a while with xrandr reporting the screen but bspc not being able to find it – clearly the bspc query command should have been returning two monitor names. Time to do some rapid debugging! I was tugged in a few different directions so I’ve covered all of them here:

DEBUG: Switching to the “uxa” AccelMethod

I know that the computer sees the monitor (lspci and xrandr confirm it). I also “know” that Xorg at least knows about the monitor (it’s black now), but the monitor still doesn’t get listed by bspc. I assume that the problem must have been with my Xorg config, so I check the logs and lo and behold:

[   499.374] (EE) intel(G0): sna_mode_shutdown_crtc: invalid state found on pipe 0, disabling CRTC:36

That line is staring me right in the face. WTF is CRTC? Whiel I have no idea it looks like sna add on configuration is not the right driver – the Arch docs mention MAYBE needing it, maybe I’m part of the group that doesn’t need it (there are even some recorded issues with it). Note that the configuration abovea ctually doesn’t have it so you may not run into this problem if you’re following along at home.

Switching the AccelMethod in the configuration to uxa got rid of the error, but bspc query still couldn’t see the two monitors.

DEBUG: Installing vulkan drivers, since I have an ivy bridge

My next thought was maybe I didn’t have all the drivers required to make intel based graphics actually work (since I normally run an ATI card). Looking back at the Arch intel graphics documentation I see that there’s a vulkan driver that’s been recommended for install – maybe I need it? I have a 3770K which is indeed Ivy Bridge (just barely), and I haven’t installed vulkan-intel!

This was more of a stab in the dark and it was revealed within seconds that it was a miss – bspc still can’t see the monitor. This amount of guessing (and missing) made me uncomfortable and prompted a return to basics…

DEBUG: Re-examining Xorg and Xrandr

At this point I was tired of guessing at fixes and installing things randomly, so I started trying to dive into the logs and error information available from the various programs I was using. First was to try and use xrandrto force video on to the device:

$ xrandr --output HDMI3 --auto --verbose
crtc 6:     1280x720  60.00 +0+0 "HDMI3"
xrandr: Configure crtc 6 failed
crtc 0: disable
crtc 1: disable
crtc 2: disable
crtc 3: disable
crtc 4: disable
crtc 5: disable
crtc 6: disable
crtc 7: disable
crtc 8: disable
screen 0: revert
crtc 0: revert
crtc 1: revert
crtc 2: revert
crtc 3: revert
crtc 4: revert
crtc 5: revert
crtc 6: revert
crtc 7: revert
crtc 8: revert

Welp, that was pretty eye opening – WTF is CRTC? Whatever it is, it’s going super wrong. A super helpful thread on Ask Ubuntu helped illuminate it a bit. Now I’ve got a new theory for what’s going wrong – it looks as if the monitor can use crtc but the gfx driver can’t? let’s take a look at the xorg log:

[  1908.734] randr: failed to set shadow slave pixmap
[  1908.734] (EE) intel(G0): failed to set mode: No space left on device
... lots more logs about RADEON ...
[  1909.703] (--) intel(G0): HDMI max TMDS frequency 150000KHz
... lots more RADEON log entries ..

After a quick paranoia check of df -h just to be sure, I was thoroughly confused about which device was running out of space. Maybe somehow I didn’t set my BIOS setting properly? There was an option to determine how much memory the iGPU would be allowed to use. Since that would require a restart I just benched the idea and moved to the easiest to test hypothesis – trying a smaller resolution with xrandr.

And IT WORKED! Using a smaller resolution with xrandr on the monitor got Xorg to recognize it and it to show up in bspc query. Having to go to a smaller resolution when I know the TV is capable of more is a bit disappointing, but I’ll take working over not-working any day.

Reconsideration: Maybe I shouldn’t do this

So after a few minutes coming off of the high of getting it working, I realized that what I had done was in fact a sad victory at best – who wants to have to turn on the TV to log in and deal with super shit resolutions? not me. My graphics card does indeed have a DisplayPort addapter though, so maybe I could actually just use a converter and use that? This lead to purchasing a HDMI->DisplayPort converter dongle and bunch of ultimately fruitless experimentation which landed me at the realization that I should quit while I’m ahead. For some reason DisplayPort just didn’t seem to jive.

NOTE FROM THE FUTURE - It turns out the problem was the converter dongle, they just dont’ seem to work. Buying a HDMI->DisplayPort cord was the answer and instantly worked, so the monitor is actually on DP and the TV is on HDMI now.

Wrapping up

So with all this behind me, it looks like I can boil down the list of steps to:

  • Making sure the integrated card is BIOS enabled, graphics are pumping out of the on-chip display
  • Ensureing the OS knows the device is there (lspci)
  • Ensuring Xorg knows the device is there (xrandr + xorg configuration)
  • Ensuring bspwm can see the monitor (bspc query), IF a low enough resolution is picked due to a possible bug in xorg/the intel driver
  • Setting the right resolution that the card/monitor can handle

Here’s the bread crumb trail of helpful links (basically a tab dump after I solved the issue):

Hope you found this post useful you’re struggling with some graphics configuration issues – as for me, the best solution was actually just to purchase a HDMI -> DisplayPort cable, and use the other ports on my discrete card. But, I did gain some valuable knowledge and I know now that it can be done… whether you should do it is another thing entirely.

BONUS: Sending sound to DisplayPort instead of HDMI

Normally my “HDMI” sound output would go to my TV, but as soon as I connected the monitor (with internal speakers I didn’t want), it started going to the monitor, which is way worse. I use pavucontrol which I discovered back in my days running Linux Mint. After some tussles with ALSA and PulseAudio, I remembered that it was possible for one device to have multiple channels to listen on (like one device could carry two sources of audio – like a gfx card carrying separate audio streams for DisplayPort and HDMI).

After a quick look at the Arch documentation (man what would I do without it…), I realized it should be possible to configure PulseAudio to pick a different channel! I basically followed the documentation to the letter and was able to diagnose and do some trial and error to fix my issues.

I had almost completely forgotten about a super useful tool, [aplay][aplay] in diagnosing/fixing audio issues (aplay -l is pretty crucial), and that along with the documentation got me through. In the end I just made some light edits to /etc/pulse/ and restarted just like the documentation instructed and I was home free. Feeling extremely grateful for the excellent documentation made available by the Arch community and linux community at large.

Did you find this read beneficial? Send me questions/comments/clarifciations.
Want my expertise on your team/project? Send me interesting opportunities!