// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2021, ASPEED Technology Inc.
// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>

#include <linux/firmware.h>
#include <linux/delay.h>
#include <drm/drm_print.h>
#include "ast_drv.h"

int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
{
	struct ast_private *ast = to_ast_private(dev);
	u8 i = 0, j = 0;

	/*
	 * CRD1[b5]: DP MCU FW is executing
	 * CRDC[b0]: DP link success
	 * CRDF[b0]: DP HPD
	 * CRE5[b0]: Host reading EDID process is done
	 */
	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
								ASTDP_HOST_EDID_READ_DONE_MASK))) {
		goto err_astdp_edid_not_ready;
	}

	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
							0x00);

	for (i = 0; i < 32; i++) {
		/*
		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
		 */
		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
				       ASTDP_AND_CLEAR_MASK, (u8)i);
		j = 0;

		/*
		 * CRD7[b0]: valid flag for EDID
		 * CRD6[b0]: mirror read pointer for EDID
		 */
		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
						ASTDP_EDID_READ_POINTER_MASK) != i)) {
			/*
			 * Delay are getting longer with each retry.
			 * 1. The Delays are often 2 loops when users request "Display Settings"
			 *	  of right-click of mouse.
			 * 2. The Delays are often longer a lot when system resume from S3/S4.
			 */
			mdelay(j+1);

			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
							ASTDP_MCU_FW_EXECUTING) &&
				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
							ASTDP_LINK_SUCCESS) &&
				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
				goto err_astdp_jump_out_loop_of_edid;
			}

			j++;
			if (j > 200)
				goto err_astdp_jump_out_loop_of_edid;
		}

		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
							0xD8, ASTDP_EDID_READ_DATA_MASK);
		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
								ASTDP_EDID_READ_DATA_MASK);
		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
								ASTDP_EDID_READ_DATA_MASK);
		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
								ASTDP_EDID_READ_DATA_MASK);

		if (i == 31) {
			/*
			 * For 128-bytes EDID_1.3,
			 * 1. Add the value of Bytes-126 to Bytes-127.
			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
			 *		equal 0	(mod 256).
			 * 2. Modify Bytes-126 to be 0.
			 *		The Bytes-126 indicates the Number of extensions to
			 *		follow. 0 represents noextensions.
			 */
			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
			*(ediddata + 2) = 0;
		}

		ediddata += 4;
	}

	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
							ASTDP_HOST_EDID_READ_DONE);

	return 0;

err_astdp_jump_out_loop_of_edid:
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
							ASTDP_HOST_EDID_READ_DONE);
	return (~(j+256) + 1);

err_astdp_edid_not_ready:
	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
		return (~0xD1 + 1);
	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
		return (~0xDC + 1);
	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
		return (~0xDF + 1);
	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
		return (~0xE5 + 1);

	return	0;
}

/*
 * Launch Aspeed DP
 */
void ast_dp_launch(struct drm_device *dev, u8 bPower)
{
	u32 i = 0, j = 0, WaitCount = 1;
	u8 bDPTX = 0;
	u8 bDPExecute = 1;

	struct ast_private *ast = to_ast_private(dev);
	// S3 come back, need more time to wait BMC ready.
	if (bPower)
		WaitCount = 300;


	// Wait total count by different condition.
	for (j = 0; j < WaitCount; j++) {
		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);

		if (bDPTX)
			break;

		msleep(100);
	}

	// 0xE : ASTDP with DPMCU FW handling
	if (bDPTX == ASTDP_DPMCU_TX) {
		// Wait one second then timeout.
		i = 0;

		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
			COPROCESSOR_LAUNCH) {
			i++;
			// wait 100 ms
			msleep(100);

			if (i >= 10) {
				// DP would not be ready.
				bDPExecute = 0;
				break;
			}
		}

		if (bDPExecute)
			ast->tx_chip_types |= BIT(AST_TX_ASTDP);

		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
							ASTDP_HOST_EDID_READ_DONE);
	}
}



void ast_dp_power_on_off(struct drm_device *dev, bool on)
{
	struct ast_private *ast = to_ast_private(dev);
	// Read and Turn off DP PHY sleep
	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);

	// Turn on DP PHY sleep
	if (!on)
		bE3 |= AST_DP_PHY_SLEEP;

	// DP Power on/off
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
}



void ast_dp_set_on_off(struct drm_device *dev, bool on)
{
	struct ast_private *ast = to_ast_private(dev);
	u8 video_on_off = on;

	// Video On/Off
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);

	// If DP plug in and link successful then check video on / off status
	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
		video_on_off <<= 4;
		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
			// wait 1 ms
			mdelay(1);
		}
	}
}

void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
{
	struct ast_private *ast = to_ast_private(crtc->dev);

	u32 ulRefreshRateIndex;
	u8 ModeIdx;

	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;

	switch (crtc->mode.crtc_hdisplay) {
	case 320:
		ModeIdx = ASTDP_320x240_60;
		break;
	case 400:
		ModeIdx = ASTDP_400x300_60;
		break;
	case 512:
		ModeIdx = ASTDP_512x384_60;
		break;
	case 640:
		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
		break;
	case 800:
		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
		break;
	case 1024:
		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
		break;
	case 1152:
		ModeIdx = ASTDP_1152x864_75;
		break;
	case 1280:
		if (crtc->mode.crtc_vdisplay == 800)
			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
		else		// 1024
			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
		break;
	case 1360:
	case 1366:
		ModeIdx = ASTDP_1366x768_60;
		break;
	case 1440:
		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
		break;
	case 1600:
		if (crtc->mode.crtc_vdisplay == 900)
			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
		else		//1200
			ModeIdx = ASTDP_1600x1200_60;
		break;
	case 1680:
		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
		break;
	case 1920:
		if (crtc->mode.crtc_vdisplay == 1080)
			ModeIdx = ASTDP_1920x1080_60;
		else		//1200
			ModeIdx = ASTDP_1920x1200_60;
		break;
	default:
		return;
	}

	/*
	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
	 * CRE1[7:0]: MISC1 (default: 0x00)
	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
	 */
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, ASTDP_AND_CLEAR_MASK,
			       ASTDP_MISC0_24bpp);
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
}
