Merge tag 'drm-intel-next-2019-04-04' into gvt-next
[sfrench/cifs-2.6.git] / drivers / gpu / drm / arm / display / komeda / komeda_kms.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7 #include <linux/component.h>
8 #include <linux/interrupt.h>
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_cma_helper.h>
15 #include <drm/drm_gem_framebuffer_helper.h>
16 #include <drm/drm_vblank.h>
17
18 #include "komeda_dev.h"
19 #include "komeda_framebuffer.h"
20 #include "komeda_kms.h"
21
22 DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops);
23
24 static int komeda_gem_cma_dumb_create(struct drm_file *file,
25                                       struct drm_device *dev,
26                                       struct drm_mode_create_dumb *args)
27 {
28         u32 alignment = 16; /* TODO get alignment from dev */
29
30         args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8),
31                             alignment);
32
33         return drm_gem_cma_dumb_create_internal(file, dev, args);
34 }
35
36 static struct drm_driver komeda_kms_driver = {
37         .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
38                            DRIVER_PRIME,
39         .lastclose                      = drm_fb_helper_lastclose,
40         .gem_free_object_unlocked       = drm_gem_cma_free_object,
41         .gem_vm_ops                     = &drm_gem_cma_vm_ops,
42         .dumb_create                    = komeda_gem_cma_dumb_create,
43         .prime_handle_to_fd             = drm_gem_prime_handle_to_fd,
44         .prime_fd_to_handle             = drm_gem_prime_fd_to_handle,
45         .gem_prime_export               = drm_gem_prime_export,
46         .gem_prime_import               = drm_gem_prime_import,
47         .gem_prime_get_sg_table         = drm_gem_cma_prime_get_sg_table,
48         .gem_prime_import_sg_table      = drm_gem_cma_prime_import_sg_table,
49         .gem_prime_vmap                 = drm_gem_cma_prime_vmap,
50         .gem_prime_vunmap               = drm_gem_cma_prime_vunmap,
51         .gem_prime_mmap                 = drm_gem_cma_prime_mmap,
52         .fops = &komeda_cma_fops,
53         .name = "komeda",
54         .desc = "Arm Komeda Display Processor driver",
55         .date = "20181101",
56         .major = 0,
57         .minor = 1,
58 };
59
60 static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
61 {
62         struct drm_device *dev = old_state->dev;
63
64         drm_atomic_helper_commit_modeset_disables(dev, old_state);
65
66         drm_atomic_helper_commit_planes(dev, old_state, 0);
67
68         drm_atomic_helper_commit_modeset_enables(dev, old_state);
69
70         drm_atomic_helper_wait_for_flip_done(dev, old_state);
71
72         drm_atomic_helper_commit_hw_done(old_state);
73
74         drm_atomic_helper_cleanup_planes(dev, old_state);
75 }
76
77 static const struct drm_mode_config_helper_funcs komeda_mode_config_helpers = {
78         .atomic_commit_tail = komeda_kms_commit_tail,
79 };
80
81 static const struct drm_mode_config_funcs komeda_mode_config_funcs = {
82         .fb_create              = komeda_fb_create,
83         .atomic_check           = drm_atomic_helper_check,
84         .atomic_commit          = drm_atomic_helper_commit,
85 };
86
87 static void komeda_kms_mode_config_init(struct komeda_kms_dev *kms,
88                                         struct komeda_dev *mdev)
89 {
90         struct drm_mode_config *config = &kms->base.mode_config;
91
92         drm_mode_config_init(&kms->base);
93
94         komeda_kms_setup_crtcs(kms, mdev);
95
96         /* Get value from dev */
97         config->min_width       = 0;
98         config->min_height      = 0;
99         config->max_width       = 4096;
100         config->max_height      = 4096;
101         config->allow_fb_modifiers = false;
102
103         config->funcs = &komeda_mode_config_funcs;
104         config->helper_private = &komeda_mode_config_helpers;
105 }
106
107 struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev)
108 {
109         struct komeda_kms_dev *kms = kzalloc(sizeof(*kms), GFP_KERNEL);
110         struct drm_device *drm;
111         int err;
112
113         if (!kms)
114                 return ERR_PTR(-ENOMEM);
115
116         drm = &kms->base;
117         err = drm_dev_init(drm, &komeda_kms_driver, mdev->dev);
118         if (err)
119                 goto free_kms;
120
121         drm->dev_private = mdev;
122
123         komeda_kms_mode_config_init(kms, mdev);
124
125         err = komeda_kms_add_private_objs(kms, mdev);
126         if (err)
127                 goto cleanup_mode_config;
128
129         err = komeda_kms_add_planes(kms, mdev);
130         if (err)
131                 goto cleanup_mode_config;
132
133         err = drm_vblank_init(drm, kms->n_crtcs);
134         if (err)
135                 goto cleanup_mode_config;
136
137         err = komeda_kms_add_crtcs(kms, mdev);
138         if (err)
139                 goto cleanup_mode_config;
140
141         err = component_bind_all(mdev->dev, kms);
142         if (err)
143                 goto cleanup_mode_config;
144
145         drm_mode_config_reset(drm);
146
147         err = drm_dev_register(drm, 0);
148         if (err)
149                 goto cleanup_mode_config;
150
151         return kms;
152
153 cleanup_mode_config:
154         drm_mode_config_cleanup(drm);
155 free_kms:
156         kfree(kms);
157         return ERR_PTR(err);
158 }
159
160 void komeda_kms_detach(struct komeda_kms_dev *kms)
161 {
162         struct drm_device *drm = &kms->base;
163         struct komeda_dev *mdev = drm->dev_private;
164
165         drm_dev_unregister(drm);
166         component_unbind_all(mdev->dev, drm);
167         komeda_kms_cleanup_private_objs(mdev);
168         drm_mode_config_cleanup(drm);
169         drm->dev_private = NULL;
170         drm_dev_put(drm);
171 }