From f99dea7db00dd46aa96eaed3a61dff9c956fd86f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Dec 2007 15:56:48 +1000 Subject: modesetting: fixup property setting and add connector property --- libdrm/xf86drmMode.c | 18 +++++++++ libdrm/xf86drmMode.h | 2 + linux-core/drm_crtc.c | 102 +++++++++++++++++++++++++++++++++++++++++------- linux-core/drm_crtc.h | 22 ++++++++++- linux-core/drm_drv.c | 1 + linux-core/intel_crt.c | 15 +++++++ linux-core/intel_lvds.c | 1 + linux-core/intel_sdvo.c | 7 ++++ shared-core/drm.h | 2 +- tests/mode/modetest.c | 31 +++++++++++++-- 10 files changed, 181 insertions(+), 20 deletions(-) diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index 7e2683ea..726c55ab 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -214,6 +214,8 @@ int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth, int drmModeRmFB(int fd, uint32_t bufferId) { return ioctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId); + + } drmModeFBPtr drmModeGetFB(int fd, uint32_t buf) @@ -511,3 +513,19 @@ void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr) drmFree(ptr->data); drmFree(ptr); } + +int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, + uint64_t value) +{ + struct drm_mode_output_set_property osp; + int ret; + + osp.output_id = output_id; + osp.prop_id = property_id; + osp.value = value; + + if (ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)) + return ret; + + return 0; +} diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h index 6fcf6a19..05b61bc8 100644 --- a/libdrm/xf86drmMode.h +++ b/libdrm/xf86drmMode.h @@ -223,3 +223,5 @@ extern void drmModeFreeProperty(drmModePropertyPtr ptr); extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id); extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr); +extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id, + uint64_t value); diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 871f8994..e1b37c0b 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -33,6 +33,33 @@ #include "drmP.h" #include "drm_crtc.h" +struct drm_prop_enum_list { + int type; + char *name; +}; + +static struct drm_prop_enum_list drm_dpms_enum_list[] = +{ { DPMSModeOn, "On" }, + { DPMSModeStandby, "Standby" }, + { DPMSModeSuspend, "Suspend" }, + { DPMSModeOff, "Off" } +}; +static struct drm_prop_enum_list drm_conn_enum_list[] = +{ { ConnectorVGA, "VGA" }, + { ConnectorDVII, "DVI-I" }, + { ConnectorDVID, "DVI-D" }, + { ConnectorDVIA, "DVI-A" }, + { ConnectorComposite, "Composite" }, + { ConnectorSVIDEO, "SVIDEO" }, + { ConnectorLVDS, "LVDS" }, + { ConnectorComponent, "Component" }, + { Connector9PinDIN, "9-pin DIN" }, + { ConnectorDisplayPort, "DisplayPort" }, + { ConnectorHDMIA, "HDMI Type A" }, + { ConnectorHDMIB, "HDMI Type B" }, +}; + + /** * drm_idr_get - allocate a new identifier * @dev: DRM device @@ -709,6 +736,34 @@ void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) } EXPORT_SYMBOL(drm_mode_destroy); +static int drm_mode_create_standard_output_properties(struct drm_device *dev) +{ + int i; + + dev->mode_config.edid_property = + drm_property_create(dev, DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, + "EDID", 0); + + dev->mode_config.dpms_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM, "DPMS", 4); + + for (i = 0; i < ARRAY_SIZE(drm_dpms_enum_list); i++) + drm_property_add_enum(dev->mode_config.dpms_property, i, drm_dpms_enum_list[i].type, drm_dpms_enum_list[i].name); + + dev->mode_config.connector_type_property = + drm_property_create(dev, DRM_MODE_PROP_ENUM | DRM_MODE_PROP_IMMUTABLE, + "Connector Type", 10); + for (i = 0; i < ARRAY_SIZE(drm_conn_enum_list); i++) + drm_property_add_enum(dev->mode_config.connector_type_property, i, drm_conn_enum_list[i].type, drm_conn_enum_list[i].name); + + dev->mode_config.connector_num_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE | DRM_MODE_PROP_IMMUTABLE, + "Connector ID", 2); + dev->mode_config.connector_num_property->values[0] = 0; + dev->mode_config.connector_num_property->values[1] = 20; + return 0; +} + /** * drm_mode_config_init - initialize DRM mode_configuration structure * @dev: DRM device @@ -728,17 +783,8 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); idr_init(&dev->mode_config.crtc_idr); - dev->mode_config.edid_property = drm_property_create(dev, - DRM_MODE_PROP_BLOB | DRM_MODE_PROP_IMMUTABLE, - "EDID", 0); - - dev->mode_config.dpms_property = drm_property_create(dev, - DRM_MODE_PROP_ENUM, - "DPMS", 4); - drm_property_add_enum(dev->mode_config.dpms_property, 0, DPMSModeOn, "On"); - drm_property_add_enum(dev->mode_config.dpms_property, 1, DPMSModeStandby, "Standby"); - drm_property_add_enum(dev->mode_config.dpms_property, 2, DPMSModeSuspend, "Suspend"); - drm_property_add_enum(dev->mode_config.dpms_property, 3, DPMSModeOff, "Off"); + + drm_mode_create_standard_output_properties(dev); } EXPORT_SYMBOL(drm_mode_config_init); @@ -2160,15 +2206,16 @@ int drm_mode_output_update_edid_property(struct drm_output *output, unsigned cha EXPORT_SYMBOL(drm_mode_output_update_edid_property); int drm_mode_output_property_set_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) + void *data, struct drm_file *file_priv) { struct drm_mode_output_set_property *out_resp = data; + struct drm_property *property; struct drm_output *output; int ret = -EINVAL; int i; mutex_lock(&dev->mode_config.mutex); - output= idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); + output = idr_find(&dev->mode_config.crtc_idr, out_resp->output_id); if (!output || (output->id != out_resp->output_id)) { goto out; } @@ -2182,8 +2229,35 @@ int drm_mode_output_property_set_ioctl(struct drm_device *dev, goto out; } + property = idr_find(&dev->mode_config.crtc_idr, out_resp->prop_id); + if (!property || (property->id != out_resp->prop_id)) { + goto out; + } + + if (property->flags & DRM_MODE_PROP_IMMUTABLE) + goto out; + + if (property->flags & DRM_MODE_PROP_RANGE) { + if (out_resp->value < property->values[0]) + goto out; + + if (out_resp->value > property->values[1]) + goto out; + } else { + int found = 0; + for (i = 0; i < property->num_values; i++) { + if (property->values[i] == out_resp->value) { + found = 1; + break; + } + } + if (!found) { + goto out; + } + } + if (output->funcs->set_property) - ret = output->funcs->set_property(output, out_resp->prop_id, out_resp->value); + ret = output->funcs->set_property(output, property, out_resp->value); out: mutex_unlock(&dev->mode_config.mutex); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index ad5ecc5d..6b6e1dbf 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -142,11 +142,26 @@ struct drm_display_mode { #define V_CLKDIV2 (1<<13) #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ + #define DPMSModeOn 0 #define DPMSModeStandby 1 #define DPMSModeSuspend 2 #define DPMSModeOff 3 +#define ConnectorUnknown 0 +#define ConnectorVGA 1 +#define ConnectorDVII 2 +#define ConnectorDVID 3 +#define ConnectorDVIA 4 +#define ConnectorComposite 5 +#define ConnectorSVIDEO 6 +#define ConnectorLVDS 7 +#define ConnectorComponent 8 +#define Connector9PinDIN 9 +#define ConnectorDisplayPort 10 +#define ConnectorHDMIA 11 +#define ConnectorHDMIB 12 + enum drm_output_status { output_status_connected = 1, output_status_disconnected = 2, @@ -396,7 +411,8 @@ struct drm_output_funcs { enum drm_output_status (*detect)(struct drm_output *output); int (*get_modes)(struct drm_output *output); /* JJJ: type checking for properties via property value type */ - bool (*set_property)(struct drm_output *output, int prop, uint64_t val); + bool (*set_property)(struct drm_output *output, struct drm_property *property, + uint64_t val); void (*cleanup)(struct drm_output *output); }; @@ -504,6 +520,8 @@ struct drm_mode_config { struct list_head property_blob_list; struct drm_property *edid_property; struct drm_property *dpms_property; + struct drm_property *connector_type_property; + struct drm_property *connector_num_property; }; struct drm_output *drm_output_create(struct drm_device *dev, @@ -597,5 +615,7 @@ extern int drm_mode_getproperty_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getblob_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_output_property_set_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); #endif /* __DRM_CRTC_H__ */ diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index f8665be7..98fb9ac8 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -125,6 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_output_property_set_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_ROOT_ONLY), diff --git a/linux-core/intel_crt.c b/linux-core/intel_crt.c index 2ab6a27b..722a62c8 100644 --- a/linux-core/intel_crt.c +++ b/linux-core/intel_crt.c @@ -204,6 +204,19 @@ static int intel_crt_get_modes(struct drm_output *output) return intel_ddc_get_modes(output); } +static bool intel_crt_set_property(struct drm_output *output, + struct drm_property *property, + uint64_t value) +{ + struct drm_device *dev = output->dev; + int i; + + if (property == dev->mode_config.dpms_property) { + intel_crt_dpms(output, (uint32_t)(value & 0xf)); + } + return true; +} + /* * Routines for controlling stuff on the analog port */ @@ -219,6 +232,7 @@ static const struct drm_output_funcs intel_crt_output_funcs = { .detect = intel_crt_detect, .get_modes = intel_crt_get_modes, .cleanup = intel_crt_destroy, + .set_property = intel_crt_set_property, }; void intel_crt_init(struct drm_device *dev) @@ -246,4 +260,5 @@ void intel_crt_init(struct drm_device *dev) output->interlace_allowed = 0; output->doublescan_allowed = 0; + drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorVGA); } diff --git a/linux-core/intel_lvds.c b/linux-core/intel_lvds.c index e3e4b38a..94232b94 100644 --- a/linux-core/intel_lvds.c +++ b/linux-core/intel_lvds.c @@ -499,6 +499,7 @@ void intel_lvds_init(struct drm_device *dev) #endif out: + drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorLVDS); return; failed: diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 51fe43cb..0da57faa 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -950,6 +950,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; struct intel_i2c_chan *i2cbus = NULL; + int connector_type; u8 ch[0x40]; int i; char name[DRM_OUTPUT_LEN]; @@ -1019,24 +1020,28 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="RGB"; + connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="RGB"; + connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; + connector_type = ConnectorDVID; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; + connector_type = ConnectorDVID; } else { @@ -1084,4 +1089,6 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); intel_output->ddc_bus = i2cbus; + + drm_output_attach_property(output, dev->mode_config.connector_type_property, connector_type); } diff --git a/shared-core/drm.h b/shared-core/drm.h index df43802f..f13e36c9 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1118,7 +1118,7 @@ struct drm_mode_mode_cmd { #define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int) #define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd) -#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_set_output_property) +#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xA7, struct drm_mode_output_set_property) #define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xA8, struct drm_mode_get_blob) #define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) #define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd) diff --git a/tests/mode/modetest.c b/tests/mode/modetest.c index 4a8c6a17..f1fe64df 100644 --- a/tests/mode/modetest.c +++ b/tests/mode/modetest.c @@ -3,10 +3,13 @@ #include #include #include +#include +#include #include "xf86drm.h" #include "xf86drmMode.h" +int dpms_prop_id = 0; const char* getConnectionText(drmModeConnection conn) { switch (conn) { @@ -72,7 +75,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id) printf("\tflags: %i\n", props->flags); printf("\tvalues %d: ", props->count_values); for (j = 0; j < props->count_values; j++) - printf("%d ", props->values[j]); + printf("%lld ", props->values[j]); printf("\n\tenums %d: \n", props->count_enums); @@ -86,6 +89,9 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id) } } else { + if (!strncmp(props->name, "DPMS", 4)) + dpms_prop_id = props->prop_id; + for (j = 0; j < props->count_enums; j++) { printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); if (output->prop_values[i] == props->enums[j].value) @@ -96,7 +102,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id) if (props->count_enums && name) { printf("\toutput property name %s %s\n", props->name, name); } else { - printf("\toutput property id %s %i\n", props->name, output->prop_values[i]); + printf("\toutput property id %s %lli\n", props->name, output->prop_values[i]); } } @@ -109,7 +115,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id) if (mode) printMode(mode); else - printf("\t\tmode: Invalid mode %i\n", output->modes[i]); + printf("\t\tmode: Invalid mode %p\n", &output->modes[i]); } return 0; @@ -123,7 +129,7 @@ int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) printf("\ty : %i\n", crtc->y); printf("\twidth : %i\n", crtc->width); printf("\theight : %i\n", crtc->height); - printf("\tmode : %i\n", crtc->mode); + printf("\tmode : %p\n", &crtc->mode); printf("\tnum outputs : %i\n", crtc->count_outputs); printf("\toutputs : %i\n", crtc->outputs); printf("\tnum possible : %i\n", crtc->count_possibles); @@ -314,6 +320,21 @@ err: return 1; } +int testDPMS(int fd, drmModeResPtr res) +{ + int output_id; + int i; + + for (i = 0; i < res->count_outputs; i++) { + output_id = res->outputs[i]; + /* turn output off */ + drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 3); + sleep(2); + drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 0); + } + return 1; + +} int main(int argc, char **argv) { @@ -343,6 +364,8 @@ int main(int argc, char **argv) testFrameBufferAdd(fd, res); + /* try dpms test */ + testDPMS(fd, res); drmModeFreeResources(res); printf("Ok\n"); -- cgit v1.2.3