drm/msm/hdmi: Enable HPD after HDMI IRQ is set up
[linux/fpc-iii.git] / drivers / gpu / drm / tinydrm / core / tinydrm-core.c
blob19c7f70adfa5b7f29545108292c82cb83c6039f8
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/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>
19 /**
20 * DOC: overview
22 * This library provides driver helpers for very simple display hardware.
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.
31 /**
32 * DOC: core
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().
39 /**
40 * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from
41 * another driver's scatter/gather table of pinned pages
42 * @drm: DRM device to import into
43 * @attach: DMA-BUF attachment
44 * @sgt: Scatter/gather table of pinned pages
46 * This function imports a scatter/gather table exported via DMA-BUF by
47 * another driver using drm_gem_cma_prime_import_sg_table(). It sets the
48 * kernel virtual address on the CMA object. Drivers should use this as their
49 * &drm_driver->gem_prime_import_sg_table callback if they need the virtual
50 * address. tinydrm_gem_cma_free_object() should be used in combination with
51 * this function.
53 * Returns:
54 * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
55 * error code on failure.
57 struct drm_gem_object *
58 tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm,
59 struct dma_buf_attachment *attach,
60 struct sg_table *sgt)
62 struct drm_gem_cma_object *cma_obj;
63 struct drm_gem_object *obj;
64 void *vaddr;
66 vaddr = dma_buf_vmap(attach->dmabuf);
67 if (!vaddr) {
68 DRM_ERROR("Failed to vmap PRIME buffer\n");
69 return ERR_PTR(-ENOMEM);
72 obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt);
73 if (IS_ERR(obj)) {
74 dma_buf_vunmap(attach->dmabuf, vaddr);
75 return obj;
78 cma_obj = to_drm_gem_cma_obj(obj);
79 cma_obj->vaddr = vaddr;
81 return obj;
83 EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table);
85 /**
86 * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM
87 * object
88 * @gem_obj: GEM object to free
90 * This function frees the backing memory of the CMA GEM object, cleans up the
91 * GEM object state and frees the memory used to store the object itself using
92 * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel
93 * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers
94 * can use this as their &drm_driver->gem_free_object_unlocked callback.
96 void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
98 if (gem_obj->import_attach) {
99 struct drm_gem_cma_object *cma_obj;
101 cma_obj = to_drm_gem_cma_obj(gem_obj);
102 dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
103 cma_obj->vaddr = NULL;
106 drm_gem_cma_free_object(gem_obj);
108 EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
110 static struct drm_framebuffer *
111 tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
112 const struct drm_mode_fb_cmd2 *mode_cmd)
114 struct tinydrm_device *tdev = drm->dev_private;
116 return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd,
117 tdev->fb_funcs);
120 static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = {
121 .fb_create = tinydrm_fb_create,
122 .atomic_check = drm_atomic_helper_check,
123 .atomic_commit = drm_atomic_helper_commit,
126 static int tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
127 const struct drm_framebuffer_funcs *fb_funcs,
128 struct drm_driver *driver)
130 struct drm_device *drm;
132 mutex_init(&tdev->dirty_lock);
133 tdev->fb_funcs = fb_funcs;
136 * We don't embed drm_device, because that prevent us from using
137 * devm_kzalloc() to allocate tinydrm_device in the driver since
138 * drm_dev_unref() frees the structure. The devm_ functions provide
139 * for easy error handling.
141 drm = drm_dev_alloc(driver, parent);
142 if (IS_ERR(drm))
143 return PTR_ERR(drm);
145 tdev->drm = drm;
146 drm->dev_private = tdev;
147 drm_mode_config_init(drm);
148 drm->mode_config.funcs = &tinydrm_mode_config_funcs;
150 return 0;
153 static void tinydrm_fini(struct tinydrm_device *tdev)
155 drm_mode_config_cleanup(tdev->drm);
156 mutex_destroy(&tdev->dirty_lock);
157 tdev->drm->dev_private = NULL;
158 drm_dev_unref(tdev->drm);
161 static void devm_tinydrm_release(void *data)
163 tinydrm_fini(data);
167 * devm_tinydrm_init - Initialize tinydrm device
168 * @parent: Parent device object
169 * @tdev: tinydrm device
170 * @fb_funcs: Framebuffer functions
171 * @driver: DRM driver
173 * This function initializes @tdev, the underlying DRM device and it's
174 * mode_config. Resources will be automatically freed on driver detach (devres)
175 * using drm_mode_config_cleanup() and drm_dev_unref().
177 * Returns:
178 * Zero on success, negative error code on failure.
180 int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev,
181 const struct drm_framebuffer_funcs *fb_funcs,
182 struct drm_driver *driver)
184 int ret;
186 ret = tinydrm_init(parent, tdev, fb_funcs, driver);
187 if (ret)
188 return ret;
190 ret = devm_add_action(parent, devm_tinydrm_release, tdev);
191 if (ret)
192 tinydrm_fini(tdev);
194 return ret;
196 EXPORT_SYMBOL(devm_tinydrm_init);
198 static int tinydrm_register(struct tinydrm_device *tdev)
200 struct drm_device *drm = tdev->drm;
201 int ret;
203 ret = drm_dev_register(tdev->drm, 0);
204 if (ret)
205 return ret;
207 ret = drm_fbdev_generic_setup(drm, 0);
208 if (ret)
209 DRM_ERROR("Failed to initialize fbdev: %d\n", ret);
211 return 0;
214 static void tinydrm_unregister(struct tinydrm_device *tdev)
216 drm_atomic_helper_shutdown(tdev->drm);
217 drm_dev_unregister(tdev->drm);
220 static void devm_tinydrm_register_release(void *data)
222 tinydrm_unregister(data);
226 * devm_tinydrm_register - Register tinydrm device
227 * @tdev: tinydrm device
229 * This function registers the underlying DRM device and fbdev.
230 * These resources will be automatically unregistered on driver detach (devres)
231 * and the display pipeline will be disabled.
233 * Returns:
234 * Zero on success, negative error code on failure.
236 int devm_tinydrm_register(struct tinydrm_device *tdev)
238 struct device *dev = tdev->drm->dev;
239 int ret;
241 ret = tinydrm_register(tdev);
242 if (ret)
243 return ret;
245 ret = devm_add_action(dev, devm_tinydrm_register_release, tdev);
246 if (ret)
247 tinydrm_unregister(tdev);
249 return ret;
251 EXPORT_SYMBOL(devm_tinydrm_register);
254 * tinydrm_shutdown - Shutdown tinydrm
255 * @tdev: tinydrm device
257 * This function makes sure that the display pipeline is disabled.
258 * Used by drivers in their shutdown callback to turn off the display
259 * on machine shutdown and reboot.
261 void tinydrm_shutdown(struct tinydrm_device *tdev)
263 drm_atomic_helper_shutdown(tdev->drm);
265 EXPORT_SYMBOL(tinydrm_shutdown);
267 MODULE_LICENSE("GPL");