OSDN Git Service

radeon: Fix type in check for tmds type.
[android-x86/external-libdrm.git] / linux-core / nv50_kms_wrapper.c
1 /*
2  * Copyright (C) 2008 Maarten Maathuis.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26
27 #include "nv50_kms_wrapper.h"
28 #include "drm_crtc_helper.h" /* be careful what you use from this */
29
30 /* This file serves as the interface between the common kernel modesetting code and the device dependent implementation. */
31
32 /*
33  * Get private functions.
34  */
35
36 struct nv50_kms_priv *nv50_get_kms_priv(struct drm_device *dev)
37 {
38         struct drm_nouveau_private *dev_priv = dev->dev_private;
39         return dev_priv->kms_priv;
40 }
41
42 /*
43  * Allocation functions.
44  */
45
46 static void *nv50_kms_alloc_crtc(struct drm_device *dev)
47 {
48         struct nv50_kms_priv *kms_priv = nv50_get_kms_priv(dev);
49         struct nv50_kms_crtc *crtc = kzalloc(sizeof(struct nv50_kms_crtc), GFP_KERNEL);
50
51         if (!crtc)
52                 return NULL;
53
54         list_add_tail(&crtc->item, &kms_priv->crtcs);
55
56         return &(crtc->priv);
57 }
58
59 static void *nv50_kms_alloc_output(struct drm_device *dev)
60 {
61         struct nv50_kms_priv *kms_priv = nv50_get_kms_priv(dev);
62         struct nv50_kms_encoder *encoder = kzalloc(sizeof(struct nv50_kms_encoder), GFP_KERNEL);
63
64         if (!encoder)
65                 return NULL;
66
67         list_add_tail(&encoder->item, &kms_priv->encoders);
68
69         return &(encoder->priv);
70 }
71
72 static void *nv50_kms_alloc_connector(struct drm_device *dev)
73 {
74         struct nv50_kms_priv *kms_priv = nv50_get_kms_priv(dev);
75         struct nv50_kms_connector *connector = kzalloc(sizeof(struct nv50_kms_connector), GFP_KERNEL);
76
77         if (!connector)
78                 return NULL;
79
80         list_add_tail(&connector->item, &kms_priv->connectors);
81
82         return &(connector->priv);
83 }
84
85 static void nv50_kms_free_crtc(void *crtc)
86 {
87         struct nv50_kms_crtc *kms_crtc = from_nv50_crtc(crtc);
88
89         list_del(&kms_crtc->item);
90
91         kfree(kms_crtc);
92 }
93
94 static void nv50_kms_free_output(void *output)
95 {
96         struct nv50_kms_encoder *kms_encoder = from_nv50_output(output);
97
98         list_del(&kms_encoder->item);
99
100         kfree(kms_encoder);
101 }
102
103 static void nv50_kms_free_connector(void *connector)
104 {
105         struct nv50_kms_connector *kms_connector = from_nv50_connector(connector);
106
107         list_del(&kms_connector->item);
108
109         kfree(kms_connector);
110 }
111
112 /*
113  * Mode conversion functions.
114  */
115
116 static struct nouveau_hw_mode *nv50_kms_to_hw_mode(struct drm_display_mode *mode)
117 {
118         struct nouveau_hw_mode *hw_mode = kzalloc(sizeof(struct nouveau_hw_mode), GFP_KERNEL);
119         if (!hw_mode)
120                 return NULL;
121
122         /* create hw values. */
123         hw_mode->clock = mode->clock;
124         hw_mode->flags = hw_mode->flags;
125
126         hw_mode->hdisplay = mode->hdisplay;
127         hw_mode->hsync_start = mode->hsync_start;
128         hw_mode->hsync_end = mode->hsync_end;
129         hw_mode->htotal = mode->htotal;
130
131         hw_mode->hblank_start = mode->hdisplay + 1;
132         hw_mode->hblank_end = mode->htotal;
133
134         hw_mode->vdisplay = mode->vdisplay;
135         hw_mode->vsync_start = mode->vsync_start;
136         hw_mode->vsync_end = mode->vsync_end;
137         hw_mode->vtotal = mode->vtotal;
138
139         hw_mode->vblank_start = mode->vdisplay + 1;
140         hw_mode->vblank_end = mode->vtotal;
141
142         return hw_mode;
143 }
144
145 /*
146  * State mirroring functions.
147  */
148
149 static void nv50_kms_mirror_routing(struct drm_device *dev)
150 {
151         struct nv50_display *display = nv50_get_display(dev);
152         struct nv50_crtc *crtc = NULL;
153         struct nv50_output *output = NULL;
154         struct nv50_connector *connector = NULL;
155         struct drm_connector *drm_connector = NULL;
156         struct drm_crtc *drm_crtc = NULL;
157
158         /* Wipe all previous connections. */
159         list_for_each_entry(connector, &display->connectors, item) {
160                 connector->output = NULL;
161         }
162
163         list_for_each_entry(output, &display->outputs, item) {
164                 output->crtc = NULL;
165         }
166
167         list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
168                 if (drm_connector->encoder) {
169                         output = to_nv50_output(drm_connector->encoder);
170                         connector = to_nv50_connector(drm_connector);
171
172                         /* hook up output to connector. */
173                         connector->output = output;
174
175                         if (drm_connector->encoder->crtc) {
176                                 crtc = to_nv50_crtc(drm_connector->encoder->crtc);
177
178                                 /* hook up output to crtc. */
179                                 output->crtc = crtc;
180                         }
181                 }
182         }
183
184         /* mirror crtc active state */
185         list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) {
186                 crtc = to_nv50_crtc(drm_crtc);
187
188                 crtc->enabled = drm_crtc->enabled;
189         }
190 }
191
192 /*
193  * FB functions.
194  */
195
196 static void nv50_kms_framebuffer_destroy(struct drm_framebuffer *drm_framebuffer)
197 {
198         drm_framebuffer_cleanup(drm_framebuffer);
199
200         kfree(drm_framebuffer);
201 }
202
203 static const struct drm_framebuffer_funcs nv50_kms_fb_funcs = {
204         .destroy = nv50_kms_framebuffer_destroy,
205 };
206
207 /*
208  * Mode config functions.
209  */
210
211 static struct drm_framebuffer *nv50_kms_framebuffer_create(struct drm_device *dev,
212                                                 struct drm_file *file_priv, struct drm_mode_fb_cmd *mode_cmd)
213 {
214         struct drm_framebuffer *drm_framebuffer = kzalloc(sizeof(struct drm_framebuffer), GFP_KERNEL);
215         if (!drm_framebuffer)
216                 return NULL;
217
218         drm_framebuffer_init(dev, drm_framebuffer, &nv50_kms_fb_funcs);
219         drm_helper_mode_fill_fb_struct(drm_framebuffer, mode_cmd);
220
221         return drm_framebuffer;
222 }
223
224 static int nv50_kms_fb_changed(struct drm_device *dev)
225 {
226         return 0; /* not needed until nouveaufb? */
227 }
228
229 static const struct drm_mode_config_funcs nv50_kms_mode_funcs = {
230         .resize_fb = NULL,
231         .fb_create = nv50_kms_framebuffer_create,
232         .fb_changed = nv50_kms_fb_changed,
233 };
234
235 /*
236  * CRTC functions.
237  */
238
239 static int nv50_kms_crtc_cursor_set(struct drm_crtc *drm_crtc, 
240                                     struct drm_file *file_priv,
241                                     uint32_t buffer_handle,
242                                     uint32_t width, uint32_t height)
243 {
244         struct nv50_crtc *crtc = to_nv50_crtc(drm_crtc);
245         struct nv50_display *display = nv50_get_display(crtc->dev);
246         int rval = 0;
247
248         if (width != 64 || height != 64)
249                 return -EINVAL;
250
251         /* set bo before doing show cursor */
252         if (buffer_handle) {
253                 rval = crtc->cursor->set_bo(crtc, (drm_handle_t) buffer_handle);
254                 if (rval != 0)
255                         goto out;
256         }
257
258         crtc->cursor->visible = buffer_handle ? true : false;
259
260         if (buffer_handle) {
261                 rval = crtc->cursor->show(crtc);
262                 if (rval != 0)
263                         goto out;
264         } else { /* no handle implies hiding the cursor */
265                 rval = crtc->cursor->hide(crtc);
266                 goto out;
267         }
268
269         if (rval != 0)
270                 return rval;
271
272 out:
273         /* in case this triggers any other cursor changes */
274         display->update(display);
275
276         return rval;
277 }
278
279 static int nv50_kms_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y)
280 {
281         struct nv50_crtc *crtc = to_nv50_crtc(drm_crtc);
282
283         return crtc->cursor->set_pos(crtc, x, y);
284 }
285
286 void nv50_kms_crtc_gamma_set(struct drm_crtc *drm_crtc, u16 *r, u16 *g, u16 *b,
287                 uint32_t size)
288 {
289         struct nv50_crtc *crtc = to_nv50_crtc(drm_crtc);
290
291         if (size != 256)
292                 return;
293
294         crtc->lut->set(crtc, (uint16_t *)r, (uint16_t *)g, (uint16_t *)b);
295 }
296
297 int nv50_kms_crtc_set_config(struct drm_mode_set *set)
298 {
299         int rval = 0, i;
300         uint32_t crtc_mask = 0;
301         struct drm_device *dev = NULL;
302         struct drm_nouveau_private *dev_priv = NULL;
303         struct nv50_display *display = NULL;
304         struct drm_connector *drm_connector = NULL;
305         struct drm_encoder *drm_encoder = NULL;
306         struct drm_crtc *drm_crtc = NULL;
307
308         struct nv50_crtc *crtc = NULL;
309         struct nv50_output *output = NULL;
310         struct nv50_connector *connector = NULL;
311         struct nouveau_hw_mode *hw_mode = NULL;
312         struct nv50_fb_info fb_info;
313
314         bool blank = false;
315         bool switch_fb = false;
316         bool modeset = false;
317
318         NV50_DEBUG("\n");
319
320         /*
321          * Supported operations:
322          * - Switch mode.
323          * - Switch framebuffer.
324          * - Blank screen.
325          */
326
327         /* Sanity checking */
328         if (!set) {
329                 DRM_ERROR("Sanity check failed\n");
330                 goto out;
331         }
332
333         if (!set->crtc) {
334                 DRM_ERROR("Sanity check failed\n");
335                 goto out;
336         }
337
338         if (set->mode) {
339                 if (set->fb) {
340                         if (!drm_mode_equal(set->mode, &set->crtc->mode))
341                                 modeset = true;
342
343                         if (set->fb != set->crtc->fb)
344                                 switch_fb = true;
345
346                         if (set->x != set->crtc->x || set->y != set->crtc->y)
347                                 switch_fb = true;
348                 }
349         } else {
350                 blank = true;
351         }
352
353         if (!set->connectors && !blank) {
354                 DRM_ERROR("Sanity check failed\n");
355                 goto out;
356         }
357
358         /* Basic variable setting */
359         dev = set->crtc->dev;
360         dev_priv = dev->dev_private;
361         display = nv50_get_display(dev);
362         crtc = to_nv50_crtc(set->crtc);
363
364         /**
365          * Wiring up the encoders and connectors.
366          */
367
368         /* for switch_fb we verify if any important changes happened */
369         if (!blank) {
370                 /* Mode validation */
371                 hw_mode = nv50_kms_to_hw_mode(set->mode);
372
373                 rval = crtc->validate_mode(crtc, hw_mode);
374
375                 if (rval != MODE_OK) {
376                         DRM_ERROR("Mode not ok\n");
377                         goto out;
378                 }
379
380                 for (i = 0; i < set->num_connectors; i++) {
381                         drm_connector = set->connectors[i];
382                         if (!drm_connector) {
383                                 DRM_ERROR("No connector\n");
384                                 goto out;
385                         }
386                         connector = to_nv50_connector(drm_connector);
387
388                         /* This is to ensure it knows the connector subtype. */
389                         drm_connector->funcs->fill_modes(drm_connector, 0, 0);
390
391                         output = connector->to_output(connector, nv50_kms_connector_get_digital(drm_connector));
392                         if (!output) {
393                                 DRM_ERROR("No output\n");
394                                 goto out;
395                         }
396
397                         rval = output->validate_mode(output, hw_mode);
398                         if (rval != MODE_OK) {
399                                 DRM_ERROR("Mode not ok\n");
400                                 goto out;
401                         }
402
403                         /* verify if any "sneaky" changes happened */
404                         if (output != connector->output)
405                                 modeset = true;
406
407                         if (output->crtc != crtc)
408                                 modeset = true;
409                 }
410         }
411
412         /* Now we verified if anything changed, fail if nothing has. */
413         if (!modeset && !switch_fb && !blank)
414                 DRM_INFO("A seemingly empty modeset encountered, this could be a bug.\n");
415
416         /* Validation done, move on to cleaning of existing structures. */
417         if (modeset) {
418                 /* find encoders that use this crtc. */
419                 list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
420                         if (drm_encoder->crtc == set->crtc) {
421                                 /* find the connector that goes with it */
422                                 list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
423                                         if (drm_connector->encoder == drm_encoder) {
424                                                 drm_connector->encoder =  NULL;
425                                                 break;
426                                         }
427                                 }
428                                 drm_encoder->crtc = NULL;
429                         }
430                 }
431
432                 /* now find if our desired encoders or connectors are in use already. */
433                 for (i = 0; i < set->num_connectors; i++) {
434                         drm_connector = set->connectors[i];
435                         if (!drm_connector) {
436                                 DRM_ERROR("No connector\n");
437                                 goto out;
438                         }
439
440                         if (!drm_connector->encoder)
441                                 continue;
442
443                         drm_encoder = drm_connector->encoder;
444                         drm_connector->encoder = NULL;
445
446                         if (!drm_encoder->crtc)
447                                 continue;
448
449                         drm_crtc = drm_encoder->crtc;
450                         drm_encoder->crtc = NULL;
451
452                         drm_crtc->enabled = false;
453                 }
454
455                 /* Time to wire up the public encoder, the private one will be handled later. */
456                 for (i = 0; i < set->num_connectors; i++) {
457                         drm_connector = set->connectors[i];
458                         if (!drm_connector) {
459                                 DRM_ERROR("No connector\n");
460                                 goto out;
461                         }
462
463                         output = connector->to_output(connector, nv50_kms_connector_get_digital(drm_connector));
464                         if (!output) {
465                                 DRM_ERROR("No output\n");
466                                 goto out;
467                         }
468
469                         /* find the encoder public structure that matches out output structure. */
470                         drm_encoder = to_nv50_kms_encoder(output);
471
472                         if (!drm_encoder) {
473                                 DRM_ERROR("No encoder\n");
474                                 goto out;
475                         }
476
477                         drm_encoder->crtc = set->crtc;
478                         set->crtc->enabled = true;
479                         drm_connector->encoder = drm_encoder;
480                 }
481         }
482
483         /**
484          * Disable crtc.
485          */
486
487         if (blank) {
488                 crtc = to_nv50_crtc(set->crtc);
489
490                 set->crtc->enabled = false;
491
492                 /* disconnect encoders and connectors */
493                 for (i = 0; i < set->num_connectors; i++) {
494                         drm_connector = set->connectors[i];
495
496                         if (!drm_connector->encoder)
497                                 continue;
498
499                         drm_connector->encoder->crtc = NULL;
500                         drm_connector->encoder = NULL;
501                 }
502         }
503
504         /**
505          * All state should now be updated, now onto the real work.
506          */
507
508         /* mirror everything to the private structs */
509         nv50_kms_mirror_routing(dev);
510
511         /**
512          * Bind framebuffer.
513          */
514
515         if (switch_fb) {
516                 crtc = to_nv50_crtc(set->crtc);
517
518                 /* set framebuffer */
519                 set->crtc->fb = set->fb;
520
521                 /* set private framebuffer */
522                 crtc = to_nv50_crtc(set->crtc);
523                 fb_info.block = find_block_by_handle(dev_priv->fb_heap, set->fb->mm_handle);
524                 fb_info.width = set->fb->width;
525                 fb_info.height = set->fb->height;
526                 fb_info.depth = set->fb->depth;
527                 fb_info.bpp = set->fb->bits_per_pixel;
528                 fb_info.pitch = set->fb->pitch;
529                 fb_info.x = set->x;
530                 fb_info.y = set->y;
531
532                 rval = crtc->fb->bind(crtc, &fb_info);
533                 if (rval != 0) {
534                         DRM_ERROR("fb_bind failed\n");
535                         goto out;
536                 }
537         }
538
539         /* this is !cursor_show */
540         if (!crtc->cursor->enabled) {
541                 rval = crtc->cursor->enable(crtc);
542                 if (rval != 0) {
543                         DRM_ERROR("cursor_enable failed\n");
544                         goto out;
545                 }
546         }
547
548         /**
549          * Blanking.
550          */
551
552         if (blank) {
553                 crtc = to_nv50_crtc(set->crtc);
554
555                 rval = crtc->blank(crtc, true);
556                 if (rval != 0) {
557                         DRM_ERROR("blanking failed\n");
558                         goto out;
559                 }
560
561                 /* detach any outputs that are currently unused */
562                 list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
563                         if (!drm_encoder->crtc) {
564                                 output = to_nv50_output(drm_encoder);
565
566                                 rval = output->execute_mode(output, true);
567                                 if (rval != 0) {
568                                         DRM_ERROR("detaching output failed\n");
569                                         goto out;
570                                 }
571                         }
572                 }
573         }
574
575         /**
576          * Change framebuffer, without changing mode.
577          */
578
579         if (switch_fb && !modeset && !blank) {
580                 crtc = to_nv50_crtc(set->crtc);
581
582                 rval = crtc->set_fb(crtc);
583                 if (rval != 0) {
584                         DRM_ERROR("set_fb failed\n");
585                         goto out;
586                 }
587
588                 /* this also sets the fb offset */
589                 rval = crtc->blank(crtc, false);
590                 if (rval != 0) {
591                         DRM_ERROR("unblanking failed\n");
592                         goto out;
593                 }
594         }
595
596         /**
597          * Normal modesetting.
598          */
599
600         if (modeset) {
601                 crtc = to_nv50_crtc(set->crtc);
602
603                 /* disconnect unused outputs */
604                 list_for_each_entry(output, &display->outputs, item) {
605                         if (output->crtc) {
606                                 crtc_mask |= 1 << output->crtc->index;
607                         } else {
608                                 rval = output->execute_mode(output, true);
609                                 if (rval != 0) {
610                                         DRM_ERROR("detaching output failed\n");
611                                         goto out;
612                                 }
613                         }
614                 }
615
616                 /* blank any unused crtcs */
617                 list_for_each_entry(crtc, &display->crtcs, item) {
618                         if (!(crtc_mask & (1 << crtc->index)))
619                                 crtc->blank(crtc, true);
620                 }
621
622                 crtc = to_nv50_crtc(set->crtc);
623
624                 rval = crtc->set_mode(crtc, hw_mode);
625                 if (rval != 0) {
626                         DRM_ERROR("crtc mode set failed\n");
627                         goto out;
628                 }
629
630                 /* find native mode. */
631                 list_for_each_entry(output, &display->outputs, item) {
632                         if (output->crtc != crtc)
633                                 continue;
634
635                         *crtc->native_mode = *output->native_mode;
636                         list_for_each_entry(connector, &display->connectors, item) {
637                                 if (connector->output != output)
638                                         continue;
639
640                                 crtc->requested_scaling_mode = connector->requested_scaling_mode;
641                                 crtc->use_dithering = connector->use_dithering;
642                                 break;
643                         }
644
645                         if (crtc->requested_scaling_mode == SCALE_NON_GPU)
646                                 crtc->use_native_mode = false;
647                         else
648                                 crtc->use_native_mode = true;
649
650                         break; /* no use in finding more than one mode */
651                 }
652
653                 rval = crtc->execute_mode(crtc);
654                 if (rval != 0) {
655                         DRM_ERROR("crtc execute mode failed\n");
656                         goto out;
657                 }
658
659                 list_for_each_entry(output, &display->outputs, item) {
660                         if (output->crtc != crtc)
661                                 continue;
662
663                         rval = output->execute_mode(output, false);
664                         if (rval != 0) {
665                                 DRM_ERROR("output execute mode failed\n");
666                                 goto out;
667                         }
668                 }
669
670                 rval = crtc->set_scale(crtc);
671                 if (rval != 0) {
672                         DRM_ERROR("crtc set scale failed\n");
673                         goto out;
674                 }
675
676                 /* next line changes crtc, so putting it here is important */
677                 display->last_crtc = crtc->index;
678         }
679
680         /* always reset dpms, regardless if any other modesetting is done. */
681         if (!blank) {
682                 /* this is executed immediately */
683                 list_for_each_entry(output, &display->outputs, item) {
684                         if (output->crtc != crtc)
685                                 continue;
686
687                         rval = output->set_power_mode(output, DRM_MODE_DPMS_ON);
688                         if (rval != 0) {
689                                 DRM_ERROR("output set power mode failed\n");
690                                 goto out;
691                         }
692                 }
693
694                 /* update dpms state to DPMSModeOn */
695                 for (i = 0; i < set->num_connectors; i++) {
696                         drm_connector = set->connectors[i];
697                         if (!drm_connector) {
698                                 DRM_ERROR("No connector\n");
699                                 goto out;
700                         }
701
702                         rval = drm_connector_property_set_value(drm_connector,
703                                         dev->mode_config.dpms_property,
704                                         DRM_MODE_DPMS_ON);
705                         if (rval != 0) {
706                                 DRM_ERROR("failed to update dpms state\n");
707                                 goto out;
708                         }
709                 }
710         }
711
712         display->update(display);
713
714         /* Update the current mode, now that all has gone well. */
715         if (modeset) {
716                 set->crtc->mode = *(set->mode);
717                 set->crtc->x = set->x;
718                 set->crtc->y = set->y;
719         }
720
721         kfree(hw_mode);
722
723         return 0;
724
725 out:
726         kfree(hw_mode);
727
728         if (rval != 0)
729                 return rval;
730         else
731                 return -EINVAL;
732 }
733
734 static void nv50_kms_crtc_destroy(struct drm_crtc *drm_crtc)
735 {
736         struct nv50_crtc *crtc = to_nv50_crtc(drm_crtc);
737
738         drm_crtc_cleanup(drm_crtc);
739
740         /* this will even destroy the public structure. */
741         crtc->destroy(crtc);
742 }
743
744 static const struct drm_crtc_funcs nv50_kms_crtc_funcs = {
745         .save = NULL,
746         .restore = NULL,
747         .cursor_set = nv50_kms_crtc_cursor_set,
748         .cursor_move = nv50_kms_crtc_cursor_move,
749         .gamma_set = nv50_kms_crtc_gamma_set,
750         .set_config = nv50_kms_crtc_set_config,
751         .destroy = nv50_kms_crtc_destroy,
752 };
753
754 static int nv50_kms_crtcs_init(struct drm_device *dev)
755 {
756         struct nv50_display *display = nv50_get_display(dev);
757         struct nv50_crtc *crtc = NULL;
758
759         /*
760          * This may look a bit confusing, but:
761          * The internal structure is already allocated and so is the public one.
762          * Just a matter of getting to the memory and register it.
763          */
764         list_for_each_entry(crtc, &display->crtcs, item) {
765                 struct drm_crtc *drm_crtc = to_nv50_kms_crtc(crtc);
766
767                 drm_crtc_init(dev, drm_crtc, &nv50_kms_crtc_funcs);
768
769                 /* init lut storage */
770                 drm_mode_crtc_set_gamma_size(drm_crtc, 256);
771         }
772
773         return 0;
774 }
775
776 /*
777  * Encoder functions
778  */
779
780 static void nv50_kms_encoder_destroy(struct drm_encoder *drm_encoder)
781 {
782         struct nv50_output *output = to_nv50_output(drm_encoder);
783
784         drm_encoder_cleanup(drm_encoder);
785
786         /* this will even destroy the public structure. */
787         output->destroy(output);
788 }
789
790 static const struct drm_encoder_funcs nv50_kms_encoder_funcs = {
791         .destroy = nv50_kms_encoder_destroy,
792 };
793
794 static int nv50_kms_encoders_init(struct drm_device *dev)
795 {
796         struct nv50_display *display = nv50_get_display(dev);
797         struct nv50_output *output = NULL;
798
799         list_for_each_entry(output, &display->outputs, item) {
800                 struct drm_encoder *drm_encoder = to_nv50_kms_encoder(output);
801                 uint32_t type = DRM_MODE_ENCODER_NONE;
802
803                 switch (output->type) {
804                         case OUTPUT_DAC:
805                                 type = DRM_MODE_ENCODER_DAC;
806                                 break;
807                         case OUTPUT_TMDS:
808                                 type = DRM_MODE_ENCODER_TMDS;
809                                 break;
810                         case OUTPUT_LVDS:
811                                 type = DRM_MODE_ENCODER_LVDS;
812                                 break;
813                         case OUTPUT_TV:
814                                 type = DRM_MODE_ENCODER_TVDAC;
815                                 break;
816                         default:
817                                 type = DRM_MODE_ENCODER_NONE;
818                                 break;
819                 }
820
821                 if (type == DRM_MODE_ENCODER_NONE) {
822                         DRM_ERROR("DRM_MODE_ENCODER_NONE encountered\n");
823                         continue;
824                 }
825
826                 drm_encoder_init(dev, drm_encoder, &nv50_kms_encoder_funcs, type);
827
828                 /* I've never seen possible crtc's restricted. */
829                 drm_encoder->possible_crtcs = 3;
830                 drm_encoder->possible_clones = 0;
831         }
832
833         return 0;
834 }
835
836 /*
837  * Connector functions
838  */
839
840
841 /* These 2 functions wrap the connector properties that deal with multiple encoders per connector. */
842 bool nv50_kms_connector_get_digital(struct drm_connector *drm_connector)
843 {
844         struct drm_device *dev = drm_connector->dev;
845
846         switch (drm_connector->connector_type) {
847                 case DRM_MODE_CONNECTOR_VGA:
848                 case DRM_MODE_CONNECTOR_SVIDEO:
849                         return false;
850                 case DRM_MODE_CONNECTOR_DVID:
851                 case DRM_MODE_CONNECTOR_LVDS:
852                         return true;
853                 default:
854                         break;
855         }
856
857         if (drm_connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
858                 int rval;
859                 uint64_t prop_val;
860
861                 rval = drm_connector_property_get_value(drm_connector, dev->mode_config.dvi_i_select_subconnector_property, &prop_val);
862                 if (rval) {
863                         DRM_ERROR("Unable to find select subconnector property, defaulting to DVI-D\n");
864                         return true;
865                 }
866
867                 /* Is a subconnector explicitly selected? */
868                 switch (prop_val) {
869                         case DRM_MODE_SUBCONNECTOR_DVID:
870                                 return true;
871                         case DRM_MODE_SUBCONNECTOR_DVIA:
872                                 return false;
873                         default:
874                                 break;
875                 }
876
877                 rval = drm_connector_property_get_value(drm_connector, dev->mode_config.dvi_i_subconnector_property, &prop_val);
878                 if (rval) {
879                         DRM_ERROR("Unable to find subconnector property, defaulting to DVI-D\n");
880                         return true;
881                 }
882
883                 /* Do we know what subconnector we currently have connected? */
884                 switch (prop_val) {
885                         case DRM_MODE_SUBCONNECTOR_DVID:
886                                 return true;
887                         case DRM_MODE_SUBCONNECTOR_DVIA:
888                                 return false;
889                         default:
890                                 DRM_ERROR("Unknown subconnector value, defaulting to DVI-D\n");
891                                 return true;
892                 }
893         }
894
895         DRM_ERROR("Unknown connector type, defaulting to analog\n");
896         return false;
897 }
898
899 static void nv50_kms_connector_set_digital(struct drm_connector *drm_connector, int digital, bool force)
900 {
901         struct drm_device *dev = drm_connector->dev;
902
903         if (drm_connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
904                 uint64_t cur_value, new_value;
905
906                 int rval = drm_connector_property_get_value(drm_connector, dev->mode_config.dvi_i_subconnector_property, &cur_value);
907                 if (rval) {
908                         DRM_ERROR("Unable to find subconnector property\n");
909                         return;
910                 }
911
912                 /* Only set when unknown or when forced to do so. */
913                 if (cur_value != DRM_MODE_SUBCONNECTOR_Unknown && !force)
914                         return;
915
916                 if (digital == 1)
917                         new_value = DRM_MODE_SUBCONNECTOR_DVID;
918                 else if (digital == 0)
919                         new_value = DRM_MODE_SUBCONNECTOR_DVIA;
920                 else
921                         new_value = DRM_MODE_SUBCONNECTOR_Unknown;
922                 drm_connector_property_set_value(drm_connector, dev->mode_config.dvi_i_subconnector_property, new_value);
923         }
924 }
925
926 void nv50_kms_connector_detect_all(struct drm_device *dev)
927 {
928         struct drm_connector *drm_connector = NULL;
929
930         list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
931                 drm_connector->funcs->detect(drm_connector);
932         }
933 }
934
935 static enum drm_connector_status nv50_kms_connector_detect(struct drm_connector *drm_connector)
936 {
937         struct drm_device *dev = drm_connector->dev;
938         struct nv50_connector *connector = to_nv50_connector(drm_connector);
939         struct nv50_output *output = NULL;
940         int hpd_detect = 0, load_detect = 0, i2c_detect = 0;
941         int old_status = drm_connector->status;
942
943         /* hotplug detect */
944         hpd_detect = connector->hpd_detect(connector);
945
946         /* load detect */
947         output = connector->to_output(connector, false); /* analog */
948         if (output && output->detect)
949                 load_detect = output->detect(output);
950
951         if (hpd_detect < 0 || load_detect < 0) /* did an error occur? */
952                 i2c_detect = connector->i2c_detect(connector);
953
954         if (load_detect == 1) {
955                 nv50_kms_connector_set_digital(drm_connector, 0, true); /* analog, forced */
956         } else if (hpd_detect == 1 && load_detect == 0) {
957                 nv50_kms_connector_set_digital(drm_connector, 1, true); /* digital, forced */
958         } else {
959                 nv50_kms_connector_set_digital(drm_connector, -1, true); /* unknown, forced */
960         }
961
962         if (hpd_detect == 1 || load_detect == 1 || i2c_detect == 1)
963                 drm_connector->status = connector_status_connected;
964         else
965                 drm_connector->status = connector_status_disconnected;
966
967         /* update our modes whenever there is reason to */
968         if (old_status != drm_connector->status) {
969                 drm_connector->funcs->fill_modes(drm_connector, 0, 0);
970
971                 /* notify fb of changes */
972                 dev->mode_config.funcs->fb_changed(dev);
973
974                 /* sent a hotplug event when appropriate. */
975                 drm_sysfs_hotplug_event(dev);
976         }
977
978         return drm_connector->status;
979 }
980
981 static void nv50_kms_connector_destroy(struct drm_connector *drm_connector)
982 {
983         struct nv50_connector *connector = to_nv50_connector(drm_connector);
984
985         drm_sysfs_connector_remove(drm_connector);
986         drm_connector_cleanup(drm_connector);
987
988         /* this will even destroy the public structure. */
989         connector->destroy(connector);
990 }
991
992 /*
993  * Detailed mode info for a standard 640x480@60Hz monitor
994  */
995 static struct drm_display_mode std_mode[] = {
996         /*{ DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
997                  752, 800, 0, 480, 490, 492, 525, 0,
998                  DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },*/ /* 640x480@60Hz */
999         { DRM_MODE("1280x1024", DRM_MODE_TYPE_DEFAULT, 135000, 1280, 1296,
1000                    1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
1001                    DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */
1002 };
1003
1004 static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, uint32_t maxX, uint32_t maxY)
1005 {
1006         struct nv50_connector *connector = to_nv50_connector(drm_connector);
1007         struct drm_device *dev = drm_connector->dev;
1008         int rval = 0;
1009         bool connected = false;
1010         struct drm_display_mode *mode, *t;
1011         struct edid *edid = NULL;
1012
1013         NV50_DEBUG("%s\n", drm_get_connector_name(drm_connector));
1014         /* set all modes to the unverified state */
1015         list_for_each_entry_safe(mode, t, &drm_connector->modes, head)
1016                 mode->status = MODE_UNVERIFIED;
1017
1018         if (nv50_kms_connector_detect(drm_connector) == connector_status_connected)
1019                 connected = true;
1020
1021         if (connected)
1022                 NV50_DEBUG("%s is connected\n", drm_get_connector_name(drm_connector));
1023         else
1024                 NV50_DEBUG("%s is disconnected\n", drm_get_connector_name(drm_connector));
1025
1026         /* Not all connnectors have an i2c channel. */
1027         if (connected && connector->i2c_chan)
1028                 edid = (struct edid *) drm_do_probe_ddc_edid(&connector->i2c_chan->adapter);
1029
1030         /* This will remove edid if needed. */
1031         drm_mode_connector_update_edid_property(drm_connector, edid);
1032
1033         if (edid) {
1034                 rval = drm_add_edid_modes(drm_connector, edid);
1035
1036                 /* Only update when relevant and when detect couldn't determine type. */
1037                 nv50_kms_connector_set_digital(drm_connector, edid->digital ? 1 : 0, false);
1038
1039                 kfree(edid);
1040         }
1041
1042         if (rval) /* number of modes  > 1 */
1043                 drm_mode_connector_list_update(drm_connector);
1044
1045         if (maxX && maxY)
1046                 drm_mode_validate_size(dev, &drm_connector->modes, maxX, maxY, 0);
1047
1048         list_for_each_entry_safe(mode, t, &drm_connector->modes, head) {
1049                 if (mode->status == MODE_OK) {
1050                         struct nouveau_hw_mode *hw_mode = nv50_kms_to_hw_mode(mode);
1051                         struct nv50_output *output = connector->to_output(connector, nv50_kms_connector_get_digital(drm_connector));
1052
1053                         mode->status = output->validate_mode(output, hw_mode);
1054                         /* find native mode, TODO: also check if we actually found one */
1055                         if (mode->status == MODE_OK) {
1056                                 if (mode->type & DRM_MODE_TYPE_PREFERRED)
1057                                         *output->native_mode = *hw_mode;
1058                         }
1059                         kfree(hw_mode);
1060                 }
1061         }
1062
1063         /* revalidate now that we have native mode */
1064         list_for_each_entry_safe(mode, t, &drm_connector->modes, head) {
1065                 if (mode->status == MODE_OK) {
1066                         struct nouveau_hw_mode *hw_mode = nv50_kms_to_hw_mode(mode);
1067                         struct nv50_output *output = connector->to_output(connector, nv50_kms_connector_get_digital(drm_connector));
1068
1069                         mode->status = output->validate_mode(output, hw_mode);
1070                         kfree(hw_mode);
1071                 }
1072         }
1073
1074         drm_mode_prune_invalid(dev, &drm_connector->modes, true);
1075
1076         /* pruning is done, so bail out. */
1077         if (!connected)
1078                 return;
1079
1080         if (list_empty(&drm_connector->modes)) {
1081                 struct drm_display_mode *stdmode;
1082                 struct nouveau_hw_mode *hw_mode;
1083                 struct nv50_output *output;
1084
1085                 NV50_DEBUG("No valid modes on %s\n", drm_get_connector_name(drm_connector));
1086
1087                 /* Making up native modes for LVDS is a bad idea. */
1088                 if (drm_connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
1089                         return;
1090
1091                 /* Should we do this here ???
1092                  * When no valid EDID modes are available we end up
1093                  * here and bailed in the past, now we add a standard
1094                  * 640x480@60Hz mode and carry on.
1095                  */
1096                 stdmode = drm_mode_duplicate(dev, &std_mode[0]);
1097                 drm_mode_probed_add(drm_connector, stdmode);
1098                 drm_mode_list_concat(&drm_connector->probed_modes,
1099                                      &drm_connector->modes);
1100
1101                 /* also add it as native mode */
1102                 hw_mode = nv50_kms_to_hw_mode(mode);
1103                 output = connector->to_output(connector, nv50_kms_connector_get_digital(drm_connector));
1104
1105                 if (hw_mode)
1106                         *output->native_mode = *hw_mode;
1107
1108                 DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
1109                           drm_get_connector_name(drm_connector));
1110         }
1111
1112         drm_mode_sort(&drm_connector->modes);
1113
1114         NV50_DEBUG("Probed modes for %s\n", drm_get_connector_name(drm_connector));
1115
1116         list_for_each_entry_safe(mode, t, &drm_connector->modes, head) {
1117                 mode->vrefresh = drm_mode_vrefresh(mode);
1118
1119                 /* is this needed, as it's unused by the driver? */
1120                 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1121                 drm_mode_debug_printmodeline(mode);
1122         }
1123 }
1124
1125 static int nv50_kms_connector_set_property(struct drm_connector *drm_connector,
1126                                         struct drm_property *property,
1127                                         uint64_t value)
1128 {
1129         struct drm_device *dev = drm_connector->dev;
1130         struct nv50_connector *connector = to_nv50_connector(drm_connector);
1131         int rval = 0;
1132         bool delay_change = false;
1133
1134         /* DPMS */
1135         if (property == dev->mode_config.dpms_property && drm_connector->encoder) {
1136                 struct nv50_output *output = to_nv50_output(drm_connector->encoder);
1137
1138                 rval = output->set_power_mode(output, (int) value);
1139
1140                 return rval;
1141         }
1142
1143         /* Scaling mode */
1144         if (property == dev->mode_config.scaling_mode_property) {
1145                 struct nv50_crtc *crtc = NULL;
1146                 struct nv50_display *display = nv50_get_display(dev);
1147                 int internal_value = 0;
1148
1149                 switch (value) {
1150                         case DRM_MODE_SCALE_NON_GPU:
1151                                 internal_value = SCALE_NON_GPU;
1152                                 break;
1153                         case DRM_MODE_SCALE_FULLSCREEN:
1154                                 internal_value = SCALE_FULLSCREEN;
1155                                 break;
1156                         case DRM_MODE_SCALE_NO_SCALE:
1157                                 internal_value = SCALE_NOSCALE;
1158                                 break;
1159                         case DRM_MODE_SCALE_ASPECT:
1160                                 internal_value = SCALE_ASPECT;
1161                                 break;
1162                         default:
1163                                 break;
1164                 }
1165
1166                 /* LVDS always needs gpu scaling */
1167                 if (connector->type == CONNECTOR_LVDS && internal_value == SCALE_NON_GPU)
1168                         return -EINVAL;
1169
1170                 connector->requested_scaling_mode = internal_value;
1171
1172                 if (drm_connector->encoder && drm_connector->encoder->crtc)
1173                         crtc = to_nv50_crtc(drm_connector->encoder->crtc);
1174
1175                 if (!crtc)
1176                         return 0;
1177
1178                 crtc->requested_scaling_mode = connector->requested_scaling_mode;
1179
1180                 /* going from and to a gpu scaled regime requires a modesetting, so wait until next modeset */
1181                 if (crtc->scaling_mode == SCALE_NON_GPU || internal_value == SCALE_NON_GPU) {
1182                         DRM_INFO("Moving from or to a non-gpu scaled mode, this will be processed upon next modeset.");
1183                         delay_change = true;
1184                 }
1185
1186                 if (delay_change)
1187                         return 0;
1188
1189                 rval = crtc->set_scale(crtc);
1190                 if (rval)
1191                         return rval;
1192
1193                 /* process command buffer */
1194                 display->update(display);
1195
1196                 return 0;
1197         }
1198
1199         /* Dithering */
1200         if (property == dev->mode_config.dithering_mode_property) {
1201                 struct nv50_crtc *crtc = NULL;
1202                 struct nv50_display *display = nv50_get_display(dev);
1203
1204                 if (value == DRM_MODE_DITHERING_ON)
1205                         connector->use_dithering = true;
1206                 else
1207                         connector->use_dithering = false;
1208
1209                 if (drm_connector->encoder && drm_connector->encoder->crtc)
1210                         crtc = to_nv50_crtc(drm_connector->encoder->crtc);
1211
1212                 if (!crtc)
1213                         return 0;
1214
1215                 /* update hw state */
1216                 crtc->use_dithering = connector->use_dithering;
1217                 rval = crtc->set_dither(crtc);
1218                 if (rval)
1219                         return rval;
1220
1221                 /* process command buffer */
1222                 display->update(display);
1223
1224                 return 0;
1225         }
1226
1227         return -EINVAL;
1228 }
1229
1230 static const struct drm_connector_funcs nv50_kms_connector_funcs = {
1231         .save = NULL,
1232         .restore = NULL,
1233         .detect = nv50_kms_connector_detect,
1234         .destroy = nv50_kms_connector_destroy,
1235         .fill_modes = nv50_kms_connector_fill_modes,
1236         .set_property = nv50_kms_connector_set_property
1237 };
1238
1239 static int nv50_kms_get_scaling_mode(struct drm_connector *drm_connector)
1240 {
1241         struct nv50_connector *connector = NULL;
1242         int drm_mode = 0;
1243
1244         if (!drm_connector) {
1245                 DRM_ERROR("drm_connector is NULL\n");
1246                 return 0;
1247         }
1248
1249         connector = to_nv50_connector(drm_connector);
1250
1251         switch (connector->requested_scaling_mode) {
1252                 case SCALE_NON_GPU:
1253                         drm_mode = DRM_MODE_SCALE_NON_GPU;
1254                         break;
1255                 case SCALE_FULLSCREEN:
1256                         drm_mode = DRM_MODE_SCALE_FULLSCREEN;
1257                         break;
1258                 case SCALE_NOSCALE:
1259                         drm_mode = DRM_MODE_SCALE_NO_SCALE;
1260                         break;
1261                 case SCALE_ASPECT:
1262                         drm_mode = DRM_MODE_SCALE_ASPECT;
1263                         break;
1264                 default:
1265                         break;
1266         }
1267
1268         return drm_mode;
1269 }
1270
1271 static int nv50_kms_connectors_init(struct drm_device *dev)
1272 {
1273         struct nv50_display *display = nv50_get_display(dev);
1274         struct nv50_connector *connector = NULL;
1275         int i;
1276
1277         /* Initialise some optional connector properties. */
1278         drm_mode_create_scaling_mode_property(dev);
1279         drm_mode_create_dithering_property(dev);
1280
1281         list_for_each_entry(connector, &display->connectors, item) {
1282                 struct drm_connector *drm_connector = to_nv50_kms_connector(connector);
1283                 uint32_t type = DRM_MODE_CONNECTOR_Unknown;
1284
1285                 switch (connector->type) {
1286                         case CONNECTOR_VGA:
1287                                 type = DRM_MODE_CONNECTOR_VGA;
1288                                 break;
1289                         case CONNECTOR_DVI_D:
1290                                 type = DRM_MODE_CONNECTOR_DVID;
1291                                 break;
1292                         case CONNECTOR_DVI_I:
1293                                 type = DRM_MODE_CONNECTOR_DVII;
1294                                 break;
1295                         case CONNECTOR_LVDS:
1296                                 type = DRM_MODE_CONNECTOR_LVDS;
1297                                 break;
1298                         case CONNECTOR_TV:
1299                                 type = DRM_MODE_CONNECTOR_SVIDEO;
1300                                 break;
1301                         default:
1302                                 type = DRM_MODE_CONNECTOR_Unknown;
1303                                 break;
1304                 }
1305
1306                 if (type == DRM_MODE_CONNECTOR_Unknown) {
1307                         DRM_ERROR("DRM_MODE_CONNECTOR_Unknown encountered\n");
1308                         continue;
1309                 }
1310
1311                 /* It should be allowed sometimes, but let's be safe for the moment. */
1312                 drm_connector->interlace_allowed = false;
1313                 drm_connector->doublescan_allowed = false;
1314
1315                 drm_connector_init(dev, drm_connector, &nv50_kms_connector_funcs, type);
1316
1317                 /* Init DVI-I specific properties */
1318                 if (type == DRM_MODE_CONNECTOR_DVII) {
1319                         drm_mode_create_dvi_i_properties(dev);
1320                         drm_connector_attach_property(drm_connector, dev->mode_config.dvi_i_subconnector_property, 0);
1321                         drm_connector_attach_property(drm_connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
1322                 }
1323
1324                 /* If supported in the future, it will have to use the scalers internally and not expose them. */
1325                 if (type != DRM_MODE_CONNECTOR_SVIDEO) {
1326                         drm_connector_attach_property(drm_connector, dev->mode_config.scaling_mode_property, nv50_kms_get_scaling_mode(drm_connector));
1327                 }
1328
1329                 drm_connector_attach_property(drm_connector, dev->mode_config.dithering_mode_property, connector->use_dithering ? DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
1330
1331                 /* attach encoders, possibilities are analog + digital */
1332                 for (i = 0; i < 2; i++) {
1333                         struct drm_encoder *drm_encoder = NULL;
1334                         struct nv50_output *output = connector->to_output(connector, i);
1335                         if (!output)
1336                                 continue;
1337
1338                         drm_encoder = to_nv50_kms_encoder(output);
1339                         if (!drm_encoder) {
1340                                 DRM_ERROR("No struct drm_connector to match struct nv50_output\n");
1341                                 continue;
1342                         }
1343
1344                         drm_mode_connector_attach_encoder(drm_connector, drm_encoder);
1345                 }
1346
1347                 drm_sysfs_connector_add(drm_connector);
1348         }
1349
1350         return 0;
1351 }
1352
1353 /*
1354  * Main functions
1355  */
1356
1357 int nv50_kms_init(struct drm_device *dev)
1358 {
1359         struct drm_nouveau_private *dev_priv = dev->dev_private;
1360         struct nv50_kms_priv *kms_priv = kzalloc(sizeof(struct nv50_kms_priv), GFP_KERNEL);
1361         struct nv50_display *display = NULL;
1362         int rval = 0;
1363
1364         if (!kms_priv)
1365                 return -ENOMEM;
1366
1367         dev_priv->kms_priv = kms_priv;
1368
1369         /* function pointers */
1370         /* an allocation interface that deals with the outside world, without polluting the core. */
1371         dev_priv->alloc_crtc = nv50_kms_alloc_crtc;
1372         dev_priv->alloc_output = nv50_kms_alloc_output;
1373         dev_priv->alloc_connector = nv50_kms_alloc_connector;
1374
1375         dev_priv->free_crtc = nv50_kms_free_crtc;
1376         dev_priv->free_output = nv50_kms_free_output;
1377         dev_priv->free_connector = nv50_kms_free_connector;
1378
1379         /* bios is needed for tables. */
1380         rval = nouveau_parse_bios(dev);
1381         if (rval != 0)
1382                 goto out;
1383
1384         /* init basic kernel modesetting */
1385         drm_mode_config_init(dev);
1386
1387         dev->mode_config.min_width = 0;
1388         dev->mode_config.min_height = 0;
1389
1390         dev->mode_config.funcs = (void *)&nv50_kms_mode_funcs;
1391
1392         dev->mode_config.max_width = 8192;
1393         dev->mode_config.max_height = 8192;
1394
1395         dev->mode_config.fb_base = dev_priv->fb_phys;
1396
1397         /* init kms lists */
1398         INIT_LIST_HEAD(&kms_priv->crtcs);
1399         INIT_LIST_HEAD(&kms_priv->encoders);
1400         INIT_LIST_HEAD(&kms_priv->connectors);
1401
1402         /* init the internal core, must be done first. */
1403         rval = nv50_display_create(dev);
1404         if (rval != 0)
1405                 goto out;
1406
1407         display = nv50_get_display(dev);
1408         if (!display) {
1409                 rval = -EINVAL;
1410                 goto out;
1411         }
1412
1413         /* pre-init now */
1414         rval = display->pre_init(display);
1415         if (rval != 0)
1416                 goto out;
1417
1418         /* init external layer */
1419         rval = nv50_kms_crtcs_init(dev);
1420         if (rval != 0)
1421                 goto out;
1422
1423         rval = nv50_kms_encoders_init(dev);
1424         if (rval != 0)
1425                 goto out;
1426
1427         rval = nv50_kms_connectors_init(dev);
1428         if (rval != 0)
1429                 goto out;
1430
1431         /* init now, this'll kill the textmode */
1432         rval = display->init(display);
1433         if (rval != 0)
1434                 goto out;
1435
1436         /* process cmdbuffer */
1437         display->update(display);
1438
1439         return 0;
1440
1441 out:
1442         kfree(kms_priv);
1443         dev_priv->kms_priv = NULL;
1444
1445         return rval;
1446 }
1447
1448 int nv50_kms_destroy(struct drm_device *dev)
1449 {
1450         drm_mode_config_cleanup(dev);
1451
1452         return 0;
1453 }
1454