1e3adcf8fSFrançois Tigeot /* 2e3adcf8fSFrançois Tigeot * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 3e3adcf8fSFrançois Tigeot * Copyright (c) 2007, 2010 Intel Corporation 4e3adcf8fSFrançois Tigeot * Jesse Barnes <jesse.barnes@intel.com> 5e3adcf8fSFrançois Tigeot * 6e3adcf8fSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 7e3adcf8fSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 8e3adcf8fSFrançois Tigeot * to deal in the Software without restriction, including without limitation 9e3adcf8fSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10e3adcf8fSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 11e3adcf8fSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 12e3adcf8fSFrançois Tigeot * 13e3adcf8fSFrançois Tigeot * The above copyright notice and this permission notice (including the next 14e3adcf8fSFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 15e3adcf8fSFrançois Tigeot * Software. 16e3adcf8fSFrançois Tigeot * 17e3adcf8fSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18e3adcf8fSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19e3adcf8fSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e3adcf8fSFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21e3adcf8fSFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22e3adcf8fSFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23e3adcf8fSFrançois Tigeot * DEALINGS IN THE SOFTWARE. 24e3adcf8fSFrançois Tigeot */ 25e3adcf8fSFrançois Tigeot 26*2c84b0b6SFrançois Tigeot #include <linux/i2c.h> 2718e26a6dSFrançois Tigeot #include <drm/drmP.h> 2818e26a6dSFrançois Tigeot #include <drm/drm_edid.h> 29e3adcf8fSFrançois Tigeot #include "intel_drv.h" 3018e26a6dSFrançois Tigeot #include "i915_drv.h" 31e3adcf8fSFrançois Tigeot #include <bus/iicbus/iiconf.h> 32e3adcf8fSFrançois Tigeot 33e3adcf8fSFrançois Tigeot bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) 34e3adcf8fSFrançois Tigeot { 35e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; 36e3adcf8fSFrançois Tigeot u8 out_buf[] = { 0x0, 0x0}; 37e3adcf8fSFrançois Tigeot u8 buf[2]; 38e3adcf8fSFrançois Tigeot struct iic_msg msgs[] = { 39e3adcf8fSFrançois Tigeot { 40e3adcf8fSFrançois Tigeot .slave = DDC_ADDR << 1, 41e3adcf8fSFrançois Tigeot .flags = IIC_M_WR, 42e3adcf8fSFrançois Tigeot .len = 1, 43e3adcf8fSFrançois Tigeot .buf = out_buf, 44e3adcf8fSFrançois Tigeot }, 45e3adcf8fSFrançois Tigeot { 46e3adcf8fSFrançois Tigeot .slave = DDC_ADDR << 1, 47e3adcf8fSFrançois Tigeot .flags = IIC_M_RD, 48e3adcf8fSFrançois Tigeot .len = 1, 49e3adcf8fSFrançois Tigeot .buf = buf, 50e3adcf8fSFrançois Tigeot } 51e3adcf8fSFrançois Tigeot }; 52e3adcf8fSFrançois Tigeot 53e3adcf8fSFrançois Tigeot return (iicbus_transfer(dev_priv->gmbus[ddc_bus], msgs, 2) 54e3adcf8fSFrançois Tigeot == 0/* XXXKIB 2*/); 55e3adcf8fSFrançois Tigeot } 56e3adcf8fSFrançois Tigeot 57e3adcf8fSFrançois Tigeot /** 58*2c84b0b6SFrançois Tigeot * intel_connector_update_modes - update connector from edid 59*2c84b0b6SFrançois Tigeot * @connector: DRM connector device to use 60*2c84b0b6SFrançois Tigeot * @edid: previously read EDID information 61*2c84b0b6SFrançois Tigeot */ 62*2c84b0b6SFrançois Tigeot int intel_connector_update_modes(struct drm_connector *connector, 63*2c84b0b6SFrançois Tigeot struct edid *edid) 64*2c84b0b6SFrançois Tigeot { 65*2c84b0b6SFrançois Tigeot int ret; 66*2c84b0b6SFrançois Tigeot 67*2c84b0b6SFrançois Tigeot drm_mode_connector_update_edid_property(connector, edid); 68*2c84b0b6SFrançois Tigeot ret = drm_add_edid_modes(connector, edid); 69*2c84b0b6SFrançois Tigeot drm_edid_to_eld(connector, edid); 70*2c84b0b6SFrançois Tigeot 71*2c84b0b6SFrançois Tigeot return ret; 72*2c84b0b6SFrançois Tigeot } 73*2c84b0b6SFrançois Tigeot 74*2c84b0b6SFrançois Tigeot /** 75e3adcf8fSFrançois Tigeot * intel_ddc_get_modes - get modelist from monitor 76e3adcf8fSFrançois Tigeot * @connector: DRM connector device to use 77e3adcf8fSFrançois Tigeot * @adapter: i2c adapter 78e3adcf8fSFrançois Tigeot * 79e3adcf8fSFrançois Tigeot * Fetch the EDID information from @connector using the DDC bus. 80e3adcf8fSFrançois Tigeot */ 81*2c84b0b6SFrançois Tigeot int intel_ddc_get_modes(struct drm_connector *connector, 82*2c84b0b6SFrançois Tigeot device_t adapter) 83e3adcf8fSFrançois Tigeot { 84e3adcf8fSFrançois Tigeot struct edid *edid; 85*2c84b0b6SFrançois Tigeot int ret; 86e3adcf8fSFrançois Tigeot 87e3adcf8fSFrançois Tigeot edid = drm_get_edid(connector, adapter); 88*2c84b0b6SFrançois Tigeot if (!edid) 89*2c84b0b6SFrançois Tigeot return 0; 90*2c84b0b6SFrançois Tigeot 91*2c84b0b6SFrançois Tigeot ret = intel_connector_update_modes(connector, edid); 92*2c84b0b6SFrançois Tigeot kfree(edid, DRM_MEM_KMS); 93e3adcf8fSFrançois Tigeot 94e3adcf8fSFrançois Tigeot return ret; 95e3adcf8fSFrançois Tigeot } 96e3adcf8fSFrançois Tigeot 97e3adcf8fSFrançois Tigeot static const struct drm_prop_enum_list force_audio_names[] = { 98e3adcf8fSFrançois Tigeot { HDMI_AUDIO_OFF_DVI, "force-dvi" }, 99e3adcf8fSFrançois Tigeot { HDMI_AUDIO_OFF, "off" }, 100e3adcf8fSFrançois Tigeot { HDMI_AUDIO_AUTO, "auto" }, 101e3adcf8fSFrançois Tigeot { HDMI_AUDIO_ON, "on" }, 102e3adcf8fSFrançois Tigeot }; 103e3adcf8fSFrançois Tigeot 104e3adcf8fSFrançois Tigeot void 105e3adcf8fSFrançois Tigeot intel_attach_force_audio_property(struct drm_connector *connector) 106e3adcf8fSFrançois Tigeot { 107e3adcf8fSFrançois Tigeot struct drm_device *dev = connector->dev; 108e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 109e3adcf8fSFrançois Tigeot struct drm_property *prop; 110e3adcf8fSFrançois Tigeot 111e3adcf8fSFrançois Tigeot prop = dev_priv->force_audio_property; 112e3adcf8fSFrançois Tigeot if (prop == NULL) { 113e3adcf8fSFrançois Tigeot prop = drm_property_create_enum(dev, 0, 114e3adcf8fSFrançois Tigeot "audio", 115e3adcf8fSFrançois Tigeot force_audio_names, 116*2c84b0b6SFrançois Tigeot ARRAY_SIZE(force_audio_names)); 117e3adcf8fSFrançois Tigeot if (prop == NULL) 118e3adcf8fSFrançois Tigeot return; 119e3adcf8fSFrançois Tigeot 120e3adcf8fSFrançois Tigeot dev_priv->force_audio_property = prop; 121e3adcf8fSFrançois Tigeot } 122b5162e19SFrançois Tigeot drm_object_attach_property(&connector->base, prop, 0); 123e3adcf8fSFrançois Tigeot } 124e3adcf8fSFrançois Tigeot 125e3adcf8fSFrançois Tigeot static const struct drm_prop_enum_list broadcast_rgb_names[] = { 126e3adcf8fSFrançois Tigeot { 0, "Full" }, 127e3adcf8fSFrançois Tigeot { 1, "Limited 16:235" }, 128e3adcf8fSFrançois Tigeot }; 129e3adcf8fSFrançois Tigeot 130e3adcf8fSFrançois Tigeot void 131e3adcf8fSFrançois Tigeot intel_attach_broadcast_rgb_property(struct drm_connector *connector) 132e3adcf8fSFrançois Tigeot { 133e3adcf8fSFrançois Tigeot struct drm_device *dev = connector->dev; 134e3adcf8fSFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 135e3adcf8fSFrançois Tigeot struct drm_property *prop; 136e3adcf8fSFrançois Tigeot 137e3adcf8fSFrançois Tigeot prop = dev_priv->broadcast_rgb_property; 138e3adcf8fSFrançois Tigeot if (prop == NULL) { 139e3adcf8fSFrançois Tigeot prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM, 140e3adcf8fSFrançois Tigeot "Broadcast RGB", 141e3adcf8fSFrançois Tigeot broadcast_rgb_names, 142*2c84b0b6SFrançois Tigeot ARRAY_SIZE(broadcast_rgb_names)); 143e3adcf8fSFrançois Tigeot if (prop == NULL) 144e3adcf8fSFrançois Tigeot return; 145e3adcf8fSFrançois Tigeot 146e3adcf8fSFrançois Tigeot dev_priv->broadcast_rgb_property = prop; 147e3adcf8fSFrançois Tigeot } 148e3adcf8fSFrançois Tigeot 149b5162e19SFrançois Tigeot drm_object_attach_property(&connector->base, prop, 0); 150e3adcf8fSFrançois Tigeot } 151