1 /* 2 * Copyright (c) 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 "dsi.h" 15 16 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi) 17 { 18 if (!msm_dsi || !msm_dsi->panel) 19 return NULL; 20 21 return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ? 22 msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] : 23 msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID]; 24 } 25 26 static void dsi_destroy(struct msm_dsi *msm_dsi) 27 { 28 if (!msm_dsi) 29 return; 30 31 msm_dsi_manager_unregister(msm_dsi); 32 if (msm_dsi->host) { 33 msm_dsi_host_destroy(msm_dsi->host); 34 msm_dsi->host = NULL; 35 } 36 37 platform_set_drvdata(msm_dsi->pdev, NULL); 38 } 39 40 static struct msm_dsi *dsi_init(struct platform_device *pdev) 41 { 42 struct msm_dsi *msm_dsi = NULL; 43 int ret; 44 45 if (!pdev) { 46 dev_err(&pdev->dev, "no dsi device\n"); 47 ret = -ENXIO; 48 goto fail; 49 } 50 51 msm_dsi = devm_kzalloc(&pdev->dev, sizeof(*msm_dsi), GFP_KERNEL); 52 if (!msm_dsi) { 53 ret = -ENOMEM; 54 goto fail; 55 } 56 DBG("dsi probed=%p", msm_dsi); 57 58 msm_dsi->pdev = pdev; 59 platform_set_drvdata(pdev, msm_dsi); 60 61 /* Init dsi host */ 62 ret = msm_dsi_host_init(msm_dsi); 63 if (ret) 64 goto fail; 65 66 /* Register to dsi manager */ 67 ret = msm_dsi_manager_register(msm_dsi); 68 if (ret) 69 goto fail; 70 71 return msm_dsi; 72 73 fail: 74 if (msm_dsi) 75 dsi_destroy(msm_dsi); 76 77 return ERR_PTR(ret); 78 } 79 80 static int dsi_bind(struct device *dev, struct device *master, void *data) 81 { 82 struct drm_device *drm = dev_get_drvdata(master); 83 struct msm_drm_private *priv = drm->dev_private; 84 struct platform_device *pdev = to_platform_device(dev); 85 struct msm_dsi *msm_dsi; 86 87 DBG(""); 88 msm_dsi = dsi_init(pdev); 89 if (IS_ERR(msm_dsi)) 90 return PTR_ERR(msm_dsi); 91 92 priv->dsi[msm_dsi->id] = msm_dsi; 93 94 return 0; 95 } 96 97 static void dsi_unbind(struct device *dev, struct device *master, 98 void *data) 99 { 100 struct drm_device *drm = dev_get_drvdata(master); 101 struct msm_drm_private *priv = drm->dev_private; 102 struct msm_dsi *msm_dsi = dev_get_drvdata(dev); 103 int id = msm_dsi->id; 104 105 if (priv->dsi[id]) { 106 dsi_destroy(msm_dsi); 107 priv->dsi[id] = NULL; 108 } 109 } 110 111 static const struct component_ops dsi_ops = { 112 .bind = dsi_bind, 113 .unbind = dsi_unbind, 114 }; 115 116 static int dsi_dev_probe(struct platform_device *pdev) 117 { 118 return component_add(&pdev->dev, &dsi_ops); 119 } 120 121 static int dsi_dev_remove(struct platform_device *pdev) 122 { 123 DBG(""); 124 component_del(&pdev->dev, &dsi_ops); 125 return 0; 126 } 127 128 static const struct of_device_id dt_match[] = { 129 { .compatible = "qcom,mdss-dsi-ctrl" }, 130 {} 131 }; 132 133 static struct platform_driver dsi_driver = { 134 .probe = dsi_dev_probe, 135 .remove = dsi_dev_remove, 136 .driver = { 137 .name = "msm_dsi", 138 .of_match_table = dt_match, 139 }, 140 }; 141 142 void __init msm_dsi_register(void) 143 { 144 DBG(""); 145 platform_driver_register(&dsi_driver); 146 } 147 148 void __exit msm_dsi_unregister(void) 149 { 150 DBG(""); 151 platform_driver_unregister(&dsi_driver); 152 } 153 154 int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, 155 struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM]) 156 { 157 struct msm_drm_private *priv = dev->dev_private; 158 int ret, i; 159 160 if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] || 161 !encoders[MSM_DSI_CMD_ENCODER_ID])) 162 return -EINVAL; 163 164 msm_dsi->dev = dev; 165 166 ret = msm_dsi_host_modeset_init(msm_dsi->host, dev); 167 if (ret) { 168 dev_err(dev->dev, "failed to modeset init host: %d\n", ret); 169 goto fail; 170 } 171 172 msm_dsi->bridge = msm_dsi_manager_bridge_init(msm_dsi->id); 173 if (IS_ERR(msm_dsi->bridge)) { 174 ret = PTR_ERR(msm_dsi->bridge); 175 dev_err(dev->dev, "failed to create dsi bridge: %d\n", ret); 176 msm_dsi->bridge = NULL; 177 goto fail; 178 } 179 180 for (i = 0; i < MSM_DSI_ENCODER_NUM; i++) { 181 encoders[i]->bridge = msm_dsi->bridge; 182 msm_dsi->encoders[i] = encoders[i]; 183 } 184 185 msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id); 186 if (IS_ERR(msm_dsi->connector)) { 187 ret = PTR_ERR(msm_dsi->connector); 188 dev_err(dev->dev, "failed to create dsi connector: %d\n", ret); 189 msm_dsi->connector = NULL; 190 goto fail; 191 } 192 193 priv->bridges[priv->num_bridges++] = msm_dsi->bridge; 194 priv->connectors[priv->num_connectors++] = msm_dsi->connector; 195 196 return 0; 197 fail: 198 if (msm_dsi) { 199 /* bridge/connector are normally destroyed by drm: */ 200 if (msm_dsi->bridge) { 201 msm_dsi_manager_bridge_destroy(msm_dsi->bridge); 202 msm_dsi->bridge = NULL; 203 } 204 if (msm_dsi->connector) { 205 msm_dsi->connector->funcs->destroy(msm_dsi->connector); 206 msm_dsi->connector = NULL; 207 } 208 } 209 210 return ret; 211 } 212 213