1 /* SPDX-License-Identifier: MIT */
3 * Copied from Linux drivers/gpu/drm/ast/ast_mode.c
4 * Please try to keep as close as possible to the upstream source.
7 #include "ast_tables.h"
9 static inline void ast_load_palette_index(struct ast_private
*ast
,
10 u8 index
, u8 red
, u8 green
,
13 ast_io_write8(ast
, AST_IO_DAC_INDEX_WRITE
, index
);
14 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
15 ast_io_write8(ast
, AST_IO_DAC_DATA
, red
);
16 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
17 ast_io_write8(ast
, AST_IO_DAC_DATA
, green
);
18 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
19 ast_io_write8(ast
, AST_IO_DAC_DATA
, blue
);
20 ast_io_read8(ast
, AST_IO_SEQ_PORT
);
23 static void ast_crtc_load_lut(struct drm_crtc
*crtc
)
25 struct ast_private
*ast
= crtc
->dev
->dev_private
;
26 /* FIXME: Gamma cor 2.6 ? */
27 for (int i
= 0; i
< 256; i
++)
28 ast_load_palette_index(ast
, i
, i
, i
, i
);
31 static bool ast_get_vbios_mode_info(struct drm_crtc
*crtc
, struct drm_display_mode
*mode
,
32 struct drm_display_mode
*adjusted_mode
,
33 struct ast_vbios_mode_info
*vbios_mode
)
35 struct ast_private
*ast
= crtc
->dev
->dev_private
;
36 const struct drm_framebuffer
*fb
= crtc
->primary
->fb
;
37 u32 refresh_rate_index
= 0, mode_id
, color_index
, refresh_rate
;
38 const struct ast_vbios_enhtable
*best
= NULL
;
42 switch (fb
->format
->cpp
[0] * 8) {
44 vbios_mode
->std_table
= &vbios_stdtable
[VGAModeIndex
];
45 color_index
= VGAModeIndex
- 1;
48 vbios_mode
->std_table
= &vbios_stdtable
[HiCModeIndex
];
49 color_index
= HiCModeIndex
;
53 vbios_mode
->std_table
= &vbios_stdtable
[TrueCModeIndex
];
54 color_index
= TrueCModeIndex
;
60 switch (crtc
->mode
.crtc_hdisplay
) {
62 vbios_mode
->enh_table
= &res_640x480
[refresh_rate_index
];
65 vbios_mode
->enh_table
= &res_800x600
[refresh_rate_index
];
68 vbios_mode
->enh_table
= &res_1024x768
[refresh_rate_index
];
71 if (crtc
->mode
.crtc_vdisplay
== 800)
72 vbios_mode
->enh_table
= &res_1280x800
[refresh_rate_index
];
74 vbios_mode
->enh_table
= &res_1280x1024
[refresh_rate_index
];
77 vbios_mode
->enh_table
= &res_1360x768
[refresh_rate_index
];
80 vbios_mode
->enh_table
= &res_1440x900
[refresh_rate_index
];
83 if (crtc
->mode
.crtc_vdisplay
== 900)
84 vbios_mode
->enh_table
= &res_1600x900
[refresh_rate_index
];
86 vbios_mode
->enh_table
= &res_1600x1200
[refresh_rate_index
];
89 vbios_mode
->enh_table
= &res_1680x1050
[refresh_rate_index
];
92 if (crtc
->mode
.crtc_vdisplay
== 1080)
93 vbios_mode
->enh_table
= &res_1920x1080
[refresh_rate_index
];
95 vbios_mode
->enh_table
= &res_1920x1200
[refresh_rate_index
];
101 refresh_rate
= mode
->vrefresh
;
102 check_sync
= vbios_mode
->enh_table
->flags
& WideScreenMode
;
104 const struct ast_vbios_enhtable
*loop
= vbios_mode
->enh_table
;
106 while (loop
->refresh_rate
!= 0xff) {
108 (((mode
->flags
& DRM_MODE_FLAG_NVSYNC
) &&
109 (loop
->flags
& PVSync
)) ||
110 ((mode
->flags
& DRM_MODE_FLAG_PVSYNC
) &&
111 (loop
->flags
& NVSync
)) ||
112 ((mode
->flags
& DRM_MODE_FLAG_NHSYNC
) &&
113 (loop
->flags
& PHSync
)) ||
114 ((mode
->flags
& DRM_MODE_FLAG_PHSYNC
) &&
115 (loop
->flags
& NHSync
)))) {
119 if (loop
->refresh_rate
<= refresh_rate
120 && (!best
|| loop
->refresh_rate
> best
->refresh_rate
))
124 if (best
|| !check_sync
)
129 vbios_mode
->enh_table
= best
;
131 hborder
= (vbios_mode
->enh_table
->flags
& HBorder
) ? 8 : 0;
132 vborder
= (vbios_mode
->enh_table
->flags
& VBorder
) ? 8 : 0;
134 adjusted_mode
->crtc_htotal
= vbios_mode
->enh_table
->ht
;
135 adjusted_mode
->crtc_hblank_start
= vbios_mode
->enh_table
->hde
+ hborder
;
136 adjusted_mode
->crtc_hblank_end
= vbios_mode
->enh_table
->ht
- hborder
;
137 adjusted_mode
->crtc_hsync_start
= vbios_mode
->enh_table
->hde
+ hborder
+
138 vbios_mode
->enh_table
->hfp
;
139 adjusted_mode
->crtc_hsync_end
= (vbios_mode
->enh_table
->hde
+ hborder
+
140 vbios_mode
->enh_table
->hfp
+
141 vbios_mode
->enh_table
->hsync
);
143 adjusted_mode
->crtc_vtotal
= vbios_mode
->enh_table
->vt
;
144 adjusted_mode
->crtc_vblank_start
= vbios_mode
->enh_table
->vde
+ vborder
;
145 adjusted_mode
->crtc_vblank_end
= vbios_mode
->enh_table
->vt
- vborder
;
146 adjusted_mode
->crtc_vsync_start
= vbios_mode
->enh_table
->vde
+ vborder
+
147 vbios_mode
->enh_table
->vfp
;
148 adjusted_mode
->crtc_vsync_end
= (vbios_mode
->enh_table
->vde
+ vborder
+
149 vbios_mode
->enh_table
->vfp
+
150 vbios_mode
->enh_table
->vsync
);
152 refresh_rate_index
= vbios_mode
->enh_table
->refresh_rate_index
;
153 mode_id
= vbios_mode
->enh_table
->mode_id
;
155 if (ast
->chip
== AST1180
) {
158 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8c, (u8
)((color_index
& 0xf) << 4));
159 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8d, refresh_rate_index
& 0xff);
160 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x8e, mode_id
& 0xff);
162 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0x00);
163 if (vbios_mode
->enh_table
->flags
& NewModeInfo
) {
164 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x91, 0xa8);
165 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x92,
166 fb
->format
->cpp
[0] * 8);
167 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x93,
168 adjusted_mode
->clock
/ 1000);
169 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x94,
170 adjusted_mode
->crtc_hdisplay
);
171 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x95,
172 adjusted_mode
->crtc_hdisplay
>> 8);
174 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x96,
175 adjusted_mode
->crtc_vdisplay
);
176 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x97,
177 adjusted_mode
->crtc_vdisplay
>> 8);
184 static void ast_set_std_reg(struct drm_crtc
*crtc
, struct drm_display_mode
*mode
,
185 struct ast_vbios_mode_info
*vbios_mode
)
187 struct ast_private
*ast
= crtc
->dev
->dev_private
;
188 const struct drm_framebuffer
*fb
= crtc
->primary
->fb
;
189 const struct ast_vbios_stdtable
*stdtable
;
193 switch (fb
->format
->cpp
[0] * 8) {
195 stdtable
= &vbios_stdtable
[VGAModeIndex
];
198 stdtable
= &vbios_stdtable
[HiCModeIndex
];
202 stdtable
= &vbios_stdtable
[TrueCModeIndex
];
208 jreg
= stdtable
->misc
;
209 ast_io_write8(ast
, AST_IO_MISC_PORT_WRITE
, jreg
);
212 ast_set_index_reg(ast
, AST_IO_SEQ_PORT
, 0x00, 0x03);
213 for (i
= 0; i
< 4; i
++) {
214 jreg
= stdtable
->seq
[i
];
217 ast_set_index_reg(ast
, AST_IO_SEQ_PORT
, (i
+ 1), jreg
);
221 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x00);
222 for (i
= 0; i
< 25; i
++)
223 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, i
, stdtable
->crtc
[i
]);
226 jreg
= ast_io_read8(ast
, AST_IO_INPUT_STATUS1_READ
);
227 for (i
= 0; i
< 20; i
++) {
228 jreg
= stdtable
->ar
[i
];
229 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, (u8
)i
);
230 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, jreg
);
232 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x14);
233 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x00);
235 jreg
= ast_io_read8(ast
, AST_IO_INPUT_STATUS1_READ
);
236 ast_io_write8(ast
, AST_IO_AR_PORT_WRITE
, 0x20);
239 for (i
= 0; i
< 9; i
++)
240 ast_set_index_reg(ast
, AST_IO_GR_PORT
, i
, stdtable
->gr
[i
]);
243 static void ast_set_crtc_reg(struct drm_crtc
*crtc
, struct drm_display_mode
*mode
,
244 struct ast_vbios_mode_info
*vbios_mode
)
246 struct ast_private
*ast
= crtc
->dev
->dev_private
;
247 u8 jreg05
= 0, jreg07
= 0, jreg09
= 0, jregAC
= 0, jregAD
= 0, jregAE
= 0;
248 u16 temp
, precache
= 0;
250 if ((ast
->chip
== AST2500
) &&
251 (vbios_mode
->enh_table
->flags
& AST2500PreCatchCRT
))
254 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x00);
256 temp
= (mode
->crtc_htotal
>> 3) - 5;
258 jregAC
|= 0x01; /* HT D[8] */
259 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x00, 0x00, temp
);
261 temp
= (mode
->crtc_hdisplay
>> 3) - 1;
263 jregAC
|= 0x04; /* HDE D[8] */
264 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x01, 0x00, temp
);
266 temp
= (mode
->crtc_hblank_start
>> 3) - 1;
268 jregAC
|= 0x10; /* HBS D[8] */
269 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x02, 0x00, temp
);
271 temp
= ((mode
->crtc_hblank_end
>> 3) - 1) & 0x7f;
273 jreg05
|= 0x80; /* HBE D[5] */
275 jregAD
|= 0x01; /* HBE D[5] */
276 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x03, 0xE0, (temp
& 0x1f));
278 temp
= ((mode
->crtc_hsync_start
-precache
) >> 3) - 1;
280 jregAC
|= 0x40; /* HRS D[5] */
281 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x04, 0x00, temp
);
283 temp
= (((mode
->crtc_hsync_end
-precache
) >> 3) - 1) & 0x3f;
285 jregAD
|= 0x04; /* HRE D[5] */
286 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x05, 0x60, (u8
)((temp
& 0x1f) | jreg05
));
288 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAC, 0x00, jregAC
);
289 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAD, 0x00, jregAD
);
292 temp
= (mode
->crtc_vtotal
) - 2;
299 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x06, 0x00, temp
);
301 temp
= (mode
->crtc_vsync_start
) - 1;
308 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x10, 0x00, temp
);
310 temp
= (mode
->crtc_vsync_end
- 1) & 0x3f;
315 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x70, temp
& 0xf);
317 temp
= mode
->crtc_vdisplay
- 1;
324 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x12, 0x00, temp
);
326 temp
= mode
->crtc_vblank_start
- 1;
333 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x15, 0x00, temp
);
335 temp
= mode
->crtc_vblank_end
- 1;
338 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x16, 0x00, temp
);
340 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x07, 0x00, jreg07
);
341 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x09, 0xdf, jreg09
);
342 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xAE, 0x00, (jregAE
| 0x80));
345 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb6, 0x3f, 0x80);
347 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xb6, 0x3f, 0x00);
349 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0x11, 0x7f, 0x80);
352 void ast_set_offset_reg(struct drm_crtc
*crtc
)
354 struct ast_private
*ast
= crtc
->dev
->dev_private
;
355 const struct drm_framebuffer
*fb
= crtc
->primary
->fb
;
359 offset
= fb
->pitches
[0] >> 3;
360 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x13, (offset
& 0xff));
361 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xb0, (offset
>> 8) & 0x3f);
364 static void ast_set_dclk_reg(struct drm_device
*dev
, struct drm_display_mode
*mode
,
365 struct ast_vbios_mode_info
*vbios_mode
)
367 struct ast_private
*ast
= dev
->dev_private
;
368 const struct ast_vbios_dclk_info
*clk_info
;
370 if (ast
->chip
== AST2500
)
371 clk_info
= &dclk_table_ast2500
[vbios_mode
->enh_table
->dclk_index
];
373 clk_info
= &dclk_table
[vbios_mode
->enh_table
->dclk_index
];
375 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xc0, 0x00, clk_info
->param1
);
376 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xc1, 0x00, clk_info
->param2
);
377 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xbb, 0x0f,
378 (clk_info
->param3
& 0xc0) |
379 ((clk_info
->param3
& 0x3) << 4));
382 static void ast_set_ext_reg(struct drm_crtc
*crtc
, struct drm_display_mode
*mode
,
383 struct ast_vbios_mode_info
*vbios_mode
)
385 struct ast_private
*ast
= crtc
->dev
->dev_private
;
386 const struct drm_framebuffer
*fb
= crtc
->primary
->fb
;
387 u8 jregA0
= 0, jregA3
= 0, jregA8
= 0;
389 switch (fb
->format
->cpp
[0] * 8) {
409 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa0, 0x8f, jregA0
);
410 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa3, 0xf0, jregA3
);
411 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa8, 0xfd, jregA8
);
414 if (ast
->chip
== AST2300
|| ast
->chip
== AST2400
||
415 ast
->chip
== AST2500
) {
416 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x78);
417 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x60);
418 } else if (ast
->chip
== AST2100
||
419 ast
->chip
== AST1100
||
420 ast
->chip
== AST2200
||
421 ast
->chip
== AST2150
) {
422 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x3f);
423 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x2f);
425 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa7, 0x2f);
426 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xa6, 0x1f);
430 static void ast_set_sync_reg(struct drm_device
*dev
, struct drm_display_mode
*mode
,
431 struct ast_vbios_mode_info
*vbios_mode
)
433 struct ast_private
*ast
= dev
->dev_private
;
436 jreg
= ast_io_read8(ast
, AST_IO_MISC_PORT_READ
);
438 if (vbios_mode
->enh_table
->flags
& NVSync
)
440 if (vbios_mode
->enh_table
->flags
& NHSync
)
442 ast_io_write8(ast
, AST_IO_MISC_PORT_WRITE
, jreg
);
445 void ast_set_start_address_crt1(struct ast_private
*ast
, u32 offset
)
450 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x0d, (u8
)(addr
& 0xff));
451 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0x0c, (u8
)((addr
>> 8) & 0xff));
452 ast_set_index_reg(ast
, AST_IO_CRTC_PORT
, 0xaf, (u8
)((addr
>> 16) & 0xff));
455 void ast_hide_cursor(struct drm_crtc
*crtc
)
457 struct ast_private
*ast
= crtc
->dev
->dev_private
;
458 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xcb, 0xfc, 0x00);
461 int ast_crtc_mode_set(struct drm_crtc
*crtc
,
462 struct drm_display_mode
*mode
,
463 struct drm_display_mode
*adjusted_mode
)
465 struct drm_device
*dev
= crtc
->dev
;
466 struct ast_private
*ast
= crtc
->dev
->dev_private
;
467 struct ast_vbios_mode_info vbios_mode
;
471 if (ast
->chip
== AST1180
) {
472 dev_err(dev
->pdev
, "AST 1180 modesetting not supported\n");
477 ast_set_index_reg_mask(ast
, AST_IO_SEQ_PORT
, 0x1, 0xdf, 0);
478 if (ast
->tx_chip_type
== AST_TX_DP501
)
479 ast_set_dp501_video_output(crtc
->dev
, 1);
480 ast_crtc_load_lut(crtc
);
483 ret
= ast_get_vbios_mode_info(crtc
, mode
, adjusted_mode
, &vbios_mode
);
485 dev_err(dev
->pdev
, "Failed to find compatible vbios mode\n");
490 ast_set_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xa1, 0xff, 0x04);
492 ast_set_std_reg(crtc
, adjusted_mode
, &vbios_mode
);
493 ast_set_crtc_reg(crtc
, adjusted_mode
, &vbios_mode
);
494 ast_set_offset_reg(crtc
);
495 ast_set_dclk_reg(dev
, adjusted_mode
, &vbios_mode
);
496 ast_set_ext_reg(crtc
, adjusted_mode
, &vbios_mode
);
497 ast_set_sync_reg(dev
, adjusted_mode
, &vbios_mode
);
499 err
= ast_crtc_do_set_base(crtc
);
505 ast_set_index_reg_mask(ast
, AST_IO_SEQ_PORT
, 0x1, 0xdf, 0);
506 ast_crtc_load_lut(crtc
);
511 enum drm_mode_status
ast_mode_valid(struct drm_connector
*connector
,
512 const unsigned int hdisplay
, const unsigned int vdisplay
)
514 struct ast_private
*ast
= connector
->dev
->dev_private
;
515 int flags
= MODE_NOMODE
;
518 if (ast
->support_wide_screen
) {
519 if ((hdisplay
== 1680) && (vdisplay
== 1050))
521 if ((hdisplay
== 1280) && (vdisplay
== 800))
523 if ((hdisplay
== 1440) && (vdisplay
== 900))
525 if ((hdisplay
== 1360) && (vdisplay
== 768))
527 if ((hdisplay
== 1600) && (vdisplay
== 900))
530 if ((ast
->chip
== AST2100
) || (ast
->chip
== AST2200
) ||
531 (ast
->chip
== AST2300
) || (ast
->chip
== AST2400
) ||
532 (ast
->chip
== AST2500
) || (ast
->chip
== AST1180
)) {
533 if ((hdisplay
== 1920) && (vdisplay
== 1080))
536 if ((hdisplay
== 1920) && (vdisplay
== 1200)) {
537 jtemp
= ast_get_index_reg_mask(ast
, AST_IO_CRTC_PORT
, 0xd1,
560 if (vdisplay
== 1024)
564 if (vdisplay
== 1200)