]> Git Repo - linux.git/blob - drivers/gpu/drm/ast/ast_mode.c
Merge v6.5-rc1 into drm-misc-fixes
[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_device *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_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_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_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_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_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_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_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 ((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_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_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_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 ((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_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_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_device *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_device *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_device *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_device *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_device *ast = to_ast_device(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. This stalls display output for several
676          * seconds and makes the display unusable. Therefore only update
677          * the offset if it changes.
678          */
679         if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
680                 ast_set_offset_reg(ast, fb);
681 }
682
683 static void ast_primary_plane_helper_atomic_enable(struct drm_plane *plane,
684                                                    struct drm_atomic_state *state)
685 {
686         struct ast_device *ast = to_ast_device(plane->dev);
687         struct ast_plane *ast_plane = to_ast_plane(plane);
688
689         /*
690          * Some BMCs stop scanning out the video signal after the driver
691          * reprogrammed the scanout address. This stalls display
692          * output for several seconds and makes the display unusable.
693          * Therefore only reprogram the address after enabling the plane.
694          */
695         ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
696         ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
697 }
698
699 static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
700                                                     struct drm_atomic_state *state)
701 {
702         struct ast_device *ast = to_ast_device(plane->dev);
703
704         ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);
705 }
706
707 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
708         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
709         .atomic_check = ast_primary_plane_helper_atomic_check,
710         .atomic_update = ast_primary_plane_helper_atomic_update,
711         .atomic_enable = ast_primary_plane_helper_atomic_enable,
712         .atomic_disable = ast_primary_plane_helper_atomic_disable,
713 };
714
715 static const struct drm_plane_funcs ast_primary_plane_funcs = {
716         .update_plane = drm_atomic_helper_update_plane,
717         .disable_plane = drm_atomic_helper_disable_plane,
718         .destroy = drm_plane_cleanup,
719         DRM_GEM_SHADOW_PLANE_FUNCS,
720 };
721
722 static int ast_primary_plane_init(struct ast_device *ast)
723 {
724         struct drm_device *dev = &ast->base;
725         struct ast_plane *ast_primary_plane = &ast->primary_plane;
726         struct drm_plane *primary_plane = &ast_primary_plane->base;
727         void __iomem *vaddr = ast->vram;
728         u64 offset = 0; /* with shmem, the primary plane is always at offset 0 */
729         unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
730         unsigned long size = ast->vram_fb_available - cursor_size;
731         int ret;
732
733         ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size,
734                              0x01, &ast_primary_plane_funcs,
735                              ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats),
736                              NULL, DRM_PLANE_TYPE_PRIMARY);
737         if (ret) {
738                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
739                 return ret;
740         }
741         drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);
742         drm_plane_enable_fb_damage_clips(primary_plane);
743
744         return 0;
745 }
746
747 /*
748  * Cursor plane
749  */
750
751 static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height)
752 {
753         union {
754                 u32 ul;
755                 u8 b[4];
756         } srcdata32[2], data32;
757         union {
758                 u16 us;
759                 u8 b[2];
760         } data16;
761         u32 csum = 0;
762         s32 alpha_dst_delta, last_alpha_dst_delta;
763         u8 __iomem *dstxor;
764         const u8 *srcxor;
765         int i, j;
766         u32 per_pixel_copy, two_pixel_copy;
767
768         alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
769         last_alpha_dst_delta = alpha_dst_delta - (width << 1);
770
771         srcxor = src;
772         dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
773         per_pixel_copy = width & 1;
774         two_pixel_copy = width >> 1;
775
776         for (j = 0; j < height; j++) {
777                 for (i = 0; i < two_pixel_copy; i++) {
778                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
779                         srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
780                         data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
781                         data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
782                         data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
783                         data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
784
785                         writel(data32.ul, dstxor);
786                         csum += data32.ul;
787
788                         dstxor += 4;
789                         srcxor += 8;
790
791                 }
792
793                 for (i = 0; i < per_pixel_copy; i++) {
794                         srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
795                         data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
796                         data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
797                         writew(data16.us, dstxor);
798                         csum += (u32)data16.us;
799
800                         dstxor += 2;
801                         srcxor += 4;
802                 }
803                 dstxor += last_alpha_dst_delta;
804         }
805
806         /* write checksum + signature */
807         dst += AST_HWC_SIZE;
808         writel(csum, dst);
809         writel(width, dst + AST_HWC_SIGNATURE_SizeX);
810         writel(height, dst + AST_HWC_SIGNATURE_SizeY);
811         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
812         writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
813 }
814
815 static void ast_set_cursor_base(struct ast_device *ast, u64 address)
816 {
817         u8 addr0 = (address >> 3) & 0xff;
818         u8 addr1 = (address >> 11) & 0xff;
819         u8 addr2 = (address >> 19) & 0xff;
820
821         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0);
822         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1);
823         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
824 }
825
826 static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y,
827                                     u8 x_offset, u8 y_offset)
828 {
829         u8 x0 = (x & 0x00ff);
830         u8 x1 = (x & 0x0f00) >> 8;
831         u8 y0 = (y & 0x00ff);
832         u8 y1 = (y & 0x0700) >> 8;
833
834         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset);
835         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset);
836         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0);
837         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1);
838         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0);
839         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);
840 }
841
842 static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled)
843 {
844         static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
845                                      AST_IO_VGACRCB_HWC_ENABLED);
846
847         u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP;
848
849         if (enabled)
850                 vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED;
851
852         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, mask, vgacrcb);
853 }
854
855 static const uint32_t ast_cursor_plane_formats[] = {
856         DRM_FORMAT_ARGB8888,
857 };
858
859 static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
860                                                 struct drm_atomic_state *state)
861 {
862         struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
863         struct drm_framebuffer *new_fb = new_plane_state->fb;
864         struct drm_crtc_state *new_crtc_state = NULL;
865         int ret;
866
867         if (new_plane_state->crtc)
868                 new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
869
870         ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
871                                                   DRM_PLANE_NO_SCALING,
872                                                   DRM_PLANE_NO_SCALING,
873                                                   true, true);
874         if (ret || !new_plane_state->visible)
875                 return ret;
876
877         if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
878                 return -EINVAL;
879
880         return 0;
881 }
882
883 static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
884                                                   struct drm_atomic_state *state)
885 {
886         struct ast_plane *ast_plane = to_ast_plane(plane);
887         struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
888         struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
889         struct drm_framebuffer *fb = plane_state->fb;
890         struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
891         struct ast_device *ast = to_ast_device(plane->dev);
892         struct iosys_map src_map = shadow_plane_state->data[0];
893         struct drm_rect damage;
894         const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
895         u64 dst_off = ast_plane->offset;
896         u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
897         u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
898         unsigned int offset_x, offset_y;
899         u16 x, y;
900         u8 x_offset, y_offset;
901
902         /*
903          * Do data transfer to hardware buffer and point the scanout
904          * engine to the offset.
905          */
906
907         if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
908                 ast_update_cursor_image(dst, src, fb->width, fb->height);
909                 ast_set_cursor_base(ast, dst_off);
910         }
911
912         /*
913          * Update location in HWC signature and registers.
914          */
915
916         writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
917         writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
918
919         offset_x = AST_MAX_HWC_WIDTH - fb->width;
920         offset_y = AST_MAX_HWC_HEIGHT - fb->height;
921
922         if (plane_state->crtc_x < 0) {
923                 x_offset = (-plane_state->crtc_x) + offset_x;
924                 x = 0;
925         } else {
926                 x_offset = offset_x;
927                 x = plane_state->crtc_x;
928         }
929         if (plane_state->crtc_y < 0) {
930                 y_offset = (-plane_state->crtc_y) + offset_y;
931                 y = 0;
932         } else {
933                 y_offset = offset_y;
934                 y = plane_state->crtc_y;
935         }
936
937         ast_set_cursor_location(ast, x, y, x_offset, y_offset);
938
939         /* Dummy write to enable HWC and make the HW pick-up the changes. */
940         ast_set_cursor_enabled(ast, true);
941 }
942
943 static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
944                                                    struct drm_atomic_state *state)
945 {
946         struct ast_device *ast = to_ast_device(plane->dev);
947
948         ast_set_cursor_enabled(ast, false);
949 }
950
951 static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
952         DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
953         .atomic_check = ast_cursor_plane_helper_atomic_check,
954         .atomic_update = ast_cursor_plane_helper_atomic_update,
955         .atomic_disable = ast_cursor_plane_helper_atomic_disable,
956 };
957
958 static const struct drm_plane_funcs ast_cursor_plane_funcs = {
959         .update_plane = drm_atomic_helper_update_plane,
960         .disable_plane = drm_atomic_helper_disable_plane,
961         .destroy = drm_plane_cleanup,
962         DRM_GEM_SHADOW_PLANE_FUNCS,
963 };
964
965 static int ast_cursor_plane_init(struct ast_device *ast)
966 {
967         struct drm_device *dev = &ast->base;
968         struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
969         struct drm_plane *cursor_plane = &ast_cursor_plane->base;
970         size_t size;
971         void __iomem *vaddr;
972         u64 offset;
973         int ret;
974
975         /*
976          * Allocate backing storage for cursors. The BOs are permanently
977          * pinned to the top end of the VRAM.
978          */
979
980         size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
981
982         if (ast->vram_fb_available < size)
983                 return -ENOMEM;
984
985         vaddr = ast->vram + ast->vram_fb_available - size;
986         offset = ast->vram_fb_available - size;
987
988         ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
989                              0x01, &ast_cursor_plane_funcs,
990                              ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
991                              NULL, DRM_PLANE_TYPE_CURSOR);
992         if (ret) {
993                 drm_err(dev, "ast_plane_init() failed: %d\n", ret);
994                 return ret;
995         }
996         drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
997         drm_plane_enable_fb_damage_clips(cursor_plane);
998
999         ast->vram_fb_available -= size;
1000
1001         return 0;
1002 }
1003
1004 /*
1005  * CRTC
1006  */
1007
1008 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
1009 {
1010         struct ast_device *ast = to_ast_device(crtc->dev);
1011         u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
1012         struct ast_crtc_state *ast_state;
1013         const struct drm_format_info *format;
1014         struct ast_vbios_mode_info *vbios_mode_info;
1015
1016         /* TODO: Maybe control display signal generation with
1017          *       Sync Enable (bit CR17.7).
1018          */
1019         switch (mode) {
1020         case DRM_MODE_DPMS_ON:
1021                 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
1022                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
1023                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1024                         ast_set_dp501_video_output(crtc->dev, 1);
1025
1026                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1027                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
1028                         ast_wait_for_vretrace(ast);
1029                         ast_dp_set_on_off(crtc->dev, 1);
1030                 }
1031
1032                 ast_state = to_ast_crtc_state(crtc->state);
1033                 format = ast_state->format;
1034
1035                 if (format) {
1036                         vbios_mode_info = &ast_state->vbios_mode_info;
1037
1038                         ast_set_color_reg(ast, format);
1039                         ast_set_vbios_color_reg(ast, format, vbios_mode_info);
1040                         if (crtc->state->gamma_lut)
1041                                 ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
1042                         else
1043                                 ast_crtc_set_gamma_linear(ast, format);
1044                 }
1045                 break;
1046         case DRM_MODE_DPMS_STANDBY:
1047         case DRM_MODE_DPMS_SUSPEND:
1048         case DRM_MODE_DPMS_OFF:
1049                 ch = mode;
1050                 if (ast->tx_chip_types & AST_TX_DP501_BIT)
1051                         ast_set_dp501_video_output(crtc->dev, 0);
1052
1053                 if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1054                         ast_dp_set_on_off(crtc->dev, 0);
1055                         ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
1056                 }
1057
1058                 ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
1059                 ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
1060                 break;
1061         }
1062 }
1063
1064 static enum drm_mode_status
1065 ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
1066 {
1067         struct ast_device *ast = to_ast_device(crtc->dev);
1068         enum drm_mode_status status;
1069         uint32_t jtemp;
1070
1071         if (ast->support_wide_screen) {
1072                 if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050))
1073                         return MODE_OK;
1074                 if ((mode->hdisplay == 1280) && (mode->vdisplay == 800))
1075                         return MODE_OK;
1076                 if ((mode->hdisplay == 1440) && (mode->vdisplay == 900))
1077                         return MODE_OK;
1078                 if ((mode->hdisplay == 1360) && (mode->vdisplay == 768))
1079                         return MODE_OK;
1080                 if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
1081                         return MODE_OK;
1082                 if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
1083                         return MODE_OK;
1084
1085                 if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
1086                     (ast->chip == AST2300) || (ast->chip == AST2400) ||
1087                     (ast->chip == AST2500) || (ast->chip == AST2600)) {
1088                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
1089                                 return MODE_OK;
1090
1091                         if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) {
1092                                 jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
1093                                 if (jtemp & 0x01)
1094                                         return MODE_NOMODE;
1095                                 else
1096                                         return MODE_OK;
1097                         }
1098                 }
1099         }
1100
1101         status = MODE_NOMODE;
1102
1103         switch (mode->hdisplay) {
1104         case 640:
1105                 if (mode->vdisplay == 480)
1106                         status = MODE_OK;
1107                 break;
1108         case 800:
1109                 if (mode->vdisplay == 600)
1110                         status = MODE_OK;
1111                 break;
1112         case 1024:
1113                 if (mode->vdisplay == 768)
1114                         status = MODE_OK;
1115                 break;
1116         case 1152:
1117                 if (mode->vdisplay == 864)
1118                         status = MODE_OK;
1119                 break;
1120         case 1280:
1121                 if (mode->vdisplay == 1024)
1122                         status = MODE_OK;
1123                 break;
1124         case 1600:
1125                 if (mode->vdisplay == 1200)
1126                         status = MODE_OK;
1127                 break;
1128         default:
1129                 break;
1130         }
1131
1132         return status;
1133 }
1134
1135 static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
1136                                         struct drm_atomic_state *state)
1137 {
1138         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1139         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1140         struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
1141         struct drm_device *dev = crtc->dev;
1142         struct ast_crtc_state *ast_state;
1143         const struct drm_format_info *format;
1144         bool succ;
1145         int ret;
1146
1147         if (!crtc_state->enable)
1148                 return 0;
1149
1150         ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
1151         if (ret)
1152                 return ret;
1153
1154         ast_state = to_ast_crtc_state(crtc_state);
1155
1156         format = ast_state->format;
1157         if (drm_WARN_ON_ONCE(dev, !format))
1158                 return -EINVAL; /* BUG: We didn't set format in primary check(). */
1159
1160         /*
1161          * The gamma LUT has to be reloaded after changing the primary
1162          * plane's color format.
1163          */
1164         if (old_ast_crtc_state->format != format)
1165                 crtc_state->color_mgmt_changed = true;
1166
1167         if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
1168                 if (crtc_state->gamma_lut->length !=
1169                     AST_LUT_SIZE * sizeof(struct drm_color_lut)) {
1170                         drm_err(dev, "Wrong size for gamma_lut %zu\n",
1171                                 crtc_state->gamma_lut->length);
1172                         return -EINVAL;
1173                 }
1174         }
1175
1176         succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
1177                                        &crtc_state->adjusted_mode,
1178                                        &ast_state->vbios_mode_info);
1179         if (!succ)
1180                 return -EINVAL;
1181
1182         return 0;
1183 }
1184
1185 static void
1186 ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
1187                              struct drm_atomic_state *state)
1188 {
1189         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
1190                                                                           crtc);
1191         struct drm_device *dev = crtc->dev;
1192         struct ast_device *ast = to_ast_device(dev);
1193         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1194         struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
1195
1196         /*
1197          * The gamma LUT has to be reloaded after changing the primary
1198          * plane's color format.
1199          */
1200         if (crtc_state->enable && crtc_state->color_mgmt_changed) {
1201                 if (crtc_state->gamma_lut)
1202                         ast_crtc_set_gamma(ast,
1203                                            ast_crtc_state->format,
1204                                            crtc_state->gamma_lut->data);
1205                 else
1206                         ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
1207         }
1208
1209         //Set Aspeed Display-Port
1210         if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
1211                 ast_dp_set_mode(crtc, vbios_mode_info);
1212 }
1213
1214 static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1215 {
1216         struct drm_device *dev = crtc->dev;
1217         struct ast_device *ast = to_ast_device(dev);
1218         struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1219         struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
1220         struct ast_vbios_mode_info *vbios_mode_info =
1221                 &ast_crtc_state->vbios_mode_info;
1222         struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
1223
1224         ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
1225         ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
1226         ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
1227         ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
1228         ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
1229         ast_set_crtthd_reg(ast);
1230         ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
1231
1232         ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
1233 }
1234
1235 static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
1236 {
1237         struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
1238         struct drm_device *dev = crtc->dev;
1239         struct ast_device *ast = to_ast_device(dev);
1240
1241         ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
1242
1243         /*
1244          * HW cursors require the underlying primary plane and CRTC to
1245          * display a valid mode and image. This is not the case during
1246          * full modeset operations. So we temporarily disable any active
1247          * plane, including the HW cursor. Each plane's atomic_update()
1248          * helper will re-enable it if necessary.
1249          *
1250          * We only do this during *full* modesets. It does not affect
1251          * simple pageflips on the planes.
1252          */
1253         drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
1254
1255         /*
1256          * Ensure that no scanout takes place before reprogramming mode
1257          * and format registers.
1258          */
1259         ast_wait_for_vretrace(ast);
1260 }
1261
1262 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
1263         .mode_valid = ast_crtc_helper_mode_valid,
1264         .atomic_check = ast_crtc_helper_atomic_check,
1265         .atomic_flush = ast_crtc_helper_atomic_flush,
1266         .atomic_enable = ast_crtc_helper_atomic_enable,
1267         .atomic_disable = ast_crtc_helper_atomic_disable,
1268 };
1269
1270 static void ast_crtc_reset(struct drm_crtc *crtc)
1271 {
1272         struct ast_crtc_state *ast_state =
1273                 kzalloc(sizeof(*ast_state), GFP_KERNEL);
1274
1275         if (crtc->state)
1276                 crtc->funcs->atomic_destroy_state(crtc, crtc->state);
1277
1278         if (ast_state)
1279                 __drm_atomic_helper_crtc_reset(crtc, &ast_state->base);
1280         else
1281                 __drm_atomic_helper_crtc_reset(crtc, NULL);
1282 }
1283
1284 static struct drm_crtc_state *
1285 ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
1286 {
1287         struct ast_crtc_state *new_ast_state, *ast_state;
1288         struct drm_device *dev = crtc->dev;
1289
1290         if (drm_WARN_ON(dev, !crtc->state))
1291                 return NULL;
1292
1293         new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL);
1294         if (!new_ast_state)
1295                 return NULL;
1296         __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base);
1297
1298         ast_state = to_ast_crtc_state(crtc->state);
1299
1300         new_ast_state->format = ast_state->format;
1301         memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
1302                sizeof(new_ast_state->vbios_mode_info));
1303
1304         return &new_ast_state->base;
1305 }
1306
1307 static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
1308                                           struct drm_crtc_state *state)
1309 {
1310         struct ast_crtc_state *ast_state = to_ast_crtc_state(state);
1311
1312         __drm_atomic_helper_crtc_destroy_state(&ast_state->base);
1313         kfree(ast_state);
1314 }
1315
1316 static const struct drm_crtc_funcs ast_crtc_funcs = {
1317         .reset = ast_crtc_reset,
1318         .destroy = drm_crtc_cleanup,
1319         .set_config = drm_atomic_helper_set_config,
1320         .page_flip = drm_atomic_helper_page_flip,
1321         .atomic_duplicate_state = ast_crtc_atomic_duplicate_state,
1322         .atomic_destroy_state = ast_crtc_atomic_destroy_state,
1323 };
1324
1325 static int ast_crtc_init(struct drm_device *dev)
1326 {
1327         struct ast_device *ast = to_ast_device(dev);
1328         struct drm_crtc *crtc = &ast->crtc;
1329         int ret;
1330
1331         ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
1332                                         &ast->cursor_plane.base, &ast_crtc_funcs,
1333                                         NULL);
1334         if (ret)
1335                 return ret;
1336
1337         drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE);
1338         drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE);
1339
1340         drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
1341
1342         return 0;
1343 }
1344
1345 /*
1346  * VGA Connector
1347  */
1348
1349 static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)
1350 {
1351         struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector);
1352         struct drm_device *dev = connector->dev;
1353         struct ast_device *ast = to_ast_device(dev);
1354         struct edid *edid;
1355         int count;
1356
1357         if (!ast_vga_connector->i2c)
1358                 goto err_drm_connector_update_edid_property;
1359
1360         /*
1361          * Protect access to I/O registers from concurrent modesetting
1362          * by acquiring the I/O-register lock.
1363          */
1364         mutex_lock(&ast->ioregs_lock);
1365
1366         edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter);
1367         if (!edid)
1368                 goto err_mutex_unlock;
1369
1370         mutex_unlock(&ast->ioregs_lock);
1371
1372         count = drm_add_edid_modes(connector, edid);
1373         kfree(edid);
1374
1375         return count;
1376
1377 err_mutex_unlock:
1378         mutex_unlock(&ast->ioregs_lock);
1379 err_drm_connector_update_edid_property:
1380         drm_connector_update_edid_property(connector, NULL);
1381         return 0;
1382 }
1383
1384 static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {
1385         .get_modes = ast_vga_connector_helper_get_modes,
1386 };
1387
1388 static const struct drm_connector_funcs ast_vga_connector_funcs = {
1389         .reset = drm_atomic_helper_connector_reset,
1390         .fill_modes = drm_helper_probe_single_connector_modes,
1391         .destroy = drm_connector_cleanup,
1392         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1393         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1394 };
1395
1396 static int ast_vga_connector_init(struct drm_device *dev,
1397                                   struct ast_vga_connector *ast_vga_connector)
1398 {
1399         struct drm_connector *connector = &ast_vga_connector->base;
1400         int ret;
1401
1402         ast_vga_connector->i2c = ast_i2c_create(dev);
1403         if (!ast_vga_connector->i2c)
1404                 drm_err(dev, "failed to add ddc bus for connector\n");
1405
1406         if (ast_vga_connector->i2c)
1407                 ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,
1408                                                   DRM_MODE_CONNECTOR_VGA,
1409                                                   &ast_vga_connector->i2c->adapter);
1410         else
1411                 ret = drm_connector_init(dev, connector, &ast_vga_connector_funcs,
1412                                          DRM_MODE_CONNECTOR_VGA);
1413         if (ret)
1414                 return ret;
1415
1416         drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);
1417
1418         connector->interlace_allowed = 0;
1419         connector->doublescan_allowed = 0;
1420
1421         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1422
1423         return 0;
1424 }
1425
1426 static int ast_vga_output_init(struct ast_device *ast)
1427 {
1428         struct drm_device *dev = &ast->base;
1429         struct drm_crtc *crtc = &ast->crtc;
1430         struct drm_encoder *encoder = &ast->output.vga.encoder;
1431         struct ast_vga_connector *ast_vga_connector = &ast->output.vga.vga_connector;
1432         struct drm_connector *connector = &ast_vga_connector->base;
1433         int ret;
1434
1435         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DAC);
1436         if (ret)
1437                 return ret;
1438         encoder->possible_crtcs = drm_crtc_mask(crtc);
1439
1440         ret = ast_vga_connector_init(dev, ast_vga_connector);
1441         if (ret)
1442                 return ret;
1443
1444         ret = drm_connector_attach_encoder(connector, encoder);
1445         if (ret)
1446                 return ret;
1447
1448         return 0;
1449 }
1450
1451 /*
1452  * SIL164 Connector
1453  */
1454
1455 static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector)
1456 {
1457         struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector);
1458         struct drm_device *dev = connector->dev;
1459         struct ast_device *ast = to_ast_device(dev);
1460         struct edid *edid;
1461         int count;
1462
1463         if (!ast_sil164_connector->i2c)
1464                 goto err_drm_connector_update_edid_property;
1465
1466         /*
1467          * Protect access to I/O registers from concurrent modesetting
1468          * by acquiring the I/O-register lock.
1469          */
1470         mutex_lock(&ast->ioregs_lock);
1471
1472         edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter);
1473         if (!edid)
1474                 goto err_mutex_unlock;
1475
1476         mutex_unlock(&ast->ioregs_lock);
1477
1478         count = drm_add_edid_modes(connector, edid);
1479         kfree(edid);
1480
1481         return count;
1482
1483 err_mutex_unlock:
1484         mutex_unlock(&ast->ioregs_lock);
1485 err_drm_connector_update_edid_property:
1486         drm_connector_update_edid_property(connector, NULL);
1487         return 0;
1488 }
1489
1490 static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = {
1491         .get_modes = ast_sil164_connector_helper_get_modes,
1492 };
1493
1494 static const struct drm_connector_funcs ast_sil164_connector_funcs = {
1495         .reset = drm_atomic_helper_connector_reset,
1496         .fill_modes = drm_helper_probe_single_connector_modes,
1497         .destroy = drm_connector_cleanup,
1498         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1499         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1500 };
1501
1502 static int ast_sil164_connector_init(struct drm_device *dev,
1503                                      struct ast_sil164_connector *ast_sil164_connector)
1504 {
1505         struct drm_connector *connector = &ast_sil164_connector->base;
1506         int ret;
1507
1508         ast_sil164_connector->i2c = ast_i2c_create(dev);
1509         if (!ast_sil164_connector->i2c)
1510                 drm_err(dev, "failed to add ddc bus for connector\n");
1511
1512         if (ast_sil164_connector->i2c)
1513                 ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs,
1514                                                   DRM_MODE_CONNECTOR_DVII,
1515                                                   &ast_sil164_connector->i2c->adapter);
1516         else
1517                 ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs,
1518                                          DRM_MODE_CONNECTOR_DVII);
1519         if (ret)
1520                 return ret;
1521
1522         drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs);
1523
1524         connector->interlace_allowed = 0;
1525         connector->doublescan_allowed = 0;
1526
1527         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1528
1529         return 0;
1530 }
1531
1532 static int ast_sil164_output_init(struct ast_device *ast)
1533 {
1534         struct drm_device *dev = &ast->base;
1535         struct drm_crtc *crtc = &ast->crtc;
1536         struct drm_encoder *encoder = &ast->output.sil164.encoder;
1537         struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector;
1538         struct drm_connector *connector = &ast_sil164_connector->base;
1539         int ret;
1540
1541         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1542         if (ret)
1543                 return ret;
1544         encoder->possible_crtcs = drm_crtc_mask(crtc);
1545
1546         ret = ast_sil164_connector_init(dev, ast_sil164_connector);
1547         if (ret)
1548                 return ret;
1549
1550         ret = drm_connector_attach_encoder(connector, encoder);
1551         if (ret)
1552                 return ret;
1553
1554         return 0;
1555 }
1556
1557 /*
1558  * DP501 Connector
1559  */
1560
1561 static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector)
1562 {
1563         void *edid;
1564         bool succ;
1565         int count;
1566
1567         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1568         if (!edid)
1569                 goto err_drm_connector_update_edid_property;
1570
1571         succ = ast_dp501_read_edid(connector->dev, edid);
1572         if (!succ)
1573                 goto err_kfree;
1574
1575         drm_connector_update_edid_property(connector, edid);
1576         count = drm_add_edid_modes(connector, edid);
1577         kfree(edid);
1578
1579         return count;
1580
1581 err_kfree:
1582         kfree(edid);
1583 err_drm_connector_update_edid_property:
1584         drm_connector_update_edid_property(connector, NULL);
1585         return 0;
1586 }
1587
1588 static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = {
1589         .get_modes = ast_dp501_connector_helper_get_modes,
1590 };
1591
1592 static const struct drm_connector_funcs ast_dp501_connector_funcs = {
1593         .reset = drm_atomic_helper_connector_reset,
1594         .fill_modes = drm_helper_probe_single_connector_modes,
1595         .destroy = drm_connector_cleanup,
1596         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1597         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1598 };
1599
1600 static int ast_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector)
1601 {
1602         int ret;
1603
1604         ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs,
1605                                  DRM_MODE_CONNECTOR_DisplayPort);
1606         if (ret)
1607                 return ret;
1608
1609         drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs);
1610
1611         connector->interlace_allowed = 0;
1612         connector->doublescan_allowed = 0;
1613
1614         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1615
1616         return 0;
1617 }
1618
1619 static int ast_dp501_output_init(struct ast_device *ast)
1620 {
1621         struct drm_device *dev = &ast->base;
1622         struct drm_crtc *crtc = &ast->crtc;
1623         struct drm_encoder *encoder = &ast->output.dp501.encoder;
1624         struct drm_connector *connector = &ast->output.dp501.connector;
1625         int ret;
1626
1627         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1628         if (ret)
1629                 return ret;
1630         encoder->possible_crtcs = drm_crtc_mask(crtc);
1631
1632         ret = ast_dp501_connector_init(dev, connector);
1633         if (ret)
1634                 return ret;
1635
1636         ret = drm_connector_attach_encoder(connector, encoder);
1637         if (ret)
1638                 return ret;
1639
1640         return 0;
1641 }
1642
1643 /*
1644  * ASPEED Display-Port Connector
1645  */
1646
1647 static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
1648 {
1649         void *edid;
1650         struct drm_device *dev = connector->dev;
1651         struct ast_device *ast = to_ast_device(dev);
1652
1653         int succ;
1654         int count;
1655
1656         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
1657         if (!edid)
1658                 goto err_drm_connector_update_edid_property;
1659
1660         /*
1661          * Protect access to I/O registers from concurrent modesetting
1662          * by acquiring the I/O-register lock.
1663          */
1664         mutex_lock(&ast->ioregs_lock);
1665
1666         succ = ast_astdp_read_edid(connector->dev, edid);
1667         if (succ < 0)
1668                 goto err_mutex_unlock;
1669
1670         mutex_unlock(&ast->ioregs_lock);
1671
1672         drm_connector_update_edid_property(connector, edid);
1673         count = drm_add_edid_modes(connector, edid);
1674         kfree(edid);
1675
1676         return count;
1677
1678 err_mutex_unlock:
1679         mutex_unlock(&ast->ioregs_lock);
1680         kfree(edid);
1681 err_drm_connector_update_edid_property:
1682         drm_connector_update_edid_property(connector, NULL);
1683         return 0;
1684 }
1685
1686 static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
1687         .get_modes = ast_astdp_connector_helper_get_modes,
1688 };
1689
1690 static const struct drm_connector_funcs ast_astdp_connector_funcs = {
1691         .reset = drm_atomic_helper_connector_reset,
1692         .fill_modes = drm_helper_probe_single_connector_modes,
1693         .destroy = drm_connector_cleanup,
1694         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1695         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1696 };
1697
1698 static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
1699 {
1700         int ret;
1701
1702         ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
1703                                  DRM_MODE_CONNECTOR_DisplayPort);
1704         if (ret)
1705                 return ret;
1706
1707         drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
1708
1709         connector->interlace_allowed = 0;
1710         connector->doublescan_allowed = 0;
1711
1712         connector->polled = DRM_CONNECTOR_POLL_CONNECT;
1713
1714         return 0;
1715 }
1716
1717 static int ast_astdp_output_init(struct ast_device *ast)
1718 {
1719         struct drm_device *dev = &ast->base;
1720         struct drm_crtc *crtc = &ast->crtc;
1721         struct drm_encoder *encoder = &ast->output.astdp.encoder;
1722         struct drm_connector *connector = &ast->output.astdp.connector;
1723         int ret;
1724
1725         ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
1726         if (ret)
1727                 return ret;
1728         encoder->possible_crtcs = drm_crtc_mask(crtc);
1729
1730         ret = ast_astdp_connector_init(dev, connector);
1731         if (ret)
1732                 return ret;
1733
1734         ret = drm_connector_attach_encoder(connector, encoder);
1735         if (ret)
1736                 return ret;
1737
1738         return 0;
1739 }
1740
1741 /*
1742  * Mode config
1743  */
1744
1745 static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
1746 {
1747         struct ast_device *ast = to_ast_device(state->dev);
1748
1749         /*
1750          * Concurrent operations could possibly trigger a call to
1751          * drm_connector_helper_funcs.get_modes by trying to read the
1752          * display modes. Protect access to I/O registers by acquiring
1753          * the I/O-register lock. Released in atomic_flush().
1754          */
1755         mutex_lock(&ast->ioregs_lock);
1756         drm_atomic_helper_commit_tail_rpm(state);
1757         mutex_unlock(&ast->ioregs_lock);
1758 }
1759
1760 static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {
1761         .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail,
1762 };
1763
1764 static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
1765                                                        const struct drm_display_mode *mode)
1766 {
1767         static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1768         struct ast_device *ast = to_ast_device(dev);
1769         unsigned long fbsize, fbpages, max_fbpages;
1770
1771         max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
1772
1773         fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
1774         fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
1775
1776         if (fbpages > max_fbpages)
1777                 return MODE_MEM;
1778
1779         return MODE_OK;
1780 }
1781
1782 static const struct drm_mode_config_funcs ast_mode_config_funcs = {
1783         .fb_create = drm_gem_fb_create_with_dirty,
1784         .mode_valid = ast_mode_config_mode_valid,
1785         .atomic_check = drm_atomic_helper_check,
1786         .atomic_commit = drm_atomic_helper_commit,
1787 };
1788
1789 int ast_mode_config_init(struct ast_device *ast)
1790 {
1791         struct drm_device *dev = &ast->base;
1792         int ret;
1793
1794         ret = drmm_mode_config_init(dev);
1795         if (ret)
1796                 return ret;
1797
1798         dev->mode_config.funcs = &ast_mode_config_funcs;
1799         dev->mode_config.min_width = 0;
1800         dev->mode_config.min_height = 0;
1801         dev->mode_config.preferred_depth = 24;
1802
1803         if (ast->chip == AST2100 ||
1804             ast->chip == AST2200 ||
1805             ast->chip == AST2300 ||
1806             ast->chip == AST2400 ||
1807             ast->chip == AST2500 ||
1808             ast->chip == AST2600) {
1809                 dev->mode_config.max_width = 1920;
1810                 dev->mode_config.max_height = 2048;
1811         } else {
1812                 dev->mode_config.max_width = 1600;
1813                 dev->mode_config.max_height = 1200;
1814         }
1815
1816         dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
1817
1818         ret = ast_primary_plane_init(ast);
1819         if (ret)
1820                 return ret;
1821
1822         ret = ast_cursor_plane_init(ast);
1823         if (ret)
1824                 return ret;
1825
1826         ast_crtc_init(dev);
1827
1828         if (ast->tx_chip_types & AST_TX_NONE_BIT) {
1829                 ret = ast_vga_output_init(ast);
1830                 if (ret)
1831                         return ret;
1832         }
1833         if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
1834                 ret = ast_sil164_output_init(ast);
1835                 if (ret)
1836                         return ret;
1837         }
1838         if (ast->tx_chip_types & AST_TX_DP501_BIT) {
1839                 ret = ast_dp501_output_init(ast);
1840                 if (ret)
1841                         return ret;
1842         }
1843         if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
1844                 ret = ast_astdp_output_init(ast);
1845                 if (ret)
1846                         return ret;
1847         }
1848
1849         drm_mode_config_reset(dev);
1850
1851         return 0;
1852 }
This page took 0.147946 seconds and 4 git commands to generate.