Merge tag 'ceph-for-6.7-rc1' of https://github.com/ceph/ceph-client
[linux-2.6-microblaze.git] / drivers / gpu / drm / fsl-dcu / fsl_dcu_drm_plane.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2015 Freescale Semiconductor, Inc.
4  *
5  * Freescale DCU drm device driver
6  */
7
8 #include <linux/regmap.h>
9
10 #include <drm/drm_atomic.h>
11 #include <drm/drm_atomic_helper.h>
12 #include <drm/drm_crtc.h>
13 #include <drm/drm_fb_dma_helper.h>
14 #include <drm/drm_fourcc.h>
15 #include <drm/drm_framebuffer.h>
16 #include <drm/drm_gem_dma_helper.h>
17 #include <drm/drm_plane_helper.h>
18 #include <drm/drm_probe_helper.h>
19
20 #include "fsl_dcu_drm_drv.h"
21 #include "fsl_dcu_drm_plane.h"
22
23 static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
24 {
25         struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
26         unsigned int total_layer = fsl_dev->soc->total_layer;
27         unsigned int index;
28
29         index = drm_plane_index(plane);
30         if (index < total_layer)
31                 return total_layer - index - 1;
32
33         dev_err(fsl_dev->dev, "No more layer left\n");
34         return -EINVAL;
35 }
36
37 static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
38                                           struct drm_atomic_state *state)
39 {
40         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
41                                                                                  plane);
42         struct drm_framebuffer *fb = new_plane_state->fb;
43
44         if (!new_plane_state->fb || !new_plane_state->crtc)
45                 return 0;
46
47         switch (fb->format->format) {
48         case DRM_FORMAT_RGB565:
49         case DRM_FORMAT_RGB888:
50         case DRM_FORMAT_XRGB8888:
51         case DRM_FORMAT_ARGB8888:
52         case DRM_FORMAT_XRGB4444:
53         case DRM_FORMAT_ARGB4444:
54         case DRM_FORMAT_XRGB1555:
55         case DRM_FORMAT_ARGB1555:
56         case DRM_FORMAT_YUV422:
57                 return 0;
58         default:
59                 return -EINVAL;
60         }
61 }
62
63 static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
64                                              struct drm_atomic_state *state)
65 {
66         struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
67         unsigned int value;
68         int index;
69
70         index = fsl_dcu_drm_plane_index(plane);
71         if (index < 0)
72                 return;
73
74         regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
75         value &= ~DCU_LAYER_EN;
76         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
77 }
78
79 static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
80                                             struct drm_atomic_state *state)
81
82 {
83         struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
84         struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
85                                                                            plane);
86         struct drm_framebuffer *fb = plane->state->fb;
87         struct drm_gem_dma_object *gem;
88         unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
89         int index;
90
91         if (!fb)
92                 return;
93
94         index = fsl_dcu_drm_plane_index(plane);
95         if (index < 0)
96                 return;
97
98         gem = drm_fb_dma_get_gem_obj(fb, 0);
99
100         switch (fb->format->format) {
101         case DRM_FORMAT_RGB565:
102                 bpp = FSL_DCU_RGB565;
103                 break;
104         case DRM_FORMAT_RGB888:
105                 bpp = FSL_DCU_RGB888;
106                 break;
107         case DRM_FORMAT_ARGB8888:
108                 alpha = DCU_LAYER_AB_WHOLE_FRAME;
109                 fallthrough;
110         case DRM_FORMAT_XRGB8888:
111                 bpp = FSL_DCU_ARGB8888;
112                 break;
113         case DRM_FORMAT_ARGB4444:
114                 alpha = DCU_LAYER_AB_WHOLE_FRAME;
115                 fallthrough;
116         case DRM_FORMAT_XRGB4444:
117                 bpp = FSL_DCU_ARGB4444;
118                 break;
119         case DRM_FORMAT_ARGB1555:
120                 alpha = DCU_LAYER_AB_WHOLE_FRAME;
121                 fallthrough;
122         case DRM_FORMAT_XRGB1555:
123                 bpp = FSL_DCU_ARGB1555;
124                 break;
125         case DRM_FORMAT_YUV422:
126                 bpp = FSL_DCU_YUV422;
127                 break;
128         default:
129                 return;
130         }
131
132         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
133                      DCU_LAYER_HEIGHT(new_state->crtc_h) |
134                      DCU_LAYER_WIDTH(new_state->crtc_w));
135         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
136                      DCU_LAYER_POSY(new_state->crtc_y) |
137                      DCU_LAYER_POSX(new_state->crtc_x));
138         regmap_write(fsl_dev->regmap,
139                      DCU_CTRLDESCLN(index, 3), gem->dma_addr);
140         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
141                      DCU_LAYER_EN |
142                      DCU_LAYER_TRANS(0xff) |
143                      DCU_LAYER_BPP(bpp) |
144                      alpha);
145         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
146                      DCU_LAYER_CKMAX_R(0xFF) |
147                      DCU_LAYER_CKMAX_G(0xFF) |
148                      DCU_LAYER_CKMAX_B(0xFF));
149         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
150                      DCU_LAYER_CKMIN_R(0) |
151                      DCU_LAYER_CKMIN_G(0) |
152                      DCU_LAYER_CKMIN_B(0));
153         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
154         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
155                      DCU_LAYER_FG_FCOLOR(0));
156         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
157                      DCU_LAYER_BG_BCOLOR(0));
158
159         if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
160                 regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
161                              DCU_LAYER_POST_SKIP(0) |
162                              DCU_LAYER_PRE_SKIP(0));
163         }
164
165         return;
166 }
167
168 static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
169         .atomic_check = fsl_dcu_drm_plane_atomic_check,
170         .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
171         .atomic_update = fsl_dcu_drm_plane_atomic_update,
172 };
173
174 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
175         .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
176         .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
177         .destroy = drm_plane_helper_destroy,
178         .disable_plane = drm_atomic_helper_disable_plane,
179         .reset = drm_atomic_helper_plane_reset,
180         .update_plane = drm_atomic_helper_update_plane,
181 };
182
183 static const u32 fsl_dcu_drm_plane_formats[] = {
184         DRM_FORMAT_RGB565,
185         DRM_FORMAT_RGB888,
186         DRM_FORMAT_XRGB8888,
187         DRM_FORMAT_ARGB8888,
188         DRM_FORMAT_XRGB4444,
189         DRM_FORMAT_ARGB4444,
190         DRM_FORMAT_XRGB1555,
191         DRM_FORMAT_ARGB1555,
192         DRM_FORMAT_YUV422,
193 };
194
195 void fsl_dcu_drm_init_planes(struct drm_device *dev)
196 {
197         struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
198         int i, j;
199
200         for (i = 0; i < fsl_dev->soc->total_layer; i++) {
201                 for (j = 1; j <= fsl_dev->soc->layer_regs; j++)
202                         regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);
203         }
204 }
205
206 struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
207 {
208         struct drm_plane *primary;
209         int ret;
210
211         primary = kzalloc(sizeof(*primary), GFP_KERNEL);
212         if (!primary) {
213                 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
214                 return NULL;
215         }
216
217         /* possible_crtc's will be filled in later by crtc_init */
218         ret = drm_universal_plane_init(dev, primary, 0,
219                                        &fsl_dcu_drm_plane_funcs,
220                                        fsl_dcu_drm_plane_formats,
221                                        ARRAY_SIZE(fsl_dcu_drm_plane_formats),
222                                        NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
223         if (ret) {
224                 kfree(primary);
225                 primary = NULL;
226         }
227         drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
228
229         return primary;
230 }