18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "edp.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_cistruct edp_bridge { 98c2ecf20Sopenharmony_ci struct drm_bridge base; 108c2ecf20Sopenharmony_ci struct msm_edp *edp; 118c2ecf20Sopenharmony_ci}; 128c2ecf20Sopenharmony_ci#define to_edp_bridge(x) container_of(x, struct edp_bridge, base) 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_civoid edp_bridge_destroy(struct drm_bridge *bridge) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci} 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic void edp_bridge_pre_enable(struct drm_bridge *bridge) 198c2ecf20Sopenharmony_ci{ 208c2ecf20Sopenharmony_ci struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 218c2ecf20Sopenharmony_ci struct msm_edp *edp = edp_bridge->edp; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci DBG(""); 248c2ecf20Sopenharmony_ci msm_edp_ctrl_power(edp->ctrl, true); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void edp_bridge_enable(struct drm_bridge *bridge) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci DBG(""); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic void edp_bridge_disable(struct drm_bridge *bridge) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci DBG(""); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic void edp_bridge_post_disable(struct drm_bridge *bridge) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 408c2ecf20Sopenharmony_ci struct msm_edp *edp = edp_bridge->edp; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci DBG(""); 438c2ecf20Sopenharmony_ci msm_edp_ctrl_power(edp->ctrl, false); 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic void edp_bridge_mode_set(struct drm_bridge *bridge, 478c2ecf20Sopenharmony_ci const struct drm_display_mode *mode, 488c2ecf20Sopenharmony_ci const struct drm_display_mode *adjusted_mode) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct drm_device *dev = bridge->dev; 518c2ecf20Sopenharmony_ci struct drm_connector *connector; 528c2ecf20Sopenharmony_ci struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 538c2ecf20Sopenharmony_ci struct msm_edp *edp = edp_bridge->edp; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode)); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 588c2ecf20Sopenharmony_ci struct drm_encoder *encoder = connector->encoder; 598c2ecf20Sopenharmony_ci struct drm_bridge *first_bridge; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (!connector->encoder) 628c2ecf20Sopenharmony_ci continue; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci first_bridge = drm_bridge_chain_get_first_bridge(encoder); 658c2ecf20Sopenharmony_ci if (bridge == first_bridge) { 668c2ecf20Sopenharmony_ci msm_edp_ctrl_timing_cfg(edp->ctrl, 678c2ecf20Sopenharmony_ci adjusted_mode, &connector->display_info); 688c2ecf20Sopenharmony_ci break; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic const struct drm_bridge_funcs edp_bridge_funcs = { 748c2ecf20Sopenharmony_ci .pre_enable = edp_bridge_pre_enable, 758c2ecf20Sopenharmony_ci .enable = edp_bridge_enable, 768c2ecf20Sopenharmony_ci .disable = edp_bridge_disable, 778c2ecf20Sopenharmony_ci .post_disable = edp_bridge_post_disable, 788c2ecf20Sopenharmony_ci .mode_set = edp_bridge_mode_set, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* initialize bridge */ 828c2ecf20Sopenharmony_cistruct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci struct drm_bridge *bridge = NULL; 858c2ecf20Sopenharmony_ci struct edp_bridge *edp_bridge; 868c2ecf20Sopenharmony_ci int ret; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci edp_bridge = devm_kzalloc(edp->dev->dev, 898c2ecf20Sopenharmony_ci sizeof(*edp_bridge), GFP_KERNEL); 908c2ecf20Sopenharmony_ci if (!edp_bridge) { 918c2ecf20Sopenharmony_ci ret = -ENOMEM; 928c2ecf20Sopenharmony_ci goto fail; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci edp_bridge->edp = edp; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci bridge = &edp_bridge->base; 988c2ecf20Sopenharmony_ci bridge->funcs = &edp_bridge_funcs; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci ret = drm_bridge_attach(edp->encoder, bridge, NULL, 0); 1018c2ecf20Sopenharmony_ci if (ret) 1028c2ecf20Sopenharmony_ci goto fail; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci return bridge; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cifail: 1078c2ecf20Sopenharmony_ci if (bridge) 1088c2ecf20Sopenharmony_ci edp_bridge_destroy(bridge); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return ERR_PTR(ret); 1118c2ecf20Sopenharmony_ci} 112