]> Git Repo - J-linux.git/blob - drivers/gpu/drm/ast/ast_mode.c
Merge tag 'docs-6.3-2' of git://git.lwn.net/linux
[J-linux.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 <[email protected]>
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_private *ast,
55                                      u8 index, u8 red, u8 green,
56                                      u8 blue)
57 {
58         ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index);
59         ast_io_read8(ast, AST_IO_SEQ_PORT);
60         ast_io_write8(ast, AST_IO_DAC_DATA, red);
61         ast_io_read8(ast, AST_IO_SEQ_PORT);
62         ast_io_write8(ast, AST_IO_DAC_DATA, green);
63         ast_io_read8(ast, AST_IO_SEQ_PORT);
64         ast_io_write8(ast, AST_IO_DAC_DATA, blue);
65         ast_io_read8(ast, AST_IO_SEQ_PORT);
66 }
67
68 static void ast_crtc_set_gamma_linear(struct ast_private *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_private *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_private *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_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4));
257
258         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
259
260         if (vbios_mode->enh_table->flags & NewModeInfo) {
261                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
262                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8);
263         }
264 }
265
266 static void ast_set_vbios_mode_reg(struct ast_private *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_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
276         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
277
278         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
279
280         if (vbios_mode->enh_table->flags & NewModeInfo) {
281                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
282                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
283                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
284                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
285                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay);
286                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8);
287         }
288 }
289
290 static void ast_set_std_reg(struct ast_private *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_MISC_PORT_WRITE, jreg);
302
303         /* Set SEQ; except Screen Disable field */
304         ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03);
305         ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 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_SEQ_PORT, (i + 1), jreg);
309         }
310
311         /* Set CRTC; except base address and offset */
312         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
313         for (i = 0; i < 12; i++)
314                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
315         for (i = 14; i < 19; i++)
316                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
317         for (i = 20; i < 25; i++)
318                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
319
320         /* set AR */
321         jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
322         for (i = 0; i < 20; i++) {
323                 jreg = stdtable->ar[i];
324                 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i);
325                 ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg);
326         }
327         ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14);
328         ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00);
329
330         jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
331         ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20);
332
333         /* Set GR */
334         for (i = 0; i < 9; i++)
335                 ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);
336 }
337
338 static void ast_set_crtc_reg(struct ast_private *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 ((ast->chip == AST2500 || ast->chip == AST2600) &&
346             (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
347                 precache = 40;
348
349         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
382
383         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC);
384         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD);
385
386         // Workaround for HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels);
387         if ((ast->chip == AST2600) && (mode->crtc_vdisplay == 1080))
388                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x02);
389         else
390                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 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_CRTC_PORT, 0x16, 0x00, temp);
440
441         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07);
442         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
443         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
444
445         if (precache)
446                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
447         else
448                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
449
450         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
451 }
452
453 static void ast_set_offset_reg(struct ast_private *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_CRTC_PORT, 0x13, (offset & 0xff));
460         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
461 }
462
463 static void ast_set_dclk_reg(struct ast_private *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 ((ast->chip == AST2500) || (ast->chip == AST2600))
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_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
475         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
476         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
477                                (clk_info->param3 & 0xc0) |
478                                ((clk_info->param3 & 0x3) << 4));
479 }
480
481 static void ast_set_color_reg(struct ast_private *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_CRTC_PORT, 0xa0, 0x8f, jregA0);
506         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3);
507         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
508 }
509
510 static void ast_set_crtthd_reg(struct ast_private *ast)
511 {
512         /* Set Threshold */
513         if (ast->chip == AST2600) {
514                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0);
515                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0);
516         } else if (ast->chip == AST2300 || ast->chip == AST2400 ||
517             ast->chip == AST2500) {
518                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
519                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
520         } else if (ast->chip == AST2100 ||
521                    ast->chip == AST1100 ||
522                    ast->chip == AST2200 ||
523                    ast->chip == AST2150) {
524                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f);
525                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f);
526         } else {
527                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f);
528                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f);
529         }
530 }
531
532 static void ast_set_sync_reg(struct ast_private *ast,
533                              struct drm_display_mode *mode,
534                              struct ast_vbios_mode_info *vbios_mode)
535 {
536         u8 jreg;
537
538         jreg  = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
539         jreg &= ~0xC0;
540         if (vbios_mode->enh_table->flags & NVSync)
541                 jreg |= 0x80;
542         if (vbios_mode->enh_table->flags & NHSync)
543                 jreg |= 0x40;
544         ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
545 }
546
547 static void ast_set_start_address_crt1(struct ast_private *ast,
548                                        unsigned int offset)
549 {
550         u32 addr;
551
552         addr = offset >> 2;
553         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff));
554         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff));
555         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff));
556
557 }
558
559 static void ast_wait_for_vretrace(struct ast_private *ast)
560 {
561         unsigned long timeout = jiffies + HZ;
562         u8 vgair1;
563
564         do {
565                 vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
566         } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
567 }
568
569 /*
570  * Planes
571  */
572
573 static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
574                           void __iomem *vaddr, u64 offset, unsigned long size,
575                           uint32_t possible_crtcs,
576                           const struct drm_plane_funcs *funcs,
577                           const uint32_t *formats, unsigned int format_count,
578                           const uint64_t *format_modifiers,
579                           enum drm_plane_type type)
580 {
581         struct drm_plane *plane = &ast_plane->base;
582
583         ast_plane->vaddr = vaddr;
584         ast_plane->offset = offset;
585         ast_plane->size = size;
586
587         return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
588                                         formats, format_count, format_modifiers,
589                                         type, NULL);
590 }
591
592 /*
593  * Primary plane
594  */
595
596 static const uint32_t ast_primary_plane_formats[] = {
597         DRM_FORMAT_XRGB8888,
598         DRM_FORMAT_RGB565,
599         DRM_FORMAT_C8,
600 };
601
602 static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
603                                                  struct drm_atomic_state *state)
604 {
605         struct drm_device *dev = plane->dev;
606         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
607         struct drm_crtc_state *new_crtc_state = NULL;
608         struct ast_crtc_state *new_ast_crtc_state;
609         int ret;
610
611         if (new_plane_state->crtc)
612                 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
613
614         ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
615                                                   DRM_PLANE_NO_SCALING,
616                                                   DRM_PLANE_NO_SCALING,
617                                                   false, true);
618         if (ret) {
619                 return ret;
620         } else if (!new_plane_state->visible) {
621                 if (drm_WARN_ON(dev, new_plane_state->crtc)) /* cannot legally happen */
622                         return -EINVAL;
623                 else
624                         return 0;
625         }
626
627         new_ast_crtc_state = to_ast_crtc_state(new_crtc_state);
628
629         new_ast_crtc_state->format = new_plane_state->fb->format;
630
631         return 0;
632 }
633
634 static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
635                               struct drm_framebuffer *fb,
636                               const struct drm_rect *clip)
637 {
638         struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(ast_plane->vaddr);
639
640         iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
641         drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
642 }
643
644 static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
645                                                    struct drm_atomic_state *state)
646 {
647         struct drm_device *dev = plane->dev;
648         struct ast_private *ast = to_ast_private(dev);
649         struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
650         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
651         struct drm_framebuffer *fb = plane_state->fb;
652         struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
653         struct drm_framebuffer *old_fb = old_plane_state->fb;
654         struct ast_plane *ast_plane = to_ast_plane(plane);
655         struct drm_rect damage;
656         struct drm_atomic_helper_damage_iter iter;
657
658         if (!old_fb || (fb->format != old_fb->format)) {
659                 struct drm_crtc *crtc = plane_state->crtc;
660                 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
661                 struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
662                 struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
663
664                 ast_set_color_reg(ast, fb->format);
665                 ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
666         }
667
668         drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
669         drm_atomic_for_each_plane_damage(&iter, &damage) {
670                 ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
671         }
672
673         /*
674          * Some BMCs stop scanning out the video signal after the driver
675          * reprogrammed the offset or scanout address. This stalls display
676          * output for several seconds and makes the display unusable.
677          * Therefore only update the offset if it changes and reprogram the
678          * address after enabling the plane.
679          */
680         if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
681                 ast_set_offset_reg(ast, fb);
682         if (!old_fb) {
683                 ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
684                 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
685         }
686 }
687
688 static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
689                                                     struct drm_atomic_state *state)
690 {
691         struct ast_private *ast = to_ast_private(plane->dev);
692
693         ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);
694 }
695
696 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
697         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
698         .atomic_check = ast_primary_plane_helper_atomic_check,
699         .atomic_update = ast_primary_plane_helper_atomic_update,
700         .atomic_disable = ast_primary_plane_helper_atomic_disable,
701 };
702
703 static const struct drm_plane_funcs ast_primary_plane_funcs = {
704         .update_plane = drm_atomic_helper_update_plane,
705         .disable_plane = drm_atomic_helper_disable_plane,
706         .destroy = drm_plane_cleanup,
707         DRM_GEM_SHADOW_PLANE_FUNCS,
708 };
709
710 static int ast_primary_plane_init(struct ast_private *ast)
711 {
712         struct drm_device *dev = &ast->base;
713         struct ast_plane *ast_primary_plane = &ast->primary_plane;
714         struct drm_plane *primary_plane = &ast_primary_plane->base;
715         void __iomem *vaddr = ast->vram;
716         u64 offset = 0; /* with shmem, the primary plane is always at offset 0 */
717         unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
718         unsigned long size = ast->vram_fb_available - cursor_size;
719         int ret;
720
721         ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size,
722                              0x01, &ast_primary_plane_funcs,
723                              ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats),
724                              NULL, DRM_PLANE_TYPE_PRIMARY);
725         if (ret) {
726                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
727                 return ret;
728         }
729         drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);
730         drm_plane_enable_fb_damage_clips(primary_plane);
731
732         return 0;
733 }
734
735 /*
736  * Cursor plane
737  */
738
739 static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height)
740 {
741         union {
742                 u32 ul;
743                 u8 b[4];
744         } srcdata32[2], data32;
745         union {
746                 u16 us;
747                 u8 b[2];
748         } data16;
749         u32 csum = 0;
750         s32 alpha_dst_delta, last_alpha_dst_delta;
751         u8 __iomem *dstxor;
752         const u8 *srcxor;
753         int i, j;
754         u32 per_pixel_copy, two_pixel_copy;
755
756         alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
757         last_alpha_dst_delta = alpha_dst_delta - (width << 1);
758
759         srcxor = src;
760         dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
761         per_pixel_copy = width & 1;
762         two_pixel_copy = width >> 1;
763
764         for (j = 0; j < height; j++) {
765                 for (i = 0; i < two_pixel_copy; i++) {
766                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
767                         srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
768                         data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
769                         data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
770                         data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
771                         data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
772
773                         writel(data32.ul, dstxor);
774                         csum += data32.ul;
775
776                         dstxor += 4;
777                         srcxor += 8;
778
779                 }
780
781                 for (i = 0; i < per_pixel_copy; i++) {
782                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
783                         data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
784                         data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
785                         writew(data16.us, dstxor);
786                         csum += (u32)data16.us;
787
788                         dstxor += 2;
789                         srcxor += 4;
790                 }
791                 dstxor += last_alpha_dst_delta;
792         }
793
794         /* write checksum + signature */
795         dst += AST_HWC_SIZE;
796         writel(csum, dst);
797         writel(width, dst + AST_HWC_SIGNATURE_SizeX);
798         writel(height, dst + AST_HWC_SIGNATURE_SizeY);
799         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
800         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
801 }
802
803 static void ast_set_cursor_base(struct ast_private *ast, u64 address)
804 {
805         u8 addr0 = (address >> 3) & 0xff;
806         u8 addr1 = (address >> 11) & 0xff;
807         u8 addr2 = (address >> 19) & 0xff;
808
809         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0);
810         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1);
811         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
812 }
813
814 static void ast_set_cursor_location(struct ast_private *ast, u16 x, u16 y,
815                                     u8 x_offset, u8 y_offset)
816 {
817         u8 x0 = (x & 0x00ff);
818         u8 x1 = (x & 0x0f00) >> 8;
819         u8 y0 = (y & 0x00ff);
820         u8 y1 = (y & 0x0700) >> 8;
821
822         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset);
823         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset);
824         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0);
825         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1);
826         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0);
827         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);
828 }
829
830 static void ast_set_cursor_enabled(struct ast_private *ast, bool enabled)
831 {
832         static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
833                                      AST_IO_VGACRCB_HWC_ENABLED);
834
835         u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP;
836
837         if (enabled)
838                 vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED;
839
840         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, mask, vgacrcb);
841 }
842
843 static const uint32_t ast_cursor_plane_formats[] = {
844         DRM_FORMAT_ARGB8888,
845 };
846
847 static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
848                                                 struct drm_atomic_state *state)
849 {
850         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
851         struct drm_framebuffer *new_fb = new_plane_state->fb;
852         struct drm_crtc_state *new_crtc_state = NULL;
853         int ret;
854
855         if (new_plane_state->crtc)
856                 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
857
858         ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
859                                                   DRM_PLANE_NO_SCALING,
860                                                   DRM_PLANE_NO_SCALING,
861                                                   true, true);
862         if (ret || !new_plane_state->visible)
863                 return ret;
864
865         if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
866                 return -EINVAL;
867
868         return 0;
869 }
870
871 static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
872                                                   struct drm_atomic_state *state)
873 {
874         struct ast_plane *ast_plane = to_ast_plane(plane);
875         struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
876         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
877         struct drm_framebuffer *fb = plane_state->fb;
878         struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
879         struct ast_private *ast = to_ast_private(plane->dev);
880         struct iosys_map src_map = shadow_plane_state->data[0];
881         struct drm_rect damage;
882         const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
883         u64 dst_off = ast_plane->offset;
884         u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
885         u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
886         unsigned int offset_x, offset_y;
887         u16 x, y;
888         u8 x_offset, y_offset;
889
890         /*
891          * Do data transfer to hardware buffer and point the scanout
892          * engine to the offset.
893          */
894
895         if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
896                 ast_update_cursor_image(dst, src, fb->width, fb->height);
897                 ast_set_cursor_base(ast, dst_off);
898         }
899
900         /*
901          * Update location in HWC signature and registers.
902          */
903
904         writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
905         writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
906
907         offset_x = AST_MAX_HWC_WIDTH - fb->width;
908         offset_y = AST_MAX_HWC_HEIGHT - fb->height;
909
910         if (plane_state->crtc_x < 0) {
911                 x_offset = (-plane_state->crtc_x) + offset_x;
912                 x = 0;
913         } else {
914                 x_offset = offset_x;
915                 x = plane_state->crtc_x;
916         }
917         if (plane_state->crtc_y < 0) {
918                 y_offset = (-plane_state->crtc_y) + offset_y;
919                 y = 0;
920         } else {
921                 y_offset = offset_y;
922                 y = plane_state->crtc_y;
923         }
924
925         ast_set_cursor_location(ast, x, y, x_offset, y_offset);
926
927         /* Dummy write to enable HWC and make the HW pick-up the changes. */
928         ast_set_cursor_enabled(ast, true);
929 }
930
931 static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
932                                                    struct drm_atomic_state *state)
933 {
934         struct ast_private *ast = to_ast_private(plane->dev);
935
936         ast_set_cursor_enabled(ast, false);
937 }
938
939 static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
940         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
941         .atomic_check = ast_cursor_plane_helper_atomic_check,
942         .atomic_update = ast_cursor_plane_helper_atomic_update,
943         .atomic_disable = ast_cursor_plane_helper_atomic_disable,
944 };
945
946 static const struct drm_plane_funcs ast_cursor_plane_funcs = {
947         .update_plane = drm_atomic_helper_update_plane,
948         .disable_plane = drm_atomic_helper_disable_plane,
949         .destroy = drm_plane_cleanup,
950         DRM_GEM_SHADOW_PLANE_FUNCS,
951 };
952
953 static int ast_cursor_plane_init(struct ast_private *ast)
954 {
955         struct drm_device *dev = &ast->base;
956         struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
957         struct drm_plane *cursor_plane = &ast_cursor_plane->base;
958         size_t size;
959         void __iomem *vaddr;
960         u64 offset;
961         int ret;
962
963         /*
964          * Allocate backing storage for cursors. The BOs are permanently
965          * pinned to the top end of the VRAM.
966          */
967
968         size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
969
970         if (ast->vram_fb_available < size)
971                 return -ENOMEM;
972
973         vaddr = ast->vram + ast->vram_fb_available - size;
974         offset = ast->vram_fb_available - size;
975
976         ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
977                              0x01, &ast_cursor_plane_funcs,
978                              ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
979                              NULL, DRM_PLANE_TYPE_CURSOR);
980         if (ret) {
981                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
982                 return ret;
983         }
984         drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
985         drm_plane_enable_fb_damage_clips(cursor_plane);
986
987         ast->vram_fb_available -= size;
988
989         return 0;
990 }
991
992 /*
993  * CRTC
994  */
995
996 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
997 {
998         struct ast_private *ast = to_ast_private(crtc->dev);
999         u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
1000         struct ast_crtc_state *ast_state;
1001         const struct drm_format_info *format;
1002         struct ast_vbios_mode_info *vbios_mode_info;
1003
1004         /* TODO: Maybe control display signal generation with
1005          *       Sync Enable (bit CR17.7).
1006          */
1007         switch (mode) {
1008         case DRM_MODE_DPMS_ON:
1009                 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
1010                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
1011                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1012                         ast_set_dp501_video_output(crtc->dev, 1);
1013
1014                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1015                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
1016                         ast_wait_for_vretrace(ast);
1017                         ast_dp_set_on_off(crtc->dev, 1);
1018                 }
1019
1020                 ast_state = to_ast_crtc_state(crtc->state);
1021                 format = ast_state->format;
1022
1023                 if (format) {
1024                         vbios_mode_info = &ast_state->vbios_mode_info;
1025
1026                         ast_set_color_reg(ast, format);
1027                         ast_set_vbios_color_reg(ast, format, vbios_mode_info);
1028                         if (crtc->state->gamma_lut)
1029                                 ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
1030                         else
1031                                 ast_crtc_set_gamma_linear(ast, format);
1032                 }
1033                 break;
1034         case DRM_MODE_DPMS_STANDBY:
1035         case DRM_MODE_DPMS_SUSPEND:
1036         case DRM_MODE_DPMS_OFF:
1037                 ch = mode;
1038                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1039                         ast_set_dp501_video_output(crtc->dev, 0);
1040
1041                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1042                         ast_dp_set_on_off(crtc->dev, 0);
1043                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
1044                 }
1045
1046                 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
1047                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
1048                 break;
1049         }
1050 }
1051
1052 static enum drm_mode_status
1053 ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
1054 {
1055         struct ast_private *ast = to_ast_private(crtc->dev);
1056         enum drm_mode_status status;
1057         uint32_t jtemp;
1058
1059         if (ast->support_wide_screen) {
1060                 if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050))
1061                         return MODE_OK;
1062                 if ((mode->hdisplay == 1280) && (mode->vdisplay == 800))
1063                         return MODE_OK;
1064                 if ((mode->hdisplay == 1440) && (mode->vdisplay == 900))
1065                         return MODE_OK;
1066                 if ((mode->hdisplay == 1360) && (mode->vdisplay == 768))
1067                         return MODE_OK;
1068                 if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
1069                         return MODE_OK;
1070                 if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
1071                         return MODE_OK;
1072
1073                 if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
1074                     (ast->chip == AST2300) || (ast->chip == AST2400) ||
1075                     (ast->chip == AST2500) || (ast->chip == AST2600)) {
1076                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
1077                                 return MODE_OK;
1078
1079                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) {
1080                                 jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
1081                                 if (jtemp & 0x01)
1082                                         return MODE_NOMODE;
1083                                 else
1084                                         return MODE_OK;
1085                         }
1086                 }
1087         }
1088
1089         status = MODE_NOMODE;
1090
1091         switch (mode->hdisplay) {
1092         case 640:
1093                 if (mode->vdisplay == 480)
1094                         status = MODE_OK;
1095                 break;
1096         case 800:
1097                 if (mode->vdisplay == 600)
1098                         status = MODE_OK;
1099                 break;
1100         case 1024:
1101                 if (mode->vdisplay == 768)
1102                         status = MODE_OK;
1103                 break;
1104         case 1152:
1105                 if (mode->vdisplay == 864)
1106                         status = MODE_OK;
1107                 break;
1108         case 1280:
1109                 if (mode->vdisplay == 1024)
1110                         status = MODE_OK;
1111                 break;
1112         case 1600:
1113                 if (mode->vdisplay == 1200)
1114                         status = MODE_OK;
1115                 break;
1116         default:
1117                 break;
1118         }
1119
1120         return status;
1121 }
1122
1123 static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
1124                                         struct drm_atomic_state *state)
1125 {
1126         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1127         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1128         struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
1129         struct drm_device *dev = crtc->dev;
1130         struct ast_crtc_state *ast_state;
1131         const struct drm_format_info *format;
1132         bool succ;
1133         int ret;
1134
1135         if (!crtc_state->enable)
1136                 return 0;
1137
1138         ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
1139         if (ret)
1140                 return ret;
1141
1142         ast_state = to_ast_crtc_state(crtc_state);
1143
1144         format = ast_state->format;
1145         if (drm_WARN_ON_ONCE(dev, !format))
1146                 return -EINVAL; /* BUG: We didn't set format in primary check(). */
1147
1148         /*
1149          * The gamma LUT has to be reloaded after changing the primary
1150          * plane's color format.
1151          */
1152         if (old_ast_crtc_state->format != format)
1153                 crtc_state->color_mgmt_changed = true;
1154
1155         if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
1156                 if (crtc_state->gamma_lut->length !=
1157                     AST_LUT_SIZE * sizeof(struct drm_color_lut)) {
1158                         drm_err(dev, "Wrong size for gamma_lut %zu\n",
1159                                 crtc_state->gamma_lut->length);
1160                         return -EINVAL;
1161                 }
1162         }
1163
1164         succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
1165                                        &crtc_state->adjusted_mode,
1166                                        &ast_state->vbios_mode_info);
1167         if (!succ)
1168                 return -EINVAL;
1169
1170         return 0;
1171 }
1172
1173 static void
1174 ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
1175                              struct drm_atomic_state *state)
1176 {
1177         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1178                                                                           crtc);
1179         struct drm_device *dev = crtc->dev;
1180         struct ast_private *ast = to_ast_private(dev);
1181         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1182         struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
1183
1184         /*
1185          * The gamma LUT has to be reloaded after changing the primary
1186          * plane's color format.
1187          */
1188         if (crtc_state->enable && crtc_state->color_mgmt_changed) {
1189                 if (crtc_state->gamma_lut)
1190                         ast_crtc_set_gamma(ast,
1191                                            ast_crtc_state->format,
1192                                            crtc_state->gamma_lut->data);
1193                 else
1194                         ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
1195         }
1196
1197         //Set Aspeed Display-Port
1198         if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
1199                 ast_dp_set_mode(crtc, vbios_mode_info);
1200 }
1201
1202 static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1203 {
1204         struct drm_device *dev = crtc->dev;
1205         struct ast_private *ast = to_ast_private(dev);
1206         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1207         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1208         struct ast_vbios_mode_info *vbios_mode_info =
1209                 &ast_crtc_state->vbios_mode_info;
1210         struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
1211
1212         ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
1213         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
1214         ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
1215         ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
1216         ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
1217         ast_set_crtthd_reg(ast);
1218         ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
1219
1220         ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
1221 }
1222
1223 static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1224 {
1225         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1226         struct drm_device *dev = crtc->dev;
1227         struct ast_private *ast = to_ast_private(dev);
1228
1229         ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1230
1231         /*
1232          * HW cursors require the underlying primary plane and CRTC to
1233          * display a valid mode and image. This is not the case during
1234          * full modeset operations. So we temporarily disable any active
1235          * plane, including the HW cursor. Each plane's atomic_update()
1236          * helper will re-enable it if necessary.
1237          *
1238          * We only do this during *full* modesets. It does not affect
1239          * simple pageflips on the planes.
1240          */
1241         drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
1242
1243         /*
1244          * Ensure that no scanout takes place before reprogramming mode
1245          * and format registers.
1246          */
1247         ast_wait_for_vretrace(ast);
1248 }
1249
1250 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
1251         .mode_valid = ast_crtc_helper_mode_valid,
1252         .atomic_check = ast_crtc_helper_atomic_check,
1253         .atomic_flush = ast_crtc_helper_atomic_flush,
1254         .atomic_enable = ast_crtc_helper_atomic_enable,
1255         .atomic_disable = ast_crtc_helper_atomic_disable,
1256 };
1257
1258 static void ast_crtc_reset(struct drm_crtc *crtc)
1259 {
1260         struct ast_crtc_state *ast_state =
1261                 kzalloc(sizeof(*ast_state), GFP_KERNEL);
1262
1263         if (crtc->state)
1264                 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
1265
1266         if (ast_state)
1267                 __drm_atomic_helper_crtc_reset(crtc, &ast_state->base);
1268         else
1269                 __drm_atomic_helper_crtc_reset(crtc, NULL);
1270 }
1271
1272 static struct drm_crtc_state *
1273 ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
1274 {
1275         struct ast_crtc_state *new_ast_state, *ast_state;
1276         struct drm_device *dev = crtc->dev;
1277
1278         if (drm_WARN_ON(dev, !crtc->state))
1279                 return NULL;
1280
1281         new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL);
1282         if (!new_ast_state)
1283                 return NULL;
1284         __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base);
1285
1286         ast_state = to_ast_crtc_state(crtc->state);
1287
1288         new_ast_state->format = ast_state->format;
1289         memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
1290                sizeof(new_ast_state->vbios_mode_info));
1291
1292         return &new_ast_state->base;
1293 }
1294
1295 static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
1296                                           struct drm_crtc_state *state)
1297 {
1298         struct ast_crtc_state *ast_state = to_ast_crtc_state(state);
1299
1300         __drm_atomic_helper_crtc_destroy_state(&ast_state->base);
1301         kfree(ast_state);
1302 }
1303
1304 static const struct drm_crtc_funcs ast_crtc_funcs = {
1305         .reset = ast_crtc_reset,
1306         .destroy = drm_crtc_cleanup,
1307         .set_config = drm_atomic_helper_set_config,
1308         .page_flip = drm_atomic_helper_page_flip,
1309         .atomic_duplicate_state = ast_crtc_atomic_duplicate_state,
1310         .atomic_destroy_state = ast_crtc_atomic_destroy_state,
1311 };
1312
1313 static int ast_crtc_init(struct drm_device *dev)
1314 {
1315         struct ast_private *ast = to_ast_private(dev);
1316         struct drm_crtc *crtc = &ast->crtc;
1317         int ret;
1318
1319         ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
1320                                         &ast->cursor_plane.base, &ast_crtc_funcs,
1321                                         NULL);
1322         if (ret)
1323                 return ret;
1324
1325         drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE);
1326         drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE);
1327
1328         drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
1329
1330         return 0;
1331 }
1332
1333 /*
1334  * VGA Connector
1335  */
1336
1337 static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
1338 {
1339         struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector);
1340         struct drm_device *dev = connector->dev;
1341         struct ast_private *ast = to_ast_private(dev);
1342         struct edid *edid;
1343         int count;
1344
1345         if (!ast_vga_connector->i2c)
1346                 goto err_drm_connector_update_edid_property;
1347
1348         /*
1349          * Protect access to I/O registers from concurrent modesetting
1350          * by acquiring the I/O-register lock.
1351          */
1352         mutex_lock(&ast->ioregs_lock);
1353
1354         edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter);
1355         if (!edid)
1356                 goto err_mutex_unlock;
1357
1358         mutex_unlock(&ast->ioregs_lock);
1359
1360         count = drm_add_edid_modes(connector, edid);
1361         kfree(edid);
1362
1363         return count;
1364
1365 err_mutex_unlock:
1366         mutex_unlock(&ast->ioregs_lock);
1367 err_drm_connector_update_edid_property:
1368         drm_connector_update_edid_property(connector, NULL);
1369         return 0;
1370 }
1371
1372 static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
1373         .get_modes = ast_vga_connector_helper_get_modes,
1374 };
1375
1376 static const struct drm_connector_funcs ast_vga_connector_funcs = {
1377         .reset = drm_atomic_helper_connector_reset,
1378         .fill_modes = drm_helper_probe_single_connector_modes,
1379         .destroy = drm_connector_cleanup,
1380         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1381         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1382 };
1383
1384 static int ast_vga_connector_init(struct drm_device *dev,
1385                                   struct ast_vga_connector *ast_vga_connector)
1386 {
1387         struct drm_connector *connector = &ast_vga_connector->base;
1388         int ret;
1389
1390         ast_vga_connector->i2c = ast_i2c_create(dev);
1391         if (!ast_vga_connector->i2c)
1392                 drm_err(dev, "failed to add ddc bus for connector\n");
1393
1394         if (ast_vga_connector->i2c)
1395                 ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,
1396                                                   DRM_MODE_CONNECTOR_VGA,
1397                                                   &ast_vga_connector->i2c->adapter);
1398         else
1399                 ret = drm_connector_init(dev, connector, &ast_vga_connector_funcs,
1400                                          DRM_MODE_CONNECTOR_VGA);
1401         if (ret)
1402                 return ret;
1403
1404         drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);
1405
1406         connector->interlace_allowed = 0;
1407         connector->doublescan_allowed = 0;
1408
1409         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1410
1411         return 0;
1412 }
1413
1414 static int ast_vga_output_init(struct ast_private *ast)
1415 {
1416         struct drm_device *dev = &ast->base;
1417         struct drm_crtc *crtc = &ast->crtc;
1418         struct drm_encoder *encoder = &ast->output.vga.encoder;
1419         struct ast_vga_connector *ast_vga_connector = &ast->output.vga.vga_connector;
1420         struct drm_connector *connector = &ast_vga_connector->base;
1421         int ret;
1422
1423         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
1424         if (ret)
1425                 return ret;
1426         encoder->possible_crtcs = drm_crtc_mask(crtc);
1427
1428         ret = ast_vga_connector_init(dev, ast_vga_connector);
1429         if (ret)
1430                 return ret;
1431
1432         ret = drm_connector_attach_encoder(connector, encoder);
1433         if (ret)
1434                 return ret;
1435
1436         return 0;
1437 }
1438
1439 /*
1440  * SIL164 Connector
1441  */
1442
1443 static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector)
1444 {
1445         struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector);
1446         struct drm_device *dev = connector->dev;
1447         struct ast_private *ast = to_ast_private(dev);
1448         struct edid *edid;
1449         int count;
1450
1451         if (!ast_sil164_connector->i2c)
1452                 goto err_drm_connector_update_edid_property;
1453
1454         /*
1455          * Protect access to I/O registers from concurrent modesetting
1456          * by acquiring the I/O-register lock.
1457          */
1458         mutex_lock(&ast->ioregs_lock);
1459
1460         edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter);
1461         if (!edid)
1462                 goto err_mutex_unlock;
1463
1464         mutex_unlock(&ast->ioregs_lock);
1465
1466         count = drm_add_edid_modes(connector, edid);
1467         kfree(edid);
1468
1469         return count;
1470
1471 err_mutex_unlock:
1472         mutex_unlock(&ast->ioregs_lock);
1473 err_drm_connector_update_edid_property:
1474         drm_connector_update_edid_property(connector, NULL);
1475         return 0;
1476 }
1477
1478 static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
1479         .get_modes = ast_sil164_connector_helper_get_modes,
1480 };
1481
1482 static const struct drm_connector_funcs ast_sil164_connector_funcs = {
1483         .reset = drm_atomic_helper_connector_reset,
1484         .fill_modes = drm_helper_probe_single_connector_modes,
1485         .destroy = drm_connector_cleanup,
1486         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1487         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1488 };
1489
1490 static int ast_sil164_connector_init(struct drm_device *dev,
1491                                      struct ast_sil164_connector *ast_sil164_connector)
1492 {
1493         struct drm_connector *connector = &ast_sil164_connector->base;
1494         int ret;
1495
1496         ast_sil164_connector->i2c = ast_i2c_create(dev);
1497         if (!ast_sil164_connector->i2c)
1498                 drm_err(dev, "failed to add ddc bus for connector\n");
1499
1500         if (ast_sil164_connector->i2c)
1501                 ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs,
1502                                                   DRM_MODE_CONNECTOR_DVII,
1503                                                   &ast_sil164_connector->i2c->adapter);
1504         else
1505                 ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs,
1506                                          DRM_MODE_CONNECTOR_DVII);
1507         if (ret)
1508                 return ret;
1509
1510         drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs);
1511
1512         connector->interlace_allowed = 0;
1513         connector->doublescan_allowed = 0;
1514
1515         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1516
1517         return 0;
1518 }
1519
1520 static int ast_sil164_output_init(struct ast_private *ast)
1521 {
1522         struct drm_device *dev = &ast->base;
1523         struct drm_crtc *crtc = &ast->crtc;
1524         struct drm_encoder *encoder = &ast->output.sil164.encoder;
1525         struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector;
1526         struct drm_connector *connector = &ast_sil164_connector->base;
1527         int ret;
1528
1529         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1530         if (ret)
1531                 return ret;
1532         encoder->possible_crtcs = drm_crtc_mask(crtc);
1533
1534         ret = ast_sil164_connector_init(dev, ast_sil164_connector);
1535         if (ret)
1536                 return ret;
1537
1538         ret = drm_connector_attach_encoder(connector, encoder);
1539         if (ret)
1540                 return ret;
1541
1542         return 0;
1543 }
1544
1545 /*
1546  * DP501 Connector
1547  */
1548
1549 static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
1550 {
1551         void *edid;
1552         bool succ;
1553         int count;
1554
1555         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1556         if (!edid)
1557                 goto err_drm_connector_update_edid_property;
1558
1559         succ = ast_dp501_read_edid(connector->dev, edid);
1560         if (!succ)
1561                 goto err_kfree;
1562
1563         drm_connector_update_edid_property(connector, edid);
1564         count = drm_add_edid_modes(connector, edid);
1565         kfree(edid);
1566
1567         return count;
1568
1569 err_kfree:
1570         kfree(edid);
1571 err_drm_connector_update_edid_property:
1572         drm_connector_update_edid_property(connector, NULL);
1573         return 0;
1574 }
1575
1576 static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
1577         .get_modes = ast_dp501_connector_helper_get_modes,
1578 };
1579
1580 static const struct drm_connector_funcs ast_dp501_connector_funcs = {
1581         .reset = drm_atomic_helper_connector_reset,
1582         .fill_modes = drm_helper_probe_single_connector_modes,
1583         .destroy = drm_connector_cleanup,
1584         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1585         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1586 };
1587
1588 static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)
1589 {
1590         int ret;
1591
1592         ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
1593                                  DRM_MODE_CONNECTOR_DisplayPort);
1594         if (ret)
1595                 return ret;
1596
1597         drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
1598
1599         connector->interlace_allowed = 0;
1600         connector->doublescan_allowed = 0;
1601
1602         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1603
1604         return 0;
1605 }
1606
1607 static int ast_dp501_output_init(struct ast_private *ast)
1608 {
1609         struct drm_device *dev = &ast->base;
1610         struct drm_crtc *crtc = &ast->crtc;
1611         struct drm_encoder *encoder = &ast->output.dp501.encoder;
1612         struct drm_connector *connector = &ast->output.dp501.connector;
1613         int ret;
1614
1615         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1616         if (ret)
1617                 return ret;
1618         encoder->possible_crtcs = drm_crtc_mask(crtc);
1619
1620         ret = ast_dp501_connector_init(dev, connector);
1621         if (ret)
1622                 return ret;
1623
1624         ret = drm_connector_attach_encoder(connector, encoder);
1625         if (ret)
1626                 return ret;
1627
1628         return 0;
1629 }
1630
1631 /*
1632  * ASPEED Display-Port Connector
1633  */
1634
1635 static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
1636 {
1637         void *edid;
1638
1639         int succ;
1640         int count;
1641
1642         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1643         if (!edid)
1644                 goto err_drm_connector_update_edid_property;
1645
1646         succ = ast_astdp_read_edid(connector->dev, edid);
1647         if (succ < 0)
1648                 goto err_kfree;
1649
1650         drm_connector_update_edid_property(connector, edid);
1651         count = drm_add_edid_modes(connector, edid);
1652         kfree(edid);
1653
1654         return count;
1655
1656 err_kfree:
1657         kfree(edid);
1658 err_drm_connector_update_edid_property:
1659         drm_connector_update_edid_property(connector, NULL);
1660         return 0;
1661 }
1662
1663 static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
1664         .get_modes = ast_astdp_connector_helper_get_modes,
1665 };
1666
1667 static const struct drm_connector_funcs ast_astdp_connector_funcs = {
1668         .reset = drm_atomic_helper_connector_reset,
1669         .fill_modes = drm_helper_probe_single_connector_modes,
1670         .destroy = drm_connector_cleanup,
1671         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1672         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1673 };
1674
1675 static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
1676 {
1677         int ret;
1678
1679         ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
1680                                  DRM_MODE_CONNECTOR_DisplayPort);
1681         if (ret)
1682                 return ret;
1683
1684         drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
1685
1686         connector->interlace_allowed = 0;
1687         connector->doublescan_allowed = 0;
1688
1689         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1690
1691         return 0;
1692 }
1693
1694 static int ast_astdp_output_init(struct ast_private *ast)
1695 {
1696         struct drm_device *dev = &ast->base;
1697         struct drm_crtc *crtc = &ast->crtc;
1698         struct drm_encoder *encoder = &ast->output.astdp.encoder;
1699         struct drm_connector *connector = &ast->output.astdp.connector;
1700         int ret;
1701
1702         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1703         if (ret)
1704                 return ret;
1705         encoder->possible_crtcs = drm_crtc_mask(crtc);
1706
1707         ret = ast_astdp_connector_init(dev, connector);
1708         if (ret)
1709                 return ret;
1710
1711         ret = drm_connector_attach_encoder(connector, encoder);
1712         if (ret)
1713                 return ret;
1714
1715         return 0;
1716 }
1717
1718 /*
1719  * Mode config
1720  */
1721
1722 static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
1723 {
1724         struct ast_private *ast = to_ast_private(state->dev);
1725
1726         /*
1727          * Concurrent operations could possibly trigger a call to
1728          * drm_connector_helper_funcs.get_modes by trying to read the
1729          * display modes. Protect access to I/O registers by acquiring
1730          * the I/O-register lock. Released in atomic_flush().
1731          */
1732         mutex_lock(&ast->ioregs_lock);
1733         drm_atomic_helper_commit_tail_rpm(state);
1734         mutex_unlock(&ast->ioregs_lock);
1735 }
1736
1737 static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {
1738         .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail,
1739 };
1740
1741 static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
1742                                                        const struct drm_display_mode *mode)
1743 {
1744         static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1745         struct ast_private *ast = to_ast_private(dev);
1746         unsigned long fbsize, fbpages, max_fbpages;
1747
1748         max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
1749
1750         fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
1751         fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
1752
1753         if (fbpages > max_fbpages)
1754                 return MODE_MEM;
1755
1756         return MODE_OK;
1757 }
1758
1759 static const struct drm_mode_config_funcs ast_mode_config_funcs = {
1760         .fb_create = drm_gem_fb_create_with_dirty,
1761         .mode_valid = ast_mode_config_mode_valid,
1762         .atomic_check = drm_atomic_helper_check,
1763         .atomic_commit = drm_atomic_helper_commit,
1764 };
1765
1766 int ast_mode_config_init(struct ast_private *ast)
1767 {
1768         struct drm_device *dev = &ast->base;
1769         int ret;
1770
1771         ret = drmm_mode_config_init(dev);
1772         if (ret)
1773                 return ret;
1774
1775         dev->mode_config.funcs = &ast_mode_config_funcs;
1776         dev->mode_config.min_width = 0;
1777         dev->mode_config.min_height = 0;
1778         dev->mode_config.preferred_depth = 24;
1779
1780         if (ast->chip == AST2100 ||
1781             ast->chip == AST2200 ||
1782             ast->chip == AST2300 ||
1783             ast->chip == AST2400 ||
1784             ast->chip == AST2500 ||
1785             ast->chip == AST2600) {
1786                 dev->mode_config.max_width = 1920;
1787                 dev->mode_config.max_height = 2048;
1788         } else {
1789                 dev->mode_config.max_width = 1600;
1790                 dev->mode_config.max_height = 1200;
1791         }
1792
1793         dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
1794
1795         ret = ast_primary_plane_init(ast);
1796         if (ret)
1797                 return ret;
1798
1799         ret = ast_cursor_plane_init(ast);
1800         if (ret)
1801                 return ret;
1802
1803         ast_crtc_init(dev);
1804
1805         if (ast->tx_chip_types & AST_TX_NONE_BIT) {
1806                 ret = ast_vga_output_init(ast);
1807                 if (ret)
1808                         return ret;
1809         }
1810         if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
1811                 ret = ast_sil164_output_init(ast);
1812                 if (ret)
1813                         return ret;
1814         }
1815         if (ast->tx_chip_types & AST_TX_DP501_BIT) {
1816                 ret = ast_dp501_output_init(ast);
1817                 if (ret)
1818                         return ret;
1819         }
1820         if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1821                 ret = ast_astdp_output_init(ast);
1822                 if (ret)
1823                         return ret;
1824         }
1825
1826         drm_mode_config_reset(dev);
1827
1828         return 0;
1829 }
This page took 0.137417 seconds and 4 git commands to generate.