drm/i915: Implement commit w/o pinning for sprites
[vsyrjala:linux.git] / drivers / gpu / drm / i915 / intel_atomic.c
1 /*
2  */
3
4 #include <drm/drmP.h>
5 #include <drm/drm_crtc.h>
6
7 #include "intel_drv.h"
8
9 static struct drm_property *prop_src_x;
10 static struct drm_property *prop_src_y;
11 static struct drm_property *prop_src_w;
12 static struct drm_property *prop_src_h;
13 static struct drm_property *prop_crtc_x;
14 static struct drm_property *prop_crtc_y;
15 static struct drm_property *prop_crtc_w;
16 static struct drm_property *prop_crtc_h;
17 static struct drm_property *prop_fb_id;
18 static struct drm_property *prop_crtc_id;
19 static struct drm_property *prop_mode_id;
20 static struct drm_property *prop_connector_ids;
21
22 struct intel_plane_state {
23         struct drm_plane *plane;
24         struct intel_plane_coords coords;
25         bool dirty;
26 };
27
28 struct intel_crtc_state {
29         struct drm_crtc *crtc;
30         struct drm_framebuffer *old_fb;
31         bool mode_dirty;
32         bool fb_dirty;
33         bool active_dirty;
34         unsigned long connectors_bitmask;
35         unsigned long encoders_bitmask;
36 };
37
38 struct intel_atomic_state {
39         struct intel_plane_state *plane;
40         struct intel_crtc_state *crtc;
41         bool dirty;
42         bool restore_hw;
43         struct drm_plane *saved_planes;
44         struct drm_crtc *saved_crtcs;
45         struct drm_connector *saved_connectors;
46         struct drm_encoder *saved_encoders;
47 };
48
49 static void update_connectors_bitmask(struct intel_crtc_state *st)
50 {
51         struct drm_device *dev = st->crtc->dev;
52         struct drm_connector *connector;
53         unsigned int i;
54
55         st->connectors_bitmask = 0;
56
57         i = 0;
58         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
59                 if (connector->encoder && connector->encoder->crtc == st->crtc)
60                         __set_bit(i, &st->connectors_bitmask);
61
62                 i++;
63         }
64 }
65
66 static void update_encoders_bitmask(struct intel_crtc_state *st)
67 {
68         struct drm_device *dev = st->crtc->dev;
69         struct drm_encoder *encoder;
70         unsigned int i;
71
72         st->encoders_bitmask = 0;
73
74         i = 0;
75         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
76                 if (encoder->crtc == st->crtc)
77                         __set_bit(i, &st->encoders_bitmask);
78
79                 i++;
80         }
81 }
82
83 static int process_connectors(struct intel_crtc_state *s, const uint32_t *ids, int count_ids)
84 {
85         struct drm_crtc *crtc = s->crtc;
86         struct drm_device *dev = crtc->dev;
87         struct drm_connector *connectors[count_ids];
88         struct drm_connector *connector;
89         struct drm_encoder *encoder;
90         int i;
91
92         for (i = 0; i < count_ids; i++) {
93                 struct drm_encoder *encoder;
94                 const struct drm_connector_helper_funcs *connector_funcs;
95                 struct drm_mode_object *obj;
96                 int j;
97
98                 /* don't accept duplicates */
99                 for (j = i + 1; j < count_ids; j++)
100                         if (ids[i] == ids[j])
101                                 return -EINVAL;
102
103                 obj = drm_mode_object_find(dev, ids[i], DRM_MODE_OBJECT_CONNECTOR);
104                 if (!obj)
105                         return -ENOENT;
106
107                 connector = obj_to_connector(obj);
108                 connector_funcs = connector->helper_private;
109
110                 encoder = connector_funcs->best_encoder(connector);
111
112                 if (!drm_encoder_crtc_ok(encoder, crtc))
113                         return -EINVAL;
114
115                 connectors[i] = connector;
116         }
117
118         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
119                 const struct drm_connector_helper_funcs *connector_funcs =
120                         connector->helper_private;
121
122                 for (i = 0; i < count_ids; i++) {
123                         if (connector == connectors[i])
124                                 break;
125                 }
126
127                 /* this connector isn't in the set */
128                 if (i == count_ids) {
129                         /* remove the link to the encoder if this crtc was driving it previously */
130                         if (connector->encoder && connector->encoder->crtc == crtc) {
131                                 s->mode_dirty = true;
132                                 connector->encoder = NULL;
133                         }
134                         continue;
135                 }
136
137                 encoder = connector_funcs->best_encoder(connector);
138
139                 if (encoder != connector->encoder) {
140                         s->mode_dirty = true;
141                         connector->encoder = encoder;
142                 }
143
144                 if (crtc != encoder->crtc) {
145                         s->mode_dirty = true;
146                         encoder->crtc = crtc;
147                 }
148         }
149
150         /* prune dangling encoder->crtc links pointing to this crtc  */
151         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
152                 if (encoder->crtc == crtc && !drm_helper_encoder_in_use(encoder))
153                         encoder->crtc = NULL;
154         }
155
156         update_connectors_bitmask(s);
157         update_encoders_bitmask(s);
158
159         return 0;
160 }
161
162 static size_t intel_atomic_state_size(const struct drm_device *dev)
163 {
164         struct intel_atomic_state *state;
165         unsigned int num_connector = dev->mode_config.num_connector;
166         unsigned int num_encoder = dev->mode_config.num_encoder;
167         unsigned int num_crtc = dev->mode_config.num_crtc;
168         unsigned int num_plane = dev->mode_config.num_plane;
169
170         return sizeof *state +
171                 num_crtc * sizeof state->crtc[0] +
172                 num_plane * sizeof state->plane[0] +
173                 num_connector * sizeof state->saved_connectors[0] +
174                 num_encoder * sizeof state->saved_encoders[0] +
175                 num_crtc * sizeof state->saved_crtcs[0] +
176                 num_plane * sizeof state->saved_planes[0];
177 }
178
179 static void *intel_atomic_begin(struct drm_device *dev, uint32_t flags)
180 {
181         struct intel_atomic_state *state;
182         struct drm_plane *plane;
183         struct drm_crtc *crtc;
184         struct drm_connector *connector;
185         struct drm_encoder *encoder;
186         unsigned int num_connector = dev->mode_config.num_connector;
187         unsigned int num_encoder = dev->mode_config.num_encoder;
188         unsigned int num_crtc = dev->mode_config.num_crtc;
189         unsigned int num_plane = dev->mode_config.num_plane;
190         int i;
191
192         state = kzalloc(intel_atomic_state_size(dev), GFP_KERNEL);
193         if (!state)
194                 return ERR_PTR(-ENOMEM);
195
196         state->crtc = (struct intel_crtc_state *)(state + 1);
197         state->plane = (struct intel_plane_state  *)(state->crtc + num_crtc);
198
199         state->saved_connectors = (struct drm_connector *)(state->plane + num_plane);
200         state->saved_encoders = (struct drm_encoder *)(state->saved_connectors + num_connector);
201         state->saved_crtcs = (struct drm_crtc *)(state->saved_encoders + num_encoder);
202         state->saved_planes = (struct drm_plane *)(state->saved_crtcs + num_crtc);
203
204         i = 0;
205         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
206                 struct intel_crtc_state *s = &state->crtc[i++];
207
208                 s->crtc = crtc;
209                 s->old_fb = crtc->fb;
210
211                 update_connectors_bitmask(s);
212                 update_encoders_bitmask(s);
213         }
214
215         i = 0;
216         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
217                 struct intel_plane_state *s = &state->plane[i++];
218
219                 s->plane = plane;
220         }
221
222         i = 0;
223         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
224                 state->saved_connectors[i++] = *connector;
225         i = 0;
226         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
227                 state->saved_encoders[i++] = *encoder;
228         i = 0;
229         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
230                 state->saved_crtcs[i++] = *crtc;
231         i = 0;
232         list_for_each_entry(plane, &dev->mode_config.plane_list, head)
233                 state->saved_planes[i++] = *plane;
234
235         return state;
236 }
237
238 static int plane_set(struct intel_atomic_state *s,
239                      struct intel_plane_state *state,
240                      struct drm_property *prop,
241                      uint64_t value)
242 {
243         struct drm_plane *plane = state->plane;
244         struct drm_mode_object *obj;
245
246         if (prop == prop_src_x) {
247                 if (plane->src_x == value)
248                         return 0;
249                 plane->src_x = value;
250         } else if (prop == prop_src_y) {
251                 if (plane->src_y == value)
252                         return 0;
253                 plane->src_y = value;
254         } else if (prop == prop_src_w) {
255                 if (plane->src_w == value)
256                         return 0;
257                 plane->src_w = value;
258         } else if (prop == prop_src_h) {
259                 if (plane->src_h == value)
260                         return 0;
261                 plane->src_h = value;
262         } else if (prop == prop_crtc_x) {
263                 if (plane->crtc_x == value)
264                         return 0;
265                 plane->crtc_x = value;
266         } else if (prop == prop_crtc_y) {
267                 if (plane->crtc_y == value)
268                         return 0;
269                 plane->crtc_y = value;
270         } else if (prop == prop_crtc_w) {
271                 if (plane->crtc_w == value)
272                         return 0;
273                 plane->crtc_w = value;
274         } else if (prop == prop_crtc_h) {
275                 if (plane->crtc_h == value)
276                         return 0;
277                 plane->crtc_h = value;
278         } else if (prop == prop_crtc_id) {
279                 struct drm_crtc *crtc = NULL;
280
281                 if (plane->crtc) {
282                         if (value == plane->crtc->base.id)
283                                 return 0;
284                 } else {
285                         if (value == 0)
286                                 return 0;
287                 }
288
289                 if (value) {
290                         obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_CRTC);
291                         if (!obj) {
292                                 printk("Unknown CRTC ID %llu\n", value);
293                                 return -ENOENT;
294                         }
295                         crtc = obj_to_crtc(obj);
296                 }
297
298                 plane->crtc = crtc;
299         } else if (prop == prop_fb_id) {
300                 struct drm_framebuffer *fb = NULL;
301
302                 if (plane->fb) {
303                         if (value == plane->fb->base.id)
304                                 return 0;
305                 } else {
306                         if (value == 0)
307                                 return 0;
308                 }
309
310                 if (value) {
311                         obj = drm_mode_object_find(plane->dev, value, DRM_MODE_OBJECT_FB);
312                         if (!obj) {
313                                 printk("Unknown framebuffer ID %llu\n", value);
314                                 return -ENOENT;
315                         }
316                         fb = obj_to_fb(obj);
317                 }
318
319                 plane->fb = fb;
320         } else
321                 return -ENOENT;
322
323         state->dirty = true;
324         s->dirty = true;
325
326         return 0;
327 }
328
329 static int crtc_set(struct intel_atomic_state *s,
330                     struct intel_crtc_state *state,
331                     struct drm_property *prop,
332                     uint64_t value, void *blob_data)
333 {
334         struct drm_crtc *crtc = state->crtc;
335         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
336         struct drm_mode_object *obj;
337
338         if (prop == prop_src_x) {
339                 if (crtc->x == value)
340                         return 0;
341                 crtc->x = value;
342                 if (crtc_funcs->mode_set_base)
343                         state->fb_dirty = true;
344                 else
345                         state->mode_dirty = true;
346         } else if (prop == prop_src_y) {
347                 if (crtc->y == value)
348                         return 0;
349                 crtc->y = value;
350                 if (crtc_funcs->mode_set_base)
351                         state->fb_dirty = true;
352                 else
353                         state->mode_dirty = true;
354         } else if (prop == prop_mode_id) {
355                 struct drm_display_mode *mode = NULL;
356
357                 if (!crtc->enabled) {
358                         if (value == 0)
359                                 return 0;
360                 }
361
362                 if (value) {
363                         obj = drm_mode_object_find(crtc->dev, value, DRM_MODE_OBJECT_MODE);
364                         if (!obj) {
365                                 printk("Unknown mode ID %llu\n", value);
366                                 return -ENOENT;
367                         }
368                         mode = obj_to_mode(obj);
369                 }
370
371                 /* FIXME should check just the user timings? */
372                 if (crtc->enabled && mode && !memcmp(&crtc->mode, mode, sizeof *mode))
373                         return 0;
374
375                 /* turn on/off or active area changed? */
376                 if (!crtc->enabled || !mode ||
377                     crtc->mode.hdisplay != mode->hdisplay ||
378                     crtc->mode.vdisplay != mode->vdisplay)
379                         state->active_dirty = true;
380
381                 if (mode) {
382                         crtc->mode = *mode;
383                         crtc->enabled = true;
384                 } else
385                         crtc->enabled = false;
386                 state->mode_dirty = true;
387         } else if (prop == prop_fb_id) {
388                 struct drm_framebuffer *fb = NULL;
389
390                 if (crtc->fb) {
391                         if (value == crtc->fb->base.id)
392                                 return 0;
393                 } else {
394                         if (value == 0)
395                                 return 0;
396                 }
397
398                 if (value) {
399                         obj = drm_mode_object_find(crtc->dev, value, DRM_MODE_OBJECT_FB);
400                         if (!obj) {
401                                 printk("Unknown framebuffer ID %llu\n", value);
402                                 return -ENOENT;
403                         }
404                         fb = obj_to_fb(obj);
405                 }
406
407                 crtc->fb = fb;
408                 if (crtc_funcs->mode_set_base)
409                         state->fb_dirty = true;
410                 else
411                         state->mode_dirty = true;
412         } else if (prop == prop_connector_ids) {
413                 const uint32_t *ids = blob_data;
414                 uint32_t count_ids = value / sizeof(uint32_t);
415                 int ret;
416
417                 if (value & 3)
418                         return -EINVAL;
419
420                 if (count_ids > crtc->dev->mode_config.num_connector)
421                         return -ERANGE;
422
423                 ret = process_connectors(state, ids, count_ids);
424                 if (ret)
425                         return ret;
426         } else
427                 return -ENOENT;
428
429         s->dirty = true;
430
431         return 0;
432 }
433
434 static struct intel_plane_state *get_plane_state(const struct drm_device *dev,
435                                                  struct intel_atomic_state *state,
436                                                  const struct drm_plane *plane)
437 {
438         int i;
439
440         for (i = 0; i < dev->mode_config.num_plane; i++)
441                 if (plane == state->plane[i].plane)
442                         return &state->plane[i];
443
444         return NULL;
445 }
446
447 static struct intel_crtc_state *get_crtc_state(const struct drm_device *dev,
448                                                struct intel_atomic_state *state,
449                                                const struct drm_crtc *crtc)
450 {
451         int i;
452
453         for (i = 0; i < dev->mode_config.num_crtc; i++)
454                 if (crtc == state->crtc[i].crtc)
455                         return &state->crtc[i];
456
457         return NULL;
458 }
459
460 static void crtc_prepare(struct drm_crtc *crtc)
461 {
462         struct drm_device *dev = crtc->dev;
463         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
464         struct drm_encoder *encoder;
465
466         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
467                 const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
468
469                 if (encoder->crtc != crtc)
470                         continue;
471
472                 encoder_funcs->prepare(encoder);
473         }
474
475         drm_crtc_prepare_encoders(dev);
476
477         crtc_funcs->prepare(crtc);
478 }
479
480 static int crtc_set_base(struct drm_crtc *crtc,
481                          struct drm_framebuffer *old_fb)
482 {
483         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
484
485         return crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb);
486 }
487
488 static int crtc_mode_set(struct drm_crtc *crtc,
489                          struct drm_framebuffer *old_fb)
490 {
491         struct drm_device *dev = crtc->dev;
492         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
493         struct drm_encoder *encoder;
494         int ret;
495
496         ret = crtc_funcs->mode_set(crtc, &crtc->mode, &crtc->hwmode,
497                                    crtc->x, crtc->y, old_fb);
498         if (ret)
499                 return ret;
500
501         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
502                 const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
503
504                 if (encoder->crtc != crtc)
505                         continue;
506
507                 encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->hwmode);
508         }
509
510         return 0;
511 }
512
513 static void crtc_commit(struct drm_crtc *crtc)
514 {
515         struct drm_device *dev = crtc->dev;
516         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
517         struct drm_encoder *encoder;
518
519         crtc_funcs->commit(crtc);
520
521         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
522                 const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
523
524                 if (encoder->crtc != crtc)
525                         continue;
526
527                 encoder_funcs->commit(encoder);
528         }
529 }
530
531 int intel_commit_plane(struct drm_plane *plane,
532                        struct drm_crtc *crtc,
533                        struct drm_framebuffer *fb,
534                        const struct intel_plane_coords *st,
535                        bool pin);
536
537 static int apply_config(struct drm_device *dev,
538                         struct intel_atomic_state *s)
539 {
540         int i, ret;
541         struct drm_plane *plane;
542
543         for (i = 0; i < dev->mode_config.num_crtc; i++) {
544                 struct intel_crtc_state *st = &s->crtc[i];
545
546                 if (!st->mode_dirty)
547                         continue;
548
549                 crtc_prepare(st->crtc);
550         }
551
552         for (i = 0; i < dev->mode_config.num_crtc; i++) {
553                 struct intel_crtc_state *st = &s->crtc[i];
554
555                 if (st->mode_dirty) {
556                         ret = crtc_mode_set(st->crtc, st->old_fb);
557                         if (ret)
558                                 return ret;
559                 } else if (st->fb_dirty) {
560                         ret = crtc_set_base(st->crtc, st->old_fb);
561                         if (ret)
562                                 return ret;
563                 } else
564                         continue;
565
566                 /*
567                  * Old fb was unpinned and new fb pinned.
568                  * Update the old_fb pointer accordingingly
569                  * in case we need to roll back later.
570                  */
571                 st->old_fb = st->crtc->fb;
572         }
573
574         for (i = 0; i < dev->mode_config.num_plane; i++) {
575                 struct intel_plane_state *st = &s->plane[i];
576                 struct drm_plane *plane = st->plane;
577
578                 if (!s->plane[i].dirty)
579                         continue;
580
581                 if (!plane->crtc)
582                         continue;
583
584                 ret = intel_commit_plane(plane, plane->crtc, plane->fb, &st->coords, true);
585                 if (ret)
586                         return ret;
587         }
588
589         for (i = 0; i < dev->mode_config.num_crtc; i++) {
590                 struct intel_crtc_state *st = &s->crtc[i];
591
592                 if (!st->mode_dirty)
593                         continue;
594
595                 crtc_commit(st->crtc);
596         }
597
598         /*
599          * FIXME perhaps better order would be
600          * 1. prepare all current objects
601          * 2. disable unused objects
602          * 3. set mode for current objects
603          * 4. commit current objects
604          */
605         drm_helper_disable_unused_functions(dev);
606         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
607                 /* planes attached to crtcs already handled in mode_set() */
608                 if (!plane->crtc || !plane->fb)
609                         plane->funcs->disable_plane(plane);
610         }
611
612         /* don't restore the old state in end() */
613         s->dirty = false;
614
615         return 0;
616 }
617
618 static void restore_state(struct drm_device *dev,
619                           struct intel_atomic_state *s)
620 {
621         int i;
622         struct drm_connector *connector;
623         struct drm_encoder *encoder;
624         struct drm_crtc *crtc;
625         struct drm_plane *plane;
626
627         i = 0;
628         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
629                 *connector = s->saved_connectors[i++];
630         i = 0;
631         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
632                 *encoder = s->saved_encoders[i++];
633         i = 0;
634         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
635                 *crtc = s->saved_crtcs[i++];
636         i = 0;
637         list_for_each_entry(plane, &dev->mode_config.plane_list, head)
638                 *plane = s->saved_planes[i++];
639
640         /* FIXME props etc. */
641
642         /* was the hardware state clobbered? */
643         if (s->restore_hw)
644                 apply_config(dev, s);
645 }
646
647 static int intel_atomic_set(struct drm_device *dev, void *state,
648                             struct drm_mode_object *obj,
649                             struct drm_property *prop,
650                             uint64_t value, void *blob_data)
651 {
652         struct intel_atomic_state *s = state;
653         int ret = -EINVAL;
654
655         switch (obj->type) {
656         case DRM_MODE_OBJECT_PLANE:
657                 ret = plane_set(s, get_plane_state(dev, s, obj_to_plane(obj)), prop, value);
658                 break;
659         case DRM_MODE_OBJECT_CRTC:
660                 ret = crtc_set(s, get_crtc_state(dev, s, obj_to_crtc(obj)), prop, value, blob_data);
661                 break;
662         default:
663                 break;
664         }
665
666         kfree(blob_data);
667
668         return ret;
669 }
670
671 int intel_check_plane(const struct drm_plane *plane,
672                       const struct drm_crtc *crtc,
673                       const struct drm_framebuffer *fb,
674                       struct intel_plane_coords *st);
675
676 static void dirty_planes(const struct drm_device *dev,
677                          struct intel_atomic_state *state,
678                          const struct drm_crtc *crtc)
679 {
680         int i;
681
682         for (i = 0; i < dev->mode_config.num_plane; i++) {
683                 struct intel_plane_state *s = &state->plane[i];
684
685                 if (s->plane->crtc == crtc)
686                         s->dirty = true;
687         }
688 }
689
690 static int check_crtc(struct intel_crtc_state *s)
691 {
692         struct drm_crtc *crtc = s->crtc;
693         struct drm_device *dev = crtc->dev;
694         struct drm_encoder *encoder;
695         struct drm_framebuffer *fb = crtc->fb;
696         struct drm_display_mode mode, adjusted_mode;
697         const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
698
699         /* must have a fb and connectors if we have a mode, and vice versa */
700         if (crtc->enabled) {
701                 if (!fb)
702                         return -EINVAL;
703                 if (!drm_helper_crtc_in_use(crtc))
704                         return -EINVAL;
705         } else {
706                 if (fb)
707                         return -EINVAL;
708                 if (drm_helper_crtc_in_use(crtc))
709                         return -EINVAL;
710         }
711
712         if (crtc->enabled) {
713                 if (crtc->mode.hdisplay > fb->width ||
714                     crtc->mode.vdisplay > fb->height ||
715                     crtc->x > fb->width - crtc->mode.hdisplay ||
716                     crtc->y > fb->height - crtc->mode.vdisplay)
717                         return -ENOSPC;
718         }
719
720         if (!crtc->enabled || !s->mode_dirty)
721                 return 0;
722
723         mode = adjusted_mode = crtc->mode;
724
725         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
726                 const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
727
728                 if (!encoder_funcs->mode_fixup(encoder, &mode, &adjusted_mode))
729                         return -EINVAL;
730         }
731
732         if (!crtc_funcs->mode_fixup(crtc, &mode, &adjusted_mode))
733                 return -EINVAL;
734
735         adjusted_mode.clock = mode.clock;
736
737         crtc->hwmode = adjusted_mode;
738
739         return 0;
740 }
741
742 static int intel_atomic_check(struct drm_device *dev, void *state)
743 {
744         struct intel_atomic_state *s = state;
745         int ret;
746         int i;
747
748         if (!s->dirty)
749                 return 0;
750
751         for (i = 0; i < dev->mode_config.num_crtc; i++) {
752                 struct intel_crtc_state *st = &s->crtc[i];
753
754                 if (!st->fb_dirty && !st->mode_dirty)
755                         continue;
756
757                 ret = check_crtc(st);
758                 if (ret)
759                         return ret;
760
761                 /*
762                  * Mark all planes on this CRTC as dirty if the active video
763                  * area changed so that the planes will get reclipped correctly.
764                  *
765                  * Also any modesetting will disable+enable the pipe, so the
766                  * plane needs to be re-enabled afterwards too.
767                  * TODO: there's no need to redo the clipping in such cases
768                  * if the computed values were cached, the could be commited
769                  * directly.
770                  */
771                 if (st->active_dirty || st->mode_dirty)
772                         dirty_planes(dev, s, st->crtc);
773         }
774
775         /* check for conflicts in encoder/connector assignment */
776         for (i = 0; i < dev->mode_config.num_crtc; i++) {
777                 struct intel_crtc_state *st = &s->crtc[i];
778                 int j;
779
780                 for (j = i + 1; j < dev->mode_config.num_crtc; j++) {
781                         struct intel_crtc_state *st2 = &s->crtc[j];
782
783                         if (st->connectors_bitmask & st2->connectors_bitmask)
784                                 return -EINVAL;
785
786                         if (st->encoders_bitmask & st2->encoders_bitmask)
787                                 return -EINVAL;
788                 }
789         }
790
791         for (i = 0; i < dev->mode_config.num_plane; i++) {
792                 struct intel_plane_state *st = &s->plane[i];
793                 const struct drm_plane *plane = st->plane;
794
795                 if (!st->dirty)
796                         continue;
797
798                 st->coords.crtc_x = plane->crtc_x;
799                 st->coords.crtc_y = plane->crtc_y;
800                 st->coords.crtc_w = plane->crtc_w;
801                 st->coords.crtc_h = plane->crtc_h;
802
803                 st->coords.src_x = plane->src_x;
804                 st->coords.src_y = plane->src_y;
805                 st->coords.src_w = plane->src_w;
806                 st->coords.src_h = plane->src_h;
807
808                 ret = intel_check_plane(plane, plane->crtc, plane->fb, &st->coords);
809                 if (ret)
810                         return ret;
811         }
812
813         return 0;
814 }
815
816 static void update_plane_props(struct drm_plane *plane)
817 {
818         struct drm_mode_object *obj = &plane->base;
819
820         drm_object_property_set_value(obj, prop_src_x, plane->src_x);
821         drm_object_property_set_value(obj, prop_src_y, plane->src_y);
822         drm_object_property_set_value(obj, prop_src_w, plane->src_w);
823         drm_object_property_set_value(obj, prop_src_h, plane->src_h);
824
825         drm_object_property_set_value(obj, prop_crtc_x, plane->crtc_x);
826         drm_object_property_set_value(obj, prop_crtc_y, plane->crtc_y);
827         drm_object_property_set_value(obj, prop_crtc_w, plane->crtc_w);
828         drm_object_property_set_value(obj, prop_crtc_h, plane->crtc_h);
829
830         drm_object_property_set_value(obj, prop_fb_id, plane->fb ? plane->fb->base.id : 0);
831         drm_object_property_set_value(obj, prop_crtc_id, plane->crtc ? plane->crtc->base.id : 0);
832 }
833
834 static int free_connector_ids(struct drm_crtc *crtc)
835 {
836         struct drm_device *dev = crtc->dev;
837         struct drm_mode_object *obj;
838         uint64_t value;
839         int ret;
840
841         ret = drm_object_property_get_value(&crtc->base, prop_connector_ids, &value);
842         if (ret)
843                 return ret;
844
845         if (!value)
846                 return 0;
847
848         obj = drm_mode_object_find(dev, value, DRM_MODE_PROP_BLOB);
849         if (!obj)
850                 return -ENOENT;
851
852         drm_property_destroy_blob(dev, obj_to_blob(obj));
853
854         return 0;
855 }
856
857 static int update_connector_ids(struct drm_crtc *crtc)
858 {
859         struct drm_device *dev = crtc->dev;
860         struct drm_connector *connector;
861         struct drm_property_blob *blob;
862         uint64_t value = 0;
863         int i = 0;
864         uint32_t connector_ids[dev->mode_config.num_connector];
865
866         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
867                 if (connector->encoder && connector->encoder->crtc == crtc)
868                         connector_ids[i++] = connector->base.id;
869         }
870
871         if (i) {
872                 /*
873                  * FIXME make blobs into vectors, and pre-allocate using worst case estimate.
874                  * That way this function could never fail.
875                  */
876                 blob = drm_property_create_blob(dev, i * sizeof connector_ids[0], connector_ids);
877                 if (!blob)
878                         return -ENOMEM;
879
880                 value = blob->base.id;
881         }
882
883         free_connector_ids(crtc);
884
885         drm_object_property_set_value(&crtc->base, prop_connector_ids, value);
886
887         return 0;
888 }
889
890 static void update_crtc_props(struct drm_crtc *crtc)
891 {
892         struct drm_mode_object *obj = &crtc->base;
893
894         drm_object_property_set_value(obj, prop_src_x, crtc->x);
895         drm_object_property_set_value(obj, prop_src_y, crtc->y);
896
897         drm_object_property_set_value(obj, prop_fb_id, crtc->fb ? crtc->fb->base.id : 0);
898
899         /*
900          * FIXME if mode is user specifiec via old setcrtc ioctl prop value should be -1
901          * or perhaps setcrtc should insert an imlicitly created mode into some list...
902          */
903         drm_object_property_set_value(obj, prop_mode_id,
904                                       crtc->enabled ? crtc->mode.base.id : 0);
905
906         update_connector_ids(crtc);
907 }
908
909 static void update_props(const struct drm_device *dev,
910                          struct intel_atomic_state *s)
911 {
912         int i;
913
914         for (i = 0; i < dev->mode_config.num_crtc; i++) {
915                 struct intel_crtc_state *st = &s->crtc[i];
916
917                 if (!st->fb_dirty && !st->mode_dirty)
918                         continue;
919
920                 update_crtc_props(st->crtc);
921         }
922
923         for (i = 0; i < dev->mode_config.num_plane; i++) {
924                 struct intel_plane_state *st = &s->plane[i];
925
926                 if (!st->dirty)
927                         continue;
928
929                 update_plane_props(st->plane);
930         }
931 }
932
933 static int intel_atomic_commit(struct drm_device *dev, void *state)
934 {
935         struct intel_atomic_state *s = state;
936         int ret;
937
938         if (!s->dirty)
939                 return 0;
940
941         ret = apply_config(dev, s);
942         if (ret) {
943                 s->restore_hw = true;
944                 return ret;
945         }
946
947         update_props(dev, s);
948
949         return 0;
950 }
951
952 static void intel_atomic_end(struct drm_device *dev, void *state)
953 {
954         struct intel_atomic_state *s = state;
955
956         /* restore the state of all objects */
957         if (s->dirty)
958                 restore_state(dev, state);
959
960         kfree(state);
961 }
962
963 static const struct drm_atomic_funcs intel_atomic_funcs = {
964         .begin = intel_atomic_begin,
965         .set = intel_atomic_set,
966         .check = intel_atomic_check,
967         .commit = intel_atomic_commit,
968         .end = intel_atomic_end,
969 };
970
971 int intel_atomic_init(struct drm_device *dev)
972 {
973         struct drm_crtc *crtc;
974         struct drm_plane *plane;
975         int ret = -ENOMEM;
976
977         prop_src_x = drm_property_create_range(dev, 0, "SRC_X", 0, UINT_MAX);
978         if (!prop_src_x)
979                 goto out;
980         prop_src_y = drm_property_create_range(dev, 0, "SRC_Y", 0, UINT_MAX);
981         if (!prop_src_y)
982                 goto destroy_src_x;
983         prop_src_w = drm_property_create_range(dev, 0, "SRC_W", 0, UINT_MAX);
984         if (!prop_src_w)
985                 goto destroy_src_y;
986         prop_src_h = drm_property_create_range(dev, 0, "SRC_H", 0, UINT_MAX);
987         if (!prop_src_h)
988                 goto destroy_src_w;
989
990         prop_crtc_x = drm_property_create_range(dev, 0, "CRTC_X", INT_MIN, INT_MAX);
991         if (!prop_crtc_x)
992                 goto destroy_src_h;
993         prop_crtc_y = drm_property_create_range(dev, 0, "CRTC_Y", INT_MIN, INT_MAX);
994         if (!prop_crtc_y)
995                 goto destroy_crtc_x;
996         prop_crtc_w = drm_property_create_range(dev, 0, "CRTC_W", 0, INT_MAX);
997         if (!prop_crtc_w)
998                 goto destroy_crtc_y;
999         prop_crtc_h = drm_property_create_range(dev, 0, "CRTC_H", 0, INT_MAX);
1000         if (!prop_crtc_h)
1001                 goto destroy_crtc_w;
1002
1003         /* FIXME create special object ID property type? */
1004         prop_fb_id = drm_property_create_range(dev, 0, "FB_ID", 0, UINT_MAX);
1005         if (!prop_fb_id)
1006                 goto destroy_crtc_h;
1007         prop_crtc_id = drm_property_create_range(dev, 0, "CRTC_ID", 0, UINT_MAX);
1008         if (!prop_crtc_id)
1009                 goto destroy_fb_id;
1010         prop_mode_id = drm_property_create_range(dev, 0, "MODE_ID", 0, UINT_MAX);
1011         if (!prop_mode_id)
1012                 goto destroy_crtc_id;
1013
1014         /* FIXME create special object ID list property type? */
1015         prop_connector_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CONNECTOR_IDS", 0);
1016         if (!prop_connector_ids)
1017                 goto destroy_mode_id;
1018
1019         list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
1020                 struct drm_mode_object *obj = &plane->base;
1021
1022                 drm_object_attach_property(obj, prop_src_x, 0);
1023                 drm_object_attach_property(obj, prop_src_y, 0);
1024                 drm_object_attach_property(obj, prop_src_w, 0);
1025                 drm_object_attach_property(obj, prop_src_h, 0);
1026
1027                 drm_object_attach_property(obj, prop_crtc_x, 0);
1028                 drm_object_attach_property(obj, prop_crtc_y, 0);
1029                 drm_object_attach_property(obj, prop_crtc_w, 0);
1030                 drm_object_attach_property(obj, prop_crtc_h, 0);
1031
1032                 drm_object_attach_property(obj, prop_fb_id, 0);
1033                 drm_object_attach_property(obj, prop_crtc_id, 0);
1034
1035                 update_plane_props(plane);
1036         }
1037
1038         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1039                 struct drm_mode_object *obj = &crtc->base;
1040
1041                 drm_object_attach_property(obj, prop_src_x, 0);
1042                 drm_object_attach_property(obj, prop_src_y, 0);
1043
1044                 drm_object_attach_property(obj, prop_fb_id, 0);
1045                 drm_object_attach_property(obj, prop_mode_id, 0);
1046                 drm_object_attach_property(obj, prop_connector_ids, 0);
1047
1048                 update_crtc_props(crtc);
1049         }
1050
1051         dev->driver->atomic_funcs = &intel_atomic_funcs;
1052
1053         return 0;
1054
1055  destroy_mode_id:
1056         drm_property_destroy(dev, prop_mode_id);
1057  destroy_crtc_id:
1058         drm_property_destroy(dev, prop_crtc_id);
1059  destroy_fb_id:
1060         drm_property_destroy(dev, prop_fb_id);
1061  destroy_crtc_h:
1062         drm_property_destroy(dev, prop_crtc_h);
1063  destroy_crtc_w:
1064         drm_property_destroy(dev, prop_crtc_w);
1065  destroy_crtc_y:
1066         drm_property_destroy(dev, prop_crtc_y);
1067  destroy_crtc_x:
1068         drm_property_destroy(dev, prop_crtc_x);
1069  destroy_src_h:
1070         drm_property_destroy(dev, prop_src_h);
1071  destroy_src_w:
1072         drm_property_destroy(dev, prop_src_w);
1073  destroy_src_y:
1074         drm_property_destroy(dev, prop_src_y);
1075  destroy_src_x:
1076         drm_property_destroy(dev, prop_src_x);
1077  out:
1078         return ret;
1079 }
1080
1081 void intel_atomic_fini(struct drm_device *dev)
1082 {
1083         struct drm_crtc *crtc;
1084
1085         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
1086                 free_connector_ids(crtc);
1087
1088         drm_property_destroy(dev, prop_connector_ids);
1089         drm_property_destroy(dev, prop_mode_id);
1090         drm_property_destroy(dev, prop_crtc_id);
1091         drm_property_destroy(dev, prop_fb_id);
1092
1093         drm_property_destroy(dev, prop_crtc_h);
1094         drm_property_destroy(dev, prop_crtc_w);
1095         drm_property_destroy(dev, prop_crtc_y);
1096         drm_property_destroy(dev, prop_crtc_x);
1097
1098         drm_property_destroy(dev, prop_src_h);
1099         drm_property_destroy(dev, prop_src_w);
1100         drm_property_destroy(dev, prop_src_y);
1101         drm_property_destroy(dev, prop_src_x);
1102 }