summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_crtc.c102
-rw-r--r--linux-core/drm_crtc.h22
-rw-r--r--linux-core/drm_drv.c1
-rw-r--r--linux-core/intel_crt.c15
-rw-r--r--linux-core/intel_lvds.c1
-rw-r--r--linux-core/intel_sdvo.c7
6 files changed, 133 insertions, 15 deletions
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);
}