]> Git Repo - linux.git/blob - drivers/gpu/drm/arm/hdlcd_drv.c
Merge tag 'kvmarm-fixes-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmar...
[linux.git] / drivers / gpu / drm / arm / hdlcd_drv.c
1 /*
2  * Copyright (C) 2013-2015 ARM Limited
3  * Author: Liviu Dudau <[email protected]>
4  *
5  * This file is subject to the terms and conditions of the GNU General Public
6  * License.  See the file COPYING in the main directory of this archive
7  * for more details.
8  *
9  *  ARM HDLCD Driver
10  */
11
12 #include <linux/module.h>
13 #include <linux/spinlock.h>
14 #include <linux/clk.h>
15 #include <linux/component.h>
16 #include <linux/console.h>
17 #include <linux/dma-mapping.h>
18 #include <linux/list.h>
19 #include <linux/of_graph.h>
20 #include <linux/of_reserved_mem.h>
21 #include <linux/platform_device.h>
22 #include <linux/pm_runtime.h>
23
24 #include <drm/drm_aperture.h>
25 #include <drm/drm_atomic_helper.h>
26 #include <drm/drm_crtc.h>
27 #include <drm/drm_debugfs.h>
28 #include <drm/drm_drv.h>
29 #include <drm/drm_fb_helper.h>
30 #include <drm/drm_gem_dma_helper.h>
31 #include <drm/drm_gem_framebuffer_helper.h>
32 #include <drm/drm_modeset_helper.h>
33 #include <drm/drm_module.h>
34 #include <drm/drm_of.h>
35 #include <drm/drm_probe_helper.h>
36 #include <drm/drm_vblank.h>
37
38 #include "hdlcd_drv.h"
39 #include "hdlcd_regs.h"
40
41 static irqreturn_t hdlcd_irq(int irq, void *arg)
42 {
43         struct hdlcd_drm_private *hdlcd = arg;
44         unsigned long irq_status;
45
46         irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
47
48 #ifdef CONFIG_DEBUG_FS
49         if (irq_status & HDLCD_INTERRUPT_UNDERRUN)
50                 atomic_inc(&hdlcd->buffer_underrun_count);
51
52         if (irq_status & HDLCD_INTERRUPT_DMA_END)
53                 atomic_inc(&hdlcd->dma_end_count);
54
55         if (irq_status & HDLCD_INTERRUPT_BUS_ERROR)
56                 atomic_inc(&hdlcd->bus_error_count);
57
58         if (irq_status & HDLCD_INTERRUPT_VSYNC)
59                 atomic_inc(&hdlcd->vsync_count);
60
61 #endif
62         if (irq_status & HDLCD_INTERRUPT_VSYNC)
63                 drm_crtc_handle_vblank(&hdlcd->crtc);
64
65         /* acknowledge interrupt(s) */
66         hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
67
68         return IRQ_HANDLED;
69 }
70
71 static int hdlcd_irq_install(struct hdlcd_drm_private *hdlcd)
72 {
73         int ret;
74
75         /* Ensure interrupts are disabled */
76         hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
77         hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
78
79         ret = request_irq(hdlcd->irq, hdlcd_irq, 0, "hdlcd", hdlcd);
80         if (ret)
81                 return ret;
82
83 #ifdef CONFIG_DEBUG_FS
84         /* enable debug interrupts */
85         hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, HDLCD_DEBUG_INT_MASK);
86 #endif
87
88         return 0;
89 }
90
91 static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd)
92 {
93         /* disable all the interrupts that we might have enabled */
94         hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
95
96         free_irq(hdlcd->irq, hdlcd);
97 }
98
99 static int hdlcd_load(struct drm_device *drm, unsigned long flags)
100 {
101         struct hdlcd_drm_private *hdlcd = drm->dev_private;
102         struct platform_device *pdev = to_platform_device(drm->dev);
103         struct resource *res;
104         u32 version;
105         int ret;
106
107         hdlcd->clk = devm_clk_get(drm->dev, "pxlclk");
108         if (IS_ERR(hdlcd->clk))
109                 return PTR_ERR(hdlcd->clk);
110
111 #ifdef CONFIG_DEBUG_FS
112         atomic_set(&hdlcd->buffer_underrun_count, 0);
113         atomic_set(&hdlcd->bus_error_count, 0);
114         atomic_set(&hdlcd->vsync_count, 0);
115         atomic_set(&hdlcd->dma_end_count, 0);
116 #endif
117
118         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
119         hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
120         if (IS_ERR(hdlcd->mmio)) {
121                 DRM_ERROR("failed to map control registers area\n");
122                 ret = PTR_ERR(hdlcd->mmio);
123                 hdlcd->mmio = NULL;
124                 return ret;
125         }
126
127         version = hdlcd_read(hdlcd, HDLCD_REG_VERSION);
128         if ((version & HDLCD_PRODUCT_MASK) != HDLCD_PRODUCT_ID) {
129                 DRM_ERROR("unknown product id: 0x%x\n", version);
130                 return -EINVAL;
131         }
132         DRM_INFO("found ARM HDLCD version r%dp%d\n",
133                 (version & HDLCD_VERSION_MAJOR_MASK) >> 8,
134                 version & HDLCD_VERSION_MINOR_MASK);
135
136         /* Get the optional framebuffer memory resource */
137         ret = of_reserved_mem_device_init(drm->dev);
138         if (ret && ret != -ENODEV)
139                 return ret;
140
141         ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
142         if (ret)
143                 goto setup_fail;
144
145         ret = hdlcd_setup_crtc(drm);
146         if (ret < 0) {
147                 DRM_ERROR("failed to create crtc\n");
148                 goto setup_fail;
149         }
150
151         ret = platform_get_irq(pdev, 0);
152         if (ret < 0)
153                 goto irq_fail;
154         hdlcd->irq = ret;
155
156         ret = hdlcd_irq_install(hdlcd);
157         if (ret < 0) {
158                 DRM_ERROR("failed to install IRQ handler\n");
159                 goto irq_fail;
160         }
161
162         return 0;
163
164 irq_fail:
165         drm_crtc_cleanup(&hdlcd->crtc);
166 setup_fail:
167         of_reserved_mem_device_release(drm->dev);
168
169         return ret;
170 }
171
172 static const struct drm_mode_config_funcs hdlcd_mode_config_funcs = {
173         .fb_create = drm_gem_fb_create,
174         .atomic_check = drm_atomic_helper_check,
175         .atomic_commit = drm_atomic_helper_commit,
176 };
177
178 static void hdlcd_setup_mode_config(struct drm_device *drm)
179 {
180         drm_mode_config_init(drm);
181         drm->mode_config.min_width = 0;
182         drm->mode_config.min_height = 0;
183         drm->mode_config.max_width = HDLCD_MAX_XRES;
184         drm->mode_config.max_height = HDLCD_MAX_YRES;
185         drm->mode_config.funcs = &hdlcd_mode_config_funcs;
186 }
187
188 #ifdef CONFIG_DEBUG_FS
189 static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
190 {
191         struct drm_info_node *node = (struct drm_info_node *)m->private;
192         struct drm_device *drm = node->minor->dev;
193         struct hdlcd_drm_private *hdlcd = drm->dev_private;
194
195         seq_printf(m, "underrun : %d\n", atomic_read(&hdlcd->buffer_underrun_count));
196         seq_printf(m, "dma_end  : %d\n", atomic_read(&hdlcd->dma_end_count));
197         seq_printf(m, "bus_error: %d\n", atomic_read(&hdlcd->bus_error_count));
198         seq_printf(m, "vsync    : %d\n", atomic_read(&hdlcd->vsync_count));
199         return 0;
200 }
201
202 static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
203 {
204         struct drm_info_node *node = (struct drm_info_node *)m->private;
205         struct drm_device *drm = node->minor->dev;
206         struct hdlcd_drm_private *hdlcd = drm->dev_private;
207         unsigned long clkrate = clk_get_rate(hdlcd->clk);
208         unsigned long mode_clock = hdlcd->crtc.mode.crtc_clock * 1000;
209
210         seq_printf(m, "hw  : %lu\n", clkrate);
211         seq_printf(m, "mode: %lu\n", mode_clock);
212         return 0;
213 }
214
215 static struct drm_info_list hdlcd_debugfs_list[] = {
216         { "interrupt_count", hdlcd_show_underrun_count, 0 },
217         { "clocks", hdlcd_show_pxlclock, 0 },
218 };
219
220 static void hdlcd_debugfs_init(struct drm_minor *minor)
221 {
222         drm_debugfs_create_files(hdlcd_debugfs_list,
223                                  ARRAY_SIZE(hdlcd_debugfs_list),
224                                  minor->debugfs_root, minor);
225 }
226 #endif
227
228 DEFINE_DRM_GEM_DMA_FOPS(fops);
229
230 static const struct drm_driver hdlcd_driver = {
231         .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
232         DRM_GEM_DMA_DRIVER_OPS,
233 #ifdef CONFIG_DEBUG_FS
234         .debugfs_init = hdlcd_debugfs_init,
235 #endif
236         .fops = &fops,
237         .name = "hdlcd",
238         .desc = "ARM HDLCD Controller DRM",
239         .date = "20151021",
240         .major = 1,
241         .minor = 0,
242 };
243
244 static int hdlcd_drm_bind(struct device *dev)
245 {
246         struct drm_device *drm;
247         struct hdlcd_drm_private *hdlcd;
248         int ret;
249
250         hdlcd = devm_kzalloc(dev, sizeof(*hdlcd), GFP_KERNEL);
251         if (!hdlcd)
252                 return -ENOMEM;
253
254         drm = drm_dev_alloc(&hdlcd_driver, dev);
255         if (IS_ERR(drm))
256                 return PTR_ERR(drm);
257
258         drm->dev_private = hdlcd;
259         dev_set_drvdata(dev, drm);
260
261         hdlcd_setup_mode_config(drm);
262         ret = hdlcd_load(drm, 0);
263         if (ret)
264                 goto err_free;
265
266         /* Set the CRTC's port so that the encoder component can find it */
267         hdlcd->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
268
269         ret = component_bind_all(dev, drm);
270         if (ret) {
271                 DRM_ERROR("Failed to bind all components\n");
272                 goto err_unload;
273         }
274
275         ret = pm_runtime_set_active(dev);
276         if (ret)
277                 goto err_pm_active;
278
279         pm_runtime_enable(dev);
280
281         ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
282         if (ret < 0) {
283                 DRM_ERROR("failed to initialise vblank\n");
284                 goto err_vblank;
285         }
286
287         /*
288          * If EFI left us running, take over from simple framebuffer
289          * drivers. Read HDLCD_REG_COMMAND to see if we are enabled.
290          */
291         if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) {
292                 hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
293                 drm_aperture_remove_framebuffers(false, &hdlcd_driver);
294         }
295
296         drm_mode_config_reset(drm);
297         drm_kms_helper_poll_init(drm);
298
299         ret = drm_dev_register(drm, 0);
300         if (ret)
301                 goto err_register;
302
303         drm_fbdev_generic_setup(drm, 32);
304
305         return 0;
306
307 err_register:
308         drm_kms_helper_poll_fini(drm);
309 err_vblank:
310         pm_runtime_disable(drm->dev);
311 err_pm_active:
312         drm_atomic_helper_shutdown(drm);
313         component_unbind_all(dev, drm);
314 err_unload:
315         of_node_put(hdlcd->crtc.port);
316         hdlcd->crtc.port = NULL;
317         hdlcd_irq_uninstall(hdlcd);
318         of_reserved_mem_device_release(drm->dev);
319 err_free:
320         drm_mode_config_cleanup(drm);
321         dev_set_drvdata(dev, NULL);
322         drm_dev_put(drm);
323
324         return ret;
325 }
326
327 static void hdlcd_drm_unbind(struct device *dev)
328 {
329         struct drm_device *drm = dev_get_drvdata(dev);
330         struct hdlcd_drm_private *hdlcd = drm->dev_private;
331
332         drm_dev_unregister(drm);
333         drm_kms_helper_poll_fini(drm);
334         component_unbind_all(dev, drm);
335         of_node_put(hdlcd->crtc.port);
336         hdlcd->crtc.port = NULL;
337         pm_runtime_get_sync(dev);
338         drm_atomic_helper_shutdown(drm);
339         hdlcd_irq_uninstall(hdlcd);
340         pm_runtime_put(dev);
341         if (pm_runtime_enabled(dev))
342                 pm_runtime_disable(dev);
343         of_reserved_mem_device_release(dev);
344         drm_mode_config_cleanup(drm);
345         drm->dev_private = NULL;
346         dev_set_drvdata(dev, NULL);
347         drm_dev_put(drm);
348 }
349
350 static const struct component_master_ops hdlcd_master_ops = {
351         .bind           = hdlcd_drm_bind,
352         .unbind         = hdlcd_drm_unbind,
353 };
354
355 static int compare_dev(struct device *dev, void *data)
356 {
357         return dev->of_node == data;
358 }
359
360 static int hdlcd_probe(struct platform_device *pdev)
361 {
362         struct device_node *port;
363         struct component_match *match = NULL;
364
365         /* there is only one output port inside each device, find it */
366         port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
367         if (!port)
368                 return -ENODEV;
369
370         drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
371         of_node_put(port);
372
373         return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
374                                                match);
375 }
376
377 static int hdlcd_remove(struct platform_device *pdev)
378 {
379         component_master_del(&pdev->dev, &hdlcd_master_ops);
380         return 0;
381 }
382
383 static const struct of_device_id  hdlcd_of_match[] = {
384         { .compatible   = "arm,hdlcd" },
385         {},
386 };
387 MODULE_DEVICE_TABLE(of, hdlcd_of_match);
388
389 static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
390 {
391         struct drm_device *drm = dev_get_drvdata(dev);
392
393         return drm_mode_config_helper_suspend(drm);
394 }
395
396 static int __maybe_unused hdlcd_pm_resume(struct device *dev)
397 {
398         struct drm_device *drm = dev_get_drvdata(dev);
399
400         drm_mode_config_helper_resume(drm);
401
402         return 0;
403 }
404
405 static SIMPLE_DEV_PM_OPS(hdlcd_pm_ops, hdlcd_pm_suspend, hdlcd_pm_resume);
406
407 static struct platform_driver hdlcd_platform_driver = {
408         .probe          = hdlcd_probe,
409         .remove         = hdlcd_remove,
410         .driver = {
411                 .name = "hdlcd",
412                 .pm = &hdlcd_pm_ops,
413                 .of_match_table = hdlcd_of_match,
414         },
415 };
416
417 drm_module_platform_driver(hdlcd_platform_driver);
418
419 MODULE_AUTHOR("Liviu Dudau");
420 MODULE_DESCRIPTION("ARM HDLCD DRM driver");
421 MODULE_LICENSE("GPL v2");
This page took 0.063907 seconds and 4 git commands to generate.