]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/tinydrm/core/tinydrm-core.c
drm/tinydrm: Drop using tinydrm_device
[linux.git] / drivers / gpu / drm / tinydrm / core / tinydrm-core.c
1 /*
2  * Copyright (C) 2016 Noralf Trønnes
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 as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_drv.h>
13 #include <drm/drm_fb_helper.h>
14 #include <drm/drm_gem_framebuffer_helper.h>
15 #include <drm/drm_probe_helper.h>
16 #include <drm/drm_print.h>
17 #include <drm/tinydrm/tinydrm.h>
18 #include <linux/device.h>
19 #include <linux/dma-buf.h>
20 #include <linux/module.h>
21
22 /**
23  * DOC: overview
24  *
25  * This library provides driver helpers for very simple display hardware.
26  *
27  * It is based on &drm_simple_display_pipe coupled with a &drm_connector which
28  * has only one fixed &drm_display_mode. The framebuffers are backed by the
29  * cma helper and have support for framebuffer flushing (dirty).
30  * fbdev support is also included.
31  *
32  */
33
34 /**
35  * DOC: core
36  *
37  * The driver allocates &tinydrm_device, initializes it using
38  * devm_tinydrm_init(), sets up the pipeline using tinydrm_display_pipe_init()
39  * and registers the DRM device using devm_tinydrm_register().
40  */
41
42 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
43         .fb_create = drm_gem_fb_create_with_dirty,
44         .atomic_check = drm_atomic_helper_check,
45         .atomic_commit = drm_atomic_helper_commit,
46 };
47
48 static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
49                         struct drm_driver *driver)
50 {
51         struct drm_device *drm;
52
53         /*
54          * We don't embed drm_device, because that prevent us from using
55          * devm_kzalloc() to allocate tinydrm_device in the driver since
56          * drm_dev_put() frees the structure. The devm_ functions provide
57          * for easy error handling.
58          */
59         drm = drm_dev_alloc(driver, parent);
60         if (IS_ERR(drm))
61                 return PTR_ERR(drm);
62
63         tdev->drm = drm;
64         drm->dev_private = tdev;
65         drm_mode_config_init(drm);
66         drm->mode_config.funcs = &tinydrm_mode_config_funcs;
67         drm->mode_config.allow_fb_modifiers = true;
68
69         return 0;
70 }
71
72 static void tinydrm_fini(struct tinydrm_device *tdev)
73 {
74         drm_mode_config_cleanup(tdev->drm);
75         tdev->drm->dev_private = NULL;
76         drm_dev_put(tdev->drm);
77 }
78
79 static void devm_tinydrm_release(void *data)
80 {
81         tinydrm_fini(data);
82 }
83
84 /**
85  * devm_tinydrm_init - Initialize tinydrm device
86  * @parent: Parent device object
87  * @tdev: tinydrm device
88  * @driver: DRM driver
89  *
90  * This function initializes @tdev, the underlying DRM device and it's
91  * mode_config. Resources will be automatically freed on driver detach (devres)
92  * using drm_mode_config_cleanup() and drm_dev_put().
93  *
94  * Returns:
95  * Zero on success, negative error code on failure.
96  */
97 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
98                       struct drm_driver *driver)
99 {
100         int ret;
101
102         ret = tinydrm_init(parent, tdev, driver);
103         if (ret)
104                 return ret;
105
106         ret = devm_add_action(parent, devm_tinydrm_release, tdev);
107         if (ret)
108                 tinydrm_fini(tdev);
109
110         return ret;
111 }
112 EXPORT_SYMBOL(devm_tinydrm_init);
113
114 static int tinydrm_register(struct tinydrm_device *tdev)
115 {
116         struct drm_device *drm = tdev->drm;
117         int ret;
118
119         ret = drm_dev_register(tdev->drm, 0);
120         if (ret)
121                 return ret;
122
123         ret = drm_fbdev_generic_setup(drm, 0);
124         if (ret)
125                 DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
126
127         return 0;
128 }
129
130 static void tinydrm_unregister(struct tinydrm_device *tdev)
131 {
132         drm_atomic_helper_shutdown(tdev->drm);
133         drm_dev_unregister(tdev->drm);
134 }
135
136 static void devm_tinydrm_register_release(void *data)
137 {
138         tinydrm_unregister(data);
139 }
140
141 /**
142  * devm_tinydrm_register - Register tinydrm device
143  * @tdev: tinydrm device
144  *
145  * This function registers the underlying DRM device and fbdev.
146  * These resources will be automatically unregistered on driver detach (devres)
147  * and the display pipeline will be disabled.
148  *
149  * Returns:
150  * Zero on success, negative error code on failure.
151  */
152 int devm_tinydrm_register(struct tinydrm_device *tdev)
153 {
154         struct device *dev = tdev->drm->dev;
155         int ret;
156
157         ret = tinydrm_register(tdev);
158         if (ret)
159                 return ret;
160
161         ret = devm_add_action(dev, devm_tinydrm_register_release, tdev);
162         if (ret)
163                 tinydrm_unregister(tdev);
164
165         return ret;
166 }
167 EXPORT_SYMBOL(devm_tinydrm_register);
168
169 MODULE_LICENSE("GPL");