GNU Linux-libre 4.19.211-gnu1
[releases.git] / drivers / gpu / drm / msm / edp / edp.c
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 <linux/of_irq.h>
15 #include "edp.h"
16
17 static irqreturn_t edp_irq(int irq, void *dev_id)
18 {
19         struct msm_edp *edp = dev_id;
20
21         /* Process eDP irq */
22         return msm_edp_ctrl_irq(edp->ctrl);
23 }
24
25 static void edp_destroy(struct platform_device *pdev)
26 {
27         struct msm_edp *edp = platform_get_drvdata(pdev);
28
29         if (!edp)
30                 return;
31
32         if (edp->ctrl) {
33                 msm_edp_ctrl_destroy(edp->ctrl);
34                 edp->ctrl = NULL;
35         }
36
37         platform_set_drvdata(pdev, NULL);
38 }
39
40 /* construct eDP at bind/probe time, grab all the resources. */
41 static struct msm_edp *edp_init(struct platform_device *pdev)
42 {
43         struct msm_edp *edp = NULL;
44         int ret;
45
46         if (!pdev) {
47                 pr_err("no eDP device\n");
48                 ret = -ENXIO;
49                 goto fail;
50         }
51
52         edp = devm_kzalloc(&pdev->dev, sizeof(*edp), GFP_KERNEL);
53         if (!edp) {
54                 ret = -ENOMEM;
55                 goto fail;
56         }
57         DBG("eDP probed=%p", edp);
58
59         edp->pdev = pdev;
60         platform_set_drvdata(pdev, edp);
61
62         ret = msm_edp_ctrl_init(edp);
63         if (ret)
64                 goto fail;
65
66         return edp;
67
68 fail:
69         if (edp)
70                 edp_destroy(pdev);
71
72         return ERR_PTR(ret);
73 }
74
75 static int edp_bind(struct device *dev, struct device *master, void *data)
76 {
77         struct drm_device *drm = dev_get_drvdata(master);
78         struct msm_drm_private *priv = drm->dev_private;
79         struct msm_edp *edp;
80
81         DBG("");
82         edp = edp_init(to_platform_device(dev));
83         if (IS_ERR(edp))
84                 return PTR_ERR(edp);
85         priv->edp = edp;
86
87         return 0;
88 }
89
90 static void edp_unbind(struct device *dev, struct device *master, void *data)
91 {
92         struct drm_device *drm = dev_get_drvdata(master);
93         struct msm_drm_private *priv = drm->dev_private;
94
95         DBG("");
96         if (priv->edp) {
97                 edp_destroy(to_platform_device(dev));
98                 priv->edp = NULL;
99         }
100 }
101
102 static const struct component_ops edp_ops = {
103                 .bind   = edp_bind,
104                 .unbind = edp_unbind,
105 };
106
107 static int edp_dev_probe(struct platform_device *pdev)
108 {
109         DBG("");
110         return component_add(&pdev->dev, &edp_ops);
111 }
112
113 static int edp_dev_remove(struct platform_device *pdev)
114 {
115         DBG("");
116         component_del(&pdev->dev, &edp_ops);
117         return 0;
118 }
119
120 static const struct of_device_id dt_match[] = {
121         { .compatible = "qcom,mdss-edp" },
122         {}
123 };
124
125 static struct platform_driver edp_driver = {
126         .probe = edp_dev_probe,
127         .remove = edp_dev_remove,
128         .driver = {
129                 .name = "msm_edp",
130                 .of_match_table = dt_match,
131         },
132 };
133
134 void __init msm_edp_register(void)
135 {
136         DBG("");
137         platform_driver_register(&edp_driver);
138 }
139
140 void __exit msm_edp_unregister(void)
141 {
142         DBG("");
143         platform_driver_unregister(&edp_driver);
144 }
145
146 /* Second part of initialization, the drm/kms level modeset_init */
147 int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev,
148                                 struct drm_encoder *encoder)
149 {
150         struct platform_device *pdev = edp->pdev;
151         struct msm_drm_private *priv = dev->dev_private;
152         int ret;
153
154         edp->encoder = encoder;
155         edp->dev = dev;
156
157         edp->bridge = msm_edp_bridge_init(edp);
158         if (IS_ERR(edp->bridge)) {
159                 ret = PTR_ERR(edp->bridge);
160                 dev_err(dev->dev, "failed to create eDP bridge: %d\n", ret);
161                 edp->bridge = NULL;
162                 goto fail;
163         }
164
165         edp->connector = msm_edp_connector_init(edp);
166         if (IS_ERR(edp->connector)) {
167                 ret = PTR_ERR(edp->connector);
168                 dev_err(dev->dev, "failed to create eDP connector: %d\n", ret);
169                 edp->connector = NULL;
170                 goto fail;
171         }
172
173         edp->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
174         if (edp->irq < 0) {
175                 ret = edp->irq;
176                 dev_err(dev->dev, "failed to get IRQ: %d\n", ret);
177                 goto fail;
178         }
179
180         ret = devm_request_irq(&pdev->dev, edp->irq,
181                         edp_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
182                         "edp_isr", edp);
183         if (ret < 0) {
184                 dev_err(dev->dev, "failed to request IRQ%u: %d\n",
185                                 edp->irq, ret);
186                 goto fail;
187         }
188
189         encoder->bridge = edp->bridge;
190
191         priv->bridges[priv->num_bridges++]       = edp->bridge;
192         priv->connectors[priv->num_connectors++] = edp->connector;
193
194         return 0;
195
196 fail:
197         /* bridge/connector are normally destroyed by drm */
198         if (edp->bridge) {
199                 edp_bridge_destroy(edp->bridge);
200                 edp->bridge = NULL;
201         }
202         if (edp->connector) {
203                 edp->connector->funcs->destroy(edp->connector);
204                 edp->connector = NULL;
205         }
206
207         return ret;
208 }