diff options
author | Russell King <rmk+cubox@arm.linux.org.uk> | 2013-10-30 10:40:49 +0000 |
---|---|---|
committer | Russell King <rmk@arm.linux.org.uk> | 2013-10-30 10:40:49 +0000 |
commit | 673eb696bef3105e49f27a789e3bff3662802d57 (patch) | |
tree | c41868db52554acb63e4399bd2708ed4ff462a05 | |
parent | 7ddfbda14828656da80c311caf4c7ef2a551c1d9 (diff) |
Separate out connector/output handing
There is nothing specific about the connector/output handing in
the Armada DRM driver, so move it to a separate file and make it
independent of the Armada DRM structures.
Signed-off-by: Russell King <rmk@arm.linux.org.uk>
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/armada_drm.c | 414 | ||||
-rw-r--r-- | src/common_drm.c | 418 | ||||
-rw-r--r-- | src/common_drm.h | 18 |
4 files changed, 442 insertions, 409 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b51f3cd..deded85 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ armada_drv_ladir = @moduledir@/drivers armada_drv_la_SOURCES = armada_module.c \ armada_drm.c \ armada_drm_xv.c \ + common_drm.c \ vivante.c \ vivante_accel.c \ vivante_unaccel.c \ diff --git a/src/armada_drm.c b/src/armada_drm.c index 6ae5d16..4c89f89 100644 --- a/src/armada_drm.c +++ b/src/armada_drm.c @@ -15,6 +15,7 @@ #include <armada_bufmgr.h> #include "armada_drm.h" +#include "common_drm.h" #include "xf86_OSproc.h" #include "xf86Crtc.h" #include "xf86cmap.h" @@ -46,24 +47,6 @@ const OptionInfoRec armada_drm_options[] = { { -1, NULL, OPTV_NONE, {0}, FALSE } }; - -struct armada_property { - drmModePropertyPtr mode_prop; - uint64_t value; - int natoms; - Atom *atoms; -}; - -struct armada_conn_info { - struct armada_drm_info *drm; - drmModeConnectorPtr mode_output; - drmModeEncoderPtr mode_encoder; - int id; - int dpms_mode; - int nprops; - struct armada_property *props; -}; - static void armada_drm_ModifyScreenPixmap(ScreenPtr pScreen, struct armada_drm_info *drm, int width, int height, int depth, int bpp, struct drm_armada_bo *bo) @@ -97,32 +80,6 @@ static void drmmode_ConvertToKMode(drmModeModeInfoPtr kmode, DisplayModePtr mode kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; } -static void drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, - drmModeModeInfoPtr kmode, DisplayModePtr mode) -{ - memset(mode, 0, sizeof(*mode)); - - mode->status = MODE_OK; - mode->Clock = kmode->clock; - mode->HDisplay = kmode->hdisplay; - mode->HSyncStart = kmode->hsync_start; - mode->HSyncEnd = kmode->hsync_end; - mode->HTotal = kmode->htotal; - mode->HSkew = kmode->hskew; - mode->VDisplay = kmode->vdisplay; - mode->VSyncStart = kmode->vsync_start; - mode->VSyncEnd = kmode->vsync_end; - mode->VTotal = kmode->vtotal; - mode->VScan = kmode->vscan; - mode->Flags = kmode->flags; - mode->name = strdup(kmode->name); - if (kmode->type & DRM_MODE_TYPE_DRIVER) - mode->type = M_T_DRIVER; - if (kmode->type & DRM_MODE_TYPE_PREFERRED) - mode->type |= M_T_PREFERRED; - xf86SetModeCrtc (mode, pScrn->adjustFlags); -} - static struct drm_armada_bo *armada_bo_alloc_framebuffer(ScrnInfoPtr pScrn, struct armada_drm_info *drm, int width, int height, int bpp) { @@ -152,367 +109,6 @@ static struct drm_armada_bo *armada_bo_alloc_framebuffer(ScrnInfoPtr pScrn, return bo; } -static drmModePropertyPtr armada_drm_conn_find_property( - struct armada_conn_info *conn, const char *name, uint32_t *blob) -{ - drmModeConnectorPtr koutput = conn->mode_output; - struct armada_drm_info *drm = conn->drm; - int i; - - for (i = 0; i < koutput->count_props; i++) { - drmModePropertyPtr p; - - p = drmModeGetProperty(drm->fd, koutput->props[i]); - if (!p || (blob && !(p->flags & DRM_MODE_PROP_BLOB))) - continue; - - if (!strcmp(p->name, name)) { - if (blob) - *blob = koutput->prop_values[i]; - return p; - } - - drmModeFreeProperty(p); - } - return NULL; -} - -static void armada_drm_conn_create_resources(xf86OutputPtr output) -{ - struct armada_conn_info *conn = output->driver_private; - struct armada_drm_info *drm = conn->drm; - drmModeConnectorPtr mop = conn->mode_output; - int i, j, n, err; - - conn->props = calloc(mop->count_props, sizeof *conn->props); - if (!conn->props) - return; - - for (i = n = 0; i < mop->count_props; i++) { - struct armada_property *prop = &conn->props[n]; - drmModePropertyPtr dprop; - Bool immutable; - - dprop = drmModeGetProperty(drm->fd, mop->props[i]); - if (!dprop || dprop->flags & DRM_MODE_PROP_BLOB || - !strcmp(dprop->name, "DPMS") || - !strcmp(dprop->name, "EDID")) { - drmModeFreeProperty(dprop); - continue; - } - - n++; - prop->mode_prop = dprop; - prop->value = mop->prop_values[i]; - - immutable = dprop->flags & DRM_MODE_PROP_IMMUTABLE ? - TRUE : FALSE; - - if (dprop->flags & DRM_MODE_PROP_RANGE) { - INT32 range[2]; - uint32_t value = prop->value; - - prop->natoms = 1; - prop->atoms = calloc(prop->natoms, sizeof *prop->atoms); - if (!prop->atoms) - continue; - - range[0] = dprop->values[0]; - range[1] = dprop->values[1]; - - prop->atoms[0] = MakeAtom(dprop->name, - strlen(dprop->name), TRUE); - err = RRConfigureOutputProperty(output->randr_output, - prop->atoms[0], FALSE, - TRUE, immutable, 2, - range); - if (err) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error %d\n", - err); - - err = RRChangeOutputProperty(output->randr_output, - prop->atoms[0], - XA_INTEGER, 32, - PropModeReplace, 1, - &value, FALSE, TRUE); - if (err) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error %d\n", - err); - } else if (dprop->flags & DRM_MODE_PROP_ENUM) { - int current; - - prop->natoms = dprop->count_enums + 1; - prop->atoms = calloc(prop->natoms, sizeof *prop->atoms); - if (!prop->atoms) - continue; - - current = prop->natoms; - prop->atoms[0] = MakeAtom(dprop->name, - strlen(dprop->name), TRUE); - for (j = 1; j < prop->natoms; j++) { - struct drm_mode_property_enum *e; - - e = &dprop->enums[j - 1]; - prop->atoms[j] = MakeAtom(e->name, - strlen(e->name), - TRUE); - if (prop->value == e->value) - current = j; - } - - err = RRConfigureOutputProperty(output->randr_output, - prop->atoms[0], FALSE, FALSE, - immutable, prop->natoms - 1, - (INT32 *)&prop->atoms[1]); - if (err) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", - err); - - err = RRChangeOutputProperty(output->randr_output, - prop->atoms[0], XA_ATOM, - 32, PropModeReplace, 1, - &prop->atoms[current], - FALSE, TRUE); - if (err) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "RRChangeOutputProperty error, %d\n", - err); - } - } - conn->nprops = n; -} - -static void armada_drm_conn_dpms(xf86OutputPtr output, int mode) -{ - struct armada_conn_info *conn = output->driver_private; - struct armada_drm_info *drm = conn->drm; - drmModePropertyPtr p = armada_drm_conn_find_property(conn, "DPMS", NULL); - - if (p) { - drmModeConnectorSetProperty(drm->fd, conn->id, p->prop_id, - mode); - conn->dpms_mode = mode; - drmModeFreeProperty(p); - } -} - -static xf86OutputStatus armada_drm_conn_detect(xf86OutputPtr output) -{ - struct armada_conn_info *conn = output->driver_private; - struct armada_drm_info *drm = conn->drm; - xf86OutputStatus status = XF86OutputStatusUnknown; - drmModeConnectorPtr koutput; - - koutput = drmModeGetConnector(drm->fd, conn->id); - if (!koutput) - return XF86OutputStatusUnknown; - - drmModeFreeConnector(conn->mode_output); - conn->mode_output = koutput; - - switch (koutput->connection) { - case DRM_MODE_CONNECTED: - status = XF86OutputStatusConnected; - break; - case DRM_MODE_DISCONNECTED: - status = XF86OutputStatusDisconnected; - break; - case DRM_MODE_UNKNOWNCONNECTION: - break; - } - return status; -} - -static Bool -armada_drm_conn_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) -{ - return MODE_OK; -} - -static DisplayModePtr armada_drm_conn_get_modes(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - DisplayModePtr modes = NULL; - struct armada_conn_info *conn = output->driver_private; - struct armada_drm_info *drm = conn->drm; - uint32_t blob; - drmModePropertyPtr p; - drmModePropertyBlobPtr edid = NULL; - xf86MonPtr mon; - int i; - - p = armada_drm_conn_find_property(conn, "EDID", &blob); - if (p) { - edid = drmModeGetPropertyBlob(drm->fd, blob); - drmModeFreeProperty(p); - } - - mon = xf86InterpretEDID(pScrn->scrnIndex, edid ? edid->data : NULL); - if (mon && edid->length > 128) - mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; - xf86OutputSetEDID(output, mon); - - /* modes should already be available */ - for (i = 0; i < conn->mode_output->count_modes; i++) { - DisplayModePtr mode = xnfalloc(sizeof *mode); - - drmmode_ConvertFromKMode(pScrn, &conn->mode_output->modes[i], mode); - modes = xf86ModesAdd(modes, mode); - } - - return modes; -} - -#ifdef RANDR_12_INTERFACE -static Bool armada_drm_conn_set_property(xf86OutputPtr output, Atom property, - RRPropertyValuePtr value) -{ - struct armada_conn_info *conn = output->driver_private; - struct armada_drm_info *drm = conn->drm; - int i; - - for (i = 0; i < conn->nprops; i++) { - struct armada_property *prop = &conn->props[i]; - drmModePropertyPtr dprop; - - if (prop->atoms[0] != property) - continue; - - dprop = prop->mode_prop; - if (dprop->flags & DRM_MODE_PROP_RANGE) { - if (value->type != XA_INTEGER || value->format != 32 || value->size != 1) - return FALSE; - - drmModeConnectorSetProperty(drm->fd, conn->id, - dprop->prop_id, (uint64_t)*(uint32_t *)value->data); - - return TRUE; - } else if (dprop->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, sizeof(atom)); - name = NameForAtom(atom); - if (name == NULL) - return FALSE; - - for (j = 0; j < dprop->count_enums; j++) { - if (!strcmp(dprop->enums[j].name, name)) { - drmModeConnectorSetProperty(drm->fd, conn->id, - dprop->prop_id, dprop->enums[j].value); - return TRUE; - } - } - return FALSE; - } - } - return TRUE; -} -#endif -#ifdef RANDR_13_INTERFACE -static Bool armada_drm_conn_get_property(xf86OutputPtr output, Atom property) -{ - return FALSE; -} -#endif - -static void armada_drm_conn_destroy(xf86OutputPtr output) -{ - struct armada_conn_info *conn = output->driver_private; - - drmModeFreeConnector(conn->mode_output); - drmModeFreeEncoder(conn->mode_encoder); - free(conn); - - output->driver_private = NULL; -} - -static const xf86OutputFuncsRec drm_output_funcs = { - .create_resources = armada_drm_conn_create_resources, - .dpms = armada_drm_conn_dpms, - .detect = armada_drm_conn_detect, - .mode_valid = armada_drm_conn_mode_valid, - .get_modes = armada_drm_conn_get_modes, -#ifdef RANDR_12_INTERFACE - .set_property = armada_drm_conn_set_property, -#endif -#ifdef RANDR_13_INTERFACE - .get_property = armada_drm_conn_get_property, -#endif - .destroy = armada_drm_conn_destroy, -}; - -static const char *const output_names[] = { - "None", "VGA", "DVI", "DVI", "DVI", "Composite", "TV", - "LVDS", "CTV", "DIN", "DP", "HDMI", "HDMI", -}; - -static const int subpixel_conv_table[] = { - 0, SubPixelUnknown, SubPixelHorizontalRGB, SubPixelHorizontalBGR, - SubPixelVerticalRGB, SubPixelVerticalBGR, SubPixelNone -}; - -static void -armada_drm_conn_init(ScrnInfoPtr pScrn, struct armada_drm_info *drm, - uint32_t id) -{ - drmModeConnectorPtr koutput; - drmModeEncoderPtr kencoder; - xf86OutputPtr output; - struct armada_conn_info *conn; - char name[32]; - - koutput = drmModeGetConnector(drm->fd, id); - if (!koutput) - return; - - kencoder = drmModeGetEncoder(drm->fd, koutput->encoders[0]); - if (!kencoder) { - drmModeFreeConnector(koutput); - return; - } - - snprintf(name, sizeof(name), "%s%d", - output_names[koutput->connector_type], - koutput->connector_type_id); - - output = xf86OutputCreate(pScrn, &drm_output_funcs, name); - if (!output) { - drmModeFreeEncoder(kencoder); - drmModeFreeConnector(koutput); - return; - } - - conn = calloc(1, sizeof *conn); - if (!conn) { - xf86OutputDestroy(output); - drmModeFreeEncoder(kencoder); - drmModeFreeConnector(koutput); - return; - } - - conn->drm = drm; - conn->id = id; - conn->mode_output = koutput; - conn->mode_encoder = kencoder; - - output->driver_private = conn; - output->mm_width = koutput->mmWidth; - output->mm_height = koutput->mmHeight; - output->subpixel_order = subpixel_conv_table[koutput->subpixel]; - output->possible_crtcs = kencoder->possible_crtcs; - output->possible_clones = kencoder->possible_clones; - output->interlaceAllowed = 1; /* wish there was a way to read that */ - output->doubleScanAllowed = 0; -} - /* * CRTC support */ @@ -572,11 +168,10 @@ static Bool armada_drm_crtc_apply(xf86CrtcPtr crtc, drmModeModeInfoPtr kmode) for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; - if (output->funcs != &drm_output_funcs || - output->crtc != crtc) + if (output->crtc != crtc) continue; - armada_drm_conn_dpms(output, DPMSModeOn); + output->funcs->dpms(output, DPMSModeOn); } } @@ -1347,7 +942,8 @@ static Bool armada_drm_pre_init(ScrnInfoPtr pScrn) return FALSE; for (i = 0; i < drm->mode_res->count_connectors; i++) - armada_drm_conn_init(pScrn, drm, drm->mode_res->connectors[i]); + common_drm_conn_init(pScrn, drm->fd, + drm->mode_res->connectors[i]); xf86InitialConfiguration(pScrn, TRUE); diff --git a/src/common_drm.c b/src/common_drm.c new file mode 100644 index 0000000..c1d640a --- /dev/null +++ b/src/common_drm.c @@ -0,0 +1,418 @@ +/* + * Marvell Armada DRM-based driver + * + * Written by Russell King, 2012, derived in part from the + * Intel xorg X server driver. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> +#include <xf86drm.h> +#include <xf86drmMode.h> + +#include "xf86.h" +#include "common_drm.h" +#include "xf86_OSproc.h" +#include "xf86Crtc.h" +#include "xf86cmap.h" +#include "fb.h" +#include "mibstore.h" +#include "micmap.h" +#include <xf86DDC.h> +#include <X11/extensions/dpmsconst.h> +#include <X11/Xatom.h> + +#ifdef HAVE_UDEV +#include <libudev.h> +#endif + +struct common_drm_property { + drmModePropertyPtr mode_prop; + uint64_t value; + int natoms; + Atom *atoms; +}; + +static void drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, + drmModeModeInfoPtr kmode, DisplayModePtr mode) +{ + memset(mode, 0, sizeof(*mode)); + + mode->status = MODE_OK; + mode->Clock = kmode->clock; + mode->HDisplay = kmode->hdisplay; + mode->HSyncStart = kmode->hsync_start; + mode->HSyncEnd = kmode->hsync_end; + mode->HTotal = kmode->htotal; + mode->HSkew = kmode->hskew; + mode->VDisplay = kmode->vdisplay; + mode->VSyncStart = kmode->vsync_start; + mode->VSyncEnd = kmode->vsync_end; + mode->VTotal = kmode->vtotal; + mode->VScan = kmode->vscan; + mode->Flags = kmode->flags; + mode->name = strdup(kmode->name); + if (kmode->type & DRM_MODE_TYPE_DRIVER) + mode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + mode->type |= M_T_PREFERRED; + xf86SetModeCrtc (mode, pScrn->adjustFlags); +} + +static drmModePropertyPtr common_drm_conn_find_property( + struct armada_conn_info *conn, const char *name, uint32_t *blob) +{ + drmModeConnectorPtr koutput = conn->mode_output; + int i; + + for (i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr p; + + p = drmModeGetProperty(conn->drm_fd, koutput->props[i]); + if (!p || (blob && !(p->flags & DRM_MODE_PROP_BLOB))) + continue; + + if (!strcmp(p->name, name)) { + if (blob) + *blob = koutput->prop_values[i]; + return p; + } + + drmModeFreeProperty(p); + } + return NULL; +} + +static void common_drm_conn_create_resources(xf86OutputPtr output) +{ + struct armada_conn_info *conn = output->driver_private; + drmModeConnectorPtr mop = conn->mode_output; + int i, j, n, err; + + conn->props = calloc(mop->count_props, sizeof *conn->props); + if (!conn->props) + return; + + for (i = n = 0; i < mop->count_props; i++) { + struct common_drm_property *prop = &conn->props[n]; + drmModePropertyPtr dprop; + Bool immutable; + + dprop = drmModeGetProperty(conn->drm_fd, mop->props[i]); + if (!dprop || dprop->flags & DRM_MODE_PROP_BLOB || + !strcmp(dprop->name, "DPMS") || + !strcmp(dprop->name, "EDID")) { + drmModeFreeProperty(dprop); + continue; + } + + n++; + prop->mode_prop = dprop; + prop->value = mop->prop_values[i]; + + immutable = dprop->flags & DRM_MODE_PROP_IMMUTABLE ? + TRUE : FALSE; + + if (dprop->flags & DRM_MODE_PROP_RANGE) { + INT32 range[2]; + uint32_t value = prop->value; + + prop->natoms = 1; + prop->atoms = calloc(prop->natoms, sizeof *prop->atoms); + if (!prop->atoms) + continue; + + range[0] = dprop->values[0]; + range[1] = dprop->values[1]; + + prop->atoms[0] = MakeAtom(dprop->name, + strlen(dprop->name), TRUE); + err = RRConfigureOutputProperty(output->randr_output, + prop->atoms[0], FALSE, + TRUE, immutable, 2, + range); + if (err) + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error %d\n", + err); + + err = RRChangeOutputProperty(output->randr_output, + prop->atoms[0], + XA_INTEGER, 32, + PropModeReplace, 1, + &value, FALSE, TRUE); + if (err) + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error %d\n", + err); + } else if (dprop->flags & DRM_MODE_PROP_ENUM) { + int current; + + prop->natoms = dprop->count_enums + 1; + prop->atoms = calloc(prop->natoms, sizeof *prop->atoms); + if (!prop->atoms) + continue; + + current = prop->natoms; + prop->atoms[0] = MakeAtom(dprop->name, + strlen(dprop->name), TRUE); + for (j = 1; j < prop->natoms; j++) { + struct drm_mode_property_enum *e; + + e = &dprop->enums[j - 1]; + prop->atoms[j] = MakeAtom(e->name, + strlen(e->name), + TRUE); + if (prop->value == e->value) + current = j; + } + + err = RRConfigureOutputProperty(output->randr_output, + prop->atoms[0], FALSE, FALSE, + immutable, prop->natoms - 1, + (INT32 *)&prop->atoms[1]); + if (err) + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", + err); + + err = RRChangeOutputProperty(output->randr_output, + prop->atoms[0], XA_ATOM, + 32, PropModeReplace, 1, + &prop->atoms[current], + FALSE, TRUE); + if (err) + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", + err); + } + } + conn->nprops = n; +} + +static void common_drm_conn_dpms(xf86OutputPtr output, int mode) +{ + struct armada_conn_info *conn = output->driver_private; + drmModePropertyPtr p = common_drm_conn_find_property(conn, "DPMS", NULL); + + if (p) { + drmModeConnectorSetProperty(conn->drm_fd, conn->drm_id, + p->prop_id, mode); + conn->dpms_mode = mode; + drmModeFreeProperty(p); + } +} + +static xf86OutputStatus common_drm_conn_detect(xf86OutputPtr output) +{ + struct armada_conn_info *conn = output->driver_private; + xf86OutputStatus status = XF86OutputStatusUnknown; + drmModeConnectorPtr koutput; + + koutput = drmModeGetConnector(conn->drm_fd, conn->drm_id); + if (!koutput) + return XF86OutputStatusUnknown; + + drmModeFreeConnector(conn->mode_output); + conn->mode_output = koutput; + + switch (koutput->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + break; + case DRM_MODE_UNKNOWNCONNECTION: + break; + } + return status; +} + +static Bool +common_drm_conn_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) +{ + return MODE_OK; +} + +static DisplayModePtr common_drm_conn_get_modes(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + struct armada_conn_info *conn = output->driver_private; + drmModePropertyBlobPtr edid = NULL; + DisplayModePtr modes = NULL; + drmModePropertyPtr p; + xf86MonPtr mon; + uint32_t blob; + int i; + + p = common_drm_conn_find_property(conn, "EDID", &blob); + if (p) { + edid = drmModeGetPropertyBlob(conn->drm_fd, blob); + drmModeFreeProperty(p); + } + + mon = xf86InterpretEDID(pScrn->scrnIndex, edid ? edid->data : NULL); + if (mon && edid->length > 128) + mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; + xf86OutputSetEDID(output, mon); + + /* modes should already be available */ + for (i = 0; i < conn->mode_output->count_modes; i++) { + DisplayModePtr mode = xnfalloc(sizeof *mode); + + drmmode_ConvertFromKMode(pScrn, &conn->mode_output->modes[i], mode); + modes = xf86ModesAdd(modes, mode); + } + + return modes; +} + +#ifdef RANDR_12_INTERFACE +static Bool common_drm_conn_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + struct armada_conn_info *conn = output->driver_private; + int i; + + for (i = 0; i < conn->nprops; i++) { + struct common_drm_property *prop = &conn->props[i]; + drmModePropertyPtr dprop; + + if (prop->atoms[0] != property) + continue; + + dprop = prop->mode_prop; + if (dprop->flags & DRM_MODE_PROP_RANGE) { + if (value->type != XA_INTEGER || value->format != 32 || value->size != 1) + return FALSE; + + drmModeConnectorSetProperty(conn->drm_fd, conn->drm_id, + dprop->prop_id, (uint64_t)*(uint32_t *)value->data); + + return TRUE; + } else if (dprop->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, sizeof(atom)); + name = NameForAtom(atom); + if (name == NULL) + return FALSE; + + for (j = 0; j < dprop->count_enums; j++) { + if (!strcmp(dprop->enums[j].name, name)) { + drmModeConnectorSetProperty(conn->drm_fd, + conn->drm_id, dprop->prop_id, + dprop->enums[j].value); + return TRUE; + } + } + return FALSE; + } + } + return TRUE; +} +#endif +#ifdef RANDR_13_INTERFACE +static Bool common_drm_conn_get_property(xf86OutputPtr output, Atom property) +{ + return FALSE; +} +#endif + +static void common_drm_conn_destroy(xf86OutputPtr output) +{ + struct armada_conn_info *conn = output->driver_private; + + drmModeFreeConnector(conn->mode_output); + drmModeFreeEncoder(conn->mode_encoder); + free(conn); + + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec drm_output_funcs = { + .create_resources = common_drm_conn_create_resources, + .dpms = common_drm_conn_dpms, + .detect = common_drm_conn_detect, + .mode_valid = common_drm_conn_mode_valid, + .get_modes = common_drm_conn_get_modes, +#ifdef RANDR_12_INTERFACE + .set_property = common_drm_conn_set_property, +#endif +#ifdef RANDR_13_INTERFACE + .get_property = common_drm_conn_get_property, +#endif + .destroy = common_drm_conn_destroy, +}; + +static const char *const output_names[] = { + "None", "VGA", "DVI", "DVI", "DVI", "Composite", "TV", + "LVDS", "CTV", "DIN", "DP", "HDMI", "HDMI", +}; + +static const int subpixel_conv_table[] = { + 0, SubPixelUnknown, SubPixelHorizontalRGB, SubPixelHorizontalBGR, + SubPixelVerticalRGB, SubPixelVerticalBGR, SubPixelNone +}; + +void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id) +{ + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + xf86OutputPtr output; + struct armada_conn_info *conn; + char name[32]; + + koutput = drmModeGetConnector(fd, id); + if (!koutput) + return; + + kencoder = drmModeGetEncoder(fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); + return; + } + + snprintf(name, sizeof(name), "%s%d", + output_names[koutput->connector_type], + koutput->connector_type_id); + + output = xf86OutputCreate(pScrn, &drm_output_funcs, name); + if (!output) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + conn = calloc(1, sizeof *conn); + if (!conn) { + xf86OutputDestroy(output); + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + conn->drm_fd = fd; + conn->drm_id = id; + conn->mode_output = koutput; + conn->mode_encoder = kencoder; + + output->driver_private = conn; + output->mm_width = koutput->mmWidth; + output->mm_height = koutput->mmHeight; + output->subpixel_order = subpixel_conv_table[koutput->subpixel]; + output->possible_crtcs = kencoder->possible_crtcs; + output->possible_clones = kencoder->possible_clones; + output->interlaceAllowed = 1; /* wish there was a way to read that */ + output->doubleScanAllowed = 0; +} diff --git a/src/common_drm.h b/src/common_drm.h new file mode 100644 index 0000000..a23cd6e --- /dev/null +++ b/src/common_drm.h @@ -0,0 +1,18 @@ +#ifndef COMMON_DRM_H +#define COMMON_DRM_H + +struct common_drm_property; + +struct armada_conn_info { + int drm_fd; + int drm_id; + int dpms_mode; + int nprops; + struct common_drm_property *props; + drmModeConnectorPtr mode_output; + drmModeEncoderPtr mode_encoder; +}; + +void common_drm_conn_init(ScrnInfoPtr pScrn, int fd, uint32_t id); + +#endif |