summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drmmode_display.c107
-rw-r--r--src/drmmode_display.h4
2 files changed, 93 insertions, 18 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 86adfeb8..d78a82ac 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -618,8 +618,12 @@ drmmode_output_destroy(xf86OutputPtr output)
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);
+ drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+ xfree(drmmode_output->props[i].atoms);
+ }
+ for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
+ drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
+ xfree(drmmode_output->mode_encoders);
}
xfree(drmmode_output->props);
drmModeFreeConnector(drmmode_output->mode_output);
@@ -847,7 +851,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
{
xf86OutputPtr output;
drmModeConnectorPtr koutput;
- drmModeEncoderPtr kencoder;
+ drmModeEncoderPtr *kencoders = NULL;
drmmode_output_private_ptr drmmode_output;
drmModePropertyPtr props;
char name[32];
@@ -857,10 +861,16 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
if (!koutput)
return;
- kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
- if (!kencoder) {
- drmModeFreeConnector(koutput);
- return;
+ kencoders = xcalloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
+ if (!kencoders) {
+ goto out_free_encoders;
+ }
+
+ for (i = 0; i < koutput->count_encoders; i++) {
+ kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
+ if (!kencoders[i]) {
+ goto out_free_encoders;
+ }
}
/* need to do smart conversion here for compat with non-kms ATI driver */
@@ -884,31 +894,31 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
if (!output) {
- drmModeFreeEncoder(kencoder);
- drmModeFreeConnector(koutput);
- return;
+ goto out_free_encoders;
}
drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1);
if (!drmmode_output) {
xf86OutputDestroy(output);
- drmModeFreeConnector(koutput);
- drmModeFreeEncoder(kencoder);
- return;
+ goto out_free_encoders;
}
drmmode_output->output_id = drmmode->mode_res->connectors[num];
drmmode_output->mode_output = koutput;
- drmmode_output->mode_encoder = kencoder;
+ drmmode_output->mode_encoders = kencoders;
drmmode_output->drmmode = drmmode;
output->mm_width = koutput->mmWidth;
output->mm_height = koutput->mmHeight;
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
output->driver_private = drmmode_output;
-
- output->possible_crtcs = kencoder->possible_crtcs;
- output->possible_clones = kencoder->possible_clones;
+
+ output->possible_crtcs = 0xf;
+ for (i = 0; i < koutput->count_encoders; i++) {
+ output->possible_crtcs &= kencoders[i]->possible_crtcs;
+ }
+ /* work out the possible clones later */
+ output->possible_clones = 0;
for (i = 0; i < koutput->count_props; i++) {
props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
@@ -923,6 +933,66 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
}
return;
+out_free_encoders:
+ if (kencoders){
+ for (i = 0; i < koutput->count_encoders; i++)
+ drmModeFreeEncoder(kencoders[i]);
+ xfree(kencoders);
+ }
+ drmModeFreeConnector(koutput);
+
+}
+
+uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
+ int i;
+ xf86OutputPtr clone_output;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int index_mask = 0;
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ clone_output = xf86_config->output[i];
+ clone_drmout = clone_output->driver_private;
+ if (output == clone_output)
+ continue;
+
+ if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
+ index_mask |= (1 << i);
+ }
+ return index_mask;
+}
+
+
+static void
+drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+ int i, j;
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ drmmode_output = output->driver_private;
+ drmmode_output->enc_clone_mask = 0xff;
+ /* and all the possible encoder clones for this output together */
+ for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
+ {
+ int k;
+ for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
+ if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
+ drmmode_output->enc_mask |= (1 << k);
+ }
+
+ drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
+ }
+ }
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ output->possible_clones = find_clones(scrn, output);
+ }
}
static Bool
@@ -1081,6 +1151,9 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char
if (zaphod_mask & (1 << i))
drmmode_output_init(pScrn, drmmode, i);
+ /* workout clones */
+ drmmode_clones_init(pScrn, drmmode);
+
xf86InitialConfiguration(pScrn, TRUE);
return TRUE;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 1410afed..371ad18e 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -64,11 +64,13 @@ typedef struct {
drmmode_ptr drmmode;
int output_id;
drmModeConnectorPtr mode_output;
- drmModeEncoderPtr mode_encoder;
+ drmModeEncoderPtr *mode_encoders;
drmModePropertyBlobPtr edid_blob;
int dpms_enum_id;
int num_props;
drmmode_prop_ptr props;
+ int enc_mask;
+ int enc_clone_mask;
} drmmode_output_private_rec, *drmmode_output_private_ptr;