• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021, ASPEED Technology Inc.
3 // Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
4 
5 #include <linux/firmware.h>
6 #include <linux/delay.h>
7 
8 #include <drm/drm_atomic_state_helper.h>
9 #include <drm/drm_edid.h>
10 #include <drm/drm_modeset_helper_vtables.h>
11 #include <drm/drm_print.h>
12 #include <drm/drm_probe_helper.h>
13 
14 #include "ast_drv.h"
15 
ast_astdp_is_connected(struct ast_device * ast)16 static bool ast_astdp_is_connected(struct ast_device *ast)
17 {
18 	if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD))
19 		return false;
20 	/*
21 	 * HPD might be set even if no monitor is connected, so also check that
22 	 * the link training was successful.
23 	 */
24 	if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDC, AST_IO_VGACRDC_LINK_SUCCESS))
25 		return false;
26 	return true;
27 }
28 
ast_astdp_read_edid_block(void * data,u8 * buf,unsigned int block,size_t len)29 static int ast_astdp_read_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
30 {
31 	struct ast_device *ast = data;
32 	size_t rdlen = round_up(len, 4);
33 	int ret = 0;
34 	unsigned int i;
35 
36 	if (block > 0)
37 		return -EIO; /* extension headers not supported */
38 
39 	/*
40 	 * Protect access to I/O registers from concurrent modesetting
41 	 * by acquiring the I/O-register lock.
42 	 */
43 	mutex_lock(&ast->modeset_lock);
44 
45 	/* Start reading EDID data */
46 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xe5, (u8)~AST_IO_VGACRE5_EDID_READ_DONE, 0x00);
47 
48 	for (i = 0; i < rdlen; i += 4) {
49 		unsigned int offset;
50 		unsigned int j;
51 		u8 ediddata[4];
52 		u8 vgacre4;
53 
54 		offset = (i + block * EDID_LENGTH) / 4;
55 		if (offset >= 64) {
56 			ret = -EIO;
57 			goto out;
58 		}
59 		vgacre4 = offset;
60 
61 		/*
62 		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
63 		 */
64 		ast_set_index_reg(ast, AST_IO_VGACRI, 0xe4, vgacre4);
65 
66 		/*
67 		 * CRD7[b0]: valid flag for EDID
68 		 * CRD6[b0]: mirror read pointer for EDID
69 		 */
70 		for (j = 0; j < 200; ++j) {
71 			u8 vgacrd7, vgacrd6;
72 
73 			/*
74 			 * Delay are getting longer with each retry.
75 			 *
76 			 * 1. No delay on first try
77 			 * 2. The Delays are often 2 loops when users request "Display Settings"
78 			 *	  of right-click of mouse.
79 			 * 3. The Delays are often longer a lot when system resume from S3/S4.
80 			 */
81 			if (j)
82 				msleep(j + 1);
83 
84 			/* Wait for EDID offset to show up in mirror register */
85 			vgacrd7 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd7);
86 			if (vgacrd7 & AST_IO_VGACRD7_EDID_VALID_FLAG) {
87 				vgacrd6 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd6);
88 				if (vgacrd6 == offset)
89 					break;
90 			}
91 		}
92 		if (j == 200) {
93 			ret = -EBUSY;
94 			goto out;
95 		}
96 
97 		ediddata[0] = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd8);
98 		ediddata[1] = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd9);
99 		ediddata[2] = ast_get_index_reg(ast, AST_IO_VGACRI, 0xda);
100 		ediddata[3] = ast_get_index_reg(ast, AST_IO_VGACRI, 0xdb);
101 
102 		if (i == 31) {
103 			/*
104 			 * For 128-bytes EDID_1.3,
105 			 * 1. Add the value of Bytes-126 to Bytes-127.
106 			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
107 			 *		equal 0	(mod 256).
108 			 * 2. Modify Bytes-126 to be 0.
109 			 *		The Bytes-126 indicates the Number of extensions to
110 			 *		follow. 0 represents noextensions.
111 			 */
112 			ediddata[3] = ediddata[3] + ediddata[2];
113 			ediddata[2] = 0;
114 		}
115 
116 		memcpy(buf, ediddata, min((len - i), 4));
117 		buf += 4;
118 	}
119 
120 out:
121 	/* Signal end of reading */
122 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xe5, (u8)~AST_IO_VGACRE5_EDID_READ_DONE,
123 			       AST_IO_VGACRE5_EDID_READ_DONE);
124 
125 	mutex_unlock(&ast->modeset_lock);
126 
127 	return ret;
128 }
129 
130 /*
131  * Launch Aspeed DP
132  */
ast_dp_launch(struct ast_device * ast)133 int ast_dp_launch(struct ast_device *ast)
134 {
135 	struct drm_device *dev = &ast->base;
136 	unsigned int i = 10;
137 
138 	while (i) {
139 		u8 vgacrd1 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd1);
140 
141 		if (vgacrd1 & AST_IO_VGACRD1_MCU_FW_EXECUTING)
142 			break;
143 		--i;
144 		msleep(100);
145 	}
146 	if (!i) {
147 		drm_err(dev, "Wait DPMCU executing timeout\n");
148 		return -ENODEV;
149 	}
150 
151 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xe5,
152 			       (u8) ~AST_IO_VGACRE5_EDID_READ_DONE,
153 			       AST_IO_VGACRE5_EDID_READ_DONE);
154 
155 	return 0;
156 }
157 
ast_dp_power_is_on(struct ast_device * ast)158 static bool ast_dp_power_is_on(struct ast_device *ast)
159 {
160 	u8 vgacre3;
161 
162 	vgacre3 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xe3);
163 
164 	return !(vgacre3 & AST_DP_PHY_SLEEP);
165 }
166 
ast_dp_power_on_off(struct drm_device * dev,bool on)167 static void ast_dp_power_on_off(struct drm_device *dev, bool on)
168 {
169 	struct ast_device *ast = to_ast_device(dev);
170 	// Read and Turn off DP PHY sleep
171 	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, AST_DP_VIDEO_ENABLE);
172 
173 	// Turn on DP PHY sleep
174 	if (!on)
175 		bE3 |= AST_DP_PHY_SLEEP;
176 
177 	// DP Power on/off
178 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
179 
180 	msleep(50);
181 }
182 
ast_dp_link_training(struct ast_device * ast)183 static void ast_dp_link_training(struct ast_device *ast)
184 {
185 	struct drm_device *dev = &ast->base;
186 	int i;
187 
188 	for (i = 0; i < 10; i++) {
189 		u8 vgacrdc;
190 
191 		if (i)
192 			msleep(100);
193 
194 		vgacrdc = ast_get_index_reg(ast, AST_IO_VGACRI, 0xdc);
195 		if (vgacrdc & AST_IO_VGACRDC_LINK_SUCCESS)
196 			return;
197 	}
198 	drm_err(dev, "Link training failed\n");
199 }
200 
ast_dp_set_on_off(struct drm_device * dev,bool on)201 static void ast_dp_set_on_off(struct drm_device *dev, bool on)
202 {
203 	struct ast_device *ast = to_ast_device(dev);
204 	u8 video_on_off = on;
205 	u32 i = 0;
206 
207 	// Video On/Off
208 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
209 
210 	video_on_off <<= 4;
211 	while (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF,
212 						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
213 		// wait 1 ms
214 		mdelay(1);
215 		if (++i > 200)
216 			break;
217 	}
218 }
219 
ast_dp_set_mode(struct drm_crtc * crtc,struct ast_vbios_mode_info * vbios_mode)220 static void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
221 {
222 	struct ast_device *ast = to_ast_device(crtc->dev);
223 
224 	u32 ulRefreshRateIndex;
225 	u8 ModeIdx;
226 
227 	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
228 
229 	switch (crtc->mode.crtc_hdisplay) {
230 	case 320:
231 		ModeIdx = ASTDP_320x240_60;
232 		break;
233 	case 400:
234 		ModeIdx = ASTDP_400x300_60;
235 		break;
236 	case 512:
237 		ModeIdx = ASTDP_512x384_60;
238 		break;
239 	case 640:
240 		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
241 		break;
242 	case 800:
243 		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
244 		break;
245 	case 1024:
246 		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
247 		break;
248 	case 1152:
249 		ModeIdx = ASTDP_1152x864_75;
250 		break;
251 	case 1280:
252 		if (crtc->mode.crtc_vdisplay == 800)
253 			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
254 		else		// 1024
255 			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
256 		break;
257 	case 1360:
258 	case 1366:
259 		ModeIdx = ASTDP_1366x768_60;
260 		break;
261 	case 1440:
262 		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
263 		break;
264 	case 1600:
265 		if (crtc->mode.crtc_vdisplay == 900)
266 			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
267 		else		//1200
268 			ModeIdx = ASTDP_1600x1200_60;
269 		break;
270 	case 1680:
271 		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
272 		break;
273 	case 1920:
274 		if (crtc->mode.crtc_vdisplay == 1080)
275 			ModeIdx = ASTDP_1920x1080_60;
276 		else		//1200
277 			ModeIdx = ASTDP_1920x1200_60;
278 		break;
279 	default:
280 		return;
281 	}
282 
283 	/*
284 	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
285 	 * CRE1[7:0]: MISC1 (default: 0x00)
286 	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
287 	 */
288 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE0, ASTDP_AND_CLEAR_MASK,
289 			       ASTDP_MISC0_24bpp);
290 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
291 	ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
292 }
293 
ast_wait_for_vretrace(struct ast_device * ast)294 static void ast_wait_for_vretrace(struct ast_device *ast)
295 {
296 	unsigned long timeout = jiffies + HZ;
297 	u8 vgair1;
298 
299 	do {
300 		vgair1 = ast_io_read8(ast, AST_IO_VGAIR1_R);
301 	} while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
302 }
303 
304 /*
305  * Encoder
306  */
307 
308 static const struct drm_encoder_funcs ast_astdp_encoder_funcs = {
309 	.destroy = drm_encoder_cleanup,
310 };
311 
ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder * encoder,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state)312 static void ast_astdp_encoder_helper_atomic_mode_set(struct drm_encoder *encoder,
313 						     struct drm_crtc_state *crtc_state,
314 						     struct drm_connector_state *conn_state)
315 {
316 	struct drm_crtc *crtc = crtc_state->crtc;
317 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
318 	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
319 
320 	ast_dp_set_mode(crtc, vbios_mode_info);
321 }
322 
ast_astdp_encoder_helper_atomic_enable(struct drm_encoder * encoder,struct drm_atomic_state * state)323 static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
324 						   struct drm_atomic_state *state)
325 {
326 	struct drm_device *dev = encoder->dev;
327 	struct ast_device *ast = to_ast_device(dev);
328 	struct ast_connector *ast_connector = &ast->output.astdp.connector;
329 
330 	if (ast_connector->physical_status == connector_status_connected) {
331 		ast_dp_power_on_off(dev, AST_DP_POWER_ON);
332 		ast_dp_link_training(ast);
333 
334 		ast_wait_for_vretrace(ast);
335 		ast_dp_set_on_off(dev, 1);
336 	}
337 }
338 
ast_astdp_encoder_helper_atomic_disable(struct drm_encoder * encoder,struct drm_atomic_state * state)339 static void ast_astdp_encoder_helper_atomic_disable(struct drm_encoder *encoder,
340 						    struct drm_atomic_state *state)
341 {
342 	struct drm_device *dev = encoder->dev;
343 
344 	ast_dp_set_on_off(dev, 0);
345 	ast_dp_power_on_off(dev, AST_DP_POWER_OFF);
346 }
347 
348 static const struct drm_encoder_helper_funcs ast_astdp_encoder_helper_funcs = {
349 	.atomic_mode_set = ast_astdp_encoder_helper_atomic_mode_set,
350 	.atomic_enable = ast_astdp_encoder_helper_atomic_enable,
351 	.atomic_disable = ast_astdp_encoder_helper_atomic_disable,
352 };
353 
354 /*
355  * Connector
356  */
357 
ast_astdp_connector_helper_get_modes(struct drm_connector * connector)358 static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
359 {
360 	struct ast_connector *ast_connector = to_ast_connector(connector);
361 	int count;
362 
363 	if (ast_connector->physical_status == connector_status_connected) {
364 		struct ast_device *ast = to_ast_device(connector->dev);
365 		const struct drm_edid *drm_edid;
366 
367 		drm_edid = drm_edid_read_custom(connector, ast_astdp_read_edid_block, ast);
368 		drm_edid_connector_update(connector, drm_edid);
369 		count = drm_edid_connector_add_modes(connector);
370 		drm_edid_free(drm_edid);
371 	} else {
372 		drm_edid_connector_update(connector, NULL);
373 
374 		/*
375 		 * There's no EDID data without a connected monitor. Set BMC-
376 		 * compatible modes in this case. The XGA default resolution
377 		 * should work well for all BMCs.
378 		 */
379 		count = drm_add_modes_noedid(connector, 4096, 4096);
380 		if (count)
381 			drm_set_preferred_mode(connector, 1024, 768);
382 	}
383 
384 	return count;
385 }
386 
ast_astdp_connector_helper_detect_ctx(struct drm_connector * connector,struct drm_modeset_acquire_ctx * ctx,bool force)387 static int ast_astdp_connector_helper_detect_ctx(struct drm_connector *connector,
388 						 struct drm_modeset_acquire_ctx *ctx,
389 						 bool force)
390 {
391 	struct ast_connector *ast_connector = to_ast_connector(connector);
392 	struct drm_device *dev = connector->dev;
393 	struct ast_device *ast = to_ast_device(connector->dev);
394 	enum drm_connector_status status = connector_status_disconnected;
395 	bool power_is_on;
396 
397 	mutex_lock(&ast->modeset_lock);
398 
399 	power_is_on = ast_dp_power_is_on(ast);
400 	if (!power_is_on)
401 		ast_dp_power_on_off(dev, true);
402 
403 	if (ast_astdp_is_connected(ast))
404 		status = connector_status_connected;
405 
406 	if (!power_is_on && status == connector_status_disconnected)
407 		ast_dp_power_on_off(dev, false);
408 
409 	mutex_unlock(&ast->modeset_lock);
410 
411 	if (status != ast_connector->physical_status)
412 		++connector->epoch_counter;
413 	ast_connector->physical_status = status;
414 
415 	return connector_status_connected;
416 }
417 
418 static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
419 	.get_modes = ast_astdp_connector_helper_get_modes,
420 	.detect_ctx = ast_astdp_connector_helper_detect_ctx,
421 };
422 
423 static const struct drm_connector_funcs ast_astdp_connector_funcs = {
424 	.reset = drm_atomic_helper_connector_reset,
425 	.fill_modes = drm_helper_probe_single_connector_modes,
426 	.destroy = drm_connector_cleanup,
427 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
428 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
429 };
430 
ast_astdp_connector_init(struct drm_device * dev,struct drm_connector * connector)431 static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
432 {
433 	int ret;
434 
435 	ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
436 				 DRM_MODE_CONNECTOR_DisplayPort);
437 	if (ret)
438 		return ret;
439 
440 	drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
441 
442 	connector->interlace_allowed = 0;
443 	connector->doublescan_allowed = 0;
444 
445 	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
446 
447 	return 0;
448 }
449 
ast_astdp_output_init(struct ast_device * ast)450 int ast_astdp_output_init(struct ast_device *ast)
451 {
452 	struct drm_device *dev = &ast->base;
453 	struct drm_crtc *crtc = &ast->crtc;
454 	struct drm_encoder *encoder = &ast->output.astdp.encoder;
455 	struct ast_connector *ast_connector = &ast->output.astdp.connector;
456 	struct drm_connector *connector = &ast_connector->base;
457 	int ret;
458 
459 	ret = drm_encoder_init(dev, encoder, &ast_astdp_encoder_funcs,
460 			       DRM_MODE_ENCODER_TMDS, NULL);
461 	if (ret)
462 		return ret;
463 	drm_encoder_helper_add(encoder, &ast_astdp_encoder_helper_funcs);
464 
465 	encoder->possible_crtcs = drm_crtc_mask(crtc);
466 
467 	ret = ast_astdp_connector_init(dev, connector);
468 	if (ret)
469 		return ret;
470 	ast_connector->physical_status = connector->status;
471 
472 	ret = drm_connector_attach_encoder(connector, encoder);
473 	if (ret)
474 		return ret;
475 
476 	return 0;
477 }
478