sna: Streamline connector probing

This is a tidy up in preparation for a more controversial patch. In the
meantime, take advantage of information that remains static over the
lifetime of our connectors.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-06-05 12:52:11 +01:00
parent b584162e38
commit 3d760c9b32
1 changed files with 276 additions and 214 deletions

View File

@ -77,27 +77,40 @@ struct sna_crtc {
};
struct sna_property {
drmModePropertyPtr mode_prop;
uint64_t value;
drmModePropertyPtr kprop;
int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
Atom *atoms;
};
struct sna_output {
int id;
drmModeConnectorPtr mode_output;
int encoder_idx;
int num_props;
struct sna_property *props;
unsigned int is_panel : 1;
uint32_t edid_idx;
uint32_t edid_blob_id;
uint32_t edid_len;
void *edid_raw;
bool has_panel_limits;
int panel_hdisplay;
int panel_vdisplay;
uint32_t dpms_id;
int dpms_mode;
char *backlight_iface;
int backlight_active_level;
int backlight_max;
int num_modes;
struct drm_mode_modeinfo *modes;
int num_props;
uint32_t *prop_ids;
uint64_t *prop_values;
struct sna_property *props;
};
static inline struct sna_output *to_sna_output(xf86OutputPtr output)
@ -107,7 +120,7 @@ static inline struct sna_output *to_sna_output(xf86OutputPtr output)
static inline int to_connector_id(xf86OutputPtr output)
{
return to_sna_output(output)->mode_output->connector_id;
return to_sna_output(output)->id;
}
static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
@ -648,12 +661,11 @@ done:
}
#endif
static void
static DisplayModePtr
mode_from_kmode(ScrnInfoPtr scrn,
drmModeModeInfoPtr kmode,
DisplayModePtr mode)
const struct drm_mode_modeinfo *kmode,
DisplayModePtr mode)
{
memset(mode, 0, sizeof(DisplayModeRec));
mode->status = MODE_OK;
mode->Clock = kmode->clock;
@ -681,7 +693,8 @@ mode_from_kmode(ScrnInfoPtr scrn,
if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS)
mode->status = MODE_BAD; /* unknown flags => unhandled */
xf86SetModeCrtc (mode, scrn->adjustFlags);
xf86SetModeCrtc(mode, scrn->adjustFlags);
return mode;
}
static void
@ -773,12 +786,14 @@ sna_crtc_apply(xf86CrtcPtr crtc)
if (output->crtc != crtc)
continue;
assert(output->possible_crtcs & (1 << i));
assert(output->possible_crtcs & (1 << sna_crtc->pipe) ||
xf86IsEntityShared(crtc->scrn->entityList[0]));
DBG(("%s: attaching output '%s' %d [%d] to crtc:%d (pipe %d) (possible crtc:%x, possible clones:%x)\n",
__FUNCTION__, output->name, i, to_connector_id(output),
sna_crtc->id, sna_crtc->pipe,
output->possible_crtcs, output->possible_clones));
(uint32_t)output->possible_crtcs,
(uint32_t)output->possible_clones));
output_ids[output_count] = to_connector_id(output);
output_count++;
}
@ -1729,33 +1744,94 @@ is_panel(int type)
type == DRM_MODE_CONNECTOR_eDP);
}
static int
find_property(struct sna *sna, struct sna_output *output, const char *name)
{
struct drm_mode_get_property prop;
int i;
VG_CLEAR(prop);
for (i = 0; i < output->num_props; i++) {
prop.prop_id = output->prop_ids[i];
prop.count_values = 0;
prop.count_enum_blobs = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
continue;
if (strcmp(prop.name, name) == 0)
return i;
}
return -1;
}
static int
find_property_id(struct sna *sna, struct sna_output *output, const char *name)
{
int idx = find_property(sna, output, name);
return idx != -1 ? output->prop_ids[idx] : 0;
}
static xf86OutputStatus
sna_output_detect(xf86OutputPtr output)
{
/* go to the hw and retrieve a new output struct */
struct sna *sna = to_sna(output->scrn);
struct sna_output *sna_output = output->driver_private;
xf86OutputStatus status;
struct drm_mode_get_connector conn;
DBG(("%s\n", __FUNCTION__));
DBG(("%s(%s)\n", __FUNCTION__, output->name));
drmModeFreeConnector(sna_output->mode_output);
sna_output->mode_output =
drmModeGetConnector(sna->kgem.fd, sna_output->id);
VG_CLEAR(conn);
conn.connector_id = sna_output->id;
sna_output->num_modes = conn.count_modes = 0; /* reprobe */
conn.count_encoders = 0;
conn.count_props = sna_output->num_props;
conn.props_ptr = (uintptr_t)sna_output->prop_ids;
conn.prop_values_ptr = (uintptr_t)sna_output->prop_values;
switch (sna_output->mode_output->connection) {
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return XF86OutputStatusUnknown;
DBG(("%s(%s): num modes %d -> %d, num props %d -> %d\n",
__FUNCTION__, output->name,
sna_output->num_modes, conn.count_modes,
sna_output->num_props, conn.count_props));
assert(conn.count_props == sna_output->num_props);
while (conn.count_modes && conn.count_modes != sna_output->num_modes) {
struct drm_mode_modeinfo *new_modes;
int old_count;
old_count = sna_output->num_modes;
new_modes = realloc(sna_output->modes,
sizeof(*sna_output->modes)*conn.count_modes);
if (new_modes == NULL)
break;
sna_output->modes = new_modes;
sna_output->num_modes = conn.count_modes;
conn.modes_ptr = (uintptr_t)sna_output->modes;
conn.count_encoders = 0;
conn.count_props = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn)) {
ErrorF("err = %d\n", errno);
sna_output->num_modes = min(old_count, sna_output->num_modes);
break;
}
}
DBG(("%s(%s): found %d modes, connection status=%d\n",
__FUNCTION__, output->name, sna_output->num_modes, conn.connection));
switch (conn.connection) {
case DRM_MODE_CONNECTED:
status = XF86OutputStatusConnected;
break;
return XF86OutputStatusConnected;
case DRM_MODE_DISCONNECTED:
status = XF86OutputStatusDisconnected;
break;
return XF86OutputStatusDisconnected;
default:
case DRM_MODE_UNKNOWNCONNECTION:
status = XF86OutputStatusUnknown;
break;
return XF86OutputStatusUnknown;
}
return status;
}
static Bool
@ -1793,70 +1869,52 @@ sna_output_attach_edid(xf86OutputPtr output)
{
struct sna *sna = to_sna(output->scrn);
struct sna_output *sna_output = output->driver_private;
drmModeConnectorPtr koutput = sna_output->mode_output;
struct drm_mode_get_blob blob;
void *raw = NULL;
int raw_length = 0;
xf86MonPtr mon = NULL;
int i;
/* look for an EDID property */
for (i = 0; i < koutput->count_props; i++) {
struct drm_mode_get_property prop;
struct drm_mode_get_blob blob;
void *tmp;
if (sna_output->edid_idx == -1)
return;
VG_CLEAR(prop);
prop.prop_id = koutput->props[i];
prop.count_values = 0;
prop.count_enum_blobs = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
continue;
raw = sna_output->edid_raw;
blob.length = sna_output->edid_len;
if (!(prop.flags & DRM_MODE_PROP_BLOB))
continue;
blob.blob_id = sna_output->prop_values[sna_output->edid_idx];
if (blob.blob_id == sna_output->edid_blob_id)
goto skip_read;
if (strcmp(prop.name, "EDID"))
continue;
blob.data = (uintptr_t)raw;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
goto done;
if (koutput->prop_values[i] == 0)
continue;
DBG(("%s: retrieving blob id=%d, length=%d\n",
__FUNCTION__, blob.blob_id, blob.length));
VG_CLEAR(blob);
blob.length = 0;
blob.data = 0;
blob.blob_id = koutput->prop_values[i];
if (blob.length > sna_output->edid_len) {
raw = realloc(raw, blob.length);
if (raw == NULL)
goto done;
VG(memset(raw, 0, blob.length));
blob.data = (uintptr_t)raw;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
continue;
DBG(("%s: retreiving blob (property %d, id=%d, value=%ld), length=%d\n",
__FUNCTION__, i, koutput->props[i], (long)koutput->prop_values[i],
blob.length));
tmp = malloc(blob.length);
if (tmp == NULL)
continue;
VG(memset(tmp, 0, blob.length));
blob.data = (uintptr_t)tmp;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
free(tmp);
continue;
}
free(raw);
raw = tmp;
raw_length = blob.length;
goto done;
}
skip_read:
if (raw) {
mon = xf86InterpretEDID(output->scrn->scrnIndex, raw);
if (mon && raw_length > 128)
if (mon && blob.length > 128)
mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
}
done:
xf86OutputSetEDID(output, mon);
free(raw);
if (raw) {
sna_output->edid_raw = raw;
sna_output->edid_len = blob.length;
sna_output->edid_blob_id = blob.blob_id;
}
}
static DisplayModePtr
@ -1903,7 +1961,6 @@ static DisplayModePtr
sna_output_get_modes(xf86OutputPtr output)
{
struct sna_output *sna_output = output->driver_private;
drmModeConnectorPtr koutput = sna_output->mode_output;
DisplayModePtr Modes = NULL;
int i;
@ -1911,15 +1968,15 @@ sna_output_get_modes(xf86OutputPtr output)
sna_output_attach_edid(output);
/* modes should already be available */
for (i = 0; i < koutput->count_modes; i++) {
for (i = 0; i < sna_output->num_modes; i++) {
DisplayModePtr Mode;
Mode = calloc(1, sizeof(DisplayModeRec));
if (Mode) {
mode_from_kmode(output->scrn, &koutput->modes[i], Mode);
Modes = xf86ModesAdd(Modes, Mode);
}
if (Mode)
Modes = xf86ModesAdd(Modes,
mode_from_kmode(output->scrn,
&sna_output->modes[i],
Mode));
}
/*
@ -1929,16 +1986,16 @@ sna_output_get_modes(xf86OutputPtr output)
* If it is incorrect, please fix me.
*/
sna_output->has_panel_limits = false;
if (is_panel(koutput->connector_type)) {
if (sna_output->is_panel) {
sna_output->panel_hdisplay = sna_output->panel_vdisplay = 0;
for (i = 0; i < koutput->count_modes; i++) {
drmModeModeInfo *mode_ptr;
for (i = 0; i < sna_output->num_modes; i++) {
struct drm_mode_modeinfo *m;
mode_ptr = &koutput->modes[i];
if (mode_ptr->hdisplay > sna_output->panel_hdisplay)
sna_output->panel_hdisplay = mode_ptr->hdisplay;
if (mode_ptr->vdisplay > sna_output->panel_vdisplay)
sna_output->panel_vdisplay = mode_ptr->vdisplay;
m = &sna_output->modes[i];
if (m->hdisplay > sna_output->panel_hdisplay)
sna_output->panel_hdisplay = m->hdisplay;
if (m->vdisplay > sna_output->panel_vdisplay)
sna_output->panel_vdisplay = m->vdisplay;
}
sna_output->has_panel_limits =
sna_output->panel_hdisplay &&
@ -1959,14 +2016,14 @@ sna_output_destroy(xf86OutputPtr output)
if (sna_output == NULL)
return;
free(sna_output->edid_raw);
for (i = 0; i < sna_output->num_props; i++) {
drmModeFreeProperty(sna_output->props[i].mode_prop);
drmModeFreeProperty(sna_output->props[i].kprop);
free(sna_output->props[i].atoms);
}
free(sna_output->props);
drmModeFreeConnector(sna_output->mode_output);
sna_output->mode_output = NULL;
free(sna_output->prop_ids);
free(sna_output->prop_values);
free(sna_output->backlight_iface);
@ -2000,52 +2057,35 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
{
struct sna *sna = to_sna(output->scrn);
struct sna_output *sna_output = output->driver_private;
drmModeConnectorPtr koutput = sna_output->mode_output;
int i;
DBG(("%s: dpms=%d\n", __FUNCTION__, dpms));
if (dpms != DPMSModeOn)
kgem_submit(&sna->kgem);
for (i = 0; i < koutput->count_props; i++) {
struct drm_mode_get_property prop;
/* Record the value of the backlight before turning
* off the display, and reset if after turning it on.
* Order is important as the kernel may record and also
* reset the backlight across DPMS. Hence we need to
* record the value before the kernel modifies it
* and reapply it afterwards.
*/
if (dpms == DPMSModeOff)
sna_output_dpms_backlight(output,
sna_output->dpms_mode,
dpms);
VG_CLEAR(prop);
prop.prop_id = koutput->props[i];
prop.count_values = 0;
prop.count_enum_blobs = 0;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
continue;
drmModeConnectorSetProperty(sna->kgem.fd,
sna_output->id,
sna_output->dpms_id,
dpms);
if (strcmp(prop.name, "DPMS"))
continue;
if (dpms != DPMSModeOff)
sna_output_dpms_backlight(output,
sna_output->dpms_mode,
dpms);
/* Record thevalue of the backlight before turning
* off the display, and reset if after turnging it on.
* Order is important as the kernel may record and also
* reset the backlight across DPMS. Hence we need to
* record the value before the kernel modifies it
* and reapply it afterwards.
*/
if (dpms == DPMSModeOff)
sna_output_dpms_backlight(output,
sna_output->dpms_mode,
dpms);
drmModeConnectorSetProperty(sna->kgem.fd,
sna_output->id,
prop.prop_id,
dpms);
if (dpms != DPMSModeOff)
sna_output_dpms_backlight(output,
sna_output->dpms_mode,
dpms);
sna_output->dpms_mode = dpms;
break;
}
sna_output->dpms_mode = dpms;
}
static bool
@ -2102,71 +2142,60 @@ sna_output_create_resources(xf86OutputPtr output)
{
struct sna *sna = to_sna(output->scrn);
struct sna_output *sna_output = output->driver_private;
drmModeConnectorPtr mode_output = sna_output->mode_output;
int i, j, err;
sna_output->props = calloc(mode_output->count_props,
sizeof(struct sna_property));
sna_output->props = calloc(sna_output->num_props,
sizeof(struct sna_property));
if (!sna_output->props)
return;
sna_output->num_props = 0;
for (i = j = 0; i < mode_output->count_props; i++) {
drmModePropertyPtr drmmode_prop;
for (i = 0; i < sna_output->num_props; i++) {
struct sna_property *p = &sna_output->props[i];
drmmode_prop = drmModeGetProperty(sna->kgem.fd,
mode_output->props[i]);
if (sna_property_ignore(drmmode_prop)) {
drmModeFreeProperty(drmmode_prop);
p->kprop = drmModeGetProperty(sna->kgem.fd,
sna_output->prop_ids[i]);
if (sna_property_ignore(p->kprop)) {
drmModeFreeProperty(p->kprop);
p->kprop = NULL;
continue;
}
sna_output->props[j].mode_prop = drmmode_prop;
sna_output->props[j].value = mode_output->prop_values[i];
j++;
}
sna_output->num_props = j;
for (i = 0; i < sna_output->num_props; i++) {
struct sna_property *p = &sna_output->props[i];
drmModePropertyPtr drmmode_prop = p->mode_prop;
if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
p->num_atoms = 1;
p->atoms = calloc(p->num_atoms, sizeof(Atom));
if (!p->atoms)
continue;
sna_output_create_ranged_atom(output, &p->atoms[0],
drmmode_prop->name,
drmmode_prop->values[0],
drmmode_prop->values[1],
p->value,
drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
p->kprop->name,
p->kprop->values[0],
p->kprop->values[1],
sna_output->prop_values[i],
p->kprop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
p->num_atoms = drmmode_prop->count_enums + 1;
} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
p->num_atoms = p->kprop->count_enums + 1;
p->atoms = calloc(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[0] = MakeAtom(p->kprop->name, strlen(p->kprop->name), TRUE);
for (j = 1; j <= p->kprop->count_enums; j++) {
struct drm_mode_property_enum *e = &p->kprop->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->kprop->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 == p->value)
for (j = 0; j < p->kprop->count_enums; j++)
if (p->kprop->enums[j].value == sna_output->prop_values[i])
break;
/* there's always a matching value */
err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
@ -2184,22 +2213,22 @@ sna_output_create_resources(xf86OutputPtr output)
* backlight_range.
*/
sna_output_create_ranged_atom(output, &backlight_atom,
BACKLIGHT_NAME, 0,
sna_output->backlight_max,
sna_output->backlight_active_level,
FALSE);
BACKLIGHT_NAME, 0,
sna_output->backlight_max,
sna_output->backlight_active_level,
FALSE);
sna_output_create_ranged_atom(output,
&backlight_deprecated_atom,
BACKLIGHT_DEPRECATED_NAME, 0,
sna_output->backlight_max,
sna_output->backlight_active_level,
FALSE);
&backlight_deprecated_atom,
BACKLIGHT_DEPRECATED_NAME, 0,
sna_output->backlight_max,
sna_output->backlight_active_level,
FALSE);
}
}
static Bool
sna_output_set_property(xf86OutputPtr output, Atom property,
RRPropertyValuePtr value)
RRPropertyValuePtr value)
{
struct sna *sna = to_sna(output->scrn);
struct sna_output *sna_output = output->driver_private;
@ -2227,10 +2256,10 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
for (i = 0; i < sna_output->num_props; i++) {
struct sna_property *p = &sna_output->props[i];
if (p->atoms[0] != property)
if (p->atoms == NULL || p->atoms[0] != property)
continue;
if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
if (p->kprop->flags & DRM_MODE_PROP_RANGE) {
uint32_t val;
if (value->type != XA_INTEGER || value->format != 32 ||
@ -2239,9 +2268,9 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
val = *(uint32_t *)value->data;
drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
p->mode_prop->prop_id, (uint64_t)val);
p->kprop->prop_id, (uint64_t)val);
return TRUE;
} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
} else if (p->kprop->flags & DRM_MODE_PROP_ENUM) {
Atom atom;
const char *name;
int j;
@ -2254,10 +2283,10 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
return FALSE;
/* 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)) {
for (j = 0; j < p->kprop->count_enums; j++) {
if (!strcmp(p->kprop->enums[j].name, name)) {
drmModeConnectorSetProperty(sna->kgem.fd, sna_output->id,
p->mode_prop->prop_id, p->mode_prop->enums[j].value);
p->kprop->prop_id, p->kprop->enums[j].value);
return TRUE;
}
}
@ -2317,8 +2346,7 @@ static const xf86OutputFuncsRec sna_output_funcs = {
.destroy = sna_output_destroy
};
static const int subpixel_conv_table[7] = {
0,
static const int subpixel_conv_table[] = {
SubPixelUnknown,
SubPixelHorizontalRGB,
SubPixelHorizontalBGR,
@ -2410,29 +2438,60 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
{
struct sna *sna = to_sna(scrn);
xf86OutputPtr output;
drmModeConnectorPtr koutput;
struct drm_mode_get_connector conn;
struct drm_mode_get_encoder enc;
struct drm_mode_modeinfo dummy;
struct sna_output *sna_output;
const char *output_name;
char name[32];
bool ret = false;
int i;
koutput = drmModeGetConnector(sna->kgem.fd,
mode->kmode->connectors[num]);
if (!koutput)
VG_CLEAR(conn);
VG_CLEAR(enc);
conn.connector_id = mode->kmode->connectors[num];
conn.count_props = 0;
conn.count_modes = 1; /* skip detect */
conn.modes_ptr = (uintptr_t)&dummy;
conn.count_encoders = 1;
conn.encoders_ptr = (uintptr_t)&enc.encoder_id;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return false;
VG_CLEAR(enc);
enc.encoder_id = koutput->encoders[0];
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc))
goto cleanup_connector;
if (conn.count_encoders != 1)
return false;
if (koutput->connector_type < ARRAY_SIZE(output_names))
output_name = output_names[koutput->connector_type];
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETENCODER, &enc))
return false;
sna_output = calloc(sizeof(struct sna_output), 1);
if (!sna_output)
return false;
sna_output->num_props = conn.count_props;
sna_output->prop_ids = malloc(sizeof(uint32_t)*conn.count_props);
sna_output->prop_values = malloc(sizeof(uint64_t)*conn.count_props);
conn.count_modes = 1;
conn.modes_ptr = (uintptr_t)&dummy;
conn.count_props = sna_output->num_props;
conn.props_ptr = (uintptr_t)sna_output->prop_ids;
conn.prop_values_ptr = (uintptr_t)sna_output->prop_values;
if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return false;
/* statically constructed property list */
assert(sna_output->num_props == conn.count_props);
if (conn.connector_type < ARRAY_SIZE(output_names))
output_name = output_names[conn.connector_type];
else
output_name = "UNKNOWN";
snprintf(name, 32, "%s%d", output_name, koutput->connector_type_id);
snprintf(name, 32, "%s%d", output_name, conn.connector_type_id);
if (xf86IsEntityShared(scrn->entityList[0])) {
const char *str;
@ -2440,7 +2499,7 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
str = xf86GetOptValString(sna->Options, OPTION_ZAPHOD);
if (str && !sna_zaphod_match(str, name)) {
ret = true;
goto cleanup_connector;
goto cleanup;
}
if ((enc.possible_crtcs & (1 << scrn->confScreen->device->screen)) == 0) {
@ -2449,7 +2508,7 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
"%s is an invalid output for screen (pipe) %d\n",
name, scrn->confScreen->device->screen);
}
goto cleanup_connector;
goto cleanup;
}
enc.possible_crtcs = 1;
@ -2464,20 +2523,20 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
* explicitly ignored the output.
*/
ret = output_ignored(scrn, name);
goto cleanup_connector;
goto cleanup;
}
sna_output = calloc(sizeof(struct sna_output), 1);
if (!sna_output)
goto cleanup_output;
sna_output->id = conn.connector_id;
sna_output->is_panel = is_panel(conn.connector_type);
sna_output->edid_idx = find_property(sna, sna_output, "EDID");
sna_output->dpms_id = find_property_id(sna, sna_output, "DPMS");
sna_output->id = mode->kmode->connectors[num];
sna_output->mode_output = koutput;
output->mm_width = conn.mm_width;
output->mm_height = conn.mm_height;
output->mm_width = koutput->mmWidth;
output->mm_height = koutput->mmHeight;
output->subpixel_order = subpixel_conv_table[koutput->subpixel];
if (conn.subpixel >= ARRAY_SIZE(subpixel_conv_table))
conn.subpixel = 0;
output->subpixel_order = subpixel_conv_table[conn.subpixel];
output->driver_private = sna_output;
for (i = 0; i < mode->kmode->count_encoders; i++) {
@ -2487,23 +2546,25 @@ sna_output_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num)
}
}
if (is_panel(koutput->connector_type))
if (sna_output->is_panel)
sna_output_backlight_init(output);
output->possible_crtcs = enc.possible_crtcs;
output->possible_clones = enc.possible_clones;
output->interlaceAllowed = TRUE;
DBG(("%s: created output '%s' %d [%d] (possible crtc:%x, possible clones:%x)\n",
__FUNCTION__, name, num, to_connector_id(output),
output->possible_crtcs, output->possible_clones));
DBG(("%s: created output '%s' %d [%d] (possible crtc:%x, possible clones:%x), edid=%d, dpms=%d\n",
__FUNCTION__, name, num, sna_output->id,
(uint32_t)output->possible_crtcs,
(uint32_t)output->possible_clones,
sna_output->edid_idx, sna_output->dpms_id));
return true;
cleanup_output:
xf86OutputDestroy(output);
cleanup_connector:
drmModeFreeConnector(koutput);
cleanup:
free(sna_output->prop_ids);
free(sna_output->prop_values);
free(sna_output);
return ret;
}
@ -2533,7 +2594,8 @@ sna_mode_compute_possible_clones(ScrnInfoPtr scrn)
output->possible_clones = clones;
DBG(("%s: updated output '%s' %d [%d] (possible crtc:%x, possible clones:%x)\n",
__FUNCTION__, output->name, i, to_connector_id(output),
output->possible_crtcs, output->possible_clones));
(uint32_t)output->possible_crtcs,
(uint32_t)output->possible_clones));
}
}