/ src / drivers / aspeed / common / ast_mode.c
ast_mode.c
  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  
  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  
 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  
 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  
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  
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 || ast->chip == AST2600) &&
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  	// Workaround for HSync Time non octave pixels (1920x1080@60Hz HSync 44 pixels);
292  	if ((ast->chip == AST2600) && (mode->crtc_vdisplay == 1080))
293  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x02);
294  	else
295  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xFC, 0xFD, 0x00);
296  
297  	/* vert timings */
298  	temp = (mode->crtc_vtotal) - 2;
299  	if (temp & 0x100)
300  		jreg07 |= 0x01;
301  	if (temp & 0x200)
302  		jreg07 |= 0x20;
303  	if (temp & 0x400)
304  		jregAE |= 0x01;
305  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp);
306  
307  	temp = (mode->crtc_vsync_start) - 1;
308  	if (temp & 0x100)
309  		jreg07 |= 0x04;
310  	if (temp & 0x200)
311  		jreg07 |= 0x80;
312  	if (temp & 0x400)
313  		jregAE |= 0x08;
314  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp);
315  
316  	temp = (mode->crtc_vsync_end - 1) & 0x3f;
317  	if (temp & 0x10)
318  		jregAE |= 0x20;
319  	if (temp & 0x20)
320  		jregAE |= 0x40;
321  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf);
322  
323  	temp = mode->crtc_vdisplay - 1;
324  	if (temp & 0x100)
325  		jreg07 |= 0x02;
326  	if (temp & 0x200)
327  		jreg07 |= 0x40;
328  	if (temp & 0x400)
329  		jregAE |= 0x02;
330  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp);
331  
332  	temp = mode->crtc_vblank_start - 1;
333  	if (temp & 0x100)
334  		jreg07 |= 0x08;
335  	if (temp & 0x200)
336  		jreg09 |= 0x20;
337  	if (temp & 0x400)
338  		jregAE |= 0x04;
339  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp);
340  
341  	temp = mode->crtc_vblank_end - 1;
342  	if (temp & 0x100)
343  		jregAE |= 0x10;
344  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp);
345  
346  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07);
347  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
348  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
349  
350  	if (precache)
351  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
352  	else
353  		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
354  
355  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
356  }
357  
358  void ast_set_offset_reg(struct drm_crtc *crtc)
359  {
360  	struct ast_private *ast = crtc->dev->dev_private;
361  	const struct drm_framebuffer *fb = crtc->primary->fb;
362  
363  	u16 offset;
364  
365  	offset = fb->pitches[0] >> 3;
366  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
367  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
368  }
369  
370  static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mode,
371  			     struct ast_vbios_mode_info *vbios_mode)
372  {
373  	struct ast_private *ast = dev->dev_private;
374  	const struct ast_vbios_dclk_info *clk_info;
375  
376  	if ((ast->chip == AST2500) || (ast->chip == AST2600))
377  		clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
378  	else
379  		clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
380  
381  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
382  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
383  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
384  			       (clk_info->param3 & 0xc0) |
385  			       ((clk_info->param3 & 0x3) << 4));
386  }
387  
388  static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
389  			     struct ast_vbios_mode_info *vbios_mode)
390  {
391  	struct ast_private *ast = crtc->dev->dev_private;
392  	const struct drm_framebuffer *fb = crtc->primary->fb;
393  	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
394  
395  	switch (fb->format->cpp[0] * 8) {
396  	case 8:
397  		jregA0 = 0x70;
398  		jregA3 = 0x01;
399  		jregA8 = 0x00;
400  		break;
401  	case 15:
402  	case 16:
403  		jregA0 = 0x70;
404  		jregA3 = 0x04;
405  		jregA8 = 0x02;
406  		break;
407  	case 24:
408  	case 32:
409  		jregA0 = 0x70;
410  		jregA3 = 0x08;
411  		jregA8 = 0x02;
412  		break;
413  	}
414  
415  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0);
416  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3);
417  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
418  
419  	/* Set Threshold */
420  	if (ast->chip == AST2600) {
421  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0);
422  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0);
423  	} else if (ast->chip == AST2300 || ast->chip == AST2400 ||
424  		 ast->chip == AST2500) {
425  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
426  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
427  	} else if (ast->chip == AST2100 ||
428  		   ast->chip == AST1100 ||
429  		   ast->chip == AST2200 ||
430  		   ast->chip == AST2150) {
431  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f);
432  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f);
433  	} else {
434  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f);
435  		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f);
436  	}
437  }
438  
439  static void ast_set_sync_reg(struct drm_device *dev, struct drm_display_mode *mode,
440  		      struct ast_vbios_mode_info *vbios_mode)
441  {
442  	struct ast_private *ast = dev->dev_private;
443  	u8 jreg;
444  
445  	jreg  = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
446  	jreg &= ~0xC0;
447  	if (vbios_mode->enh_table->flags & NVSync)
448  		jreg |= 0x80;
449  	if (vbios_mode->enh_table->flags & NHSync)
450  		jreg |= 0x40;
451  	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
452  }
453  
454  void ast_set_start_address_crt1(struct ast_private *ast, u32 offset)
455  {
456  	u32 addr;
457  
458  	addr = offset >> 2;
459  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff));
460  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff));
461  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff));
462  }
463  
464  void ast_hide_cursor(struct drm_crtc *crtc)
465  {
466  	struct ast_private *ast = crtc->dev->dev_private;
467  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
468  }
469  
470  int ast_crtc_mode_set(struct drm_crtc *crtc,
471  		      struct drm_display_mode *mode,
472  		      struct drm_display_mode *adjusted_mode)
473  {
474  	struct drm_device *dev = crtc->dev;
475  	struct ast_private *ast = crtc->dev->dev_private;
476  	struct ast_vbios_mode_info vbios_mode;
477  	bool ret;
478  	int err;
479  
480  	if (ast->chip == AST1180) {
481  		dev_err(dev->pdev, "AST 1180 modesetting not supported\n");
482  		return -EINVAL;
483  	}
484  
485  	/* DPMS, set on */
486  	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0);
487  	if (ast->tx_chip_type == AST_TX_DP501)
488  		ast_set_dp501_video_output(crtc->dev, 1);
489  	ast_crtc_load_lut(crtc);
490  
491  	/* Get mode */
492  	ret = ast_get_vbios_mode_info(crtc, mode, adjusted_mode, &vbios_mode);
493  	if (ret == false) {
494  		dev_err(dev->pdev, "Failed to find compatible vbios mode\n");
495  		return -EINVAL;
496  	}
497  	ast_open_key(ast);
498  
499  	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa1, 0xff, 0x04);
500  
501  	ast_set_std_reg(crtc, adjusted_mode, &vbios_mode);
502  	ast_set_crtc_reg(crtc, adjusted_mode, &vbios_mode);
503  	ast_set_offset_reg(crtc);
504  	ast_set_dclk_reg(dev, adjusted_mode, &vbios_mode);
505  	ast_set_ext_reg(crtc, adjusted_mode, &vbios_mode);
506  	ast_set_sync_reg(dev, adjusted_mode, &vbios_mode);
507  
508  	err = ast_crtc_do_set_base(crtc);
509  	if (err)
510  		return err;
511  
512  	/* Commit changes */
513  
514  	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0);
515  	ast_crtc_load_lut(crtc);
516  
517  	return 0;
518  }
519  
520  enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
521  				    const unsigned int hdisplay, const unsigned int vdisplay)
522  {
523  	struct ast_private *ast = connector->dev->dev_private;
524  	int flags = MODE_NOMODE;
525  	uint32_t jtemp;
526  
527  	if (ast->support_wide_screen) {
528  		if ((hdisplay == 1680) && (vdisplay == 1050))
529  			return MODE_OK;
530  		if ((hdisplay == 1280) && (vdisplay == 800))
531  			return MODE_OK;
532  		if ((hdisplay == 1440) && (vdisplay == 900))
533  			return MODE_OK;
534  		if ((hdisplay == 1360) && (vdisplay == 768))
535  			return MODE_OK;
536  		if ((hdisplay == 1600) && (vdisplay == 900))
537  			return MODE_OK;
538  
539  		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
540  		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
541  		    (ast->chip == AST2500) || (ast->chip == AST1180) ||
542  		    (ast->chip == AST2600)) {
543  			if ((hdisplay == 1920) && (vdisplay == 1080))
544  				return MODE_OK;
545  
546  			if ((hdisplay == 1920) && (vdisplay == 1200)) {
547  				jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1,
548  							       0xff);
549  				if (jtemp & 0x01)
550  					return MODE_NOMODE;
551  				else
552  					return MODE_OK;
553  			}
554  		}
555  	}
556  	switch (hdisplay) {
557  	case 640:
558  		if (vdisplay == 480)
559  			flags = MODE_OK;
560  		break;
561  	case 800:
562  		if (vdisplay == 600)
563  			flags = MODE_OK;
564  		break;
565  	case 1024:
566  		if (vdisplay == 768)
567  			flags = MODE_OK;
568  		break;
569  	case 1280:
570  		if (vdisplay == 1024)
571  			flags = MODE_OK;
572  		break;
573  	case 1600:
574  		if (vdisplay == 1200)
575  			flags = MODE_OK;
576  		break;
577  	default:
578  		return flags;
579  	}
580  
581  	return flags;
582  }