summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-10-24 15:23:33 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2016-10-24 15:42:34 +0100
commit325570e731b5819e28ce6bae72242914bb2d7f8e (patch)
tree9c6f01fc35ee81e525d4d8de83a54fe20150c5bd
parent388fd4a65411f4984768132eab380b9a67f14e3c (diff)
sna: Check for the per-connector backlight sysfs interface
Modern kernels include a link from the sysfs connector directory to the backlight interface on that connector. Try to find that link first as this should allow us to enable backlight interfaces on connectors other than the presumed solitary panel. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_display.c110
1 files changed, 105 insertions, 5 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index db2bd146..28a2ee8f 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -39,6 +39,7 @@
#include <errno.h>
#include <poll.h>
#include <ctype.h>
+#include <dirent.h>
#if HAVE_ALLOCA_H
#include <alloca.h>
@@ -253,6 +254,8 @@ struct sna_output {
unsigned int is_panel : 1;
unsigned int add_default_modes : 1;
+ int connector_type;
+ int connector_type_id;
uint32_t edid_idx;
uint32_t edid_blob_id;
@@ -974,11 +977,97 @@ has_user_backlight_override(xf86OutputPtr output)
return strdup(str);
}
+static int get_device_minor(int fd)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) || !S_ISCHR(st.st_mode))
+ return -1;
+
+ return st.st_rdev & 0x63;
+}
+
+static const char * const sysfs_connector_types[] = {
+ /* DRM_MODE_CONNECTOR_Unknown */ "Unknown",
+ /* DRM_MODE_CONNECTOR_VGA */ "VGA",
+ /* DRM_MODE_CONNECTOR_DVII */ "DVI-I",
+ /* DRM_MODE_CONNECTOR_DVID */ "DVI-D",
+ /* DRM_MODE_CONNECTOR_DVIA */ "DVI-A",
+ /* DRM_MODE_CONNECTOR_Composite */ "Composite",
+ /* DRM_MODE_CONNECTOR_SVIDEO */ "SVIDEO",
+ /* DRM_MODE_CONNECTOR_LVDS */ "LVDS",
+ /* DRM_MODE_CONNECTOR_Component */ "Component",
+ /* DRM_MODE_CONNECTOR_9PinDIN */ "DIN",
+ /* DRM_MODE_CONNECTOR_DisplayPort */ "DP",
+ /* DRM_MODE_CONNECTOR_HDMIA */ "HDMI-A",
+ /* DRM_MODE_CONNECTOR_HDMIB */ "HDMI-B",
+ /* DRM_MODE_CONNECTOR_TV */ "TV",
+ /* DRM_MODE_CONNECTOR_eDP */ "eDP",
+ /* DRM_MODE_CONNECTOR_VIRTUAL */ "Virtual",
+ /* DRM_MODE_CONNECTOR_DSI */ "DSI",
+ /* DRM_MODE_CONNECTOR_DPI */ "DPI"
+};
+
+static char *has_connector_backlight(xf86OutputPtr output, char *buf)
+{
+ struct sna_output *sna_output = output->driver_private;
+ struct sna *sna = to_sna(output->scrn);
+ char path[1024];
+ DIR *dir;
+ struct dirent *de;
+ int minor, len;
+ char *ret = NULL;
+
+ if (sna_output->connector_type >= ARRAY_SIZE(sysfs_connector_types))
+ return NULL;
+
+ minor = get_device_minor(sna->kgem.fd);
+ if (minor < 0)
+ return NULL;
+
+ len = snprintf(path, sizeof(path),
+ "/sys/class/drm/card%d-%s-%d",
+ minor,
+ sysfs_connector_types[sna_output->connector_type],
+ sna_output->connector_type_id);
+ DBG(("%s: lookup %s\n", __FUNCTION__, path));
+
+ dir = opendir(path);
+ while ((de = readdir(dir))) {
+ struct stat st;
+
+ if (*de->d_name == '.')
+ continue;
+
+ snprintf(path + len, sizeof(path) - len,
+ "/%s", de->d_name);
+
+ if (stat(path, &st))
+ continue;
+
+ if (!S_ISDIR(st.st_mode))
+ continue;
+
+ DBG(("%s: testing %s as backlight\n",
+ __FUNCTION__, de->d_name));
+
+ if (backlight_exists(de->d_name)) {
+ snprintf(buf, 128, "%s", de->d_name);
+ ret = buf;
+ break;
+ }
+ }
+
+ closedir(dir);
+ return ret;
+}
+
static void
sna_output_backlight_init(xf86OutputPtr output)
{
struct sna_output *sna_output = output->driver_private;
struct pci_device *pci;
+ char buf[128];
MessageType from;
char *best_iface;
@@ -986,11 +1075,20 @@ sna_output_backlight_init(xf86OutputPtr output)
return;
#endif
- from = X_CONFIG;
- best_iface = has_user_backlight_override(output);
+ if (sna_output->is_panel) {
+ from = X_CONFIG;
+ best_iface = has_user_backlight_override(output);
+ if (best_iface)
+ goto done;
+ }
+
+ best_iface = has_connector_backlight(output, buf);
if (best_iface)
goto done;
+ if (!sna_output->is_panel)
+ return;
+
/* XXX detect right backlight for multi-GPU/panels */
from = X_PROBED;
pci = xf86GetPciInfoForEntity(to_sna(output->scrn)->pEnt->index);
@@ -4487,7 +4585,8 @@ static const char * const output_names[] = {
/* DRM_MODE_CONNECTOR_TV */ "TV",
/* DRM_MODE_CONNECTOR_eDP */ "eDP",
/* DRM_MODE_CONNECTOR_VIRTUAL */ "Virtual",
- /* DRM_MODE_CONNECTOR_DSI */ "DSI"
+ /* DRM_MODE_CONNECTOR_DSI */ "DSI",
+ /* DRM_MODE_CONNECTOR_DPI */ "DPI"
};
static bool
@@ -4911,6 +5010,8 @@ sna_output_add(struct sna *sna, unsigned id, unsigned serial)
if (!sna_output)
return -1;
+ sna_output->connector_type = compat_conn.conn.connector_type;
+ sna_output->connector_type_id = compat_conn.conn.connector_type_id;
sna_output->num_props = compat_conn.conn.count_props;
sna_output->prop_ids = malloc(sizeof(uint32_t)*compat_conn.conn.count_props);
sna_output->prop_values = malloc(sizeof(uint64_t)*compat_conn.conn.count_props);
@@ -5040,8 +5141,7 @@ reset:
sna_output->base = output;
backlight_init(&sna_output->backlight);
- if (sna_output->is_panel)
- sna_output_backlight_init(output);
+ sna_output_backlight_init(output);
output->possible_crtcs = possible_crtcs & count_to_mask(sna->mode.num_real_crtc);
output->interlaceAllowed = TRUE;