]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/tinydrm/core/tinydrm-core.c
Merge branch 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[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_crtc_helper.h>
13 #include <drm/drm_fb_helper.h>
14 #include <drm/drm_gem_framebuffer_helper.h>
15 #include <drm/tinydrm/tinydrm.h>
16 #include <linux/device.h>
17 #include <linux/dma-buf.h>
18
19 /**
20  * DOC: overview
21  *
22  * This library provides driver helpers for very simple display hardware.
23  *
24  * It is based on &drm_simple_display_pipe coupled with a &drm_connector which
25  * has only one fixed &drm_display_mode. The framebuffers are backed by the
26  * cma helper and have support for framebuffer flushing (dirty).
27  * fbdev support is also included.
28  *
29  */
30
31 /**
32  * DOC: core
33  *
34  * The driver allocates &tinydrm_device, initializes it using
35  * devm_tinydrm_init(), sets up the pipeline using tinydrm_display_pipe_init()
36  * and registers the DRM device using devm_tinydrm_register().
37  */
38
39 static struct drm_framebuffer *
40 tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
41                   const struct drm_mode_fb_cmd2 *mode_cmd)
42 {
43         struct tinydrm_device *tdev = drm->dev_private;
44
45         return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd,
46                                             tdev->fb_funcs);
47 }
48
49 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
50         .fb_create = tinydrm_fb_create,
51         .atomic_check = drm_atomic_helper_check,
52         .atomic_commit = drm_atomic_helper_commit,
53 };
54
55 static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
56                         const struct drm_framebuffer_funcs *fb_funcs,
57                         struct drm_driver *driver)
58 {
59         struct drm_device *drm;
60
61         mutex_init(&tdev->dirty_lock);
62         tdev->fb_funcs = fb_funcs;
63
64         /*
65          * We don't embed drm_device, because that prevent us from using
66          * devm_kzalloc() to allocate tinydrm_device in the driver since
67          * drm_dev_put() frees the structure. The devm_ functions provide
68          * for easy error handling.
69          */
70         drm = drm_dev_alloc(driver, parent);
71         if (IS_ERR(drm))
72                 return PTR_ERR(drm);
73
74         tdev->drm = drm;
75         drm->dev_private = tdev;
76         drm_mode_config_init(drm);
77         drm->mode_config.funcs = &tinydrm_mode_config_funcs;
78         drm->mode_config.allow_fb_modifiers = true;
79
80         return 0;
81 }
82
83 static void tinydrm_fini(struct tinydrm_device *tdev)
84 {
85         drm_mode_config_cleanup(tdev->drm);
86         mutex_destroy(&tdev->dirty_lock);
87         tdev->drm->dev_private = NULL;
88         drm_dev_put(tdev->drm);
89 }
90
91 static void devm_tinydrm_release(void *data)
92 {
93         tinydrm_fini(data);
94 }
95
96 /**
97  * devm_tinydrm_init - Initialize tinydrm device
98  * @parent: Parent device object
99  * @tdev: tinydrm device
100  * @fb_funcs: Framebuffer functions
101  * @driver: DRM driver
102  *
103  * This function initializes @tdev, the underlying DRM device and it's
104  * mode_config. Resources will be automatically freed on driver detach (devres)
105  * using drm_mode_config_cleanup() and drm_dev_put().
106  *
107  * Returns:
108  * Zero on success, negative error code on failure.
109  */
110 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
111                       const struct drm_framebuffer_funcs *fb_funcs,
112                       struct drm_driver *driver)
113 {
114         int ret;
115
116         ret = tinydrm_init(parent, tdev, fb_funcs, driver);
117         if (ret)
118                 return ret;
119
120         ret = devm_add_action(parent, devm_tinydrm_release, tdev);
121         if (ret)
122                 tinydrm_fini(tdev);
123
124         return ret;
125 }
126 EXPORT_SYMBOL(devm_tinydrm_init);
127
128 static int tinydrm_register(struct tinydrm_device *tdev)
129 {
130         struct drm_device *drm = tdev->drm;
131         int ret;
132
133         ret = drm_dev_register(tdev->drm, 0);
134         if (ret)
135                 return ret;
136
137         ret = drm_fbdev_generic_setup(drm, 0);
138         if (ret)
139                 DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
140
141         return 0;
142 }
143
144 static void tinydrm_unregister(struct tinydrm_device *tdev)
145 {
146         drm_atomic_helper_shutdown(tdev->drm);
147         drm_dev_unregister(tdev->drm);
148 }
149
150 static void devm_tinydrm_register_release(void *data)
151 {
152         tinydrm_unregister(data);
153 }
154
155 /**
156  * devm_tinydrm_register - Register tinydrm device
157  * @tdev: tinydrm device
158  *
159  * This function registers the underlying DRM device and fbdev.
160  * These resources will be automatically unregistered on driver detach (devres)
161  * and the display pipeline will be disabled.
162  *
163  * Returns:
164  * Zero on success, negative error code on failure.
165  */
166 int devm_tinydrm_register(struct tinydrm_device *tdev)
167 {
168         struct device *dev = tdev->drm->dev;
169         int ret;
170
171         ret = tinydrm_register(tdev);
172         if (ret)
173                 return ret;
174
175         ret = devm_add_action(dev, devm_tinydrm_register_release, tdev);
176         if (ret)
177                 tinydrm_unregister(tdev);
178
179         return ret;
180 }
181 EXPORT_SYMBOL(devm_tinydrm_register);
182
183 /**
184  * tinydrm_shutdown - Shutdown tinydrm
185  * @tdev: tinydrm device
186  *
187  * This function makes sure that the display pipeline is disabled.
188  * Used by drivers in their shutdown callback to turn off the display
189  * on machine shutdown and reboot.
190  */
191 void tinydrm_shutdown(struct tinydrm_device *tdev)
192 {
193         drm_atomic_helper_shutdown(tdev->drm);
194 }
195 EXPORT_SYMBOL(tinydrm_shutdown);
196
197 MODULE_LICENSE("GPL");