RK3368 GPU version Rogue M 1.28
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / rogue_m / kernel / drivers / staging / imgtec / adf_sunxi.c
1 /*************************************************************************/ /*!
2 @File           adf_sunxi.c
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
44 #include <video/adf.h>
45 #include <video/adf_client.h>
46 #include <linux/slab.h>
47 #include <linux/seq_file.h>
48 #include <linux/debugfs.h>
49
50 #ifdef SUPPORT_ADF_SUNXI_FBDEV
51 #include <video/adf_fbdev.h>
52 #endif
53
54 #include PVR_ANDROID_ION_HEADER
55 #include PVR_ANDROID_SYNC_HEADER
56
57 #include <linux/sw_sync.h>
58
59 #include "adf_common.h"
60 #include "adf_sunxi.h"
61
62 #include "pvrmodule.h"
63
64 #define MAX_DISPLAYS 2
65 /* This is the maximum number of overlays per display
66  * Any global limitation validation must be done in either adf_sunxi_attach()
67  * or adf_sunxi_validate() */
68 #define NUM_OVERLAYS 4
69 #define NUM_BLENDER_PIPES 2
70 #define MAX_BUFFERS (MAX_DISPLAYS * NUM_OVERLAYS)
71
72 #define DEBUG_POST_DUMP_COUNT 4
73 #define VALIDATE_LOG_LINES 50
74 #define VALIDATE_LOG_LINE_SIZE 50
75
76 #ifdef ADF_VERBOSE_DEBUG
77 #define sunxi_dbg(x...) dev_dbg(x)
78 #else
79 #define sunxi_dbg(...)
80 #endif
81
82 struct sunxi_interface {
83         struct adf_interface interface;
84         enum adf_interface_type adf_type;
85         const char *name;
86
87         int num_supported_modes;
88         struct drm_mode_modeinfo *supported_modes;
89
90         bool connected;
91
92         int display_id;
93         disp_output_type disp_type;
94 };
95
96
97 struct sunxi_overlay {
98         struct adf_overlay_engine overlay;
99         /* <0 means not attached, otherwise offset in sunxi.interfaces */
100         struct sunxi_interface *interface;
101 };
102
103 struct {
104         struct adf_device device;
105         struct device *dev;
106         struct sunxi_interface interfaces[MAX_DISPLAYS];
107         struct sunxi_overlay overlays[MAX_DISPLAYS][NUM_OVERLAYS];
108         struct ion_client *ion_client;
109         u32 ion_heap_id;
110         atomic_t refcount;
111
112         struct disp_composer_ops disp_ops;
113
114         /* Used to dump the last config to debugfs file */
115         struct setup_dispc_data last_config[DEBUG_POST_DUMP_COUNT];
116         u32 last_config_id[DEBUG_POST_DUMP_COUNT];
117         int last_config_pos;
118
119         char validate_log[VALIDATE_LOG_LINES][VALIDATE_LOG_LINE_SIZE];
120         int validate_log_position;
121
122         struct dentry *debugfs_config_file;
123         struct dentry *debugfs_val_log;
124
125         atomic_t postcount;
126         atomic_t callbackcount;
127
128         wait_queue_head_t post_wait_queue;
129
130 #ifdef SUPPORT_ADF_SUNXI_FBDEV
131         struct adf_fbdev fbdev;
132 #endif
133 } sunxi;
134
135 static const u32 sunxi_supported_formats[] = {
136         DRM_FORMAT_BGRA8888,
137         DRM_FORMAT_BGRX8888,
138         DRM_FORMAT_ARGB8888,
139         DRM_FORMAT_XRGB8888,
140         DRM_FORMAT_YVU420,
141 };
142 #define NUM_SUPPORTED_FORMATS ARRAY_SIZE(sunxi_supported_formats)
143
144 static void val_log(u32 post_id, const char *fmt, ...)
145 {
146         va_list args;
147         char *str;
148         int offset;
149
150         sunxi.validate_log_position = (sunxi.validate_log_position + 1)
151                 % VALIDATE_LOG_LINES;
152
153         str = sunxi.validate_log[sunxi.validate_log_position];
154
155         offset = snprintf(str, VALIDATE_LOG_LINE_SIZE, "id %u:",
156                 post_id);
157
158         va_start(args, fmt);
159         vsnprintf(str+offset, VALIDATE_LOG_LINE_SIZE-offset, fmt, args);
160         va_end(args);
161 }
162
163 static bool
164 is_supported_format(u32 drm_format)
165 {
166         int i;
167
168         for (i = 0; i < NUM_SUPPORTED_FORMATS; i++) {
169                 if (sunxi_supported_formats[i] == drm_format)
170                         return true;
171         }
172         return false;
173 }
174
175 static disp_pixel_format
176 sunxi_format_to_disp(u32 format)
177 {
178         switch (format) {
179         case DRM_FORMAT_BGRA8888:
180                 return DISP_FORMAT_ARGB_8888;
181         case DRM_FORMAT_ARGB8888:
182                 return DISP_FORMAT_BGRA_8888;
183         case DRM_FORMAT_BGRX8888:
184                 return DISP_FORMAT_XRGB_8888;
185         case DRM_FORMAT_XRGB8888:
186                 return DISP_FORMAT_BGRX_8888;
187         case DRM_FORMAT_YVU420:
188                 return DISP_FORMAT_YUV420_P;
189         default:
190                 BUG();
191                 return -1;
192         }
193 }
194
195 static bool
196 sunxi_format_has_alpha(u32 format)
197 {
198         switch (format) {
199         case DRM_FORMAT_BGRA8888:
200         case DRM_FORMAT_ARGB8888:
201                 return true;
202         case DRM_FORMAT_BGRX8888:
203         case DRM_FORMAT_XRGB8888:
204         case DRM_FORMAT_YVU420:
205                 return false;
206         default:
207                 BUG();
208                 return false;
209         }
210 }
211
212 static u32
213 sunxi_format_bpp(u32 format)
214 {
215         switch (format) {
216         case DRM_FORMAT_BGRA8888:
217         case DRM_FORMAT_BGRX8888:
218         case DRM_FORMAT_ARGB8888:
219         case DRM_FORMAT_XRGB8888:
220                 return 4;
221         case DRM_FORMAT_YVU420:
222                 return 1;
223         default:
224                 BUG();
225                 return 0;
226         }
227 }
228
229 static bool
230 sunxi_format_uv_is_swapped(u32 format)
231 {
232         switch (format) {
233         case DRM_FORMAT_BGRA8888:
234         case DRM_FORMAT_BGRX8888:
235         case DRM_FORMAT_ARGB8888:
236         case DRM_FORMAT_XRGB8888:
237                 return false;
238         case DRM_FORMAT_YVU420:
239                 return true;
240         default:
241                 BUG();
242                 return false;
243         }
244 }
245
246 static bool
247 buffer_is_scaled(const struct adf_buffer_config_ext *ext_config_data)
248 {
249         int srcWidth = ext_config_data->crop.x2 - ext_config_data->crop.x1;
250         int srcHeight = ext_config_data->crop.y2 - ext_config_data->crop.y1;
251         int dstWidth = ext_config_data->display.x2
252                 - ext_config_data->display.x1;
253         int dstHeight = ext_config_data->display.y2
254                 - ext_config_data->display.y1;
255         if (srcWidth != dstWidth ||
256             srcHeight != dstHeight)
257                 return true;
258         else
259                 return false;
260 }
261
262 static int
263 sunxi_buffer_to_layer_info(const struct adf_buffer *buf,
264         const struct adf_buffer_config_ext *ext_config_data,
265         const struct adf_buffer_mapping *mappings, disp_layer_info *layer)
266 {
267         int plane;
268
269         if (buffer_is_scaled(ext_config_data))
270                 layer->mode = DISP_LAYER_WORK_MODE_SCALER;
271         else
272                 layer->mode = DISP_LAYER_WORK_MODE_NORMAL;
273
274         /* Pipe/z are set in the parent function */
275         layer->pipe = 0;
276         layer->zorder = 0;
277         /*  0 = per-pixel alpha, 1 = global alpha */
278         switch (ext_config_data->blend_type) {
279         case ADF_BUFFER_BLENDING_NONE_EXT:
280                 layer->alpha_mode = 1;
281                 layer->alpha_value = 255;
282                 break;
283         case ADF_BUFFER_BLENDING_PREMULT_EXT:
284                 if (sunxi_format_has_alpha(buf->format))
285                         layer->alpha_mode = 0;
286                 else
287                         layer->alpha_mode = 1;
288                 layer->alpha_value = ext_config_data->plane_alpha;
289                 layer->fb.pre_multiply = true;
290                 break;
291         case ADF_BUFFER_BLENDING_COVERAGE_EXT:
292                 dev_err(sunxi.dev, "Coverage blending not implemented\n");
293                 return -1;
294         default:
295                 dev_err(sunxi.dev, "Unknown blending type %d\n",
296                         ext_config_data->blend_type);
297                 return -1;
298
299         }
300         layer->ck_enable = false;
301         layer->screen_win.x = ext_config_data->display.x1;
302         layer->screen_win.y = ext_config_data->display.y1;
303         layer->screen_win.width = ext_config_data->display.x2 -
304                 ext_config_data->display.x1;
305         layer->screen_win.height = ext_config_data->display.y2 -
306                 ext_config_data->display.y1;
307
308         if (mappings) {
309                 for (plane = 0; plane < buf->n_planes; plane++) {
310                         layer->fb.addr[plane] =
311                                 sg_phys(mappings->sg_tables[plane]->sgl) +
312                                 buf->offset[plane];
313                 }
314
315                 /* Fix up planar formats with VU plane ordering. For some
316                  * reason this is not properly handled by the sunxi disp
317                  * driver for sun9i.
318                  */
319                 if (sunxi_format_uv_is_swapped(buf->format)) {
320                         unsigned int tmp = layer->fb.addr[1];
321                         layer->fb.addr[1] = layer->fb.addr[2];
322                         layer->fb.addr[2] = tmp;
323                 }
324         }
325
326         layer->fb.size.width = buf->pitch[0] / sunxi_format_bpp(buf->format);
327         layer->fb.size.height = buf->h;
328         layer->fb.format = sunxi_format_to_disp(buf->format);
329         layer->fb.src_win.x = ext_config_data->crop.x1;
330         layer->fb.src_win.y = ext_config_data->crop.y1;
331         /*  fb.src_win.width/height is only used for scaled layers */
332         layer->fb.src_win.width = ext_config_data->crop.x2 -
333                 ext_config_data->crop.x1;
334         layer->fb.src_win.height = ext_config_data->crop.y2 -
335                 ext_config_data->crop.y1;
336
337         return 0;
338 }
339
340 static int
341 adf_sunxi_open(struct adf_obj *obj, struct inode *inode, struct file *file)
342 {
343         atomic_inc(&sunxi.refcount);
344         return 0;
345 }
346
347 static void adf_sunxi_set_hotplug_state(struct sunxi_interface *intf,
348         bool enable);
349
350 static void
351 adf_sunxi_release(struct adf_obj *obj, struct inode *inode, struct file *file)
352 {
353         struct sync_fence *release_fence;
354         int dpy;
355
356         if (atomic_dec_return(&sunxi.refcount))
357                 return;
358
359         /* NULL flip to push buffer off screen */
360         release_fence = adf_device_post(obj->parent, NULL, 0, NULL, 0, NULL, 0);
361
362         if (IS_ERR_OR_NULL(release_fence)) {
363                 dev_err(obj->parent->dev, "Failed to queue null flip command (err=%d)\n",
364                         (int)PTR_ERR(release_fence));
365                 return;
366         }
367
368         /* Disable any hotplug events */
369         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
370                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_NONE)
371                         continue;
372                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_HDMI)
373                         adf_sunxi_set_hotplug_state(&sunxi.interfaces[dpy],
374                                 false);
375         }
376
377         sync_fence_put(release_fence);
378 }
379
380 struct pipe_assignments {
381         int pipe[MAX_BUFFERS];
382 };
383 static void adf_sunxi_state_free(struct adf_device *dev, void *driver_state)
384 {
385         struct pipe_assignments *pipe_assignments =
386                 driver_state;
387
388         kfree(pipe_assignments);
389 }
390
391 static int get_buf_display(struct adf_buffer *buf)
392 {
393         int dpy, ovl;
394
395         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
396                 for (ovl = 0; ovl < NUM_OVERLAYS; ovl++) {
397                         if (&sunxi.overlays[dpy][ovl].overlay ==
398                                 buf->overlay_engine) {
399                                 goto found_ovl;
400                         }
401                 }
402         }
403         return -1;
404 found_ovl:
405         return dpy;
406 }
407
408 struct pipe_assignment_state {
409         int current_pipe[MAX_DISPLAYS];
410         int max_pipe[MAX_DISPLAYS];
411         int current_pipe_layers[MAX_DISPLAYS];
412
413         struct drm_clip_rect current_pipe_rects[MAX_DISPLAYS][NUM_OVERLAYS];
414 };
415
416 static int
417 assign_pipe(struct pipe_assignment_state *state, int dpy, bool blended,
418         struct drm_clip_rect *display_rect)
419 {
420         struct drm_clip_rect *current_pipe_rects =
421                 &state->current_pipe_rects[dpy][0];
422         int rect;
423
424         /* The sunxi display block appears to support a single blender
425         * taking multiple input rects, so long as the blended
426         * rects do not overlap */
427         if (blended) {
428                 for (rect = 0; rect < state->current_pipe_layers[dpy]; rect++) {
429                         const struct drm_clip_rect *layer_rect = &
430                                 current_pipe_rects[rect];
431                         if (!adf_img_rects_intersect(layer_rect,
432                                 display_rect)) {
433                                 continue;
434                         }
435                         /* We need to assign a new pipe */
436                         state->current_pipe[dpy]++;
437                         state->current_pipe_layers[dpy] = 0;
438                         if (state->current_pipe[dpy] >=
439                                 state->max_pipe[dpy]) {
440                                 return -1;
441                         }
442                 }
443         }
444         current_pipe_rects[state->current_pipe_layers[dpy]] =
445                 *display_rect;
446         state->current_pipe_layers[dpy]++;
447
448         return state->current_pipe[dpy];
449 }
450
451 static int adf_sunxi_validate(struct adf_device *dev, struct adf_post *cfg,
452         void **driver_state)
453 {
454         int i, dpy, pipe;
455         struct adf_post_ext *post_ext = cfg->custom_data;
456         struct adf_buffer_config_ext *bufs_ext;
457         size_t expected_custom_data_size;
458
459         struct pipe_assignment_state pipe_state;
460         struct pipe_assignments *pipe_assignments;
461         bool scaler_in_use[MAX_DISPLAYS];
462         int err = 0;
463         u32 post_id;
464
465         bool is_post = cfg->n_bufs && cfg->bufs[0].acquire_fence != NULL;
466
467         if (cfg->n_bufs == 0) {
468                 val_log(0, "NULL flip\n");
469                 return 0;
470         }
471
472         if (!post_ext) {
473                 dev_err(dev->dev, "Invalid custom data pointer\n");
474                 return -EINVAL;
475         }
476         post_id = post_ext->post_id;
477
478         expected_custom_data_size = sizeof(struct adf_post_ext)
479                 + cfg->n_bufs * sizeof(struct adf_buffer_config_ext);
480         if (cfg->custom_data_size != expected_custom_data_size) {
481                 dev_err(dev->dev, "Invalid custom data size - expected %u for %u buffers, got %u\n",
482                         expected_custom_data_size, cfg->n_bufs,
483                         cfg->custom_data_size);
484                 return -EINVAL;
485         }
486
487         bufs_ext = &post_ext->bufs_ext[0];
488
489         /* Reset blend pipe state */
490         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
491                 scaler_in_use[dpy] = false;
492                 pipe_state.current_pipe[dpy] = 0;
493                 pipe_state.current_pipe_layers[dpy] = 0;
494         }
495
496         /* NOTE: The current method of assigning pipes over multiple displays
497          * is unknown and needs experimentation/documentation to correct.
498          * The current assumption is that there are 2 blend sources (pipe 0
499          * and 1) on the internal display, and only 1 (pipe 0) on hdmi */
500         if (sunxi.interfaces[DISPLAY_HDMI].connected) {
501                 pipe_state.max_pipe[DISPLAY_HDMI] = 1;
502                 pipe_state.current_pipe[DISPLAY_HDMI] = 0;
503                 pipe_state.max_pipe[DISPLAY_INTERNAL] = NUM_BLENDER_PIPES;
504                 pipe_state.current_pipe[DISPLAY_INTERNAL] = 1;
505         } else {
506                 pipe_state.max_pipe[DISPLAY_INTERNAL] = NUM_BLENDER_PIPES;
507                 pipe_state.current_pipe[DISPLAY_INTERNAL] = 0;
508                 pipe_state.max_pipe[DISPLAY_HDMI] = 0;
509                 pipe_state.current_pipe[DISPLAY_HDMI] = 0;
510         }
511
512         pipe_assignments =
513                 kzalloc(sizeof(struct pipe_assignments), GFP_KERNEL);
514         if (!pipe_assignments) {
515                 dev_err(dev->dev, "Failed to allocate pipe assignment state\n");
516                 err = -ENOMEM;
517                 goto err_free_assignments;
518         }
519
520
521         if (cfg->n_bufs > MAX_BUFFERS) {
522                 dev_err(dev->dev, "Trying to post %d buffers (max %d)\n",
523                         MAX_BUFFERS, NUM_OVERLAYS);
524                 err = -EINVAL;
525                 goto err_free_assignments;
526         }
527
528         for (i = 0; i < cfg->n_bufs; i++) {
529                 bool buffer_is_sane;
530                 struct adf_buffer *buf = &cfg->bufs[i];
531                 struct adf_buffer_config_ext *ebuf = &bufs_ext[i];
532
533                 dpy = get_buf_display(buf);
534                 if (dpy < 0) {
535                         dev_err(dev->dev, "Buffer %d has invalid assigned overlay\n",
536                                 i);
537                         err = -EINVAL;
538                         goto err_free_assignments;
539                 }
540
541                 buffer_is_sane =
542                         adf_img_buffer_sanity_check(
543                                 &sunxi.interfaces[dpy].interface,
544                                 buf,
545                                 ebuf);
546
547                 if (!buffer_is_sane) {
548                         dev_err(dev->dev, "Buffer %d failed sanity check\n",
549                                 i);
550                         err = -EINVAL;
551                         goto err_free_assignments;
552                 }
553
554                 if (!is_supported_format(buf->format)) {
555                         /* This should be cleanly rejected when trying to assign
556                          * an overlay engine */
557                         dev_err(dev->dev, "Buffer %d has unrecognised format 0x%08x\n",
558                                 i, buf->format);
559                         err = -EINVAL;
560                         goto err_free_assignments;
561                 }
562                 if (buffer_is_scaled(ebuf)) {
563                         /* The assumption is that there is a single scaled
564                          * layer allowed per display, otherwise there may
565                          * be a unbounded top end to the samples required per
566                          * frame when testing validity a single layer at a time
567                          * */
568                         if (scaler_in_use[dpy]) {
569                                 val_log(post_id, "Buffer %d is second scaled layer\n",
570                                         i);
571                                 err = -EINVAL;
572                                 goto err_free_assignments;
573                         }
574                         scaler_in_use[dpy] = true;
575                         if (!sunxi.disp_ops.is_support_scaler_layer(dpy,
576                                 ebuf->crop.x2 - ebuf->crop.x1,
577                                 ebuf->crop.y2 - ebuf->crop.y1,
578                                 ebuf->display.x2 - ebuf->display.x1,
579                                 ebuf->display.y2 - ebuf->display.y1)) {
580                                         val_log(post_id, "Buffer %d unsupported scaled layer\n",
581                                                 i);
582                                         err = -EINVAL;
583                                         goto err_free_assignments;
584                                 }
585                 }
586                 if (ebuf->transform != ADF_BUFFER_TRANSFORM_NONE_EXT) {
587                         /* TODO: Sunxi transform support */
588                         val_log(post_id, "Transformed layers not supported at the minute\n");
589                         err = -EINVAL;
590                         goto err_free_assignments;
591                 }
592
593                 if (ebuf->blend_type != ADF_BUFFER_BLENDING_NONE_EXT &&
594                     ebuf->plane_alpha != 255 &&
595                     sunxi_format_has_alpha(buf->format)) {
596                         /* The sunxi display block appears to only support
597                          * pixel /or/ global (plane) alpha, not both */
598                         val_log(post_id, "Layer has both plane and pixel alpha\n");
599                         err = -EINVAL;
600                         goto err_free_assignments;
601                 }
602
603                 pipe = assign_pipe(&pipe_state, dpy,
604                         ebuf->blend_type != ADF_BUFFER_BLENDING_NONE_EXT,
605                         &ebuf->display);
606
607                 if (pipe < 0) {
608                         val_log(post_id, "Ran out of blend pipes\n");
609                         err = -EINVAL;
610                         goto err_free_assignments;
611                 }
612                 pipe_assignments->pipe[i] = pipe;
613         }
614         val_log(post_id, "Validate succeeded\n");
615
616         *driver_state = pipe_assignments;
617
618         return 0;
619 err_free_assignments:
620         if (is_post)
621                 dev_err(dev->dev, "Failed validate for post\n");
622         kfree(pipe_assignments);
623         return err;
624 }
625
626 static void sunxi_retire_callback(void)
627 {
628         atomic_inc(&sunxi.callbackcount);
629         wake_up(&sunxi.post_wait_queue);
630 }
631
632 static bool sunxi_post_completed(u32 post_id)
633 {
634         return (atomic_read(&sunxi.callbackcount) >= post_id);
635 }
636
637 static void adf_sunxi_post(struct adf_device *adf_dev, struct adf_post *cfg,
638         void *driver_state)
639 {
640         struct setup_dispc_data *disp_data;
641         int err, buf;
642         struct adf_post_ext *post_ext = cfg->custom_data;
643         struct adf_buffer_config_ext *ext_config_data = NULL;
644         int num_buffers[MAX_DISPLAYS];
645         int dpy;
646         struct pipe_assignments *pipe_assignments;
647         u32 post_count, post_id;
648         /* Allow a timeout of 4 frames before we force the frame off-screen */
649         long timeout =
650                 msecs_to_jiffies((1000 / 60) * 4);
651
652         if (cfg->n_bufs == 0) {
653                 val_log(0, "NULL flip\n");
654                 post_id = 0;
655                 post_ext = NULL;
656         } else {
657                 BUG_ON(post_ext == NULL);
658                 post_id = post_ext->post_id;
659                 ext_config_data = &post_ext->bufs_ext[0];
660                 val_log(post_id, "Posting\n");
661         }
662
663         pipe_assignments = driver_state;
664         if (!pipe_assignments && cfg->n_bufs != 0) {
665                 dev_err(adf_dev->dev, "Invalid driver state\n");
666                 return;
667         }
668
669         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++)
670                 num_buffers[dpy] = 0;
671
672         disp_data = kzalloc(sizeof(struct setup_dispc_data), GFP_KERNEL);
673         if (!disp_data) {
674                 dev_err(adf_dev->dev, "Failed to allocate post data");
675                 return;
676         }
677
678         for (buf = 0; buf < cfg->n_bufs; buf++) {
679
680                 dpy = get_buf_display(&cfg->bufs[buf]);
681                 if (dpy < 0) {
682                         dev_err(adf_dev->dev, "Invalid overlay %p assigned to layer %d",
683                                 cfg->bufs[buf].overlay_engine, buf);
684                         goto err_free_data;
685                 }
686
687                 err = sunxi_buffer_to_layer_info(&cfg->bufs[buf],
688                         &ext_config_data[buf],
689                         &cfg->mappings[buf],
690                         &disp_data->layer_info[dpy][num_buffers[dpy]]);
691
692                 if (err) {
693                         dev_err(adf_dev->dev, "Failed to setup layer info (%d)\n",
694                                 err);
695                         goto err_free_data;
696                 }
697                 disp_data->layer_info[dpy][num_buffers[dpy]].pipe =
698                         pipe_assignments->pipe[buf];
699                 disp_data->layer_info[dpy][num_buffers[dpy]].zorder = buf;
700                 num_buffers[dpy]++;
701         }
702
703         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
704                 sunxi_dbg(adf_dev->dev, "Dpy %u has %u layers\n", dpy,
705                         num_buffers[dpy]);
706                 disp_data->layer_num[dpy] = num_buffers[dpy];
707         }
708
709         disp_data->hConfigData = disp_data;
710
711         sunxi.last_config_pos = (sunxi.last_config_pos + 1)
712                 % DEBUG_POST_DUMP_COUNT;
713
714         sunxi.last_config[sunxi.last_config_pos] = *disp_data;
715         sunxi.last_config_id[sunxi.last_config_pos] = post_id;
716
717         err = sunxi.disp_ops.dispc_gralloc_queue(disp_data);
718         if (err)
719                 dev_err(adf_dev->dev, "Failed to queue post (%d)\n", err);
720
721         post_count = atomic_add_return(1, &sunxi.postcount);
722
723         if (wait_event_timeout(sunxi.post_wait_queue,
724                 sunxi_post_completed(post_count-1), timeout) == 0) {
725                 dev_err(sunxi.dev, "Timeout waiting for post callback\n");
726
727         }
728
729 err_free_data:
730         kfree(disp_data);
731         return;
732
733 }
734
735 static bool adf_sunxi_supports_event(struct adf_obj *obj,
736         enum adf_event_type type)
737 {
738         switch (obj->type) {
739         case ADF_OBJ_INTERFACE: {
740                 struct adf_interface *intf =
741                         container_of(obj, struct adf_interface, base);
742                 struct sunxi_interface *sunxi_intf =
743                         container_of(intf, struct sunxi_interface, interface);
744                 switch (type) {
745                 case ADF_EVENT_VSYNC:
746                         return true;
747                 case ADF_EVENT_HOTPLUG:
748                         /* Only support hotplug on HDMI displays */
749                         return (sunxi_intf->disp_type == DISP_OUTPUT_TYPE_HDMI);
750                 default:
751                         return false;
752                 }
753         }
754         default:
755                 return false;
756         }
757         return false;
758 }
759
760 static struct
761 {
762         u32 width, height, refresh;
763         disp_tv_mode mode;
764 } hdmi_valid_modes[] = {
765         /* List of modes in preference order */
766         { 1920, 1080,   60,     DISP_TV_MOD_1080P_60HZ},
767         { 1920, 1080,   50,     DISP_TV_MOD_1080P_50HZ},
768         { 1280, 720,    60,     DISP_TV_MOD_720P_60HZ},
769         { 1280, 720,    50,     DISP_TV_MOD_720P_50HZ},
770         { 1920, 1080,   25,     DISP_TV_MOD_1080P_25HZ},
771         { 1920, 1080,   30,     DISP_TV_MOD_1080P_30HZ},
772         { 640,  480,    30,     DISP_TV_MOD_480P},
773 };
774 #define NUM_HDMI_VALID_MODES \
775         (sizeof(hdmi_valid_modes)/sizeof(hdmi_valid_modes[0]))
776
777 static void setup_drm_mode(struct drm_mode_modeinfo *mode, int height,
778         int width, int refresh)
779 {
780         memset(mode, 0, sizeof(*mode));
781
782         mode->vrefresh = refresh;
783         mode->hdisplay = width;
784         mode->vdisplay = height;
785
786         adf_modeinfo_set_name(mode);
787 }
788
789 static void sunxi_disp_vsync_callback(void *user_data, u32 screen_id)
790 {
791         adf_vsync_notify(&sunxi.interfaces[screen_id].interface, ktime_get());
792 }
793
794 static int sunxi_disp_hotplug_callback(void *user_data,
795         disp_hotplug_state state)
796 {
797         struct sunxi_interface *intf = user_data;
798         int ret;
799         int mode_count = 0;
800         unsigned int idx;
801
802         dev_dbg(sunxi.dev, "%s: called state = %u\n", __func__, state);
803
804         /* Only HDMI displays can be hotplugged */
805         BUG_ON(intf->disp_type != DISP_OUTPUT_TYPE_HDMI);
806
807         kfree(intf->supported_modes);
808         intf->supported_modes = NULL;
809         intf->num_supported_modes = 0;
810         switch (state) {
811         default:
812                 dev_err(sunxi.dev, "%s: Invalid hotplug state\n", __func__);
813                 /* Fall-thru, treat as disconnect */
814         case DISP_HOTPLUG_DISCONNECT:
815                 intf->connected = false;
816                 adf_hotplug_notify_disconnected(&intf->interface);
817                 dev_dbg(sunxi.dev, "%s: set disconnected\n", __func__);
818                 return 0;
819         case DISP_HOTPLUG_CONNECT:
820                 intf->connected = true;
821                 break;
822         }
823
824         for (idx = 0; idx < NUM_HDMI_VALID_MODES; idx++) {
825                 ret = sunxi.disp_ops.hdmi_check_support_mode(intf->display_id,
826                         hdmi_valid_modes[idx].mode);
827                 if (ret == 1)
828                         mode_count++;
829         }
830
831         intf->num_supported_modes = mode_count;
832         if (mode_count == 0) {
833                 dev_warn(sunxi.dev, "%s: No supported modes found for display id %d - forcing 720p\n",
834                         __func__, intf->display_id);
835                 intf->num_supported_modes = 1;
836                 intf->supported_modes = kzalloc(
837                         sizeof(struct drm_mode_modeinfo), GFP_KERNEL);
838                 if (!intf->supported_modes) {
839                         dev_err(sunxi.dev, "%s: Failed to allocate mode list\n",
840                                 __func__);
841                         goto err_out;
842                 }
843                 /* Force the first mode in the supported list */
844                 setup_drm_mode(&intf->supported_modes[0],
845                         hdmi_valid_modes[0].height, hdmi_valid_modes[0].width,
846                         hdmi_valid_modes[0].refresh);
847         } else {
848                 unsigned int supported_idx = 0;
849
850                 intf->num_supported_modes = mode_count;
851                 intf->supported_modes = kzalloc(
852                         mode_count * sizeof(struct drm_mode_modeinfo),
853                         GFP_KERNEL);
854                 if (!intf->supported_modes) {
855                         dev_err(sunxi.dev, "%s: Failed to allocate mode list\n",
856                                 __func__);
857                         goto err_out;
858                 }
859                 for (idx = 0; idx < NUM_HDMI_VALID_MODES; idx++) {
860                         if (sunxi.disp_ops.hdmi_check_support_mode(
861                                 intf->display_id,
862                                 hdmi_valid_modes[idx].mode) != 1) {
863                                 continue;
864                         }
865                         BUG_ON(supported_idx >= intf->num_supported_modes);
866                         setup_drm_mode(&intf->supported_modes[supported_idx],
867                                 hdmi_valid_modes[idx].height,
868                                 hdmi_valid_modes[idx].width,
869                                 hdmi_valid_modes[idx].refresh);
870                         supported_idx++;
871                 }
872                 BUG_ON(supported_idx != intf->num_supported_modes);
873         }
874         adf_hotplug_notify_connected(&intf->interface, intf->supported_modes,
875                 intf->num_supported_modes);
876         /* Default to first mode */
877         ret = adf_interface_set_mode(&intf->interface,
878                 &intf->supported_modes[0]);
879         if (ret) {
880                 dev_err(sunxi.dev, "%s: Failed hotplug modeset (%d)\n",
881                         __func__, ret);
882                 return ret;
883         }
884         dev_dbg(sunxi.dev, "%s: set connect\n", __func__);
885         return 0;
886
887 err_out:
888         intf->num_supported_modes = 0;
889         kfree(intf->supported_modes);
890         intf->supported_modes = NULL;
891         return -1;
892 }
893
894 static void adf_sunxi_set_hotplug_state(struct sunxi_interface *intf,
895         bool enabled)
896 {
897         BUG_ON(intf->disp_type != DISP_OUTPUT_TYPE_HDMI);
898         dev_dbg(sunxi.dev, "%s: hotplug set to %s\n", __func__,
899                 enabled ? "enabled" : "disabled");
900         if (enabled) {
901                 sunxi.disp_ops.hotplug_enable(intf->display_id, true);
902                 sunxi.disp_ops.hotplug_callback(intf->display_id, intf,
903                         sunxi_disp_hotplug_callback);
904                 sunxi.disp_ops.hdmi_enable(intf->display_id);
905
906         } else {
907                 sunxi.disp_ops.hdmi_disable(intf->display_id);
908                 sunxi.disp_ops.hotplug_enable(intf->display_id, false);
909                 sunxi.disp_ops.hotplug_callback(intf->display_id, NULL, NULL);
910         }
911
912 }
913
914 static void adf_sunxi_set_event(struct adf_obj *obj, enum adf_event_type type,
915         bool enabled)
916 {
917         switch (obj->type) {
918         case ADF_OBJ_INTERFACE: {
919                 struct adf_interface *intf =
920                         container_of(obj, struct adf_interface, base);
921                 struct sunxi_interface *sunxi_intf =
922                         container_of(intf, struct sunxi_interface, interface);
923                 switch (type) {
924                 case ADF_EVENT_VSYNC:
925                         sunxi.disp_ops.vsync_enable(sunxi_intf->display_id, enabled);
926                         break;
927                 case ADF_EVENT_HOTPLUG:
928                         adf_sunxi_set_hotplug_state(sunxi_intf, enabled);
929                         break;
930                 default:
931                         BUG();
932                 }
933                 break;
934         }
935         default:
936                 BUG();
937         }
938 }
939
940
941 static disp_tv_mode
942 find_matching_disp_tv_mode_id(struct drm_mode_modeinfo *mode)
943 {
944         unsigned int idx;
945
946         for (idx = 0; idx < NUM_HDMI_VALID_MODES; idx++) {
947                 if (hdmi_valid_modes[idx].width == mode->hdisplay &&
948                     hdmi_valid_modes[idx].height == mode->vdisplay &&
949                     hdmi_valid_modes[idx].refresh == mode->vrefresh) {
950                         return hdmi_valid_modes[idx].mode;
951                 }
952         }
953         dev_err(sunxi.dev, "%s: No matching disp_tv_mode for %ux%u@%u\n",
954                 __func__, mode->hdisplay, mode->vdisplay, mode->vrefresh);
955         return 0;
956 }
957
958 static int adf_sunxi_modeset(struct adf_interface *intf,
959         struct drm_mode_modeinfo *mode)
960 {
961         disp_tv_mode disp_mode;
962         int err;
963         struct sunxi_interface *sunxi_intf =
964                 container_of(intf, struct sunxi_interface, interface);
965
966         dev_dbg(sunxi.dev, "%s: setting %d (type %d) to %ux%u@%u\n", __func__,
967                 sunxi_intf->display_id, sunxi_intf->disp_type, mode->hdisplay,
968                 mode->vdisplay, mode->vrefresh);
969
970         if (sunxi_intf->disp_type != DISP_OUTPUT_TYPE_HDMI) {
971                 dev_dbg(sunxi.dev, "%s: Stub modeset for internal display\n",
972                         __func__);
973                 return 0;
974         }
975
976         disp_mode = find_matching_disp_tv_mode_id(mode);
977
978         dev_dbg(sunxi.dev, "%s: HDMI modeset to mode %d\n", __func__,
979                 disp_mode);
980
981         err = sunxi.disp_ops.hdmi_disable(sunxi_intf->display_id);
982         if (err) {
983                 dev_err(sunxi.dev, "%s: Failed to disable display id %d for modeset\n",
984                         __func__, sunxi_intf->display_id);
985                 return -EFAULT;
986         }
987
988         err = sunxi.disp_ops.hdmi_set_mode(sunxi_intf->display_id, disp_mode);
989         if (err) {
990                 dev_err(sunxi.dev, "%s: Failed to set mode %ux%u@%u (id %d) to display id %d\n",
991                         __func__, mode->hdisplay, mode->vdisplay,
992                         mode->vrefresh, disp_mode, sunxi_intf->display_id);
993                 return -EFAULT;
994         }
995
996         err = sunxi.disp_ops.hdmi_enable(sunxi_intf->display_id);
997         if (err) {
998                 dev_err(sunxi.dev, "%s: Failed to enable display id %d after modeset\n",
999                         __func__, sunxi_intf->display_id);
1000                 return -EFAULT;
1001         }
1002         return 0;
1003 }
1004
1005 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1006
1007 static int adf_sunxi_alloc_simple_buffer(struct adf_interface *intf, u16 w,
1008         u16 h, u32 format, struct dma_buf **dma_buf, u32 *offset, u32 *pitch)
1009 {
1010         int err = 0;
1011         u32 bpp = sunxi_format_bpp(format);
1012         u32 size = h * w * bpp;
1013         struct ion_handle *hdl;
1014         struct adf_device *dev = intf->base.parent;
1015
1016         if (bpp == 0) {
1017                 dev_err(dev->dev, "%s: unknown format (0x%08x)\n",
1018                         __func__, format);
1019                 err = -EINVAL;
1020                 goto err_out;
1021         }
1022
1023         hdl = ion_alloc(sunxi.ion_client, size, 0,
1024                 (1 << sunxi.ion_heap_id), 0);
1025         if (IS_ERR(hdl)) {
1026                 err = PTR_ERR(hdl);
1027                 dev_err(dev->dev, "%s: ion_alloc failed (%d)\n",
1028                         __func__, err);
1029                 goto err_out;
1030         }
1031         *dma_buf = ion_share_dma_buf(sunxi.ion_client, hdl);
1032         if (IS_ERR(*dma_buf)) {
1033                 err = PTR_ERR(hdl);
1034                 dev_err(dev->dev, "%s: ion_share_dma_buf failed (%d)\n",
1035                         __func__, err);
1036                 goto err_free_buffer;
1037
1038         }
1039         *pitch = w * bpp;
1040         *offset = 0;
1041 err_free_buffer:
1042         ion_free(sunxi.ion_client, hdl);
1043 err_out:
1044         return err;
1045 }
1046
1047 static int adf_sunxi_describe_simple_post(struct adf_interface *intf,
1048         struct adf_buffer *fb, void *data, size_t *size)
1049 {
1050         *size = 0;
1051         return 0;
1052 }
1053
1054 #endif /* SUPPORT_ADF_SUNXI_FBDEV */
1055
1056 static struct adf_device_ops adf_sunxi_device_ops = {
1057         .owner = THIS_MODULE,
1058         .base = {
1059                 .open = adf_sunxi_open,
1060                 .release = adf_sunxi_release,
1061                 .ioctl = adf_img_ioctl,
1062         },
1063         .state_free = adf_sunxi_state_free,
1064         .validate = adf_sunxi_validate,
1065         .post = adf_sunxi_post,
1066 };
1067
1068 static struct adf_interface_ops adf_sunxi_interface_ops = {
1069         .base = {
1070                 .supports_event = adf_sunxi_supports_event,
1071                 .set_event = adf_sunxi_set_event,
1072         },
1073         .modeset = adf_sunxi_modeset,
1074 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1075         .alloc_simple_buffer = adf_sunxi_alloc_simple_buffer,
1076         .describe_simple_post = adf_sunxi_describe_simple_post,
1077 #endif
1078 };
1079
1080 static struct adf_overlay_engine_ops adf_sunxi_overlay_ops = {
1081         .supported_formats = &sunxi_supported_formats[0],
1082         .n_supported_formats = NUM_SUPPORTED_FORMATS,
1083 };
1084
1085 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1086
1087 static struct fb_ops adf_sunxi_fb_ops = {
1088         .owner = THIS_MODULE,
1089         .fb_open = adf_fbdev_open,
1090         .fb_release = adf_fbdev_release,
1091         .fb_check_var = adf_fbdev_check_var,
1092         .fb_set_par = adf_fbdev_set_par,
1093         .fb_blank = adf_fbdev_blank,
1094         .fb_pan_display = adf_fbdev_pan_display,
1095         .fb_fillrect = cfb_fillrect,
1096         .fb_copyarea = cfb_copyarea,
1097         .fb_imageblit = cfb_imageblit,
1098         .fb_mmap = adf_fbdev_mmap,
1099 };
1100 #endif
1101
1102
1103
1104 static void sunxi_debugfs_print_window(struct seq_file *s, const char *prefix,
1105         const disp_window *win)
1106 {
1107         if (win->x)
1108                 seq_printf(s, "%sx\t=\t%u\n", prefix, win->x);
1109         if (win->y)
1110                 seq_printf(s, "%sy\t=\t%u\n", prefix, win->y);
1111         seq_printf(s, "%sw\t=\t%u\n", prefix, win->width);
1112         seq_printf(s, "%sh\t=\t%u\n", prefix, win->height);
1113
1114 }
1115
1116 static void sunxi_debugfs_print_fb_info(struct seq_file *s, const char *prefix,
1117         const disp_fb_info *fb)
1118 {
1119         int i;
1120
1121         for (i = 0; i < 3; i++)
1122                 if (fb->addr[i])
1123                         seq_printf(s, "%saddr[%d]\t=\t0x%08x\n", prefix, i,
1124                                 fb->addr[i]);
1125         seq_printf(s, "%ssize.w\t=\t%u\n", prefix, fb->size.width);
1126         seq_printf(s, "%ssize.h\t=\t%u\n", prefix, fb->size.height);
1127         seq_printf(s, "%sformat\t=\t0x%x\n", prefix, fb->format);
1128         if (fb->cs_mode)
1129                 seq_printf(s, "%scs_mode\t=\t0x%x\n", prefix, fb->cs_mode);
1130         if (fb->b_trd_src)
1131                 seq_printf(s, "%sb_trd_src\t=\t0x%x\n", prefix, fb->b_trd_src);
1132         if (fb->trd_mode)
1133                 seq_printf(s, "%strd_mode\t=\t0x%x\n", prefix, fb->trd_mode);
1134         for (i = 0; i < 3; i++)
1135                 if (fb->trd_right_addr[i])
1136                         seq_printf(s, "%strd_right_addr[%d]\t=\t0x%x\n", prefix,
1137                                 i, fb->trd_right_addr[i]);
1138         /* Default alpha mode is pre-multiply, so interesting values would
1139          * not equal 0x1 */
1140         if (fb->pre_multiply != 0x1)
1141                 seq_printf(s, "%spre_multiply\t=\t0x%x\n", prefix,
1142                         fb->pre_multiply);
1143
1144 }
1145
1146 static void sunxi_debugfs_print_layer_info(struct seq_file *s, int layer_num,
1147         disp_layer_info *layer_info)
1148 {
1149         int i;
1150
1151         for (i = 0; i < layer_num; i++) {
1152                 disp_layer_info *layer = &layer_info[i];
1153
1154                 seq_printf(s, "\tlayer[%d] = {\n", i);
1155                 if (layer->mode)
1156                         seq_printf(s, "\t\tmode\t=\t0x%x\n", layer->mode);
1157                 seq_printf(s, "\t\tpipe\t=\t0x%x\n", layer->pipe);
1158                 seq_printf(s, "\t\tzorder\t=\t0x%x\n", layer->zorder);
1159                 if (layer->alpha_mode)
1160                         seq_printf(s, "\t\talpha_mode\t=\t0x%x\n",
1161                                 layer->alpha_mode);
1162                 /* The default alpha is 0xff, so interesting values would be
1163                  * when it does not equal 0xff */
1164                 if (layer->alpha_value != 0xff)
1165                         seq_printf(s, "\t\talpha_value\t=\t0x%x\n",
1166                                 layer->alpha_value);
1167                 if (layer->ck_enable)
1168                         seq_printf(s, "\t\tck_enable\t=\t0x%x\n",
1169                                 layer->ck_enable);
1170                 sunxi_debugfs_print_window(s, "\t\tscreen_win.",
1171                         &layer->screen_win);
1172                 sunxi_debugfs_print_fb_info(s, "\t\tfb.", &layer->fb);
1173                 if (layer->b_trd_out)
1174                         seq_printf(s, "\t\tb_trd_out\t=\t0x%x\n",
1175                                 layer->b_trd_out);
1176                 if (layer->out_trd_mode)
1177                         seq_printf(s, "\t\tout_trd_mode\t=\t0x%x\n",
1178                         layer->out_trd_mode);
1179                 seq_printf(s, "\t\tid\t=\t%u }\n", layer->id);
1180         }
1181 }
1182
1183 static void sunxi_debugfs_print_config(struct seq_file *s, u32 post_id,
1184         struct setup_dispc_data *config)
1185 {
1186         int dpy;
1187
1188         seq_printf(s, "adf_sunxi post_id %u = {\n", post_id);
1189         for (dpy = 0; dpy < 3; dpy++) {
1190                 seq_printf(s, "\tlayer_num[%d] = %u\n", dpy,
1191                         config->layer_num[dpy]);
1192                 sunxi_debugfs_print_layer_info(s,
1193                         config->layer_num[dpy],
1194                         &config->layer_info[dpy][0]);
1195         }
1196         seq_puts(s, "}\n");
1197 }
1198
1199 static int sunxi_debugfs_show(struct seq_file *s, void *unused)
1200 {
1201         /* FIXME: Should properly lock to reduce the risk of modification
1202          * while printing? */
1203         int post;
1204
1205         for (post = 0; post < DEBUG_POST_DUMP_COUNT; post++) {
1206                 /* Start at current buffer position +1 (oldest post in the
1207                  * log) */
1208                 int pos = (sunxi.last_config_pos + post + 1)
1209                         % DEBUG_POST_DUMP_COUNT;
1210                 sunxi_debugfs_print_config(s, sunxi.last_config_id[pos],
1211                         &sunxi.last_config[pos]);
1212         }
1213         return 0;
1214 }
1215
1216 static int sunxi_debugfs_open(struct inode *inode, struct file *file)
1217 {
1218         return single_open(file, sunxi_debugfs_show, inode->i_private);
1219 }
1220
1221 static const struct file_operations adf_sunxi_debugfs_fops = {
1222         .open = sunxi_debugfs_open,
1223         .read = seq_read,
1224         .llseek = seq_lseek,
1225         .release = single_release,
1226 };
1227
1228 static int sunxi_debugfs_val_show(struct seq_file *s, void *unused)
1229 {
1230         int line;
1231
1232         for (line = 0; line < VALIDATE_LOG_LINES; line++) {
1233                 int pos = (sunxi.validate_log_position + line + 1)
1234                         % VALIDATE_LOG_LINES;
1235                 seq_puts(s, sunxi.validate_log[pos]);
1236         }
1237         return 0;
1238 }
1239
1240 static int sunxi_debugfs_val_open(struct inode *inode, struct file *file)
1241 {
1242         return single_open(file, sunxi_debugfs_val_show, inode->i_private);
1243 }
1244
1245 static const struct file_operations adf_sunxi_debugfs_val_fops = {
1246         .open = sunxi_debugfs_val_open,
1247         .read = seq_read,
1248         .llseek = seq_lseek,
1249         .release = single_release,
1250 };
1251
1252 static int adf_init_lcd_interface(struct sunxi_interface *interface)
1253 {
1254         int height, width;
1255         int refresh = 60;
1256         int err;
1257
1258         interface->connected = true;
1259         interface->name = "LCD";
1260         interface->adf_type = ADF_INTF_DSI;
1261         err = adf_interface_init(&interface->interface, &sunxi.device,
1262                 interface->adf_type, interface->display_id,
1263                 ADF_INTF_FLAG_PRIMARY, &adf_sunxi_interface_ops,
1264                 interface->name);
1265         if (err) {
1266                 dev_err(sunxi.dev, "%s: Failed to init adf interface %d (%d)\n",
1267                         __func__, interface->display_id, err);
1268                 goto err_out;
1269         }
1270         height = sunxi.disp_ops.get_screen_height(interface->display_id);
1271         if (height < 0) {
1272                 dev_err(sunxi.dev, "%s: Failed to query display height (%d)\n",
1273                         __func__, height);
1274                 err = -EFAULT;
1275                 goto err_out;
1276         }
1277         width = sunxi.disp_ops.get_screen_width(interface->display_id);
1278         if (width < 0) {
1279                 dev_err(sunxi.dev, "%s: Failed to query display width (%d)\n",
1280                         __func__, width);
1281                 err = -EFAULT;
1282                 goto err_out;
1283         }
1284
1285         interface->supported_modes = kzalloc(sizeof(struct drm_mode_modeinfo),
1286                 GFP_KERNEL);
1287         if (!interface->supported_modes) {
1288                 dev_err(sunxi.dev, "%s: Failed to allocate mode struct\n",
1289                         __func__);
1290                 err = -ENOMEM;
1291                 goto err_out;
1292         }
1293         interface->num_supported_modes = 1;
1294         setup_drm_mode(&interface->supported_modes[0], height, width, refresh);
1295
1296         err = adf_hotplug_notify_connected(&interface->interface,
1297                 interface->supported_modes, interface->num_supported_modes);
1298         if (err) {
1299                 dev_err(sunxi.dev, "%s: Failed to notify connected (%d)\n",
1300                         __func__, err);
1301                 goto err_out;
1302         }
1303         /* We need to set initial mode */
1304         err = adf_interface_set_mode(&interface->interface,
1305                 &interface->supported_modes[0]);
1306         if (err) {
1307                 dev_err(sunxi.dev, "%s: Failed initial modeset (%d)\n",
1308                         __func__, err);
1309                 goto err_out;
1310         }
1311         err = sunxi.disp_ops.vsync_callback(NULL, sunxi_disp_vsync_callback);
1312         if (err) {
1313                 dev_err(sunxi.dev, "%s: Failed to set vsync callback (%d)\n",
1314                         __func__, err);
1315                 goto err_out;
1316         }
1317         err = 0;
1318 err_out:
1319         return err;
1320 }
1321
1322 static int adf_init_hdmi_interface(struct sunxi_interface *interface)
1323 {
1324         disp_hotplug_state hotplug_state;
1325         int err;
1326
1327         interface->name = "HDMI";
1328         interface->adf_type = ADF_INTF_HDMI;
1329         hotplug_state = sunxi.disp_ops.hotplug_state(interface->display_id);
1330
1331         err = adf_interface_init(&interface->interface, &sunxi.device,
1332                 interface->adf_type, interface->display_id,
1333                 ADF_INTF_FLAG_EXTERNAL, &adf_sunxi_interface_ops,
1334                 interface->name);
1335         if (err) {
1336                 dev_err(sunxi.dev, "%s: Failed to init adf interface %d (%d)\n",
1337                         __func__, interface->display_id, err);
1338                 goto err_out;
1339         }
1340
1341         switch (hotplug_state) {
1342         case DISP_HOTPLUG_CONNECT:
1343                 interface->connected = true;
1344                 break;
1345         default:
1346                 dev_err(sunxi.dev, "%s: Error querying hotplug state for display id %d\n",
1347                         __func__, interface->display_id);
1348                 hotplug_state = DISP_HOTPLUG_DISCONNECT;
1349                 /* Fall-thru, act as if disconnected*/
1350         case DISP_HOTPLUG_DISCONNECT:
1351                 interface->connected = false;
1352                 break;
1353         }
1354         /* Call the hotplug function to setup modes */
1355         sunxi_disp_hotplug_callback(interface, hotplug_state);
1356
1357         err = 0;
1358 err_out:
1359         return err;
1360 }
1361
1362
1363 static void adf_init_interface(struct sunxi_interface *interface, int id)
1364 {
1365         BUG_ON(!interface);
1366         memset(interface, 0, sizeof(*interface));
1367         interface->disp_type = sunxi.disp_ops.get_output_type(id);
1368         interface->display_id = id;
1369         dev_dbg(sunxi.dev, "%s: interface %d\n", __func__, id);
1370
1371         switch (interface->disp_type) {
1372         default:
1373                 dev_err(sunxi.dev, "%s: Unsupported interface type %d for display %d\n",
1374                         __func__, interface->disp_type, id);
1375                 interface->disp_type = DISP_OUTPUT_TYPE_NONE;
1376                 /* Fall-thru */
1377         case DISP_OUTPUT_TYPE_NONE:
1378                 dev_dbg(sunxi.dev, "%s: Skipping interface %d - type %d\n",
1379                         __func__, id, interface->disp_type);
1380                 interface->connected = false;
1381                 return;
1382         case DISP_OUTPUT_TYPE_LCD:
1383                 adf_init_lcd_interface(interface);
1384                 break;
1385         case DISP_OUTPUT_TYPE_HDMI:
1386                 adf_init_hdmi_interface(interface);
1387                 break;
1388         }
1389 }
1390
1391 static int adf_sunxi_probe(struct platform_device *pdev)
1392 {
1393         int err = 0;
1394         int dpy = 0;
1395         int ovl = 0;
1396
1397         memset(&sunxi.last_config, 0, sizeof(sunxi.last_config));
1398
1399         atomic_set(&sunxi.postcount, 0);
1400         atomic_set(&sunxi.callbackcount, 0);
1401         init_waitqueue_head(&sunxi.post_wait_queue);
1402
1403         sunxi.dev = &pdev->dev;
1404
1405         err = adf_device_init(&sunxi.device, sunxi.dev,
1406                 &adf_sunxi_device_ops, "sunxi_device");
1407         if (err) {
1408                 dev_err(sunxi.dev, "Failed to init ADF device (%d)\n",
1409                         err);
1410                 goto err_out;
1411         }
1412
1413         err = disp_get_composer_ops(&sunxi.disp_ops);
1414         if (err) {
1415                 dev_err(sunxi.dev, "Failed to get composer ops (%d)\n",
1416                         err);
1417                 goto err_free_overlays;
1418         }
1419         /* Set the retire callback */
1420         err = sunxi.disp_ops.set_retire_callback(sunxi_retire_callback);
1421         if (err) {
1422                 dev_err(sunxi.dev, "Failed to set retire callback (%d)\n",
1423                         err);
1424                 goto err_free_overlays;
1425         }
1426         /* The HDMI must be enabled to receive hotplug events, which in turn
1427          * must already must have a valid mode set */
1428         err = sunxi.disp_ops.hdmi_set_mode(1, DISP_TV_MOD_720P_60HZ);
1429         if (err) {
1430                 dev_warn(sunxi.dev, "Failed to enable initial hdmi mode on dpy 1 (%d)\n",
1431                         err);
1432                 /* Not fatal */
1433         }
1434         dev_dbg(sunxi.dev, "%s: %d hdmi_enable\n", __func__, __LINE__);
1435         err = sunxi.disp_ops.hdmi_enable(1);
1436         if (err) {
1437                 dev_warn(sunxi.dev, "Failed to enable hdmi on dpy 1 (%d)\n",
1438                         err);
1439                 /* Not fatal */
1440         }
1441
1442         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++)
1443                 adf_init_interface(&sunxi.interfaces[dpy], dpy);
1444
1445         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
1446                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_NONE)
1447                         continue;
1448                 for (ovl = 0; ovl < NUM_OVERLAYS; ovl++) {
1449                         err = adf_overlay_engine_init(
1450                                 &sunxi.overlays[dpy][ovl].overlay,
1451                                 &sunxi.device, &adf_sunxi_overlay_ops,
1452                                 "sunxi_overlay_%d-%d", dpy, ovl);
1453                         if (err) {
1454                                 dev_err(sunxi.dev, "Failed to init overlay %d-%d (%d)\n",
1455                                         dpy, ovl, err);
1456                                 goto err_free_overlays;
1457                         }
1458                         err = adf_attachment_allow(&sunxi.device,
1459                                 &sunxi.overlays[dpy][ovl].overlay,
1460                                 &sunxi.interfaces[dpy].interface);
1461
1462                         if (err) {
1463                                 dev_err(sunxi.dev, "Failed to attach overlay %d-%d (%d)\n",
1464                                         dpy, ovl, err);
1465                                 goto err_free_overlays;
1466                         }
1467                 }
1468         }
1469
1470
1471         sunxi.ion_heap_id = ION_HEAP_TYPE_CARVEOUT;
1472
1473         sunxi.ion_client = ion_client_create(idev, "adf_sunxi");
1474
1475         if (IS_ERR(sunxi.ion_client)) {
1476                 err = PTR_ERR(sunxi.ion_client);
1477                 dev_err(sunxi.dev, "Failed to create ion client (%d)\n",
1478                         err);
1479                 goto err_free_overlays;
1480         }
1481
1482 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1483         err = adf_fbdev_init(&sunxi.fbdev,
1484                 &sunxi.interfaces[DISPLAY_INTERNAL].interface,
1485                 &sunxi.overlays[DISPLAY_INTERNAL].overlay,
1486                 sunxi.interfaces[DISPLAY_INTERNAL].width,
1487                 sunxi.interfaces[DISPLAY_INTERNAL].height,
1488                 DRM_FORMAT_BGRA8888,
1489                 &adf_sunxi_fb_ops,
1490                 "adf_sunxi_fb");
1491         if (err) {
1492                 dev_err(sunxi.dev, "Failed to init ADF fbdev (%d)\n", err);
1493                 goto err_free_ion_client;
1494         }
1495 #endif
1496
1497         sunxi.debugfs_config_file = debugfs_create_file("adf_debug", S_IRUGO,
1498                 NULL, NULL, &adf_sunxi_debugfs_fops);
1499
1500         sunxi.debugfs_val_log = debugfs_create_file("adf_val_log", S_IRUGO,
1501                 NULL, NULL, &adf_sunxi_debugfs_val_fops);
1502         dev_err(sunxi.dev, "Successfully loaded adf_sunxi\n");
1503
1504         return 0;
1505 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1506 err_free_ion_client:
1507 #endif
1508         ion_client_destroy(sunxi.ion_client);
1509 err_free_overlays:
1510         for (; dpy > 0; dpy--) {
1511                 if (sunxi.interfaces[dpy-1].disp_type == DISP_OUTPUT_TYPE_NONE)
1512                         continue;
1513                 for (; ovl > 0; ovl--) {
1514                         adf_overlay_engine_destroy(
1515                                 &sunxi.overlays[dpy-1][ovl-1].overlay);
1516                 }
1517         }
1518         dpy = MAX_DISPLAYS;
1519         for (; dpy > 0; dpy--) {
1520                 if (sunxi.interfaces[dpy-1].disp_type == DISP_OUTPUT_TYPE_NONE)
1521                         continue;
1522                 if (sunxi.interfaces[dpy-1].disp_type == DISP_OUTPUT_TYPE_HDMI)
1523                         adf_sunxi_set_hotplug_state(&sunxi.interfaces[dpy],
1524                                 false);
1525                 adf_interface_destroy(&sunxi.interfaces[dpy-1].interface);
1526         }
1527         adf_device_destroy(&sunxi.device);
1528 err_out:
1529         debugfs_remove(sunxi.debugfs_config_file);
1530         sunxi.debugfs_config_file = NULL;
1531         debugfs_remove(sunxi.debugfs_val_log);
1532         sunxi.debugfs_val_log = NULL;
1533         return err;
1534 }
1535
1536 static int adf_sunxi_remove(struct platform_device *pdev)
1537 {
1538         int dpy;
1539         int ovl;
1540 #ifdef SUPPORT_ADF_SUNXI_FBDEV
1541         adf_fbdev_destroy(&sunxi.fbdev);
1542 #endif
1543         debugfs_remove(sunxi.debugfs_config_file);
1544         sunxi.debugfs_config_file = NULL;
1545         debugfs_remove(sunxi.debugfs_val_log);
1546         sunxi.debugfs_val_log = NULL;
1547         ion_client_destroy(sunxi.ion_client);
1548         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
1549                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_NONE)
1550                         continue;
1551                 for (ovl = 0; ovl < NUM_OVERLAYS; ovl++)
1552                         adf_overlay_engine_destroy(
1553                                 &sunxi.overlays[dpy][ovl].overlay);
1554         }
1555         for (dpy = 0; dpy < MAX_DISPLAYS; dpy++) {
1556                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_NONE)
1557                         continue;
1558                 if (sunxi.interfaces[dpy].disp_type == DISP_OUTPUT_TYPE_HDMI)
1559                         adf_sunxi_set_hotplug_state(&sunxi.interfaces[dpy],
1560                                 false);
1561                 adf_interface_destroy(&sunxi.interfaces[dpy].interface);
1562         }
1563         adf_device_destroy(&sunxi.device);
1564         return 0;
1565 }
1566
1567 static void adf_sunxi_device_release(struct device *dev)
1568 {
1569         /* NOOP */
1570         return;
1571 }
1572
1573 static int adf_sunxi_device_suspend(struct platform_device *pdev, pm_message_t state)
1574 {
1575         return 0;
1576 }
1577 static int adf_sunxi_device_resume(struct platform_device *pdev)
1578 {
1579         return 0;
1580 }
1581
1582 struct platform_device adf_sunxi_platform_device =
1583 {
1584         .name = "adf_sunxi",
1585         .id = -1,
1586         .dev.release = adf_sunxi_device_release,
1587 };
1588
1589 struct platform_driver adf_sunxi_platform_driver =
1590 {
1591         .driver.name = "adf_sunxi",
1592         .probe = adf_sunxi_probe,
1593         .remove = adf_sunxi_remove,
1594         .suspend = adf_sunxi_device_suspend,
1595         .resume = adf_sunxi_device_resume,
1596 };
1597
1598 static int __init adf_sunxi_init(void)
1599 {
1600         platform_device_register(&adf_sunxi_platform_device);
1601         platform_driver_register(&adf_sunxi_platform_driver);
1602         return 0;
1603 }
1604
1605 static void __exit adf_sunxi_exit(void)
1606 {
1607         platform_device_unregister(&adf_sunxi_platform_device);
1608         platform_driver_unregister(&adf_sunxi_platform_driver);
1609 }
1610
1611 module_init(adf_sunxi_init);
1612 module_exit(adf_sunxi_exit);