interconnect: qcom: icc-rpm: Fix peak rate calculation
[linux-2.6-microblaze.git] / drivers / gpu / drm / ast / ast_mode.c
1 /*
2  * Copyright 2012 Red Hat Inc.
3  * Parts based on xf86-video-ast
4  * Copyright (c) 2005 ASPEED Technology Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  */
27 /*
28  * Authors: Dave Airlie <airlied@redhat.com>
29  */
30
31 #include <linux/export.h>
32 #include <linux/pci.h>
33
34 #include <drm/drm_atomic.h>
35 #include <drm/drm_atomic_helper.h>
36 #include <drm/drm_atomic_state_helper.h>
37 #include <drm/drm_crtc.h>
38 #include <drm/drm_damage_helper.h>
39 #include <drm/drm_edid.h>
40 #include <drm/drm_format_helper.h>
41 #include <drm/drm_fourcc.h>
42 #include <drm/drm_gem_atomic_helper.h>
43 #include <drm/drm_gem_framebuffer_helper.h>
44 #include <drm/drm_gem_shmem_helper.h>
45 #include <drm/drm_managed.h>
46 #include <drm/drm_probe_helper.h>
47 #include <drm/drm_simple_kms_helper.h>
48
49 #include "ast_drv.h"
50 #include "ast_tables.h"
51
52 #define AST_LUT_SIZE 256
53
54 static inline void ast_load_palette_index(struct ast_device *ast,
55                                      u8 index, u8 red, u8 green,
56                                      u8 blue)
57 {
58         ast_io_write8(ast, AST_IO_VGADWR, index);
59         ast_io_read8(ast, AST_IO_VGASRI);
60         ast_io_write8(ast, AST_IO_VGAPDR, red);
61         ast_io_read8(ast, AST_IO_VGASRI);
62         ast_io_write8(ast, AST_IO_VGAPDR, green);
63         ast_io_read8(ast, AST_IO_VGASRI);
64         ast_io_write8(ast, AST_IO_VGAPDR, blue);
65         ast_io_read8(ast, AST_IO_VGASRI);
66 }
67
68 static void ast_crtc_set_gamma_linear(struct ast_device *ast,
69                                       const struct drm_format_info *format)
70 {
71         int i;
72
73         switch (format->format) {
74         case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
75         case DRM_FORMAT_RGB565:
76         case DRM_FORMAT_XRGB8888:
77                 for (i = 0; i < AST_LUT_SIZE; i++)
78                         ast_load_palette_index(ast, i, i, i, i);
79                 break;
80         default:
81                 drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
82                               &format->format);
83                 break;
84         }
85 }
86
87 static void ast_crtc_set_gamma(struct ast_device *ast,
88                                const struct drm_format_info *format,
89                                struct drm_color_lut *lut)
90 {
91         int i;
92
93         switch (format->format) {
94         case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
95         case DRM_FORMAT_RGB565:
96         case DRM_FORMAT_XRGB8888:
97                 for (i = 0; i < AST_LUT_SIZE; i++)
98                         ast_load_palette_index(ast, i,
99                                                lut[i].red >> 8,
100                                                lut[i].green >> 8,
101                                                lut[i].blue >> 8);
102                 break;
103         default:
104                 drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
105                               &format->format);
106                 break;
107         }
108 }
109
110 static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
111                                     const struct drm_display_mode *mode,
112                                     struct drm_display_mode *adjusted_mode,
113                                     struct ast_vbios_mode_info *vbios_mode)
114 {
115         u32 refresh_rate_index = 0, refresh_rate;
116         const struct ast_vbios_enhtable *best = NULL;
117         u32 hborder, vborder;
118         bool check_sync;
119
120         switch (format->cpp[0] * 8) {
121         case 8:
122                 vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
123                 break;
124         case 16:
125                 vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
126                 break;
127         case 24:
128         case 32:
129                 vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
130                 break;
131         default:
132                 return false;
133         }
134
135         switch (mode->crtc_hdisplay) {
136         case 640:
137                 vbios_mode->enh_table = &res_640x480[refresh_rate_index];
138                 break;
139         case 800:
140                 vbios_mode->enh_table = &res_800x600[refresh_rate_index];
141                 break;
142         case 1024:
143                 vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
144                 break;
145         case 1152:
146                 vbios_mode->enh_table = &res_1152x864[refresh_rate_index];
147                 break;
148         case 1280:
149                 if (mode->crtc_vdisplay == 800)
150                         vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
151                 else
152                         vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
153                 break;
154         case 1360:
155                 vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
156                 break;
157         case 1440:
158                 vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
159                 break;
160         case 1600:
161                 if (mode->crtc_vdisplay == 900)
162                         vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
163                 else
164                         vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
165                 break;
166         case 1680:
167                 vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
168                 break;
169         case 1920:
170                 if (mode->crtc_vdisplay == 1080)
171                         vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
172                 else
173                         vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
174                 break;
175         default:
176                 return false;
177         }
178
179         refresh_rate = drm_mode_vrefresh(mode);
180         check_sync = vbios_mode->enh_table->flags & WideScreenMode;
181
182         while (1) {
183                 const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
184
185                 while (loop->refresh_rate != 0xff) {
186                         if ((check_sync) &&
187                             (((mode->flags & DRM_MODE_FLAG_NVSYNC)  &&
188                               (loop->flags & PVSync))  ||
189                              ((mode->flags & DRM_MODE_FLAG_PVSYNC)  &&
190                               (loop->flags & NVSync))  ||
191                              ((mode->flags & DRM_MODE_FLAG_NHSYNC)  &&
192                               (loop->flags & PHSync))  ||
193                              ((mode->flags & DRM_MODE_FLAG_PHSYNC)  &&
194                               (loop->flags & NHSync)))) {
195                                 loop++;
196                                 continue;
197                         }
198                         if (loop->refresh_rate <= refresh_rate
199                             && (!best || loop->refresh_rate > best->refresh_rate))
200                                 best = loop;
201                         loop++;
202                 }
203                 if (best || !check_sync)
204                         break;
205                 check_sync = 0;
206         }
207
208         if (best)
209                 vbios_mode->enh_table = best;
210
211         hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
212         vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
213
214         adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht;
215         adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder;
216         adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder;
217         adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder +
218                 vbios_mode->enh_table->hfp;
219         adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder +
220                                          vbios_mode->enh_table->hfp +
221                                          vbios_mode->enh_table->hsync);
222
223         adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt;
224         adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder;
225         adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder;
226         adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder +
227                 vbios_mode->enh_table->vfp;
228         adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder +
229                                          vbios_mode->enh_table->vfp +
230                                          vbios_mode->enh_table->vsync);
231
232         return true;
233 }
234
235 static void ast_set_vbios_color_reg(struct ast_device *ast,
236                                     const struct drm_format_info *format,
237                                     const struct ast_vbios_mode_info *vbios_mode)
238 {
239         u32 color_index;
240
241         switch (format->cpp[0]) {
242         case 1:
243                 color_index = VGAModeIndex - 1;
244                 break;
245         case 2:
246                 color_index = HiCModeIndex;
247                 break;
248         case 3:
249         case 4:
250                 color_index = TrueCModeIndex;
251                 break;
252         default:
253                 return;
254         }
255
256         ast_set_index_reg(ast, AST_IO_VGACRI, 0x8c, (u8)((color_index & 0x0f) << 4));
257
258         ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00);
259
260         if (vbios_mode->enh_table->flags & NewModeInfo) {
261                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8);
262                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x92, format->cpp[0] * 8);
263         }
264 }
265
266 static void ast_set_vbios_mode_reg(struct ast_device *ast,
267                                    const struct drm_display_mode *adjusted_mode,
268                                    const struct ast_vbios_mode_info *vbios_mode)
269 {
270         u32 refresh_rate_index, mode_id;
271
272         refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
273         mode_id = vbios_mode->enh_table->mode_id;
274
275         ast_set_index_reg(ast, AST_IO_VGACRI, 0x8d, refresh_rate_index & 0xff);
276         ast_set_index_reg(ast, AST_IO_VGACRI, 0x8e, mode_id & 0xff);
277
278         ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0x00);
279
280         if (vbios_mode->enh_table->flags & NewModeInfo) {
281                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x91, 0xa8);
282                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x93, adjusted_mode->clock / 1000);
283                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x94, adjusted_mode->crtc_hdisplay);
284                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x95, adjusted_mode->crtc_hdisplay >> 8);
285                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x96, adjusted_mode->crtc_vdisplay);
286                 ast_set_index_reg(ast, AST_IO_VGACRI, 0x97, adjusted_mode->crtc_vdisplay >> 8);
287         }
288 }
289
290 static void ast_set_std_reg(struct ast_device *ast,
291                             struct drm_display_mode *mode,
292                             struct ast_vbios_mode_info *vbios_mode)
293 {
294         const struct ast_vbios_stdtable *stdtable;
295         u32 i;
296         u8 jreg;
297
298         stdtable = vbios_mode->std_table;
299
300         jreg = stdtable->misc;
301         ast_io_write8(ast, AST_IO_VGAMR_W, jreg);
302
303         /* Set SEQ; except Screen Disable field */
304         ast_set_index_reg(ast, AST_IO_VGASRI, 0x00, 0x03);
305         ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x01, 0xdf, stdtable->seq[0]);
306         for (i = 1; i < 4; i++) {
307                 jreg = stdtable->seq[i];
308                 ast_set_index_reg(ast, AST_IO_VGASRI, (i + 1), jreg);
309         }
310
311         /* Set CRTC; except base address and offset */
312         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x00);
313         for (i = 0; i < 12; i++)
314                 ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]);
315         for (i = 14; i < 19; i++)
316                 ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]);
317         for (i = 20; i < 25; i++)
318                 ast_set_index_reg(ast, AST_IO_VGACRI, i, stdtable->crtc[i]);
319
320         /* set AR */
321         jreg = ast_io_read8(ast, AST_IO_VGAIR1_R);
322         for (i = 0; i < 20; i++) {
323                 jreg = stdtable->ar[i];
324                 ast_io_write8(ast, AST_IO_VGAARI_W, (u8)i);
325                 ast_io_write8(ast, AST_IO_VGAARI_W, jreg);
326         }
327         ast_io_write8(ast, AST_IO_VGAARI_W, 0x14);
328         ast_io_write8(ast, AST_IO_VGAARI_W, 0x00);
329
330         jreg = ast_io_read8(ast, AST_IO_VGAIR1_R);
331         ast_io_write8(ast, AST_IO_VGAARI_W, 0x20);
332
333         /* Set GR */
334         for (i = 0; i < 9; i++)
335                 ast_set_index_reg(ast, AST_IO_VGAGRI, i, stdtable->gr[i]);
336 }
337
338 static void ast_set_crtc_reg(struct ast_device *ast,
339                              struct drm_display_mode *mode,
340                              struct ast_vbios_mode_info *vbios_mode)
341 {
342         u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0;
343         u16 temp, precache = 0;
344
345         if ((IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) &&
346             (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
347                 precache = 40;
348
349         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x00);
350
351         temp = (mode->crtc_htotal >> 3) - 5;
352         if (temp & 0x100)
353                 jregAC |= 0x01; /* HT D[8] */
354         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x00, 0x00, temp);
355
356         temp = (mode->crtc_hdisplay >> 3) - 1;
357         if (temp & 0x100)
358                 jregAC |= 0x04; /* HDE D[8] */
359         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x01, 0x00, temp);
360
361         temp = (mode->crtc_hblank_start >> 3) - 1;
362         if (temp & 0x100)
363                 jregAC |= 0x10; /* HBS D[8] */
364         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x02, 0x00, temp);
365
366         temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f;
367         if (temp & 0x20)
368                 jreg05 |= 0x80;  /* HBE D[5] */
369         if (temp & 0x40)
370                 jregAD |= 0x01;  /* HBE D[5] */
371         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x03, 0xE0, (temp & 0x1f));
372
373         temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
374         if (temp & 0x100)
375                 jregAC |= 0x40; /* HRS D[5] */
376         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x04, 0x00, temp);
377
378         temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
379         if (temp & 0x20)
380                 jregAD |= 0x04; /* HRE D[5] */
381         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
382
383         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAC, 0x00, jregAC);
384         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAD, 0x00, jregAD);
385
386         // Workaround for HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels);
387         if (IS_AST_GEN7(ast) && (mode->crtc_vdisplay == 1080))
388                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xFC, 0xFD, 0x02);
389         else
390                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xFC, 0xFD, 0x00);
391
392         /* vert timings */
393         temp = (mode->crtc_vtotal) - 2;
394         if (temp & 0x100)
395                 jreg07 |= 0x01;
396         if (temp & 0x200)
397                 jreg07 |= 0x20;
398         if (temp & 0x400)
399                 jregAE |= 0x01;
400         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x06, 0x00, temp);
401
402         temp = (mode->crtc_vsync_start) - 1;
403         if (temp & 0x100)
404                 jreg07 |= 0x04;
405         if (temp & 0x200)
406                 jreg07 |= 0x80;
407         if (temp & 0x400)
408                 jregAE |= 0x08;
409         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x10, 0x00, temp);
410
411         temp = (mode->crtc_vsync_end - 1) & 0x3f;
412         if (temp & 0x10)
413                 jregAE |= 0x20;
414         if (temp & 0x20)
415                 jregAE |= 0x40;
416         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x70, temp & 0xf);
417
418         temp = mode->crtc_vdisplay - 1;
419         if (temp & 0x100)
420                 jreg07 |= 0x02;
421         if (temp & 0x200)
422                 jreg07 |= 0x40;
423         if (temp & 0x400)
424                 jregAE |= 0x02;
425         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x12, 0x00, temp);
426
427         temp = mode->crtc_vblank_start - 1;
428         if (temp & 0x100)
429                 jreg07 |= 0x08;
430         if (temp & 0x200)
431                 jreg09 |= 0x20;
432         if (temp & 0x400)
433                 jregAE |= 0x04;
434         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x15, 0x00, temp);
435
436         temp = mode->crtc_vblank_end - 1;
437         if (temp & 0x100)
438                 jregAE |= 0x10;
439         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x16, 0x00, temp);
440
441         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x07, 0x00, jreg07);
442         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x09, 0xdf, jreg09);
443         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xAE, 0x00, (jregAE | 0x80));
444
445         if (precache)
446                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0x3f, 0x80);
447         else
448                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0x3f, 0x00);
449
450         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0x11, 0x7f, 0x80);
451 }
452
453 static void ast_set_offset_reg(struct ast_device *ast,
454                                struct drm_framebuffer *fb)
455 {
456         u16 offset;
457
458         offset = fb->pitches[0] >> 3;
459         ast_set_index_reg(ast, AST_IO_VGACRI, 0x13, (offset & 0xff));
460         ast_set_index_reg(ast, AST_IO_VGACRI, 0xb0, (offset >> 8) & 0x3f);
461 }
462
463 static void ast_set_dclk_reg(struct ast_device *ast,
464                              struct drm_display_mode *mode,
465                              struct ast_vbios_mode_info *vbios_mode)
466 {
467         const struct ast_vbios_dclk_info *clk_info;
468
469         if (IS_AST_GEN6(ast) || IS_AST_GEN7(ast))
470                 clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
471         else
472                 clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
473
474         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc0, 0x00, clk_info->param1);
475         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xc1, 0x00, clk_info->param2);
476         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xbb, 0x0f,
477                                (clk_info->param3 & 0xc0) |
478                                ((clk_info->param3 & 0x3) << 4));
479 }
480
481 static void ast_set_color_reg(struct ast_device *ast,
482                               const struct drm_format_info *format)
483 {
484         u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
485
486         switch (format->cpp[0] * 8) {
487         case 8:
488                 jregA0 = 0x70;
489                 jregA3 = 0x01;
490                 jregA8 = 0x00;
491                 break;
492         case 15:
493         case 16:
494                 jregA0 = 0x70;
495                 jregA3 = 0x04;
496                 jregA8 = 0x02;
497                 break;
498         case 32:
499                 jregA0 = 0x70;
500                 jregA3 = 0x08;
501                 jregA8 = 0x02;
502                 break;
503         }
504
505         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa0, 0x8f, jregA0);
506         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa3, 0xf0, jregA3);
507         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xa8, 0xfd, jregA8);
508 }
509
510 static void ast_set_crtthd_reg(struct ast_device *ast)
511 {
512         /* Set Threshold */
513         if (IS_AST_GEN7(ast)) {
514                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0xe0);
515                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0xa0);
516         } else if (IS_AST_GEN6(ast) || IS_AST_GEN5(ast) || IS_AST_GEN4(ast)) {
517                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x78);
518                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x60);
519         } else if (IS_AST_GEN3(ast) || IS_AST_GEN2(ast)) {
520                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x3f);
521                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x2f);
522         } else {
523                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa7, 0x2f);
524                 ast_set_index_reg(ast, AST_IO_VGACRI, 0xa6, 0x1f);
525         }
526 }
527
528 static void ast_set_sync_reg(struct ast_device *ast,
529                              struct drm_display_mode *mode,
530                              struct ast_vbios_mode_info *vbios_mode)
531 {
532         u8 jreg;
533
534         jreg  = ast_io_read8(ast, AST_IO_VGAMR_R);
535         jreg &= ~0xC0;
536         if (vbios_mode->enh_table->flags & NVSync)
537                 jreg |= 0x80;
538         if (vbios_mode->enh_table->flags & NHSync)
539                 jreg |= 0x40;
540         ast_io_write8(ast, AST_IO_VGAMR_W, jreg);
541 }
542
543 static void ast_set_start_address_crt1(struct ast_device *ast,
544                                        unsigned int offset)
545 {
546         u32 addr;
547
548         addr = offset >> 2;
549         ast_set_index_reg(ast, AST_IO_VGACRI, 0x0d, (u8)(addr & 0xff));
550         ast_set_index_reg(ast, AST_IO_VGACRI, 0x0c, (u8)((addr >> 8) & 0xff));
551         ast_set_index_reg(ast, AST_IO_VGACRI, 0xaf, (u8)((addr >> 16) & 0xff));
552
553 }
554
555 static void ast_wait_for_vretrace(struct ast_device *ast)
556 {
557         unsigned long timeout = jiffies + HZ;
558         u8 vgair1;
559
560         do {
561                 vgair1 = ast_io_read8(ast, AST_IO_VGAIR1_R);
562         } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
563 }
564
565 /*
566  * Planes
567  */
568
569 static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
570                           void __iomem *vaddr, u64 offset, unsigned long size,
571                           uint32_t possible_crtcs,
572                           const struct drm_plane_funcs *funcs,
573                           const uint32_t *formats, unsigned int format_count,
574                           const uint64_t *format_modifiers,
575                           enum drm_plane_type type)
576 {
577         struct drm_plane *plane = &ast_plane->base;
578
579         ast_plane->vaddr = vaddr;
580         ast_plane->offset = offset;
581         ast_plane->size = size;
582
583         return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
584                                         formats, format_count, format_modifiers,
585                                         type, NULL);
586 }
587
588 /*
589  * Primary plane
590  */
591
592 static const uint32_t ast_primary_plane_formats[] = {
593         DRM_FORMAT_XRGB8888,
594         DRM_FORMAT_RGB565,
595         DRM_FORMAT_C8,
596 };
597
598 static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
599                                                  struct drm_atomic_state *state)
600 {
601         struct drm_device *dev = plane->dev;
602         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
603         struct drm_crtc_state *new_crtc_state = NULL;
604         struct ast_crtc_state *new_ast_crtc_state;
605         int ret;
606
607         if (new_plane_state->crtc)
608                 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
609
610         ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
611                                                   DRM_PLANE_NO_SCALING,
612                                                   DRM_PLANE_NO_SCALING,
613                                                   false, true);
614         if (ret) {
615                 return ret;
616         } else if (!new_plane_state->visible) {
617                 if (drm_WARN_ON(dev, new_plane_state->crtc)) /* cannot legally happen */
618                         return -EINVAL;
619                 else
620                         return 0;
621         }
622
623         new_ast_crtc_state = to_ast_crtc_state(new_crtc_state);
624
625         new_ast_crtc_state->format = new_plane_state->fb->format;
626
627         return 0;
628 }
629
630 static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
631                               struct drm_framebuffer *fb,
632                               const struct drm_rect *clip)
633 {
634         struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(ast_plane->vaddr);
635
636         iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
637         drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
638 }
639
640 static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
641                                                    struct drm_atomic_state *state)
642 {
643         struct drm_device *dev = plane->dev;
644         struct ast_device *ast = to_ast_device(dev);
645         struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
646         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
647         struct drm_framebuffer *fb = plane_state->fb;
648         struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
649         struct drm_framebuffer *old_fb = old_plane_state->fb;
650         struct ast_plane *ast_plane = to_ast_plane(plane);
651         struct drm_rect damage;
652         struct drm_atomic_helper_damage_iter iter;
653
654         if (!old_fb || (fb->format != old_fb->format)) {
655                 struct drm_crtc *crtc = plane_state->crtc;
656                 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
657                 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
658                 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
659
660                 ast_set_color_reg(ast, fb->format);
661                 ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
662         }
663
664         drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
665         drm_atomic_for_each_plane_damage(&iter, &damage) {
666                 ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
667         }
668
669         /*
670          * Some BMCs stop scanning out the video signal after the driver
671          * reprogrammed the offset. This stalls display output for several
672          * seconds and makes the display unusable. Therefore only update
673          * the offset if it changes.
674          */
675         if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
676                 ast_set_offset_reg(ast, fb);
677 }
678
679 static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane,
680                                                    struct drm_atomic_state *state)
681 {
682         struct ast_device *ast = to_ast_device(plane->dev);
683         struct ast_plane *ast_plane = to_ast_plane(plane);
684
685         /*
686          * Some BMCs stop scanning out the video signal after the driver
687          * reprogrammed the scanout address. This stalls display
688          * output for several seconds and makes the display unusable.
689          * Therefore only reprogram the address after enabling the plane.
690          */
691         ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
692         ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x00);
693 }
694
695 static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
696                                                     struct drm_atomic_state *state)
697 {
698         struct ast_device *ast = to_ast_device(plane->dev);
699
700         ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20);
701 }
702
703 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
704         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
705         .atomic_check = ast_primary_plane_helper_atomic_check,
706         .atomic_update = ast_primary_plane_helper_atomic_update,
707         .atomic_enable = ast_primary_plane_helper_atomic_enable,
708         .atomic_disable = ast_primary_plane_helper_atomic_disable,
709 };
710
711 static const struct drm_plane_funcs ast_primary_plane_funcs = {
712         .update_plane = drm_atomic_helper_update_plane,
713         .disable_plane = drm_atomic_helper_disable_plane,
714         .destroy = drm_plane_cleanup,
715         DRM_GEM_SHADOW_PLANE_FUNCS,
716 };
717
718 static int ast_primary_plane_init(struct ast_device *ast)
719 {
720         struct drm_device *dev = &ast->base;
721         struct ast_plane *ast_primary_plane = &ast->primary_plane;
722         struct drm_plane *primary_plane = &ast_primary_plane->base;
723         void __iomem *vaddr = ast->vram;
724         u64 offset = 0; /* with shmem, the primary plane is always at offset 0 */
725         unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
726         unsigned long size = ast->vram_fb_available - cursor_size;
727         int ret;
728
729         ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size,
730                              0x01, &ast_primary_plane_funcs,
731                              ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats),
732                              NULL, DRM_PLANE_TYPE_PRIMARY);
733         if (ret) {
734                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
735                 return ret;
736         }
737         drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);
738         drm_plane_enable_fb_damage_clips(primary_plane);
739
740         return 0;
741 }
742
743 /*
744  * Cursor plane
745  */
746
747 static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height)
748 {
749         union {
750                 u32 ul;
751                 u8 b[4];
752         } srcdata32[2], data32;
753         union {
754                 u16 us;
755                 u8 b[2];
756         } data16;
757         u32 csum = 0;
758         s32 alpha_dst_delta, last_alpha_dst_delta;
759         u8 __iomem *dstxor;
760         const u8 *srcxor;
761         int i, j;
762         u32 per_pixel_copy, two_pixel_copy;
763
764         alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
765         last_alpha_dst_delta = alpha_dst_delta - (width << 1);
766
767         srcxor = src;
768         dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
769         per_pixel_copy = width & 1;
770         two_pixel_copy = width >> 1;
771
772         for (j = 0; j < height; j++) {
773                 for (i = 0; i < two_pixel_copy; i++) {
774                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
775                         srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
776                         data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
777                         data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
778                         data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
779                         data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
780
781                         writel(data32.ul, dstxor);
782                         csum += data32.ul;
783
784                         dstxor += 4;
785                         srcxor += 8;
786
787                 }
788
789                 for (i = 0; i < per_pixel_copy; i++) {
790                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
791                         data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
792                         data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
793                         writew(data16.us, dstxor);
794                         csum += (u32)data16.us;
795
796                         dstxor += 2;
797                         srcxor += 4;
798                 }
799                 dstxor += last_alpha_dst_delta;
800         }
801
802         /* write checksum + signature */
803         dst += AST_HWC_SIZE;
804         writel(csum, dst);
805         writel(width, dst + AST_HWC_SIGNATURE_SizeX);
806         writel(height, dst + AST_HWC_SIGNATURE_SizeY);
807         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
808         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
809 }
810
811 static void ast_set_cursor_base(struct ast_device *ast, u64 address)
812 {
813         u8 addr0 = (address >> 3) & 0xff;
814         u8 addr1 = (address >> 11) & 0xff;
815         u8 addr2 = (address >> 19) & 0xff;
816
817         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0);
818         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1);
819         ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2);
820 }
821
822 static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y,
823                                     u8 x_offset, u8 y_offset)
824 {
825         u8 x0 = (x & 0x00ff);
826         u8 x1 = (x & 0x0f00) >> 8;
827         u8 y0 = (y & 0x00ff);
828         u8 y1 = (y & 0x0700) >> 8;
829
830         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset);
831         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset);
832         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0);
833         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1);
834         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0);
835         ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1);
836 }
837
838 static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled)
839 {
840         static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
841                                      AST_IO_VGACRCB_HWC_ENABLED);
842
843         u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP;
844
845         if (enabled)
846                 vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED;
847
848         ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb);
849 }
850
851 static const uint32_t ast_cursor_plane_formats[] = {
852         DRM_FORMAT_ARGB8888,
853 };
854
855 static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
856                                                 struct drm_atomic_state *state)
857 {
858         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
859         struct drm_framebuffer *new_fb = new_plane_state->fb;
860         struct drm_crtc_state *new_crtc_state = NULL;
861         int ret;
862
863         if (new_plane_state->crtc)
864                 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
865
866         ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
867                                                   DRM_PLANE_NO_SCALING,
868                                                   DRM_PLANE_NO_SCALING,
869                                                   true, true);
870         if (ret || !new_plane_state->visible)
871                 return ret;
872
873         if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
874                 return -EINVAL;
875
876         return 0;
877 }
878
879 static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
880                                                   struct drm_atomic_state *state)
881 {
882         struct ast_plane *ast_plane = to_ast_plane(plane);
883         struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
884         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
885         struct drm_framebuffer *fb = plane_state->fb;
886         struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
887         struct ast_device *ast = to_ast_device(plane->dev);
888         struct iosys_map src_map = shadow_plane_state->data[0];
889         struct drm_rect damage;
890         const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
891         u64 dst_off = ast_plane->offset;
892         u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
893         u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
894         unsigned int offset_x, offset_y;
895         u16 x, y;
896         u8 x_offset, y_offset;
897
898         /*
899          * Do data transfer to hardware buffer and point the scanout
900          * engine to the offset.
901          */
902
903         if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
904                 ast_update_cursor_image(dst, src, fb->width, fb->height);
905                 ast_set_cursor_base(ast, dst_off);
906         }
907
908         /*
909          * Update location in HWC signature and registers.
910          */
911
912         writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
913         writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
914
915         offset_x = AST_MAX_HWC_WIDTH - fb->width;
916         offset_y = AST_MAX_HWC_HEIGHT - fb->height;
917
918         if (plane_state->crtc_x < 0) {
919                 x_offset = (-plane_state->crtc_x) + offset_x;
920                 x = 0;
921         } else {
922                 x_offset = offset_x;
923                 x = plane_state->crtc_x;
924         }
925         if (plane_state->crtc_y < 0) {
926                 y_offset = (-plane_state->crtc_y) + offset_y;
927                 y = 0;
928         } else {
929                 y_offset = offset_y;
930                 y = plane_state->crtc_y;
931         }
932
933         ast_set_cursor_location(ast, x, y, x_offset, y_offset);
934
935         /* Dummy write to enable HWC and make the HW pick-up the changes. */
936         ast_set_cursor_enabled(ast, true);
937 }
938
939 static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
940                                                    struct drm_atomic_state *state)
941 {
942         struct ast_device *ast = to_ast_device(plane->dev);
943
944         ast_set_cursor_enabled(ast, false);
945 }
946
947 static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
948         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
949         .atomic_check = ast_cursor_plane_helper_atomic_check,
950         .atomic_update = ast_cursor_plane_helper_atomic_update,
951         .atomic_disable = ast_cursor_plane_helper_atomic_disable,
952 };
953
954 static const struct drm_plane_funcs ast_cursor_plane_funcs = {
955         .update_plane = drm_atomic_helper_update_plane,
956         .disable_plane = drm_atomic_helper_disable_plane,
957         .destroy = drm_plane_cleanup,
958         DRM_GEM_SHADOW_PLANE_FUNCS,
959 };
960
961 static int ast_cursor_plane_init(struct ast_device *ast)
962 {
963         struct drm_device *dev = &ast->base;
964         struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
965         struct drm_plane *cursor_plane = &ast_cursor_plane->base;
966         size_t size;
967         void __iomem *vaddr;
968         u64 offset;
969         int ret;
970
971         /*
972          * Allocate backing storage for cursors. The BOs are permanently
973          * pinned to the top end of the VRAM.
974          */
975
976         size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
977
978         if (ast->vram_fb_available < size)
979                 return -ENOMEM;
980
981         vaddr = ast->vram + ast->vram_fb_available - size;
982         offset = ast->vram_fb_available - size;
983
984         ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
985                              0x01, &ast_cursor_plane_funcs,
986                              ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
987                              NULL, DRM_PLANE_TYPE_CURSOR);
988         if (ret) {
989                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
990                 return ret;
991         }
992         drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
993         drm_plane_enable_fb_damage_clips(cursor_plane);
994
995         ast->vram_fb_available -= size;
996
997         return 0;
998 }
999
1000 /*
1001  * CRTC
1002  */
1003
1004 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
1005 {
1006         struct ast_device *ast = to_ast_device(crtc->dev);
1007         u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
1008         struct ast_crtc_state *ast_state;
1009         const struct drm_format_info *format;
1010         struct ast_vbios_mode_info *vbios_mode_info;
1011
1012         /* TODO: Maybe control display signal generation with
1013          *       Sync Enable (bit CR17.7).
1014          */
1015         switch (mode) {
1016         case DRM_MODE_DPMS_ON:
1017                 ast_set_index_reg_mask(ast, AST_IO_VGASRI,  0x01, 0xdf, 0);
1018                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, 0);
1019                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1020                         ast_set_dp501_video_output(crtc->dev, 1);
1021
1022                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1023                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
1024                         ast_wait_for_vretrace(ast);
1025                         ast_dp_set_on_off(crtc->dev, 1);
1026                 }
1027
1028                 ast_state = to_ast_crtc_state(crtc->state);
1029                 format = ast_state->format;
1030
1031                 if (format) {
1032                         vbios_mode_info = &ast_state->vbios_mode_info;
1033
1034                         ast_set_color_reg(ast, format);
1035                         ast_set_vbios_color_reg(ast, format, vbios_mode_info);
1036                         if (crtc->state->gamma_lut)
1037                                 ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
1038                         else
1039                                 ast_crtc_set_gamma_linear(ast, format);
1040                 }
1041                 break;
1042         case DRM_MODE_DPMS_STANDBY:
1043         case DRM_MODE_DPMS_SUSPEND:
1044         case DRM_MODE_DPMS_OFF:
1045                 ch = mode;
1046                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1047                         ast_set_dp501_video_output(crtc->dev, 0);
1048
1049                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1050                         ast_dp_set_on_off(crtc->dev, 0);
1051                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
1052                 }
1053
1054                 ast_set_index_reg_mask(ast, AST_IO_VGASRI,  0x01, 0xdf, 0x20);
1055                 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xfc, ch);
1056                 break;
1057         }
1058 }
1059
1060 static enum drm_mode_status
1061 ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
1062 {
1063         struct ast_device *ast = to_ast_device(crtc->dev);
1064         enum drm_mode_status status;
1065         uint32_t jtemp;
1066
1067         if (ast->support_wide_screen) {
1068                 if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050))
1069                         return MODE_OK;
1070                 if ((mode->hdisplay == 1280) && (mode->vdisplay == 800))
1071                         return MODE_OK;
1072                 if ((mode->hdisplay == 1440) && (mode->vdisplay == 900))
1073                         return MODE_OK;
1074                 if ((mode->hdisplay == 1360) && (mode->vdisplay == 768))
1075                         return MODE_OK;
1076                 if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
1077                         return MODE_OK;
1078                 if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
1079                         return MODE_OK;
1080
1081                 if ((ast->chip == AST2100) || // GEN2, but not AST1100 (?)
1082                     (ast->chip == AST2200) || // GEN3, but not AST2150 (?)
1083                     IS_AST_GEN4(ast) || IS_AST_GEN5(ast) ||
1084                     IS_AST_GEN6(ast) || IS_AST_GEN7(ast)) {
1085                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
1086                                 return MODE_OK;
1087
1088                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) {
1089                                 jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff);
1090                                 if (jtemp & 0x01)
1091                                         return MODE_NOMODE;
1092                                 else
1093                                         return MODE_OK;
1094                         }
1095                 }
1096         }
1097
1098         status = MODE_NOMODE;
1099
1100         switch (mode->hdisplay) {
1101         case 640:
1102                 if (mode->vdisplay == 480)
1103                         status = MODE_OK;
1104                 break;
1105         case 800:
1106                 if (mode->vdisplay == 600)
1107                         status = MODE_OK;
1108                 break;
1109         case 1024:
1110                 if (mode->vdisplay == 768)
1111                         status = MODE_OK;
1112                 break;
1113         case 1152:
1114                 if (mode->vdisplay == 864)
1115                         status = MODE_OK;
1116                 break;
1117         case 1280:
1118                 if (mode->vdisplay == 1024)
1119                         status = MODE_OK;
1120                 break;
1121         case 1600:
1122                 if (mode->vdisplay == 1200)
1123                         status = MODE_OK;
1124                 break;
1125         default:
1126                 break;
1127         }
1128
1129         return status;
1130 }
1131
1132 static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
1133                                         struct drm_atomic_state *state)
1134 {
1135         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1136         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1137         struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
1138         struct drm_device *dev = crtc->dev;
1139         struct ast_crtc_state *ast_state;
1140         const struct drm_format_info *format;
1141         bool succ;
1142         int ret;
1143
1144         if (!crtc_state->enable)
1145                 return 0;
1146
1147         ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
1148         if (ret)
1149                 return ret;
1150
1151         ast_state = to_ast_crtc_state(crtc_state);
1152
1153         format = ast_state->format;
1154         if (drm_WARN_ON_ONCE(dev, !format))
1155                 return -EINVAL; /* BUG: We didn't set format in primary check(). */
1156
1157         /*
1158          * The gamma LUT has to be reloaded after changing the primary
1159          * plane's color format.
1160          */
1161         if (old_ast_crtc_state->format != format)
1162                 crtc_state->color_mgmt_changed = true;
1163
1164         if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
1165                 if (crtc_state->gamma_lut->length !=
1166                     AST_LUT_SIZE * sizeof(struct drm_color_lut)) {
1167                         drm_err(dev, "Wrong size for gamma_lut %zu\n",
1168                                 crtc_state->gamma_lut->length);
1169                         return -EINVAL;
1170                 }
1171         }
1172
1173         succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
1174                                        &crtc_state->adjusted_mode,
1175                                        &ast_state->vbios_mode_info);
1176         if (!succ)
1177                 return -EINVAL;
1178
1179         return 0;
1180 }
1181
1182 static void
1183 ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
1184                              struct drm_atomic_state *state)
1185 {
1186         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1187                                                                           crtc);
1188         struct drm_device *dev = crtc->dev;
1189         struct ast_device *ast = to_ast_device(dev);
1190         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1191         struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
1192
1193         /*
1194          * The gamma LUT has to be reloaded after changing the primary
1195          * plane's color format.
1196          */
1197         if (crtc_state->enable && crtc_state->color_mgmt_changed) {
1198                 if (crtc_state->gamma_lut)
1199                         ast_crtc_set_gamma(ast,
1200                                            ast_crtc_state->format,
1201                                            crtc_state->gamma_lut->data);
1202                 else
1203                         ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
1204         }
1205
1206         //Set Aspeed Display-Port
1207         if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
1208                 ast_dp_set_mode(crtc, vbios_mode_info);
1209 }
1210
1211 static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1212 {
1213         struct drm_device *dev = crtc->dev;
1214         struct ast_device *ast = to_ast_device(dev);
1215         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1216         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1217         struct ast_vbios_mode_info *vbios_mode_info =
1218                 &ast_crtc_state->vbios_mode_info;
1219         struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
1220
1221         ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
1222         ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06);
1223         ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
1224         ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
1225         ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
1226         ast_set_crtthd_reg(ast);
1227         ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
1228
1229         ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
1230 }
1231
1232 static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1233 {
1234         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1235         struct drm_device *dev = crtc->dev;
1236         struct ast_device *ast = to_ast_device(dev);
1237
1238         ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1239
1240         /*
1241          * HW cursors require the underlying primary plane and CRTC to
1242          * display a valid mode and image. This is not the case during
1243          * full modeset operations. So we temporarily disable any active
1244          * plane, including the HW cursor. Each plane's atomic_update()
1245          * helper will re-enable it if necessary.
1246          *
1247          * We only do this during *full* modesets. It does not affect
1248          * simple pageflips on the planes.
1249          */
1250         drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
1251
1252         /*
1253          * Ensure that no scanout takes place before reprogramming mode
1254          * and format registers.
1255          */
1256         ast_wait_for_vretrace(ast);
1257 }
1258
1259 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
1260         .mode_valid = ast_crtc_helper_mode_valid,
1261         .atomic_check = ast_crtc_helper_atomic_check,
1262         .atomic_flush = ast_crtc_helper_atomic_flush,
1263         .atomic_enable = ast_crtc_helper_atomic_enable,
1264         .atomic_disable = ast_crtc_helper_atomic_disable,
1265 };
1266
1267 static void ast_crtc_reset(struct drm_crtc *crtc)
1268 {
1269         struct ast_crtc_state *ast_state =
1270                 kzalloc(sizeof(*ast_state), GFP_KERNEL);
1271
1272         if (crtc->state)
1273                 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
1274
1275         if (ast_state)
1276                 __drm_atomic_helper_crtc_reset(crtc, &ast_state->base);
1277         else
1278                 __drm_atomic_helper_crtc_reset(crtc, NULL);
1279 }
1280
1281 static struct drm_crtc_state *
1282 ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
1283 {
1284         struct ast_crtc_state *new_ast_state, *ast_state;
1285         struct drm_device *dev = crtc->dev;
1286
1287         if (drm_WARN_ON(dev, !crtc->state))
1288                 return NULL;
1289
1290         new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL);
1291         if (!new_ast_state)
1292                 return NULL;
1293         __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base);
1294
1295         ast_state = to_ast_crtc_state(crtc->state);
1296
1297         new_ast_state->format = ast_state->format;
1298         memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
1299                sizeof(new_ast_state->vbios_mode_info));
1300
1301         return &new_ast_state->base;
1302 }
1303
1304 static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
1305                                           struct drm_crtc_state *state)
1306 {
1307         struct ast_crtc_state *ast_state = to_ast_crtc_state(state);
1308
1309         __drm_atomic_helper_crtc_destroy_state(&ast_state->base);
1310         kfree(ast_state);
1311 }
1312
1313 static const struct drm_crtc_funcs ast_crtc_funcs = {
1314         .reset = ast_crtc_reset,
1315         .destroy = drm_crtc_cleanup,
1316         .set_config = drm_atomic_helper_set_config,
1317         .page_flip = drm_atomic_helper_page_flip,
1318         .atomic_duplicate_state = ast_crtc_atomic_duplicate_state,
1319         .atomic_destroy_state = ast_crtc_atomic_destroy_state,
1320 };
1321
1322 static int ast_crtc_init(struct drm_device *dev)
1323 {
1324         struct ast_device *ast = to_ast_device(dev);
1325         struct drm_crtc *crtc = &ast->crtc;
1326         int ret;
1327
1328         ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
1329                                         &ast->cursor_plane.base, &ast_crtc_funcs,
1330                                         NULL);
1331         if (ret)
1332                 return ret;
1333
1334         drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE);
1335         drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE);
1336
1337         drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
1338
1339         return 0;
1340 }
1341
1342 /*
1343  * VGA Connector
1344  */
1345
1346 static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
1347 {
1348         struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector);
1349         struct drm_device *dev = connector->dev;
1350         struct ast_device *ast = to_ast_device(dev);
1351         struct edid *edid;
1352         int count;
1353
1354         if (!ast_vga_connector->i2c)
1355                 goto err_drm_connector_update_edid_property;
1356
1357         /*
1358          * Protect access to I/O registers from concurrent modesetting
1359          * by acquiring the I/O-register lock.
1360          */
1361         mutex_lock(&ast->ioregs_lock);
1362
1363         edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter);
1364         if (!edid)
1365                 goto err_mutex_unlock;
1366
1367         mutex_unlock(&ast->ioregs_lock);
1368
1369         count = drm_add_edid_modes(connector, edid);
1370         kfree(edid);
1371
1372         return count;
1373
1374 err_mutex_unlock:
1375         mutex_unlock(&ast->ioregs_lock);
1376 err_drm_connector_update_edid_property:
1377         drm_connector_update_edid_property(connector, NULL);
1378         return 0;
1379 }
1380
1381 static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
1382         .get_modes = ast_vga_connector_helper_get_modes,
1383 };
1384
1385 static const struct drm_connector_funcs ast_vga_connector_funcs = {
1386         .reset = drm_atomic_helper_connector_reset,
1387         .fill_modes = drm_helper_probe_single_connector_modes,
1388         .destroy = drm_connector_cleanup,
1389         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1390         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1391 };
1392
1393 static int ast_vga_connector_init(struct drm_device *dev,
1394                                   struct ast_vga_connector *ast_vga_connector)
1395 {
1396         struct drm_connector *connector = &ast_vga_connector->base;
1397         int ret;
1398
1399         ast_vga_connector->i2c = ast_i2c_create(dev);
1400         if (!ast_vga_connector->i2c)
1401                 drm_err(dev, "failed to add ddc bus for connector\n");
1402
1403         if (ast_vga_connector->i2c)
1404                 ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,
1405                                                   DRM_MODE_CONNECTOR_VGA,
1406                                                   &ast_vga_connector->i2c->adapter);
1407         else
1408                 ret = drm_connector_init(dev, connector, &ast_vga_connector_funcs,
1409                                          DRM_MODE_CONNECTOR_VGA);
1410         if (ret)
1411                 return ret;
1412
1413         drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);
1414
1415         connector->interlace_allowed = 0;
1416         connector->doublescan_allowed = 0;
1417
1418         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1419
1420         return 0;
1421 }
1422
1423 static int ast_vga_output_init(struct ast_device *ast)
1424 {
1425         struct drm_device *dev = &ast->base;
1426         struct drm_crtc *crtc = &ast->crtc;
1427         struct drm_encoder *encoder = &ast->output.vga.encoder;
1428         struct ast_vga_connector *ast_vga_connector = &ast->output.vga.vga_connector;
1429         struct drm_connector *connector = &ast_vga_connector->base;
1430         int ret;
1431
1432         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
1433         if (ret)
1434                 return ret;
1435         encoder->possible_crtcs = drm_crtc_mask(crtc);
1436
1437         ret = ast_vga_connector_init(dev, ast_vga_connector);
1438         if (ret)
1439                 return ret;
1440
1441         ret = drm_connector_attach_encoder(connector, encoder);
1442         if (ret)
1443                 return ret;
1444
1445         return 0;
1446 }
1447
1448 /*
1449  * SIL164 Connector
1450  */
1451
1452 static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector)
1453 {
1454         struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector);
1455         struct drm_device *dev = connector->dev;
1456         struct ast_device *ast = to_ast_device(dev);
1457         struct edid *edid;
1458         int count;
1459
1460         if (!ast_sil164_connector->i2c)
1461                 goto err_drm_connector_update_edid_property;
1462
1463         /*
1464          * Protect access to I/O registers from concurrent modesetting
1465          * by acquiring the I/O-register lock.
1466          */
1467         mutex_lock(&ast->ioregs_lock);
1468
1469         edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter);
1470         if (!edid)
1471                 goto err_mutex_unlock;
1472
1473         mutex_unlock(&ast->ioregs_lock);
1474
1475         count = drm_add_edid_modes(connector, edid);
1476         kfree(edid);
1477
1478         return count;
1479
1480 err_mutex_unlock:
1481         mutex_unlock(&ast->ioregs_lock);
1482 err_drm_connector_update_edid_property:
1483         drm_connector_update_edid_property(connector, NULL);
1484         return 0;
1485 }
1486
1487 static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
1488         .get_modes = ast_sil164_connector_helper_get_modes,
1489 };
1490
1491 static const struct drm_connector_funcs ast_sil164_connector_funcs = {
1492         .reset = drm_atomic_helper_connector_reset,
1493         .fill_modes = drm_helper_probe_single_connector_modes,
1494         .destroy = drm_connector_cleanup,
1495         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1496         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1497 };
1498
1499 static int ast_sil164_connector_init(struct drm_device *dev,
1500                                      struct ast_sil164_connector *ast_sil164_connector)
1501 {
1502         struct drm_connector *connector = &ast_sil164_connector->base;
1503         int ret;
1504
1505         ast_sil164_connector->i2c = ast_i2c_create(dev);
1506         if (!ast_sil164_connector->i2c)
1507                 drm_err(dev, "failed to add ddc bus for connector\n");
1508
1509         if (ast_sil164_connector->i2c)
1510                 ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs,
1511                                                   DRM_MODE_CONNECTOR_DVII,
1512                                                   &ast_sil164_connector->i2c->adapter);
1513         else
1514                 ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs,
1515                                          DRM_MODE_CONNECTOR_DVII);
1516         if (ret)
1517                 return ret;
1518
1519         drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs);
1520
1521         connector->interlace_allowed = 0;
1522         connector->doublescan_allowed = 0;
1523
1524         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1525
1526         return 0;
1527 }
1528
1529 static int ast_sil164_output_init(struct ast_device *ast)
1530 {
1531         struct drm_device *dev = &ast->base;
1532         struct drm_crtc *crtc = &ast->crtc;
1533         struct drm_encoder *encoder = &ast->output.sil164.encoder;
1534         struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector;
1535         struct drm_connector *connector = &ast_sil164_connector->base;
1536         int ret;
1537
1538         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1539         if (ret)
1540                 return ret;
1541         encoder->possible_crtcs = drm_crtc_mask(crtc);
1542
1543         ret = ast_sil164_connector_init(dev, ast_sil164_connector);
1544         if (ret)
1545                 return ret;
1546
1547         ret = drm_connector_attach_encoder(connector, encoder);
1548         if (ret)
1549                 return ret;
1550
1551         return 0;
1552 }
1553
1554 /*
1555  * DP501 Connector
1556  */
1557
1558 static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
1559 {
1560         void *edid;
1561         bool succ;
1562         int count;
1563
1564         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1565         if (!edid)
1566                 goto err_drm_connector_update_edid_property;
1567
1568         succ = ast_dp501_read_edid(connector->dev, edid);
1569         if (!succ)
1570                 goto err_kfree;
1571
1572         drm_connector_update_edid_property(connector, edid);
1573         count = drm_add_edid_modes(connector, edid);
1574         kfree(edid);
1575
1576         return count;
1577
1578 err_kfree:
1579         kfree(edid);
1580 err_drm_connector_update_edid_property:
1581         drm_connector_update_edid_property(connector, NULL);
1582         return 0;
1583 }
1584
1585 static int ast_dp501_connector_helper_detect_ctx(struct drm_connector *connector,
1586                                                  struct drm_modeset_acquire_ctx *ctx,
1587                                                  bool force)
1588 {
1589         struct ast_device *ast = to_ast_device(connector->dev);
1590
1591         if (ast_dp501_is_connected(ast))
1592                 return connector_status_connected;
1593         return connector_status_disconnected;
1594 }
1595
1596 static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
1597         .get_modes = ast_dp501_connector_helper_get_modes,
1598         .detect_ctx = ast_dp501_connector_helper_detect_ctx,
1599 };
1600
1601 static const struct drm_connector_funcs ast_dp501_connector_funcs = {
1602         .reset = drm_atomic_helper_connector_reset,
1603         .fill_modes = drm_helper_probe_single_connector_modes,
1604         .destroy = drm_connector_cleanup,
1605         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1606         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1607 };
1608
1609 static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)
1610 {
1611         int ret;
1612
1613         ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
1614                                  DRM_MODE_CONNECTOR_DisplayPort);
1615         if (ret)
1616                 return ret;
1617
1618         drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
1619
1620         connector->interlace_allowed = 0;
1621         connector->doublescan_allowed = 0;
1622
1623         connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
1624
1625         return 0;
1626 }
1627
1628 static int ast_dp501_output_init(struct ast_device *ast)
1629 {
1630         struct drm_device *dev = &ast->base;
1631         struct drm_crtc *crtc = &ast->crtc;
1632         struct drm_encoder *encoder = &ast->output.dp501.encoder;
1633         struct drm_connector *connector = &ast->output.dp501.connector;
1634         int ret;
1635
1636         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1637         if (ret)
1638                 return ret;
1639         encoder->possible_crtcs = drm_crtc_mask(crtc);
1640
1641         ret = ast_dp501_connector_init(dev, connector);
1642         if (ret)
1643                 return ret;
1644
1645         ret = drm_connector_attach_encoder(connector, encoder);
1646         if (ret)
1647                 return ret;
1648
1649         return 0;
1650 }
1651
1652 /*
1653  * ASPEED Display-Port Connector
1654  */
1655
1656 static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
1657 {
1658         void *edid;
1659         struct drm_device *dev = connector->dev;
1660         struct ast_device *ast = to_ast_device(dev);
1661
1662         int succ;
1663         int count;
1664
1665         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1666         if (!edid)
1667                 goto err_drm_connector_update_edid_property;
1668
1669         /*
1670          * Protect access to I/O registers from concurrent modesetting
1671          * by acquiring the I/O-register lock.
1672          */
1673         mutex_lock(&ast->ioregs_lock);
1674
1675         succ = ast_astdp_read_edid(connector->dev, edid);
1676         if (succ < 0)
1677                 goto err_mutex_unlock;
1678
1679         mutex_unlock(&ast->ioregs_lock);
1680
1681         drm_connector_update_edid_property(connector, edid);
1682         count = drm_add_edid_modes(connector, edid);
1683         kfree(edid);
1684
1685         return count;
1686
1687 err_mutex_unlock:
1688         mutex_unlock(&ast->ioregs_lock);
1689         kfree(edid);
1690 err_drm_connector_update_edid_property:
1691         drm_connector_update_edid_property(connector, NULL);
1692         return 0;
1693 }
1694
1695 static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector,
1696                                                  struct drm_modeset_acquire_ctx *ctx,
1697                                                  bool force)
1698 {
1699         struct ast_device *ast = to_ast_device(connector->dev);
1700
1701         if (ast_astdp_is_connected(ast))
1702                 return connector_status_connected;
1703         return connector_status_disconnected;
1704 }
1705
1706 static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
1707         .get_modes = ast_astdp_connector_helper_get_modes,
1708         .detect_ctx = ast_astdp_connector_helper_detect_ctx,
1709 };
1710
1711 static const struct drm_connector_funcs ast_astdp_connector_funcs = {
1712         .reset = drm_atomic_helper_connector_reset,
1713         .fill_modes = drm_helper_probe_single_connector_modes,
1714         .destroy = drm_connector_cleanup,
1715         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1716         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1717 };
1718
1719 static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
1720 {
1721         int ret;
1722
1723         ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
1724                                  DRM_MODE_CONNECTOR_DisplayPort);
1725         if (ret)
1726                 return ret;
1727
1728         drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
1729
1730         connector->interlace_allowed = 0;
1731         connector->doublescan_allowed = 0;
1732
1733         connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
1734
1735         return 0;
1736 }
1737
1738 static int ast_astdp_output_init(struct ast_device *ast)
1739 {
1740         struct drm_device *dev = &ast->base;
1741         struct drm_crtc *crtc = &ast->crtc;
1742         struct drm_encoder *encoder = &ast->output.astdp.encoder;
1743         struct drm_connector *connector = &ast->output.astdp.connector;
1744         int ret;
1745
1746         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1747         if (ret)
1748                 return ret;
1749         encoder->possible_crtcs = drm_crtc_mask(crtc);
1750
1751         ret = ast_astdp_connector_init(dev, connector);
1752         if (ret)
1753                 return ret;
1754
1755         ret = drm_connector_attach_encoder(connector, encoder);
1756         if (ret)
1757                 return ret;
1758
1759         return 0;
1760 }
1761
1762 /*
1763  * BMC virtual Connector
1764  */
1765
1766 static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {
1767         .destroy = drm_encoder_cleanup,
1768 };
1769
1770 static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
1771 {
1772         return drm_add_modes_noedid(connector, 4096, 4096);
1773 }
1774
1775 static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
1776         .get_modes = ast_bmc_connector_helper_get_modes,
1777 };
1778
1779 static const struct drm_connector_funcs ast_bmc_connector_funcs = {
1780         .reset = drm_atomic_helper_connector_reset,
1781         .fill_modes = drm_helper_probe_single_connector_modes,
1782         .destroy = drm_connector_cleanup,
1783         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1784         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1785 };
1786
1787 static int ast_bmc_output_init(struct ast_device *ast)
1788 {
1789         struct drm_device *dev = &ast->base;
1790         struct drm_crtc *crtc = &ast->crtc;
1791         struct drm_encoder *encoder = &ast->output.bmc.encoder;
1792         struct drm_connector *connector = &ast->output.bmc.connector;
1793         int ret;
1794
1795         ret = drm_encoder_init(dev, encoder,
1796                                &ast_bmc_encoder_funcs,
1797                                DRM_MODE_ENCODER_VIRTUAL, "ast_bmc");
1798         if (ret)
1799                 return ret;
1800         encoder->possible_crtcs = drm_crtc_mask(crtc);
1801
1802         ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
1803                                  DRM_MODE_CONNECTOR_VIRTUAL);
1804         if (ret)
1805                 return ret;
1806
1807         drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
1808
1809         ret = drm_connector_attach_encoder(connector, encoder);
1810         if (ret)
1811                 return ret;
1812
1813         return 0;
1814 }
1815
1816 /*
1817  * Mode config
1818  */
1819
1820 static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
1821 {
1822         struct ast_device *ast = to_ast_device(state->dev);
1823
1824         /*
1825          * Concurrent operations could possibly trigger a call to
1826          * drm_connector_helper_funcs.get_modes by trying to read the
1827          * display modes. Protect access to I/O registers by acquiring
1828          * the I/O-register lock. Released in atomic_flush().
1829          */
1830         mutex_lock(&ast->ioregs_lock);
1831         drm_atomic_helper_commit_tail_rpm(state);
1832         mutex_unlock(&ast->ioregs_lock);
1833 }
1834
1835 static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {
1836         .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail,
1837 };
1838
1839 static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
1840                                                        const struct drm_display_mode *mode)
1841 {
1842         static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1843         struct ast_device *ast = to_ast_device(dev);
1844         unsigned long fbsize, fbpages, max_fbpages;
1845
1846         max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
1847
1848         fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
1849         fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
1850
1851         if (fbpages > max_fbpages)
1852                 return MODE_MEM;
1853
1854         return MODE_OK;
1855 }
1856
1857 static const struct drm_mode_config_funcs ast_mode_config_funcs = {
1858         .fb_create = drm_gem_fb_create_with_dirty,
1859         .mode_valid = ast_mode_config_mode_valid,
1860         .atomic_check = drm_atomic_helper_check,
1861         .atomic_commit = drm_atomic_helper_commit,
1862 };
1863
1864 int ast_mode_config_init(struct ast_device *ast)
1865 {
1866         struct drm_device *dev = &ast->base;
1867         int ret;
1868
1869         ret = drmm_mode_config_init(dev);
1870         if (ret)
1871                 return ret;
1872
1873         dev->mode_config.funcs = &ast_mode_config_funcs;
1874         dev->mode_config.min_width = 0;
1875         dev->mode_config.min_height = 0;
1876         dev->mode_config.preferred_depth = 24;
1877
1878         if (ast->chip == AST2100 || // GEN2, but not AST1100 (?)
1879             ast->chip == AST2200 || // GEN3, but not AST2150 (?)
1880             IS_AST_GEN7(ast) ||
1881             IS_AST_GEN6(ast) ||
1882             IS_AST_GEN5(ast) ||
1883             IS_AST_GEN4(ast)) {
1884                 dev->mode_config.max_width = 1920;
1885                 dev->mode_config.max_height = 2048;
1886         } else {
1887                 dev->mode_config.max_width = 1600;
1888                 dev->mode_config.max_height = 1200;
1889         }
1890
1891         dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
1892
1893         ret = ast_primary_plane_init(ast);
1894         if (ret)
1895                 return ret;
1896
1897         ret = ast_cursor_plane_init(ast);
1898         if (ret)
1899                 return ret;
1900
1901         ast_crtc_init(dev);
1902
1903         if (ast->tx_chip_types & AST_TX_NONE_BIT) {
1904                 ret = ast_vga_output_init(ast);
1905                 if (ret)
1906                         return ret;
1907         }
1908         if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
1909                 ret = ast_sil164_output_init(ast);
1910                 if (ret)
1911                         return ret;
1912         }
1913         if (ast->tx_chip_types & AST_TX_DP501_BIT) {
1914                 ret = ast_dp501_output_init(ast);
1915                 if (ret)
1916                         return ret;
1917         }
1918         if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1919                 ret = ast_astdp_output_init(ast);
1920                 if (ret)
1921                         return ret;
1922         }
1923         ret = ast_bmc_output_init(ast);
1924         if (ret)
1925                 return ret;
1926
1927         drm_mode_config_reset(dev);
1928
1929         drm_kms_helper_poll_init(dev);
1930
1931         return 0;
1932 }