[ltp] switching output on t61 (nvidia quadro 140 NVS)

Andreas Jellinghaus linux-thinkpad@linux-thinkpad.org
Tue, 2 Sep 2008 10:26:06 +0200


--Boundary-00=_eiPvI6dn2MpDRFr
Content-Type: text/plain;
  charset="utf-8"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hi,

like many users of T61 with nvidia quadro 140 nvs I'm annoyed,
that we can't easily switch our display output. instead we need
to start nvidia-settings, click on the displays, click detect
display, click on the disabled, click configure, select twinview,
click ok, click on the old enabled, click configure, select disabled
click ok, click in the confirm window on "disable", click apply,
wait till the switch is done and we can see the result, click on
the apply window to confirm the change, click quit, click on the
quit dialog to confirm the quit.

attached is a command line too to change the video output.
not questions, simply done. if the other output is not attached,
your fault. (hint: cursor up and "enter" will run it again).

I tried to add this to thinkwiki.org to the video output
switching page, but uploading a makefile and a c file doesn't
work. any better idea?

also maybe you know how I can configure my linux (kubuntu 8.04)
to run this command when I press some key? (the fn+f7 isn't working
so maybe we can use that one? :) )

if anyone wants to improve this command, please feel free to do so.
for some users a gui box with a confirm (and a reset if that isn't
done within 20 seconds) might be nice.

Regards, Andreas

--Boundary-00=_eiPvI6dn2MpDRFr
Content-Type: text/x-makefile;
  charset="utf-8";
  name="Makefile"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="Makefile"

# tested on Ubuntu 8.04 LTS amd64
# you need these packages:
# 	libext-dev
# 	libxnvctrl-dev
# to compile this application

CC = gcc
CFLAGS = -Wall -I/usr/include/NVCtrl/
LDFLAGS = 
LIBS = -lXNVCtrl -lXext

APPS = switch-display

all: $(APPS)

% : %.c
	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) $(LIBS)

clean:
	rm -rf *.o *~ $(APPS)

--Boundary-00=_eiPvI6dn2MpDRFr
Content-Type: text/x-csrc;
  charset="utf-8";
  name="switch-display.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="switch-display.c"

/*
 * switch-display: A tool for switching display for Lenovo T61 laptops
 * 	(and friends - with Nvidia Quadro 140 NVS graphics)
 *
 * Copyright (C) 2008 Andreas Jellinghaus
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of Version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
 * of the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the:
 *
 *           Free Software Foundation, Inc.
 *           59 Temple Place - Suite 330
 *           Boston, MA 02111-1307, USA
 *
 * This program is based on 
 * 	nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
 *  	and Linux systems.
 *    
 *	Copyright (C) 2004 NVIDIA Corporation.
 *
 */

#include <stdio.h>
#include <stdlib.h>

#include <X11/Xlib.h>

#include "NVCtrl.h"
#include "NVCtrlLib.h"

int main(int argc, char *argv[])
{
	Display *dpy;
	Bool ret;
	int screen = -1;
	int display_devices, connected_displays, enabled_displays, new_displays;

	/*
	 * Open a display connection, and make sure the NV-CONTROL X
	 * extension is present on the screen we want to use.
	 */

	dpy = XOpenDisplay(NULL);
	if (!dpy) {
		fprintf(stderr, "Cannot open display '%s'.\n", XDisplayName(NULL));
		return 1;
	}

	screen = DefaultScreen(dpy);

	if (!XNVCTRLIsNvScreen(dpy, screen)) {
		fprintf(stderr, "The NV-CONTROL X not available on screen "
				"%d of '%s'.\n", screen, XDisplayName(NULL));
		return 1;
	}

	/* Probe the GPU for new/old display devices */

	ret = XNVCTRLQueryTargetAttribute(dpy,
									  NV_CTRL_TARGET_TYPE_GPU, 0,
									  0,
									  NV_CTRL_PROBE_DISPLAYS, &display_devices);

	if (!ret) {
		fprintf(stderr, "Failed to probe the enabled Display "
				"Devices on GPU-%d.\n\n", 0);
		return 1;
	}

	printf("  display devices on GPU-%d):\n", 0);

	/*
	 * Get the bitmask of connected display 
	 */

	ret = XNVCTRLQueryAttribute(dpy,
								screen,
								0,
								NV_CTRL_CONNECTED_DISPLAYS,
								&connected_displays);
	if (!ret) {
		fprintf(stderr, "Unable to determine connected displays for "
				"screen %d of '%s'\n", screen, XDisplayName(NULL));
		return 1;
	}

	/*
	 * Get the bitmask of enabled display
	 */

	ret = XNVCTRLQueryAttribute(dpy,
								screen,
								0, NV_CTRL_ENABLED_DISPLAYS, &enabled_displays);
	if (!ret) {
		fprintf(stderr, "Unable to determine enabled displays for "
				"screen %d of '%s'\n", screen, XDisplayName(NULL));
		return 1;
	}

	/* now enable what is not enabled (switch) */

	new_displays = connected_displays ^ enabled_displays;

	printf
		("connected displays: 0x%08x, enabled displays: 0x%08x new displays: 0x%08x\n",
		 connected_displays, enabled_displays, new_displays);

	if (!new_displays) {
		fprintf(stderr, "no new display, aborting!\n");
		return 1;
	}

	ret = XNVCTRLSetAttributeAndGetStatus
		(dpy, screen, 0, NV_CTRL_SWITCH_TO_DISPLAYS, new_displays);

	if (!ret) {
		fprintf(stderr, "Unable to switch to new displays for "
				"screen %d of '%s'\n", screen, XDisplayName(NULL));
		return 1;
	}

	return 0;
}

--Boundary-00=_eiPvI6dn2MpDRFr--