1/* 2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14#include "edp.h" 15 16struct edp_bridge { 17 struct drm_bridge base; 18 struct msm_edp *edp; 19}; 20#define to_edp_bridge(x) container_of(x, struct edp_bridge, base) 21 22void edp_bridge_destroy(struct drm_bridge *bridge) 23{ 24} 25 26static void edp_bridge_pre_enable(struct drm_bridge *bridge) 27{ 28 struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 29 struct msm_edp *edp = edp_bridge->edp; 30 31 DBG(""); 32 msm_edp_ctrl_power(edp->ctrl, true); 33} 34 35static void edp_bridge_enable(struct drm_bridge *bridge) 36{ 37 DBG(""); 38} 39 40static void edp_bridge_disable(struct drm_bridge *bridge) 41{ 42 DBG(""); 43} 44 45static void edp_bridge_post_disable(struct drm_bridge *bridge) 46{ 47 struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 48 struct msm_edp *edp = edp_bridge->edp; 49 50 DBG(""); 51 msm_edp_ctrl_power(edp->ctrl, false); 52} 53 54static void edp_bridge_mode_set(struct drm_bridge *bridge, 55 struct drm_display_mode *mode, 56 struct drm_display_mode *adjusted_mode) 57{ 58 struct drm_device *dev = bridge->dev; 59 struct drm_connector *connector; 60 struct edp_bridge *edp_bridge = to_edp_bridge(bridge); 61 struct msm_edp *edp = edp_bridge->edp; 62 63 DBG("set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", 64 mode->base.id, mode->name, 65 mode->vrefresh, mode->clock, 66 mode->hdisplay, mode->hsync_start, 67 mode->hsync_end, mode->htotal, 68 mode->vdisplay, mode->vsync_start, 69 mode->vsync_end, mode->vtotal, 70 mode->type, mode->flags); 71 72 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 73 if ((connector->encoder != NULL) && 74 (connector->encoder->bridge == bridge)) { 75 msm_edp_ctrl_timing_cfg(edp->ctrl, 76 adjusted_mode, &connector->display_info); 77 break; 78 } 79 } 80} 81 82static const struct drm_bridge_funcs edp_bridge_funcs = { 83 .pre_enable = edp_bridge_pre_enable, 84 .enable = edp_bridge_enable, 85 .disable = edp_bridge_disable, 86 .post_disable = edp_bridge_post_disable, 87 .mode_set = edp_bridge_mode_set, 88}; 89 90/* initialize bridge */ 91struct drm_bridge *msm_edp_bridge_init(struct msm_edp *edp) 92{ 93 struct drm_bridge *bridge = NULL; 94 struct edp_bridge *edp_bridge; 95 int ret; 96 97 edp_bridge = devm_kzalloc(edp->dev->dev, 98 sizeof(*edp_bridge), GFP_KERNEL); 99 if (!edp_bridge) { 100 ret = -ENOMEM; 101 goto fail; 102 } 103 104 edp_bridge->edp = edp; 105 106 bridge = &edp_bridge->base; 107 bridge->funcs = &edp_bridge_funcs; 108 109 ret = drm_bridge_attach(edp->dev, bridge); 110 if (ret) 111 goto fail; 112 113 return bridge; 114 115fail: 116 if (bridge) 117 edp_bridge_destroy(bridge); 118 119 return ERR_PTR(ret); 120} 121