brintos

brintos / linux-shallow public Read only

0
0
Text · 58.6 KiB · f342fc5 Raw
2259 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.4 */5 6#define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__7 8#include <linux/types.h>9#include <linux/completion.h>10#include <linux/delay.h>11#include <linux/phy/phy.h>12#include <linux/phy/phy-dp.h>13#include <linux/pm_opp.h>14 15#include <drm/display/drm_dp_helper.h>16#include <drm/drm_fixed.h>17#include <drm/drm_print.h>18 19#include "dp_reg.h"20#include "dp_ctrl.h"21#include "dp_link.h"22 23#define DP_KHZ_TO_HZ 100024#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES	(30 * HZ / 1000) /* 30 ms */25#define PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES       (300 * HZ / 1000) /* 300 ms */26#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2)27 28#define DP_CTRL_INTR_READY_FOR_VIDEO     BIT(0)29#define DP_CTRL_INTR_IDLE_PATTERN_SENT  BIT(3)30 31#define MR_LINK_TRAINING1  0x832#define MR_LINK_SYMBOL_ERM 0x8033#define MR_LINK_PRBS7 0x10034#define MR_LINK_CUSTOM80 0x20035#define MR_LINK_TRAINING4  0x4036 37enum {38	DP_TRAINING_NONE,39	DP_TRAINING_1,40	DP_TRAINING_2,41};42 43struct dp_tu_calc_input {44	u64 lclk;        /* 162, 270, 540 and 810 */45	u64 pclk_khz;    /* in KHz */46	u64 hactive;     /* active h-width */47	u64 hporch;      /* bp + fp + pulse */48	int nlanes;      /* no.of.lanes */49	int bpp;         /* bits */50	int pixel_enc;   /* 444, 420, 422 */51	int dsc_en;     /* dsc on/off */52	int async_en;   /* async mode */53	int fec_en;     /* fec */54	int compress_ratio; /* 2:1 = 200, 3:1 = 300, 3.75:1 = 375 */55	int num_of_dsc_slices; /* number of slices per line */56};57 58struct dp_vc_tu_mapping_table {59	u32 vic;60	u8 lanes;61	u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */62	u8 bpp;63	u8 valid_boundary_link;64	u16 delay_start_link;65	bool boundary_moderation_en;66	u8 valid_lower_boundary_link;67	u8 upper_boundary_count;68	u8 lower_boundary_count;69	u8 tu_size_minus1;70};71 72struct dp_ctrl_private {73	struct dp_ctrl dp_ctrl;74	struct drm_device *drm_dev;75	struct device *dev;76	struct drm_dp_aux *aux;77	struct dp_panel *panel;78	struct dp_link *link;79	struct dp_catalog *catalog;80 81	struct phy *phy;82 83	unsigned int num_core_clks;84	struct clk_bulk_data *core_clks;85 86	unsigned int num_link_clks;87	struct clk_bulk_data *link_clks;88 89	struct clk *pixel_clk;90 91	union phy_configure_opts phy_opts;92 93	struct completion idle_comp;94	struct completion psr_op_comp;95	struct completion video_comp;96 97	bool core_clks_on;98	bool link_clks_on;99	bool stream_clks_on;100};101 102static int dp_aux_link_configure(struct drm_dp_aux *aux,103					struct dp_link_info *link)104{105	u8 values[2];106	int err;107 108	values[0] = drm_dp_link_rate_to_bw_code(link->rate);109	values[1] = link->num_lanes;110 111	if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)112		values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;113 114	err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));115	if (err < 0)116		return err;117 118	return 0;119}120 121void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl)122{123	struct dp_ctrl_private *ctrl;124 125	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);126 127	reinit_completion(&ctrl->idle_comp);128	dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_PUSH_IDLE);129 130	if (!wait_for_completion_timeout(&ctrl->idle_comp,131			IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))132		pr_warn("PUSH_IDLE pattern timedout\n");133 134	drm_dbg_dp(ctrl->drm_dev, "mainlink off\n");135}136 137static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)138{139	u32 config = 0, tbd;140	const u8 *dpcd = ctrl->panel->dpcd;141 142	/* Default-> LSCLK DIV: 1/4 LCLK  */143	config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);144 145	if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)146		config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */147 148	/* Scrambler reset enable */149	if (drm_dp_alternate_scrambler_reset_cap(dpcd))150		config |= DP_CONFIGURATION_CTRL_ASSR;151 152	tbd = dp_link_get_test_bits_depth(ctrl->link,153			ctrl->panel->dp_mode.bpp);154 155	config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;156 157	/* Num of Lanes */158	config |= ((ctrl->link->link_params.num_lanes - 1)159			<< DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT);160 161	if (drm_dp_enhanced_frame_cap(dpcd))162		config |= DP_CONFIGURATION_CTRL_ENHANCED_FRAMING;163 164	config |= DP_CONFIGURATION_CTRL_P_INTERLACED; /* progressive video */165 166	/* sync clock & static Mvid */167	config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN;168	config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK;169 170	if (ctrl->panel->psr_cap.version)171		config |= DP_CONFIGURATION_CTRL_SEND_VSC;172 173	dp_catalog_ctrl_config_ctrl(ctrl->catalog, config);174}175 176static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)177{178	u32 cc, tb;179 180	dp_catalog_ctrl_lane_mapping(ctrl->catalog);181	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);182	dp_catalog_setup_peripheral_flush(ctrl->catalog);183 184	dp_ctrl_config_ctrl(ctrl);185 186	tb = dp_link_get_test_bits_depth(ctrl->link,187		ctrl->panel->dp_mode.bpp);188	cc = dp_link_get_colorimetry_config(ctrl->link);189	dp_catalog_ctrl_config_misc(ctrl->catalog, cc, tb);190	dp_panel_timing_cfg(ctrl->panel);191}192 193/*194 * The structure and few functions present below are IP/Hardware195 * specific implementation. Most of the implementation will not196 * have coding comments197 */198struct tu_algo_data {199	s64 lclk_fp;200	s64 pclk_fp;201	s64 lwidth;202	s64 lwidth_fp;203	s64 hbp_relative_to_pclk;204	s64 hbp_relative_to_pclk_fp;205	int nlanes;206	int bpp;207	int pixelEnc;208	int dsc_en;209	int async_en;210	int bpc;211 212	uint delay_start_link_extra_pixclk;213	int extra_buffer_margin;214	s64 ratio_fp;215	s64 original_ratio_fp;216 217	s64 err_fp;218	s64 n_err_fp;219	s64 n_n_err_fp;220	int tu_size;221	int tu_size_desired;222	int tu_size_minus1;223 224	int valid_boundary_link;225	s64 resulting_valid_fp;226	s64 total_valid_fp;227	s64 effective_valid_fp;228	s64 effective_valid_recorded_fp;229	int n_tus;230	int n_tus_per_lane;231	int paired_tus;232	int remainder_tus;233	int remainder_tus_upper;234	int remainder_tus_lower;235	int extra_bytes;236	int filler_size;237	int delay_start_link;238 239	int extra_pclk_cycles;240	int extra_pclk_cycles_in_link_clk;241	s64 ratio_by_tu_fp;242	s64 average_valid2_fp;243	int new_valid_boundary_link;244	int remainder_symbols_exist;245	int n_symbols;246	s64 n_remainder_symbols_per_lane_fp;247	s64 last_partial_tu_fp;248	s64 TU_ratio_err_fp;249 250	int n_tus_incl_last_incomplete_tu;251	int extra_pclk_cycles_tmp;252	int extra_pclk_cycles_in_link_clk_tmp;253	int extra_required_bytes_new_tmp;254	int filler_size_tmp;255	int lower_filler_size_tmp;256	int delay_start_link_tmp;257 258	bool boundary_moderation_en;259	int boundary_mod_lower_err;260	int upper_boundary_count;261	int lower_boundary_count;262	int i_upper_boundary_count;263	int i_lower_boundary_count;264	int valid_lower_boundary_link;265	int even_distribution_BF;266	int even_distribution_legacy;267	int even_distribution;268	int min_hblank_violated;269	s64 delay_start_time_fp;270	s64 hbp_time_fp;271	s64 hactive_time_fp;272	s64 diff_abs_fp;273 274	s64 ratio;275};276 277static int _tu_param_compare(s64 a, s64 b)278{279	u32 a_sign;280	u32 b_sign;281	s64 a_temp, b_temp, minus_1;282 283	if (a == b)284		return 0;285 286	minus_1 = drm_fixp_from_fraction(-1, 1);287 288	a_sign = (a >> 32) & 0x80000000 ? 1 : 0;289 290	b_sign = (b >> 32) & 0x80000000 ? 1 : 0;291 292	if (a_sign > b_sign)293		return 2;294	else if (b_sign > a_sign)295		return 1;296 297	if (!a_sign && !b_sign) { /* positive */298		if (a > b)299			return 1;300		else301			return 2;302	} else { /* negative */303		a_temp = drm_fixp_mul(a, minus_1);304		b_temp = drm_fixp_mul(b, minus_1);305 306		if (a_temp > b_temp)307			return 2;308		else309			return 1;310	}311}312 313static void dp_panel_update_tu_timings(struct dp_tu_calc_input *in,314					struct tu_algo_data *tu)315{316	int nlanes = in->nlanes;317	int dsc_num_slices = in->num_of_dsc_slices;318	int dsc_num_bytes  = 0;319	int numerator;320	s64 pclk_dsc_fp;321	s64 dwidth_dsc_fp;322	s64 hbp_dsc_fp;323 324	int tot_num_eoc_symbols = 0;325	int tot_num_hor_bytes   = 0;326	int tot_num_dummy_bytes = 0;327	int dwidth_dsc_bytes    = 0;328	int  eoc_bytes           = 0;329 330	s64 temp1_fp, temp2_fp, temp3_fp;331 332	tu->lclk_fp              = drm_fixp_from_fraction(in->lclk, 1);333	tu->pclk_fp              = drm_fixp_from_fraction(in->pclk_khz, 1000);334	tu->lwidth               = in->hactive;335	tu->hbp_relative_to_pclk = in->hporch;336	tu->nlanes               = in->nlanes;337	tu->bpp                  = in->bpp;338	tu->pixelEnc             = in->pixel_enc;339	tu->dsc_en               = in->dsc_en;340	tu->async_en             = in->async_en;341	tu->lwidth_fp            = drm_fixp_from_fraction(in->hactive, 1);342	tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1);343 344	if (tu->pixelEnc == 420) {345		temp1_fp = drm_fixp_from_fraction(2, 1);346		tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp);347		tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp);348		tu->hbp_relative_to_pclk_fp =349				drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2);350	}351 352	if (tu->pixelEnc == 422) {353		switch (tu->bpp) {354		case 24:355			tu->bpp = 16;356			tu->bpc = 8;357			break;358		case 30:359			tu->bpp = 20;360			tu->bpc = 10;361			break;362		default:363			tu->bpp = 16;364			tu->bpc = 8;365			break;366		}367	} else {368		tu->bpc = tu->bpp/3;369	}370 371	if (!in->dsc_en)372		goto fec_check;373 374	temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100);375	temp2_fp = drm_fixp_from_fraction(in->bpp, 1);376	temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);377	temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp);378 379	temp1_fp = drm_fixp_from_fraction(8, 1);380	temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);381 382	numerator = drm_fixp2int(temp3_fp);383 384	dsc_num_bytes  = numerator / dsc_num_slices;385	eoc_bytes           = dsc_num_bytes % nlanes;386	tot_num_eoc_symbols = nlanes * dsc_num_slices;387	tot_num_hor_bytes   = dsc_num_bytes * dsc_num_slices;388	tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices;389 390	if (dsc_num_bytes == 0)391		pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes);392 393	dwidth_dsc_bytes = (tot_num_hor_bytes +394				tot_num_eoc_symbols +395				(eoc_bytes == 0 ? 0 : tot_num_dummy_bytes));396 397	dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3);398 399	temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp);400	temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp);401	pclk_dsc_fp = temp1_fp;402 403	temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp);404	temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp);405	hbp_dsc_fp = temp2_fp;406 407	/* output */408	tu->pclk_fp = pclk_dsc_fp;409	tu->lwidth_fp = dwidth_dsc_fp;410	tu->hbp_relative_to_pclk_fp = hbp_dsc_fp;411 412fec_check:413	if (in->fec_en) {414		temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */415		tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp);416	}417}418 419static void _tu_valid_boundary_calc(struct tu_algo_data *tu)420{421	s64 temp1_fp, temp2_fp, temp, temp1, temp2;422	int compare_result_1, compare_result_2, compare_result_3;423 424	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);425	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);426 427	tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp);428 429	temp = (tu->i_upper_boundary_count *430				tu->new_valid_boundary_link +431				tu->i_lower_boundary_count *432				(tu->new_valid_boundary_link-1));433	tu->average_valid2_fp = drm_fixp_from_fraction(temp,434					(tu->i_upper_boundary_count +435					tu->i_lower_boundary_count));436 437	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);438	temp2_fp = tu->lwidth_fp;439	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);440	temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);441	tu->n_tus = drm_fixp2int(temp2_fp);442	if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)443		tu->n_tus += 1;444 445	temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1);446	temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp);447	temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1);448	temp2_fp = temp1_fp - temp2_fp;449	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);450	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);451	tu->n_remainder_symbols_per_lane_fp = temp2_fp;452 453	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);454	tu->last_partial_tu_fp =455			drm_fixp_div(tu->n_remainder_symbols_per_lane_fp,456					temp1_fp);457 458	if (tu->n_remainder_symbols_per_lane_fp != 0)459		tu->remainder_symbols_exist = 1;460	else461		tu->remainder_symbols_exist = 0;462 463	temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes);464	tu->n_tus_per_lane = drm_fixp2int(temp1_fp);465 466	tu->paired_tus = (int)((tu->n_tus_per_lane) /467					(tu->i_upper_boundary_count +468					 tu->i_lower_boundary_count));469 470	tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus *471						(tu->i_upper_boundary_count +472						tu->i_lower_boundary_count);473 474	if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) {475		tu->remainder_tus_upper = tu->i_upper_boundary_count;476		tu->remainder_tus_lower = tu->remainder_tus -477						tu->i_upper_boundary_count;478	} else {479		tu->remainder_tus_upper = tu->remainder_tus;480		tu->remainder_tus_lower = 0;481	}482 483	temp = tu->paired_tus * (tu->i_upper_boundary_count *484				tu->new_valid_boundary_link +485				tu->i_lower_boundary_count *486				(tu->new_valid_boundary_link - 1)) +487				(tu->remainder_tus_upper *488				 tu->new_valid_boundary_link) +489				(tu->remainder_tus_lower *490				(tu->new_valid_boundary_link - 1));491	tu->total_valid_fp = drm_fixp_from_fraction(temp, 1);492 493	if (tu->remainder_symbols_exist) {494		temp1_fp = tu->total_valid_fp +495				tu->n_remainder_symbols_per_lane_fp;496		temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);497		temp2_fp = temp2_fp + tu->last_partial_tu_fp;498		temp1_fp = drm_fixp_div(temp1_fp, temp2_fp);499	} else {500		temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);501		temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp);502	}503	tu->effective_valid_fp = temp1_fp;504 505	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);506	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);507	tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp;508 509	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);510	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);511	tu->n_err_fp = tu->average_valid2_fp - temp2_fp;512 513	tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0;514 515	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);516	temp2_fp = tu->lwidth_fp;517	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);518	temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);519 520	if (temp2_fp)521		tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp);522	else523		tu->n_tus_incl_last_incomplete_tu = 0;524 525	temp1 = 0;526	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);527	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);528	temp1_fp = tu->average_valid2_fp - temp2_fp;529	temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1);530	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);531 532	if (temp1_fp)533		temp1 = drm_fixp2int_ceil(temp1_fp);534 535	temp = tu->i_upper_boundary_count * tu->nlanes;536	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);537	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);538	temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1);539	temp2_fp = temp1_fp - temp2_fp;540	temp1_fp = drm_fixp_from_fraction(temp, 1);541	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);542 543	if (temp2_fp)544		temp2 = drm_fixp2int_ceil(temp2_fp);545	else546		temp2 = 0;547	tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2);548 549	temp1_fp = drm_fixp_from_fraction(8, tu->bpp);550	temp2_fp = drm_fixp_from_fraction(551	tu->extra_required_bytes_new_tmp, 1);552	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);553 554	if (temp1_fp)555		tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp);556	else557		tu->extra_pclk_cycles_tmp = 0;558 559	temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1);560	temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);561	temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);562 563	if (temp1_fp)564		tu->extra_pclk_cycles_in_link_clk_tmp =565						drm_fixp2int_ceil(temp1_fp);566	else567		tu->extra_pclk_cycles_in_link_clk_tmp = 0;568 569	tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link;570 571	tu->lower_filler_size_tmp = tu->filler_size_tmp + 1;572 573	tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp +574					tu->lower_filler_size_tmp +575					tu->extra_buffer_margin;576 577	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1);578	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);579 580	compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp);581	if (compare_result_1 == 2)582		compare_result_1 = 1;583	else584		compare_result_1 = 0;585 586	compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp);587	if (compare_result_2 == 2)588		compare_result_2 = 1;589	else590		compare_result_2 = 0;591 592	compare_result_3 = _tu_param_compare(tu->hbp_time_fp,593					tu->delay_start_time_fp);594	if (compare_result_3 == 2)595		compare_result_3 = 0;596	else597		compare_result_3 = 1;598 599	if (((tu->even_distribution == 1) ||600			((tu->even_distribution_BF == 0) &&601			(tu->even_distribution_legacy == 0))) &&602			tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 &&603			compare_result_2 &&604			(compare_result_1 || (tu->min_hblank_violated == 1)) &&605			(tu->new_valid_boundary_link - 1) > 0 &&606			compare_result_3 &&607			(tu->delay_start_link_tmp <= 1023)) {608		tu->upper_boundary_count = tu->i_upper_boundary_count;609		tu->lower_boundary_count = tu->i_lower_boundary_count;610		tu->err_fp = tu->n_n_err_fp;611		tu->boundary_moderation_en = true;612		tu->tu_size_desired = tu->tu_size;613		tu->valid_boundary_link = tu->new_valid_boundary_link;614		tu->effective_valid_recorded_fp = tu->effective_valid_fp;615		tu->even_distribution_BF = 1;616		tu->delay_start_link = tu->delay_start_link_tmp;617	} else if (tu->boundary_mod_lower_err == 0) {618		compare_result_1 = _tu_param_compare(tu->n_n_err_fp,619							tu->diff_abs_fp);620		if (compare_result_1 == 2)621			tu->boundary_mod_lower_err = 1;622	}623}624 625static void _dp_ctrl_calc_tu(struct dp_ctrl_private *ctrl,626				struct dp_tu_calc_input *in,627				struct dp_vc_tu_mapping_table *tu_table)628{629	struct tu_algo_data *tu;630	int compare_result_1, compare_result_2;631	u64 temp = 0;632	s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0;633 634	s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */635	s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */636	s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */637	s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000);638 639	u8 DP_BRUTE_FORCE = 1;640	s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */641	uint EXTRA_PIXCLK_CYCLE_DELAY = 4;642	uint HBLANK_MARGIN = 4;643 644	tu = kzalloc(sizeof(*tu), GFP_KERNEL);645	if (!tu)646		return;647 648	dp_panel_update_tu_timings(in, tu);649 650	tu->err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */651 652	temp1_fp = drm_fixp_from_fraction(4, 1);653	temp2_fp = drm_fixp_mul(temp1_fp, tu->lclk_fp);654	temp_fp = drm_fixp_div(temp2_fp, tu->pclk_fp);655	tu->extra_buffer_margin = drm_fixp2int_ceil(temp_fp);656 657	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);658	temp2_fp = drm_fixp_mul(tu->pclk_fp, temp1_fp);659	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);660	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);661	tu->ratio_fp = drm_fixp_div(temp2_fp, tu->lclk_fp);662 663	tu->original_ratio_fp = tu->ratio_fp;664	tu->boundary_moderation_en = false;665	tu->upper_boundary_count = 0;666	tu->lower_boundary_count = 0;667	tu->i_upper_boundary_count = 0;668	tu->i_lower_boundary_count = 0;669	tu->valid_lower_boundary_link = 0;670	tu->even_distribution_BF = 0;671	tu->even_distribution_legacy = 0;672	tu->even_distribution = 0;673	tu->delay_start_time_fp = 0;674 675	tu->err_fp = drm_fixp_from_fraction(1000, 1);676	tu->n_err_fp = 0;677	tu->n_n_err_fp = 0;678 679	tu->ratio = drm_fixp2int(tu->ratio_fp);680	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);681	div64_u64_rem(tu->lwidth_fp, temp1_fp, &temp2_fp);682	if (temp2_fp != 0 &&683			!tu->ratio && tu->dsc_en == 0) {684		tu->ratio_fp = drm_fixp_mul(tu->ratio_fp, RATIO_SCALE_fp);685		tu->ratio = drm_fixp2int(tu->ratio_fp);686		if (tu->ratio)687			tu->ratio_fp = drm_fixp_from_fraction(1, 1);688	}689 690	if (tu->ratio > 1)691		tu->ratio = 1;692 693	if (tu->ratio == 1)694		goto tu_size_calc;695 696	compare_result_1 = _tu_param_compare(tu->ratio_fp, const_p49_fp);697	if (!compare_result_1 || compare_result_1 == 1)698		compare_result_1 = 1;699	else700		compare_result_1 = 0;701 702	compare_result_2 = _tu_param_compare(tu->ratio_fp, const_p56_fp);703	if (!compare_result_2 || compare_result_2 == 2)704		compare_result_2 = 1;705	else706		compare_result_2 = 0;707 708	if (tu->dsc_en && compare_result_1 && compare_result_2) {709		HBLANK_MARGIN += 4;710		drm_dbg_dp(ctrl->drm_dev,711			"increase HBLANK_MARGIN to %d\n", HBLANK_MARGIN);712	}713 714tu_size_calc:715	for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) {716		temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);717		temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);718		temp = drm_fixp2int_ceil(temp2_fp);719		temp1_fp = drm_fixp_from_fraction(temp, 1);720		tu->n_err_fp = temp1_fp - temp2_fp;721 722		if (tu->n_err_fp < tu->err_fp) {723			tu->err_fp = tu->n_err_fp;724			tu->tu_size_desired = tu->tu_size;725		}726	}727 728	tu->tu_size_minus1 = tu->tu_size_desired - 1;729 730	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);731	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);732	tu->valid_boundary_link = drm_fixp2int_ceil(temp2_fp);733 734	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);735	temp2_fp = tu->lwidth_fp;736	temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp);737 738	temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1);739	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);740	tu->n_tus = drm_fixp2int(temp2_fp);741	if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)742		tu->n_tus += 1;743 744	tu->even_distribution_legacy = tu->n_tus % tu->nlanes == 0 ? 1 : 0;745 746	drm_dbg_dp(ctrl->drm_dev,747			"n_sym = %d, num_of_tus = %d\n",748			tu->valid_boundary_link, tu->n_tus);749 750	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);751	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);752	temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1);753	temp2_fp = temp1_fp - temp2_fp;754	temp1_fp = drm_fixp_from_fraction(tu->n_tus + 1, 1);755	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);756 757	temp = drm_fixp2int(temp2_fp);758	if (temp && temp2_fp)759		tu->extra_bytes = drm_fixp2int_ceil(temp2_fp);760	else761		tu->extra_bytes = 0;762 763	temp1_fp = drm_fixp_from_fraction(tu->extra_bytes, 1);764	temp2_fp = drm_fixp_from_fraction(8, tu->bpp);765	temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);766 767	if (temp && temp1_fp)768		tu->extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp);769	else770		tu->extra_pclk_cycles = drm_fixp2int(temp1_fp);771 772	temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);773	temp2_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles, 1);774	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);775 776	if (temp1_fp)777		tu->extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp);778	else779		tu->extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp);780 781	tu->filler_size = tu->tu_size_desired - tu->valid_boundary_link;782 783	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);784	tu->ratio_by_tu_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);785 786	tu->delay_start_link = tu->extra_pclk_cycles_in_link_clk +787				tu->filler_size + tu->extra_buffer_margin;788 789	tu->resulting_valid_fp =790			drm_fixp_from_fraction(tu->valid_boundary_link, 1);791 792	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);793	temp2_fp = drm_fixp_div(tu->resulting_valid_fp, temp1_fp);794	tu->TU_ratio_err_fp = temp2_fp - tu->original_ratio_fp;795 796	temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1);797	temp1_fp = tu->hbp_relative_to_pclk_fp - temp1_fp;798	tu->hbp_time_fp = drm_fixp_div(temp1_fp, tu->pclk_fp);799 800	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link, 1);801	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);802 803	compare_result_1 = _tu_param_compare(tu->hbp_time_fp,804					tu->delay_start_time_fp);805	if (compare_result_1 == 2) /* if (hbp_time_fp < delay_start_time_fp) */806		tu->min_hblank_violated = 1;807 808	tu->hactive_time_fp = drm_fixp_div(tu->lwidth_fp, tu->pclk_fp);809 810	compare_result_2 = _tu_param_compare(tu->hactive_time_fp,811						tu->delay_start_time_fp);812	if (compare_result_2 == 2)813		tu->min_hblank_violated = 1;814 815	tu->delay_start_time_fp = 0;816 817	/* brute force */818 819	tu->delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY;820	tu->diff_abs_fp = tu->resulting_valid_fp - tu->ratio_by_tu_fp;821 822	temp = drm_fixp2int(tu->diff_abs_fp);823	if (!temp && tu->diff_abs_fp <= 0xffff)824		tu->diff_abs_fp = 0;825 826	/* if(diff_abs < 0) diff_abs *= -1 */827	if (tu->diff_abs_fp < 0)828		tu->diff_abs_fp = drm_fixp_mul(tu->diff_abs_fp, -1);829 830	tu->boundary_mod_lower_err = 0;831	if ((tu->diff_abs_fp != 0 &&832			((tu->diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) ||833			 (tu->even_distribution_legacy == 0) ||834			 (DP_BRUTE_FORCE == 1))) ||835			(tu->min_hblank_violated == 1)) {836		do {837			tu->err_fp = drm_fixp_from_fraction(1000, 1);838 839			temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);840			temp2_fp = drm_fixp_from_fraction(841					tu->delay_start_link_extra_pixclk, 1);842			temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);843 844			if (temp1_fp)845				tu->extra_buffer_margin =846					drm_fixp2int_ceil(temp1_fp);847			else848				tu->extra_buffer_margin = 0;849 850			temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);851			temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp);852 853			if (temp1_fp)854				tu->n_symbols = drm_fixp2int_ceil(temp1_fp);855			else856				tu->n_symbols = 0;857 858			for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) {859				for (tu->i_upper_boundary_count = 1;860					tu->i_upper_boundary_count <= 15;861					tu->i_upper_boundary_count++) {862					for (tu->i_lower_boundary_count = 1;863						tu->i_lower_boundary_count <= 15;864						tu->i_lower_boundary_count++) {865						_tu_valid_boundary_calc(tu);866					}867				}868			}869			tu->delay_start_link_extra_pixclk--;870		} while (tu->boundary_moderation_en != true &&871			tu->boundary_mod_lower_err == 1 &&872			tu->delay_start_link_extra_pixclk != 0);873 874		if (tu->boundary_moderation_en == true) {875			temp1_fp = drm_fixp_from_fraction(876					(tu->upper_boundary_count *877					tu->valid_boundary_link +878					tu->lower_boundary_count *879					(tu->valid_boundary_link - 1)), 1);880			temp2_fp = drm_fixp_from_fraction(881					(tu->upper_boundary_count +882					tu->lower_boundary_count), 1);883			tu->resulting_valid_fp =884					drm_fixp_div(temp1_fp, temp2_fp);885 886			temp1_fp = drm_fixp_from_fraction(887					tu->tu_size_desired, 1);888			tu->ratio_by_tu_fp =889				drm_fixp_mul(tu->original_ratio_fp, temp1_fp);890 891			tu->valid_lower_boundary_link =892				tu->valid_boundary_link - 1;893 894			temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);895			temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp);896			temp2_fp = drm_fixp_div(temp1_fp,897						tu->resulting_valid_fp);898			tu->n_tus = drm_fixp2int(temp2_fp);899 900			tu->tu_size_minus1 = tu->tu_size_desired - 1;901			tu->even_distribution_BF = 1;902 903			temp1_fp =904				drm_fixp_from_fraction(tu->tu_size_desired, 1);905			temp2_fp =906				drm_fixp_div(tu->resulting_valid_fp, temp1_fp);907			tu->TU_ratio_err_fp = temp2_fp - tu->original_ratio_fp;908		}909	}910 911	temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu->lwidth_fp);912 913	if (temp2_fp)914		temp = drm_fixp2int_ceil(temp2_fp);915	else916		temp = 0;917 918	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);919	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);920	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);921	temp2_fp = drm_fixp_div(temp1_fp, temp2_fp);922	temp1_fp = drm_fixp_from_fraction(temp, 1);923	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);924	temp = drm_fixp2int(temp2_fp);925 926	if (tu->async_en)927		tu->delay_start_link += (int)temp;928 929	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link, 1);930	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);931 932	/* OUTPUTS */933	tu_table->valid_boundary_link       = tu->valid_boundary_link;934	tu_table->delay_start_link          = tu->delay_start_link;935	tu_table->boundary_moderation_en    = tu->boundary_moderation_en;936	tu_table->valid_lower_boundary_link = tu->valid_lower_boundary_link;937	tu_table->upper_boundary_count      = tu->upper_boundary_count;938	tu_table->lower_boundary_count      = tu->lower_boundary_count;939	tu_table->tu_size_minus1            = tu->tu_size_minus1;940 941	drm_dbg_dp(ctrl->drm_dev, "TU: valid_boundary_link: %d\n",942				tu_table->valid_boundary_link);943	drm_dbg_dp(ctrl->drm_dev, "TU: delay_start_link: %d\n",944				tu_table->delay_start_link);945	drm_dbg_dp(ctrl->drm_dev, "TU: boundary_moderation_en: %d\n",946			tu_table->boundary_moderation_en);947	drm_dbg_dp(ctrl->drm_dev, "TU: valid_lower_boundary_link: %d\n",948			tu_table->valid_lower_boundary_link);949	drm_dbg_dp(ctrl->drm_dev, "TU: upper_boundary_count: %d\n",950			tu_table->upper_boundary_count);951	drm_dbg_dp(ctrl->drm_dev, "TU: lower_boundary_count: %d\n",952			tu_table->lower_boundary_count);953	drm_dbg_dp(ctrl->drm_dev, "TU: tu_size_minus1: %d\n",954			tu_table->tu_size_minus1);955 956	kfree(tu);957}958 959static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,960		struct dp_vc_tu_mapping_table *tu_table)961{962	struct dp_tu_calc_input in;963	struct drm_display_mode *drm_mode;964 965	drm_mode = &ctrl->panel->dp_mode.drm_mode;966 967	in.lclk = ctrl->link->link_params.rate / 1000;968	in.pclk_khz = drm_mode->clock;969	in.hactive = drm_mode->hdisplay;970	in.hporch = drm_mode->htotal - drm_mode->hdisplay;971	in.nlanes = ctrl->link->link_params.num_lanes;972	in.bpp = ctrl->panel->dp_mode.bpp;973	in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;974	in.dsc_en = 0;975	in.async_en = 0;976	in.fec_en = 0;977	in.num_of_dsc_slices = 0;978	in.compress_ratio = 100;979 980	_dp_ctrl_calc_tu(ctrl, &in, tu_table);981}982 983static void dp_ctrl_setup_tr_unit(struct dp_ctrl_private *ctrl)984{985	u32 dp_tu = 0x0;986	u32 valid_boundary = 0x0;987	u32 valid_boundary2 = 0x0;988	struct dp_vc_tu_mapping_table tu_calc_table;989 990	dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);991 992	dp_tu |= tu_calc_table.tu_size_minus1;993	valid_boundary |= tu_calc_table.valid_boundary_link;994	valid_boundary |= (tu_calc_table.delay_start_link << 16);995 996	valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1);997	valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16);998	valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20);999 1000	if (tu_calc_table.boundary_moderation_en)1001		valid_boundary2 |= BIT(0);1002 1003	pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",1004			dp_tu, valid_boundary, valid_boundary2);1005 1006	dp_catalog_ctrl_update_transfer_unit(ctrl->catalog,1007				dp_tu, valid_boundary, valid_boundary2);1008}1009 1010static int dp_ctrl_wait4video_ready(struct dp_ctrl_private *ctrl)1011{1012	int ret = 0;1013 1014	if (!wait_for_completion_timeout(&ctrl->video_comp,1015				WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES)) {1016		DRM_ERROR("wait4video timedout\n");1017		ret = -ETIMEDOUT;1018	}1019	return ret;1020}1021 1022static int dp_ctrl_set_vx_px(struct dp_ctrl_private *ctrl,1023			     u8 v_level, u8 p_level)1024{1025	union phy_configure_opts *phy_opts = &ctrl->phy_opts;1026 1027	/* TODO: Update for all lanes instead of just first one */1028	phy_opts->dp.voltage[0] = v_level;1029	phy_opts->dp.pre[0] = p_level;1030	phy_opts->dp.set_voltages = 1;1031	phy_configure(ctrl->phy, phy_opts);1032	phy_opts->dp.set_voltages = 0;1033 1034	return 0;1035}1036 1037static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)1038{1039	struct dp_link *link = ctrl->link;1040	int ret = 0, lane, lane_cnt;1041	u8 buf[4];1042	u32 max_level_reached = 0;1043	u32 voltage_swing_level = link->phy_params.v_level;1044	u32 pre_emphasis_level = link->phy_params.p_level;1045 1046	drm_dbg_dp(ctrl->drm_dev,1047		"voltage level: %d emphasis level: %d\n",1048			voltage_swing_level, pre_emphasis_level);1049	ret = dp_ctrl_set_vx_px(ctrl,1050		voltage_swing_level, pre_emphasis_level);1051 1052	if (ret)1053		return ret;1054 1055	if (voltage_swing_level >= DP_TRAIN_LEVEL_MAX) {1056		drm_dbg_dp(ctrl->drm_dev,1057				"max. voltage swing level reached %d\n",1058				voltage_swing_level);1059		max_level_reached |= DP_TRAIN_MAX_SWING_REACHED;1060	}1061 1062	if (pre_emphasis_level >= DP_TRAIN_LEVEL_MAX) {1063		drm_dbg_dp(ctrl->drm_dev,1064				"max. pre-emphasis level reached %d\n",1065				pre_emphasis_level);1066		max_level_reached  |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;1067	}1068 1069	pre_emphasis_level <<= DP_TRAIN_PRE_EMPHASIS_SHIFT;1070 1071	lane_cnt = ctrl->link->link_params.num_lanes;1072	for (lane = 0; lane < lane_cnt; lane++)1073		buf[lane] = voltage_swing_level | pre_emphasis_level1074				| max_level_reached;1075 1076	drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n",1077			voltage_swing_level | pre_emphasis_level);1078	ret = drm_dp_dpcd_write(ctrl->aux, DP_TRAINING_LANE0_SET,1079					buf, lane_cnt);1080	if (ret == lane_cnt)1081		ret = 0;1082 1083	return ret;1084}1085 1086static bool dp_ctrl_train_pattern_set(struct dp_ctrl_private *ctrl,1087		u8 pattern)1088{1089	u8 buf;1090	int ret = 0;1091 1092	drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern);1093 1094	buf = pattern;1095 1096	if (pattern && pattern != DP_TRAINING_PATTERN_4)1097		buf |= DP_LINK_SCRAMBLING_DISABLE;1098 1099	ret = drm_dp_dpcd_writeb(ctrl->aux, DP_TRAINING_PATTERN_SET, buf);1100	return ret == 1;1101}1102 1103static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,1104				    u8 *link_status)1105{1106	int ret = 0, len;1107 1108	len = drm_dp_dpcd_read_link_status(ctrl->aux, link_status);1109	if (len != DP_LINK_STATUS_SIZE) {1110		DRM_ERROR("DP link status read failed, err: %d\n", len);1111		ret = -EINVAL;1112	}1113 1114	return ret;1115}1116 1117static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,1118			int *training_step)1119{1120	int tries, old_v_level, ret = 0;1121	u8 link_status[DP_LINK_STATUS_SIZE];1122	int const maximum_retries = 4;1123 1124	dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);1125 1126	*training_step = DP_TRAINING_1;1127 1128	ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, 1);1129	if (ret)1130		return ret;1131	dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |1132		DP_LINK_SCRAMBLING_DISABLE);1133 1134	ret = dp_ctrl_update_vx_px(ctrl);1135	if (ret)1136		return ret;1137 1138	tries = 0;1139	old_v_level = ctrl->link->phy_params.v_level;1140	for (tries = 0; tries < maximum_retries; tries++) {1141		drm_dp_link_train_clock_recovery_delay(ctrl->aux, ctrl->panel->dpcd);1142 1143		ret = dp_ctrl_read_link_status(ctrl, link_status);1144		if (ret)1145			return ret;1146 1147		if (drm_dp_clock_recovery_ok(link_status,1148			ctrl->link->link_params.num_lanes)) {1149			return 0;1150		}1151 1152		if (ctrl->link->phy_params.v_level >=1153			DP_TRAIN_LEVEL_MAX) {1154			DRM_ERROR_RATELIMITED("max v_level reached\n");1155			return -EAGAIN;1156		}1157 1158		if (old_v_level != ctrl->link->phy_params.v_level) {1159			tries = 0;1160			old_v_level = ctrl->link->phy_params.v_level;1161		}1162 1163		dp_link_adjust_levels(ctrl->link, link_status);1164		ret = dp_ctrl_update_vx_px(ctrl);1165		if (ret)1166			return ret;1167	}1168 1169	DRM_ERROR("max tries reached\n");1170	return -ETIMEDOUT;1171}1172 1173static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)1174{1175	int ret = 0;1176 1177	switch (ctrl->link->link_params.rate) {1178	case 810000:1179		ctrl->link->link_params.rate = 540000;1180		break;1181	case 540000:1182		ctrl->link->link_params.rate = 270000;1183		break;1184	case 270000:1185		ctrl->link->link_params.rate = 162000;1186		break;1187	case 162000:1188	default:1189		ret = -EINVAL;1190		break;1191	}1192 1193	if (!ret) {1194		drm_dbg_dp(ctrl->drm_dev, "new rate=0x%x\n",1195				ctrl->link->link_params.rate);1196	}1197 1198	return ret;1199}1200 1201static int dp_ctrl_link_lane_down_shift(struct dp_ctrl_private *ctrl)1202{1203 1204	if (ctrl->link->link_params.num_lanes == 1)1205		return -1;1206 1207	ctrl->link->link_params.num_lanes /= 2;1208	ctrl->link->link_params.rate = ctrl->panel->link_info.rate;1209 1210	ctrl->link->phy_params.p_level = 0;1211	ctrl->link->phy_params.v_level = 0;1212 1213	return 0;1214}1215 1216static void dp_ctrl_clear_training_pattern(struct dp_ctrl_private *ctrl)1217{1218	dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE);1219	drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd);1220}1221 1222static int dp_ctrl_link_train_2(struct dp_ctrl_private *ctrl,1223			int *training_step)1224{1225	int tries = 0, ret = 0;1226	u8 pattern;1227	u32 state_ctrl_bit;1228	int const maximum_retries = 5;1229	u8 link_status[DP_LINK_STATUS_SIZE];1230 1231	dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);1232 1233	*training_step = DP_TRAINING_2;1234 1235	if (drm_dp_tps4_supported(ctrl->panel->dpcd)) {1236		pattern = DP_TRAINING_PATTERN_4;1237		state_ctrl_bit = 4;1238	} else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) {1239		pattern = DP_TRAINING_PATTERN_3;1240		state_ctrl_bit = 3;1241	} else {1242		pattern = DP_TRAINING_PATTERN_2;1243		state_ctrl_bit = 2;1244	}1245 1246	ret = dp_catalog_ctrl_set_pattern_state_bit(ctrl->catalog, state_ctrl_bit);1247	if (ret)1248		return ret;1249 1250	dp_ctrl_train_pattern_set(ctrl, pattern);1251 1252	for (tries = 0; tries <= maximum_retries; tries++) {1253		drm_dp_link_train_channel_eq_delay(ctrl->aux, ctrl->panel->dpcd);1254 1255		ret = dp_ctrl_read_link_status(ctrl, link_status);1256		if (ret)1257			return ret;1258 1259		if (drm_dp_channel_eq_ok(link_status,1260			ctrl->link->link_params.num_lanes)) {1261			return 0;1262		}1263 1264		dp_link_adjust_levels(ctrl->link, link_status);1265		ret = dp_ctrl_update_vx_px(ctrl);1266		if (ret)1267			return ret;1268 1269	}1270 1271	return -ETIMEDOUT;1272}1273 1274static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,1275			int *training_step)1276{1277	int ret = 0;1278	const u8 *dpcd = ctrl->panel->dpcd;1279	u8 encoding[] = { 0, DP_SET_ANSI_8B10B };1280	u8 assr;1281	struct dp_link_info link_info = {0};1282 1283	dp_ctrl_config_ctrl(ctrl);1284 1285	link_info.num_lanes = ctrl->link->link_params.num_lanes;1286	link_info.rate = ctrl->link->link_params.rate;1287	link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;1288 1289	dp_link_reset_phy_params_vx_px(ctrl->link);1290 1291	dp_aux_link_configure(ctrl->aux, &link_info);1292 1293	if (drm_dp_max_downspread(dpcd))1294		encoding[0] |= DP_SPREAD_AMP_0_5;1295 1296	/* config DOWNSPREAD_CTRL and MAIN_LINK_CHANNEL_CODING_SET */1297	drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, encoding, 2);1298 1299	if (drm_dp_alternate_scrambler_reset_cap(dpcd)) {1300		assr = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;1301		drm_dp_dpcd_write(ctrl->aux, DP_EDP_CONFIGURATION_SET,1302				&assr, 1);1303	}1304 1305	ret = dp_ctrl_link_train_1(ctrl, training_step);1306	if (ret) {1307		DRM_ERROR("link training #1 failed. ret=%d\n", ret);1308		goto end;1309	}1310 1311	/* print success info as this is a result of user initiated action */1312	drm_dbg_dp(ctrl->drm_dev, "link training #1 successful\n");1313 1314	ret = dp_ctrl_link_train_2(ctrl, training_step);1315	if (ret) {1316		DRM_ERROR("link training #2 failed. ret=%d\n", ret);1317		goto end;1318	}1319 1320	/* print success info as this is a result of user initiated action */1321	drm_dbg_dp(ctrl->drm_dev, "link training #2 successful\n");1322 1323end:1324	dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);1325 1326	return ret;1327}1328 1329static int dp_ctrl_setup_main_link(struct dp_ctrl_private *ctrl,1330			int *training_step)1331{1332	int ret = 0;1333 1334	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);1335 1336	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)1337		return ret;1338 1339	/*1340	 * As part of previous calls, DP controller state might have1341	 * transitioned to PUSH_IDLE. In order to start transmitting1342	 * a link training pattern, we have to first do soft reset.1343	 */1344 1345	ret = dp_ctrl_link_train(ctrl, training_step);1346 1347	return ret;1348}1349 1350int dp_ctrl_core_clk_enable(struct dp_ctrl *dp_ctrl)1351{1352	struct dp_ctrl_private *ctrl;1353	int ret = 0;1354 1355	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1356 1357	if (ctrl->core_clks_on) {1358		drm_dbg_dp(ctrl->drm_dev, "core clks already enabled\n");1359		return 0;1360	}1361 1362	ret = clk_bulk_prepare_enable(ctrl->num_core_clks, ctrl->core_clks);1363	if (ret)1364		return ret;1365 1366	ctrl->core_clks_on = true;1367 1368	drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n");1369	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",1370		   ctrl->stream_clks_on ? "on" : "off",1371		   ctrl->link_clks_on ? "on" : "off",1372		   ctrl->core_clks_on ? "on" : "off");1373 1374	return 0;1375}1376 1377void dp_ctrl_core_clk_disable(struct dp_ctrl *dp_ctrl)1378{1379	struct dp_ctrl_private *ctrl;1380 1381	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1382 1383	clk_bulk_disable_unprepare(ctrl->num_core_clks, ctrl->core_clks);1384 1385	ctrl->core_clks_on = false;1386 1387	drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n");1388	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",1389		   ctrl->stream_clks_on ? "on" : "off",1390		   ctrl->link_clks_on ? "on" : "off",1391		   ctrl->core_clks_on ? "on" : "off");1392}1393 1394static int dp_ctrl_link_clk_enable(struct dp_ctrl *dp_ctrl)1395{1396	struct dp_ctrl_private *ctrl;1397	int ret = 0;1398 1399	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1400 1401	if (ctrl->link_clks_on) {1402		drm_dbg_dp(ctrl->drm_dev, "links clks already enabled\n");1403		return 0;1404	}1405 1406	if (!ctrl->core_clks_on) {1407		drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n");1408 1409		dp_ctrl_core_clk_enable(dp_ctrl);1410	}1411 1412	ret = clk_bulk_prepare_enable(ctrl->num_link_clks, ctrl->link_clks);1413	if (ret)1414		return ret;1415 1416	ctrl->link_clks_on = true;1417 1418	drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n");1419	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",1420		   ctrl->stream_clks_on ? "on" : "off",1421		   ctrl->link_clks_on ? "on" : "off",1422		   ctrl->core_clks_on ? "on" : "off");1423 1424	return 0;1425}1426 1427static void dp_ctrl_link_clk_disable(struct dp_ctrl *dp_ctrl)1428{1429	struct dp_ctrl_private *ctrl;1430 1431	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1432 1433	clk_bulk_disable_unprepare(ctrl->num_link_clks, ctrl->link_clks);1434 1435	ctrl->link_clks_on = false;1436 1437	drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n");1438	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",1439		   ctrl->stream_clks_on ? "on" : "off",1440		   ctrl->link_clks_on ? "on" : "off",1441		   ctrl->core_clks_on ? "on" : "off");1442}1443 1444static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl)1445{1446	int ret = 0;1447	struct phy *phy = ctrl->phy;1448	const u8 *dpcd = ctrl->panel->dpcd;1449 1450	ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes;1451	ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100;1452	ctrl->phy_opts.dp.ssc = drm_dp_max_downspread(dpcd);1453 1454	phy_configure(phy, &ctrl->phy_opts);1455	phy_power_on(phy);1456 1457	dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000);1458	ret = dp_ctrl_link_clk_enable(&ctrl->dp_ctrl);1459	if (ret)1460		DRM_ERROR("Unable to start link clocks. ret=%d\n", ret);1461 1462	drm_dbg_dp(ctrl->drm_dev, "link rate=%d\n", ctrl->link->link_params.rate);1463 1464	return ret;1465}1466 1467void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable)1468{1469	struct dp_ctrl_private *ctrl;1470 1471	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1472 1473	dp_catalog_ctrl_reset(ctrl->catalog);1474 1475	/*1476	 * all dp controller programmable registers will not1477	 * be reset to default value after DP_SW_RESET1478	 * therefore interrupt mask bits have to be updated1479	 * to enable/disable interrupts1480	 */1481	dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);1482}1483 1484void dp_ctrl_config_psr(struct dp_ctrl *dp_ctrl)1485{1486	u8 cfg;1487	struct dp_ctrl_private *ctrl = container_of(dp_ctrl,1488			struct dp_ctrl_private, dp_ctrl);1489 1490	if (!ctrl->panel->psr_cap.version)1491		return;1492 1493	dp_catalog_ctrl_config_psr(ctrl->catalog);1494 1495	cfg = DP_PSR_ENABLE;1496	drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1);1497}1498 1499void dp_ctrl_set_psr(struct dp_ctrl *dp_ctrl, bool enter)1500{1501	struct dp_ctrl_private *ctrl = container_of(dp_ctrl,1502			struct dp_ctrl_private, dp_ctrl);1503 1504	if (!ctrl->panel->psr_cap.version)1505		return;1506 1507	/*1508	 * When entering PSR,1509	 * 1. Send PSR enter SDP and wait for the PSR_UPDATE_INT1510	 * 2. Turn off video1511	 * 3. Disable the mainlink1512	 *1513	 * When exiting PSR,1514	 * 1. Enable the mainlink1515	 * 2. Send the PSR exit SDP1516	 */1517	if (enter) {1518		reinit_completion(&ctrl->psr_op_comp);1519		dp_catalog_ctrl_set_psr(ctrl->catalog, true);1520 1521		if (!wait_for_completion_timeout(&ctrl->psr_op_comp,1522			PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES)) {1523			DRM_ERROR("PSR_ENTRY timedout\n");1524			dp_catalog_ctrl_set_psr(ctrl->catalog, false);1525			return;1526		}1527 1528		dp_ctrl_push_idle(dp_ctrl);1529		dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);1530 1531		dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, false);1532	} else {1533		dp_catalog_ctrl_psr_mainlink_enable(ctrl->catalog, true);1534 1535		dp_catalog_ctrl_set_psr(ctrl->catalog, false);1536		dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);1537		dp_ctrl_wait4video_ready(ctrl);1538		dp_catalog_ctrl_state_ctrl(ctrl->catalog, 0);1539	}1540}1541 1542void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl)1543{1544	struct dp_ctrl_private *ctrl;1545	struct phy *phy;1546 1547	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1548	phy = ctrl->phy;1549 1550	dp_catalog_ctrl_phy_reset(ctrl->catalog);1551	phy_init(phy);1552 1553	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",1554			phy, phy->init_count, phy->power_count);1555}1556 1557void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl)1558{1559	struct dp_ctrl_private *ctrl;1560	struct phy *phy;1561 1562	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1563	phy = ctrl->phy;1564 1565	dp_catalog_ctrl_phy_reset(ctrl->catalog);1566	phy_exit(phy);1567	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",1568			phy, phy->init_count, phy->power_count);1569}1570 1571static int dp_ctrl_reinitialize_mainlink(struct dp_ctrl_private *ctrl)1572{1573	struct phy *phy = ctrl->phy;1574	int ret = 0;1575 1576	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);1577	ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes;1578	phy_configure(phy, &ctrl->phy_opts);1579	/*1580	 * Disable and re-enable the mainlink clock since the1581	 * link clock might have been adjusted as part of the1582	 * link maintenance.1583	 */1584	dev_pm_opp_set_rate(ctrl->dev, 0);1585 1586	dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);1587 1588	phy_power_off(phy);1589	/* hw recommended delay before re-enabling clocks */1590	msleep(20);1591 1592	ret = dp_ctrl_enable_mainlink_clocks(ctrl);1593	if (ret) {1594		DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret);1595		return ret;1596	}1597 1598	return ret;1599}1600 1601static int dp_ctrl_deinitialize_mainlink(struct dp_ctrl_private *ctrl)1602{1603	struct phy *phy;1604 1605	phy = ctrl->phy;1606 1607	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);1608 1609	dp_catalog_ctrl_reset(ctrl->catalog);1610 1611	dev_pm_opp_set_rate(ctrl->dev, 0);1612	dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);1613 1614	phy_power_off(phy);1615 1616	/* aux channel down, reinit phy */1617	phy_exit(phy);1618	phy_init(phy);1619 1620	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",1621			phy, phy->init_count, phy->power_count);1622	return 0;1623}1624 1625static int dp_ctrl_link_maintenance(struct dp_ctrl_private *ctrl)1626{1627	int ret = 0;1628	int training_step = DP_TRAINING_NONE;1629 1630	dp_ctrl_push_idle(&ctrl->dp_ctrl);1631 1632	ctrl->link->phy_params.p_level = 0;1633	ctrl->link->phy_params.v_level = 0;1634 1635	ret = dp_ctrl_setup_main_link(ctrl, &training_step);1636	if (ret)1637		goto end;1638 1639	dp_ctrl_clear_training_pattern(ctrl);1640 1641	dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);1642 1643	ret = dp_ctrl_wait4video_ready(ctrl);1644end:1645	return ret;1646}1647 1648static bool dp_ctrl_send_phy_test_pattern(struct dp_ctrl_private *ctrl)1649{1650	bool success = false;1651	u32 pattern_sent = 0x0;1652	u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;1653 1654	drm_dbg_dp(ctrl->drm_dev, "request: 0x%x\n", pattern_requested);1655 1656	if (dp_ctrl_set_vx_px(ctrl,1657			ctrl->link->phy_params.v_level,1658			ctrl->link->phy_params.p_level)) {1659		DRM_ERROR("Failed to set v/p levels\n");1660		return false;1661	}1662	dp_catalog_ctrl_send_phy_pattern(ctrl->catalog, pattern_requested);1663	dp_ctrl_update_vx_px(ctrl);1664	dp_link_send_test_response(ctrl->link);1665 1666	pattern_sent = dp_catalog_ctrl_read_phy_pattern(ctrl->catalog);1667 1668	switch (pattern_sent) {1669	case MR_LINK_TRAINING1:1670		success = (pattern_requested ==1671				DP_PHY_TEST_PATTERN_D10_2);1672		break;1673	case MR_LINK_SYMBOL_ERM:1674		success = ((pattern_requested ==1675			DP_PHY_TEST_PATTERN_ERROR_COUNT) ||1676				(pattern_requested ==1677				DP_PHY_TEST_PATTERN_CP2520));1678		break;1679	case MR_LINK_PRBS7:1680		success = (pattern_requested ==1681				DP_PHY_TEST_PATTERN_PRBS7);1682		break;1683	case MR_LINK_CUSTOM80:1684		success = (pattern_requested ==1685				DP_PHY_TEST_PATTERN_80BIT_CUSTOM);1686		break;1687	case MR_LINK_TRAINING4:1688		success = (pattern_requested ==1689				DP_PHY_TEST_PATTERN_SEL_MASK);1690		break;1691	default:1692		success = false;1693	}1694 1695	drm_dbg_dp(ctrl->drm_dev, "%s: test->0x%x\n",1696		success ? "success" : "failed", pattern_requested);1697	return success;1698}1699 1700static int dp_ctrl_process_phy_test_request(struct dp_ctrl_private *ctrl)1701{1702	int ret;1703	unsigned long pixel_rate;1704 1705	if (!ctrl->link->phy_params.phy_test_pattern_sel) {1706		drm_dbg_dp(ctrl->drm_dev,1707			"no test pattern selected by sink\n");1708		return 0;1709	}1710 1711	/*1712	 * The global reset will need DP link related clocks to be1713	 * running. Add the global reset just before disabling the1714	 * link clocks and core clocks.1715	 */1716	dp_ctrl_off(&ctrl->dp_ctrl);1717 1718	ret = dp_ctrl_on_link(&ctrl->dp_ctrl);1719	if (ret) {1720		DRM_ERROR("failed to enable DP link controller\n");1721		return ret;1722	}1723 1724	pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;1725	ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);1726	if (ret) {1727		DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);1728		return ret;1729	}1730 1731	if (ctrl->stream_clks_on) {1732		drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n");1733	} else {1734		ret = clk_prepare_enable(ctrl->pixel_clk);1735		if (ret) {1736			DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);1737			return ret;1738		}1739		ctrl->stream_clks_on = true;1740	}1741 1742	dp_ctrl_send_phy_test_pattern(ctrl);1743 1744	return 0;1745}1746 1747void dp_ctrl_handle_sink_request(struct dp_ctrl *dp_ctrl)1748{1749	struct dp_ctrl_private *ctrl;1750	u32 sink_request = 0x0;1751 1752	if (!dp_ctrl) {1753		DRM_ERROR("invalid input\n");1754		return;1755	}1756 1757	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1758	sink_request = ctrl->link->sink_request;1759 1760	if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {1761		drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n");1762		if (dp_ctrl_process_phy_test_request(ctrl)) {1763			DRM_ERROR("process phy_test_req failed\n");1764			return;1765		}1766	}1767 1768	if (sink_request & DP_LINK_STATUS_UPDATED) {1769		if (dp_ctrl_link_maintenance(ctrl)) {1770			DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");1771			return;1772		}1773	}1774 1775	if (sink_request & DP_TEST_LINK_TRAINING) {1776		dp_link_send_test_response(ctrl->link);1777		if (dp_ctrl_link_maintenance(ctrl)) {1778			DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");1779			return;1780		}1781	}1782}1783 1784static bool dp_ctrl_clock_recovery_any_ok(1785			const u8 link_status[DP_LINK_STATUS_SIZE],1786			int lane_count)1787{1788	int reduced_cnt;1789 1790	if (lane_count <= 1)1791		return false;1792 1793	/*1794	 * only interested in the lane number after reduced1795	 * lane_count = 4, then only interested in 2 lanes1796	 * lane_count = 2, then only interested in 1 lane1797	 */1798	reduced_cnt = lane_count >> 1;1799 1800	return drm_dp_clock_recovery_ok(link_status, reduced_cnt);1801}1802 1803static bool dp_ctrl_channel_eq_ok(struct dp_ctrl_private *ctrl)1804{1805	u8 link_status[DP_LINK_STATUS_SIZE];1806	int num_lanes = ctrl->link->link_params.num_lanes;1807 1808	dp_ctrl_read_link_status(ctrl, link_status);1809 1810	return drm_dp_channel_eq_ok(link_status, num_lanes);1811}1812 1813int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)1814{1815	int rc = 0;1816	struct dp_ctrl_private *ctrl;1817	u32 rate;1818	int link_train_max_retries = 5;1819	u32 const phy_cts_pixel_clk_khz = 148500;1820	u8 link_status[DP_LINK_STATUS_SIZE];1821	unsigned int training_step;1822	unsigned long pixel_rate;1823 1824	if (!dp_ctrl)1825		return -EINVAL;1826 1827	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1828 1829	rate = ctrl->panel->link_info.rate;1830	pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;1831 1832	dp_ctrl_core_clk_enable(&ctrl->dp_ctrl);1833 1834	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {1835		drm_dbg_dp(ctrl->drm_dev,1836				"using phy test link parameters\n");1837		if (!pixel_rate)1838			pixel_rate = phy_cts_pixel_clk_khz;1839	} else {1840		ctrl->link->link_params.rate = rate;1841		ctrl->link->link_params.num_lanes =1842			ctrl->panel->link_info.num_lanes;1843		if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)1844			pixel_rate >>= 1;1845	}1846 1847	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",1848		ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes,1849		pixel_rate);1850 1851	rc = dp_ctrl_enable_mainlink_clocks(ctrl);1852	if (rc)1853		return rc;1854 1855	while (--link_train_max_retries) {1856		training_step = DP_TRAINING_NONE;1857		rc = dp_ctrl_setup_main_link(ctrl, &training_step);1858		if (rc == 0) {1859			/* training completed successfully */1860			break;1861		} else if (training_step == DP_TRAINING_1) {1862			/* link train_1 failed */1863			if (!dp_catalog_link_is_connected(ctrl->catalog))1864				break;1865 1866			dp_ctrl_read_link_status(ctrl, link_status);1867 1868			rc = dp_ctrl_link_rate_down_shift(ctrl);1869			if (rc < 0) { /* already in RBR = 1.6G */1870				if (dp_ctrl_clock_recovery_any_ok(link_status,1871					ctrl->link->link_params.num_lanes)) {1872					/*1873					 * some lanes are ready,1874					 * reduce lane number1875					 */1876					rc = dp_ctrl_link_lane_down_shift(ctrl);1877					if (rc < 0) { /* lane == 1 already */1878						/* end with failure */1879						break;1880					}1881				} else {1882					/* end with failure */1883					break; /* lane == 1 already */1884				}1885			}1886		} else if (training_step == DP_TRAINING_2) {1887			/* link train_2 failed */1888			if (!dp_catalog_link_is_connected(ctrl->catalog))1889				break;1890 1891			dp_ctrl_read_link_status(ctrl, link_status);1892 1893			if (!drm_dp_clock_recovery_ok(link_status,1894					ctrl->link->link_params.num_lanes))1895				rc = dp_ctrl_link_rate_down_shift(ctrl);1896			else1897				rc = dp_ctrl_link_lane_down_shift(ctrl);1898 1899			if (rc < 0) {1900				/* end with failure */1901				break; /* lane == 1 already */1902			}1903 1904			/* stop link training before start re training  */1905			dp_ctrl_clear_training_pattern(ctrl);1906		}1907 1908		rc = dp_ctrl_reinitialize_mainlink(ctrl);1909		if (rc) {1910			DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc);1911			break;1912		}1913	}1914 1915	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)1916		return rc;1917 1918	if (rc == 0) {  /* link train successfully */1919		/*1920		 * do not stop train pattern here1921		 * stop link training at on_stream1922		 * to pass compliance test1923		 */1924	} else  {1925		/*1926		 * link training failed1927		 * end txing train pattern here1928		 */1929		dp_ctrl_clear_training_pattern(ctrl);1930 1931		dp_ctrl_deinitialize_mainlink(ctrl);1932		rc = -ECONNRESET;1933	}1934 1935	return rc;1936}1937 1938static int dp_ctrl_link_retrain(struct dp_ctrl_private *ctrl)1939{1940	int training_step = DP_TRAINING_NONE;1941 1942	return dp_ctrl_setup_main_link(ctrl, &training_step);1943}1944 1945int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)1946{1947	int ret = 0;1948	bool mainlink_ready = false;1949	struct dp_ctrl_private *ctrl;1950	unsigned long pixel_rate;1951	unsigned long pixel_rate_orig;1952 1953	if (!dp_ctrl)1954		return -EINVAL;1955 1956	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);1957 1958	pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;1959 1960	if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)1961		pixel_rate >>= 1;1962 1963	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",1964		ctrl->link->link_params.rate,1965		ctrl->link->link_params.num_lanes, pixel_rate);1966 1967	drm_dbg_dp(ctrl->drm_dev,1968		"core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",1969		ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on);1970 1971	if (!ctrl->link_clks_on) { /* link clk is off */1972		ret = dp_ctrl_enable_mainlink_clocks(ctrl);1973		if (ret) {1974			DRM_ERROR("Failed to start link clocks. ret=%d\n", ret);1975			goto end;1976		}1977	}1978 1979	ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);1980	if (ret) {1981		DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);1982		goto end;1983	}1984 1985	if (ctrl->stream_clks_on) {1986		drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n");1987	} else {1988		ret = clk_prepare_enable(ctrl->pixel_clk);1989		if (ret) {1990			DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);1991			goto end;1992		}1993		ctrl->stream_clks_on = true;1994	}1995 1996	if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))1997		dp_ctrl_link_retrain(ctrl);1998 1999	/* stop txing train pattern to end link training */2000	dp_ctrl_clear_training_pattern(ctrl);2001 2002	/*2003	 * Set up transfer unit values and set controller state to send2004	 * video.2005	 */2006	reinit_completion(&ctrl->video_comp);2007 2008	dp_ctrl_configure_source_params(ctrl);2009 2010	dp_catalog_ctrl_config_msa(ctrl->catalog,2011		ctrl->link->link_params.rate,2012		pixel_rate_orig,2013		ctrl->panel->dp_mode.out_fmt_is_yuv_420);2014 2015	dp_ctrl_setup_tr_unit(ctrl);2016 2017	dp_catalog_ctrl_state_ctrl(ctrl->catalog, DP_STATE_CTRL_SEND_VIDEO);2018 2019	ret = dp_ctrl_wait4video_ready(ctrl);2020	if (ret)2021		return ret;2022 2023	mainlink_ready = dp_catalog_ctrl_mainlink_ready(ctrl->catalog);2024	drm_dbg_dp(ctrl->drm_dev,2025		"mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");2026 2027end:2028	return ret;2029}2030 2031void dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)2032{2033	struct dp_ctrl_private *ctrl;2034	struct phy *phy;2035 2036	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);2037	phy = ctrl->phy;2038 2039	dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);2040 2041	/* set dongle to D3 (power off) mode */2042	dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);2043 2044	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);2045 2046	if (ctrl->stream_clks_on) {2047		clk_disable_unprepare(ctrl->pixel_clk);2048		ctrl->stream_clks_on = false;2049	}2050 2051	dev_pm_opp_set_rate(ctrl->dev, 0);2052	dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);2053 2054	phy_power_off(phy);2055 2056	/* aux channel down, reinit phy */2057	phy_exit(phy);2058	phy_init(phy);2059 2060	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",2061			phy, phy->init_count, phy->power_count);2062}2063 2064void dp_ctrl_off_link(struct dp_ctrl *dp_ctrl)2065{2066	struct dp_ctrl_private *ctrl;2067	struct phy *phy;2068 2069	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);2070	phy = ctrl->phy;2071 2072	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);2073 2074	dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);2075 2076	DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",2077		phy, phy->init_count, phy->power_count);2078 2079	phy_power_off(phy);2080 2081	DRM_DEBUG_DP("After, phy=%p init_count=%d power_on=%d\n",2082		phy, phy->init_count, phy->power_count);2083}2084 2085void dp_ctrl_off(struct dp_ctrl *dp_ctrl)2086{2087	struct dp_ctrl_private *ctrl;2088	struct phy *phy;2089 2090	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);2091	phy = ctrl->phy;2092 2093	dp_catalog_panel_disable_vsc_sdp(ctrl->catalog);2094 2095	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);2096 2097	dp_catalog_ctrl_reset(ctrl->catalog);2098 2099	if (ctrl->stream_clks_on) {2100		clk_disable_unprepare(ctrl->pixel_clk);2101		ctrl->stream_clks_on = false;2102	}2103 2104	dev_pm_opp_set_rate(ctrl->dev, 0);2105	dp_ctrl_link_clk_disable(&ctrl->dp_ctrl);2106 2107	phy_power_off(phy);2108	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",2109			phy, phy->init_count, phy->power_count);2110}2111 2112irqreturn_t dp_ctrl_isr(struct dp_ctrl *dp_ctrl)2113{2114	struct dp_ctrl_private *ctrl;2115	u32 isr;2116	irqreturn_t ret = IRQ_NONE;2117 2118	if (!dp_ctrl)2119		return IRQ_NONE;2120 2121	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);2122 2123	if (ctrl->panel->psr_cap.version) {2124		isr = dp_catalog_ctrl_read_psr_interrupt_status(ctrl->catalog);2125 2126		if (isr)2127			complete(&ctrl->psr_op_comp);2128 2129		if (isr & PSR_EXIT_INT)2130			drm_dbg_dp(ctrl->drm_dev, "PSR exit done\n");2131 2132		if (isr & PSR_UPDATE_INT)2133			drm_dbg_dp(ctrl->drm_dev, "PSR frame update done\n");2134 2135		if (isr & PSR_CAPTURE_INT)2136			drm_dbg_dp(ctrl->drm_dev, "PSR frame capture done\n");2137	}2138 2139	isr = dp_catalog_ctrl_get_interrupt(ctrl->catalog);2140 2141 2142	if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) {2143		drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n");2144		complete(&ctrl->video_comp);2145		ret = IRQ_HANDLED;2146	}2147 2148	if (isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) {2149		drm_dbg_dp(ctrl->drm_dev, "idle_patterns_sent\n");2150		complete(&ctrl->idle_comp);2151		ret = IRQ_HANDLED;2152	}2153 2154	return ret;2155}2156 2157static const char *core_clks[] = {2158	"core_iface",2159	"core_aux",2160};2161 2162static const char *ctrl_clks[] = {2163	"ctrl_link",2164	"ctrl_link_iface",2165};2166 2167static int dp_ctrl_clk_init(struct dp_ctrl *dp_ctrl)2168{2169	struct dp_ctrl_private *ctrl;2170	struct device *dev;2171	int i, rc;2172 2173	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);2174	dev = ctrl->dev;2175 2176	ctrl->num_core_clks = ARRAY_SIZE(core_clks);2177	ctrl->core_clks = devm_kcalloc(dev, ctrl->num_core_clks, sizeof(*ctrl->core_clks), GFP_KERNEL);2178	if (!ctrl->core_clks)2179		return -ENOMEM;2180 2181	for (i = 0; i < ctrl->num_core_clks; i++)2182		ctrl->core_clks[i].id = core_clks[i];2183 2184	rc = devm_clk_bulk_get(dev, ctrl->num_core_clks, ctrl->core_clks);2185	if (rc)2186		return rc;2187 2188	ctrl->num_link_clks = ARRAY_SIZE(ctrl_clks);2189	ctrl->link_clks = devm_kcalloc(dev, ctrl->num_link_clks, sizeof(*ctrl->link_clks), GFP_KERNEL);2190	if (!ctrl->link_clks)2191		return -ENOMEM;2192 2193	for (i = 0; i < ctrl->num_link_clks; i++)2194		ctrl->link_clks[i].id = ctrl_clks[i];2195 2196	rc = devm_clk_bulk_get(dev, ctrl->num_link_clks, ctrl->link_clks);2197	if (rc)2198		return rc;2199 2200	ctrl->pixel_clk = devm_clk_get(dev, "stream_pixel");2201	if (IS_ERR(ctrl->pixel_clk))2202		return PTR_ERR(ctrl->pixel_clk);2203 2204	return 0;2205}2206 2207struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link,2208			struct dp_panel *panel,	struct drm_dp_aux *aux,2209			struct dp_catalog *catalog,2210			struct phy *phy)2211{2212	struct dp_ctrl_private *ctrl;2213	int ret;2214 2215	if (!dev || !panel || !aux ||2216	    !link || !catalog) {2217		DRM_ERROR("invalid input\n");2218		return ERR_PTR(-EINVAL);2219	}2220 2221	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);2222	if (!ctrl) {2223		DRM_ERROR("Mem allocation failure\n");2224		return ERR_PTR(-ENOMEM);2225	}2226 2227	ret = devm_pm_opp_set_clkname(dev, "ctrl_link");2228	if (ret) {2229		dev_err(dev, "invalid DP OPP table in device tree\n");2230		/* caller do PTR_ERR(opp_table) */2231		return (struct dp_ctrl *)ERR_PTR(ret);2232	}2233 2234	/* OPP table is optional */2235	ret = devm_pm_opp_of_add_table(dev);2236	if (ret)2237		dev_err(dev, "failed to add DP OPP table\n");2238 2239	init_completion(&ctrl->idle_comp);2240	init_completion(&ctrl->psr_op_comp);2241	init_completion(&ctrl->video_comp);2242 2243	/* in parameters */2244	ctrl->panel    = panel;2245	ctrl->aux      = aux;2246	ctrl->link     = link;2247	ctrl->catalog  = catalog;2248	ctrl->dev      = dev;2249	ctrl->phy      = phy;2250 2251	ret = dp_ctrl_clk_init(&ctrl->dp_ctrl);2252	if (ret) {2253		dev_err(dev, "failed to init clocks\n");2254		return ERR_PTR(ret);2255	}2256 2257	return &ctrl->dp_ctrl;2258}2259