GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / gpu / drm / msm / mdp / mdp5 / mdp5_mdss.c
1 /*
2  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/irqdomain.h>
18 #include <linux/irq.h>
19
20 #include "msm_drv.h"
21 #include "mdp5_kms.h"
22
23 /*
24  * If needed, this can become more specific: something like struct mdp5_mdss,
25  * which contains a 'struct msm_mdss base' member.
26  */
27 struct msm_mdss {
28         struct drm_device *dev;
29
30         void __iomem *mmio, *vbif;
31
32         struct regulator *vdd;
33
34         struct clk *ahb_clk;
35         struct clk *axi_clk;
36         struct clk *vsync_clk;
37
38         struct {
39                 volatile unsigned long enabled_mask;
40                 struct irq_domain *domain;
41         } irqcontroller;
42 };
43
44 static inline void mdss_write(struct msm_mdss *mdss, u32 reg, u32 data)
45 {
46         msm_writel(data, mdss->mmio + reg);
47 }
48
49 static inline u32 mdss_read(struct msm_mdss *mdss, u32 reg)
50 {
51         return msm_readl(mdss->mmio + reg);
52 }
53
54 static irqreturn_t mdss_irq(int irq, void *arg)
55 {
56         struct msm_mdss *mdss = arg;
57         u32 intr;
58
59         intr = mdss_read(mdss, REG_MDSS_HW_INTR_STATUS);
60
61         VERB("intr=%08x", intr);
62
63         while (intr) {
64                 irq_hw_number_t hwirq = fls(intr) - 1;
65
66                 generic_handle_irq(irq_find_mapping(
67                                 mdss->irqcontroller.domain, hwirq));
68                 intr &= ~(1 << hwirq);
69         }
70
71         return IRQ_HANDLED;
72 }
73
74 /*
75  * interrupt-controller implementation, so sub-blocks (MDP/HDMI/eDP/DSI/etc)
76  * can register to get their irq's delivered
77  */
78
79 #define VALID_IRQS  (MDSS_HW_INTR_STATUS_INTR_MDP | \
80                 MDSS_HW_INTR_STATUS_INTR_DSI0 | \
81                 MDSS_HW_INTR_STATUS_INTR_DSI1 | \
82                 MDSS_HW_INTR_STATUS_INTR_HDMI | \
83                 MDSS_HW_INTR_STATUS_INTR_EDP)
84
85 static void mdss_hw_mask_irq(struct irq_data *irqd)
86 {
87         struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd);
88
89         smp_mb__before_atomic();
90         clear_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask);
91         smp_mb__after_atomic();
92 }
93
94 static void mdss_hw_unmask_irq(struct irq_data *irqd)
95 {
96         struct msm_mdss *mdss = irq_data_get_irq_chip_data(irqd);
97
98         smp_mb__before_atomic();
99         set_bit(irqd->hwirq, &mdss->irqcontroller.enabled_mask);
100         smp_mb__after_atomic();
101 }
102
103 static struct irq_chip mdss_hw_irq_chip = {
104         .name           = "mdss",
105         .irq_mask       = mdss_hw_mask_irq,
106         .irq_unmask     = mdss_hw_unmask_irq,
107 };
108
109 static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq,
110                                  irq_hw_number_t hwirq)
111 {
112         struct msm_mdss *mdss = d->host_data;
113
114         if (!(VALID_IRQS & (1 << hwirq)))
115                 return -EPERM;
116
117         irq_set_chip_and_handler(irq, &mdss_hw_irq_chip, handle_level_irq);
118         irq_set_chip_data(irq, mdss);
119
120         return 0;
121 }
122
123 static const struct irq_domain_ops mdss_hw_irqdomain_ops = {
124         .map = mdss_hw_irqdomain_map,
125         .xlate = irq_domain_xlate_onecell,
126 };
127
128
129 static int mdss_irq_domain_init(struct msm_mdss *mdss)
130 {
131         struct device *dev = mdss->dev->dev;
132         struct irq_domain *d;
133
134         d = irq_domain_add_linear(dev->of_node, 32, &mdss_hw_irqdomain_ops,
135                                   mdss);
136         if (!d) {
137                 dev_err(dev, "mdss irq domain add failed\n");
138                 return -ENXIO;
139         }
140
141         mdss->irqcontroller.enabled_mask = 0;
142         mdss->irqcontroller.domain = d;
143
144         return 0;
145 }
146
147 int msm_mdss_enable(struct msm_mdss *mdss)
148 {
149         DBG("");
150
151         clk_prepare_enable(mdss->ahb_clk);
152         if (mdss->axi_clk)
153                 clk_prepare_enable(mdss->axi_clk);
154         if (mdss->vsync_clk)
155                 clk_prepare_enable(mdss->vsync_clk);
156
157         return 0;
158 }
159
160 int msm_mdss_disable(struct msm_mdss *mdss)
161 {
162         DBG("");
163
164         if (mdss->vsync_clk)
165                 clk_disable_unprepare(mdss->vsync_clk);
166         if (mdss->axi_clk)
167                 clk_disable_unprepare(mdss->axi_clk);
168         clk_disable_unprepare(mdss->ahb_clk);
169
170         return 0;
171 }
172
173 static int msm_mdss_get_clocks(struct msm_mdss *mdss)
174 {
175         struct platform_device *pdev = to_platform_device(mdss->dev->dev);
176
177         mdss->ahb_clk = msm_clk_get(pdev, "iface");
178         if (IS_ERR(mdss->ahb_clk))
179                 mdss->ahb_clk = NULL;
180
181         mdss->axi_clk = msm_clk_get(pdev, "bus");
182         if (IS_ERR(mdss->axi_clk))
183                 mdss->axi_clk = NULL;
184
185         mdss->vsync_clk = msm_clk_get(pdev, "vsync");
186         if (IS_ERR(mdss->vsync_clk))
187                 mdss->vsync_clk = NULL;
188
189         return 0;
190 }
191
192 void msm_mdss_destroy(struct drm_device *dev)
193 {
194         struct msm_drm_private *priv = dev->dev_private;
195         struct msm_mdss *mdss = priv->mdss;
196
197         if (!mdss)
198                 return;
199
200         irq_domain_remove(mdss->irqcontroller.domain);
201         mdss->irqcontroller.domain = NULL;
202
203         regulator_disable(mdss->vdd);
204
205         pm_runtime_disable(dev->dev);
206 }
207
208 int msm_mdss_init(struct drm_device *dev)
209 {
210         struct platform_device *pdev = to_platform_device(dev->dev);
211         struct msm_drm_private *priv = dev->dev_private;
212         struct msm_mdss *mdss;
213         int ret;
214
215         DBG("");
216
217         if (!of_device_is_compatible(dev->dev->of_node, "qcom,mdss"))
218                 return 0;
219
220         mdss = devm_kzalloc(dev->dev, sizeof(*mdss), GFP_KERNEL);
221         if (!mdss) {
222                 ret = -ENOMEM;
223                 goto fail;
224         }
225
226         mdss->dev = dev;
227
228         mdss->mmio = msm_ioremap(pdev, "mdss_phys", "MDSS");
229         if (IS_ERR(mdss->mmio)) {
230                 ret = PTR_ERR(mdss->mmio);
231                 goto fail;
232         }
233
234         mdss->vbif = msm_ioremap(pdev, "vbif_phys", "VBIF");
235         if (IS_ERR(mdss->vbif)) {
236                 ret = PTR_ERR(mdss->vbif);
237                 goto fail;
238         }
239
240         ret = msm_mdss_get_clocks(mdss);
241         if (ret) {
242                 dev_err(dev->dev, "failed to get clocks: %d\n", ret);
243                 goto fail;
244         }
245
246         /* Regulator to enable GDSCs in downstream kernels */
247         mdss->vdd = devm_regulator_get(dev->dev, "vdd");
248         if (IS_ERR(mdss->vdd)) {
249                 ret = PTR_ERR(mdss->vdd);
250                 goto fail;
251         }
252
253         ret = regulator_enable(mdss->vdd);
254         if (ret) {
255                 dev_err(dev->dev, "failed to enable regulator vdd: %d\n",
256                         ret);
257                 goto fail;
258         }
259
260         ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0),
261                                mdss_irq, 0, "mdss_isr", mdss);
262         if (ret) {
263                 dev_err(dev->dev, "failed to init irq: %d\n", ret);
264                 goto fail_irq;
265         }
266
267         ret = mdss_irq_domain_init(mdss);
268         if (ret) {
269                 dev_err(dev->dev, "failed to init sub-block irqs: %d\n", ret);
270                 goto fail_irq;
271         }
272
273         priv->mdss = mdss;
274
275         pm_runtime_enable(dev->dev);
276
277         return 0;
278 fail_irq:
279         regulator_disable(mdss->vdd);
280 fail:
281         return ret;
282 }