Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
0003  * Copyright (c) 2007, 2010 Intel Corporation
0004  *   Jesse Barnes <jesse.barnes@intel.com>
0005  *
0006  * Permission is hereby granted, free of charge, to any person obtaining a
0007  * copy of this software and associated documentation files (the "Software"),
0008  * to deal in the Software without restriction, including without limitation
0009  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010  * and/or sell copies of the Software, and to permit persons to whom the
0011  * Software is furnished to do so, subject to the following conditions:
0012  *
0013  * The above copyright notice and this permission notice (including the next
0014  * paragraph) shall be included in all copies or substantial portions of the
0015  * Software.
0016  *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0018  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0020  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0021  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0022  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0023  * DEALINGS IN THE SOFTWARE.
0024  */
0025 
0026 #include <linux/i2c.h>
0027 #include <linux/slab.h>
0028 
0029 #include <drm/drm_atomic_helper.h>
0030 #include <drm/drm_edid.h>
0031 
0032 #include "i915_drv.h"
0033 #include "intel_backlight.h"
0034 #include "intel_connector.h"
0035 #include "intel_display_debugfs.h"
0036 #include "intel_display_types.h"
0037 #include "intel_hdcp.h"
0038 #include "intel_panel.h"
0039 
0040 int intel_connector_init(struct intel_connector *connector)
0041 {
0042     struct intel_digital_connector_state *conn_state;
0043 
0044     /*
0045      * Allocate enough memory to hold intel_digital_connector_state,
0046      * This might be a few bytes too many, but for connectors that don't
0047      * need it we'll free the state and allocate a smaller one on the first
0048      * successful commit anyway.
0049      */
0050     conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
0051     if (!conn_state)
0052         return -ENOMEM;
0053 
0054     __drm_atomic_helper_connector_reset(&connector->base,
0055                         &conn_state->base);
0056 
0057     INIT_LIST_HEAD(&connector->panel.fixed_modes);
0058 
0059     return 0;
0060 }
0061 
0062 struct intel_connector *intel_connector_alloc(void)
0063 {
0064     struct intel_connector *connector;
0065 
0066     connector = kzalloc(sizeof(*connector), GFP_KERNEL);
0067     if (!connector)
0068         return NULL;
0069 
0070     if (intel_connector_init(connector) < 0) {
0071         kfree(connector);
0072         return NULL;
0073     }
0074 
0075     return connector;
0076 }
0077 
0078 /*
0079  * Free the bits allocated by intel_connector_alloc.
0080  * This should only be used after intel_connector_alloc has returned
0081  * successfully, and before drm_connector_init returns successfully.
0082  * Otherwise the destroy callbacks for the connector and the state should
0083  * take care of proper cleanup/free (see intel_connector_destroy).
0084  */
0085 void intel_connector_free(struct intel_connector *connector)
0086 {
0087     kfree(to_intel_digital_connector_state(connector->base.state));
0088     kfree(connector);
0089 }
0090 
0091 /*
0092  * Connector type independent destroy hook for drm_connector_funcs.
0093  */
0094 void intel_connector_destroy(struct drm_connector *connector)
0095 {
0096     struct intel_connector *intel_connector = to_intel_connector(connector);
0097 
0098     kfree(intel_connector->detect_edid);
0099 
0100     intel_hdcp_cleanup(intel_connector);
0101 
0102     if (!IS_ERR_OR_NULL(intel_connector->edid))
0103         kfree(intel_connector->edid);
0104 
0105     intel_panel_fini(intel_connector);
0106 
0107     drm_connector_cleanup(connector);
0108 
0109     if (intel_connector->port)
0110         drm_dp_mst_put_port_malloc(intel_connector->port);
0111 
0112     kfree(connector);
0113 }
0114 
0115 int intel_connector_register(struct drm_connector *connector)
0116 {
0117     struct intel_connector *intel_connector = to_intel_connector(connector);
0118     int ret;
0119 
0120     ret = intel_backlight_device_register(intel_connector);
0121     if (ret)
0122         goto err;
0123 
0124     if (i915_inject_probe_failure(to_i915(connector->dev))) {
0125         ret = -EFAULT;
0126         goto err_backlight;
0127     }
0128 
0129     intel_connector_debugfs_add(intel_connector);
0130 
0131     return 0;
0132 
0133 err_backlight:
0134     intel_backlight_device_unregister(intel_connector);
0135 err:
0136     return ret;
0137 }
0138 
0139 void intel_connector_unregister(struct drm_connector *connector)
0140 {
0141     struct intel_connector *intel_connector = to_intel_connector(connector);
0142 
0143     intel_backlight_device_unregister(intel_connector);
0144 }
0145 
0146 void intel_connector_attach_encoder(struct intel_connector *connector,
0147                     struct intel_encoder *encoder)
0148 {
0149     connector->encoder = encoder;
0150     drm_connector_attach_encoder(&connector->base, &encoder->base);
0151 }
0152 
0153 /*
0154  * Simple connector->get_hw_state implementation for encoders that support only
0155  * one connector and no cloning and hence the encoder state determines the state
0156  * of the connector.
0157  */
0158 bool intel_connector_get_hw_state(struct intel_connector *connector)
0159 {
0160     enum pipe pipe = 0;
0161     struct intel_encoder *encoder = intel_attached_encoder(connector);
0162 
0163     return encoder->get_hw_state(encoder, &pipe);
0164 }
0165 
0166 enum pipe intel_connector_get_pipe(struct intel_connector *connector)
0167 {
0168     struct drm_device *dev = connector->base.dev;
0169 
0170     drm_WARN_ON(dev,
0171             !drm_modeset_is_locked(&dev->mode_config.connection_mutex));
0172 
0173     if (!connector->base.state->crtc)
0174         return INVALID_PIPE;
0175 
0176     return to_intel_crtc(connector->base.state->crtc)->pipe;
0177 }
0178 
0179 /**
0180  * intel_connector_update_modes - update connector from edid
0181  * @connector: DRM connector device to use
0182  * @edid: previously read EDID information
0183  */
0184 int intel_connector_update_modes(struct drm_connector *connector,
0185                 struct edid *edid)
0186 {
0187     int ret;
0188 
0189     drm_connector_update_edid_property(connector, edid);
0190     ret = drm_add_edid_modes(connector, edid);
0191 
0192     return ret;
0193 }
0194 
0195 /**
0196  * intel_ddc_get_modes - get modelist from monitor
0197  * @connector: DRM connector device to use
0198  * @adapter: i2c adapter
0199  *
0200  * Fetch the EDID information from @connector using the DDC bus.
0201  */
0202 int intel_ddc_get_modes(struct drm_connector *connector,
0203             struct i2c_adapter *adapter)
0204 {
0205     struct edid *edid;
0206     int ret;
0207 
0208     edid = drm_get_edid(connector, adapter);
0209     if (!edid)
0210         return 0;
0211 
0212     ret = intel_connector_update_modes(connector, edid);
0213     kfree(edid);
0214 
0215     return ret;
0216 }
0217 
0218 static const struct drm_prop_enum_list force_audio_names[] = {
0219     { HDMI_AUDIO_OFF_DVI, "force-dvi" },
0220     { HDMI_AUDIO_OFF, "off" },
0221     { HDMI_AUDIO_AUTO, "auto" },
0222     { HDMI_AUDIO_ON, "on" },
0223 };
0224 
0225 void
0226 intel_attach_force_audio_property(struct drm_connector *connector)
0227 {
0228     struct drm_device *dev = connector->dev;
0229     struct drm_i915_private *dev_priv = to_i915(dev);
0230     struct drm_property *prop;
0231 
0232     prop = dev_priv->force_audio_property;
0233     if (prop == NULL) {
0234         prop = drm_property_create_enum(dev, 0,
0235                        "audio",
0236                        force_audio_names,
0237                        ARRAY_SIZE(force_audio_names));
0238         if (prop == NULL)
0239             return;
0240 
0241         dev_priv->force_audio_property = prop;
0242     }
0243     drm_object_attach_property(&connector->base, prop, 0);
0244 }
0245 
0246 static const struct drm_prop_enum_list broadcast_rgb_names[] = {
0247     { INTEL_BROADCAST_RGB_AUTO, "Automatic" },
0248     { INTEL_BROADCAST_RGB_FULL, "Full" },
0249     { INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" },
0250 };
0251 
0252 void
0253 intel_attach_broadcast_rgb_property(struct drm_connector *connector)
0254 {
0255     struct drm_device *dev = connector->dev;
0256     struct drm_i915_private *dev_priv = to_i915(dev);
0257     struct drm_property *prop;
0258 
0259     prop = dev_priv->broadcast_rgb_property;
0260     if (prop == NULL) {
0261         prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
0262                        "Broadcast RGB",
0263                        broadcast_rgb_names,
0264                        ARRAY_SIZE(broadcast_rgb_names));
0265         if (prop == NULL)
0266             return;
0267 
0268         dev_priv->broadcast_rgb_property = prop;
0269     }
0270 
0271     drm_object_attach_property(&connector->base, prop, 0);
0272 }
0273 
0274 void
0275 intel_attach_aspect_ratio_property(struct drm_connector *connector)
0276 {
0277     if (!drm_mode_create_aspect_ratio_property(connector->dev))
0278         drm_object_attach_property(&connector->base,
0279             connector->dev->mode_config.aspect_ratio_property,
0280             DRM_MODE_PICTURE_ASPECT_NONE);
0281 }
0282 
0283 void
0284 intel_attach_hdmi_colorspace_property(struct drm_connector *connector)
0285 {
0286     if (!drm_mode_create_hdmi_colorspace_property(connector))
0287         drm_connector_attach_colorspace_property(connector);
0288 }
0289 
0290 void
0291 intel_attach_dp_colorspace_property(struct drm_connector *connector)
0292 {
0293     if (!drm_mode_create_dp_colorspace_property(connector))
0294         drm_connector_attach_colorspace_property(connector);
0295 }