2 * Copyright 2012 Red Hat Inc.
3 * Parts based on xf86-video-ast
4 * Copyright (c) 2005 ASPEED Technology Inc.
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:
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.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
28 * Authors: Dave Airlie <airlied@redhat.com>
31 #include <linux/export.h>
32 #include <linux/pci.h>
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_crtc_helper.h>
39 #include <drm/drm_fourcc.h>
40 #include <drm/drm_gem_framebuffer_helper.h>
41 #include <drm/drm_gem_vram_helper.h>
42 #include <drm/drm_plane_helper.h>
43 #include <drm/drm_probe_helper.h>
44 #include <drm/drm_simple_kms_helper.h>
47 #include "ast_tables.h"
49 static struct ast_i2c_chan
*ast_i2c_create(struct drm_device
*dev
);
50 static void ast_i2c_destroy(struct ast_i2c_chan
*i2c
);
52 static inline void ast_load_palette_index(struct ast_private
*ast
,
53 u8 index
, u8 red
, u8 green
,
56 ast_io_write8(ast
, AST_IO_DAC_INDEX_WRITE
, index
);
57 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
58 ast_io_write8(ast
, AST_IO_DAC_DATA
, red
);
59 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
60 ast_io_write8(ast
, AST_IO_DAC_DATA
, green
);
61 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
62 ast_io_write8(ast
, AST_IO_DAC_DATA
, blue
);
63 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
66 static void ast_crtc_load_lut(struct ast_private
*ast
, struct drm_crtc
*crtc
)
74 r
= crtc
->gamma_store
;
75 g
= r
+ crtc
->gamma_size
;
76 b
= g
+ crtc
->gamma_size
;
78 for (i
= 0; i
< 256; i
++)
79 ast_load_palette_index(ast
, i
, *r
++ >> 8, *g
++ >> 8, *b
++ >> 8);
82 static bool ast_get_vbios_mode_info(const struct drm_format_info
*format
,
83 const struct drm_display_mode
*mode
,
84 struct drm_display_mode
*adjusted_mode
,
85 struct ast_vbios_mode_info
*vbios_mode
)
87 u32 refresh_rate_index
= 0, refresh_rate
;
88 const struct ast_vbios_enhtable
*best
= NULL
;
92 switch (format
->cpp
[0] * 8) {
94 vbios_mode
->std_table
= &vbios_stdtable
[VGAModeIndex
];
97 vbios_mode
->std_table
= &vbios_stdtable
[HiCModeIndex
];
101 vbios_mode
->std_table
= &vbios_stdtable
[TrueCModeIndex
];
107 switch (mode
->crtc_hdisplay
) {
109 vbios_mode
->enh_table
= &res_640x480
[refresh_rate_index
];
112 vbios_mode
->enh_table
= &res_800x600
[refresh_rate_index
];
115 vbios_mode
->enh_table
= &res_1024x768
[refresh_rate_index
];
118 if (mode
->crtc_vdisplay
== 800)
119 vbios_mode
->enh_table
= &res_1280x800
[refresh_rate_index
];
121 vbios_mode
->enh_table
= &res_1280x1024
[refresh_rate_index
];
124 vbios_mode
->enh_table
= &res_1360x768
[refresh_rate_index
];
127 vbios_mode
->enh_table
= &res_1440x900
[refresh_rate_index
];
130 if (mode
->crtc_vdisplay
== 900)
131 vbios_mode
->enh_table
= &res_1600x900
[refresh_rate_index
];
133 vbios_mode
->enh_table
= &res_1600x1200
[refresh_rate_index
];
136 vbios_mode
->enh_table
= &res_1680x1050
[refresh_rate_index
];
139 if (mode
->crtc_vdisplay
== 1080)
140 vbios_mode
->enh_table
= &res_1920x1080
[refresh_rate_index
];
142 vbios_mode
->enh_table
= &res_1920x1200
[refresh_rate_index
];
148 refresh_rate
= drm_mode_vrefresh(mode
);
149 check_sync
= vbios_mode
->enh_table
->flags
& WideScreenMode
;
152 const struct ast_vbios_enhtable
*loop
= vbios_mode
->enh_table
;
154 while (loop
->refresh_rate
!= 0xff) {
156 (((mode
->flags
& DRM_MODE_FLAG_NVSYNC
) &&
157 (loop
->flags
& PVSync
)) ||
158 ((mode
->flags
& DRM_MODE_FLAG_PVSYNC
) &&
159 (loop
->flags
& NVSync
)) ||
160 ((mode
->flags
& DRM_MODE_FLAG_NHSYNC
) &&
161 (loop
->flags
& PHSync
)) ||
162 ((mode
->flags
& DRM_MODE_FLAG_PHSYNC
) &&
163 (loop
->flags
& NHSync
)))) {
167 if (loop
->refresh_rate
<= refresh_rate
168 && (!best
|| loop
->refresh_rate
> best
->refresh_rate
))
172 if (best
|| !check_sync
)
178 vbios_mode
->enh_table
= best
;
180 hborder
= (vbios_mode
->enh_table
->flags
& HBorder
) ? 8 : 0;
181 vborder
= (vbios_mode
->enh_table
->flags
& VBorder
) ? 8 : 0;
183 adjusted_mode
->crtc_htotal
= vbios_mode
->enh_table
->ht
;
184 adjusted_mode
->crtc_hblank_start
= vbios_mode
->enh_table
->hde
+ hborder
;
185 adjusted_mode
->crtc_hblank_end
= vbios_mode
->enh_table
->ht
- hborder
;
186 adjusted_mode
->crtc_hsync_start
= vbios_mode
->enh_table
->hde
+ hborder
+
187 vbios_mode
->enh_table
->hfp
;
188 adjusted_mode
->crtc_hsync_end
= (vbios_mode
->enh_table
->hde
+ hborder
+
189 vbios_mode
->enh_table
->hfp
+
190 vbios_mode
->enh_table
->hsync
);
192 adjusted_mode
->crtc_vtotal
= vbios_mode
->enh_table
->vt
;
193 adjusted_mode
->crtc_vblank_start
= vbios_mode
->enh_table
->vde
+ vborder
;
194 adjusted_mode
->crtc_vblank_end
= vbios_mode
->enh_table
->vt
- vborder
;
195 adjusted_mode
->crtc_vsync_start
= vbios_mode
->enh_table
->vde
+ vborder
+
196 vbios_mode
->enh_table
->vfp
;
197 adjusted_mode
->crtc_vsync_end
= (vbios_mode
->enh_table
->vde
+ vborder
+
198 vbios_mode
->enh_table
->vfp
+
199 vbios_mode
->enh_table
->vsync
);
204 static void ast_set_vbios_color_reg(struct ast_private
*ast
,
205 const struct drm_format_info
*format
,
206 const struct ast_vbios_mode_info
*vbios_mode
)
210 switch (format
->cpp
[0]) {
212 color_index
= VGAModeIndex
- 1;
215 color_index
= HiCModeIndex
;
219 color_index
= TrueCModeIndex
;
225 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8c, (u8
)((color_index
& 0x0f) << 4));
227 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0x00);
229 if (vbios_mode
->enh_table
->flags
& NewModeInfo
) {
230 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0xa8);
231 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x92, format
->cpp
[0] * 8);
235 static void ast_set_vbios_mode_reg(struct ast_private
*ast
,
236 const struct drm_display_mode
*adjusted_mode
,
237 const struct ast_vbios_mode_info
*vbios_mode
)
239 u32 refresh_rate_index
, mode_id
;
241 refresh_rate_index
= vbios_mode
->enh_table
->refresh_rate_index
;
242 mode_id
= vbios_mode
->enh_table
->mode_id
;
244 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8d, refresh_rate_index
& 0xff);
245 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8e, mode_id
& 0xff);
247 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0x00);
249 if (vbios_mode
->enh_table
->flags
& NewModeInfo
) {
250 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0xa8);
251 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x93, adjusted_mode
->clock
/ 1000);
252 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x94, adjusted_mode
->crtc_hdisplay
);
253 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x95, adjusted_mode
->crtc_hdisplay
>> 8);
254 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x96, adjusted_mode
->crtc_vdisplay
);
255 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x97, adjusted_mode
->crtc_vdisplay
>> 8);
259 static void ast_set_std_reg(struct ast_private
*ast
,
260 struct drm_display_mode
*mode
,
261 struct ast_vbios_mode_info
*vbios_mode
)
263 const struct ast_vbios_stdtable
*stdtable
;
267 stdtable
= vbios_mode
->std_table
;
269 jreg
= stdtable
->misc
;
270 ast_io_write8(ast
, AST_IO_MISC_PORT_WRITE
, jreg
);
272 /* Set SEQ; except Screen Disable field */
273 ast_set_index_reg(ast
, AST_IO_SEQ_PORT
, 0x00, 0x03);
274 ast_set_index_reg_mask(ast
, AST_IO_SEQ_PORT
, 0x01, 0xdf, stdtable
->seq
[0]);
275 for (i
= 1; i
< 4; i
++) {
276 jreg
= stdtable
->seq
[i
];
277 ast_set_index_reg(ast
, AST_IO_SEQ_PORT
, (i
+ 1) , jreg
);
280 /* Set CRTC; except base address and offset */
281 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x00);
282 for (i
= 0; i
< 12; i
++)
283 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, i
, stdtable
->crtc
[i
]);
284 for (i
= 14; i
< 19; i
++)
285 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, i
, stdtable
->crtc
[i
]);
286 for (i
= 20; i
< 25; i
++)
287 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, i
, stdtable
->crtc
[i
]);
290 jreg
= ast_io_read8(ast
, AST_IO_INPUT_STATUS1_READ
);
291 for (i
= 0; i
< 20; i
++) {
292 jreg
= stdtable
->ar
[i
];
293 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, (u8
)i
);
294 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, jreg
);
296 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x14);
297 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x00);
299 jreg
= ast_io_read8(ast
, AST_IO_INPUT_STATUS1_READ
);
300 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x20);
303 for (i
= 0; i
< 9; i
++)
304 ast_set_index_reg(ast
, AST_IO_GR_PORT
, i
, stdtable
->gr
[i
]);
307 static void ast_set_crtc_reg(struct ast_private
*ast
,
308 struct drm_display_mode
*mode
,
309 struct ast_vbios_mode_info
*vbios_mode
)
311 u8 jreg05
= 0, jreg07
= 0, jreg09
= 0, jregAC
= 0, jregAD
= 0, jregAE
= 0;
312 u16 temp
, precache
= 0;
314 if ((ast
->chip
== AST2500
) &&
315 (vbios_mode
->enh_table
->flags
& AST2500PreCatchCRT
))
318 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x00);
320 temp
= (mode
->crtc_htotal
>> 3) - 5;
322 jregAC
|= 0x01; /* HT D[8] */
323 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x00, 0x00, temp
);
325 temp
= (mode
->crtc_hdisplay
>> 3) - 1;
327 jregAC
|= 0x04; /* HDE D[8] */
328 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x01, 0x00, temp
);
330 temp
= (mode
->crtc_hblank_start
>> 3) - 1;
332 jregAC
|= 0x10; /* HBS D[8] */
333 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x02, 0x00, temp
);
335 temp
= ((mode
->crtc_hblank_end
>> 3) - 1) & 0x7f;
337 jreg05
|= 0x80; /* HBE D[5] */
339 jregAD
|= 0x01; /* HBE D[5] */
340 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x03, 0xE0, (temp
& 0x1f));
342 temp
= ((mode
->crtc_hsync_start
-precache
) >> 3) - 1;
344 jregAC
|= 0x40; /* HRS D[5] */
345 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x04, 0x00, temp
);
347 temp
= (((mode
->crtc_hsync_end
-precache
) >> 3) - 1) & 0x3f;
349 jregAD
|= 0x04; /* HRE D[5] */
350 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x05, 0x60, (u8
)((temp
& 0x1f) | jreg05
));
352 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAC, 0x00, jregAC
);
353 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAD, 0x00, jregAD
);
356 temp
= (mode
->crtc_vtotal
) - 2;
363 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x06, 0x00, temp
);
365 temp
= (mode
->crtc_vsync_start
) - 1;
372 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x10, 0x00, temp
);
374 temp
= (mode
->crtc_vsync_end
- 1) & 0x3f;
379 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x70, temp
& 0xf);
381 temp
= mode
->crtc_vdisplay
- 1;
388 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x12, 0x00, temp
);
390 temp
= mode
->crtc_vblank_start
- 1;
397 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x15, 0x00, temp
);
399 temp
= mode
->crtc_vblank_end
- 1;
402 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x16, 0x00, temp
);
404 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x07, 0x00, jreg07
);
405 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x09, 0xdf, jreg09
);
406 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAE, 0x00, (jregAE
| 0x80));
409 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb6, 0x3f, 0x80);
411 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb6, 0x3f, 0x00);
413 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x80);
416 static void ast_set_offset_reg(struct ast_private
*ast
,
417 struct drm_framebuffer
*fb
)
421 offset
= fb
->pitches
[0] >> 3;
422 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x13, (offset
& 0xff));
423 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xb0, (offset
>> 8) & 0x3f);
426 static void ast_set_dclk_reg(struct ast_private
*ast
,
427 struct drm_display_mode
*mode
,
428 struct ast_vbios_mode_info
*vbios_mode
)
430 const struct ast_vbios_dclk_info
*clk_info
;
432 if (ast
->chip
== AST2500
)
433 clk_info
= &dclk_table_ast2500
[vbios_mode
->enh_table
->dclk_index
];
435 clk_info
= &dclk_table
[vbios_mode
->enh_table
->dclk_index
];
437 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xc0, 0x00, clk_info
->param1
);
438 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xc1, 0x00, clk_info
->param2
);
439 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xbb, 0x0f,
440 (clk_info
->param3
& 0xc0) |
441 ((clk_info
->param3
& 0x3) << 4));
444 static void ast_set_color_reg(struct ast_private
*ast
,
445 const struct drm_format_info
*format
)
447 u8 jregA0
= 0, jregA3
= 0, jregA8
= 0;
449 switch (format
->cpp
[0] * 8) {
468 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa0, 0x8f, jregA0
);
469 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa3, 0xf0, jregA3
);
470 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa8, 0xfd, jregA8
);
473 static void ast_set_crtthd_reg(struct ast_private
*ast
)
476 if (ast
->chip
== AST2300
|| ast
->chip
== AST2400
||
477 ast
->chip
== AST2500
) {
478 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x78);
479 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x60);
480 } else if (ast
->chip
== AST2100
||
481 ast
->chip
== AST1100
||
482 ast
->chip
== AST2200
||
483 ast
->chip
== AST2150
) {
484 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x3f);
485 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x2f);
487 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x2f);
488 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x1f);
492 static void ast_set_sync_reg(struct ast_private
*ast
,
493 struct drm_display_mode
*mode
,
494 struct ast_vbios_mode_info
*vbios_mode
)
498 jreg
= ast_io_read8(ast
, AST_IO_MISC_PORT_READ
);
500 if (vbios_mode
->enh_table
->flags
& NVSync
) jreg
|= 0x80;
501 if (vbios_mode
->enh_table
->flags
& NHSync
) jreg
|= 0x40;
502 ast_io_write8(ast
, AST_IO_MISC_PORT_WRITE
, jreg
);
505 static void ast_set_start_address_crt1(struct ast_private
*ast
,
511 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x0d, (u8
)(addr
& 0xff));
512 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x0c, (u8
)((addr
>> 8) & 0xff));
513 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xaf, (u8
)((addr
>> 16) & 0xff));
517 static void ast_wait_for_vretrace(struct ast_private
*ast
)
519 unsigned long timeout
= jiffies
+ HZ
;
523 vgair1
= ast_io_read8(ast
, AST_IO_INPUT_STATUS1_READ
);
524 } while (!(vgair1
& AST_IO_VGAIR1_VREFRESH
) && time_before(jiffies
, timeout
));
531 static const uint32_t ast_primary_plane_formats
[] = {
537 static int ast_primary_plane_helper_atomic_check(struct drm_plane
*plane
,
538 struct drm_plane_state
*state
)
540 struct drm_crtc_state
*crtc_state
;
541 struct ast_crtc_state
*ast_crtc_state
;
547 crtc_state
= drm_atomic_get_new_crtc_state(state
->state
, state
->crtc
);
549 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
550 DRM_PLANE_HELPER_NO_SCALING
,
551 DRM_PLANE_HELPER_NO_SCALING
,
559 ast_crtc_state
= to_ast_crtc_state(crtc_state
);
561 ast_crtc_state
->format
= state
->fb
->format
;
567 ast_primary_plane_helper_atomic_update(struct drm_plane
*plane
,
568 struct drm_plane_state
*old_state
)
570 struct drm_device
*dev
= plane
->dev
;
571 struct ast_private
*ast
= to_ast_private(dev
);
572 struct drm_plane_state
*state
= plane
->state
;
573 struct drm_gem_vram_object
*gbo
;
575 struct drm_framebuffer
*fb
= state
->fb
;
576 struct drm_framebuffer
*old_fb
= old_state
->fb
;
578 if (!old_fb
|| (fb
->format
!= old_fb
->format
)) {
579 struct drm_crtc_state
*crtc_state
= state
->crtc
->state
;
580 struct ast_crtc_state
*ast_crtc_state
= to_ast_crtc_state(crtc_state
);
581 struct ast_vbios_mode_info
*vbios_mode_info
= &ast_crtc_state
->vbios_mode_info
;
583 ast_set_color_reg(ast
, fb
->format
);
584 ast_set_vbios_color_reg(ast
, fb
->format
, vbios_mode_info
);
587 gbo
= drm_gem_vram_of_gem(fb
->obj
[0]);
588 gpu_addr
= drm_gem_vram_offset(gbo
);
589 if (drm_WARN_ON_ONCE(dev
, gpu_addr
< 0))
590 return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
592 ast_set_offset_reg(ast
, fb
);
593 ast_set_start_address_crt1(ast
, (u32
)gpu_addr
);
595 ast_set_index_reg_mask(ast
, AST_IO_SEQ_PORT
, 0x1, 0xdf, 0x00);
599 ast_primary_plane_helper_atomic_disable(struct drm_plane
*plane
,
600 struct drm_plane_state
*old_state
)
602 struct ast_private
*ast
= to_ast_private(plane
->dev
);
604 ast_set_index_reg_mask(ast
, AST_IO_SEQ_PORT
, 0x1, 0xdf, 0x20);
607 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs
= {
608 .prepare_fb
= drm_gem_vram_plane_helper_prepare_fb
,
609 .cleanup_fb
= drm_gem_vram_plane_helper_cleanup_fb
,
610 .atomic_check
= ast_primary_plane_helper_atomic_check
,
611 .atomic_update
= ast_primary_plane_helper_atomic_update
,
612 .atomic_disable
= ast_primary_plane_helper_atomic_disable
,
615 static const struct drm_plane_funcs ast_primary_plane_funcs
= {
616 .update_plane
= drm_atomic_helper_update_plane
,
617 .disable_plane
= drm_atomic_helper_disable_plane
,
618 .destroy
= drm_plane_cleanup
,
619 .reset
= drm_atomic_helper_plane_reset
,
620 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
621 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
628 static const uint32_t ast_cursor_plane_formats
[] = {
633 ast_cursor_plane_helper_prepare_fb(struct drm_plane
*plane
,
634 struct drm_plane_state
*new_state
)
636 struct drm_framebuffer
*fb
= new_state
->fb
;
637 struct drm_crtc
*crtc
= new_state
->crtc
;
638 struct ast_private
*ast
;
644 ast
= to_ast_private(plane
->dev
);
646 ret
= ast_cursor_blit(ast
, fb
);
653 static int ast_cursor_plane_helper_atomic_check(struct drm_plane
*plane
,
654 struct drm_plane_state
*state
)
656 struct drm_framebuffer
*fb
= state
->fb
;
657 struct drm_crtc_state
*crtc_state
;
663 crtc_state
= drm_atomic_get_new_crtc_state(state
->state
, state
->crtc
);
665 ret
= drm_atomic_helper_check_plane_state(state
, crtc_state
,
666 DRM_PLANE_HELPER_NO_SCALING
,
667 DRM_PLANE_HELPER_NO_SCALING
,
675 if (fb
->width
> AST_MAX_HWC_WIDTH
|| fb
->height
> AST_MAX_HWC_HEIGHT
)
682 ast_cursor_plane_helper_atomic_update(struct drm_plane
*plane
,
683 struct drm_plane_state
*old_state
)
685 struct drm_plane_state
*state
= plane
->state
;
686 struct drm_framebuffer
*fb
= state
->fb
;
687 struct ast_private
*ast
= to_ast_private(plane
->dev
);
688 unsigned int offset_x
, offset_y
;
690 offset_x
= AST_MAX_HWC_WIDTH
- fb
->width
;
691 offset_y
= AST_MAX_HWC_WIDTH
- fb
->height
;
693 if (state
->fb
!= old_state
->fb
) {
694 /* A new cursor image was installed. */
695 ast_cursor_page_flip(ast
);
698 ast_cursor_show(ast
, state
->crtc_x
, state
->crtc_y
,
703 ast_cursor_plane_helper_atomic_disable(struct drm_plane
*plane
,
704 struct drm_plane_state
*old_state
)
706 struct ast_private
*ast
= to_ast_private(plane
->dev
);
708 ast_cursor_hide(ast
);
711 static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs
= {
712 .prepare_fb
= ast_cursor_plane_helper_prepare_fb
,
713 .cleanup_fb
= NULL
, /* not required for cursor plane */
714 .atomic_check
= ast_cursor_plane_helper_atomic_check
,
715 .atomic_update
= ast_cursor_plane_helper_atomic_update
,
716 .atomic_disable
= ast_cursor_plane_helper_atomic_disable
,
719 static const struct drm_plane_funcs ast_cursor_plane_funcs
= {
720 .update_plane
= drm_atomic_helper_update_plane
,
721 .disable_plane
= drm_atomic_helper_disable_plane
,
722 .destroy
= drm_plane_cleanup
,
723 .reset
= drm_atomic_helper_plane_reset
,
724 .atomic_duplicate_state
= drm_atomic_helper_plane_duplicate_state
,
725 .atomic_destroy_state
= drm_atomic_helper_plane_destroy_state
,
732 static void ast_crtc_dpms(struct drm_crtc
*crtc
, int mode
)
734 struct ast_private
*ast
= to_ast_private(crtc
->dev
);
736 /* TODO: Maybe control display signal generation with
737 * Sync Enable (bit CR17.7).
740 case DRM_MODE_DPMS_ON
:
741 case DRM_MODE_DPMS_STANDBY
:
742 case DRM_MODE_DPMS_SUSPEND
:
743 if (ast
->tx_chip_type
== AST_TX_DP501
)
744 ast_set_dp501_video_output(crtc
->dev
, 1);
746 case DRM_MODE_DPMS_OFF
:
747 if (ast
->tx_chip_type
== AST_TX_DP501
)
748 ast_set_dp501_video_output(crtc
->dev
, 0);
753 static int ast_crtc_helper_atomic_check(struct drm_crtc
*crtc
,
754 struct drm_atomic_state
*state
)
756 struct drm_crtc_state
*crtc_state
= drm_atomic_get_new_crtc_state(state
,
758 struct drm_device
*dev
= crtc
->dev
;
759 struct ast_crtc_state
*ast_state
;
760 const struct drm_format_info
*format
;
763 if (!crtc_state
->enable
)
764 return 0; /* no mode checks if CRTC is being disabled */
766 ast_state
= to_ast_crtc_state(crtc_state
);
768 format
= ast_state
->format
;
769 if (drm_WARN_ON_ONCE(dev
, !format
))
770 return -EINVAL
; /* BUG: We didn't set format in primary check(). */
772 succ
= ast_get_vbios_mode_info(format
, &crtc_state
->mode
,
773 &crtc_state
->adjusted_mode
,
774 &ast_state
->vbios_mode_info
);
782 ast_crtc_helper_atomic_flush(struct drm_crtc
*crtc
,
783 struct drm_atomic_state
*state
)
785 struct drm_crtc_state
*crtc_state
= drm_atomic_get_new_crtc_state(state
,
787 struct drm_crtc_state
*old_crtc_state
= drm_atomic_get_old_crtc_state(state
,
789 struct ast_private
*ast
= to_ast_private(crtc
->dev
);
790 struct ast_crtc_state
*ast_crtc_state
= to_ast_crtc_state(crtc_state
);
791 struct ast_crtc_state
*old_ast_crtc_state
= to_ast_crtc_state(old_crtc_state
);
794 * The gamma LUT has to be reloaded after changing the primary
795 * plane's color format.
797 if (old_ast_crtc_state
->format
!= ast_crtc_state
->format
)
798 ast_crtc_load_lut(ast
, crtc
);
802 ast_crtc_helper_atomic_enable(struct drm_crtc
*crtc
,
803 struct drm_atomic_state
*state
)
805 struct drm_device
*dev
= crtc
->dev
;
806 struct ast_private
*ast
= to_ast_private(dev
);
807 struct drm_crtc_state
*crtc_state
= crtc
->state
;
808 struct ast_crtc_state
*ast_crtc_state
= to_ast_crtc_state(crtc_state
);
809 struct ast_vbios_mode_info
*vbios_mode_info
=
810 &ast_crtc_state
->vbios_mode_info
;
811 struct drm_display_mode
*adjusted_mode
= &crtc_state
->adjusted_mode
;
813 ast_set_vbios_mode_reg(ast
, adjusted_mode
, vbios_mode_info
);
814 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa1, 0x06);
815 ast_set_std_reg(ast
, adjusted_mode
, vbios_mode_info
);
816 ast_set_crtc_reg(ast
, adjusted_mode
, vbios_mode_info
);
817 ast_set_dclk_reg(ast
, adjusted_mode
, vbios_mode_info
);
818 ast_set_crtthd_reg(ast
);
819 ast_set_sync_reg(ast
, adjusted_mode
, vbios_mode_info
);
821 ast_crtc_dpms(crtc
, DRM_MODE_DPMS_ON
);
825 ast_crtc_helper_atomic_disable(struct drm_crtc
*crtc
,
826 struct drm_atomic_state
*state
)
828 struct drm_crtc_state
*old_crtc_state
= drm_atomic_get_old_crtc_state(state
,
830 struct drm_device
*dev
= crtc
->dev
;
831 struct ast_private
*ast
= to_ast_private(dev
);
833 ast_crtc_dpms(crtc
, DRM_MODE_DPMS_OFF
);
836 * HW cursors require the underlying primary plane and CRTC to
837 * display a valid mode and image. This is not the case during
838 * full modeset operations. So we temporarily disable any active
839 * plane, including the HW cursor. Each plane's atomic_update()
840 * helper will re-enable it if necessary.
842 * We only do this during *full* modesets. It does not affect
843 * simple pageflips on the planes.
845 drm_atomic_helper_disable_planes_on_crtc(old_crtc_state
, false);
848 * Ensure that no scanout takes place before reprogramming mode
849 * and format registers.
851 ast_wait_for_vretrace(ast
);
854 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs
= {
855 .atomic_check
= ast_crtc_helper_atomic_check
,
856 .atomic_flush
= ast_crtc_helper_atomic_flush
,
857 .atomic_enable
= ast_crtc_helper_atomic_enable
,
858 .atomic_disable
= ast_crtc_helper_atomic_disable
,
861 static void ast_crtc_reset(struct drm_crtc
*crtc
)
863 struct ast_crtc_state
*ast_state
=
864 kzalloc(sizeof(*ast_state
), GFP_KERNEL
);
867 crtc
->funcs
->atomic_destroy_state(crtc
, crtc
->state
);
869 __drm_atomic_helper_crtc_reset(crtc
, &ast_state
->base
);
872 static struct drm_crtc_state
*
873 ast_crtc_atomic_duplicate_state(struct drm_crtc
*crtc
)
875 struct ast_crtc_state
*new_ast_state
, *ast_state
;
876 struct drm_device
*dev
= crtc
->dev
;
878 if (drm_WARN_ON(dev
, !crtc
->state
))
881 new_ast_state
= kmalloc(sizeof(*new_ast_state
), GFP_KERNEL
);
884 __drm_atomic_helper_crtc_duplicate_state(crtc
, &new_ast_state
->base
);
886 ast_state
= to_ast_crtc_state(crtc
->state
);
888 new_ast_state
->format
= ast_state
->format
;
889 memcpy(&new_ast_state
->vbios_mode_info
, &ast_state
->vbios_mode_info
,
890 sizeof(new_ast_state
->vbios_mode_info
));
892 return &new_ast_state
->base
;
895 static void ast_crtc_atomic_destroy_state(struct drm_crtc
*crtc
,
896 struct drm_crtc_state
*state
)
898 struct ast_crtc_state
*ast_state
= to_ast_crtc_state(state
);
900 __drm_atomic_helper_crtc_destroy_state(&ast_state
->base
);
904 static const struct drm_crtc_funcs ast_crtc_funcs
= {
905 .reset
= ast_crtc_reset
,
906 .gamma_set
= drm_atomic_helper_legacy_gamma_set
,
907 .destroy
= drm_crtc_cleanup
,
908 .set_config
= drm_atomic_helper_set_config
,
909 .page_flip
= drm_atomic_helper_page_flip
,
910 .atomic_duplicate_state
= ast_crtc_atomic_duplicate_state
,
911 .atomic_destroy_state
= ast_crtc_atomic_destroy_state
,
914 static int ast_crtc_init(struct drm_device
*dev
)
916 struct ast_private
*ast
= to_ast_private(dev
);
917 struct drm_crtc
*crtc
= &ast
->crtc
;
920 ret
= drm_crtc_init_with_planes(dev
, crtc
, &ast
->primary_plane
,
921 &ast
->cursor_plane
, &ast_crtc_funcs
,
926 drm_mode_crtc_set_gamma_size(crtc
, 256);
927 drm_crtc_helper_add(crtc
, &ast_crtc_helper_funcs
);
936 static int ast_encoder_init(struct drm_device
*dev
)
938 struct ast_private
*ast
= to_ast_private(dev
);
939 struct drm_encoder
*encoder
= &ast
->encoder
;
942 ret
= drm_simple_encoder_init(dev
, encoder
, DRM_MODE_ENCODER_DAC
);
946 encoder
->possible_crtcs
= 1;
955 static int ast_get_modes(struct drm_connector
*connector
)
957 struct ast_connector
*ast_connector
= to_ast_connector(connector
);
958 struct ast_private
*ast
= to_ast_private(connector
->dev
);
962 if (ast
->tx_chip_type
== AST_TX_DP501
) {
963 ast
->dp501_maxclk
= 0xff;
964 edid
= kmalloc(128, GFP_KERNEL
);
968 flags
= ast_dp501_read_edid(connector
->dev
, (u8
*)edid
);
970 ast
->dp501_maxclk
= ast_get_dp501_max_clk(connector
->dev
);
975 edid
= drm_get_edid(connector
, &ast_connector
->i2c
->adapter
);
977 drm_connector_update_edid_property(&ast_connector
->base
, edid
);
978 ret
= drm_add_edid_modes(connector
, edid
);
982 drm_connector_update_edid_property(&ast_connector
->base
, NULL
);
986 static enum drm_mode_status
ast_mode_valid(struct drm_connector
*connector
,
987 struct drm_display_mode
*mode
)
989 struct ast_private
*ast
= to_ast_private(connector
->dev
);
990 int flags
= MODE_NOMODE
;
993 if (ast
->support_wide_screen
) {
994 if ((mode
->hdisplay
== 1680) && (mode
->vdisplay
== 1050))
996 if ((mode
->hdisplay
== 1280) && (mode
->vdisplay
== 800))
998 if ((mode
->hdisplay
== 1440) && (mode
->vdisplay
== 900))
1000 if ((mode
->hdisplay
== 1360) && (mode
->vdisplay
== 768))
1002 if ((mode
->hdisplay
== 1600) && (mode
->vdisplay
== 900))
1005 if ((ast
->chip
== AST2100
) || (ast
->chip
== AST2200
) ||
1006 (ast
->chip
== AST2300
) || (ast
->chip
== AST2400
) ||
1007 (ast
->chip
== AST2500
)) {
1008 if ((mode
->hdisplay
== 1920) && (mode
->vdisplay
== 1080))
1011 if ((mode
->hdisplay
== 1920) && (mode
->vdisplay
== 1200)) {
1012 jtemp
= ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xd1, 0xff);
1020 switch (mode
->hdisplay
) {
1022 if (mode
->vdisplay
== 480) flags
= MODE_OK
;
1025 if (mode
->vdisplay
== 600) flags
= MODE_OK
;
1028 if (mode
->vdisplay
== 768) flags
= MODE_OK
;
1031 if (mode
->vdisplay
== 1024) flags
= MODE_OK
;
1034 if (mode
->vdisplay
== 1200) flags
= MODE_OK
;
1043 static void ast_connector_destroy(struct drm_connector
*connector
)
1045 struct ast_connector
*ast_connector
= to_ast_connector(connector
);
1046 ast_i2c_destroy(ast_connector
->i2c
);
1047 drm_connector_cleanup(connector
);
1050 static const struct drm_connector_helper_funcs ast_connector_helper_funcs
= {
1051 .get_modes
= ast_get_modes
,
1052 .mode_valid
= ast_mode_valid
,
1055 static const struct drm_connector_funcs ast_connector_funcs
= {
1056 .reset
= drm_atomic_helper_connector_reset
,
1057 .fill_modes
= drm_helper_probe_single_connector_modes
,
1058 .destroy
= ast_connector_destroy
,
1059 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
1060 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
1063 static int ast_connector_init(struct drm_device
*dev
)
1065 struct ast_private
*ast
= to_ast_private(dev
);
1066 struct ast_connector
*ast_connector
= &ast
->connector
;
1067 struct drm_connector
*connector
= &ast_connector
->base
;
1068 struct drm_encoder
*encoder
= &ast
->encoder
;
1070 ast_connector
->i2c
= ast_i2c_create(dev
);
1071 if (!ast_connector
->i2c
)
1072 drm_err(dev
, "failed to add ddc bus for connector\n");
1074 drm_connector_init_with_ddc(dev
, connector
,
1075 &ast_connector_funcs
,
1076 DRM_MODE_CONNECTOR_VGA
,
1077 &ast_connector
->i2c
->adapter
);
1079 drm_connector_helper_add(connector
, &ast_connector_helper_funcs
);
1081 connector
->interlace_allowed
= 0;
1082 connector
->doublescan_allowed
= 0;
1084 connector
->polled
= DRM_CONNECTOR_POLL_CONNECT
;
1086 drm_connector_attach_encoder(connector
, encoder
);
1095 static const struct drm_mode_config_helper_funcs
1096 ast_mode_config_helper_funcs
= {
1097 .atomic_commit_tail
= drm_atomic_helper_commit_tail_rpm
,
1100 static const struct drm_mode_config_funcs ast_mode_config_funcs
= {
1101 .fb_create
= drm_gem_fb_create
,
1102 .mode_valid
= drm_vram_helper_mode_valid
,
1103 .atomic_check
= drm_atomic_helper_check
,
1104 .atomic_commit
= drm_atomic_helper_commit
,
1107 int ast_mode_config_init(struct ast_private
*ast
)
1109 struct drm_device
*dev
= &ast
->base
;
1112 ret
= ast_cursor_init(ast
);
1116 ret
= drmm_mode_config_init(dev
);
1120 dev
->mode_config
.funcs
= &ast_mode_config_funcs
;
1121 dev
->mode_config
.min_width
= 0;
1122 dev
->mode_config
.min_height
= 0;
1123 dev
->mode_config
.preferred_depth
= 24;
1124 dev
->mode_config
.prefer_shadow
= 1;
1125 dev
->mode_config
.fb_base
= pci_resource_start(dev
->pdev
, 0);
1127 if (ast
->chip
== AST2100
||
1128 ast
->chip
== AST2200
||
1129 ast
->chip
== AST2300
||
1130 ast
->chip
== AST2400
||
1131 ast
->chip
== AST2500
) {
1132 dev
->mode_config
.max_width
= 1920;
1133 dev
->mode_config
.max_height
= 2048;
1135 dev
->mode_config
.max_width
= 1600;
1136 dev
->mode_config
.max_height
= 1200;
1139 dev
->mode_config
.helper_private
= &ast_mode_config_helper_funcs
;
1141 memset(&ast
->primary_plane
, 0, sizeof(ast
->primary_plane
));
1142 ret
= drm_universal_plane_init(dev
, &ast
->primary_plane
, 0x01,
1143 &ast_primary_plane_funcs
,
1144 ast_primary_plane_formats
,
1145 ARRAY_SIZE(ast_primary_plane_formats
),
1146 NULL
, DRM_PLANE_TYPE_PRIMARY
, NULL
);
1148 drm_err(dev
, "ast: drm_universal_plane_init() failed: %d\n", ret
);
1151 drm_plane_helper_add(&ast
->primary_plane
,
1152 &ast_primary_plane_helper_funcs
);
1154 ret
= drm_universal_plane_init(dev
, &ast
->cursor_plane
, 0x01,
1155 &ast_cursor_plane_funcs
,
1156 ast_cursor_plane_formats
,
1157 ARRAY_SIZE(ast_cursor_plane_formats
),
1158 NULL
, DRM_PLANE_TYPE_CURSOR
, NULL
);
1160 drm_err(dev
, "drm_universal_plane_failed(): %d\n", ret
);
1163 drm_plane_helper_add(&ast
->cursor_plane
,
1164 &ast_cursor_plane_helper_funcs
);
1167 ast_encoder_init(dev
);
1168 ast_connector_init(dev
);
1170 drm_mode_config_reset(dev
);
1175 static int get_clock(void *i2c_priv
)
1177 struct ast_i2c_chan
*i2c
= i2c_priv
;
1178 struct ast_private
*ast
= to_ast_private(i2c
->dev
);
1179 uint32_t val
, val2
, count
, pass
;
1183 val
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x10) >> 4) & 0x01;
1185 val2
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x10) >> 4) & 0x01;
1190 val
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x10) >> 4) & 0x01;
1192 } while ((pass
< 5) && (count
++ < 0x10000));
1194 return val
& 1 ? 1 : 0;
1197 static int get_data(void *i2c_priv
)
1199 struct ast_i2c_chan
*i2c
= i2c_priv
;
1200 struct ast_private
*ast
= to_ast_private(i2c
->dev
);
1201 uint32_t val
, val2
, count
, pass
;
1205 val
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x20) >> 5) & 0x01;
1207 val2
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x20) >> 5) & 0x01;
1212 val
= (ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x20) >> 5) & 0x01;
1214 } while ((pass
< 5) && (count
++ < 0x10000));
1216 return val
& 1 ? 1 : 0;
1219 static void set_clock(void *i2c_priv
, int clock
)
1221 struct ast_i2c_chan
*i2c
= i2c_priv
;
1222 struct ast_private
*ast
= to_ast_private(i2c
->dev
);
1226 for (i
= 0; i
< 0x10000; i
++) {
1227 ujcrb7
= ((clock
& 0x01) ? 0 : 1);
1228 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0xf4, ujcrb7
);
1229 jtemp
= ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x01);
1230 if (ujcrb7
== jtemp
)
1235 static void set_data(void *i2c_priv
, int data
)
1237 struct ast_i2c_chan
*i2c
= i2c_priv
;
1238 struct ast_private
*ast
= to_ast_private(i2c
->dev
);
1242 for (i
= 0; i
< 0x10000; i
++) {
1243 ujcrb7
= ((data
& 0x01) ? 0 : 1) << 2;
1244 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0xf1, ujcrb7
);
1245 jtemp
= ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb7, 0x04);
1246 if (ujcrb7
== jtemp
)
1251 static struct ast_i2c_chan
*ast_i2c_create(struct drm_device
*dev
)
1253 struct ast_i2c_chan
*i2c
;
1256 i2c
= kzalloc(sizeof(struct ast_i2c_chan
), GFP_KERNEL
);
1260 i2c
->adapter
.owner
= THIS_MODULE
;
1261 i2c
->adapter
.class = I2C_CLASS_DDC
;
1262 i2c
->adapter
.dev
.parent
= &dev
->pdev
->dev
;
1264 i2c_set_adapdata(&i2c
->adapter
, i2c
);
1265 snprintf(i2c
->adapter
.name
, sizeof(i2c
->adapter
.name
),
1267 i2c
->adapter
.algo_data
= &i2c
->bit
;
1269 i2c
->bit
.udelay
= 20;
1270 i2c
->bit
.timeout
= 2;
1271 i2c
->bit
.data
= i2c
;
1272 i2c
->bit
.setsda
= set_data
;
1273 i2c
->bit
.setscl
= set_clock
;
1274 i2c
->bit
.getsda
= get_data
;
1275 i2c
->bit
.getscl
= get_clock
;
1276 ret
= i2c_bit_add_bus(&i2c
->adapter
);
1278 drm_err(dev
, "Failed to register bit i2c\n");
1288 static void ast_i2c_destroy(struct ast_i2c_chan
*i2c
)
1292 i2c_del_adapter(&i2c
->adapter
);