Home | History | Annotate | Line # | Download | only in ast
      1 /*	$NetBSD: ast_mode.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2012 Red Hat Inc.
      5  * Parts based on xf86-video-ast
      6  * Copyright (c) 2005 ASPEED Technology Inc.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * The above copyright notice and this permission notice (including the
     25  * next paragraph) shall be included in all copies or substantial portions
     26  * of the Software.
     27  *
     28  */
     29 /*
     30  * Authors: Dave Airlie <airlied (at) redhat.com>
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: ast_mode.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $");
     35 
     36 #include <linux/export.h>
     37 #include <linux/pci.h>
     38 
     39 #include <drm/drm_atomic.h>
     40 #include <drm/drm_atomic_helper.h>
     41 #include <drm/drm_atomic_state_helper.h>
     42 #include <drm/drm_crtc.h>
     43 #include <drm/drm_crtc_helper.h>
     44 #include <drm/drm_fourcc.h>
     45 #include <drm/drm_gem_vram_helper.h>
     46 #include <drm/drm_plane_helper.h>
     47 #include <drm/drm_probe_helper.h>
     48 
     49 #include "ast_drv.h"
     50 #include "ast_tables.h"
     51 
     52 static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
     53 static void ast_i2c_destroy(struct ast_i2c_chan *i2c);
     54 static int ast_cursor_move(struct drm_crtc *crtc,
     55 			   int x, int y);
     56 
     57 
     58 static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height);
     59 static int ast_cursor_update(void *dst, void *src, unsigned int width,
     60 			     unsigned int height);
     61 static void ast_cursor_set_base(struct ast_private *ast, u64 address);
     62 static int ast_cursor_move(struct drm_crtc *crtc,
     63 			   int x, int y);
     64 
     65 static inline void ast_load_palette_index(struct ast_private *ast,
     66 				     u8 index, u8 red, u8 green,
     67 				     u8 blue)
     68 {
     69 	ast_io_write8(ast, AST_IO_DAC_INDEX_WRITE, index);
     70 	ast_io_read8(ast, AST_IO_SEQ_PORT);
     71 	ast_io_write8(ast, AST_IO_DAC_DATA, red);
     72 	ast_io_read8(ast, AST_IO_SEQ_PORT);
     73 	ast_io_write8(ast, AST_IO_DAC_DATA, green);
     74 	ast_io_read8(ast, AST_IO_SEQ_PORT);
     75 	ast_io_write8(ast, AST_IO_DAC_DATA, blue);
     76 	ast_io_read8(ast, AST_IO_SEQ_PORT);
     77 }
     78 
     79 static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc)
     80 {
     81 	u16 *r, *g, *b;
     82 	int i;
     83 
     84 	if (!crtc->enabled)
     85 		return;
     86 
     87 	r = crtc->gamma_store;
     88 	g = r + crtc->gamma_size;
     89 	b = g + crtc->gamma_size;
     90 
     91 	for (i = 0; i < 256; i++)
     92 		ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8);
     93 }
     94 
     95 static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
     96 				    const struct drm_display_mode *mode,
     97 				    struct drm_display_mode *adjusted_mode,
     98 				    struct ast_vbios_mode_info *vbios_mode)
     99 {
    100 	u32 refresh_rate_index = 0, refresh_rate;
    101 	const struct ast_vbios_enhtable *best = NULL;
    102 	u32 hborder, vborder;
    103 	bool check_sync;
    104 
    105 	switch (format->cpp[0] * 8) {
    106 	case 8:
    107 		vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
    108 		break;
    109 	case 16:
    110 		vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
    111 		break;
    112 	case 24:
    113 	case 32:
    114 		vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
    115 		break;
    116 	default:
    117 		return false;
    118 	}
    119 
    120 	switch (mode->crtc_hdisplay) {
    121 	case 640:
    122 		vbios_mode->enh_table = &res_640x480[refresh_rate_index];
    123 		break;
    124 	case 800:
    125 		vbios_mode->enh_table = &res_800x600[refresh_rate_index];
    126 		break;
    127 	case 1024:
    128 		vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
    129 		break;
    130 	case 1280:
    131 		if (mode->crtc_vdisplay == 800)
    132 			vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
    133 		else
    134 			vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
    135 		break;
    136 	case 1360:
    137 		vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
    138 		break;
    139 	case 1440:
    140 		vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
    141 		break;
    142 	case 1600:
    143 		if (mode->crtc_vdisplay == 900)
    144 			vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
    145 		else
    146 			vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
    147 		break;
    148 	case 1680:
    149 		vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
    150 		break;
    151 	case 1920:
    152 		if (mode->crtc_vdisplay == 1080)
    153 			vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
    154 		else
    155 			vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
    156 		break;
    157 	default:
    158 		return false;
    159 	}
    160 
    161 	refresh_rate = drm_mode_vrefresh(mode);
    162 	check_sync = vbios_mode->enh_table->flags & WideScreenMode;
    163 
    164 	while (1) {
    165 		const struct ast_vbios_enhtable *loop = vbios_mode->enh_table;
    166 
    167 		while (loop->refresh_rate != 0xff) {
    168 			if ((check_sync) &&
    169 			    (((mode->flags & DRM_MODE_FLAG_NVSYNC)  &&
    170 			      (loop->flags & PVSync))  ||
    171 			     ((mode->flags & DRM_MODE_FLAG_PVSYNC)  &&
    172 			      (loop->flags & NVSync))  ||
    173 			     ((mode->flags & DRM_MODE_FLAG_NHSYNC)  &&
    174 			      (loop->flags & PHSync))  ||
    175 			     ((mode->flags & DRM_MODE_FLAG_PHSYNC)  &&
    176 			      (loop->flags & NHSync)))) {
    177 				loop++;
    178 				continue;
    179 			}
    180 			if (loop->refresh_rate <= refresh_rate
    181 			    && (!best || loop->refresh_rate > best->refresh_rate))
    182 				best = loop;
    183 			loop++;
    184 		}
    185 		if (best || !check_sync)
    186 			break;
    187 		check_sync = 0;
    188 	}
    189 
    190 	if (best)
    191 		vbios_mode->enh_table = best;
    192 
    193 	hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
    194 	vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
    195 
    196 	adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht;
    197 	adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder;
    198 	adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder;
    199 	adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder +
    200 		vbios_mode->enh_table->hfp;
    201 	adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder +
    202 					 vbios_mode->enh_table->hfp +
    203 					 vbios_mode->enh_table->hsync);
    204 
    205 	adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt;
    206 	adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder;
    207 	adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder;
    208 	adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder +
    209 		vbios_mode->enh_table->vfp;
    210 	adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder +
    211 					 vbios_mode->enh_table->vfp +
    212 					 vbios_mode->enh_table->vsync);
    213 
    214 	return true;
    215 }
    216 
    217 static void ast_set_vbios_color_reg(struct ast_private *ast,
    218 				    const struct drm_format_info *format,
    219 				    const struct ast_vbios_mode_info *vbios_mode)
    220 {
    221 	u32 color_index;
    222 
    223 	switch (format->cpp[0]) {
    224 	case 1:
    225 		color_index = VGAModeIndex - 1;
    226 		break;
    227 	case 2:
    228 		color_index = HiCModeIndex;
    229 		break;
    230 	case 3:
    231 	case 4:
    232 		color_index = TrueCModeIndex;
    233 	default:
    234 		return;
    235 	}
    236 
    237 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0x0f) << 4));
    238 
    239 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
    240 
    241 	if (vbios_mode->enh_table->flags & NewModeInfo) {
    242 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
    243 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, format->cpp[0] * 8);
    244 	}
    245 }
    246 
    247 static void ast_set_vbios_mode_reg(struct ast_private *ast,
    248 				   const struct drm_display_mode *adjusted_mode,
    249 				   const struct ast_vbios_mode_info *vbios_mode)
    250 {
    251 	u32 refresh_rate_index, mode_id;
    252 
    253 	refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
    254 	mode_id = vbios_mode->enh_table->mode_id;
    255 
    256 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
    257 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);
    258 
    259 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
    260 
    261 	if (vbios_mode->enh_table->flags & NewModeInfo) {
    262 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
    263 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
    264 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
    265 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);
    266 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay);
    267 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8);
    268 	}
    269 }
    270 
    271 static void ast_set_std_reg(struct ast_private *ast,
    272 			    struct drm_display_mode *mode,
    273 			    struct ast_vbios_mode_info *vbios_mode)
    274 {
    275 	const struct ast_vbios_stdtable *stdtable;
    276 	u32 i;
    277 	u8 jreg;
    278 
    279 	stdtable = vbios_mode->std_table;
    280 
    281 	jreg = stdtable->misc;
    282 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
    283 
    284 	/* Set SEQ; except Screen Disable field */
    285 	ast_set_index_reg(ast, AST_IO_SEQ_PORT, 0x00, 0x03);
    286 	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x01, 0xdf, stdtable->seq[0]);
    287 	for (i = 1; i < 4; i++) {
    288 		jreg = stdtable->seq[i];
    289 		ast_set_index_reg(ast, AST_IO_SEQ_PORT, (i + 1) , jreg);
    290 	}
    291 
    292 	/* Set CRTC; except base address and offset */
    293 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
    294 	for (i = 0; i < 12; i++)
    295 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
    296 	for (i = 14; i < 19; i++)
    297 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
    298 	for (i = 20; i < 25; i++)
    299 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, stdtable->crtc[i]);
    300 
    301 	/* set AR */
    302 	jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
    303 	for (i = 0; i < 20; i++) {
    304 		jreg = stdtable->ar[i];
    305 		ast_io_write8(ast, AST_IO_AR_PORT_WRITE, (u8)i);
    306 		ast_io_write8(ast, AST_IO_AR_PORT_WRITE, jreg);
    307 	}
    308 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x14);
    309 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x00);
    310 
    311 	jreg = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
    312 	ast_io_write8(ast, AST_IO_AR_PORT_WRITE, 0x20);
    313 
    314 	/* Set GR */
    315 	for (i = 0; i < 9; i++)
    316 		ast_set_index_reg(ast, AST_IO_GR_PORT, i, stdtable->gr[i]);
    317 }
    318 
    319 static void ast_set_crtc_reg(struct ast_private *ast,
    320 			     struct drm_display_mode *mode,
    321 			     struct ast_vbios_mode_info *vbios_mode)
    322 {
    323 	u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0;
    324 	u16 temp, precache = 0;
    325 
    326 	if ((ast->chip == AST2500) &&
    327 	    (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
    328 		precache = 40;
    329 
    330 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
    331 
    332 	temp = (mode->crtc_htotal >> 3) - 5;
    333 	if (temp & 0x100)
    334 		jregAC |= 0x01; /* HT D[8] */
    335 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x00, 0x00, temp);
    336 
    337 	temp = (mode->crtc_hdisplay >> 3) - 1;
    338 	if (temp & 0x100)
    339 		jregAC |= 0x04; /* HDE D[8] */
    340 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x01, 0x00, temp);
    341 
    342 	temp = (mode->crtc_hblank_start >> 3) - 1;
    343 	if (temp & 0x100)
    344 		jregAC |= 0x10; /* HBS D[8] */
    345 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x02, 0x00, temp);
    346 
    347 	temp = ((mode->crtc_hblank_end >> 3) - 1) & 0x7f;
    348 	if (temp & 0x20)
    349 		jreg05 |= 0x80;  /* HBE D[5] */
    350 	if (temp & 0x40)
    351 		jregAD |= 0x01;  /* HBE D[5] */
    352 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f));
    353 
    354 	temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
    355 	if (temp & 0x100)
    356 		jregAC |= 0x40; /* HRS D[5] */
    357 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp);
    358 
    359 	temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
    360 	if (temp & 0x20)
    361 		jregAD |= 0x04; /* HRE D[5] */
    362 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
    363 
    364 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAC, 0x00, jregAC);
    365 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAD, 0x00, jregAD);
    366 
    367 	/* vert timings */
    368 	temp = (mode->crtc_vtotal) - 2;
    369 	if (temp & 0x100)
    370 		jreg07 |= 0x01;
    371 	if (temp & 0x200)
    372 		jreg07 |= 0x20;
    373 	if (temp & 0x400)
    374 		jregAE |= 0x01;
    375 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x06, 0x00, temp);
    376 
    377 	temp = (mode->crtc_vsync_start) - 1;
    378 	if (temp & 0x100)
    379 		jreg07 |= 0x04;
    380 	if (temp & 0x200)
    381 		jreg07 |= 0x80;
    382 	if (temp & 0x400)
    383 		jregAE |= 0x08;
    384 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x10, 0x00, temp);
    385 
    386 	temp = (mode->crtc_vsync_end - 1) & 0x3f;
    387 	if (temp & 0x10)
    388 		jregAE |= 0x20;
    389 	if (temp & 0x20)
    390 		jregAE |= 0x40;
    391 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x70, temp & 0xf);
    392 
    393 	temp = mode->crtc_vdisplay - 1;
    394 	if (temp & 0x100)
    395 		jreg07 |= 0x02;
    396 	if (temp & 0x200)
    397 		jreg07 |= 0x40;
    398 	if (temp & 0x400)
    399 		jregAE |= 0x02;
    400 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x12, 0x00, temp);
    401 
    402 	temp = mode->crtc_vblank_start - 1;
    403 	if (temp & 0x100)
    404 		jreg07 |= 0x08;
    405 	if (temp & 0x200)
    406 		jreg09 |= 0x20;
    407 	if (temp & 0x400)
    408 		jregAE |= 0x04;
    409 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x15, 0x00, temp);
    410 
    411 	temp = mode->crtc_vblank_end - 1;
    412 	if (temp & 0x100)
    413 		jregAE |= 0x10;
    414 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x16, 0x00, temp);
    415 
    416 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x07, 0x00, jreg07);
    417 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
    418 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
    419 
    420 	if (precache)
    421 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
    422 	else
    423 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
    424 
    425 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
    426 }
    427 
    428 static void ast_set_offset_reg(struct ast_private *ast,
    429 			       struct drm_framebuffer *fb)
    430 {
    431 	u16 offset;
    432 
    433 	offset = fb->pitches[0] >> 3;
    434 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x13, (offset & 0xff));
    435 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xb0, (offset >> 8) & 0x3f);
    436 }
    437 
    438 static void ast_set_dclk_reg(struct ast_private *ast,
    439 			     struct drm_display_mode *mode,
    440 			     struct ast_vbios_mode_info *vbios_mode)
    441 {
    442 	const struct ast_vbios_dclk_info *clk_info;
    443 
    444 	if (ast->chip == AST2500)
    445 		clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
    446 	else
    447 		clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
    448 
    449 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
    450 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
    451 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
    452 			       (clk_info->param3 & 0xc0) |
    453 			       ((clk_info->param3 & 0x3) << 4));
    454 }
    455 
    456 static void ast_set_color_reg(struct ast_private *ast,
    457 			      const struct drm_format_info *format)
    458 {
    459 	u8 jregA0 = 0, jregA3 = 0, jregA8 = 0;
    460 
    461 	switch (format->cpp[0] * 8) {
    462 	case 8:
    463 		jregA0 = 0x70;
    464 		jregA3 = 0x01;
    465 		jregA8 = 0x00;
    466 		break;
    467 	case 15:
    468 	case 16:
    469 		jregA0 = 0x70;
    470 		jregA3 = 0x04;
    471 		jregA8 = 0x02;
    472 		break;
    473 	case 32:
    474 		jregA0 = 0x70;
    475 		jregA3 = 0x08;
    476 		jregA8 = 0x02;
    477 		break;
    478 	}
    479 
    480 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa0, 0x8f, jregA0);
    481 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xf0, jregA3);
    482 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
    483 }
    484 
    485 static void ast_set_crtthd_reg(struct ast_private *ast)
    486 {
    487 	/* Set Threshold */
    488 	if (ast->chip == AST2300 || ast->chip == AST2400 ||
    489 	    ast->chip == AST2500) {
    490 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
    491 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
    492 	} else if (ast->chip == AST2100 ||
    493 		   ast->chip == AST1100 ||
    494 		   ast->chip == AST2200 ||
    495 		   ast->chip == AST2150) {
    496 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x3f);
    497 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x2f);
    498 	} else {
    499 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x2f);
    500 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x1f);
    501 	}
    502 }
    503 
    504 static void ast_set_sync_reg(struct ast_private *ast,
    505 			     struct drm_display_mode *mode,
    506 			     struct ast_vbios_mode_info *vbios_mode)
    507 {
    508 	u8 jreg;
    509 
    510 	jreg  = ast_io_read8(ast, AST_IO_MISC_PORT_READ);
    511 	jreg &= ~0xC0;
    512 	if (vbios_mode->enh_table->flags & NVSync) jreg |= 0x80;
    513 	if (vbios_mode->enh_table->flags & NHSync) jreg |= 0x40;
    514 	ast_io_write8(ast, AST_IO_MISC_PORT_WRITE, jreg);
    515 }
    516 
    517 static void ast_set_start_address_crt1(struct ast_private *ast,
    518 				       unsigned offset)
    519 {
    520 	u32 addr;
    521 
    522 	addr = offset >> 2;
    523 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0d, (u8)(addr & 0xff));
    524 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x0c, (u8)((addr >> 8) & 0xff));
    525 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xaf, (u8)((addr >> 16) & 0xff));
    526 
    527 }
    528 
    529 /*
    530  * Primary plane
    531  */
    532 
    533 static const uint32_t ast_primary_plane_formats[] = {
    534 	DRM_FORMAT_XRGB8888,
    535 	DRM_FORMAT_RGB565,
    536 	DRM_FORMAT_C8,
    537 };
    538 
    539 static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
    540 						 struct drm_plane_state *state)
    541 {
    542 	struct drm_crtc_state *crtc_state;
    543 	struct ast_crtc_state *ast_crtc_state;
    544 	int ret;
    545 
    546 	if (!state->crtc)
    547 		return 0;
    548 
    549 	crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
    550 
    551 	ret = drm_atomic_helper_check_plane_state(state, crtc_state,
    552 						  DRM_PLANE_HELPER_NO_SCALING,
    553 						  DRM_PLANE_HELPER_NO_SCALING,
    554 						  false, true);
    555 	if (ret)
    556 		return ret;
    557 
    558 	if (!state->visible)
    559 		return 0;
    560 
    561 	ast_crtc_state = to_ast_crtc_state(crtc_state);
    562 
    563 	ast_crtc_state->format = state->fb->format;
    564 
    565 	return 0;
    566 }
    567 
    568 void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
    569 					    struct drm_plane_state *old_state)
    570 {
    571 	struct ast_private *ast = plane->dev->dev_private;
    572 	struct drm_plane_state *state = plane->state;
    573 	struct drm_gem_vram_object *gbo;
    574 	s64 gpu_addr;
    575 
    576 	gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
    577 	gpu_addr = drm_gem_vram_offset(gbo);
    578 	if (WARN_ON_ONCE(gpu_addr < 0))
    579 		return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
    580 
    581 	ast_set_offset_reg(ast, state->fb);
    582 	ast_set_start_address_crt1(ast, (u32)gpu_addr);
    583 
    584 	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
    585 }
    586 
    587 static void
    588 ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
    589 					struct drm_plane_state *old_state)
    590 {
    591 	struct ast_private *ast = plane->dev->dev_private;
    592 
    593 	ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x20);
    594 }
    595 
    596 static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
    597 	.prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
    598 	.cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
    599 	.atomic_check = ast_primary_plane_helper_atomic_check,
    600 	.atomic_update = ast_primary_plane_helper_atomic_update,
    601 	.atomic_disable = ast_primary_plane_helper_atomic_disable,
    602 };
    603 
    604 static const struct drm_plane_funcs ast_primary_plane_funcs = {
    605 	.update_plane = drm_atomic_helper_update_plane,
    606 	.disable_plane = drm_atomic_helper_disable_plane,
    607 	.destroy = drm_plane_cleanup,
    608 	.reset = drm_atomic_helper_plane_reset,
    609 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
    610 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
    611 };
    612 
    613 /*
    614  * Cursor plane
    615  */
    616 
    617 static const uint32_t ast_cursor_plane_formats[] = {
    618 	DRM_FORMAT_ARGB8888,
    619 };
    620 
    621 static int
    622 ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane,
    623 				   struct drm_plane_state *new_state)
    624 {
    625 	struct drm_framebuffer *fb = new_state->fb;
    626 	struct drm_crtc *crtc = new_state->crtc;
    627 	struct drm_gem_vram_object *gbo;
    628 	struct ast_private *ast;
    629 	int ret;
    630 	void *src, *dst;
    631 
    632 	if (!crtc || !fb)
    633 		return 0;
    634 
    635 	if (WARN_ON_ONCE(fb->width > AST_MAX_HWC_WIDTH) ||
    636 	    WARN_ON_ONCE(fb->height > AST_MAX_HWC_HEIGHT))
    637 		return -EINVAL; /* BUG: didn't test in atomic_check() */
    638 
    639 	ast = crtc->dev->dev_private;
    640 
    641 	gbo = drm_gem_vram_of_gem(fb->obj[0]);
    642 	src = drm_gem_vram_vmap(gbo);
    643 	if (IS_ERR(src)) {
    644 		ret = PTR_ERR(src);
    645 		goto err_drm_gem_vram_unpin;
    646 	}
    647 
    648 	dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]);
    649 	if (IS_ERR(dst)) {
    650 		ret = PTR_ERR(dst);
    651 		goto err_drm_gem_vram_vunmap_src;
    652 	}
    653 
    654 	ret = ast_cursor_update(dst, src, fb->width, fb->height);
    655 	if (ret)
    656 		goto err_drm_gem_vram_vunmap_dst;
    657 
    658 	/* Always unmap buffers here. Destination buffers are
    659 	 * perma-pinned while the driver is active. We're only
    660 	 * changing ref-counters here.
    661 	 */
    662 	drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst);
    663 	drm_gem_vram_vunmap(gbo, src);
    664 
    665 	return 0;
    666 
    667 err_drm_gem_vram_vunmap_dst:
    668 	drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst);
    669 err_drm_gem_vram_vunmap_src:
    670 	drm_gem_vram_vunmap(gbo, src);
    671 err_drm_gem_vram_unpin:
    672 	drm_gem_vram_unpin(gbo);
    673 	return ret;
    674 }
    675 
    676 static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
    677 						struct drm_plane_state *state)
    678 {
    679 	struct drm_framebuffer *fb = state->fb;
    680 	struct drm_crtc_state *crtc_state;
    681 	int ret;
    682 
    683 	if (!state->crtc)
    684 		return 0;
    685 
    686 	crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc);
    687 
    688 	ret = drm_atomic_helper_check_plane_state(state, crtc_state,
    689 						  DRM_PLANE_HELPER_NO_SCALING,
    690 						  DRM_PLANE_HELPER_NO_SCALING,
    691 						  true, true);
    692 	if (ret)
    693 		return ret;
    694 
    695 	if (!state->visible)
    696 		return 0;
    697 
    698 	if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT)
    699 		return -EINVAL;
    700 
    701 	return 0;
    702 }
    703 
    704 static void
    705 ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
    706 				      struct drm_plane_state *old_state)
    707 {
    708 	struct drm_plane_state *state = plane->state;
    709 	struct drm_crtc *crtc = state->crtc;
    710 	struct drm_framebuffer *fb = state->fb;
    711 	struct ast_private *ast = plane->dev->dev_private;
    712 	struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
    713 	struct drm_gem_vram_object *gbo;
    714 	s64 off;
    715 	u8 jreg;
    716 
    717 	ast_crtc->offset_x = AST_MAX_HWC_WIDTH - fb->width;
    718 	ast_crtc->offset_y = AST_MAX_HWC_WIDTH - fb->height;
    719 
    720 	if (state->fb != old_state->fb) {
    721 		/* A new cursor image was installed. */
    722 		gbo = ast->cursor.gbo[ast->cursor.next_index];
    723 		off = drm_gem_vram_offset(gbo);
    724 		if (WARN_ON_ONCE(off < 0))
    725 			return; /* Bug: we didn't pin cursor HW BO to VRAM. */
    726 		ast_cursor_set_base(ast, off);
    727 
    728 		++ast->cursor.next_index;
    729 		ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo);
    730 	}
    731 
    732 	ast_cursor_move(crtc, state->crtc_x, state->crtc_y);
    733 
    734 	jreg = 0x2;
    735 	/* enable ARGB cursor */
    736 	jreg |= 1;
    737 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
    738 }
    739 
    740 static void
    741 ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
    742 				       struct drm_plane_state *old_state)
    743 {
    744 	struct ast_private *ast = plane->dev->dev_private;
    745 
    746 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
    747 }
    748 
    749 static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
    750 	.prepare_fb = ast_cursor_plane_helper_prepare_fb,
    751 	.cleanup_fb = NULL, /* not required for cursor plane */
    752 	.atomic_check = ast_cursor_plane_helper_atomic_check,
    753 	.atomic_update = ast_cursor_plane_helper_atomic_update,
    754 	.atomic_disable = ast_cursor_plane_helper_atomic_disable,
    755 };
    756 
    757 static const struct drm_plane_funcs ast_cursor_plane_funcs = {
    758 	.update_plane = drm_atomic_helper_update_plane,
    759 	.disable_plane = drm_atomic_helper_disable_plane,
    760 	.destroy = drm_plane_cleanup,
    761 	.reset = drm_atomic_helper_plane_reset,
    762 	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
    763 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
    764 };
    765 
    766 /*
    767  * CRTC
    768  */
    769 
    770 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
    771 {
    772 	struct ast_private *ast = crtc->dev->dev_private;
    773 
    774 	if (ast->chip == AST1180)
    775 		return;
    776 
    777 	/* TODO: Maybe control display signal generation with
    778 	 *       Sync Enable (bit CR17.7).
    779 	 */
    780 	switch (mode) {
    781 	case DRM_MODE_DPMS_ON:
    782 	case DRM_MODE_DPMS_STANDBY:
    783 	case DRM_MODE_DPMS_SUSPEND:
    784 		if (ast->tx_chip_type == AST_TX_DP501)
    785 			ast_set_dp501_video_output(crtc->dev, 1);
    786 		ast_crtc_load_lut(ast, crtc);
    787 		break;
    788 	case DRM_MODE_DPMS_OFF:
    789 		if (ast->tx_chip_type == AST_TX_DP501)
    790 			ast_set_dp501_video_output(crtc->dev, 0);
    791 		break;
    792 	}
    793 }
    794 
    795 static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
    796 					struct drm_crtc_state *state)
    797 {
    798 	struct ast_private *ast = crtc->dev->dev_private;
    799 	struct ast_crtc_state *ast_state;
    800 	const struct drm_format_info *format;
    801 	bool succ;
    802 
    803 	if (ast->chip == AST1180) {
    804 		DRM_ERROR("AST 1180 modesetting not supported\n");
    805 		return -EINVAL;
    806 	}
    807 
    808 	ast_state = to_ast_crtc_state(state);
    809 
    810 	format = ast_state->format;
    811 	if (!format)
    812 		return 0;
    813 
    814 	succ = ast_get_vbios_mode_info(format, &state->mode,
    815 				       &state->adjusted_mode,
    816 				       &ast_state->vbios_mode_info);
    817 	if (!succ)
    818 		return -EINVAL;
    819 
    820 	return 0;
    821 }
    822 
    823 static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc,
    824 					 struct drm_crtc_state *old_crtc_state)
    825 {
    826 	struct ast_private *ast = crtc->dev->dev_private;
    827 
    828 	ast_open_key(ast);
    829 }
    830 
    831 static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
    832 					 struct drm_crtc_state *old_crtc_state)
    833 {
    834 	struct drm_device *dev = crtc->dev;
    835 	struct ast_private *ast = dev->dev_private;
    836 	struct ast_crtc_state *ast_state;
    837 	const struct drm_format_info *format;
    838 	struct ast_vbios_mode_info *vbios_mode_info;
    839 	struct drm_display_mode *adjusted_mode;
    840 
    841 	crtc->state->no_vblank = true;
    842 
    843 	ast_state = to_ast_crtc_state(crtc->state);
    844 
    845 	format = ast_state->format;
    846 	if (!format)
    847 		return;
    848 
    849 	vbios_mode_info = &ast_state->vbios_mode_info;
    850 
    851 	ast_set_color_reg(ast, format);
    852 	ast_set_vbios_color_reg(ast, format, vbios_mode_info);
    853 
    854 	if (!crtc->state->mode_changed)
    855 		return;
    856 
    857 	adjusted_mode = &crtc->state->adjusted_mode;
    858 
    859 	ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
    860 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa1, 0x06);
    861 	ast_set_std_reg(ast, adjusted_mode, vbios_mode_info);
    862 	ast_set_crtc_reg(ast, adjusted_mode, vbios_mode_info);
    863 	ast_set_dclk_reg(ast, adjusted_mode, vbios_mode_info);
    864 	ast_set_crtthd_reg(ast);
    865 	ast_set_sync_reg(ast, adjusted_mode, vbios_mode_info);
    866 }
    867 
    868 static void
    869 ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
    870 			      struct drm_crtc_state *old_crtc_state)
    871 {
    872 	ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
    873 }
    874 
    875 static void
    876 ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
    877 			       struct drm_crtc_state *old_crtc_state)
    878 {
    879 	ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
    880 }
    881 
    882 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
    883 	.atomic_check = ast_crtc_helper_atomic_check,
    884 	.atomic_begin = ast_crtc_helper_atomic_begin,
    885 	.atomic_flush = ast_crtc_helper_atomic_flush,
    886 	.atomic_enable = ast_crtc_helper_atomic_enable,
    887 	.atomic_disable = ast_crtc_helper_atomic_disable,
    888 };
    889 
    890 static void ast_crtc_destroy(struct drm_crtc *crtc)
    891 {
    892 	drm_crtc_cleanup(crtc);
    893 	kfree(crtc);
    894 }
    895 
    896 static struct drm_crtc_state *
    897 ast_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
    898 {
    899 	struct ast_crtc_state *new_ast_state, *ast_state;
    900 
    901 	if (WARN_ON(!crtc->state))
    902 		return NULL;
    903 
    904 	new_ast_state = kmalloc(sizeof(*new_ast_state), GFP_KERNEL);
    905 	if (!new_ast_state)
    906 		return NULL;
    907 	__drm_atomic_helper_crtc_duplicate_state(crtc, &new_ast_state->base);
    908 
    909 	ast_state = to_ast_crtc_state(crtc->state);
    910 
    911 	new_ast_state->format = ast_state->format;
    912 	memcpy(&new_ast_state->vbios_mode_info, &ast_state->vbios_mode_info,
    913 	       sizeof(new_ast_state->vbios_mode_info));
    914 
    915 	return &new_ast_state->base;
    916 }
    917 
    918 static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
    919 					  struct drm_crtc_state *state)
    920 {
    921 	struct ast_crtc_state *ast_state = to_ast_crtc_state(state);
    922 
    923 	__drm_atomic_helper_crtc_destroy_state(&ast_state->base);
    924 	kfree(ast_state);
    925 }
    926 
    927 static const struct drm_crtc_funcs ast_crtc_funcs = {
    928 	.reset = drm_atomic_helper_crtc_reset,
    929 	.set_config = drm_crtc_helper_set_config,
    930 	.gamma_set = drm_atomic_helper_legacy_gamma_set,
    931 	.destroy = ast_crtc_destroy,
    932 	.set_config = drm_atomic_helper_set_config,
    933 	.page_flip = drm_atomic_helper_page_flip,
    934 	.atomic_duplicate_state = ast_crtc_atomic_duplicate_state,
    935 	.atomic_destroy_state = ast_crtc_atomic_destroy_state,
    936 };
    937 
    938 static int ast_crtc_init(struct drm_device *dev)
    939 {
    940 	struct ast_private *ast = dev->dev_private;
    941 	struct ast_crtc *crtc;
    942 	int ret;
    943 
    944 	crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL);
    945 	if (!crtc)
    946 		return -ENOMEM;
    947 
    948 	ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane,
    949 					&ast->cursor_plane, &ast_crtc_funcs,
    950 					NULL);
    951 	if (ret)
    952 		goto err_kfree;
    953 
    954 	drm_mode_crtc_set_gamma_size(&crtc->base, 256);
    955 	drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
    956 	return 0;
    957 
    958 err_kfree:
    959 	kfree(crtc);
    960 	return ret;
    961 }
    962 
    963 /*
    964  * Encoder
    965  */
    966 
    967 static void ast_encoder_destroy(struct drm_encoder *encoder)
    968 {
    969 	drm_encoder_cleanup(encoder);
    970 	kfree(encoder);
    971 }
    972 
    973 static const struct drm_encoder_funcs ast_enc_funcs = {
    974 	.destroy = ast_encoder_destroy,
    975 };
    976 
    977 static int ast_encoder_init(struct drm_device *dev)
    978 {
    979 	struct ast_encoder *ast_encoder;
    980 
    981 	ast_encoder = kzalloc(sizeof(struct ast_encoder), GFP_KERNEL);
    982 	if (!ast_encoder)
    983 		return -ENOMEM;
    984 
    985 	drm_encoder_init(dev, &ast_encoder->base, &ast_enc_funcs,
    986 			 DRM_MODE_ENCODER_DAC, NULL);
    987 
    988 	ast_encoder->base.possible_crtcs = 1;
    989 	return 0;
    990 }
    991 
    992 /*
    993  * Connector
    994  */
    995 
    996 static int ast_get_modes(struct drm_connector *connector)
    997 {
    998 	struct ast_connector *ast_connector = to_ast_connector(connector);
    999 	struct ast_private *ast = connector->dev->dev_private;
   1000 	struct edid *edid;
   1001 	int ret;
   1002 	bool flags = false;
   1003 	if (ast->tx_chip_type == AST_TX_DP501) {
   1004 		ast->dp501_maxclk = 0xff;
   1005 		edid = kmalloc(128, GFP_KERNEL);
   1006 		if (!edid)
   1007 			return -ENOMEM;
   1008 
   1009 		flags = ast_dp501_read_edid(connector->dev, (u8 *)edid);
   1010 		if (flags)
   1011 			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
   1012 		else
   1013 			kfree(edid);
   1014 	}
   1015 	if (!flags)
   1016 		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
   1017 	if (edid) {
   1018 		drm_connector_update_edid_property(&ast_connector->base, edid);
   1019 		ret = drm_add_edid_modes(connector, edid);
   1020 		kfree(edid);
   1021 		return ret;
   1022 	} else
   1023 		drm_connector_update_edid_property(&ast_connector->base, NULL);
   1024 	return 0;
   1025 }
   1026 
   1027 static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
   1028 			  struct drm_display_mode *mode)
   1029 {
   1030 	struct ast_private *ast = connector->dev->dev_private;
   1031 	int flags = MODE_NOMODE;
   1032 	uint32_t jtemp;
   1033 
   1034 	if (ast->support_wide_screen) {
   1035 		if ((mode->hdisplay == 1680) && (mode->vdisplay == 1050))
   1036 			return MODE_OK;
   1037 		if ((mode->hdisplay == 1280) && (mode->vdisplay == 800))
   1038 			return MODE_OK;
   1039 		if ((mode->hdisplay == 1440) && (mode->vdisplay == 900))
   1040 			return MODE_OK;
   1041 		if ((mode->hdisplay == 1360) && (mode->vdisplay == 768))
   1042 			return MODE_OK;
   1043 		if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
   1044 			return MODE_OK;
   1045 
   1046 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
   1047 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
   1048 		    (ast->chip == AST2500) || (ast->chip == AST1180)) {
   1049 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
   1050 				return MODE_OK;
   1051 
   1052 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1200)) {
   1053 				jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
   1054 				if (jtemp & 0x01)
   1055 					return MODE_NOMODE;
   1056 				else
   1057 					return MODE_OK;
   1058 			}
   1059 		}
   1060 	}
   1061 	switch (mode->hdisplay) {
   1062 	case 640:
   1063 		if (mode->vdisplay == 480) flags = MODE_OK;
   1064 		break;
   1065 	case 800:
   1066 		if (mode->vdisplay == 600) flags = MODE_OK;
   1067 		break;
   1068 	case 1024:
   1069 		if (mode->vdisplay == 768) flags = MODE_OK;
   1070 		break;
   1071 	case 1280:
   1072 		if (mode->vdisplay == 1024) flags = MODE_OK;
   1073 		break;
   1074 	case 1600:
   1075 		if (mode->vdisplay == 1200) flags = MODE_OK;
   1076 		break;
   1077 	default:
   1078 		return flags;
   1079 	}
   1080 
   1081 	return flags;
   1082 }
   1083 
   1084 static void ast_connector_destroy(struct drm_connector *connector)
   1085 {
   1086 	struct ast_connector *ast_connector = to_ast_connector(connector);
   1087 	ast_i2c_destroy(ast_connector->i2c);
   1088 	drm_connector_unregister(connector);
   1089 	drm_connector_cleanup(connector);
   1090 	kfree(connector);
   1091 }
   1092 
   1093 static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
   1094 	.get_modes = ast_get_modes,
   1095 	.mode_valid = ast_mode_valid,
   1096 };
   1097 
   1098 static const struct drm_connector_funcs ast_connector_funcs = {
   1099 	.reset = drm_atomic_helper_connector_reset,
   1100 	.fill_modes = drm_helper_probe_single_connector_modes,
   1101 	.destroy = ast_connector_destroy,
   1102 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
   1103 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
   1104 };
   1105 
   1106 static int ast_connector_init(struct drm_device *dev)
   1107 {
   1108 	struct ast_connector *ast_connector;
   1109 	struct drm_connector *connector;
   1110 	struct drm_encoder *encoder;
   1111 
   1112 	ast_connector = kzalloc(sizeof(struct ast_connector), GFP_KERNEL);
   1113 	if (!ast_connector)
   1114 		return -ENOMEM;
   1115 
   1116 	connector = &ast_connector->base;
   1117 	ast_connector->i2c = ast_i2c_create(dev);
   1118 	if (!ast_connector->i2c)
   1119 		DRM_ERROR("failed to add ddc bus for connector\n");
   1120 
   1121 	drm_connector_init_with_ddc(dev, connector,
   1122 				    &ast_connector_funcs,
   1123 				    DRM_MODE_CONNECTOR_VGA,
   1124 				    &ast_connector->i2c->adapter);
   1125 
   1126 	drm_connector_helper_add(connector, &ast_connector_helper_funcs);
   1127 
   1128 	connector->interlace_allowed = 0;
   1129 	connector->doublescan_allowed = 0;
   1130 
   1131 	drm_connector_register(connector);
   1132 
   1133 	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
   1134 
   1135 	encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head);
   1136 	drm_connector_attach_encoder(connector, encoder);
   1137 
   1138 	return 0;
   1139 }
   1140 
   1141 /* allocate cursor cache and pin at start of VRAM */
   1142 static int ast_cursor_init(struct drm_device *dev)
   1143 {
   1144 	struct ast_private *ast = dev->dev_private;
   1145 	size_t size, i;
   1146 	struct drm_gem_vram_object *gbo;
   1147 	int ret;
   1148 
   1149 	size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
   1150 
   1151 	for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
   1152 		gbo = drm_gem_vram_create(dev, size, 0);
   1153 		if (IS_ERR(gbo)) {
   1154 			ret = PTR_ERR(gbo);
   1155 			goto err_drm_gem_vram_put;
   1156 		}
   1157 		ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
   1158 					    DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
   1159 		if (ret) {
   1160 			drm_gem_vram_put(gbo);
   1161 			goto err_drm_gem_vram_put;
   1162 		}
   1163 
   1164 		ast->cursor.gbo[i] = gbo;
   1165 	}
   1166 
   1167 	return 0;
   1168 
   1169 err_drm_gem_vram_put:
   1170 	while (i) {
   1171 		--i;
   1172 		gbo = ast->cursor.gbo[i];
   1173 		drm_gem_vram_unpin(gbo);
   1174 		drm_gem_vram_put(gbo);
   1175 		ast->cursor.gbo[i] = NULL;
   1176 	}
   1177 	return ret;
   1178 }
   1179 
   1180 static void ast_cursor_fini(struct drm_device *dev)
   1181 {
   1182 	struct ast_private *ast = dev->dev_private;
   1183 	size_t i;
   1184 	struct drm_gem_vram_object *gbo;
   1185 
   1186 	for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
   1187 		gbo = ast->cursor.gbo[i];
   1188 		drm_gem_vram_unpin(gbo);
   1189 		drm_gem_vram_put(gbo);
   1190 	}
   1191 }
   1192 
   1193 int ast_mode_init(struct drm_device *dev)
   1194 {
   1195 	struct ast_private *ast = dev->dev_private;
   1196 	int ret;
   1197 
   1198 	memset(&ast->primary_plane, 0, sizeof(ast->primary_plane));
   1199 	ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01,
   1200 				       &ast_primary_plane_funcs,
   1201 				       ast_primary_plane_formats,
   1202 				       ARRAY_SIZE(ast_primary_plane_formats),
   1203 				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
   1204 	if (ret) {
   1205 		DRM_ERROR("ast: drm_universal_plane_init() failed: %d\n", ret);
   1206 		return ret;
   1207 	}
   1208 	drm_plane_helper_add(&ast->primary_plane,
   1209 			     &ast_primary_plane_helper_funcs);
   1210 
   1211 	ret = drm_universal_plane_init(dev, &ast->cursor_plane, 0x01,
   1212 				       &ast_cursor_plane_funcs,
   1213 				       ast_cursor_plane_formats,
   1214 				       ARRAY_SIZE(ast_cursor_plane_formats),
   1215 				       NULL, DRM_PLANE_TYPE_CURSOR, NULL);
   1216 	if (ret) {
   1217 		DRM_ERROR("drm_universal_plane_failed(): %d\n", ret);
   1218 		return ret;
   1219 	}
   1220 	drm_plane_helper_add(&ast->cursor_plane,
   1221 			     &ast_cursor_plane_helper_funcs);
   1222 
   1223 	ast_cursor_init(dev);
   1224 	ast_crtc_init(dev);
   1225 	ast_encoder_init(dev);
   1226 	ast_connector_init(dev);
   1227 
   1228 	return 0;
   1229 }
   1230 
   1231 void ast_mode_fini(struct drm_device *dev)
   1232 {
   1233 	ast_cursor_fini(dev);
   1234 }
   1235 
   1236 static int get_clock(void *i2c_priv)
   1237 {
   1238 	struct ast_i2c_chan *i2c = i2c_priv;
   1239 	struct ast_private *ast = i2c->dev->dev_private;
   1240 	uint32_t val, val2, count, pass;
   1241 
   1242 	count = 0;
   1243 	pass = 0;
   1244 	val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
   1245 	do {
   1246 		val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
   1247 		if (val == val2) {
   1248 			pass++;
   1249 		} else {
   1250 			pass = 0;
   1251 			val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
   1252 		}
   1253 	} while ((pass < 5) && (count++ < 0x10000));
   1254 
   1255 	return val & 1 ? 1 : 0;
   1256 }
   1257 
   1258 static int get_data(void *i2c_priv)
   1259 {
   1260 	struct ast_i2c_chan *i2c = i2c_priv;
   1261 	struct ast_private *ast = i2c->dev->dev_private;
   1262 	uint32_t val, val2, count, pass;
   1263 
   1264 	count = 0;
   1265 	pass = 0;
   1266 	val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
   1267 	do {
   1268 		val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
   1269 		if (val == val2) {
   1270 			pass++;
   1271 		} else {
   1272 			pass = 0;
   1273 			val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
   1274 		}
   1275 	} while ((pass < 5) && (count++ < 0x10000));
   1276 
   1277 	return val & 1 ? 1 : 0;
   1278 }
   1279 
   1280 static void set_clock(void *i2c_priv, int clock)
   1281 {
   1282 	struct ast_i2c_chan *i2c = i2c_priv;
   1283 	struct ast_private *ast = i2c->dev->dev_private;
   1284 	int i;
   1285 	u8 ujcrb7, jtemp;
   1286 
   1287 	for (i = 0; i < 0x10000; i++) {
   1288 		ujcrb7 = ((clock & 0x01) ? 0 : 1);
   1289 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
   1290 		jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
   1291 		if (ujcrb7 == jtemp)
   1292 			break;
   1293 	}
   1294 }
   1295 
   1296 static void set_data(void *i2c_priv, int data)
   1297 {
   1298 	struct ast_i2c_chan *i2c = i2c_priv;
   1299 	struct ast_private *ast = i2c->dev->dev_private;
   1300 	int i;
   1301 	u8 ujcrb7, jtemp;
   1302 
   1303 	for (i = 0; i < 0x10000; i++) {
   1304 		ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
   1305 		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
   1306 		jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
   1307 		if (ujcrb7 == jtemp)
   1308 			break;
   1309 	}
   1310 }
   1311 
   1312 static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
   1313 {
   1314 	struct ast_i2c_chan *i2c;
   1315 	int ret;
   1316 
   1317 	i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL);
   1318 	if (!i2c)
   1319 		return NULL;
   1320 
   1321 	i2c->adapter.owner = THIS_MODULE;
   1322 	i2c->adapter.class = I2C_CLASS_DDC;
   1323 	i2c->adapter.dev.parent = &dev->pdev->dev;
   1324 	i2c->dev = dev;
   1325 	i2c_set_adapdata(&i2c->adapter, i2c);
   1326 	snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
   1327 		 "AST i2c bit bus");
   1328 	i2c->adapter.algo_data = &i2c->bit;
   1329 
   1330 	i2c->bit.udelay = 20;
   1331 	i2c->bit.timeout = 2;
   1332 	i2c->bit.data = i2c;
   1333 	i2c->bit.setsda = set_data;
   1334 	i2c->bit.setscl = set_clock;
   1335 	i2c->bit.getsda = get_data;
   1336 	i2c->bit.getscl = get_clock;
   1337 	ret = i2c_bit_add_bus(&i2c->adapter);
   1338 	if (ret) {
   1339 		DRM_ERROR("Failed to register bit i2c\n");
   1340 		goto out_free;
   1341 	}
   1342 
   1343 	return i2c;
   1344 out_free:
   1345 	kfree(i2c);
   1346 	return NULL;
   1347 }
   1348 
   1349 static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
   1350 {
   1351 	if (!i2c)
   1352 		return;
   1353 	i2c_del_adapter(&i2c->adapter);
   1354 	kfree(i2c);
   1355 }
   1356 
   1357 static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height)
   1358 {
   1359 	union {
   1360 		u32 ul;
   1361 		u8 b[4];
   1362 	} srcdata32[2], data32;
   1363 	union {
   1364 		u16 us;
   1365 		u8 b[2];
   1366 	} data16;
   1367 	u32 csum = 0;
   1368 	s32 alpha_dst_delta, last_alpha_dst_delta;
   1369 	u8 *srcxor, *dstxor;
   1370 	int i, j;
   1371 	u32 per_pixel_copy, two_pixel_copy;
   1372 
   1373 	alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
   1374 	last_alpha_dst_delta = alpha_dst_delta - (width << 1);
   1375 
   1376 	srcxor = src;
   1377 	dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
   1378 	per_pixel_copy = width & 1;
   1379 	two_pixel_copy = width >> 1;
   1380 
   1381 	for (j = 0; j < height; j++) {
   1382 		for (i = 0; i < two_pixel_copy; i++) {
   1383 			srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
   1384 			srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
   1385 			data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
   1386 			data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
   1387 			data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
   1388 			data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
   1389 
   1390 			writel(data32.ul, dstxor);
   1391 			csum += data32.ul;
   1392 
   1393 			dstxor += 4;
   1394 			srcxor += 8;
   1395 
   1396 		}
   1397 
   1398 		for (i = 0; i < per_pixel_copy; i++) {
   1399 			srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
   1400 			data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
   1401 			data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
   1402 			writew(data16.us, dstxor);
   1403 			csum += (u32)data16.us;
   1404 
   1405 			dstxor += 2;
   1406 			srcxor += 4;
   1407 		}
   1408 		dstxor += last_alpha_dst_delta;
   1409 	}
   1410 	return csum;
   1411 }
   1412 
   1413 static int ast_cursor_update(void *dst, void *src, unsigned int width,
   1414 			     unsigned int height)
   1415 {
   1416 	u32 csum;
   1417 
   1418 	/* do data transfer to cursor cache */
   1419 	csum = copy_cursor_image(src, dst, width, height);
   1420 
   1421 	/* write checksum + signature */
   1422 	dst += AST_HWC_SIZE;
   1423 	writel(csum, dst);
   1424 	writel(width, dst + AST_HWC_SIGNATURE_SizeX);
   1425 	writel(height, dst + AST_HWC_SIGNATURE_SizeY);
   1426 	writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
   1427 	writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
   1428 
   1429 	return 0;
   1430 }
   1431 
   1432 static void ast_cursor_set_base(struct ast_private *ast, u64 address)
   1433 {
   1434 	u8 addr0 = (address >> 3) & 0xff;
   1435 	u8 addr1 = (address >> 11) & 0xff;
   1436 	u8 addr2 = (address >> 19) & 0xff;
   1437 
   1438 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0);
   1439 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1);
   1440 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
   1441 }
   1442 
   1443 static int ast_cursor_move(struct drm_crtc *crtc,
   1444 			   int x, int y)
   1445 {
   1446 	struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
   1447 	struct ast_private *ast = crtc->dev->dev_private;
   1448 	struct drm_gem_vram_object *gbo;
   1449 	int x_offset, y_offset;
   1450 	u8 *dst, *sig;
   1451 	u8 jreg;
   1452 
   1453 	gbo = ast->cursor.gbo[ast->cursor.next_index];
   1454 	dst = drm_gem_vram_vmap(gbo);
   1455 	if (IS_ERR(dst))
   1456 		return PTR_ERR(dst);
   1457 
   1458 	sig = dst + AST_HWC_SIZE;
   1459 	writel(x, sig + AST_HWC_SIGNATURE_X);
   1460 	writel(y, sig + AST_HWC_SIGNATURE_Y);
   1461 
   1462 	x_offset = ast_crtc->offset_x;
   1463 	y_offset = ast_crtc->offset_y;
   1464 	if (x < 0) {
   1465 		x_offset = (-x) + ast_crtc->offset_x;
   1466 		x = 0;
   1467 	}
   1468 
   1469 	if (y < 0) {
   1470 		y_offset = (-y) + ast_crtc->offset_y;
   1471 		y = 0;
   1472 	}
   1473 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset);
   1474 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset);
   1475 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, (x & 0xff));
   1476 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, ((x >> 8) & 0x0f));
   1477 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, (y & 0xff));
   1478 	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));
   1479 
   1480 	/* dummy write to fire HWC */
   1481 	jreg = 0x02 |
   1482 	       0x01; /* enable ARGB4444 cursor */
   1483 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
   1484 
   1485 	drm_gem_vram_vunmap(gbo, dst);
   1486 
   1487 	return 0;
   1488 }
   1489