rcutorture: Eliminate unused ts_rem local from rcu_trace_clock_local()
[linux/fpc-iii.git] / drivers / gpu / drm / tinydrm / core / tinydrm-core.c
blob551709e6b11449d2086b98966979f54991b570c6
1 /*
2 * Copyright (C) 2016 Noralf Trønnes
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 */
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_crtc_helper.h>
13 #include <drm/tinydrm/tinydrm.h>
14 #include <linux/device.h>
15 #include <linux/dma-buf.h>
17 /**
18 * DOC: overview
20 * This library provides driver helpers for very simple display hardware.
22 * It is based on &drm_simple_display_pipe coupled with a &drm_connector which
23 * has only one fixed &drm_display_mode. The framebuffers are backed by the
24 * cma helper and have support for framebuffer flushing (dirty).
25 * fbdev support is also included.
29 /**
30 * DOC: core
32 * The driver allocates &tinydrm_device, initializes it using
33 * devm_tinydrm_init(), sets up the pipeline using tinydrm_display_pipe_init()
34 * and registers the DRM device using devm_tinydrm_register().
37 /**
38 * tinydrm_lastclose - DRM lastclose helper
39 * @drm: DRM device
41 * This function ensures that fbdev is restored when drm_lastclose() is called
42 * on the last drm_release(). Drivers can use this as their
43 * &drm_driver->lastclose callback.
45 void tinydrm_lastclose(struct drm_device *drm)
47 struct tinydrm_device *tdev = drm->dev_private;
49 DRM_DEBUG_KMS("\n");
50 drm_fbdev_cma_restore_mode(tdev->fbdev_cma);
52 EXPORT_SYMBOL(tinydrm_lastclose);
54 /**
55 * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from
56 * another driver's scatter/gather table of pinned pages
57 * @drm: DRM device to import into
58 * @attach: DMA-BUF attachment
59 * @sgt: Scatter/gather table of pinned pages
61 * This function imports a scatter/gather table exported via DMA-BUF by
62 * another driver using drm_gem_cma_prime_import_sg_table(). It sets the
63 * kernel virtual address on the CMA object. Drivers should use this as their
64 * &drm_driver->gem_prime_import_sg_table callback if they need the virtual
65 * address. tinydrm_gem_cma_free_object() should be used in combination with
66 * this function.
68 * Returns:
69 * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
70 * error code on failure.
72 struct drm_gem_object *
73 tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
74 struct dma_buf_attachment *attach,
75 struct sg_table *sgt)
77 struct drm_gem_cma_object *cma_obj;
78 struct drm_gem_object *obj;
79 void *vaddr;
81 vaddr = dma_buf_vmap(attach->dmabuf);
82 if (!vaddr) {
83 DRM_ERROR("Failed to vmap PRIME buffer\n");
84 return ERR_PTR(-ENOMEM);
87 obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt);
88 if (IS_ERR(obj)) {
89 dma_buf_vunmap(attach->dmabuf, vaddr);
90 return obj;
93 cma_obj = to_drm_gem_cma_obj(obj);
94 cma_obj->vaddr = vaddr;
96 return obj;
98 EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table);
101 * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM
102 * object
103 * @gem_obj: GEM object to free
105 * This function frees the backing memory of the CMA GEM object, cleans up the
106 * GEM object state and frees the memory used to store the object itself using
107 * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel
108 * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers
109 * can use this as their &drm_driver->gem_free_object callback.
111 void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
113 if (gem_obj->import_attach) {
114 struct drm_gem_cma_object *cma_obj;
116 cma_obj = to_drm_gem_cma_obj(gem_obj);
117 dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
118 cma_obj->vaddr = NULL;
121 drm_gem_cma_free_object(gem_obj);
123 EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
125 static struct drm_framebuffer *
126 tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
127 const struct drm_mode_fb_cmd2 *mode_cmd)
129 struct tinydrm_device *tdev = drm->dev_private;
131 return drm_fb_cma_create_with_funcs(drm, file_priv, mode_cmd,
132 tdev->fb_funcs);
135 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
136 .fb_create = tinydrm_fb_create,
137 .atomic_check = drm_atomic_helper_check,
138 .atomic_commit = drm_atomic_helper_commit,
141 static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
142 const struct drm_framebuffer_funcs *fb_funcs,
143 struct drm_driver *driver)
145 struct drm_device *drm;
147 mutex_init(&tdev->dirty_lock);
148 tdev->fb_funcs = fb_funcs;
151 * We don't embed drm_device, because that prevent us from using
152 * devm_kzalloc() to allocate tinydrm_device in the driver since
153 * drm_dev_unref() frees the structure. The devm_ functions provide
154 * for easy error handling.
156 drm = drm_dev_alloc(driver, parent);
157 if (IS_ERR(drm))
158 return PTR_ERR(drm);
160 tdev->drm = drm;
161 drm->dev_private = tdev;
162 drm_mode_config_init(drm);
163 drm->mode_config.funcs = &tinydrm_mode_config_funcs;
165 return 0;
168 static void tinydrm_fini(struct tinydrm_device *tdev)
170 drm_mode_config_cleanup(tdev->drm);
171 mutex_destroy(&tdev->dirty_lock);
172 tdev->drm->dev_private = NULL;
173 drm_dev_unref(tdev->drm);
176 static void devm_tinydrm_release(void *data)
178 tinydrm_fini(data);
182 * devm_tinydrm_init - Initialize tinydrm device
183 * @parent: Parent device object
184 * @tdev: tinydrm device
185 * @fb_funcs: Framebuffer functions
186 * @driver: DRM driver
188 * This function initializes @tdev, the underlying DRM device and it's
189 * mode_config. Resources will be automatically freed on driver detach (devres)
190 * using drm_mode_config_cleanup() and drm_dev_unref().
192 * Returns:
193 * Zero on success, negative error code on failure.
195 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
196 const struct drm_framebuffer_funcs *fb_funcs,
197 struct drm_driver *driver)
199 int ret;
201 ret = tinydrm_init(parent, tdev, fb_funcs, driver);
202 if (ret)
203 return ret;
205 ret = devm_add_action(parent, devm_tinydrm_release, tdev);
206 if (ret)
207 tinydrm_fini(tdev);
209 return ret;
211 EXPORT_SYMBOL(devm_tinydrm_init);
213 static int tinydrm_register(struct tinydrm_device *tdev)
215 struct drm_device *drm = tdev->drm;
216 int bpp = drm->mode_config.preferred_depth;
217 struct drm_fbdev_cma *fbdev;
218 int ret;
220 ret = drm_dev_register(tdev->drm, 0);
221 if (ret)
222 return ret;
224 fbdev = drm_fbdev_cma_init_with_funcs(drm, bpp ? bpp : 32,
225 drm->mode_config.num_connector,
226 tdev->fb_funcs);
227 if (IS_ERR(fbdev))
228 DRM_ERROR("Failed to initialize fbdev: %ld\n", PTR_ERR(fbdev));
229 else
230 tdev->fbdev_cma = fbdev;
232 return 0;
235 static void tinydrm_unregister(struct tinydrm_device *tdev)
237 struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma;
239 drm_atomic_helper_shutdown(tdev->drm);
240 /* don't restore fbdev in lastclose, keep pipeline disabled */
241 tdev->fbdev_cma = NULL;
242 drm_dev_unregister(tdev->drm);
243 if (fbdev_cma)
244 drm_fbdev_cma_fini(fbdev_cma);
247 static void devm_tinydrm_register_release(void *data)
249 tinydrm_unregister(data);
253 * devm_tinydrm_register - Register tinydrm device
254 * @tdev: tinydrm device
256 * This function registers the underlying DRM device and fbdev.
257 * These resources will be automatically unregistered on driver detach (devres)
258 * and the display pipeline will be disabled.
260 * Returns:
261 * Zero on success, negative error code on failure.
263 int devm_tinydrm_register(struct tinydrm_device *tdev)
265 struct device *dev = tdev->drm->dev;
266 int ret;
268 ret = tinydrm_register(tdev);
269 if (ret)
270 return ret;
272 ret = devm_add_action(dev, devm_tinydrm_register_release, tdev);
273 if (ret)
274 tinydrm_unregister(tdev);
276 return ret;
278 EXPORT_SYMBOL(devm_tinydrm_register);
281 * tinydrm_shutdown - Shutdown tinydrm
282 * @tdev: tinydrm device
284 * This function makes sure that the display pipeline is disabled.
285 * Used by drivers in their shutdown callback to turn off the display
286 * on machine shutdown and reboot.
288 void tinydrm_shutdown(struct tinydrm_device *tdev)
290 drm_atomic_helper_shutdown(tdev->drm);
292 EXPORT_SYMBOL(tinydrm_shutdown);
295 * tinydrm_suspend - Suspend tinydrm
296 * @tdev: tinydrm device
298 * Used in driver PM operations to suspend tinydrm.
299 * Suspends fbdev and DRM.
300 * Resume with tinydrm_resume().
302 * Returns:
303 * Zero on success, negative error code on failure.
305 int tinydrm_suspend(struct tinydrm_device *tdev)
307 struct drm_atomic_state *state;
309 if (tdev->suspend_state) {
310 DRM_ERROR("Failed to suspend: state already set\n");
311 return -EINVAL;
314 drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 1);
315 state = drm_atomic_helper_suspend(tdev->drm);
316 if (IS_ERR(state)) {
317 drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0);
318 return PTR_ERR(state);
321 tdev->suspend_state = state;
323 return 0;
325 EXPORT_SYMBOL(tinydrm_suspend);
328 * tinydrm_resume - Resume tinydrm
329 * @tdev: tinydrm device
331 * Used in driver PM operations to resume tinydrm.
332 * Suspend with tinydrm_suspend().
334 * Returns:
335 * Zero on success, negative error code on failure.
337 int tinydrm_resume(struct tinydrm_device *tdev)
339 struct drm_atomic_state *state = tdev->suspend_state;
340 int ret;
342 if (!state) {
343 DRM_ERROR("Failed to resume: state is not set\n");
344 return -EINVAL;
347 tdev->suspend_state = NULL;
349 ret = drm_atomic_helper_resume(tdev->drm, state);
350 if (ret) {
351 DRM_ERROR("Error resuming state: %d\n", ret);
352 return ret;
355 drm_fbdev_cma_set_suspend_unlocked(tdev->fbdev_cma, 0);
357 return 0;
359 EXPORT_SYMBOL(tinydrm_resume);
361 MODULE_LICENSE("GPL");