brintos

brintos / linux-shallow public Read only

0
0
Text · 27.5 KiB · 3afc73c Raw
1056 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Analogix DP (Display port) core register interface driver.4 *5 * Copyright (C) 2012 Samsung Electronics Co., Ltd.6 * Author: Jingoo Han <jg1.han@samsung.com>7 */8 9#include <linux/delay.h>10#include <linux/device.h>11#include <linux/gpio/consumer.h>12#include <linux/io.h>13#include <linux/iopoll.h>14 15#include <drm/bridge/analogix_dp.h>16 17#include "analogix_dp_core.h"18#include "analogix_dp_reg.h"19 20#define COMMON_INT_MASK_1	021#define COMMON_INT_MASK_2	022#define COMMON_INT_MASK_3	023#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)24#define INT_STA_MASK		INT_HPD25 26void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable)27{28	u32 reg;29 30	if (enable) {31		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);32		reg |= HDCP_VIDEO_MUTE;33		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);34	} else {35		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);36		reg &= ~HDCP_VIDEO_MUTE;37		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);38	}39}40 41void analogix_dp_stop_video(struct analogix_dp_device *dp)42{43	u32 reg;44 45	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);46	reg &= ~VIDEO_EN;47	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);48}49 50void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable)51{52	u32 reg;53 54	if (enable)55		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |56		      LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;57	else58		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |59		      LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;60 61	writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP);62}63 64void analogix_dp_init_analog_param(struct analogix_dp_device *dp)65{66	u32 reg;67 68	reg = TX_TERMINAL_CTRL_50_OHM;69	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1);70 71	reg = SEL_24M | TX_DVDD_BIT_1_0625V;72	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2);73 74	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {75		reg = REF_CLK_24M;76		if (dp->plat_data->dev_type == RK3288_DP)77			reg ^= REF_CLK_MASK;78 79		writel(reg, dp->reg_base + ANALOGIX_DP_PLL_REG_1);80		writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2);81		writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3);82		writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4);83		writel(0x22, dp->reg_base + ANALOGIX_DP_PLL_REG_5);84	}85 86	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;87	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3);88 89	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |90		TX_CUR1_2X | TX_CUR_16_MA;91	writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1);92 93	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |94		CH1_AMP_400_MV | CH0_AMP_400_MV;95	writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL);96}97 98void analogix_dp_init_interrupt(struct analogix_dp_device *dp)99{100	/* Set interrupt pin assertion polarity as high */101	writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL);102 103	/* Clear pending regisers */104	writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);105	writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2);106	writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3);107	writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);108	writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA);109 110	/* 0:mask,1: unmask */111	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);112	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);113	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);114	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);115	writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);116}117 118void analogix_dp_reset(struct analogix_dp_device *dp)119{120	u32 reg;121 122	analogix_dp_stop_video(dp);123	analogix_dp_enable_video_mute(dp, 0);124 125	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))126		reg = RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N |127			SW_FUNC_EN_N;128	else129		reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |130			AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |131			HDCP_FUNC_EN_N | SW_FUNC_EN_N;132 133	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);134 135	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |136		SERDES_FIFO_FUNC_EN_N |137		LS_CLK_DOMAIN_FUNC_EN_N;138	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);139 140	usleep_range(20, 30);141 142	analogix_dp_lane_swap(dp, 0);143 144	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);145	writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);146	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);147	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);148 149	writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);150	writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL);151 152	writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);153	writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);154 155	writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL);156 157	writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST);158 159	writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD);160	writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN);161 162	writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH);163	writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH);164 165	writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);166}167 168void analogix_dp_swreset(struct analogix_dp_device *dp)169{170	writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET);171}172 173void analogix_dp_config_interrupt(struct analogix_dp_device *dp)174{175	u32 reg;176 177	/* 0: mask, 1: unmask */178	reg = COMMON_INT_MASK_1;179	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);180 181	reg = COMMON_INT_MASK_2;182	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);183 184	reg = COMMON_INT_MASK_3;185	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);186 187	reg = COMMON_INT_MASK_4;188	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);189 190	reg = INT_STA_MASK;191	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);192}193 194void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)195{196	u32 reg;197 198	/* 0: mask, 1: unmask */199	reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);200	reg &= ~COMMON_INT_MASK_4;201	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);202 203	reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);204	reg &= ~INT_STA_MASK;205	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);206}207 208void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)209{210	u32 reg;211 212	/* 0: mask, 1: unmask */213	reg = COMMON_INT_MASK_4;214	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);215 216	reg = INT_STA_MASK;217	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);218}219 220int analogix_dp_wait_pll_locked(struct analogix_dp_device *dp)221{222	u32 val;223 224	return readl_poll_timeout(dp->reg_base + ANALOGIX_DP_DEBUG_CTL, val,225				  val & PLL_LOCK, 120,226				  120 * DP_TIMEOUT_LOOP_COUNT);227}228 229void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)230{231	u32 reg;232	u32 mask = DP_PLL_PD;233	u32 pd_addr = ANALOGIX_DP_PLL_CTL;234 235	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {236		pd_addr = ANALOGIX_DP_PD;237		mask = RK_PLL_PD;238	}239 240	reg = readl(dp->reg_base + pd_addr);241	if (enable)242		reg |= mask;243	else244		reg &= ~mask;245	writel(reg, dp->reg_base + pd_addr);246}247 248void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,249				       enum analog_power_block block,250				       bool enable)251{252	u32 reg;253	u32 phy_pd_addr = ANALOGIX_DP_PHY_PD;254	u32 mask;255 256	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))257		phy_pd_addr = ANALOGIX_DP_PD;258 259	switch (block) {260	case AUX_BLOCK:261		if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))262			mask = RK_AUX_PD;263		else264			mask = AUX_PD;265 266		reg = readl(dp->reg_base + phy_pd_addr);267		if (enable)268			reg |= mask;269		else270			reg &= ~mask;271		writel(reg, dp->reg_base + phy_pd_addr);272		break;273	case CH0_BLOCK:274		mask = CH0_PD;275		reg = readl(dp->reg_base + phy_pd_addr);276 277		if (enable)278			reg |= mask;279		else280			reg &= ~mask;281		writel(reg, dp->reg_base + phy_pd_addr);282		break;283	case CH1_BLOCK:284		mask = CH1_PD;285		reg = readl(dp->reg_base + phy_pd_addr);286 287		if (enable)288			reg |= mask;289		else290			reg &= ~mask;291		writel(reg, dp->reg_base + phy_pd_addr);292		break;293	case CH2_BLOCK:294		mask = CH2_PD;295		reg = readl(dp->reg_base + phy_pd_addr);296 297		if (enable)298			reg |= mask;299		else300			reg &= ~mask;301		writel(reg, dp->reg_base + phy_pd_addr);302		break;303	case CH3_BLOCK:304		mask = CH3_PD;305		reg = readl(dp->reg_base + phy_pd_addr);306 307		if (enable)308			reg |= mask;309		else310			reg &= ~mask;311		writel(reg, dp->reg_base + phy_pd_addr);312		break;313	case ANALOG_TOTAL:314		/*315		 * There is no bit named DP_PHY_PD, so We used DP_INC_BG316		 * to power off everything instead of DP_PHY_PD in317		 * Rockchip318		 */319		if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))320			mask = DP_INC_BG;321		else322			mask = DP_PHY_PD;323 324		reg = readl(dp->reg_base + phy_pd_addr);325		if (enable)326			reg |= mask;327		else328			reg &= ~mask;329 330		writel(reg, dp->reg_base + phy_pd_addr);331		if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))332			usleep_range(10, 15);333		break;334	case POWER_ALL:335		if (enable) {336			reg = DP_ALL_PD;337			writel(reg, dp->reg_base + phy_pd_addr);338		} else {339			reg = DP_ALL_PD;340			writel(reg, dp->reg_base + phy_pd_addr);341			usleep_range(10, 15);342			reg &= ~DP_INC_BG;343			writel(reg, dp->reg_base + phy_pd_addr);344			usleep_range(10, 15);345 346			writel(0x00, dp->reg_base + phy_pd_addr);347		}348		break;349	default:350		break;351	}352}353 354int analogix_dp_init_analog_func(struct analogix_dp_device *dp)355{356	u32 reg;357 358	analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);359 360	reg = PLL_LOCK_CHG;361	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);362 363	reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL);364	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);365	writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL);366 367	/* Power up PLL */368	analogix_dp_set_pll_power_down(dp, 0);369 370	/* Enable Serdes FIFO function and Link symbol clock domain module */371	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);372	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N373		| AUX_FUNC_EN_N);374	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);375	return 0;376}377 378void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp)379{380	u32 reg;381 382	if (dp->hpd_gpiod)383		return;384 385	reg = HOTPLUG_CHG | HPD_LOST | PLUG;386	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);387 388	reg = INT_HPD;389	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);390}391 392void analogix_dp_init_hpd(struct analogix_dp_device *dp)393{394	u32 reg;395 396	if (dp->hpd_gpiod)397		return;398 399	analogix_dp_clear_hotplug_interrupts(dp);400 401	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);402	reg &= ~(F_HPD | HPD_CTRL);403	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);404}405 406void analogix_dp_force_hpd(struct analogix_dp_device *dp)407{408	u32 reg;409 410	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);411	reg = (F_HPD | HPD_CTRL);412	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);413}414 415enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)416{417	u32 reg;418 419	if (dp->hpd_gpiod) {420		reg = gpiod_get_value(dp->hpd_gpiod);421		if (reg)422			return DP_IRQ_TYPE_HP_CABLE_IN;423		else424			return DP_IRQ_TYPE_HP_CABLE_OUT;425	} else {426		/* Parse hotplug interrupt status register */427		reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);428 429		if (reg & PLUG)430			return DP_IRQ_TYPE_HP_CABLE_IN;431 432		if (reg & HPD_LOST)433			return DP_IRQ_TYPE_HP_CABLE_OUT;434 435		if (reg & HOTPLUG_CHG)436			return DP_IRQ_TYPE_HP_CHANGE;437 438		return DP_IRQ_TYPE_UNKNOWN;439	}440}441 442void analogix_dp_reset_aux(struct analogix_dp_device *dp)443{444	u32 reg;445 446	/* Disable AUX channel module */447	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);448	reg |= AUX_FUNC_EN_N;449	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);450}451 452void analogix_dp_init_aux(struct analogix_dp_device *dp)453{454	u32 reg;455 456	/* Clear inerrupts related to AUX channel */457	reg = RPLY_RECEIV | AUX_ERR;458	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);459 460	analogix_dp_set_analog_power_down(dp, AUX_BLOCK, true);461	usleep_range(10, 11);462	analogix_dp_set_analog_power_down(dp, AUX_BLOCK, false);463 464	analogix_dp_reset_aux(dp);465 466	/* AUX_BIT_PERIOD_EXPECTED_DELAY doesn't apply to Rockchip IP */467	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type))468		reg = 0;469	else470		reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3);471 472	/* Disable AUX transaction H/W retry */473	reg |= AUX_HW_RETRY_COUNT_SEL(0) |474	       AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;475 476	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL);477 478	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */479	reg = DEFER_CTRL_EN | DEFER_COUNT(1);480	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL);481 482	/* Enable AUX channel module */483	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);484	reg &= ~AUX_FUNC_EN_N;485	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);486}487 488int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp)489{490	u32 reg;491 492	if (dp->hpd_gpiod) {493		if (gpiod_get_value(dp->hpd_gpiod))494			return 0;495	} else {496		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);497		if (reg & HPD_STATUS)498			return 0;499	}500 501	return -EINVAL;502}503 504void analogix_dp_enable_sw_function(struct analogix_dp_device *dp)505{506	u32 reg;507 508	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);509	reg &= ~SW_FUNC_EN_N;510	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);511}512 513void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)514{515	u32 reg;516 517	reg = bwtype;518	if ((bwtype == DP_LINK_BW_2_7) || (bwtype == DP_LINK_BW_1_62))519		writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET);520}521 522void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)523{524	u32 reg;525 526	reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET);527	*bwtype = reg;528}529 530void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)531{532	u32 reg;533 534	reg = count;535	writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);536}537 538void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)539{540	u32 reg;541 542	reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);543	*count = reg;544}545 546void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp)547{548	u8 lane;549 550	for (lane = 0; lane < dp->link_train.lane_count; lane++)551		writel(dp->link_train.training_lane[lane],552		       dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);553}554 555u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane)556{557	return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane);558}559 560void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,561				      bool enable)562{563	u32 reg;564 565	if (enable) {566		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);567		reg |= ENHANCED;568		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);569	} else {570		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);571		reg &= ~ENHANCED;572		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);573	}574}575 576void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,577				      enum pattern_set pattern)578{579	u32 reg;580 581	switch (pattern) {582	case PRBS7:583		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;584		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);585		break;586	case D10_2:587		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;588		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);589		break;590	case TRAINING_PTN1:591		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;592		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);593		break;594	case TRAINING_PTN2:595		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;596		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);597		break;598	case DP_NONE:599		reg = SCRAMBLING_ENABLE |600			LINK_QUAL_PATTERN_SET_DISABLE |601			SW_TRAINING_PATTERN_SET_NORMAL;602		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);603		break;604	default:605		break;606	}607}608 609void analogix_dp_reset_macro(struct analogix_dp_device *dp)610{611	u32 reg;612 613	reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST);614	reg |= MACRO_RST;615	writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);616 617	/* 10 us is the minimum reset time. */618	usleep_range(10, 20);619 620	reg &= ~MACRO_RST;621	writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);622}623 624void analogix_dp_init_video(struct analogix_dp_device *dp)625{626	u32 reg;627 628	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;629	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);630 631	reg = 0x0;632	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);633 634	reg = CHA_CRI(4) | CHA_CTRL;635	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);636 637	reg = 0x0;638	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);639 640	reg = VID_HRES_TH(2) | VID_VRES_TH(0);641	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8);642}643 644void analogix_dp_set_video_color_format(struct analogix_dp_device *dp)645{646	u32 reg;647 648	/* Configure the input color depth, color space, dynamic range */649	reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) |650		(dp->video_info.color_depth << IN_BPC_SHIFT) |651		(dp->video_info.color_space << IN_COLOR_F_SHIFT);652	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2);653 654	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */655	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);656	reg &= ~IN_YC_COEFFI_MASK;657	if (dp->video_info.ycbcr_coeff)658		reg |= IN_YC_COEFFI_ITU709;659	else660		reg |= IN_YC_COEFFI_ITU601;661	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);662}663 664int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp)665{666	u32 reg;667 668	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);669	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);670 671	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);672 673	if (!(reg & DET_STA)) {674		dev_dbg(dp->dev, "Input stream clock not detected.\n");675		return -EINVAL;676	}677 678	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);679	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);680 681	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);682	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");683 684	if (reg & CHA_STA) {685		dev_dbg(dp->dev, "Input stream clk is changing\n");686		return -EINVAL;687	}688 689	return 0;690}691 692void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,693				 enum clock_recovery_m_value_type type,694				 u32 m_value, u32 n_value)695{696	u32 reg;697 698	if (type == REGISTER_M) {699		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);700		reg |= FIX_M_VID;701		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);702		reg = m_value & 0xff;703		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0);704		reg = (m_value >> 8) & 0xff;705		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1);706		reg = (m_value >> 16) & 0xff;707		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2);708 709		reg = n_value & 0xff;710		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0);711		reg = (n_value >> 8) & 0xff;712		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1);713		reg = (n_value >> 16) & 0xff;714		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2);715	} else  {716		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);717		reg &= ~FIX_M_VID;718		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);719 720		writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0);721		writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1);722		writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2);723	}724}725 726void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type)727{728	u32 reg;729 730	if (type == VIDEO_TIMING_FROM_CAPTURE) {731		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);732		reg &= ~FORMAT_SEL;733		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);734	} else {735		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);736		reg |= FORMAT_SEL;737		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);738	}739}740 741void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable)742{743	u32 reg;744 745	if (enable) {746		reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);747		reg &= ~VIDEO_MODE_MASK;748		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;749		writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);750	} else {751		reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);752		reg &= ~VIDEO_MODE_MASK;753		reg |= VIDEO_MODE_SLAVE_MODE;754		writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);755	}756}757 758void analogix_dp_start_video(struct analogix_dp_device *dp)759{760	u32 reg;761 762	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);763	reg |= VIDEO_EN;764	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);765}766 767int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)768{769	u32 reg;770 771	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);772	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);773 774	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);775	if (!(reg & STRM_VALID)) {776		dev_dbg(dp->dev, "Input video stream is not detected.\n");777		return -EINVAL;778	}779 780	return 0;781}782 783void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)784{785	u32 reg;786 787	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);788	if (dp->plat_data && is_rockchip(dp->plat_data->dev_type)) {789		reg &= ~(RK_VID_CAP_FUNC_EN_N | RK_VID_FIFO_FUNC_EN_N);790	} else {791		reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);792		reg |= MASTER_VID_FUNC_EN_N;793	}794	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);795 796	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);797	reg &= ~INTERACE_SCAN_CFG;798	reg |= (dp->video_info.interlaced << 2);799	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);800 801	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);802	reg &= ~VSYNC_POLARITY_CFG;803	reg |= (dp->video_info.v_sync_polarity << 1);804	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);805 806	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);807	reg &= ~HSYNC_POLARITY_CFG;808	reg |= (dp->video_info.h_sync_polarity << 0);809	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);810 811	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;812	writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);813}814 815void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)816{817	u32 reg;818 819	reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);820	reg &= ~SCRAMBLING_DISABLE;821	writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);822}823 824void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)825{826	u32 reg;827 828	reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);829	reg |= SCRAMBLING_DISABLE;830	writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);831}832 833void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp)834{835	writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON);836}837 838static ssize_t analogix_dp_get_psr_status(struct analogix_dp_device *dp)839{840	ssize_t val;841	u8 status;842 843	val = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &status);844	if (val < 0) {845		dev_err(dp->dev, "PSR_STATUS read failed ret=%zd", val);846		return val;847	}848	return status;849}850 851int analogix_dp_send_psr_spd(struct analogix_dp_device *dp,852			     struct dp_sdp *vsc, bool blocking)853{854	unsigned int val;855	int ret;856	ssize_t psr_status;857 858	/* don't send info frame */859	val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);860	val &= ~IF_EN;861	writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);862 863	/* configure single frame update mode */864	writel(PSR_FRAME_UP_TYPE_BURST | PSR_CRC_SEL_HARDWARE,865	       dp->reg_base + ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL);866 867	/* configure VSC HB0~HB3 */868	writel(vsc->sdp_header.HB0, dp->reg_base + ANALOGIX_DP_SPD_HB0);869	writel(vsc->sdp_header.HB1, dp->reg_base + ANALOGIX_DP_SPD_HB1);870	writel(vsc->sdp_header.HB2, dp->reg_base + ANALOGIX_DP_SPD_HB2);871	writel(vsc->sdp_header.HB3, dp->reg_base + ANALOGIX_DP_SPD_HB3);872 873	/* configure reused VSC PB0~PB3, magic number from vendor */874	writel(0x00, dp->reg_base + ANALOGIX_DP_SPD_PB0);875	writel(0x16, dp->reg_base + ANALOGIX_DP_SPD_PB1);876	writel(0xCE, dp->reg_base + ANALOGIX_DP_SPD_PB2);877	writel(0x5D, dp->reg_base + ANALOGIX_DP_SPD_PB3);878 879	/* configure DB0 / DB1 values */880	writel(vsc->db[0], dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB0);881	writel(vsc->db[1], dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB1);882 883	/* set reuse spd inforframe */884	val = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);885	val |= REUSE_SPD_EN;886	writel(val, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);887 888	/* mark info frame update */889	val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);890	val = (val | IF_UP) & ~IF_EN;891	writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);892 893	/* send info frame */894	val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);895	val |= IF_EN;896	writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);897 898	if (!blocking)899		return 0;900 901	/*902	 * db[1]!=0: entering PSR, wait for fully active remote frame buffer.903	 * db[1]==0: exiting PSR, wait for either904	 *  (a) ACTIVE_RESYNC - the sink "must display the905	 *      incoming active frames from the Source device with no visible906	 *      glitches and/or artifacts", even though timings may still be907	 *      re-synchronizing; or908	 *  (b) INACTIVE - the transition is fully complete.909	 */910	ret = readx_poll_timeout(analogix_dp_get_psr_status, dp, psr_status,911		psr_status >= 0 &&912		((vsc->db[1] && psr_status == DP_PSR_SINK_ACTIVE_RFB) ||913		(!vsc->db[1] && (psr_status == DP_PSR_SINK_ACTIVE_RESYNC ||914				 psr_status == DP_PSR_SINK_INACTIVE))),915		1500, DP_TIMEOUT_PSR_LOOP_MS * 1000);916	if (ret) {917		dev_warn(dp->dev, "Failed to apply PSR %d\n", ret);918		return ret;919	}920	return 0;921}922 923ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,924			     struct drm_dp_aux_msg *msg)925{926	u32 reg;927	u8 *buffer = msg->buffer;928	unsigned int i;929	int ret;930 931	/* Buffer size of AUX CH is 16 bytes */932	if (WARN_ON(msg->size > 16))933		return -E2BIG;934 935	/* Clear AUX CH data buffer */936	reg = BUF_CLR;937	writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);938 939	switch (msg->request & ~DP_AUX_I2C_MOT) {940	case DP_AUX_I2C_WRITE:941		reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_I2C_TRANSACTION;942		if (msg->request & DP_AUX_I2C_MOT)943			reg |= AUX_TX_COMM_MOT;944		break;945 946	case DP_AUX_I2C_READ:947		reg = AUX_TX_COMM_READ | AUX_TX_COMM_I2C_TRANSACTION;948		if (msg->request & DP_AUX_I2C_MOT)949			reg |= AUX_TX_COMM_MOT;950		break;951 952	case DP_AUX_NATIVE_WRITE:953		reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_DP_TRANSACTION;954		break;955 956	case DP_AUX_NATIVE_READ:957		reg = AUX_TX_COMM_READ | AUX_TX_COMM_DP_TRANSACTION;958		break;959 960	default:961		return -EINVAL;962	}963 964	reg |= AUX_LENGTH(msg->size);965	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);966 967	/* Select DPCD device address */968	reg = AUX_ADDR_7_0(msg->address);969	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);970	reg = AUX_ADDR_15_8(msg->address);971	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);972	reg = AUX_ADDR_19_16(msg->address);973	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);974 975	if (!(msg->request & DP_AUX_I2C_READ)) {976		for (i = 0; i < msg->size; i++) {977			reg = buffer[i];978			writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +979			       4 * i);980		}981	}982 983	/* Enable AUX CH operation */984	reg = AUX_EN;985 986	/* Zero-sized messages specify address-only transactions. */987	if (msg->size < 1)988		reg |= ADDR_ONLY;989 990	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);991 992	ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2,993				 reg, !(reg & AUX_EN), 25, 500 * 1000);994	if (ret) {995		dev_err(dp->dev, "AUX CH enable timeout!\n");996		goto aux_error;997	}998 999	/* TODO: Wait for an interrupt instead of looping? */1000	/* Is AUX CH command reply received? */1001	ret = readx_poll_timeout(readl, dp->reg_base + ANALOGIX_DP_INT_STA,1002				 reg, reg & RPLY_RECEIV, 10, 20 * 1000);1003	if (ret) {1004		dev_err(dp->dev, "AUX CH cmd reply timeout!\n");1005		goto aux_error;1006	}1007 1008	/* Clear interrupt source for AUX CH command reply */1009	writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA);1010 1011	/* Clear interrupt source for AUX CH access error */1012	reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);1013	if ((reg & AUX_ERR)) {1014		u32 aux_status = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA) &1015				 AUX_STATUS_MASK;1016 1017		writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);1018 1019		if (aux_status == AUX_STATUS_TIMEOUT_ERROR)1020			return -ETIMEDOUT;1021 1022		dev_warn(dp->dev, "AUX CH error happened: %#x (%d)\n",1023			 aux_status, !!(reg & AUX_ERR));1024		goto aux_error;1025	}1026 1027	if (msg->request & DP_AUX_I2C_READ) {1028		for (i = 0; i < msg->size; i++) {1029			reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +1030				    4 * i);1031			buffer[i] = (unsigned char)reg;1032		}1033	}1034 1035	/* Check if Rx sends defer */1036	reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM);1037	if (reg == AUX_RX_COMM_AUX_DEFER)1038		msg->reply = DP_AUX_NATIVE_REPLY_DEFER;1039	else if (reg == AUX_RX_COMM_I2C_DEFER)1040		msg->reply = DP_AUX_I2C_REPLY_DEFER;1041	else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE ||1042		 (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_READ)1043		msg->reply = DP_AUX_I2C_REPLY_ACK;1044	else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE ||1045		 (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)1046		msg->reply = DP_AUX_NATIVE_REPLY_ACK;1047 1048	return msg->size;1049 1050aux_error:1051	/* if aux err happen, reset aux */1052	analogix_dp_init_aux(dp);1053 1054	return -EREMOTEIO;1055}1056