Solved Samsung ATIV Book 2 Brightness

Hi,

The laptop has the Intel HD Graphics 4000 and I'm using FreeBSD 11.0-CURRENT r260256 for Newcons. FreeBSD works well on this laptop, the only problem is the LCD brightness, that simply doesn't work. Loading acpi_video.ko with kldload acpi_video has no effect: I can set hw.acpi.video.lcd0.brightnes but the LCD brightness is unchanged. I can set LCD brightness only at boot where the Fn+F2/F3 keys work. What can I try next?

Thanks.

Maurizio
 
I have quickly read the FreeBSD Porter's Handbook and, probably, porting the intel-gpu-tools is above my capacity. But I can share the patched tools with the community: intel-gpu-tools-freebsd-1.5.tar.bz2.

I have compiled the source code of the intel_backlight in FreeBSD 11 and it works in FreeBSD 10 too. It seems to work in FreeBSD 9, running it I receive the expected error message "Couldn't map MMIO region: No such file or directory" because the system has an Nvidia card.

To recompile the code you need gmake. I have installed all the DEPENDENCIES in the README file: for the graphics/cairo port version 1.12 the patch cairo-1.12.16.diff is needed, more info in CFT for cairo 1.12.

Maurizio
 
Can you post the differences as a diff(1) instead of a tarball? This would make it easier for me to add the port in a maintainable a way. It may also be possible to get some of them upstreamed.
 
Last edited by a moderator:
I ran the command: diff -ruN intel-gpu-tools-1.5.bak intel-gpu-tools-1.5
The output is:
Code:
diff -ruN intel-gpu-tools-1.5.bak/freebsd_include/libemm64.h intel-gpu-tools-1.5/freebsd_include/libemm64.h
--- intel-gpu-tools-1.5.bak/freebsd_include/libemm64.h	1970-01-01 01:00:00.000000000 +0100
+++ intel-gpu-tools-1.5/freebsd_include/libemm64.h	2014-02-01 16:28:19.750527218 +0100
@@ -0,0 +1,114 @@
+#include <sys/types.h>
+
+#ifdef __i386__
+
+/* 32 bit application */
+
+__BEGIN_DECLS
+
+/* mmap64 family of syscalls.  Requires kernel support. */
+u_int64_t mmap64(u_int64_t addr, u_int64_t len, int prot, int flags,
+	    int fd, off_t offset);
+int     munmap64(u_int64_t addr, u_int64_t len);
+int     msync64(u_int64_t addr, u_int64_t len, int flags);
+
+/* generic bcopy/bzero functions. */
+extern void bcopy64(u_int64_t src, u_int64_t dst, u_int64_t len);
+extern void bzero64(u_int64_t dst, u_int64_t len);
+
+/* Note: ANSI C memset returns first arg as void *.  Not this one. */
+extern void memset64(u_int64_t dst, int val, u_int64_t len);
+
+/*
+ * Call your own 64 bit code functions.  It is called like this:
+ *   u_int32_t (*func)(void *arg);
+ * Pass an argument structure as 'arg'.  If you need more than a 32 bit
+ * return, put the return value in the 'arg' struct.  Compile the code
+ * fragment on a 64 bit freebsd-6 box, or any gcc that accepts -m64. You
+ * can link on a 32 bit freebsd-6 box, or try 'ld -r' or file2c etc.
+ * Restrictions: the 64 bit code blob must be self contained.  It may not call
+ * other functions nor reference symbols or a linker error will happen.
+ * Ignore the warning:
+ * warning: i386:x86-64 architecture of input file `func64.o' is incompatible with i386 output
+ */
+extern u_int32_t tramp64(void *func, void *arg);
+
+/*
+ * Load a simple 64 bit .so file for use with tramp64().  It should be -fpic.
+ * It must be self contained and make no external symbol or library references.
+ * Link it with libc.a or libc_pic.a if necessary to satisfy this.  There
+ * is NO support for the usual shlib magic (init,fini etc), so there are no
+ * static constructors etc.  I'd recommend using simple C here anyway.
+ */
+extern void *dlopen64(char *path);
+extern void *dlsym64(void *handle, char *func);
+extern void dlclose64(void *handle);
+
+__END_DECLS
+
+#else
+
+/* 64 bit application - just inlines. library is a stub. */
+#include <sys/mman.h>
+#include <string.h>
+
+static __inline u_int64_t
+mmap64(u_int64_t addr, u_int64_t len, int prot, int flags,
+	    int fd, off_t offset)
+{
+	return (u_int64_t)mmap((void *)addr, len, prot, flags, fd, offset);
+}
+static __inline int
+munmap64(u_int64_t addr, u_int64_t len)
+{
+	return munmap((void *)addr, len);
+}
+static __inline int
+msync64(u_int64_t addr, u_int64_t len, int flags)
+{
+	return msync((void *)addr, len, flags);
+}
+
+static __inline void
+bcopy64(u_int64_t src, u_int64_t dst, u_int64_t len)
+{
+	bcopy((void *)src, (void *)dst, len);
+}
+static __inline void
+bzero64(u_int64_t dst, u_int64_t len)
+{
+	bzero((void *)dst, len);
+}
+static __inline void
+memset64(u_int64_t dst, int val, u_int64_t len)
+{
+	memset((void *)dst, val, len);
+}
+
+#endif	/* end of arch-specific */
+
+/* Generic helper functions */
+static __inline void
+memcpy_to64(uintptr_t dst, void *src, size_t len)
+{
+        bcopy64((uintptr_t)src, dst, len);
+}
+
+static __inline void
+memcpy_from64(void *dst, u_int64_t src, size_t len)
+{
+        bcopy64(src, (uintptr_t)dst, len);
+}
+
+static __inline void
+memcpy64(u_int64_t dst, u_int64_t src, u_int64_t len)
+{
+        bcopy64(src, dst, len);
+}
+
+static __inline void
+memmove64(u_int64_t dst, u_int64_t src, u_int64_t len)
+{
+        bcopy64(src, dst, len);
+}
+
diff -ruN intel-gpu-tools-1.5.bak/lib/drmtest.h intel-gpu-tools-1.5/lib/drmtest.h
--- intel-gpu-tools-1.5.bak/lib/drmtest.h	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/lib/drmtest.h	2014-02-07 18:58:53.504528435 +0100
@@ -28,6 +28,11 @@
 #ifndef DRMTEST_H
 #define DRMTEST_H
 
+#include <libgen.h>
+#include <signal.h>
+#define sighandler_t sig_t
+#include "../freebsd_include/libemm64.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -38,6 +43,7 @@
 #include <setjmp.h>
 #include <sys/mman.h>
 
+
 #include "xf86drm.h"
 #include "xf86drmMode.h"
 #include "i915_drm.h"
diff -ruN intel-gpu-tools-1.5.bak/lib/igt_debugfs.c intel-gpu-tools-1.5/lib/igt_debugfs.c
--- intel-gpu-tools-1.5.bak/lib/igt_debugfs.c	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/lib/igt_debugfs.c	2014-02-01 14:35:08.516048605 +0100
@@ -51,7 +51,7 @@
 	if (stat("/sys/kernel/debug", &st))
 		return errno;
 
-	if (mount("debug", "/sys/kernel/debug", "debugfs", 0, 0))
+	if (mount("debug", "/sys/kernel/debug", "debugfs", 0))
 		return errno;
 
 find_minor:
diff -ruN intel-gpu-tools-1.5.bak/overlay/debugfs.c intel-gpu-tools-1.5/overlay/debugfs.c
--- intel-gpu-tools-1.5.bak/overlay/debugfs.c	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/overlay/debugfs.c	2014-02-01 22:00:59.064991242 +0100
@@ -50,7 +50,7 @@
 	if (stat("/sys/kernel/debug", &st))
 		return errno;
 
-	if (mount("debug", "/sys/kernel/debug", "debugfs", 0, 0))
+	if (mount("debug", "/sys/kernel/debug", "debugfs", 0))
 		return errno;
 
 find_minor:
diff -ruN intel-gpu-tools-1.5.bak/overlay/perf.h intel-gpu-tools-1.5/overlay/perf.h
--- intel-gpu-tools-1.5.bak/overlay/perf.h	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/overlay/perf.h	2014-02-07 20:27:40.692162433 +0100
@@ -1,8 +1,6 @@
 #ifndef I915_PERF_H
 #define I915_PERF_H
 
-#include <linux/perf_event.h>
-
 #define I915_SAMPLE_BUSY	0
 #define I915_SAMPLE_WAIT	1
 #define I915_SAMPLE_SEMA	2
Files intel-gpu-tools-1.5.bak/tests/gem_stress and intel-gpu-tools-1.5/tests/gem_stress differ
diff -ruN intel-gpu-tools-1.5.bak/tests/kms_sysfs_edid_timing intel-gpu-tools-1.5/tests/kms_sysfs_edid_timing
--- intel-gpu-tools-1.5.bak/tests/kms_sysfs_edid_timing	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/tests/kms_sysfs_edid_timing	2014-02-02 10:19:14.004004872 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/local/bin/bash
 #
 # This check the time we take to read the content of all the possible connectors.
 # Without the edid -ENXIO patch (http://permalink.gmane.org/gmane.comp.video.dri.devel/62083),
diff -ruN intel-gpu-tools-1.5.bak/tools/intel_backlight.c intel-gpu-tools-1.5/tools/intel_backlight.c
--- intel-gpu-tools-1.5.bak/tools/intel_backlight.c	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/tools/intel_backlight.c	2014-02-05 05:09:38.573207235 +0100
@@ -22,7 +22,7 @@
  *
  * Authors:
  *	Chris Wilson <chris@chris-wilson.co.uk>
- *
+ *	Maurizio Vairani <maurizio.vairani@cloverinformatica.it>
  */
 
 #include <stdint.h>
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include "intel_gpu_tools.h"
+#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
 
 /* XXX PCH only today */
 
@@ -43,27 +44,68 @@
 {
 	*(volatile uint32_t *)((volatile char*)mmio + reg) = val;
 }
+								  
+static int brightness_levels[] = {1, 2, 4, 6, 9, 12, 16, 20, 25, 30, 36, 43,
+								  51, 60, 70, 80, 90, 100};
+
+static int brightness_incr(int curr)
+{
+	int i;
+	for (i = 0; i < NUM_ELEMENTS(brightness_levels) - 1; ++i)
+		if (curr < brightness_levels[i])
+			break;
+	return brightness_levels[i];
+}
+
+static int brightness_decr(int curr)
+{
+	int i;
+	for (i = NUM_ELEMENTS(brightness_levels) - 1; i > 0; --i)
+		if (brightness_levels[i] < curr)
+			break;
+	return brightness_levels[i];
+}
 
 int main(int argc, char** argv)
 {
-	uint32_t current, max;
+	uint32_t current, max, min;
+	int result;
 
 	intel_get_mmio(intel_get_pci_device());
 
 	current = reg_read(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
 	max = reg_read(BLC_PWM_PCH_CTL2) >> 16;
 
-	printf ("current backlight value: %d%%\n", current * 100 / max);
-
+	min = 0.5 + 0.5 * max / 100.0;	// 0.5%
+	/*
+	printf ("min: %d, NUM_ELEMENTS(brightness_levels): %d\n", min, 
+		NUM_ELEMENTS(brightness_levels));
+	*/
+	result = 0.5 + current * 100.0 / max;
+	printf ("current backlight value: %d%% (%d/%d)\n", result, current, max);
+	
 	if (argc > 1) {
-		uint32_t v = atoi (argv[1]) * max / 100;
-		if (v > max)
+		uint32_t v;
+		if (0 == strcmp(argv[1], "incr")) 
+			v = 0.5 + brightness_incr(result) * max / 100.0;
+		else if (0 == strcmp(argv[1], "decr"))
+			v = 0.5 + brightness_decr(result) * max / 100.0;
+		else	
+			v = 0.5 + atoi (argv[1]) * max / 100.0;
+		/*
+		printf("v: %d\n", v);
+		*/
+		if (v < min)
+			v = min;
+		else if (v > max)
 			v = max;
 		reg_write(BLC_PWM_CPU_CTL,
 			  (reg_read(BLC_PWM_CPU_CTL) &~ BACKLIGHT_DUTY_CYCLE_MASK) | v);
 		(void) reg_read(BLC_PWM_CPU_CTL);
-		printf ("set backlight to %d%%\n", v * 100 / max);
+		result = 0.5 + v * 100.0 / max;
+		printf ("set backlight to %d%% (%d/%d)\n", result, v, max);
 	}
 
-	return 0;
+	return result;
 }
+
diff -ruN intel-gpu-tools-1.5.bak/tools/intel_vga_read.c intel-gpu-tools-1.5/tools/intel_vga_read.c
--- intel-gpu-tools-1.5.bak/tools/intel_vga_read.c	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/tools/intel_vga_read.c	2014-02-01 21:56:46.802007638 +0100
@@ -30,7 +30,8 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <sys/io.h>
+//#include <sys/io.h>
+#include <machine/cpufunc.h>
 #include "intel_gpu_tools.h"
 
 static uint8_t read_reg(uint32_t reg, bool use_mmio)
@@ -76,7 +77,7 @@
 	if (use_mmio)
 		intel_register_access_init(intel_get_pci_device(), 0);
 	else
-		assert(iopl(3) == 0);
+		;//assert(iopl(3) == 0);
 
 	for (i = 0; i < argc; i++) {
 		sscanf(argv[i], "0x%x", &reg);
@@ -86,7 +87,7 @@
 	if (use_mmio)
 		intel_register_access_fini();
 	else
-		iopl(0);
+		;//iopl(0);
 
 	return ret;
 }
diff -ruN intel-gpu-tools-1.5.bak/tools/intel_vga_write.c intel-gpu-tools-1.5/tools/intel_vga_write.c
--- intel-gpu-tools-1.5.bak/tools/intel_vga_write.c	2013-11-06 15:06:10.000000000 +0100
+++ intel-gpu-tools-1.5/tools/intel_vga_write.c	2014-02-01 21:58:07.823002244 +0100
@@ -30,7 +30,9 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <sys/io.h>
+//#include <sys/io.h>
+#include <machine/cpufunc.h>
+
 #include "intel_gpu_tools.h"
 
 static void write_reg(uint32_t reg, uint8_t val, bool use_mmio)
@@ -79,14 +81,14 @@
 	if (use_mmio)
 		intel_register_access_init(intel_get_pci_device(), 0);
 	else
-		assert(iopl(3) == 0);
+		;//assert(iopl(3) == 0);
 
 	write_reg(reg, val, use_mmio);
 
 	if (use_mmio)
 		intel_register_access_fini();
 	else
-		iopl(0);
+		;//iopl(0);
 
 	return ret;
 }

If you need the output in another format let me know.
Maurizio
 
Back
Top