16a227d5fSAlan Cox /* 26a227d5fSAlan Cox * Copyright © 2006-2011 Intel Corporation 36a227d5fSAlan Cox * 46a227d5fSAlan Cox * Permission is hereby granted, free of charge, to any person obtaining a 56a227d5fSAlan Cox * copy of this software and associated documentation files (the "Software"), 66a227d5fSAlan Cox * to deal in the Software without restriction, including without limitation 76a227d5fSAlan Cox * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86a227d5fSAlan Cox * and/or sell copies of the Software, and to permit persons to whom the 96a227d5fSAlan Cox * Software is furnished to do so, subject to the following conditions: 106a227d5fSAlan Cox * 116a227d5fSAlan Cox * The above copyright notice and this permission notice (including the next 126a227d5fSAlan Cox * paragraph) shall be included in all copies or substantial portions of the 136a227d5fSAlan Cox * Software. 146a227d5fSAlan Cox * 156a227d5fSAlan Cox * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166a227d5fSAlan Cox * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176a227d5fSAlan Cox * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186a227d5fSAlan Cox * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196a227d5fSAlan Cox * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206a227d5fSAlan Cox * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216a227d5fSAlan Cox * DEALINGS IN THE SOFTWARE. 226a227d5fSAlan Cox * 236a227d5fSAlan Cox * Authors: 246a227d5fSAlan Cox * jim liu <jim.liu@intel.com> 256a227d5fSAlan Cox * 266a227d5fSAlan Cox * FIXME: 276a227d5fSAlan Cox * We should probably make this generic and share it with Medfield 286a227d5fSAlan Cox */ 296a227d5fSAlan Cox 306a227d5fSAlan Cox #include <drm/drmP.h> 316a227d5fSAlan Cox #include <drm/drm.h> 326a227d5fSAlan Cox #include <drm/drm_crtc.h> 336a227d5fSAlan Cox #include <drm/drm_edid.h> 346a227d5fSAlan Cox #include "psb_intel_drv.h" 356a227d5fSAlan Cox #include "psb_drv.h" 366a227d5fSAlan Cox #include "psb_intel_reg.h" 37455b9e91SKirill A. Shutemov #include "cdv_device.h" 386a227d5fSAlan Cox #include <linux/pm_runtime.h> 396a227d5fSAlan Cox 406a227d5fSAlan Cox /* hdmi control bits */ 416a227d5fSAlan Cox #define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9) 426a227d5fSAlan Cox #define HDMI_BORDER_ENABLE (1 << 7) 436a227d5fSAlan Cox #define HDMI_AUDIO_ENABLE (1 << 6) 446a227d5fSAlan Cox #define HDMI_VSYNC_ACTIVE_HIGH (1 << 4) 456a227d5fSAlan Cox #define HDMI_HSYNC_ACTIVE_HIGH (1 << 3) 466a227d5fSAlan Cox /* hdmi-b control bits */ 476a227d5fSAlan Cox #define HDMIB_PIPE_B_SELECT (1 << 30) 486a227d5fSAlan Cox 496a227d5fSAlan Cox 506a227d5fSAlan Cox struct mid_intel_hdmi_priv { 516a227d5fSAlan Cox u32 hdmi_reg; 526a227d5fSAlan Cox u32 save_HDMIB; 536a227d5fSAlan Cox bool has_hdmi_sink; 546a227d5fSAlan Cox bool has_hdmi_audio; 556a227d5fSAlan Cox /* Should set this when detect hotplug */ 566a227d5fSAlan Cox bool hdmi_device_connected; 576a227d5fSAlan Cox struct mdfld_hdmi_i2c *i2c_bus; 586a227d5fSAlan Cox struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ 596a227d5fSAlan Cox struct drm_device *dev; 606a227d5fSAlan Cox }; 616a227d5fSAlan Cox 626a227d5fSAlan Cox static void cdv_hdmi_mode_set(struct drm_encoder *encoder, 636a227d5fSAlan Cox struct drm_display_mode *mode, 646a227d5fSAlan Cox struct drm_display_mode *adjusted_mode) 656a227d5fSAlan Cox { 666a227d5fSAlan Cox struct drm_device *dev = encoder->dev; 67367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = to_gma_encoder(encoder); 68367e4408SPatrik Jakobsson struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv; 696a227d5fSAlan Cox u32 hdmib; 706a227d5fSAlan Cox struct drm_crtc *crtc = encoder->crtc; 716306865dSPatrik Jakobsson struct gma_crtc *gma_crtc = to_gma_crtc(crtc); 726a227d5fSAlan Cox 736a227d5fSAlan Cox hdmib = (2 << 10); 746a227d5fSAlan Cox 756a227d5fSAlan Cox if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) 766a227d5fSAlan Cox hdmib |= HDMI_VSYNC_ACTIVE_HIGH; 776a227d5fSAlan Cox if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) 786a227d5fSAlan Cox hdmib |= HDMI_HSYNC_ACTIVE_HIGH; 796a227d5fSAlan Cox 806306865dSPatrik Jakobsson if (gma_crtc->pipe == 1) 816a227d5fSAlan Cox hdmib |= HDMIB_PIPE_B_SELECT; 826a227d5fSAlan Cox 836a227d5fSAlan Cox if (hdmi_priv->has_hdmi_audio) { 846a227d5fSAlan Cox hdmib |= HDMI_AUDIO_ENABLE; 856a227d5fSAlan Cox hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC; 866a227d5fSAlan Cox } 876a227d5fSAlan Cox 886a227d5fSAlan Cox REG_WRITE(hdmi_priv->hdmi_reg, hdmib); 896a227d5fSAlan Cox REG_READ(hdmi_priv->hdmi_reg); 906a227d5fSAlan Cox } 916a227d5fSAlan Cox 926a227d5fSAlan Cox static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) 936a227d5fSAlan Cox { 946a227d5fSAlan Cox struct drm_device *dev = encoder->dev; 95367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = to_gma_encoder(encoder); 96367e4408SPatrik Jakobsson struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv; 976a227d5fSAlan Cox u32 hdmib; 986a227d5fSAlan Cox 996a227d5fSAlan Cox hdmib = REG_READ(hdmi_priv->hdmi_reg); 1006a227d5fSAlan Cox 1016a227d5fSAlan Cox if (mode != DRM_MODE_DPMS_ON) 1026a227d5fSAlan Cox REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN); 1036a227d5fSAlan Cox else 1046a227d5fSAlan Cox REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN); 1056a227d5fSAlan Cox REG_READ(hdmi_priv->hdmi_reg); 1066a227d5fSAlan Cox } 1076a227d5fSAlan Cox 1086a227d5fSAlan Cox static void cdv_hdmi_save(struct drm_connector *connector) 1096a227d5fSAlan Cox { 1106a227d5fSAlan Cox struct drm_device *dev = connector->dev; 111367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = gma_attached_encoder(connector); 112367e4408SPatrik Jakobsson struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv; 1136a227d5fSAlan Cox 1146a227d5fSAlan Cox hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg); 1156a227d5fSAlan Cox } 1166a227d5fSAlan Cox 1176a227d5fSAlan Cox static void cdv_hdmi_restore(struct drm_connector *connector) 1186a227d5fSAlan Cox { 1196a227d5fSAlan Cox struct drm_device *dev = connector->dev; 120367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = gma_attached_encoder(connector); 121367e4408SPatrik Jakobsson struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv; 1226a227d5fSAlan Cox 1236a227d5fSAlan Cox REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB); 1246a227d5fSAlan Cox REG_READ(hdmi_priv->hdmi_reg); 1256a227d5fSAlan Cox } 1266a227d5fSAlan Cox 1276a227d5fSAlan Cox static enum drm_connector_status cdv_hdmi_detect( 1286a227d5fSAlan Cox struct drm_connector *connector, bool force) 1296a227d5fSAlan Cox { 130367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = gma_attached_encoder(connector); 131367e4408SPatrik Jakobsson struct mid_intel_hdmi_priv *hdmi_priv = gma_encoder->dev_priv; 1326a227d5fSAlan Cox struct edid *edid = NULL; 1336a227d5fSAlan Cox enum drm_connector_status status = connector_status_disconnected; 1346a227d5fSAlan Cox 135367e4408SPatrik Jakobsson edid = drm_get_edid(connector, &gma_encoder->i2c_bus->adapter); 1366a227d5fSAlan Cox 1376a227d5fSAlan Cox hdmi_priv->has_hdmi_sink = false; 1386a227d5fSAlan Cox hdmi_priv->has_hdmi_audio = false; 1396a227d5fSAlan Cox if (edid) { 1406a227d5fSAlan Cox if (edid->input & DRM_EDID_INPUT_DIGITAL) { 1416a227d5fSAlan Cox status = connector_status_connected; 1426a227d5fSAlan Cox hdmi_priv->has_hdmi_sink = 1436a227d5fSAlan Cox drm_detect_hdmi_monitor(edid); 1446a227d5fSAlan Cox hdmi_priv->has_hdmi_audio = 1456a227d5fSAlan Cox drm_detect_monitor_audio(edid); 1466a227d5fSAlan Cox } 1476a227d5fSAlan Cox kfree(edid); 1486a227d5fSAlan Cox } 1496a227d5fSAlan Cox return status; 1506a227d5fSAlan Cox } 1516a227d5fSAlan Cox 1526a227d5fSAlan Cox static int cdv_hdmi_set_property(struct drm_connector *connector, 1536a227d5fSAlan Cox struct drm_property *property, 1546a227d5fSAlan Cox uint64_t value) 1556a227d5fSAlan Cox { 1566a227d5fSAlan Cox struct drm_encoder *encoder = connector->encoder; 1576a227d5fSAlan Cox 1586a227d5fSAlan Cox if (!strcmp(property->name, "scaling mode") && encoder) { 1596306865dSPatrik Jakobsson struct gma_crtc *crtc = to_gma_crtc(encoder->crtc); 1606a227d5fSAlan Cox bool centre; 1616a227d5fSAlan Cox uint64_t curValue; 1626a227d5fSAlan Cox 1636a227d5fSAlan Cox if (!crtc) 1646a227d5fSAlan Cox return -1; 1656a227d5fSAlan Cox 1666a227d5fSAlan Cox switch (value) { 1676a227d5fSAlan Cox case DRM_MODE_SCALE_FULLSCREEN: 1686a227d5fSAlan Cox break; 1696a227d5fSAlan Cox case DRM_MODE_SCALE_NO_SCALE: 1706a227d5fSAlan Cox break; 1716a227d5fSAlan Cox case DRM_MODE_SCALE_ASPECT: 1726a227d5fSAlan Cox break; 1736a227d5fSAlan Cox default: 1746a227d5fSAlan Cox return -1; 1756a227d5fSAlan Cox } 1766a227d5fSAlan Cox 177a69ac9eaSRob Clark if (drm_object_property_get_value(&connector->base, 1786a227d5fSAlan Cox property, &curValue)) 1796a227d5fSAlan Cox return -1; 1806a227d5fSAlan Cox 1816a227d5fSAlan Cox if (curValue == value) 1826a227d5fSAlan Cox return 0; 1836a227d5fSAlan Cox 184a69ac9eaSRob Clark if (drm_object_property_set_value(&connector->base, 1856a227d5fSAlan Cox property, value)) 1866a227d5fSAlan Cox return -1; 1876a227d5fSAlan Cox 1886a227d5fSAlan Cox centre = (curValue == DRM_MODE_SCALE_NO_SCALE) || 1896a227d5fSAlan Cox (value == DRM_MODE_SCALE_NO_SCALE); 1906a227d5fSAlan Cox 1916a227d5fSAlan Cox if (crtc->saved_mode.hdisplay != 0 && 1926a227d5fSAlan Cox crtc->saved_mode.vdisplay != 0) { 1936a227d5fSAlan Cox if (centre) { 1946a227d5fSAlan Cox if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, 195f4510a27SMatt Roper encoder->crtc->x, encoder->crtc->y, encoder->crtc->primary->fb)) 1966a227d5fSAlan Cox return -1; 1976a227d5fSAlan Cox } else { 19845fe734cSJani Nikula const struct drm_encoder_helper_funcs *helpers 1996a227d5fSAlan Cox = encoder->helper_private; 2006a227d5fSAlan Cox helpers->mode_set(encoder, &crtc->saved_mode, 2016a227d5fSAlan Cox &crtc->saved_adjusted_mode); 2026a227d5fSAlan Cox } 2036a227d5fSAlan Cox } 2046a227d5fSAlan Cox } 2056a227d5fSAlan Cox return 0; 2066a227d5fSAlan Cox } 2076a227d5fSAlan Cox 2086a227d5fSAlan Cox /* 2096a227d5fSAlan Cox * Return the list of HDMI DDC modes if available. 2106a227d5fSAlan Cox */ 2116a227d5fSAlan Cox static int cdv_hdmi_get_modes(struct drm_connector *connector) 2126a227d5fSAlan Cox { 213367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = gma_attached_encoder(connector); 2146a227d5fSAlan Cox struct edid *edid = NULL; 2156a227d5fSAlan Cox int ret = 0; 2166a227d5fSAlan Cox 217367e4408SPatrik Jakobsson edid = drm_get_edid(connector, &gma_encoder->i2c_bus->adapter); 2186a227d5fSAlan Cox if (edid) { 219*c555f023SDaniel Vetter drm_connector_update_edid_property(connector, edid); 220a12d6a07SPatrik Jakobsson ret = drm_add_edid_modes(connector, edid); 2216a227d5fSAlan Cox kfree(edid); 2226a227d5fSAlan Cox } 2236a227d5fSAlan Cox return ret; 2246a227d5fSAlan Cox } 2256a227d5fSAlan Cox 22667772782SLuc Van Oostenryck static enum drm_mode_status cdv_hdmi_mode_valid(struct drm_connector *connector, 2276a227d5fSAlan Cox struct drm_display_mode *mode) 2286a227d5fSAlan Cox { 2296a227d5fSAlan Cox if (mode->clock > 165000) 2306a227d5fSAlan Cox return MODE_CLOCK_HIGH; 2316a227d5fSAlan Cox if (mode->clock < 20000) 2326a227d5fSAlan Cox return MODE_CLOCK_HIGH; 2336a227d5fSAlan Cox 2346a227d5fSAlan Cox /* just in case */ 2356a227d5fSAlan Cox if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 2366a227d5fSAlan Cox return MODE_NO_DBLESCAN; 2376a227d5fSAlan Cox 2386a227d5fSAlan Cox /* just in case */ 2396a227d5fSAlan Cox if (mode->flags & DRM_MODE_FLAG_INTERLACE) 2406a227d5fSAlan Cox return MODE_NO_INTERLACE; 2416a227d5fSAlan Cox 2426a227d5fSAlan Cox return MODE_OK; 2436a227d5fSAlan Cox } 2446a227d5fSAlan Cox 2456a227d5fSAlan Cox static void cdv_hdmi_destroy(struct drm_connector *connector) 2466a227d5fSAlan Cox { 247367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder = gma_attached_encoder(connector); 2486a227d5fSAlan Cox 249367e4408SPatrik Jakobsson psb_intel_i2c_destroy(gma_encoder->i2c_bus); 25034ea3d38SThomas Wood drm_connector_unregister(connector); 2516a227d5fSAlan Cox drm_connector_cleanup(connector); 2526a227d5fSAlan Cox kfree(connector); 2536a227d5fSAlan Cox } 2546a227d5fSAlan Cox 2556a227d5fSAlan Cox static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { 2566a227d5fSAlan Cox .dpms = cdv_hdmi_dpms, 257c9d49590SPatrik Jakobsson .prepare = gma_encoder_prepare, 2586a227d5fSAlan Cox .mode_set = cdv_hdmi_mode_set, 259c9d49590SPatrik Jakobsson .commit = gma_encoder_commit, 2606a227d5fSAlan Cox }; 2616a227d5fSAlan Cox 2626a227d5fSAlan Cox static const struct drm_connector_helper_funcs 2636a227d5fSAlan Cox cdv_hdmi_connector_helper_funcs = { 2646a227d5fSAlan Cox .get_modes = cdv_hdmi_get_modes, 2656a227d5fSAlan Cox .mode_valid = cdv_hdmi_mode_valid, 266c9d49590SPatrik Jakobsson .best_encoder = gma_best_encoder, 2676a227d5fSAlan Cox }; 2686a227d5fSAlan Cox 2696a227d5fSAlan Cox static const struct drm_connector_funcs cdv_hdmi_connector_funcs = { 2706a227d5fSAlan Cox .dpms = drm_helper_connector_dpms, 2716a227d5fSAlan Cox .detect = cdv_hdmi_detect, 2726a227d5fSAlan Cox .fill_modes = drm_helper_probe_single_connector_modes, 2736a227d5fSAlan Cox .set_property = cdv_hdmi_set_property, 2746a227d5fSAlan Cox .destroy = cdv_hdmi_destroy, 2756a227d5fSAlan Cox }; 2766a227d5fSAlan Cox 2776a227d5fSAlan Cox void cdv_hdmi_init(struct drm_device *dev, 2786a227d5fSAlan Cox struct psb_intel_mode_device *mode_dev, int reg) 2796a227d5fSAlan Cox { 280367e4408SPatrik Jakobsson struct gma_encoder *gma_encoder; 281a3d5d75fSPatrik Jakobsson struct gma_connector *gma_connector; 2826a227d5fSAlan Cox struct drm_connector *connector; 2836a227d5fSAlan Cox struct drm_encoder *encoder; 2846a227d5fSAlan Cox struct mid_intel_hdmi_priv *hdmi_priv; 2856a227d5fSAlan Cox int ddc_bus; 2866a227d5fSAlan Cox 287367e4408SPatrik Jakobsson gma_encoder = kzalloc(sizeof(struct gma_encoder), GFP_KERNEL); 288a12d6a07SPatrik Jakobsson 289367e4408SPatrik Jakobsson if (!gma_encoder) 2906a227d5fSAlan Cox return; 2916a227d5fSAlan Cox 292a3d5d75fSPatrik Jakobsson gma_connector = kzalloc(sizeof(struct gma_connector), 293a12d6a07SPatrik Jakobsson GFP_KERNEL); 294a12d6a07SPatrik Jakobsson 295a3d5d75fSPatrik Jakobsson if (!gma_connector) 296a12d6a07SPatrik Jakobsson goto err_connector; 297a12d6a07SPatrik Jakobsson 298a12d6a07SPatrik Jakobsson hdmi_priv = kzalloc(sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL); 299a12d6a07SPatrik Jakobsson 300a12d6a07SPatrik Jakobsson if (!hdmi_priv) 301a12d6a07SPatrik Jakobsson goto err_priv; 302a12d6a07SPatrik Jakobsson 303a3d5d75fSPatrik Jakobsson connector = &gma_connector->base; 304bda50031SKero van Gelder connector->polled = DRM_CONNECTOR_POLL_HPD; 305d56f57acSDaniel Vetter gma_connector->save = cdv_hdmi_save; 306d56f57acSDaniel Vetter gma_connector->restore = cdv_hdmi_restore; 307d56f57acSDaniel Vetter 308367e4408SPatrik Jakobsson encoder = &gma_encoder->base; 309a12d6a07SPatrik Jakobsson drm_connector_init(dev, connector, 3106a227d5fSAlan Cox &cdv_hdmi_connector_funcs, 3116a227d5fSAlan Cox DRM_MODE_CONNECTOR_DVID); 3126a227d5fSAlan Cox 313a12d6a07SPatrik Jakobsson drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs, 31413a3d91fSVille Syrjälä DRM_MODE_ENCODER_TMDS, NULL); 3156a227d5fSAlan Cox 316367e4408SPatrik Jakobsson gma_connector_attach_encoder(gma_connector, gma_encoder); 317367e4408SPatrik Jakobsson gma_encoder->type = INTEL_OUTPUT_HDMI; 3186a227d5fSAlan Cox hdmi_priv->hdmi_reg = reg; 3196a227d5fSAlan Cox hdmi_priv->has_hdmi_sink = false; 320367e4408SPatrik Jakobsson gma_encoder->dev_priv = hdmi_priv; 3216a227d5fSAlan Cox 3226a227d5fSAlan Cox drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs); 3236a227d5fSAlan Cox drm_connector_helper_add(connector, 3246a227d5fSAlan Cox &cdv_hdmi_connector_helper_funcs); 3256a227d5fSAlan Cox connector->display_info.subpixel_order = SubPixelHorizontalRGB; 3266a227d5fSAlan Cox connector->interlace_allowed = false; 3276a227d5fSAlan Cox connector->doublescan_allowed = false; 3286a227d5fSAlan Cox 329a69ac9eaSRob Clark drm_object_attach_property(&connector->base, 330a12d6a07SPatrik Jakobsson dev->mode_config.scaling_mode_property, 331a12d6a07SPatrik Jakobsson DRM_MODE_SCALE_FULLSCREEN); 3326a227d5fSAlan Cox 3336a227d5fSAlan Cox switch (reg) { 3346a227d5fSAlan Cox case SDVOB: 3356a227d5fSAlan Cox ddc_bus = GPIOE; 336367e4408SPatrik Jakobsson gma_encoder->ddi_select = DDI0_SELECT; 3376a227d5fSAlan Cox break; 3386a227d5fSAlan Cox case SDVOC: 3396a227d5fSAlan Cox ddc_bus = GPIOD; 340367e4408SPatrik Jakobsson gma_encoder->ddi_select = DDI1_SELECT; 3416a227d5fSAlan Cox break; 3426a227d5fSAlan Cox default: 3436a227d5fSAlan Cox DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); 3446a227d5fSAlan Cox goto failed_ddc; 3456a227d5fSAlan Cox break; 3466a227d5fSAlan Cox } 3476a227d5fSAlan Cox 348367e4408SPatrik Jakobsson gma_encoder->i2c_bus = psb_intel_i2c_create(dev, 3496a227d5fSAlan Cox ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC"); 3506a227d5fSAlan Cox 351367e4408SPatrik Jakobsson if (!gma_encoder->i2c_bus) { 3526a227d5fSAlan Cox dev_err(dev->dev, "No ddc adapter available!\n"); 3536a227d5fSAlan Cox goto failed_ddc; 3546a227d5fSAlan Cox } 355a12d6a07SPatrik Jakobsson 356367e4408SPatrik Jakobsson hdmi_priv->hdmi_i2c_adapter = &(gma_encoder->i2c_bus->adapter); 3576a227d5fSAlan Cox hdmi_priv->dev = dev; 35834ea3d38SThomas Wood drm_connector_register(connector); 3596a227d5fSAlan Cox return; 3606a227d5fSAlan Cox 3616a227d5fSAlan Cox failed_ddc: 362a12d6a07SPatrik Jakobsson drm_encoder_cleanup(encoder); 363a12d6a07SPatrik Jakobsson drm_connector_cleanup(connector); 364a12d6a07SPatrik Jakobsson err_priv: 365a3d5d75fSPatrik Jakobsson kfree(gma_connector); 366a12d6a07SPatrik Jakobsson err_connector: 367367e4408SPatrik Jakobsson kfree(gma_encoder); 3686a227d5fSAlan Cox } 369