summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-07-02 10:21:42 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-07-02 10:25:39 +0100
commite80f9c4670a0e84521907b1baa059322784b1558 (patch)
tree8bf6cceebda34f8d7957d93ae3ec5f4b321407a9
parent61e16dc5673a1ac96b2ecee072cc3e80971be5d9 (diff)
sna: Prefer backlight iface based on /sys/class/backlight/*/type
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_display.c152
1 files changed, 111 insertions, 41 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 07ff607e..0d9e4741 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -34,8 +34,10 @@
34#include <sys/stat.h> 34#include <sys/stat.h>
35#include <fcntl.h> 35#include <fcntl.h>
36#include <unistd.h> 36#include <unistd.h>
37#include <dirent.h>
37#include <errno.h> 38#include <errno.h>
38#include <poll.h> 39#include <poll.h>
40#include <ctype.h>
39 41
40#include <xorgVersion.h> 42#include <xorgVersion.h>
41#include <X11/Xatom.h> 43#include <X11/Xatom.h>
@@ -91,7 +93,7 @@ struct sna_output {
91 int panel_vdisplay; 93 int panel_vdisplay;
92 94
93 int dpms_mode; 95 int dpms_mode;
94 const char *backlight_iface; 96 char *backlight_iface;
95 int backlight_active_level; 97 int backlight_active_level;
96 int backlight_max; 98 int backlight_max;
97 struct list link; 99 struct list link;
@@ -104,28 +106,6 @@ static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
104 106
105#define BACKLIGHT_CLASS "/sys/class/backlight" 107#define BACKLIGHT_CLASS "/sys/class/backlight"
106 108
107/*
108 * List of available kernel interfaces in priority order
109 */
110static const char *backlight_interfaces[] = {
111 "intel", /* prefer our own native backlight driver */
112 "asus-laptop",
113 "asus-nb-wmi",
114 "eeepc",
115 "thinkpad_screen",
116 "mbp_backlight",
117 "fujitsu-laptop",
118 "sony",
119 "samsung",
120 "acpi_video1", /* finally fallback to the generic acpi drivers */
121 "acpi_video0",
122 NULL,
123};
124/*
125 * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table +
126 * '/' + "max_backlight"
127 */
128#define BACKLIGHT_PATH_LEN 80
129/* Enough for 10 digits of backlight + '\n' + '\0' */ 109/* Enough for 10 digits of backlight + '\n' + '\0' */
130#define BACKLIGHT_VALUE_LEN 12 110#define BACKLIGHT_VALUE_LEN 12
131 111
@@ -219,14 +199,14 @@ static void
219sna_output_backlight_set(xf86OutputPtr output, int level) 199sna_output_backlight_set(xf86OutputPtr output, int level)
220{ 200{
221 struct sna_output *sna_output = output->driver_private; 201 struct sna_output *sna_output = output->driver_private;
222 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 202 char path[1024], val[BACKLIGHT_VALUE_LEN];
223 int fd, len, ret; 203 int fd, len, ret;
224 204
225 DBG(("%s: level=%d\n", __FUNCTION__, level)); 205 DBG(("%s: level=%d\n", __FUNCTION__, level));
226 206
227 if (level > sna_output->backlight_max) 207 if (level > sna_output->backlight_max)
228 level = sna_output->backlight_max; 208 level = sna_output->backlight_max;
229 if (! sna_output->backlight_iface || level < 0) 209 if (!sna_output->backlight_iface || level < 0)
230 return; 210 return;
231 211
232 len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level); 212 len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level);
@@ -252,7 +232,7 @@ static int
252sna_output_backlight_get(xf86OutputPtr output) 232sna_output_backlight_get(xf86OutputPtr output)
253{ 233{
254 struct sna_output *sna_output = output->driver_private; 234 struct sna_output *sna_output = output->driver_private;
255 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 235 char path[1024], val[BACKLIGHT_VALUE_LEN];
256 int fd, level; 236 int fd, level;
257 237
258 sprintf(path, "%s/%s/actual_brightness", 238 sprintf(path, "%s/%s/actual_brightness",
@@ -287,7 +267,7 @@ static int
287sna_output_backlight_get_max(xf86OutputPtr output) 267sna_output_backlight_get_max(xf86OutputPtr output)
288{ 268{
289 struct sna_output *sna_output = output->driver_private; 269 struct sna_output *sna_output = output->driver_private;
290 char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN]; 270 char path[1024], val[BACKLIGHT_VALUE_LEN];
291 int fd, max = 0; 271 int fd, max = 0;
292 272
293 sprintf(path, "%s/%s/max_brightness", 273 sprintf(path, "%s/%s/max_brightness",
@@ -313,29 +293,117 @@ sna_output_backlight_get_max(xf86OutputPtr output)
313 return max; 293 return max;
314} 294}
315 295
296enum {
297 FIRMWARE,
298 PLATFORM,
299 RAW,
300 NAMED,
301};
302
316static void 303static void
317sna_output_backlight_init(xf86OutputPtr output) 304sna_output_backlight_init(xf86OutputPtr output)
318{ 305{
306 static const char *known_interfaces[] = {
307 "asus-laptop",
308 "asus-nb-wmi",
309 "eeepc",
310 "thinkpad_screen",
311 "mbp_backlight",
312 "fujitsu-laptop",
313 "sony",
314 "samsung",
315 "acpi_video1",
316 "acpi_video0",
317 "intel_backlight",
318 };
319 struct sna_output *sna_output = output->driver_private; 319 struct sna_output *sna_output = output->driver_private;
320 int i; 320 char *best_iface;
321 int best_type;
322 DIR *dir;
323 struct dirent *de;
324
325 best_iface = NULL;
326 best_type = INT_MAX;
327
328 dir = opendir(BACKLIGHT_CLASS);
329 while ((de = readdir(dir))) {
330 char path[1024];
331 char buf[100];
332 int fd, v;
333
334 snprintf(path, sizeof(path), "%s/%s/type",
335 BACKLIGHT_CLASS, de->d_name);
336
337 v = -1;
338 fd = open(path, O_RDONLY);
339 if (fd >= 0) {
340 v = read(fd, buf, sizeof(buf)-1);
341 close(fd);
342 }
343 if (v > 0) {
344 while (v > 0 && isspace(buf[v-1]))
345 v--;
346 buf[v] = '\0';
347
348 if (strcmp(buf, "raw") == 0)
349 v = RAW;
350 else if (strcmp(buf, "platform") == 0)
351 v = PLATFORM;
352 else if (strcmp(buf, "firmware") == 0)
353 v = FIRMWARE;
354 else
355 v = NAMED;
356 } else
357 v = NAMED;
358
359 /* Fallback to priority list of known iface for old kernels */
360 if (v == NAMED) {
361 int i;
362 for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
363 if (strcmp(de->d_name, known_interfaces[i]) == 0)
364 break;
365 }
366 v += i;
367 }
368
369 if (v < best_type) {
370 char *copy;
371 int max;
372
373 /* XXX detect right backlight for multi-GPU/panels */
374
375 sna_output->backlight_iface = de->d_name;
376 max = sna_output_backlight_get_max(output);
377 if (max <= 0)
378 continue;
321 379
322 for (i = 0; backlight_interfaces[i] != NULL; i++) { 380 copy = strdup(de->d_name);
323 char path[BACKLIGHT_PATH_LEN]; 381 if (copy) {
324 struct stat buf; 382 free(best_iface);
325 383 best_iface = copy;
326 sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]); 384 best_type = v;
327 if (!stat(path, &buf)) {
328 sna_output->backlight_iface = backlight_interfaces[i];
329 sna_output->backlight_max = sna_output_backlight_get_max(output);
330 if (sna_output->backlight_max > 0) {
331 sna_output->backlight_active_level = sna_output_backlight_get(output);
332 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
333 "found backlight control interface %s\n", path);
334 return;
335 } 385 }
336 } 386 }
337 } 387 }
388
338 sna_output->backlight_iface = NULL; 389 sna_output->backlight_iface = NULL;
390
391 if (best_iface) {
392 const char *str;
393
394 sna_output->backlight_iface = best_iface;
395 sna_output->backlight_max = sna_output_backlight_get_max(output);
396 sna_output->backlight_active_level = sna_output_backlight_get(output);
397 switch (best_type) {
398 case FIRMWARE: str = "firmware"; break;
399 case PLATFORM: str = "platform"; break;
400 case RAW: str = "raw"; break;
401 default: str = "unknown"; break;
402 }
403 xf86DrvMsg(output->scrn->scrnIndex, X_INFO,
404 "found backlight control interface %s (type '%s')\n",
405 best_iface, str);
406 }
339} 407}
340 408
341 409
@@ -1515,6 +1583,8 @@ sna_output_destroy(xf86OutputPtr output)
1515 drmModeFreeConnector(sna_output->mode_output); 1583 drmModeFreeConnector(sna_output->mode_output);
1516 sna_output->mode_output = NULL; 1584 sna_output->mode_output = NULL;
1517 1585
1586 free(sna_output->backlight_iface);
1587
1518 list_del(&sna_output->link); 1588 list_del(&sna_output->link);
1519 free(sna_output); 1589 free(sna_output);
1520 1590