Linux, Nvidia, HDMI and HD video + audio

One of the great things about newer video cards is that they will handle both video and audio in one device, and pass both through the HDMI cable.  This is a huge advantage for media center type boxes running MythTV, XBMC, Boxee, etc, as you can connect your media center directly to your receiver or TV via HDMI to receive digital audio and video.

However, as audio and video always seem to be complicated in linux, getting it working isn’t necessarily the easiest task.  I recently went through an update and have made an attempt to record all of my steps through the process.  Hopefully this information may be helpful to someone looking to attempt something similar.

The card

I purchased an Nvidia off-brand ASUS GeForce GT 430 Video Card (without fan) for around $70 new because I wanted it to be quiet.  However, there are many alternatives like the cheaper ASUS GeForce GT 430 low profile with fan or the ASUS GeForce GT 440 with fan, but the important thing is that you get one that is compatible with the VDPAU library – this library is what provides the best hardware acceleration for HD video playback.  MythTV maintains a good list of chipsets that VDPAU supports.

In addition, I wanted my Myth box to be out of sight for both visual appeal and to prevent machine noise around my entertainment center.  So, I purchased a long HDMI cable for this purpose.  CAUTION – I actually struggled with this.  At first I bought what looked like a really nice cable – name brand, CL3 rating and 3D supported.  I found out later that the gauge of the wires used in this cable are terribly small, which caused huge problems with reflection (the best way I can describe reflection is comparing the problem to the old analog term “ghosting”).

Thanks to Amazon’s fantastic return policy, they took the old cable back and I then purchased a Tartan 40 foot HDMI cable instead.  This one had larger 24 AWG wires in it and a lot more insulation – it is noticeably thicker.  This cable, although the same length and run the same way, presents a crystal clear picture.

Installing the driver

There are many ways the Nvidia driver can be installed.  I will outline a few, but please note that there are many other ways, including compiling the kernel module for the driver from kernel source.

The mechanism you use for installing the Nvidia driver will probably depend on what you’re attempting to do, and how you’re installing other packages you will use with it.  In my case, I am running MythTV.  I also really wanted to make the installation of both Nvidia and MythTV easy, so I wanted to find repos that could provide everything for me.

There are several repos to choose from.

ATrpms

At the time of my installation, the only one available was ATrpms.  Would I recommend going with this option again?  I’m not sure – there have been many issues with this repository failing to properly link revisions of RPMs together (so therefore updates aren’t detected), dependencies being missed so an installtion or upgrade of MythTV itself doesn’t also upgrade all of the required libraries, etc.  However, it is what I am currently running, and it runs well.

Adding the repository – I added it as disabled by default. This is to prevent it from updating base packages to atrpm versions. I simply enable this repo when I install or update packages I have installed from it, thus preventing any inadvertent base package updates.  Place the following into your /etc/yum.repos.d/atrpms.repo file:

[atrpms]
name=Red Hat Enterprise Linux $releasever - $basearch - ATrpms
failovermethod=priority
baseurl=http://dl.atrpms.net/el$releasever-$basearch/atrpms/stable
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-atrpms

Then to perform the installation of whatever package you wish to install (in this example, the nvidia-graphics package and its dependencies only), execute the following command:

$] sudo yum install nvidia-graphics --enablerepo atrpms

ELRepo

Before installing Nvidia through ATrpms, I got it working successfully with the kmod-nvidia package from ELRepo.  This option is really great because the package provided here is actually compiled on your system and will work with any kernel.  However, libraries it provides conflict with the ATrpms Nvidia packages, so if you’re looking to install MythTV from a repo as well, you need to make the decision up front if you’re going to use ATrpms or RPMFusion.

Adding the repository – I added this repo as enabled by default, it doesn’t appear to replace any base packages during updates. Place the following into your /etc/yum.repos.d/elrepo.repo file:

[elrepo]
name=ELRepo.org Community Enterprise Linux Repository - el6
baseurl=http://elrepo.org/linux/elrepo/el6/$basearch/
mirrorlist=http://elrepo.org/mirrors-elrepo.el6
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

Then to perform the installation of whatever package you wish to install (in this example, the kmod-nvidia package and its dependencies only), execute the following command:

$] sudo yum install kmod-nvidia

RPM Fusion

RPM Fusion recently added support for MythTV to their repository. At the time I performed my installation, a policy they had of not replacing packages provided by the base was preventing them from including MythTV in their repo. Looking over the files, I’m not sure that they actually provide the Nvidia drivers and the VDPAU library, which you would probably need to instead get from Elrepo. However, I have not tried the MythTV package from RPM Fusion as of yet.

Adding the repository – I added this repo as enabled by default, it doesn’t appear to replace any base packages during updates. Place the following into your /etc/yum.repos.d/rpmfusion.repo file:

[rpmfusion-free-updates]
name=RPM Fusion for EL 6 - Free - Updates
#baseurl=http://download1.rpmfusion.org/free/el/updates/6/$basearch/
mirrorlist=http://mirrors.rpmfusion.org/mirrorlist?repo=free-el-updates-released-6&arch=$basearch
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-free-el-6

[rpmfusion-nonfree-updates]
name=RPM Fusion for EL 6 - Nonfree - Updates
#baseurl=http://download1.rpmfusion.org/nonfree/el/updates/6/$basearch/
mirrorlist=http://mirrors.rpmfusion.org/mirrorlist?repo=nonfree-el-updates-released-6&arch=$basearch
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmfusion-nonfree-el-6

Then to perform the installation of whatever package you wish to install (I’m not certain what the nvidia package is in this repo, if there even is one, so in this example, the mythtv package and its dependencies only), execute the following command:

$] sudo yum install mythtv

Fixing the video driver installation

Regardless of the method you choose to install the driver, there are a few additional steps you’ll need to complete once the driver installation has completed in order for it to work properly (at least in my experience).

Whatever package you used above for installation of the driver will make attempts to disable the open-source Nouveau driver which is used by default.  However, in every attempt I have made at installing an Nvidia driver, these attempts never completely worked and a few additional steps are required:

Blacklist the nouveau driver

Blacklisting the nouveau driver prevents it from getting used by default.  The system always defaults to nouveau if it is available, overriding the propritary Nvidia driver.

  1. Check that rdblacklist=nouveau exists at the end of your kernel line in /boot/grub/grub.conf  Example:
title CentOS (2.6.32-220.17.1.el6.x86_64)
	root (hd0,0)
	kernel /vmlinuz-2.6.32-220.17.1.el6.x86_64 ro root=/dev/mapper/vg_mark-lv_root rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=us LANG=en_US.UTF-8 rd_NO_MD quiet SYSFONT=latarcyrheb-sun16 rhgb crashkernel=auto rd_LVM_LV=vg_mark/lv_swap rd_LVM_LV=vg_mark/lv_root rd_NO_DM rdblacklist=nouveau
	initrd /initramfs-2.6.32-220.17.1.el6.x86_64.img
  1. Add blacklist nouveau to /etc/modprobe.d/blacklist.conf
  2. Reboot

This time you should notice that the Nvidia driver actually loads:

$] lsmod | grep nvidia
nvidia              12332193  30
i2c_core               31276  5 nvidia,hdpvr,v4l2_common,videodev,i2c_i801

Configure X to optimize video

In order to get X to display everything the way I wanted, I had to fiddle with the Xorg.conf file a bit, and then also setup the nvidia-settings and set it to load the settings when starting X.

The following are the settings that worked for me in the display-related sections of xorg.conf:

Section "Monitor"
	Identifier   "Monitor0"
	VendorName   "Unknown"
	ModelName    "Unknown"
	HorizSync    28.0 - 33.0
	VertRefresh  43.0 - 72.0
	Option      "DPMS"
EndSection

Section "Device"
	Identifier  "Device0"
	Driver      "nvidia"
	VendorName  "NVIDIA Corporation"
EndSection

Section "Screen"
	Identifier "Screen0"
	Device     "Device0"
	Monitor    "Monitor0"
	DefaultDepth     24
	SubSection "Display"
		Depth     24
	EndSubSection
EndSection

Then I made the required adjustments using nvidia-settings from within X itself.  This was to set resolution, correct the overscan, and perfect a few other settings that I couldn’t get right in the xorg.conf file.  Then I setup nvidia-settings to load my configuration when X starts.  This can be done via the GUI in X, or in my setup, through a config file:

  1. Edit ~/.config/autostart/nvidia-settings.desktop
  2. Place the following into that file, or equivalent settings to run nvidia-settings -l via the X gui:
[Desktop Entry]
Type=Application
Exec=/usr/bin/nvidia-settings -l
Hidden=false
X-GNOME-Autostart-enabled=true
Name[en_US]=Load nVidia settings
Name=Load nVidia settings
Comment[en_US]=
Comment=

With all of that set, video was now working properly. One more note – if you have another display to hook up this will likely affect the resolution (adversely) on your TV, whether the second display is hooked up via DVI or VGA, set to secondary, etc.  I suggest leaving your other monitor disconnected and have your TV be your only display device.

Getting audio to work through HDMI

With video behind us, there is still the issue of audio over HDMI and the configuration of Alsa.  At this point, I’m hoping that we’re half-way through the pain, but we’ll see.

The first thing to do is to discover some information about your device:

$] sudo aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
	Subdevices: 1/1
	Subdevice #0: subdevice #0

From the above, you will notice that my Nvidia card is card 0.  The other important thing to note is that the input I’m connected to (HDMI) is device #3.

You can also gather this information / confirm this by:

$] cat /proc/asound/card0/eld#3.0
monitor_present         1
eld_valid               1
monitor_name            SAMSUNG

connection_type         HDMI
eld_version             [0x2] CEA-861D or below
edid_version            [0x3] CEA-861-B, C or D
manufacture_id          0x2d4c
product_id              0x3c7
port_id                 0x20000
support_hdcp            0
support_ai              0
audio_sync_delay        0
speakers                [0x1] FL/FR
sad_count               1
sad0_coding_type        [0x1] LPCM
sad0_channels           2
sad0_rates              [0xe0] 32000 44100 48000
sad0_bits               [0xe0000] 16 20 24

Change the card0 to match which card number your Nvidia device is, and eld#3.0 should match the device number (3).  Worst case, you can iterate through the different options until you find the one that shows your TV.

Now, with the information that we’ve gathered above, lets modify some configs.

asound.conf

The alsa configuration file (located in /etc/asound.conf or /etc/alsa/asound.conf) needs to be modified to reflect the information we’ve gathered.

  1. First, remove any other garbage in there, ESPECIALLY if there’s any junk in there regarding pulse.
  2. Now add the following lines, using the card# and device# that you found earlier:
pcm.!default {
	type hw
	card 0
	device 3
}

ctl.!default {
	type hw
	card 0
	device 3
}

dist-alsa.conf

Next is the dist-alsa.conf found in /etc/modprobe.d/ folder.  Again with the information that you found above about your device# that is connected to your monitor, use one of these (where X in eld#X.0 corresponds to your device number):

  • eld#0.0 -> 0x101
  • eld#1.0 -> 0x102
  • eld#2.0 -> 0x104
  • eld#3.0 -> 0x108
  1. Comment out any other configuration in this file, especially a line performing:  install snd-pcm ….
  2. Add the following line, updating the probe_mask to match the hex number in the list above:
options snd-hda-intel enable_msi=0 probe_mask=0x108

Group permissions

Using the system-config-users script, or by editing /etc/group, make sure both the “audio” and “video” groups contain your user and/or the user that will be logged into the system when doing audio/video playback.

Reboot

Now that everything has been updated, you should be able to perform one last final reboot.

Unmute audio

After the reboot, alsamixer should have access to the HDMI audio device.  Unmute all audio channels for the HDMI device:

alsamixer -V all

Once in alsamixer, hit F6 and then select your HDMI device.  Unmute everything in there by hitting M.  Anything that is muted will show “MM”, unmuted will show “00”

Conclusion

You should now have HD video and audio.  One thing to remember – your TV will always report that it only supports 2 channels.  So if you want to support more than 2 channel audio, you’ll want to run your HDMI to your receiver first, then on to your TV.  This, however, may have an effect on the information returned about video resolution, I’ve not tested this connection method.