static int sun4i_hdmi_get_modes(struct drm_connector *connector) { struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector); struct edid *edid; int ret; edid = drm_get_edid(connector, hdmi->i2c); if (!edid) return 0; hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid); DRM_DEBUG_DRIVER("Monitor is %s monitor\n", hdmi->hdmi_monitor ? "an HDMI" : "a DVI"); drm_mode_connector_update_edid_property(connector, edid); cec_s_phys_addr_from_edid(hdmi->cec_adap, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); return ret; }
/* * A new EDID is set. If there is no CEC adapter, then create one. If * there was a CEC adapter, then check if the CEC adapter properties * were unchanged and just update the CEC physical address. Otherwise * unregister the old CEC adapter and create a new one. */ void drm_dp_cec_set_edid(struct drm_dp_aux *aux, const struct edid *edid) { u32 cec_caps = CEC_CAP_DEFAULTS | CEC_CAP_NEEDS_HPD; unsigned int num_las = 1; u8 cap; /* No transfer function was set, so not a DP connector */ if (!aux->transfer) return; #ifndef CONFIG_MEDIA_CEC_RC /* * CEC_CAP_RC is part of CEC_CAP_DEFAULTS, but it is stripped by * cec_allocate_adapter() if CONFIG_MEDIA_CEC_RC is undefined. * * Do this here as well to ensure the tests against cec_caps are * correct. */ cec_caps &= ~CEC_CAP_RC; #endif cancel_delayed_work_sync(&aux->cec.unregister_work); mutex_lock(&aux->cec.lock); if (!drm_dp_cec_cap(aux, &cap)) { /* CEC is not supported, unregister any existing adapter */ cec_unregister_adapter(aux->cec.adap); aux->cec.adap = NULL; goto unlock; } if (cap & DP_CEC_SNOOPING_CAPABLE) cec_caps |= CEC_CAP_MONITOR_ALL; if (cap & DP_CEC_MULTIPLE_LA_CAPABLE) num_las = CEC_MAX_LOG_ADDRS; if (aux->cec.adap) { if (aux->cec.adap->capabilities == cec_caps && aux->cec.adap->available_log_addrs == num_las) { /* Unchanged, so just set the phys addr */ cec_s_phys_addr_from_edid(aux->cec.adap, edid); goto unlock; } /* * The capabilities changed, so unregister the old * adapter first. */ cec_unregister_adapter(aux->cec.adap); } /* Create a new adapter */ aux->cec.adap = cec_allocate_adapter(&drm_dp_cec_adap_ops, aux, aux->cec.name, cec_caps, num_las); if (IS_ERR(aux->cec.adap)) { aux->cec.adap = NULL; goto unlock; } if (cec_register_adapter(aux->cec.adap, aux->cec.parent)) { cec_delete_adapter(aux->cec.adap); aux->cec.adap = NULL; } else { /* * Update the phys addr for the new CEC adapter. When called * from drm_dp_cec_register_connector() edid == NULL, so in * that case the phys addr is just invalidated. */ cec_s_phys_addr_from_edid(aux->cec.adap, edid); } unlock: mutex_unlock(&aux->cec.lock); }