[PATCH 1/3] kms: Don't hardcode the output properties [PATCH 2/3] kms: Implement output->get_property when RandR1.3 is available. [PATCH 3/3] kms: Add TV-out support src/drmmode_display.c | 403 ++++++++++++++++++++++++++++++++----------------- 1 files changed, 261 insertions(+), 142 deletions(-)
Francisco Jerez
2009-Aug-12 00:18 UTC
[Nouveau] [PATCH 1/3] kms: Don't hardcode the output properties
Replicate any properties the kernel exposes. Mostly taken from the
intel DDX.
---
src/drmmode_display.c | 303 ++++++++++++++++++++++++-------------------------
1 files changed, 151 insertions(+), 152 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3f04be1..805dc5b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -58,11 +58,22 @@ typedef struct {
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
+ drmModePropertyPtr mode_prop;
+ int index; /* Index within the kernel-side property arrays for
+ * this connector. */
+ int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
+ * num_atoms == num_enums + 1 */
+ Atom *atoms;
+} drmmode_prop_rec, *drmmode_prop_ptr;
+
+typedef struct {
drmmode_ptr drmmode;
int output_id;
drmModeConnectorPtr mode_output;
drmModeEncoderPtr mode_encoder;
drmModePropertyBlobPtr edid_blob;
+ int num_props;
+ drmmode_prop_ptr props;
} drmmode_output_private_rec, *drmmode_output_private_ptr;
static void drmmode_output_dpms(xf86OutputPtr output, int mode);
@@ -613,9 +624,14 @@ static void
drmmode_output_destroy(xf86OutputPtr output)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
+ int i;
if (drmmode_output->edid_blob)
drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+ xfree(drmmode_output->props[i].atoms);
+ }
drmModeFreeConnector(drmmode_output->mode_output);
xfree(drmmode_output);
output->driver_private = NULL;
@@ -652,140 +668,110 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
mode_id, mode);
}
-/*
- * Several scaling modes exist, let the user choose.
- */
-struct drmmode_enum {
- char *name;
- int value;
-};
-
-static struct drmmode_enum scaling_mode[] = {
- { "non-gpu", DRM_MODE_SCALE_NON_GPU },
- { "fullscreen", DRM_MODE_SCALE_FULLSCREEN },
- { "aspect", DRM_MODE_SCALE_ASPECT },
- { "noscale", DRM_MODE_SCALE_NO_SCALE },
- { NULL, -1 /* invalid */ }
-};
-static Atom scaling_mode_atom;
-
-static struct drmmode_enum dithering_mode[] = {
- { "off", DRM_MODE_DITHERING_OFF },
- { "on", DRM_MODE_DITHERING_ON },
- { NULL, -1 /* invalid */ }
-};
-static Atom dithering_atom;
-
-static int
-drmmode_enum_lookup_value(struct drmmode_enum *ptr, char *name, int size) {
- if (size == 0)
- size = strlen(name);
-
- while (ptr->name) {
- if (!strcmp(name, ptr->name))
- return ptr->value;
- ptr++;
- }
-
- return -1;
-}
-
-static char *
-drmmode_enum_lookup_name(struct drmmode_enum *ptr, int value)
+static Bool
+drmmode_property_ignore(drmModePropertyPtr prop)
{
- while (ptr->name) {
- if (ptr->value == value)
- return ptr->name;
- ptr++;
- }
+ if (!prop)
+ return TRUE;
+ /* ignore blob prop */
+ if (prop->flags & DRM_MODE_PROP_BLOB)
+ return TRUE;
+ /* ignore standard property */
+ if (!strcmp(prop->name, "EDID") ||
+ !strcmp(prop->name, "DPMS"))
+ return TRUE;
- return NULL;
+ return FALSE;
}
-drmModePropertyPtr
-drmmode_output_property_find(xf86OutputPtr output, uint32_t type,
- const char *name)
+static void
+drmmode_output_create_resources(xf86OutputPtr output)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
- drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmModeConnectorPtr mode_output = drmmode_output->mode_output;
drmmode_ptr drmmode = drmmode_output->drmmode;
- drmModePropertyPtr props;
- int i;
+ drmModePropertyPtr drmmode_prop;
+ uint32_t value;
+ int i, j, err;
- for (i = 0; i < koutput->count_props; i++) {
- props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ drmmode_output->props = xcalloc(mode_output->count_props,
sizeof(drmmode_prop_rec));
+ if (!drmmode_output->props)
+ return;
- if (!props || !(props->flags & type))
+ drmmode_output->num_props = 0;
+ for (i = 0, j = 0; i < mode_output->count_props; i++) {
+ drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
+ if (drmmode_property_ignore(drmmode_prop)) {
+ drmModeFreeProperty(drmmode_prop);
continue;
-
- if (!strcmp(props->name, name))
- return props;
- }
-
- return NULL;
-}
-
-static const char *
-drmmode_output_property_string(xf86OutputPtr output, struct drmmode_enum *ptr,
- const char *prop)
-{
- drmmode_output_private_ptr drmmode_output = output->driver_private;
- drmModeConnectorPtr koutput = drmmode_output->mode_output;
- drmModePropertyPtr props;
- const char *name;
- int i;
-
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM, prop);
- if (!props)
- return "unknown_prop";
-
- for (i = 0; i < koutput->count_props; i++) {
- if (koutput->props[i] == props->prop_id)
- break;
- }
-
- if (koutput->props[i] != props->prop_id)
- return "unknown_output_prop";
-
- name = drmmode_enum_lookup_name(ptr, koutput->prop_values[i]);
- return name ? name : "unknown_enum";
-}
-
-static void
-drmmode_output_create_resources(xf86OutputPtr output)
-{
- ScrnInfoPtr pScrn = output->scrn;
- const char *name;
- int ret;
-
- scaling_mode_atom = MakeAtom("SCALING_MODE", 12, TRUE);
- dithering_atom = MakeAtom("DITHERING", 9, TRUE);
-
- ret = RRConfigureOutputProperty(output->randr_output, scaling_mode_atom,
- FALSE, FALSE, FALSE, 0, NULL);
- if (ret) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Error creating SCALING_MODE property: %d\n", ret);
+ }
+ drmmode_output->props[j].mode_prop = drmmode_prop;
+ drmmode_output->props[j].index = i;
+ drmmode_output->num_props++;
+ j++;
}
- name = drmmode_output_property_string(output, scaling_mode,
- "scaling mode");
- RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
- XA_STRING, 8, PropModeReplace, strlen(name),
- (char *)name, FALSE, FALSE);
-
- ret = RRConfigureOutputProperty(output->randr_output, dithering_atom,
- FALSE, FALSE, FALSE, 0, NULL);
- if (ret) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Error creating DITHERING property: %d\n", ret);
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+ drmmode_prop = p->mode_prop;
+
+ value = drmmode_output->mode_output->prop_values[p->index];
+
+ if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
+ INT32 range[2];
+
+ p->num_atoms = 1;
+ p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name,
strlen(drmmode_prop->name), TRUE);
+ range[0] = drmmode_prop->values[0];
+ range[1] = drmmode_prop->values[1];
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, TRUE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ 2, range);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_INTEGER, 32, PropModeReplace, 1,
+ &value, FALSE, FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
+ p->num_atoms = drmmode_prop->count_enums + 1;
+ p->atoms = xcalloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name,
strlen(drmmode_prop->name), TRUE);
+ for (j = 1; j <= drmmode_prop->count_enums; j++) {
+ struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+ p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+ }
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, FALSE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ for (j = 0; j < drmmode_prop->count_enums; j++)
+ if (drmmode_prop->enums[j].value == value)
+ break;
+ /* there's always a matching value */
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE,
FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ }
}
-
- name = drmmode_output_property_string(output, dithering_mode,
- "dithering");
- RRChangeOutputProperty(output->randr_output, dithering_atom,
- XA_STRING, 8, PropModeReplace, strlen(name),
- (char *)name, FALSE, FALSE);
}
static Bool
@@ -794,47 +780,60 @@ drmmode_output_set_property(xf86OutputPtr output, Atom
property,
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
drmmode_ptr drmmode = drmmode_output->drmmode;
- drmModePropertyPtr props;
- int mode, ret = 0;
+ int i, ret;
- if (property == scaling_mode_atom) {
- if (value->type != XA_STRING || value->format != 8)
- return FALSE;
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
- mode = drmmode_enum_lookup_value(scaling_mode, value->data,
- value->size);
- if (mode == -1)
- return FALSE;
+ if (p->atoms[0] != property)
+ continue;
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM,
- "scaling mode");
- if (!props)
- return FALSE;
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ uint32_t val;
- ret = drmModeConnectorSetProperty(drmmode->fd,
- drmmode_output->output_id,
- props->prop_id, mode);
- } else
- if (property == dithering_atom) {
- if (value->type != XA_STRING || value->format != 8)
- return FALSE;
+ if (value->type != XA_INTEGER || value->format != 32 ||
+ value->size != 1)
+ return FALSE;
+ val = *(uint32_t *)value->data;
- mode = drmmode_enum_lookup_value(dithering_mode, value->data,
- value->size);
- if (mode == -1)
- return FALSE;
+ ret = drmModeConnectorSetProperty(drmmode->fd,
drmmode_output->output_id,
+ p->mode_prop->prop_id, (uint64_t)val);
- props = drmmode_output_property_find(output, DRM_MODE_PROP_ENUM,
- "dithering");
- if (!props)
- return FALSE;
+ if (ret)
+ return FALSE;
+
+ return TRUE;
- ret = drmModeConnectorSetProperty(drmmode->fd,
- drmmode_output->output_id,
- props->prop_id, mode);
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ Atom atom;
+ const char *name;
+ int j;
+
+ if (value->type != XA_ATOM || value->format != 32 || value->size !=
1)
+ return FALSE;
+ memcpy(&atom, value->data, 4);
+ name = NameForAtom(atom);
+
+ /* search for matching name string, then set its value down */
+ for (j = 0; j < p->mode_prop->count_enums; j++) {
+ if (!strcmp(p->mode_prop->enums[j].name, name)) {
+ ret = drmModeConnectorSetProperty(drmmode->fd,
+ drmmode_output->output_id,
+ p->mode_prop->prop_id,
+ p->mode_prop->enums[j].value);
+
+ if (ret)
+ return FALSE;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
}
- return ret == 0;
+ return TRUE;
}
static const xf86OutputFuncsRec drmmode_output_funcs = {
--
1.6.3.3
Francisco Jerez
2009-Aug-12 00:18 UTC
[Nouveau] [PATCH 2/3] kms: Implement output->get_property when RandR1.3 is available.
This allows getting updated values when the kernel is modifying them
behind our back.
---
src/drmmode_display.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 805dc5b..9b61da8 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -836,6 +836,56 @@ drmmode_output_set_property(xf86OutputPtr output, Atom
property,
return TRUE;
}
+#ifdef RANDR_13_INTERFACE
+static Bool
+drmmode_output_get_property(xf86OutputPtr output, Atom property)
+{
+
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ uint32_t value;
+ int err, i;
+
+ drmModeFreeConnector(drmmode_output->mode_output);
+
+ drmmode_output->mode_output + drmModeGetConnector(drmmode->fd,
drmmode_output->output_id);
+
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+ if (p->atoms[0] != property)
+ continue;
+
+ value = drmmode_output->mode_output->prop_values[p->index];
+
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ err = RRChangeOutputProperty(output->randr_output,
+ property, XA_INTEGER, 32,
+ PropModeReplace, 1, &value,
+ FALSE, FALSE);
+
+ return !err;
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ int j;
+
+ /* search for matching name string, then set its value down */
+ for (j = 0; j < p->mode_prop->count_enums; j++) {
+ if (p->mode_prop->enums[j].value == value)
+ break;
+ }
+
+ err = RRChangeOutputProperty(output->randr_output, property,
+ XA_ATOM, 32, PropModeReplace, 1,
+ &p->atoms[j+1], FALSE, FALSE);
+
+ return !err;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+
static const xf86OutputFuncsRec drmmode_output_funcs = {
.create_resources = drmmode_output_create_resources,
.dpms = drmmode_output_dpms,
@@ -853,6 +903,9 @@ static const xf86OutputFuncsRec drmmode_output_funcs = {
.get_modes = drmmode_output_get_modes,
.set_property = drmmode_output_set_property,
+#ifdef RANDR_13_INTERFACE
+ .get_property = drmmode_output_get_property,
+#endif
.destroy = drmmode_output_destroy
};
--
1.6.3.3
---
src/drmmode_display.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9b61da8..daa3f53 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -571,8 +571,16 @@ drmmode_output_detect(xf86OutputPtr output)
}
static Bool
-drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+
+ if (koutput->connector_type == DRM_MODE_CONNECTOR_TV
+ && mode->type & M_T_DEFAULT)
+ /* Default modes are harmful here. */
+ return MODE_BAD;
+
return MODE_OK;
}
@@ -778,8 +786,10 @@ static Bool
drmmode_output_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
{
+ ScrnInfoPtr pScrn = output->scrn;
drmmode_output_private_ptr drmmode_output = output->driver_private;
drmmode_ptr drmmode = drmmode_output->drmmode;
+ const char* property_name = NameForAtom(property);
int i, ret;
for (i = 0; i < drmmode_output->num_props; i++) {
@@ -802,7 +812,7 @@ drmmode_output_set_property(xf86OutputPtr output, Atom
property,
if (ret)
return FALSE;
- return TRUE;
+ goto out;
} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
Atom atom;
@@ -825,7 +835,7 @@ drmmode_output_set_property(xf86OutputPtr output, Atom
property,
if (ret)
return FALSE;
- return TRUE;
+ goto out;
}
}
@@ -833,6 +843,62 @@ drmmode_output_set_property(xf86OutputPtr output, Atom
property,
}
}
+out:
+ /* The following properties are evil because they often
+ * render the current CRTC mode invalid.
+ */
+
+ if (!strcmp(property_name, "mode")
+ || !strcmp(property_name, "scale")) {
+ xf86CrtcPtr crtc = output->crtc;
+ drmmode_crtc_private_ptr drmmode_crtc;
+ DisplayModePtr mode,
+ mode_same = NULL,
+ mode_preferred = NULL;
+
+ drmModeFreeConnector(drmmode_output->mode_output);
+ drmmode_output->mode_output = drmModeGetConnector(drmmode->fd,
+ drmmode_output->output_id);
+
+ if (!drmmode_output->mode_output || !pScrn->vtSema
+ || !crtc || !crtc->enabled)
+ return TRUE;
+
+ drmmode_crtc = crtc->driver_private;
+
+ xf86ProbeOutputModes(pScrn, 0, 0);
+ xf86SetScrnInfoModes(pScrn);
+
+ /* Look for a mode with the same dimensions, otherwise
+ * use the preferred one. */
+
+ for (mode = output->probed_modes; mode;
+ mode = mode->next) {
+ if (crtc->mode.HDisplay == mode->HDisplay
+ && crtc->mode.VDisplay == mode->VDisplay)
+ mode_same = mode;
+
+ if (mode->type & M_T_PREFERRED)
+ mode_preferred = mode;
+ }
+
+ if (mode_same)
+ mode = mode_same;
+ else if (mode_preferred)
+ mode = mode_preferred;
+
+ /* Disable the CRTC first to ensure a full modeset is performed. */
+ drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+
+ if(mode)
+ drmmode_set_mode_major(crtc, mode, crtc->rotation, crtc->x,
crtc->y);
+
+ if (output->randr_output->modes)
+ xf86RandR12TellChanged(pScrn->pScreen);
+
+ }
+
return TRUE;
}
@@ -922,13 +988,14 @@ const char *output_names[] = { "None",
"DVI-D",
"DVI-A",
"Composite",
- "TV",
+ "SVIDEO",
"LVDS",
"CTV",
"DIN",
"DP",
"HDMI",
"HDMI",
+ "TV",
};
--
1.6.3.3
---
src/drmmode_display.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9b61da8..f2fe0e8 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -571,8 +571,12 @@ drmmode_output_detect(xf86OutputPtr output)
}
static Bool
-drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
{
+ if (mode->type & M_T_DEFAULT)
+ /* Default modes are harmful here. */
+ return MODE_BAD;
+
return MODE_OK;
}
@@ -922,13 +926,14 @@ const char *output_names[] = { "None",
"DVI-D",
"DVI-A",
"Composite",
- "TV",
+ "SVIDEO",
"LVDS",
"CTV",
"DIN",
"DP",
"HDMI",
"HDMI",
+ "TV",
};
--
1.6.3.3
Maybe Matching Threads
- [PATCH 1/2] nouveau/mode: split out create_ranged_atom
- [PATCH] drmmode: Add backlight support
- [PATCH] drmmode: update logic for dynamic connectors, paths, and tiles
- [PATCH 2/2] nouveau: add libbacklight and randr property support.
- [PATCH] drmmode: update logic for dynamic connectors, paths, and tiles