Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / gpu / drm / msm / dsi / dsi.c
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