RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / kernel / drivers / staging / imgtec / adf_common.c
1 /*************************************************************************/ /*!
2 @File
3 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4 @License        Dual MIT/GPLv2
5
6 The contents of this file are subject to the MIT license as set out below.
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 Alternatively, the contents of this file may be used under the terms of
19 the GNU General Public License Version 2 ("GPL") in which case the provisions
20 of GPL are applicable instead of those above.
21
22 If you wish to allow use of your version of this file only under the terms of
23 GPL, and not to allow others to use your version of this file under the terms
24 of the MIT license, indicate your decision by deleting the provisions above
25 and replace them with the notice and other provisions required by GPL as set
26 out in the file called "GPL-COPYING" included in this distribution. If you do
27 not delete the provisions above, a recipient may use your version of this file
28 under the terms of either the MIT license or GPL.
29
30 This License is also included in this distribution in the file called
31 "MIT-COPYING".
32
33 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
34 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
35 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
37 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
38 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 */ /**************************************************************************/
41 /* vi: set ts=8: */
42
43 #include "adf_common.h"
44
45 #include <linux/uaccess.h>
46 #include <linux/slab.h>
47 #include <linux/dma-buf.h>
48 #include <linux/compat.h>
49 #include <linux/bug.h>
50
51 #include <video/adf_client.h>
52
53 #ifdef DEBUG_VALIDATE
54 #define val_dbg(dev, fmt, x...) dev_dbg(dev, fmt, x)
55 #else
56 #define val_dbg(dev, fmt, x...) do { } while (0)
57 #endif
58
59 static long validate(struct adf_device *dev,
60         struct adf_validate_config_ext __user *arg)
61 {
62         struct adf_interface **intfs = NULL;
63         struct adf_buffer *bufs = NULL;
64         struct adf_post post_cfg;
65         u32 post_ext_size;
66         void *driver_state;
67         int err = 0;
68         size_t i, j;
69
70         if (arg->n_interfaces > ADF_MAX_INTERFACES) {
71                 err = -EINVAL;
72                 goto err_out;
73         }
74
75         if (arg->n_bufs > ADF_MAX_BUFFERS) {
76                 err = -EINVAL;
77                 goto err_out;
78         }
79
80         post_ext_size = sizeof(struct adf_post_ext) +
81                 arg->n_bufs * sizeof(struct adf_buffer_config_ext);
82
83         if (!access_ok(VERIFY_READ, arg->bufs,
84                        sizeof(struct adf_buffer_config) * arg->n_bufs)) {
85                 err = -EFAULT;
86                 goto err_out;
87         }
88
89         if (!access_ok(VERIFY_READ, arg->post_ext,
90                        post_ext_size)) {
91                 err = -EFAULT;
92                 goto err_out;
93         }
94
95         if (arg->n_interfaces) {
96                 if (!access_ok(VERIFY_READ, arg->interfaces,
97                      sizeof(*arg->interfaces) * arg->n_interfaces)) {
98                         err = -EFAULT;
99                         goto err_out;
100                 }
101                 intfs = kmalloc_array(arg->n_interfaces, sizeof(intfs[0]),
102                                       GFP_KERNEL);
103                 if (!intfs) {
104                         err = -ENOMEM;
105                         goto err_out;
106                 }
107         }
108
109         for (i = 0; i < arg->n_interfaces; i++) {
110                 intfs[i] = idr_find(&dev->interfaces, arg->interfaces[i]);
111                 if (!intfs[i]) {
112                         err = -EINVAL;
113                         goto err_out;
114                 }
115         }
116
117         if (arg->n_bufs) {
118                 bufs = kcalloc(arg->n_bufs, sizeof(bufs[0]), GFP_KERNEL);
119                 if (!bufs) {
120                         err = -ENOMEM;
121                         goto err_out;
122                 }
123         }
124
125         for (i = 0; i < arg->n_bufs; i++) {
126                 struct adf_buffer_config *config = &arg->bufs[i];
127
128                 memset(&bufs[i], 0, sizeof(bufs[i]));
129
130                 if (config->n_planes > ADF_MAX_PLANES) {
131                         err = -EINVAL;
132                         goto err_import;
133                 }
134
135                 bufs[i].overlay_engine = idr_find(&dev->overlay_engines,
136                                                   config->overlay_engine);
137                 if (!bufs[i].overlay_engine) {
138                         err = -ENOENT;
139                         goto err_import;
140                 }
141
142                 bufs[i].w = config->w;
143                 bufs[i].h = config->h;
144                 bufs[i].format = config->format;
145
146                 for (j = 0; j < config->n_planes; j++) {
147                         bufs[i].dma_bufs[j] = dma_buf_get(config->fd[j]);
148                         if (IS_ERR_OR_NULL(bufs[i].dma_bufs[j])) {
149                                 err = PTR_ERR(bufs[i].dma_bufs[j]);
150                                 bufs[i].dma_bufs[j] = NULL;
151                                 goto err_import;
152                         }
153                         bufs[i].offset[j] = config->offset[j];
154                         bufs[i].pitch[j] = config->pitch[j];
155                 }
156                 bufs[i].n_planes = config->n_planes;
157
158                 bufs[i].acquire_fence = NULL;
159         }
160
161         /* Fake up a post configuration to validate */
162         post_cfg.custom_data_size = post_ext_size;
163         post_cfg.custom_data = arg->post_ext;
164         post_cfg.n_bufs = arg->n_bufs;
165         post_cfg.bufs = bufs;
166
167         /* Mapping dma bufs is too expensive for validate, and we don't
168          * need to do it at the moment.
169          */
170         post_cfg.mappings = NULL;
171
172         err = dev->ops->validate(dev, &post_cfg, &driver_state);
173         if (err)
174                 goto err_import;
175
176         /* For the validate ioctl, we don't need the driver state. If it
177          * was allocated, free it immediately.
178          */
179         if (dev->ops->state_free)
180                 dev->ops->state_free(dev, driver_state);
181
182 err_import:
183         for (i = 0; i < arg->n_bufs; i++)
184                 for (j = 0; j < ARRAY_SIZE(bufs[i].dma_bufs); j++)
185                         if (bufs[i].dma_bufs[j])
186                                 dma_buf_put(bufs[i].dma_bufs[j]);
187 err_out:
188         kfree(intfs);
189         kfree(bufs);
190         return err;
191 }
192
193 static long adf_img_ioctl_validate(struct adf_device *dev,
194 struct adf_validate_config_ext __user *arg)
195 {
196         int err;
197
198         if (!access_ok(VERIFY_READ, arg,
199              sizeof(struct adf_validate_config_ext))) {
200                 err = -EFAULT;
201                 goto err_out;
202         }
203         err = validate(dev, arg);
204 err_out:
205         return err;
206 }
207
208 #ifdef CONFIG_COMPAT
209
210 #define ADF_VALIDATE_CONFIG_EXT32 \
211         _IOW(ADF_IOCTL_TYPE, ADF_IOCTL_NR_VALIDATE_IMG, \
212                 struct adf_validate_config_ext32)
213
214 struct adf_validate_config_ext32 {
215         __u32           n_interfaces;
216         compat_uptr_t   interfaces;
217
218         __u32           n_bufs;
219
220         compat_uptr_t   bufs;
221         compat_uptr_t   post_ext;
222 } __packed;
223
224 /* adf_validate_config_ext32 must map to the adf_validate_config_ext struct.
225  * Changes to struct adf_validate_config_ext will likely be needed to be
226  * mirrored in adf_validate_config_ext32, so put a sanity check here to try
227  * to notice if the size has changed from what's expected.
228  */
229
230 static long adf_img_ioctl_validate_compat(struct adf_device *dev,
231                   struct adf_validate_config_ext32 __user *arg_compat)
232 {
233         struct adf_validate_config_ext arg;
234         int err = 0;
235
236         BUILD_BUG_ON_MSG(sizeof(struct adf_validate_config_ext) != 32,
237                 "adf_validate_config_ext has unexpected size");
238
239         if (!access_ok(VERIFY_READ, arg_compat,
240                 sizeof(struct adf_validate_config_ext32))) {
241                 err = -EFAULT;
242                 goto err_out;
243         }
244
245         arg.n_interfaces = arg_compat->n_interfaces;
246         arg.interfaces = compat_ptr(arg_compat->interfaces);
247         arg.n_bufs = arg_compat->n_bufs;
248         arg.bufs = compat_ptr(arg_compat->bufs);
249         arg.post_ext = compat_ptr(arg_compat->post_ext);
250
251         err = validate(dev, &arg);
252 err_out:
253         return err;
254 }
255
256 #endif /* CONFIG_COMPAT */
257
258 long adf_img_ioctl(struct adf_obj *obj, unsigned int cmd, unsigned long arg)
259 {
260         struct adf_device *dev =
261                 (struct adf_device *)obj->parent;
262
263         switch (cmd) {
264         case ADF_VALIDATE_CONFIG_EXT:
265                 return adf_img_ioctl_validate(dev,
266                         (struct adf_validate_config_ext __user *)arg);
267 #ifdef CONFIG_COMPAT
268         case ADF_VALIDATE_CONFIG_EXT32:
269                 return adf_img_ioctl_validate_compat(dev,
270                         (struct adf_validate_config_ext32 __user *)
271                                                         compat_ptr(arg));
272 #endif
273         }
274
275         return -ENOTTY;
276 }
277
278 /* Callers of this function should have taken the dev->client_lock */
279
280 static struct adf_interface *
281 get_interface_attached_to_overlay(struct adf_device *dev,
282                                   struct adf_overlay_engine *overlay)
283 {
284         struct adf_interface *interface = NULL;
285         struct adf_attachment_list *entry;
286
287         /* We are open-coding adf_attachment_list_to_array. We can't use the
288          * adf_device_attachments helper because it takes the client lock,
289          * which is already held for calls to validate.
290          */
291         list_for_each_entry(entry, &dev->attached, head) {
292                 /* If there are multiple interfaces attached to an overlay,
293                  * this will return the last.
294                  */
295                 if (entry->attachment.overlay_engine == overlay)
296                         interface = entry->attachment.interface;
297         }
298
299         return interface;
300 }
301
302 int adf_img_validate_simple(struct adf_device *dev, struct adf_post *cfg,
303                             void **driver_state)
304 {
305         struct adf_post_ext *post_ext = cfg->custom_data;
306         struct adf_overlay_engine *overlay;
307         struct adf_interface *interface;
308         struct adf_buffer *buffer;
309         int i = 0;
310         struct device *device = dev->dev;
311         size_t expected_custom_data_size;
312
313         /* "Null" flip handling */
314         if (cfg->n_bufs == 0)
315                 return 0;
316
317         expected_custom_data_size = sizeof(struct adf_post_ext)
318                 + cfg->n_bufs * sizeof(struct adf_buffer_config_ext);
319         if (cfg->custom_data_size != expected_custom_data_size) {
320                 val_dbg(device, "Custom data size %zu not expected size %zu",
321                          cfg->custom_data_size,
322                          sizeof(struct adf_buffer_config_ext));
323                 return -EINVAL;
324         }
325
326         if (cfg->n_bufs != 1) {
327                 val_dbg(device, "Got %zu buffers in post. Should be 1.\n",
328                         cfg->n_bufs);
329                 return -EINVAL;
330         }
331
332         buffer = &cfg->bufs[0];
333         overlay = buffer->overlay_engine;
334         if (!overlay) {
335                 dev_err(device, "Buffer without an overlay engine.\n");
336                 return -EINVAL;
337         }
338
339         for (i = 0; i < overlay->ops->n_supported_formats; i++) {
340                 if (buffer->format == overlay->ops->supported_formats[i])
341                         break;
342         }
343
344         if (i == overlay->ops->n_supported_formats) {
345                 char req_format_str[ADF_FORMAT_STR_SIZE];
346
347                 adf_format_str(buffer->format, req_format_str);
348
349                 val_dbg(device, "Unsupported buffer format %s.\n",
350                         req_format_str);
351                 return -EINVAL;
352         }
353
354         interface = get_interface_attached_to_overlay(dev, overlay);
355         if (!interface) {
356                 dev_err(device, "No interface attached to overlay\n");
357                 return -EINVAL;
358         }
359
360         if (buffer->w != interface->current_mode.hdisplay) {
361                 val_dbg(device, "Buffer width %u is not expected %u.\n",
362                          buffer->w, interface->current_mode.hdisplay);
363                 return -EINVAL;
364         }
365
366         if (buffer->h != interface->current_mode.vdisplay) {
367                 val_dbg(device, "Buffer height %u is not expected %u.\n",
368                          buffer->h, interface->current_mode.vdisplay);
369                 return -EINVAL;
370         }
371
372         if (buffer->n_planes != 1) {
373                 val_dbg(device, "Buffer n_planes %u is not 1.\n",
374                         buffer->n_planes);
375                 return -EINVAL;
376         }
377
378         if (buffer->offset[0] != 0) {
379                 val_dbg(device, "Buffer offset %u is not 0.\n",
380                         buffer->offset[0]);
381                 return -EINVAL;
382         }
383
384         for (i = 0; i < cfg->n_bufs; i++) {
385                 struct adf_buffer_config_ext *buf_ext = &post_ext->bufs_ext[i];
386                 u16 hdisplay = interface->current_mode.hdisplay;
387                 u16 vdisplay = interface->current_mode.vdisplay;
388
389                 if (buf_ext->crop.x1 != 0 ||
390                     buf_ext->crop.y1 != 0 ||
391                     buf_ext->crop.x2 != hdisplay ||
392                     buf_ext->crop.y2 != vdisplay) {
393                         val_dbg(device, "Buffer crop {%u,%u,%u,%u} not expected {%u,%u,%u,%u}.\n",
394                                 buf_ext->crop.x1, buf_ext->crop.y1,
395                                 buf_ext->crop.x2, buf_ext->crop.y2,
396                                 0, 0, hdisplay, vdisplay);
397
398                         /* Userspace might be emulating a lower resolution */
399                         if (buf_ext->crop.x2 > hdisplay ||
400                             buf_ext->crop.y2 > vdisplay)
401                                 return -EINVAL;
402                 }
403
404                 if (buf_ext->display.x1 != 0 ||
405                     buf_ext->display.y1 != 0 ||
406                     buf_ext->display.x2 != hdisplay ||
407                     buf_ext->display.y2 != vdisplay) {
408                         val_dbg(device, "Buffer display {%u,%u,%u,%u} not expected {%u,%u,%u,%u}.\n",
409                                 buf_ext->display.x1, buf_ext->display.y1,
410                                 buf_ext->display.x2, buf_ext->display.y2,
411                                 0, 0, hdisplay, vdisplay);
412
413                         /* Userspace might be emulating a lower resolution */
414                         if (buf_ext->display.x2 > hdisplay ||
415                             buf_ext->display.y2 > vdisplay)
416                                 return -EINVAL;
417                 }
418
419                 if (buf_ext->transform != ADF_BUFFER_TRANSFORM_NONE_EXT) {
420                         val_dbg(device, "Buffer transform 0x%x not expected transform 0x%x.\n",
421                                 buf_ext->transform,
422                                 ADF_BUFFER_TRANSFORM_NONE_EXT);
423                         return -EINVAL;
424                 }
425
426                 if (buf_ext->blend_type != ADF_BUFFER_BLENDING_PREMULT_EXT &&
427                     buf_ext->blend_type != ADF_BUFFER_BLENDING_NONE_EXT) {
428                         val_dbg(device, "Buffer blend type %u not supported.\n",
429                                 buf_ext->blend_type);
430                         return -EINVAL;
431                 }
432
433                 if (buf_ext->plane_alpha != 0xff) {
434                         val_dbg(device, "Buffer plane alpha %u not expected plane alpha %u.\n",
435                                 buf_ext->plane_alpha, 0xff);
436                         return -EINVAL;
437                 }
438         }
439
440         return 0;
441 }
442
443 bool adf_img_buffer_sanity_check(const struct adf_interface *intf,
444         const struct adf_buffer *buf,
445         const struct adf_buffer_config_ext *buf_ext)
446 {
447         struct device *dev = intf->base.parent->dev;
448         int plane;
449
450         if (buf->w == 0) {
451                 dev_err(dev, "Buffer sanity failed: Zero width\n");
452                 return false;
453         }
454         if (buf->h == 0) {
455                 dev_err(dev, "Buffer sanity failed: Zero height\n");
456                 return false;
457         }
458         if (buf->format == 0) {
459                 dev_err(dev, "Buffer sanity failed: Zero format\n");
460                 return false;
461         }
462         if (buf->pitch == 0) {
463                 dev_err(dev, "Buffer sanity failed: Zero pitch\n");
464                 return false;
465         }
466         if (buf->n_planes == 0) {
467                 dev_err(dev, "Buffer sanity failed: Zero plane count\n");
468                 return false;
469         }
470         if (buf->overlay_engine == NULL) {
471                 dev_err(dev, "Buffer sanity failed: NULL assigned overlay\n");
472                 return false;
473         }
474
475         for (plane = 0; plane < buf->n_planes; plane++) {
476                 if (buf->dma_bufs[plane] == NULL) {
477                         dev_err(dev, "Buffer sanity failed: NULL dma buf for plane %d\n",
478                                 plane);
479                         return false;
480                 }
481                 if (buf->pitch[plane] == 0) {
482                         dev_err(dev, "Buffer sanity failed: Zero pitch for plane %d\n",
483                                 plane);
484                         return false;
485                 }
486                 /* The offset may be zero, so we can't check that here */
487         }
488
489         if (buf_ext->crop.x1 >= buf_ext->crop.x2 ||
490             buf_ext->crop.y1 >= buf_ext->crop.y2) {
491                 dev_err(dev, "Buffer sanity failed: Invalid crop rect (%d,%d)(%d,%d)\n",
492                         buf_ext->crop.x1, buf_ext->crop.y1,
493                         buf_ext->crop.x2, buf_ext->crop.y2);
494                 return false;
495         }
496
497         if (buf_ext->crop.x1 > buf->w ||
498             buf_ext->crop.x2 > buf->w ||
499             buf_ext->crop.y1 > buf->h ||
500             buf_ext->crop.y2 > buf->h) {
501                 dev_err(dev, "Buffer sanity failed: Crop rect (%d,%d)(%d,%d) outside of %dx%d source buffer\n",
502                         buf_ext->crop.x1, buf_ext->crop.y1,
503                         buf_ext->crop.x2, buf_ext->crop.y2,
504                         buf->w, buf->h);
505                 return false;
506         }
507
508         if (buf_ext->display.x1 >= buf_ext->display.x2 ||
509             buf_ext->display.y1 >= buf_ext->display.y2) {
510                 dev_err(dev, "Buffer sanity failed: Invalid display rect (%d,%d)(%d,%d)\n",
511                         buf_ext->display.x1, buf_ext->display.y1,
512                         buf_ext->display.x2, buf_ext->display.y2);
513                 return false;
514         }
515
516         if (buf_ext->crop.x1 > buf->w ||
517             buf_ext->crop.x2 > buf->w ||
518             buf_ext->crop.y1 > buf->h ||
519             buf_ext->crop.y2 > buf->h) {
520                 dev_err(dev, "Buffer sanity failed: Display rect (%d,%d)(%d,%d) outside of %dx%d current interface mode\n",
521                         buf_ext->crop.x1, buf_ext->crop.y1,
522                         buf_ext->crop.x2, buf_ext->crop.y2,
523                         intf->current_mode.hdisplay,
524                         intf->current_mode.vdisplay);
525             return false;
526         }
527
528         switch (buf_ext->transform) {
529         case ADF_BUFFER_TRANSFORM_NONE_EXT:
530         case ADF_BUFFER_TRANSFORM_FLIP_H_EXT:
531         case ADF_BUFFER_TRANSFORM_FLIP_V_EXT:
532         case ADF_BUFFER_TRANSFORM_ROT_90_EXT:
533         case ADF_BUFFER_TRANSFORM_ROT_180_EXT:
534         case ADF_BUFFER_TRANSFORM_ROT_270_EXT:
535                 break;
536         default:
537                 dev_err(dev, "Invalid transform 0x%x\n", buf_ext->transform);
538                 return false;
539         }
540
541         switch (buf_ext->blend_type) {
542         case ADF_BUFFER_BLENDING_NONE_EXT:
543         case ADF_BUFFER_BLENDING_PREMULT_EXT:
544         case ADF_BUFFER_BLENDING_COVERAGE_EXT:
545                 break;
546         default:
547                 dev_err(dev, "Invalid blend type 0x%x\n", buf_ext->blend_type);
548                 return false;
549         }
550         return true;
551 }
552
553 bool adf_img_rects_intersect(const struct drm_clip_rect *rect1,
554         const struct drm_clip_rect *rect2)
555 {
556         if (rect1->x1 < rect2->x2 &&
557             rect1->x2 > rect2->x1 &&
558             rect1->y1 < rect2->y2 &&
559             rect1->y2 > rect2->y1)
560                 return true;
561         return false;
562 }
563
564