xref: /aosp_15_r20/external/coreboot/src/drivers/aspeed/common/ast_mode.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copied from Linux drivers/gpu/drm/ast/ast_mode.c
4  * Please try to keep as close as possible to the upstream source.
5  */
6 #include "ast_drv.h"
7 #include "ast_tables.h"
8 
ast_load_palette_index(struct ast_private * ast,u8 index,u8 red,u8 green,u8 blue)9 static inline void ast_load_palette_index(struct ast_private *ast,
10 				     u8 index, u8 red, u8 green,
11 				     u8 blue)
12 {
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);
21 }
22 
ast_crtc_load_lut(struct drm_crtc * crtc)23 static void ast_crtc_load_lut(struct drm_crtc *crtc)
24 {
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);
29 }
30 
ast_get_vbios_mode_info(struct drm_crtc * crtc,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode,struct ast_vbios_mode_info * vbios_mode)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)
34 {
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;
39 	u32 hborder, vborder;
40 	bool check_sync;
41 
42 	switch (fb->format->cpp[0] * 8) {
43 	case 8:
44 		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
45 		color_index = VGAModeIndex - 1;
46 		break;
47 	case 16:
48 		vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
49 		color_index = HiCModeIndex;
50 		break;
51 	case 24:
52 	case 32:
53 		vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
54 		color_index = TrueCModeIndex;
55 		break;
56 	default:
57 		return false;
58 	}
59 
60 	switch (crtc->mode.crtc_hdisplay) {
61 	case 640:
62 		vbios_mode->enh_table = &res_640x480[refresh_rate_index];
63 		break;
64 	case 800:
65 		vbios_mode->enh_table = &res_800x600[refresh_rate_index];
66 		break;
67 	case 1024:
68 		vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
69 		break;
70 	case 1280:
71 		if (crtc->mode.crtc_vdisplay == 800)
72 			vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
73 		else
74 			vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
75 		break;
76 	case 1360:
77 		vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
78 		break;
79 	case 1440:
80 		vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
81 		break;
82 	case 1600:
83 		if (crtc->mode.crtc_vdisplay == 900)
84 			vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
85 		else
86 			vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
87 		break;
88 	case 1680:
89 		vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
90 		break;
91 	case 1920:
92 		if (crtc->mode.crtc_vdisplay == 1080)
93 			vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
94 		else
95 			vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
96 		break;
97 	default:
98 		return false;
99 	}
100 
101 	refresh_rate = mode->vrefresh;
102 	check_sync = vbios_mode->enh_table->flags & WideScreenMode;
103 	do {
104 		const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
105 
106 		while (loop->refresh_rate != 0xff) {
107 			if ((check_sync) &&
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)))) {
116 				loop++;
117 				continue;
118 			}
119 			if (loop->refresh_rate <= refresh_rate
120 			    && (!best || loop->refresh_rate > best->refresh_rate))
121 				best = loop;
122 			loop++;
123 		}
124 		if (best || !check_sync)
125 			break;
126 		check_sync = 0;
127 	} while (1);
128 	if (best)
129 		vbios_mode->enh_table = best;
130 
131 	hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
132 	vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
133 
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);
142 
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);
151 
152 	refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
153 	mode_id = vbios_mode->enh_table->mode_id;
154 
155 	if (ast->chip == AST1180) {
156 		/* TODO 1180 */
157 	} else {
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);
161 
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);
173 
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);
178 		}
179 	}
180 
181 	return true;
182 }
183 
ast_set_std_reg(struct drm_crtc * crtc,struct drm_display_mode * mode,struct ast_vbios_mode_info * vbios_mode)184 static void ast_set_std_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
185 			    struct ast_vbios_mode_info *vbios_mode)
186 {
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;
190 	u32 i;
191 	u8 jreg;
192 
193 	switch (fb->format->cpp[0] * 8) {
194 	case 8:
195 		stdtable = &vbios_stdtable[VGAModeIndex];
196 		break;
197 	case 16:
198 		stdtable = &vbios_stdtable[HiCModeIndex];
199 		break;
200 	case 24:
201 	case 32:
202 		stdtable = &vbios_stdtable[TrueCModeIndex];
203 		break;
204 	default:
205 		return;
206 	}
207 
208 	jreg = stdtable->misc;
209 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
210 
211 	/* Set SEQ */
212 	ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03);
213 	for (i = 0; i < 4; i++) {
214 		jreg = stdtable->seq[i];
215 		if (!i)
216 			jreg |= 0x20;
217 		ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1), jreg);
218 	}
219 
220 	/* Set CRTC */
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]);
224 
225 	/* set AR */
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);
231 	}
232 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14);
233 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00);
234 
235 	jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
236 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20);
237 
238 	/* Set GR */
239 	for (i = 0; i < 9; i++)
240 		ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);
241 }
242 
ast_set_crtc_reg(struct drm_crtc * crtc,struct drm_display_mode * mode,struct ast_vbios_mode_info * vbios_mode)243 static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
244 			     struct ast_vbios_mode_info *vbios_mode)
245 {
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;
249 
250 	if ((ast->chip == AST2500) &&
251 	    (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
252 		precache = 40;
253 
254 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
255 
256 	temp = (mode->crtc_htotal >> 3) - 5;
257 	if (temp & 0x100)
258 		jregAC |= 0x01; /* HT D[8] */
259 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp);
260 
261 	temp = (mode->crtc_hdisplay >> 3) - 1;
262 	if (temp & 0x100)
263 		jregAC |= 0x04; /* HDE D[8] */
264 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp);
265 
266 	temp = (mode->crtc_hblank_start >> 3) - 1;
267 	if (temp & 0x100)
268 		jregAC |= 0x10; /* HBS D[8] */
269 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp);
270 
271 	temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f;
272 	if (temp & 0x20)
273 		jreg05 |= 0x80;  /* HBE D[5] */
274 	if (temp & 0x40)
275 		jregAD |= 0x01;  /* HBE D[5] */
276 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f));
277 
278 	temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
279 	if (temp & 0x100)
280 		jregAC |= 0x40; /* HRS D[5] */
281 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp);
282 
283 	temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
284 	if (temp & 0x20)
285 		jregAD |= 0x04; /* HRE D[5] */
286 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
287 
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);
290 
291 	/* vert timings */
292 	temp = (mode->crtc_vtotal) - 2;
293 	if (temp & 0x100)
294 		jreg07 |= 0x01;
295 	if (temp & 0x200)
296 		jreg07 |= 0x20;
297 	if (temp & 0x400)
298 		jregAE |= 0x01;
299 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp);
300 
301 	temp = (mode->crtc_vsync_start) - 1;
302 	if (temp & 0x100)
303 		jreg07 |= 0x04;
304 	if (temp & 0x200)
305 		jreg07 |= 0x80;
306 	if (temp & 0x400)
307 		jregAE |= 0x08;
308 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp);
309 
310 	temp = (mode->crtc_vsync_end - 1) & 0x3f;
311 	if (temp & 0x10)
312 		jregAE |= 0x20;
313 	if (temp & 0x20)
314 		jregAE |= 0x40;
315 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf);
316 
317 	temp = mode->crtc_vdisplay - 1;
318 	if (temp & 0x100)
319 		jreg07 |= 0x02;
320 	if (temp & 0x200)
321 		jreg07 |= 0x40;
322 	if (temp & 0x400)
323 		jregAE |= 0x02;
324 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp);
325 
326 	temp = mode->crtc_vblank_start - 1;
327 	if (temp & 0x100)
328 		jreg07 |= 0x08;
329 	if (temp & 0x200)
330 		jreg09 |= 0x20;
331 	if (temp & 0x400)
332 		jregAE |= 0x04;
333 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp);
334 
335 	temp = mode->crtc_vblank_end - 1;
336 	if (temp & 0x100)
337 		jregAE |= 0x10;
338 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp);
339 
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));
343 
344 	if (precache)
345 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
346 	else
347 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
348 
349 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
350 }
351 
ast_set_offset_reg(struct drm_crtc * crtc)352 void ast_set_offset_reg(struct drm_crtc *crtc)
353 {
354 	struct ast_private *ast = crtc->dev->dev_private;
355 	const struct drm_framebuffer *fb = crtc->primary->fb;
356 
357 	u16 offset;
358 
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);
362 }
363 
ast_set_dclk_reg(struct drm_device * dev,struct drm_display_mode * mode,struct ast_vbios_mode_info * vbios_mode)364 static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode,
365 			     struct ast_vbios_mode_info *vbios_mode)
366 {
367 	struct ast_private *ast = dev->dev_private;
368 	const struct ast_vbios_dclk_info *clk_info;
369 
370 	if (ast->chip == AST2500)
371 		clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
372 	else
373 		clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
374 
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));
380 }
381 
ast_set_ext_reg(struct drm_crtc * crtc,struct drm_display_mode * mode,struct ast_vbios_mode_info * vbios_mode)382 static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
383 			     struct ast_vbios_mode_info *vbios_mode)
384 {
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;
388 
389 	switch (fb->format->cpp[0] * 8) {
390 	case 8:
391 		jregA0 = 0x70;
392 		jregA3 = 0x01;
393 		jregA8 = 0x00;
394 		break;
395 	case 15:
396 	case 16:
397 		jregA0 = 0x70;
398 		jregA3 = 0x04;
399 		jregA8 = 0x02;
400 		break;
401 	case 24:
402 	case 32:
403 		jregA0 = 0x70;
404 		jregA3 = 0x08;
405 		jregA8 = 0x02;
406 		break;
407 	}
408 
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);
412 
413 	/* Set Threshold */
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);
424 	} else {
425 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f);
426 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f);
427 	}
428 }
429 
ast_set_sync_reg(struct drm_device * dev,struct drm_display_mode * mode,struct ast_vbios_mode_info * vbios_mode)430 static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
431 		      struct ast_vbios_mode_info *vbios_mode)
432 {
433 	struct ast_private *ast = dev->dev_private;
434 	u8 jreg;
435 
436 	jreg  = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
437 	jreg &= ~0xC0;
438 	if (vbios_mode->enh_table->flags & NVSync)
439 		jreg |= 0x80;
440 	if (vbios_mode->enh_table->flags & NHSync)
441 		jreg |= 0x40;
442 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
443 }
444 
ast_set_start_address_crt1(struct ast_private * ast,u32 offset)445 void ast_set_start_address_crt1(struct ast_private *ast, u32 offset)
446 {
447 	u32 addr;
448 
449 	addr = offset >> 2;
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));
453 }
454 
ast_hide_cursor(struct drm_crtc * crtc)455 void ast_hide_cursor(struct drm_crtc *crtc)
456 {
457 	struct ast_private *ast = crtc->dev->dev_private;
458 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
459 }
460 
ast_crtc_mode_set(struct drm_crtc * crtc,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)461 int ast_crtc_mode_set(struct drm_crtc *crtc,
462 		      struct drm_display_mode *mode,
463 		      struct drm_display_mode *adjusted_mode)
464 {
465 	struct drm_device *dev = crtc->dev;
466 	struct ast_private *ast = crtc->dev->dev_private;
467 	struct ast_vbios_mode_info vbios_mode;
468 	bool ret;
469 	int err;
470 
471 	if (ast->chip == AST1180) {
472 		dev_err(dev->pdev, "AST 1180 modesetting not supported\n");
473 		return -EINVAL;
474 	}
475 
476 	/* DPMS, set on */
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);
481 
482 	/* Get mode */
483 	ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode);
484 	if (ret == false) {
485 		dev_err(dev->pdev, "Failed to find compatible vbios mode\n");
486 		return -EINVAL;
487 	}
488 	ast_open_key(ast);
489 
490 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
491 
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);
498 
499 	err = ast_crtc_do_set_base(crtc);
500 	if (err)
501 		return err;
502 
503 	/* Commit changes */
504 
505 	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0);
506 	ast_crtc_load_lut(crtc);
507 
508 	return 0;
509 }
510 
ast_mode_valid(struct drm_connector * connector,const unsigned int hdisplay,const unsigned int vdisplay)511 enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
512 				    const unsigned int hdisplay, const unsigned int vdisplay)
513 {
514 	struct ast_private *ast = connector->dev->dev_private;
515 	int flags = MODE_NOMODE;
516 	uint32_t jtemp;
517 
518 	if (ast->support_wide_screen) {
519 		if ((hdisplay == 1680) && (vdisplay == 1050))
520 			return MODE_OK;
521 		if ((hdisplay == 1280) && (vdisplay == 800))
522 			return MODE_OK;
523 		if ((hdisplay == 1440) && (vdisplay == 900))
524 			return MODE_OK;
525 		if ((hdisplay == 1360) && (vdisplay == 768))
526 			return MODE_OK;
527 		if ((hdisplay == 1600) && (vdisplay == 900))
528 			return MODE_OK;
529 
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))
534 				return MODE_OK;
535 
536 			if ((hdisplay == 1920) && (vdisplay == 1200)) {
537 				jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1,
538 							       0xff);
539 				if (jtemp & 0x01)
540 					return MODE_NOMODE;
541 				else
542 					return MODE_OK;
543 			}
544 		}
545 	}
546 	switch (hdisplay) {
547 	case 640:
548 		if (vdisplay == 480)
549 			flags = MODE_OK;
550 		break;
551 	case 800:
552 		if (vdisplay == 600)
553 			flags = MODE_OK;
554 		break;
555 	case 1024:
556 		if (vdisplay == 768)
557 			flags = MODE_OK;
558 		break;
559 	case 1280:
560 		if (vdisplay == 1024)
561 			flags = MODE_OK;
562 		break;
563 	case 1600:
564 		if (vdisplay == 1200)
565 			flags = MODE_OK;
566 		break;
567 	default:
568 		return flags;
569 	}
570 
571 	return flags;
572 }
573