diff options
Diffstat (limited to 'linux-core')
| -rw-r--r-- | linux-core/drm_crtc.c | 102 | ||||
| -rw-r--r-- | linux-core/drm_crtc.h | 22 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 1 | ||||
| -rw-r--r-- | linux-core/intel_crt.c | 15 | ||||
| -rw-r--r-- | linux-core/intel_lvds.c | 1 | ||||
| -rw-r--r-- | linux-core/intel_sdvo.c | 7 | 
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);  }  | 
