File Index
Files and directories
Sign in
FILE

dp_ctrl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/dp/dp_ctrl.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   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/clk.h>
  10#include <linux/completion.h>
  11#include <linux/delay.h>
  12#include <linux/iopoll.h>
  13#include <linux/phy/phy.h>
  14#include <linux/phy/phy-dp.h>
  15#include <linux/pm_opp.h>
  16#include <linux/rational.h>
  17#include <linux/string_choices.h>
  18
  19#include <drm/display/drm_dp_helper.h>
  20#include <drm/drm_device.h>
  21#include <drm/drm_fixed.h>
  22#include <drm/drm_print.h>
  23
  24#include "dp_reg.h"
  25#include "dp_ctrl.h"
  26#include "dp_link.h"
  27
  28#define POLLING_SLEEP_US			1000
  29#define POLLING_TIMEOUT_US			10000
  30
  31#define DP_KHZ_TO_HZ 1000
  32#define IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES	(30 * HZ / 1000) /* 30 ms */
  33#define PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES       (300 * HZ / 1000) /* 300 ms */
  34#define WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES (HZ / 2)
  35
  36#define DP_INTERRUPT_STATUS_ACK_SHIFT	1
  37#define DP_INTERRUPT_STATUS_MASK_SHIFT	2
  38
  39#define DP_INTERRUPT_STATUS1 \
  40	(DP_INTR_AUX_XFER_DONE| \
  41	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
  42	DP_INTR_NACK_DEFER | DP_INTR_WRONG_DATA_CNT | \
  43	DP_INTR_I2C_NACK | DP_INTR_I2C_DEFER | \
  44	DP_INTR_PLL_UNLOCKED | DP_INTR_AUX_ERROR)
  45
  46#define DP_INTERRUPT_STATUS1_ACK \
  47	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_ACK_SHIFT)
  48#define DP_INTERRUPT_STATUS1_MASK \
  49	(DP_INTERRUPT_STATUS1 << DP_INTERRUPT_STATUS_MASK_SHIFT)
  50
  51#define DP_INTERRUPT_STATUS2 \
  52	(DP_INTR_READY_FOR_VIDEO | DP_INTR_IDLE_PATTERN_SENT | \
  53	DP_INTR_FRAME_END | DP_INTR_CRC_UPDATED)
  54
  55#define DP_INTERRUPT_STATUS2_ACK \
  56	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_ACK_SHIFT)
  57#define DP_INTERRUPT_STATUS2_MASK \
  58	(DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT)
  59
  60#define DP_INTERRUPT_STATUS4 \
  61	(PSR_UPDATE_INT | PSR_CAPTURE_INT | PSR_EXIT_INT | \
  62	PSR_UPDATE_ERROR_INT | PSR_WAKE_ERROR_INT)
  63
  64#define DP_INTERRUPT_MASK4 \
  65	(PSR_UPDATE_MASK | PSR_CAPTURE_MASK | PSR_EXIT_MASK | \
  66	PSR_UPDATE_ERROR_MASK | PSR_WAKE_ERROR_MASK)
  67
  68#define DP_CTRL_INTR_READY_FOR_VIDEO     BIT(0)
  69#define DP_CTRL_INTR_IDLE_PATTERN_SENT  BIT(3)
  70
  71#define MR_LINK_TRAINING1  0x8
  72#define MR_LINK_SYMBOL_ERM 0x80
  73#define MR_LINK_PRBS7 0x100
  74#define MR_LINK_CUSTOM80 0x200
  75#define MR_LINK_TRAINING4  0x40
  76
  77enum {
  78	DP_TRAINING_NONE,
  79	DP_TRAINING_1,
  80	DP_TRAINING_2,
  81};
  82
  83struct msm_dp_tu_calc_input {
  84	u64 lclk;        /* 162, 270, 540 and 810 */
  85	u64 pclk_khz;    /* in KHz */
  86	u64 hactive;     /* active h-width */
  87	u64 hporch;      /* bp + fp + pulse */
  88	int nlanes;      /* no.of.lanes */
  89	int bpp;         /* bits */
  90	int pixel_enc;   /* 444, 420, 422 */
  91	int dsc_en;     /* dsc on/off */
  92	int async_en;   /* async mode */
  93	int fec_en;     /* fec */
  94	int compress_ratio; /* 2:1 = 200, 3:1 = 300, 3.75:1 = 375 */
  95	int num_of_dsc_slices; /* number of slices per line */
  96};
  97
  98struct msm_dp_vc_tu_mapping_table {
  99	u32 vic;
 100	u8 lanes;
 101	u8 lrate; /* DP_LINK_RATE -> 162(6), 270(10), 540(20), 810 (30) */
 102	u8 bpp;
 103	u8 valid_boundary_link;
 104	u16 delay_start_link;
 105	bool boundary_moderation_en;
 106	u8 valid_lower_boundary_link;
 107	u8 upper_boundary_count;
 108	u8 lower_boundary_count;
 109	u8 tu_size_minus1;
 110};
 111
 112struct msm_dp_ctrl_private {
 113	struct msm_dp_ctrl msm_dp_ctrl;
 114	struct drm_device *drm_dev;
 115	struct device *dev;
 116	struct drm_dp_aux *aux;
 117	struct msm_dp_panel *panel;
 118	struct msm_dp_link *link;
 119	void __iomem *ahb_base;
 120	void __iomem *link_base;
 121
 122	struct phy *phy;
 123
 124	unsigned int num_core_clks;
 125	struct clk_bulk_data *core_clks;
 126
 127	unsigned int num_link_clks;
 128	struct clk_bulk_data *link_clks;
 129
 130	struct clk *pixel_clk;
 131
 132	union phy_configure_opts phy_opts;
 133
 134	struct completion idle_comp;
 135	struct completion psr_op_comp;
 136	struct completion video_comp;
 137
 138	u32 hw_revision;
 139
 140	bool core_clks_on;
 141	bool link_clks_on;
 142	bool stream_clks_on;
 143};
 144
 145static inline u32 msm_dp_read_ahb(const struct msm_dp_ctrl_private *ctrl, u32 offset)
 146{
 147	return readl_relaxed(ctrl->ahb_base + offset);
 148}
 149
 150static inline void msm_dp_write_ahb(struct msm_dp_ctrl_private *ctrl,
 151			       u32 offset, u32 data)
 152{
 153	/*
 154	 * To make sure phy reg writes happens before any other operation,
 155	 * this function uses writel() instread of writel_relaxed()
 156	 */
 157	writel(data, ctrl->ahb_base + offset);
 158}
 159
 160static inline u32 msm_dp_read_link(struct msm_dp_ctrl_private *ctrl, u32 offset)
 161{
 162	return readl_relaxed(ctrl->link_base + offset);
 163}
 164
 165static inline void msm_dp_write_link(struct msm_dp_ctrl_private *ctrl,
 166			       u32 offset, u32 data)
 167{
 168	/*
 169	 * To make sure link reg writes happens before any other operation,
 170	 * this function uses writel() instread of writel_relaxed()
 171	 */
 172	writel(data, ctrl->link_base + offset);
 173}
 174
 175static int msm_dp_aux_link_configure(struct drm_dp_aux *aux,
 176					struct msm_dp_link_info *link)
 177{
 178	u8 values[2];
 179	int err;
 180
 181	values[0] = drm_dp_link_rate_to_bw_code(link->rate);
 182	values[1] = link->num_lanes;
 183
 184	if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
 185		values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 186
 187	err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
 188	if (err < 0)
 189		return err;
 190
 191	return 0;
 192}
 193
 194/*
 195 * NOTE: resetting DP controller will also clear any pending HPD related interrupts
 196 */
 197void msm_dp_ctrl_reset(struct msm_dp_ctrl *msm_dp_ctrl)
 198{
 199	struct msm_dp_ctrl_private *ctrl =
 200		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
 201	u32 sw_reset;
 202
 203	sw_reset = msm_dp_read_ahb(ctrl, REG_DP_SW_RESET);
 204
 205	sw_reset |= DP_SW_RESET;
 206	msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset);
 207	usleep_range(1000, 1100); /* h/w recommended delay */
 208
 209	sw_reset &= ~DP_SW_RESET;
 210	msm_dp_write_ahb(ctrl, REG_DP_SW_RESET, sw_reset);
 211
 212	if (!ctrl->hw_revision) {
 213		ctrl->hw_revision = msm_dp_read_ahb(ctrl, REG_DP_HW_VERSION);
 214		ctrl->panel->hw_revision = ctrl->hw_revision;
 215	}
 216}
 217
 218static u32 msm_dp_ctrl_get_aux_interrupt(struct msm_dp_ctrl_private *ctrl)
 219{
 220	u32 intr, intr_ack;
 221
 222	intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS);
 223	intr &= ~DP_INTERRUPT_STATUS1_MASK;
 224	intr_ack = (intr & DP_INTERRUPT_STATUS1)
 225			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
 226	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS,
 227		     intr_ack | DP_INTERRUPT_STATUS1_MASK);
 228
 229	return intr;
 230
 231}
 232
 233static u32 msm_dp_ctrl_get_interrupt(struct msm_dp_ctrl_private *ctrl)
 234{
 235	u32 intr, intr_ack;
 236
 237	intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS2);
 238	intr &= ~DP_INTERRUPT_STATUS2_MASK;
 239	intr_ack = (intr & DP_INTERRUPT_STATUS2)
 240			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
 241	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2,
 242		     intr_ack | DP_INTERRUPT_STATUS2_MASK);
 243
 244	return intr;
 245}
 246
 247void msm_dp_ctrl_enable_irq(struct msm_dp_ctrl *msm_dp_ctrl)
 248{
 249	struct msm_dp_ctrl_private *ctrl =
 250		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
 251
 252	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS,
 253			DP_INTERRUPT_STATUS1_MASK);
 254	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2,
 255			DP_INTERRUPT_STATUS2_MASK);
 256}
 257
 258void msm_dp_ctrl_disable_irq(struct msm_dp_ctrl *msm_dp_ctrl)
 259{
 260	struct msm_dp_ctrl_private *ctrl =
 261		container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
 262
 263	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS, 0x00);
 264	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS2, 0x00);
 265}
 266
 267static u32 msm_dp_ctrl_get_psr_interrupt(struct msm_dp_ctrl_private *ctrl)
 268{
 269	u32 intr, intr_ack;
 270
 271	intr = msm_dp_read_ahb(ctrl, REG_DP_INTR_STATUS4);
 272	intr_ack = (intr & DP_INTERRUPT_STATUS4)
 273			<< DP_INTERRUPT_STATUS_ACK_SHIFT;
 274	msm_dp_write_ahb(ctrl, REG_DP_INTR_STATUS4, intr_ack);
 275
 276	return intr;
 277}
 278
 279static void msm_dp_ctrl_config_psr_interrupt(struct msm_dp_ctrl_private *ctrl)
 280{
 281	msm_dp_write_ahb(ctrl, REG_DP_INTR_MASK4, DP_INTERRUPT_MASK4);
 282}
 283
 284static void msm_dp_ctrl_psr_mainlink_enable(struct msm_dp_ctrl_private *ctrl)
 285{
 286	u32 val;
 287
 288	val = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
 289	val |= DP_MAINLINK_CTRL_ENABLE;
 290	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, val);
 291}
 292
 293static void msm_dp_ctrl_psr_mainlink_disable(struct msm_dp_ctrl_private *ctrl)
 294{
 295	u32 val;
 296
 297	val = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
 298	val &= ~DP_MAINLINK_CTRL_ENABLE;
 299	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, val);
 300}
 301
 302static void msm_dp_ctrl_mainlink_enable(struct msm_dp_ctrl_private *ctrl)
 303{
 304	u32 mainlink_ctrl;
 305
 306	drm_dbg_dp(ctrl->drm_dev, "enable\n");
 307
 308	mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
 309
 310	mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET |
 311					DP_MAINLINK_CTRL_ENABLE);
 312	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 313
 314	mainlink_ctrl |= DP_MAINLINK_CTRL_RESET;
 315	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 316
 317	mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET;
 318	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 319
 320	mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE |
 321				DP_MAINLINK_FB_BOUNDARY_SEL);
 322	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 323}
 324
 325static void msm_dp_ctrl_mainlink_disable(struct msm_dp_ctrl_private *ctrl)
 326{
 327	u32 mainlink_ctrl;
 328
 329	drm_dbg_dp(ctrl->drm_dev, "disable\n");
 330
 331	mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
 332	mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE;
 333	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 334}
 335
 336static void msm_dp_setup_peripheral_flush(struct msm_dp_ctrl_private *ctrl)
 337{
 338	u32 mainlink_ctrl;
 339
 340	mainlink_ctrl = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
 341
 342	if (ctrl->hw_revision >= DP_HW_VERSION_1_2)
 343		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
 344	else
 345		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
 346
 347	msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
 348}
 349
 350static bool msm_dp_ctrl_mainlink_ready(struct msm_dp_ctrl_private *ctrl)
 351{
 352	u32 data;
 353	int ret;
 354
 355	/* Poll for mainlink ready status */
 356	ret = readl_poll_timeout(ctrl->link_base + REG_DP_MAINLINK_READY,
 357				data, data & DP_MAINLINK_READY_FOR_VIDEO,
 358				POLLING_SLEEP_US, POLLING_TIMEOUT_US);
 359	if (ret < 0) {
 360		DRM_ERROR("mainlink not ready\n");
 361		return false;
 362	}
 363
 364	return true;
 365}
 366
 367void msm_dp_ctrl_push_idle(struct msm_dp_ctrl *msm_dp_ctrl)
 368{
 369	struct msm_dp_ctrl_private *ctrl;
 370
 371	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
 372
 373	reinit_completion(&ctrl->idle_comp);
 374	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_PUSH_IDLE);
 375
 376	if (!wait_for_completion_timeout(&ctrl->idle_comp,
 377			IDLE_PATTERN_COMPLETION_TIMEOUT_JIFFIES))
 378		pr_warn("PUSH_IDLE pattern timedout\n");
 379
 380	drm_dbg_dp(ctrl->drm_dev, "mainlink off\n");
 381}
 382
 383static void msm_dp_ctrl_config_ctrl(struct msm_dp_ctrl_private *ctrl)
 384{
 385	u32 config = 0, tbd;
 386	const u8 *dpcd = ctrl->panel->dpcd;
 387
 388	/* Default-> LSCLK DIV: 1/4 LCLK  */
 389	config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
 390
 391	if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
 392		config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
 393
 394	/* Scrambler reset enable */
 395	if (drm_dp_alternate_scrambler_reset_cap(dpcd))
 396		config |= DP_CONFIGURATION_CTRL_ASSR;
 397
 398	tbd = msm_dp_link_get_test_bits_depth(ctrl->link,
 399			ctrl->panel->msm_dp_mode.bpp);
 400
 401	config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT;
 402
 403	/* Num of Lanes */
 404	config |= ((ctrl->link->link_params.num_lanes - 1)
 405			<< DP_CONFIGURATION_CTRL_NUM_OF_LANES_SHIFT);
 406
 407	if (drm_dp_enhanced_frame_cap(dpcd))
 408		config |= DP_CONFIGURATION_CTRL_ENHANCED_FRAMING;
 409
 410	config |= DP_CONFIGURATION_CTRL_P_INTERLACED; /* progressive video */
 411
 412	/* sync clock & static Mvid */
 413	config |= DP_CONFIGURATION_CTRL_STATIC_DYNAMIC_CN;
 414	config |= DP_CONFIGURATION_CTRL_SYNC_ASYNC_CLK;
 415
 416	if (ctrl->panel->psr_cap.version)
 417		config |= DP_CONFIGURATION_CTRL_SEND_VSC;
 418
 419	drm_dbg_dp(ctrl->drm_dev, "DP_CONFIGURATION_CTRL=0x%x\n", config);
 420
 421	msm_dp_write_link(ctrl, REG_DP_CONFIGURATION_CTRL, config);
 422}
 423
 424static void msm_dp_ctrl_lane_mapping(struct msm_dp_ctrl_private *ctrl)
 425{
 426	u32 *lane_map = ctrl->link->lane_map;
 427	u32 ln_mapping;
 428
 429	ln_mapping = lane_map[0] << LANE0_MAPPING_SHIFT;
 430	ln_mapping |= lane_map[1] << LANE1_MAPPING_SHIFT;
 431	ln_mapping |= lane_map[2] << LANE2_MAPPING_SHIFT;
 432	ln_mapping |= lane_map[3] << LANE3_MAPPING_SHIFT;
 433
 434	msm_dp_write_link(ctrl, REG_DP_LOGICAL2PHYSICAL_LANE_MAPPING,
 435			ln_mapping);
 436}
 437
 438static void msm_dp_ctrl_configure_source_params(struct msm_dp_ctrl_private *ctrl)
 439{
 440	u32 colorimetry_cfg, test_bits_depth, misc_val;
 441
 442	msm_dp_ctrl_lane_mapping(ctrl);
 443	msm_dp_setup_peripheral_flush(ctrl);
 444
 445	msm_dp_ctrl_config_ctrl(ctrl);
 446
 447	test_bits_depth = msm_dp_link_get_test_bits_depth(ctrl->link, ctrl->panel->msm_dp_mode.bpp);
 448	colorimetry_cfg = msm_dp_link_get_colorimetry_config(ctrl->link);
 449
 450	misc_val = msm_dp_read_link(ctrl, REG_DP_MISC1_MISC0);
 451
 452	/* clear bpp bits */
 453	misc_val &= ~(0x07 << DP_MISC0_TEST_BITS_DEPTH_SHIFT);
 454	misc_val |= colorimetry_cfg << DP_MISC0_COLORIMETRY_CFG_SHIFT;
 455	misc_val |= test_bits_depth << DP_MISC0_TEST_BITS_DEPTH_SHIFT;
 456	/* Configure clock to synchronous mode */
 457	misc_val |= DP_MISC0_SYNCHRONOUS_CLK;
 458
 459	drm_dbg_dp(ctrl->drm_dev, "misc settings = 0x%x\n", misc_val);
 460	msm_dp_write_link(ctrl, REG_DP_MISC1_MISC0, misc_val);
 461
 462	msm_dp_panel_timing_cfg(ctrl->panel, ctrl->msm_dp_ctrl.wide_bus_en);
 463}
 464
 465/*
 466 * The structure and few functions present below are IP/Hardware
 467 * specific implementation. Most of the implementation will not
 468 * have coding comments
 469 */
 470struct tu_algo_data {
 471	s64 lclk_fp;
 472	s64 pclk_fp;
 473	s64 lwidth;
 474	s64 lwidth_fp;
 475	s64 hbp_relative_to_pclk;
 476	s64 hbp_relative_to_pclk_fp;
 477	int nlanes;
 478	int bpp;
 479	int pixelEnc;
 480	int dsc_en;
 481	int async_en;
 482	int bpc;
 483
 484	uint delay_start_link_extra_pixclk;
 485	int extra_buffer_margin;
 486	s64 ratio_fp;
 487	s64 original_ratio_fp;
 488
 489	s64 err_fp;
 490	s64 n_err_fp;
 491	s64 n_n_err_fp;
 492	int tu_size;
 493	int tu_size_desired;
 494	int tu_size_minus1;
 495
 496	int valid_boundary_link;
 497	s64 resulting_valid_fp;
 498	s64 total_valid_fp;
 499	s64 effective_valid_fp;
 500	s64 effective_valid_recorded_fp;
 501	int n_tus;
 502	int n_tus_per_lane;
 503	int paired_tus;
 504	int remainder_tus;
 505	int remainder_tus_upper;
 506	int remainder_tus_lower;
 507	int extra_bytes;
 508	int filler_size;
 509	int delay_start_link;
 510
 511	int extra_pclk_cycles;
 512	int extra_pclk_cycles_in_link_clk;
 513	s64 ratio_by_tu_fp;
 514	s64 average_valid2_fp;
 515	int new_valid_boundary_link;
 516	int remainder_symbols_exist;
 517	int n_symbols;
 518	s64 n_remainder_symbols_per_lane_fp;
 519	s64 last_partial_tu_fp;
 520	s64 TU_ratio_err_fp;
 521
 522	int n_tus_incl_last_incomplete_tu;
 523	int extra_pclk_cycles_tmp;
 524	int extra_pclk_cycles_in_link_clk_tmp;
 525	int extra_required_bytes_new_tmp;
 526	int filler_size_tmp;
 527	int lower_filler_size_tmp;
 528	int delay_start_link_tmp;
 529
 530	bool boundary_moderation_en;
 531	int boundary_mod_lower_err;
 532	int upper_boundary_count;
 533	int lower_boundary_count;
 534	int i_upper_boundary_count;
 535	int i_lower_boundary_count;
 536	int valid_lower_boundary_link;
 537	int even_distribution_BF;
 538	int even_distribution_legacy;
 539	int even_distribution;
 540	int min_hblank_violated;
 541	s64 delay_start_time_fp;
 542	s64 hbp_time_fp;
 543	s64 hactive_time_fp;
 544	s64 diff_abs_fp;
 545
 546	s64 ratio;
 547};
 548
 549static int _tu_param_compare(s64 a, s64 b)
 550{
 551	u32 a_sign;
 552	u32 b_sign;
 553	s64 a_temp, b_temp, minus_1;
 554
 555	if (a == b)
 556		return 0;
 557
 558	minus_1 = drm_fixp_from_fraction(-1, 1);
 559
 560	a_sign = (a >> 32) & 0x80000000 ? 1 : 0;
 561
 562	b_sign = (b >> 32) & 0x80000000 ? 1 : 0;
 563
 564	if (a_sign > b_sign)
 565		return 2;
 566	else if (b_sign > a_sign)
 567		return 1;
 568
 569	if (!a_sign && !b_sign) { /* positive */
 570		if (a > b)
 571			return 1;
 572		else
 573			return 2;
 574	} else { /* negative */
 575		a_temp = drm_fixp_mul(a, minus_1);
 576		b_temp = drm_fixp_mul(b, minus_1);
 577
 578		if (a_temp > b_temp)
 579			return 2;
 580		else
 581			return 1;
 582	}
 583}
 584
 585static void msm_dp_panel_update_tu_timings(struct msm_dp_tu_calc_input *in,
 586					struct tu_algo_data *tu)
 587{
 588	int nlanes = in->nlanes;
 589	int dsc_num_slices = in->num_of_dsc_slices;
 590	int dsc_num_bytes  = 0;
 591	int numerator;
 592	s64 pclk_dsc_fp;
 593	s64 dwidth_dsc_fp;
 594	s64 hbp_dsc_fp;
 595
 596	int tot_num_eoc_symbols = 0;
 597	int tot_num_hor_bytes   = 0;
 598	int tot_num_dummy_bytes = 0;
 599	int dwidth_dsc_bytes    = 0;
 600	int  eoc_bytes           = 0;
 601
 602	s64 temp1_fp, temp2_fp, temp3_fp;
 603
 604	tu->lclk_fp              = drm_fixp_from_fraction(in->lclk, 1);
 605	tu->pclk_fp              = drm_fixp_from_fraction(in->pclk_khz, 1000);
 606	tu->lwidth               = in->hactive;
 607	tu->hbp_relative_to_pclk = in->hporch;
 608	tu->nlanes               = in->nlanes;
 609	tu->bpp                  = in->bpp;
 610	tu->pixelEnc             = in->pixel_enc;
 611	tu->dsc_en               = in->dsc_en;
 612	tu->async_en             = in->async_en;
 613	tu->lwidth_fp            = drm_fixp_from_fraction(in->hactive, 1);
 614	tu->hbp_relative_to_pclk_fp = drm_fixp_from_fraction(in->hporch, 1);
 615
 616	if (tu->pixelEnc == 420) {
 617		temp1_fp = drm_fixp_from_fraction(2, 1);
 618		tu->pclk_fp = drm_fixp_div(tu->pclk_fp, temp1_fp);
 619		tu->lwidth_fp = drm_fixp_div(tu->lwidth_fp, temp1_fp);
 620		tu->hbp_relative_to_pclk_fp =
 621				drm_fixp_div(tu->hbp_relative_to_pclk_fp, 2);
 622	}
 623
 624	if (tu->pixelEnc == 422) {
 625		switch (tu->bpp) {
 626		case 24:
 627			tu->bpp = 16;
 628			tu->bpc = 8;
 629			break;
 630		case 30:
 631			tu->bpp = 20;
 632			tu->bpc = 10;
 633			break;
 634		default:
 635			tu->bpp = 16;
 636			tu->bpc = 8;
 637			break;
 638		}
 639	} else {
 640		tu->bpc = tu->bpp/3;
 641	}
 642
 643	if (!in->dsc_en)
 644		goto fec_check;
 645
 646	temp1_fp = drm_fixp_from_fraction(in->compress_ratio, 100);
 647	temp2_fp = drm_fixp_from_fraction(in->bpp, 1);
 648	temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
 649	temp2_fp = drm_fixp_mul(tu->lwidth_fp, temp3_fp);
 650
 651	temp1_fp = drm_fixp_from_fraction(8, 1);
 652	temp3_fp = drm_fixp_div(temp2_fp, temp1_fp);
 653
 654	numerator = drm_fixp2int(temp3_fp);
 655
 656	dsc_num_bytes  = numerator / dsc_num_slices;
 657	eoc_bytes           = dsc_num_bytes % nlanes;
 658	tot_num_eoc_symbols = nlanes * dsc_num_slices;
 659	tot_num_hor_bytes   = dsc_num_bytes * dsc_num_slices;
 660	tot_num_dummy_bytes = (nlanes - eoc_bytes) * dsc_num_slices;
 661
 662	if (dsc_num_bytes == 0)
 663		pr_info("incorrect no of bytes per slice=%d\n", dsc_num_bytes);
 664
 665	dwidth_dsc_bytes = (tot_num_hor_bytes +
 666				tot_num_eoc_symbols +
 667				(eoc_bytes == 0 ? 0 : tot_num_dummy_bytes));
 668
 669	dwidth_dsc_fp = drm_fixp_from_fraction(dwidth_dsc_bytes, 3);
 670
 671	temp2_fp = drm_fixp_mul(tu->pclk_fp, dwidth_dsc_fp);
 672	temp1_fp = drm_fixp_div(temp2_fp, tu->lwidth_fp);
 673	pclk_dsc_fp = temp1_fp;
 674
 675	temp1_fp = drm_fixp_div(pclk_dsc_fp, tu->pclk_fp);
 676	temp2_fp = drm_fixp_mul(tu->hbp_relative_to_pclk_fp, temp1_fp);
 677	hbp_dsc_fp = temp2_fp;
 678
 679	/* output */
 680	tu->pclk_fp = pclk_dsc_fp;
 681	tu->lwidth_fp = dwidth_dsc_fp;
 682	tu->hbp_relative_to_pclk_fp = hbp_dsc_fp;
 683
 684fec_check:
 685	if (in->fec_en) {
 686		temp1_fp = drm_fixp_from_fraction(976, 1000); /* 0.976 */
 687		tu->lclk_fp = drm_fixp_mul(tu->lclk_fp, temp1_fp);
 688	}
 689}
 690
 691static void _tu_valid_boundary_calc(struct tu_algo_data *tu)
 692{
 693	s64 temp1_fp, temp2_fp, temp, temp1, temp2;
 694	int compare_result_1, compare_result_2, compare_result_3;
 695
 696	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 697	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 698
 699	tu->new_valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
 700
 701	temp = (tu->i_upper_boundary_count *
 702				tu->new_valid_boundary_link +
 703				tu->i_lower_boundary_count *
 704				(tu->new_valid_boundary_link-1));
 705	tu->average_valid2_fp = drm_fixp_from_fraction(temp,
 706					(tu->i_upper_boundary_count +
 707					tu->i_lower_boundary_count));
 708
 709	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
 710	temp2_fp = tu->lwidth_fp;
 711	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 712	temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
 713	tu->n_tus = drm_fixp2int(temp2_fp);
 714	if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
 715		tu->n_tus += 1;
 716
 717	temp1_fp = drm_fixp_from_fraction(tu->n_tus, 1);
 718	temp2_fp = drm_fixp_mul(temp1_fp, tu->average_valid2_fp);
 719	temp1_fp = drm_fixp_from_fraction(tu->n_symbols, 1);
 720	temp2_fp = temp1_fp - temp2_fp;
 721	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
 722	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
 723	tu->n_remainder_symbols_per_lane_fp = temp2_fp;
 724
 725	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 726	tu->last_partial_tu_fp =
 727			drm_fixp_div(tu->n_remainder_symbols_per_lane_fp,
 728					temp1_fp);
 729
 730	if (tu->n_remainder_symbols_per_lane_fp != 0)
 731		tu->remainder_symbols_exist = 1;
 732	else
 733		tu->remainder_symbols_exist = 0;
 734
 735	temp1_fp = drm_fixp_from_fraction(tu->n_tus, tu->nlanes);
 736	tu->n_tus_per_lane = drm_fixp2int(temp1_fp);
 737
 738	tu->paired_tus = (int)((tu->n_tus_per_lane) /
 739					(tu->i_upper_boundary_count +
 740					 tu->i_lower_boundary_count));
 741
 742	tu->remainder_tus = tu->n_tus_per_lane - tu->paired_tus *
 743						(tu->i_upper_boundary_count +
 744						tu->i_lower_boundary_count);
 745
 746	if ((tu->remainder_tus - tu->i_upper_boundary_count) > 0) {
 747		tu->remainder_tus_upper = tu->i_upper_boundary_count;
 748		tu->remainder_tus_lower = tu->remainder_tus -
 749						tu->i_upper_boundary_count;
 750	} else {
 751		tu->remainder_tus_upper = tu->remainder_tus;
 752		tu->remainder_tus_lower = 0;
 753	}
 754
 755	temp = tu->paired_tus * (tu->i_upper_boundary_count *
 756				tu->new_valid_boundary_link +
 757				tu->i_lower_boundary_count *
 758				(tu->new_valid_boundary_link - 1)) +
 759				(tu->remainder_tus_upper *
 760				 tu->new_valid_boundary_link) +
 761				(tu->remainder_tus_lower *
 762				(tu->new_valid_boundary_link - 1));
 763	tu->total_valid_fp = drm_fixp_from_fraction(temp, 1);
 764
 765	if (tu->remainder_symbols_exist) {
 766		temp1_fp = tu->total_valid_fp +
 767				tu->n_remainder_symbols_per_lane_fp;
 768		temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
 769		temp2_fp = temp2_fp + tu->last_partial_tu_fp;
 770		temp1_fp = drm_fixp_div(temp1_fp, temp2_fp);
 771	} else {
 772		temp2_fp = drm_fixp_from_fraction(tu->n_tus_per_lane, 1);
 773		temp1_fp = drm_fixp_div(tu->total_valid_fp, temp2_fp);
 774	}
 775	tu->effective_valid_fp = temp1_fp;
 776
 777	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 778	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 779	tu->n_n_err_fp = tu->effective_valid_fp - temp2_fp;
 780
 781	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 782	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 783	tu->n_err_fp = tu->average_valid2_fp - temp2_fp;
 784
 785	tu->even_distribution = tu->n_tus % tu->nlanes == 0 ? 1 : 0;
 786
 787	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
 788	temp2_fp = tu->lwidth_fp;
 789	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 790	temp2_fp = drm_fixp_div(temp1_fp, tu->average_valid2_fp);
 791
 792	if (temp2_fp)
 793		tu->n_tus_incl_last_incomplete_tu = drm_fixp2int_ceil(temp2_fp);
 794	else
 795		tu->n_tus_incl_last_incomplete_tu = 0;
 796
 797	temp1 = 0;
 798	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 799	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
 800	temp1_fp = tu->average_valid2_fp - temp2_fp;
 801	temp2_fp = drm_fixp_from_fraction(tu->n_tus_incl_last_incomplete_tu, 1);
 802	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 803
 804	if (temp1_fp)
 805		temp1 = drm_fixp2int_ceil(temp1_fp);
 806
 807	temp = tu->i_upper_boundary_count * tu->nlanes;
 808	temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 809	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
 810	temp1_fp = drm_fixp_from_fraction(tu->new_valid_boundary_link, 1);
 811	temp2_fp = temp1_fp - temp2_fp;
 812	temp1_fp = drm_fixp_from_fraction(temp, 1);
 813	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 814
 815	if (temp2_fp)
 816		temp2 = drm_fixp2int_ceil(temp2_fp);
 817	else
 818		temp2 = 0;
 819	tu->extra_required_bytes_new_tmp = (int)(temp1 + temp2);
 820
 821	temp1_fp = drm_fixp_from_fraction(8, tu->bpp);
 822	temp2_fp = drm_fixp_from_fraction(
 823	tu->extra_required_bytes_new_tmp, 1);
 824	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
 825
 826	if (temp1_fp)
 827		tu->extra_pclk_cycles_tmp = drm_fixp2int_ceil(temp1_fp);
 828	else
 829		tu->extra_pclk_cycles_tmp = 0;
 830
 831	temp1_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles_tmp, 1);
 832	temp2_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
 833	temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
 834
 835	if (temp1_fp)
 836		tu->extra_pclk_cycles_in_link_clk_tmp =
 837						drm_fixp2int_ceil(temp1_fp);
 838	else
 839		tu->extra_pclk_cycles_in_link_clk_tmp = 0;
 840
 841	tu->filler_size_tmp = tu->tu_size - tu->new_valid_boundary_link;
 842
 843	tu->lower_filler_size_tmp = tu->filler_size_tmp + 1;
 844
 845	tu->delay_start_link_tmp = tu->extra_pclk_cycles_in_link_clk_tmp +
 846					tu->lower_filler_size_tmp +
 847					tu->extra_buffer_margin;
 848
 849	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link_tmp, 1);
 850	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);
 851
 852	compare_result_1 = _tu_param_compare(tu->n_n_err_fp, tu->diff_abs_fp);
 853	if (compare_result_1 == 2)
 854		compare_result_1 = 1;
 855	else
 856		compare_result_1 = 0;
 857
 858	compare_result_2 = _tu_param_compare(tu->n_n_err_fp, tu->err_fp);
 859	if (compare_result_2 == 2)
 860		compare_result_2 = 1;
 861	else
 862		compare_result_2 = 0;
 863
 864	compare_result_3 = _tu_param_compare(tu->hbp_time_fp,
 865					tu->delay_start_time_fp);
 866	if (compare_result_3 == 2)
 867		compare_result_3 = 0;
 868	else
 869		compare_result_3 = 1;
 870
 871	if (((tu->even_distribution == 1) ||
 872			((tu->even_distribution_BF == 0) &&
 873			(tu->even_distribution_legacy == 0))) &&
 874			tu->n_err_fp >= 0 && tu->n_n_err_fp >= 0 &&
 875			compare_result_2 &&
 876			(compare_result_1 || (tu->min_hblank_violated == 1)) &&
 877			(tu->new_valid_boundary_link - 1) > 0 &&
 878			compare_result_3 &&
 879			(tu->delay_start_link_tmp <= 1023)) {
 880		tu->upper_boundary_count = tu->i_upper_boundary_count;
 881		tu->lower_boundary_count = tu->i_lower_boundary_count;
 882		tu->err_fp = tu->n_n_err_fp;
 883		tu->boundary_moderation_en = true;
 884		tu->tu_size_desired = tu->tu_size;
 885		tu->valid_boundary_link = tu->new_valid_boundary_link;
 886		tu->effective_valid_recorded_fp = tu->effective_valid_fp;
 887		tu->even_distribution_BF = 1;
 888		tu->delay_start_link = tu->delay_start_link_tmp;
 889	} else if (tu->boundary_mod_lower_err == 0) {
 890		compare_result_1 = _tu_param_compare(tu->n_n_err_fp,
 891							tu->diff_abs_fp);
 892		if (compare_result_1 == 2)
 893			tu->boundary_mod_lower_err = 1;
 894	}
 895}
 896
 897static void _dp_ctrl_calc_tu(struct msm_dp_ctrl_private *ctrl,
 898				struct msm_dp_tu_calc_input *in,
 899				struct msm_dp_vc_tu_mapping_table *tu_table)
 900{
 901	struct tu_algo_data *tu;
 902	int compare_result_1, compare_result_2;
 903	u64 temp = 0;
 904	s64 temp_fp = 0, temp1_fp = 0, temp2_fp = 0;
 905
 906	s64 LCLK_FAST_SKEW_fp = drm_fixp_from_fraction(6, 10000); /* 0.0006 */
 907	s64 const_p49_fp = drm_fixp_from_fraction(49, 100); /* 0.49 */
 908	s64 const_p56_fp = drm_fixp_from_fraction(56, 100); /* 0.56 */
 909	s64 RATIO_SCALE_fp = drm_fixp_from_fraction(1001, 1000);
 910
 911	u8 DP_BRUTE_FORCE = 1;
 912	s64 BRUTE_FORCE_THRESHOLD_fp = drm_fixp_from_fraction(1, 10); /* 0.1 */
 913	uint EXTRA_PIXCLK_CYCLE_DELAY = 4;
 914	uint HBLANK_MARGIN = 4;
 915
 916	tu = kzalloc(sizeof(*tu), GFP_KERNEL);
 917	if (!tu)
 918		return;
 919
 920	msm_dp_panel_update_tu_timings(in, tu);
 921
 922	tu->err_fp = drm_fixp_from_fraction(1000, 1); /* 1000 */
 923
 924	temp1_fp = drm_fixp_from_fraction(4, 1);
 925	temp2_fp = drm_fixp_mul(temp1_fp, tu->lclk_fp);
 926	temp_fp = drm_fixp_div(temp2_fp, tu->pclk_fp);
 927	tu->extra_buffer_margin = drm_fixp2int_ceil(temp_fp);
 928
 929	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
 930	temp2_fp = drm_fixp_mul(tu->pclk_fp, temp1_fp);
 931	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
 932	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
 933	tu->ratio_fp = drm_fixp_div(temp2_fp, tu->lclk_fp);
 934
 935	tu->original_ratio_fp = tu->ratio_fp;
 936	tu->boundary_moderation_en = false;
 937	tu->upper_boundary_count = 0;
 938	tu->lower_boundary_count = 0;
 939	tu->i_upper_boundary_count = 0;
 940	tu->i_lower_boundary_count = 0;
 941	tu->valid_lower_boundary_link = 0;
 942	tu->even_distribution_BF = 0;
 943	tu->even_distribution_legacy = 0;
 944	tu->even_distribution = 0;
 945	tu->delay_start_time_fp = 0;
 946
 947	tu->err_fp = drm_fixp_from_fraction(1000, 1);
 948	tu->n_err_fp = 0;
 949	tu->n_n_err_fp = 0;
 950
 951	tu->ratio = drm_fixp2int(tu->ratio_fp);
 952	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
 953	div64_u64_rem(tu->lwidth_fp, temp1_fp, &temp2_fp);
 954	if (temp2_fp != 0 &&
 955			!tu->ratio && tu->dsc_en == 0) {
 956		tu->ratio_fp = drm_fixp_mul(tu->ratio_fp, RATIO_SCALE_fp);
 957		tu->ratio = drm_fixp2int(tu->ratio_fp);
 958		if (tu->ratio)
 959			tu->ratio_fp = drm_fixp_from_fraction(1, 1);
 960	}
 961
 962	if (tu->ratio > 1)
 963		tu->ratio = 1;
 964
 965	if (tu->ratio == 1)
 966		goto tu_size_calc;
 967
 968	compare_result_1 = _tu_param_compare(tu->ratio_fp, const_p49_fp);
 969	if (!compare_result_1 || compare_result_1 == 1)
 970		compare_result_1 = 1;
 971	else
 972		compare_result_1 = 0;
 973
 974	compare_result_2 = _tu_param_compare(tu->ratio_fp, const_p56_fp);
 975	if (!compare_result_2 || compare_result_2 == 2)
 976		compare_result_2 = 1;
 977	else
 978		compare_result_2 = 0;
 979
 980	if (tu->dsc_en && compare_result_1 && compare_result_2) {
 981		HBLANK_MARGIN += 4;
 982		drm_dbg_dp(ctrl->drm_dev,
 983			"increase HBLANK_MARGIN to %d\n", HBLANK_MARGIN);
 984	}
 985
 986tu_size_calc:
 987	for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) {
 988		temp1_fp = drm_fixp_from_fraction(tu->tu_size, 1);
 989		temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
 990		temp = drm_fixp2int_ceil(temp2_fp);
 991		temp1_fp = drm_fixp_from_fraction(temp, 1);
 992		tu->n_err_fp = temp1_fp - temp2_fp;
 993
 994		if (tu->n_err_fp < tu->err_fp) {
 995			tu->err_fp = tu->n_err_fp;
 996			tu->tu_size_desired = tu->tu_size;
 997		}
 998	}
 999
1000	tu->tu_size_minus1 = tu->tu_size_desired - 1;
1001
1002	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);
1003	temp2_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
1004	tu->valid_boundary_link = drm_fixp2int_ceil(temp2_fp);
1005
1006	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
1007	temp2_fp = tu->lwidth_fp;
1008	temp2_fp = drm_fixp_mul(temp2_fp, temp1_fp);
1009
1010	temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1);
1011	temp2_fp = drm_fixp_div(temp2_fp, temp1_fp);
1012	tu->n_tus = drm_fixp2int(temp2_fp);
1013	if ((temp2_fp & 0xFFFFFFFF) > 0xFFFFF000)
1014		tu->n_tus += 1;
1015
1016	tu->even_distribution_legacy = tu->n_tus % tu->nlanes == 0 ? 1 : 0;
1017
1018	drm_dbg_dp(ctrl->drm_dev,
1019			"n_sym = %d, num_of_tus = %d\n",
1020			tu->valid_boundary_link, tu->n_tus);
1021
1022	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);
1023	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
1024	temp1_fp = drm_fixp_from_fraction(tu->valid_boundary_link, 1);
1025	temp2_fp = temp1_fp - temp2_fp;
1026	temp1_fp = drm_fixp_from_fraction(tu->n_tus + 1, 1);
1027	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
1028
1029	temp = drm_fixp2int(temp2_fp);
1030	if (temp && temp2_fp)
1031		tu->extra_bytes = drm_fixp2int_ceil(temp2_fp);
1032	else
1033		tu->extra_bytes = 0;
1034
1035	temp1_fp = drm_fixp_from_fraction(tu->extra_bytes, 1);
1036	temp2_fp = drm_fixp_from_fraction(8, tu->bpp);
1037	temp1_fp = drm_fixp_mul(temp1_fp, temp2_fp);
1038
1039	if (temp && temp1_fp)
1040		tu->extra_pclk_cycles = drm_fixp2int_ceil(temp1_fp);
1041	else
1042		tu->extra_pclk_cycles = drm_fixp2int(temp1_fp);
1043
1044	temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
1045	temp2_fp = drm_fixp_from_fraction(tu->extra_pclk_cycles, 1);
1046	temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
1047
1048	if (temp1_fp)
1049		tu->extra_pclk_cycles_in_link_clk = drm_fixp2int_ceil(temp1_fp);
1050	else
1051		tu->extra_pclk_cycles_in_link_clk = drm_fixp2int(temp1_fp);
1052
1053	tu->filler_size = tu->tu_size_desired - tu->valid_boundary_link;
1054
1055	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);
1056	tu->ratio_by_tu_fp = drm_fixp_mul(tu->ratio_fp, temp1_fp);
1057
1058	tu->delay_start_link = tu->extra_pclk_cycles_in_link_clk +
1059				tu->filler_size + tu->extra_buffer_margin;
1060
1061	tu->resulting_valid_fp =
1062			drm_fixp_from_fraction(tu->valid_boundary_link, 1);
1063
1064	temp1_fp = drm_fixp_from_fraction(tu->tu_size_desired, 1);
1065	temp2_fp = drm_fixp_div(tu->resulting_valid_fp, temp1_fp);
1066	tu->TU_ratio_err_fp = temp2_fp - tu->original_ratio_fp;
1067
1068	temp1_fp = drm_fixp_from_fraction(HBLANK_MARGIN, 1);
1069	temp1_fp = tu->hbp_relative_to_pclk_fp - temp1_fp;
1070	tu->hbp_time_fp = drm_fixp_div(temp1_fp, tu->pclk_fp);
1071
1072	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link, 1);
1073	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);
1074
1075	compare_result_1 = _tu_param_compare(tu->hbp_time_fp,
1076					tu->delay_start_time_fp);
1077	if (compare_result_1 == 2) /* if (hbp_time_fp < delay_start_time_fp) */
1078		tu->min_hblank_violated = 1;
1079
1080	tu->hactive_time_fp = drm_fixp_div(tu->lwidth_fp, tu->pclk_fp);
1081
1082	compare_result_2 = _tu_param_compare(tu->hactive_time_fp,
1083						tu->delay_start_time_fp);
1084	if (compare_result_2 == 2)
1085		tu->min_hblank_violated = 1;
1086
1087	tu->delay_start_time_fp = 0;
1088
1089	/* brute force */
1090
1091	tu->delay_start_link_extra_pixclk = EXTRA_PIXCLK_CYCLE_DELAY;
1092	tu->diff_abs_fp = tu->resulting_valid_fp - tu->ratio_by_tu_fp;
1093
1094	temp = drm_fixp2int(tu->diff_abs_fp);
1095	if (!temp && tu->diff_abs_fp <= 0xffff)
1096		tu->diff_abs_fp = 0;
1097
1098	/* if(diff_abs < 0) diff_abs *= -1 */
1099	if (tu->diff_abs_fp < 0)
1100		tu->diff_abs_fp = drm_fixp_mul(tu->diff_abs_fp, -1);
1101
1102	tu->boundary_mod_lower_err = 0;
1103	if ((tu->diff_abs_fp != 0 &&
1104			((tu->diff_abs_fp > BRUTE_FORCE_THRESHOLD_fp) ||
1105			 (tu->even_distribution_legacy == 0) ||
1106			 (DP_BRUTE_FORCE == 1))) ||
1107			(tu->min_hblank_violated == 1)) {
1108		do {
1109			tu->err_fp = drm_fixp_from_fraction(1000, 1);
1110
1111			temp1_fp = drm_fixp_div(tu->lclk_fp, tu->pclk_fp);
1112			temp2_fp = drm_fixp_from_fraction(
1113					tu->delay_start_link_extra_pixclk, 1);
1114			temp1_fp = drm_fixp_mul(temp2_fp, temp1_fp);
1115
1116			if (temp1_fp)
1117				tu->extra_buffer_margin =
1118					drm_fixp2int_ceil(temp1_fp);
1119			else
1120				tu->extra_buffer_margin = 0;
1121
1122			temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
1123			temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp);
1124
1125			if (temp1_fp)
1126				tu->n_symbols = drm_fixp2int_ceil(temp1_fp);
1127			else
1128				tu->n_symbols = 0;
1129
1130			for (tu->tu_size = 32; tu->tu_size <= 64; tu->tu_size++) {
1131				for (tu->i_upper_boundary_count = 1;
1132					tu->i_upper_boundary_count <= 15;
1133					tu->i_upper_boundary_count++) {
1134					for (tu->i_lower_boundary_count = 1;
1135						tu->i_lower_boundary_count <= 15;
1136						tu->i_lower_boundary_count++) {
1137						_tu_valid_boundary_calc(tu);
1138					}
1139				}
1140			}
1141			tu->delay_start_link_extra_pixclk--;
1142		} while (tu->boundary_moderation_en != true &&
1143			tu->boundary_mod_lower_err == 1 &&
1144			tu->delay_start_link_extra_pixclk != 0);
1145
1146		if (tu->boundary_moderation_en == true) {
1147			temp1_fp = drm_fixp_from_fraction(
1148					(tu->upper_boundary_count *
1149					tu->valid_boundary_link +
1150					tu->lower_boundary_count *
1151					(tu->valid_boundary_link - 1)), 1);
1152			temp2_fp = drm_fixp_from_fraction(
1153					(tu->upper_boundary_count +
1154					tu->lower_boundary_count), 1);
1155			tu->resulting_valid_fp =
1156					drm_fixp_div(temp1_fp, temp2_fp);
1157
1158			temp1_fp = drm_fixp_from_fraction(
1159					tu->tu_size_desired, 1);
1160			tu->ratio_by_tu_fp =
1161				drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
1162
1163			tu->valid_lower_boundary_link =
1164				tu->valid_boundary_link - 1;
1165
1166			temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
1167			temp1_fp = drm_fixp_mul(tu->lwidth_fp, temp1_fp);
1168			temp2_fp = drm_fixp_div(temp1_fp,
1169						tu->resulting_valid_fp);
1170			tu->n_tus = drm_fixp2int(temp2_fp);
1171
1172			tu->tu_size_minus1 = tu->tu_size_desired - 1;
1173			tu->even_distribution_BF = 1;
1174
1175			temp1_fp =
1176				drm_fixp_from_fraction(tu->tu_size_desired, 1);
1177			temp2_fp =
1178				drm_fixp_div(tu->resulting_valid_fp, temp1_fp);
1179			tu->TU_ratio_err_fp = temp2_fp - tu->original_ratio_fp;
1180		}
1181	}
1182
1183	temp2_fp = drm_fixp_mul(LCLK_FAST_SKEW_fp, tu->lwidth_fp);
1184
1185	if (temp2_fp)
1186		temp = drm_fixp2int_ceil(temp2_fp);
1187	else
1188		temp = 0;
1189
1190	temp1_fp = drm_fixp_from_fraction(tu->nlanes, 1);
1191	temp2_fp = drm_fixp_mul(tu->original_ratio_fp, temp1_fp);
1192	temp1_fp = drm_fixp_from_fraction(tu->bpp, 8);
1193	temp2_fp = drm_fixp_div(temp1_fp, temp2_fp);
1194	temp1_fp = drm_fixp_from_fraction(temp, 1);
1195	temp2_fp = drm_fixp_mul(temp1_fp, temp2_fp);
1196	temp = drm_fixp2int(temp2_fp);
1197
1198	if (tu->async_en)
1199		tu->delay_start_link += (int)temp;
1200
1201	temp1_fp = drm_fixp_from_fraction(tu->delay_start_link, 1);
1202	tu->delay_start_time_fp = drm_fixp_div(temp1_fp, tu->lclk_fp);
1203
1204	/* OUTPUTS */
1205	tu_table->valid_boundary_link       = tu->valid_boundary_link;
1206	tu_table->delay_start_link          = tu->delay_start_link;
1207	tu_table->boundary_moderation_en    = tu->boundary_moderation_en;
1208	tu_table->valid_lower_boundary_link = tu->valid_lower_boundary_link;
1209	tu_table->upper_boundary_count      = tu->upper_boundary_count;
1210	tu_table->lower_boundary_count      = tu->lower_boundary_count;
1211	tu_table->tu_size_minus1            = tu->tu_size_minus1;
1212
1213	drm_dbg_dp(ctrl->drm_dev, "TU: valid_boundary_link: %d\n",
1214				tu_table->valid_boundary_link);
1215	drm_dbg_dp(ctrl->drm_dev, "TU: delay_start_link: %d\n",
1216				tu_table->delay_start_link);
1217	drm_dbg_dp(ctrl->drm_dev, "TU: boundary_moderation_en: %d\n",
1218			tu_table->boundary_moderation_en);
1219	drm_dbg_dp(ctrl->drm_dev, "TU: valid_lower_boundary_link: %d\n",
1220			tu_table->valid_lower_boundary_link);
1221	drm_dbg_dp(ctrl->drm_dev, "TU: upper_boundary_count: %d\n",
1222			tu_table->upper_boundary_count);
1223	drm_dbg_dp(ctrl->drm_dev, "TU: lower_boundary_count: %d\n",
1224			tu_table->lower_boundary_count);
1225	drm_dbg_dp(ctrl->drm_dev, "TU: tu_size_minus1: %d\n",
1226			tu_table->tu_size_minus1);
1227
1228	kfree(tu);
1229}
1230
1231static void msm_dp_ctrl_calc_tu_parameters(struct msm_dp_ctrl_private *ctrl,
1232		struct msm_dp_vc_tu_mapping_table *tu_table)
1233{
1234	struct msm_dp_tu_calc_input in;
1235	struct drm_display_mode *drm_mode;
1236
1237	drm_mode = &ctrl->panel->msm_dp_mode.drm_mode;
1238
1239	in.lclk = ctrl->link->link_params.rate / 1000;
1240	in.pclk_khz = drm_mode->clock;
1241	in.hactive = drm_mode->hdisplay;
1242	in.hporch = drm_mode->htotal - drm_mode->hdisplay;
1243	in.nlanes = ctrl->link->link_params.num_lanes;
1244	in.bpp = ctrl->panel->msm_dp_mode.bpp;
1245	in.pixel_enc = ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
1246	in.dsc_en = 0;
1247	in.async_en = 0;
1248	in.fec_en = 0;
1249	in.num_of_dsc_slices = 0;
1250	in.compress_ratio = 100;
1251
1252	_dp_ctrl_calc_tu(ctrl, &in, tu_table);
1253}
1254
1255static void msm_dp_ctrl_setup_tr_unit(struct msm_dp_ctrl_private *ctrl)
1256{
1257	u32 msm_dp_tu = 0x0;
1258	u32 valid_boundary = 0x0;
1259	u32 valid_boundary2 = 0x0;
1260	struct msm_dp_vc_tu_mapping_table tu_calc_table;
1261
1262	msm_dp_ctrl_calc_tu_parameters(ctrl, &tu_calc_table);
1263
1264	msm_dp_tu |= tu_calc_table.tu_size_minus1;
1265	valid_boundary |= tu_calc_table.valid_boundary_link;
1266	valid_boundary |= (tu_calc_table.delay_start_link << 16);
1267
1268	valid_boundary2 |= (tu_calc_table.valid_lower_boundary_link << 1);
1269	valid_boundary2 |= (tu_calc_table.upper_boundary_count << 16);
1270	valid_boundary2 |= (tu_calc_table.lower_boundary_count << 20);
1271
1272	if (tu_calc_table.boundary_moderation_en)
1273		valid_boundary2 |= BIT(0);
1274
1275	pr_debug("dp_tu=0x%x, valid_boundary=0x%x, valid_boundary2=0x%x\n",
1276			msm_dp_tu, valid_boundary, valid_boundary2);
1277
1278	msm_dp_write_link(ctrl, REG_DP_VALID_BOUNDARY, valid_boundary);
1279	msm_dp_write_link(ctrl, REG_DP_TU, msm_dp_tu);
1280	msm_dp_write_link(ctrl, REG_DP_VALID_BOUNDARY_2, valid_boundary2);
1281}
1282
1283static int msm_dp_ctrl_wait4video_ready(struct msm_dp_ctrl_private *ctrl)
1284{
1285	int ret = 0;
1286
1287	if (!wait_for_completion_timeout(&ctrl->video_comp,
1288				WAIT_FOR_VIDEO_READY_TIMEOUT_JIFFIES)) {
1289		DRM_ERROR("wait4video timedout\n");
1290		ret = -ETIMEDOUT;
1291	}
1292	return ret;
1293}
1294
1295static int msm_dp_ctrl_set_vx_px(struct msm_dp_ctrl_private *ctrl,
1296			     u8 v_level, u8 p_level)
1297{
1298	union phy_configure_opts *phy_opts = &ctrl->phy_opts;
1299
1300	/* TODO: Update for all lanes instead of just first one */
1301	phy_opts->dp.voltage[0] = v_level;
1302	phy_opts->dp.pre[0] = p_level;
1303	phy_opts->dp.set_voltages = 1;
1304	phy_configure(ctrl->phy, phy_opts);
1305	phy_opts->dp.set_voltages = 0;
1306
1307	return 0;
1308}
1309
1310static int msm_dp_ctrl_update_phy_vx_px(struct msm_dp_ctrl_private *ctrl,
1311					enum drm_dp_phy dp_phy)
1312{
1313	struct msm_dp_link *link = ctrl->link;
1314	int lane, lane_cnt, reg;
1315	int ret = 0;
1316	u8 buf[4];
1317	u32 max_level_reached = 0;
1318	u32 voltage_swing_level = link->phy_params.v_level;
1319	u32 pre_emphasis_level = link->phy_params.p_level;
1320
1321	drm_dbg_dp(ctrl->drm_dev,
1322		"voltage level: %d emphasis level: %d\n",
1323			voltage_swing_level, pre_emphasis_level);
1324	ret = msm_dp_ctrl_set_vx_px(ctrl,
1325		voltage_swing_level, pre_emphasis_level);
1326
1327	if (ret)
1328		return ret;
1329
1330	if (voltage_swing_level >= DP_TRAIN_LEVEL_MAX) {
1331		drm_dbg_dp(ctrl->drm_dev,
1332				"max. voltage swing level reached %d\n",
1333				voltage_swing_level);
1334		max_level_reached |= DP_TRAIN_MAX_SWING_REACHED;
1335	}
1336
1337	if (pre_emphasis_level >= DP_TRAIN_LEVEL_MAX) {
1338		drm_dbg_dp(ctrl->drm_dev,
1339				"max. pre-emphasis level reached %d\n",
1340				pre_emphasis_level);
1341		max_level_reached  |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
1342	}
1343
1344	pre_emphasis_level <<= DP_TRAIN_PRE_EMPHASIS_SHIFT;
1345
1346	lane_cnt = ctrl->link->link_params.num_lanes;
1347	for (lane = 0; lane < lane_cnt; lane++)
1348		buf[lane] = voltage_swing_level | pre_emphasis_level
1349				| max_level_reached;
1350
1351	drm_dbg_dp(ctrl->drm_dev, "sink: p|v=0x%x\n",
1352			voltage_swing_level | pre_emphasis_level);
1353
1354	if (dp_phy == DP_PHY_DPRX)
1355		reg = DP_TRAINING_LANE0_SET;
1356	else
1357		reg = DP_TRAINING_LANE0_SET_PHY_REPEATER(dp_phy);
1358
1359	ret = drm_dp_dpcd_write(ctrl->aux, reg, buf, lane_cnt);
1360	if (ret == lane_cnt)
1361		ret = 0;
1362
1363	return ret;
1364}
1365
1366static bool msm_dp_ctrl_train_pattern_set(struct msm_dp_ctrl_private *ctrl,
1367		u8 pattern, enum drm_dp_phy dp_phy)
1368{
1369	u8 buf;
1370	int reg;
1371	int ret = 0;
1372
1373	drm_dbg_dp(ctrl->drm_dev, "sink: pattern=%x\n", pattern);
1374
1375	buf = pattern;
1376
1377	if (pattern && pattern != DP_TRAINING_PATTERN_4)
1378		buf |= DP_LINK_SCRAMBLING_DISABLE;
1379
1380	if (dp_phy == DP_PHY_DPRX)
1381		reg = DP_TRAINING_PATTERN_SET;
1382	else
1383		reg = DP_TRAINING_PATTERN_SET_PHY_REPEATER(dp_phy);
1384
1385	ret = drm_dp_dpcd_writeb(ctrl->aux, reg, buf);
1386	return ret == 1;
1387}
1388
1389static int msm_dp_ctrl_set_pattern_state_bit(struct msm_dp_ctrl_private *ctrl,
1390					 u32 state_bit)
1391{
1392	int bit, ret;
1393	u32 data;
1394
1395	bit = BIT(state_bit - 1);
1396	drm_dbg_dp(ctrl->drm_dev, "hw: bit=%d train=%d\n", bit, state_bit);
1397	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, bit);
1398
1399	bit = BIT(state_bit - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;
1400
1401	/* Poll for mainlink ready status */
1402	ret = readx_poll_timeout(readl, ctrl->link_base + REG_DP_MAINLINK_READY,
1403				 data, data & bit,
1404				 POLLING_SLEEP_US, POLLING_TIMEOUT_US);
1405	if (ret < 0) {
1406		DRM_ERROR("set state_bit for link_train=%d failed\n", state_bit);
1407		return ret;
1408	}
1409
1410	return 0;
1411}
1412
1413static int msm_dp_ctrl_link_train_1(struct msm_dp_ctrl_private *ctrl,
1414			int *training_step, enum drm_dp_phy dp_phy)
1415{
1416	int delay_us;
1417	int tries, old_v_level, ret = 0;
1418	u8 link_status[DP_LINK_STATUS_SIZE];
1419	int const maximum_retries = 4;
1420
1421	delay_us = drm_dp_read_clock_recovery_delay(ctrl->aux,
1422						    ctrl->panel->dpcd, dp_phy, false);
1423
1424	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0);
1425
1426	*training_step = DP_TRAINING_1;
1427
1428	ret = msm_dp_ctrl_set_pattern_state_bit(ctrl, 1);
1429	if (ret)
1430		return ret;
1431	msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
1432		DP_LINK_SCRAMBLING_DISABLE, dp_phy);
1433
1434	msm_dp_link_reset_phy_params_vx_px(ctrl->link);
1435	ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy);
1436	if (ret)
1437		return ret;
1438
1439	tries = 0;
1440	old_v_level = ctrl->link->phy_params.v_level;
1441	for (tries = 0; tries < maximum_retries; tries++) {
1442		fsleep(delay_us);
1443
1444		ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status);
1445		if (ret)
1446			return ret;
1447
1448		if (drm_dp_clock_recovery_ok(link_status,
1449			ctrl->link->link_params.num_lanes)) {
1450			return 0;
1451		}
1452
1453		if (ctrl->link->phy_params.v_level >=
1454			DP_TRAIN_LEVEL_MAX) {
1455			DRM_ERROR_RATELIMITED("max v_level reached\n");
1456			return -EAGAIN;
1457		}
1458
1459		if (old_v_level != ctrl->link->phy_params.v_level) {
1460			tries = 0;
1461			old_v_level = ctrl->link->phy_params.v_level;
1462		}
1463
1464		msm_dp_link_adjust_levels(ctrl->link, link_status);
1465		ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy);
1466		if (ret)
1467			return ret;
1468	}
1469
1470	DRM_ERROR("max tries reached\n");
1471	return -ETIMEDOUT;
1472}
1473
1474static int msm_dp_ctrl_link_rate_down_shift(struct msm_dp_ctrl_private *ctrl)
1475{
1476	int ret = 0;
1477
1478	switch (ctrl->link->link_params.rate) {
1479	case 810000:
1480		ctrl->link->link_params.rate = 540000;
1481		break;
1482	case 540000:
1483		ctrl->link->link_params.rate = 270000;
1484		break;
1485	case 270000:
1486		ctrl->link->link_params.rate = 162000;
1487		break;
1488	case 162000:
1489	default:
1490		ret = -EINVAL;
1491		break;
1492	}
1493
1494	if (!ret) {
1495		drm_dbg_dp(ctrl->drm_dev, "new rate=0x%x\n",
1496				ctrl->link->link_params.rate);
1497	}
1498
1499	return ret;
1500}
1501
1502static int msm_dp_ctrl_link_lane_down_shift(struct msm_dp_ctrl_private *ctrl)
1503{
1504
1505	if (ctrl->link->link_params.num_lanes == 1)
1506		return -1;
1507
1508	ctrl->link->link_params.num_lanes /= 2;
1509	ctrl->link->link_params.rate = ctrl->panel->link_info.rate;
1510
1511	ctrl->link->phy_params.p_level = 0;
1512	ctrl->link->phy_params.v_level = 0;
1513
1514	return 0;
1515}
1516
1517static void msm_dp_ctrl_clear_training_pattern(struct msm_dp_ctrl_private *ctrl,
1518					       enum drm_dp_phy dp_phy)
1519{
1520	int delay_us;
1521
1522	msm_dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_DISABLE, dp_phy);
1523
1524	delay_us = drm_dp_read_channel_eq_delay(ctrl->aux,
1525						ctrl->panel->dpcd, dp_phy, false);
1526	fsleep(delay_us);
1527}
1528
1529static int msm_dp_ctrl_link_train_2(struct msm_dp_ctrl_private *ctrl,
1530			int *training_step, enum drm_dp_phy dp_phy)
1531{
1532	int delay_us;
1533	int tries = 0, ret = 0;
1534	u8 pattern;
1535	u32 state_ctrl_bit;
1536	int const maximum_retries = 5;
1537	u8 link_status[DP_LINK_STATUS_SIZE];
1538
1539	delay_us = drm_dp_read_channel_eq_delay(ctrl->aux,
1540						ctrl->panel->dpcd, dp_phy, false);
1541
1542	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0);
1543
1544	*training_step = DP_TRAINING_2;
1545
1546	if (drm_dp_tps4_supported(ctrl->panel->dpcd)) {
1547		pattern = DP_TRAINING_PATTERN_4;
1548		state_ctrl_bit = 4;
1549	} else if (drm_dp_tps3_supported(ctrl->panel->dpcd)) {
1550		pattern = DP_TRAINING_PATTERN_3;
1551		state_ctrl_bit = 3;
1552	} else {
1553		pattern = DP_TRAINING_PATTERN_2;
1554		state_ctrl_bit = 2;
1555	}
1556
1557	ret = msm_dp_ctrl_set_pattern_state_bit(ctrl, state_ctrl_bit);
1558	if (ret)
1559		return ret;
1560
1561	msm_dp_ctrl_train_pattern_set(ctrl, pattern, dp_phy);
1562
1563	for (tries = 0; tries <= maximum_retries; tries++) {
1564		fsleep(delay_us);
1565
1566		ret = drm_dp_dpcd_read_phy_link_status(ctrl->aux, dp_phy, link_status);
1567		if (ret)
1568			return ret;
1569
1570		if (drm_dp_channel_eq_ok(link_status,
1571			ctrl->link->link_params.num_lanes)) {
1572			return 0;
1573		}
1574
1575		msm_dp_link_adjust_levels(ctrl->link, link_status);
1576		ret = msm_dp_ctrl_update_phy_vx_px(ctrl, dp_phy);
1577		if (ret)
1578			return ret;
1579
1580	}
1581
1582	return -ETIMEDOUT;
1583}
1584
1585static int msm_dp_ctrl_link_train_1_2(struct msm_dp_ctrl_private *ctrl,
1586				      int *training_step, enum drm_dp_phy dp_phy)
1587{
1588	int ret;
1589
1590	ret = msm_dp_ctrl_link_train_1(ctrl, training_step, dp_phy);
1591	if (ret) {
1592		DRM_ERROR("link training #1 on phy %d failed. ret=%d\n", dp_phy, ret);
1593		return ret;
1594	}
1595	drm_dbg_dp(ctrl->drm_dev, "link training #1 on phy %d successful\n", dp_phy);
1596
1597	ret = msm_dp_ctrl_link_train_2(ctrl, training_step, dp_phy);
1598	if (ret) {
1599		DRM_ERROR("link training #2 on phy %d failed. ret=%d\n", dp_phy, ret);
1600		return ret;
1601	}
1602	drm_dbg_dp(ctrl->drm_dev, "link training #2 on phy %d successful\n", dp_phy);
1603
1604	return 0;
1605}
1606
1607static int msm_dp_ctrl_link_train(struct msm_dp_ctrl_private *ctrl,
1608			int *training_step)
1609{
1610	int i;
1611	int ret = 0;
1612	const u8 *dpcd = ctrl->panel->dpcd;
1613	u8 encoding[] = { 0, DP_SET_ANSI_8B10B };
1614	u8 assr;
1615	struct msm_dp_link_info link_info = {0};
1616
1617	msm_dp_ctrl_config_ctrl(ctrl);
1618
1619	link_info.num_lanes = ctrl->link->link_params.num_lanes;
1620	link_info.rate = ctrl->link->link_params.rate;
1621	link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;
1622
1623	msm_dp_aux_link_configure(ctrl->aux, &link_info);
1624
1625	if (drm_dp_max_downspread(dpcd))
1626		encoding[0] |= DP_SPREAD_AMP_0_5;
1627
1628	/* config DOWNSPREAD_CTRL and MAIN_LINK_CHANNEL_CODING_SET */
1629	drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, encoding, 2);
1630
1631	if (drm_dp_alternate_scrambler_reset_cap(dpcd)) {
1632		assr = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;
1633		drm_dp_dpcd_write(ctrl->aux, DP_EDP_CONFIGURATION_SET,
1634				&assr, 1);
1635	}
1636
1637	for (i = ctrl->link->lttpr_count - 1; i >= 0; i--) {
1638		enum drm_dp_phy dp_phy = DP_PHY_LTTPR(i);
1639
1640		ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, dp_phy);
1641		msm_dp_ctrl_clear_training_pattern(ctrl, dp_phy);
1642
1643		if (ret)
1644			break;
1645	}
1646
1647	if (ret) {
1648		DRM_ERROR("link training of LTTPR(s) failed. ret=%d\n", ret);
1649		goto end;
1650	}
1651
1652	ret = msm_dp_ctrl_link_train_1_2(ctrl, training_step, DP_PHY_DPRX);
1653	if (ret) {
1654		DRM_ERROR("link training on sink failed. ret=%d\n", ret);
1655		goto end;
1656	}
1657
1658end:
1659	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0);
1660
1661	return ret;
1662}
1663
1664static int msm_dp_ctrl_setup_main_link(struct msm_dp_ctrl_private *ctrl,
1665			int *training_step)
1666{
1667	int ret = 0;
1668
1669	msm_dp_ctrl_mainlink_enable(ctrl);
1670
1671	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
1672		return ret;
1673
1674	/*
1675	 * As part of previous calls, DP controller state might have
1676	 * transitioned to PUSH_IDLE. In order to start transmitting
1677	 * a link training pattern, we have to first do soft reset.
1678	 */
1679
1680	ret = msm_dp_ctrl_link_train(ctrl, training_step);
1681
1682	return ret;
1683}
1684
1685int msm_dp_ctrl_core_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl)
1686{
1687	struct msm_dp_ctrl_private *ctrl;
1688	int ret = 0;
1689
1690	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1691
1692	if (ctrl->core_clks_on) {
1693		drm_dbg_dp(ctrl->drm_dev, "core clks already enabled\n");
1694		return 0;
1695	}
1696
1697	ret = clk_bulk_prepare_enable(ctrl->num_core_clks, ctrl->core_clks);
1698	if (ret)
1699		return ret;
1700
1701	ctrl->core_clks_on = true;
1702
1703	drm_dbg_dp(ctrl->drm_dev, "enable core clocks \n");
1704	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",
1705		   str_on_off(ctrl->stream_clks_on),
1706		   str_on_off(ctrl->link_clks_on),
1707		   str_on_off(ctrl->core_clks_on));
1708
1709	return 0;
1710}
1711
1712void msm_dp_ctrl_core_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl)
1713{
1714	struct msm_dp_ctrl_private *ctrl;
1715
1716	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1717
1718	clk_bulk_disable_unprepare(ctrl->num_core_clks, ctrl->core_clks);
1719
1720	ctrl->core_clks_on = false;
1721
1722	drm_dbg_dp(ctrl->drm_dev, "disable core clocks \n");
1723	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",
1724		   str_on_off(ctrl->stream_clks_on),
1725		   str_on_off(ctrl->link_clks_on),
1726		   str_on_off(ctrl->core_clks_on));
1727}
1728
1729static int msm_dp_ctrl_link_clk_enable(struct msm_dp_ctrl *msm_dp_ctrl)
1730{
1731	struct msm_dp_ctrl_private *ctrl;
1732	int ret = 0;
1733
1734	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1735
1736	if (ctrl->link_clks_on) {
1737		drm_dbg_dp(ctrl->drm_dev, "links clks already enabled\n");
1738		return 0;
1739	}
1740
1741	if (!ctrl->core_clks_on) {
1742		drm_dbg_dp(ctrl->drm_dev, "Enable core clks before link clks\n");
1743
1744		msm_dp_ctrl_core_clk_enable(msm_dp_ctrl);
1745	}
1746
1747	ret = clk_bulk_prepare_enable(ctrl->num_link_clks, ctrl->link_clks);
1748	if (ret)
1749		return ret;
1750
1751	ctrl->link_clks_on = true;
1752
1753	drm_dbg_dp(ctrl->drm_dev, "enable link clocks\n");
1754	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",
1755		   str_on_off(ctrl->stream_clks_on),
1756		   str_on_off(ctrl->link_clks_on),
1757		   str_on_off(ctrl->core_clks_on));
1758
1759	return 0;
1760}
1761
1762static void msm_dp_ctrl_link_clk_disable(struct msm_dp_ctrl *msm_dp_ctrl)
1763{
1764	struct msm_dp_ctrl_private *ctrl;
1765
1766	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1767
1768	clk_bulk_disable_unprepare(ctrl->num_link_clks, ctrl->link_clks);
1769
1770	ctrl->link_clks_on = false;
1771
1772	drm_dbg_dp(ctrl->drm_dev, "disabled link clocks\n");
1773	drm_dbg_dp(ctrl->drm_dev, "stream_clks:%s link_clks:%s core_clks:%s\n",
1774		   str_on_off(ctrl->stream_clks_on),
1775		   str_on_off(ctrl->link_clks_on),
1776		   str_on_off(ctrl->core_clks_on));
1777}
1778
1779static int msm_dp_ctrl_enable_mainlink_clocks(struct msm_dp_ctrl_private *ctrl)
1780{
1781	int ret = 0;
1782	struct phy *phy = ctrl->phy;
1783	const u8 *dpcd = ctrl->panel->dpcd;
1784
1785	ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes;
1786	ctrl->phy_opts.dp.link_rate = ctrl->link->link_params.rate / 100;
1787	ctrl->phy_opts.dp.ssc = drm_dp_max_downspread(dpcd);
1788
1789	phy_configure(phy, &ctrl->phy_opts);
1790	phy_power_on(phy);
1791
1792	dev_pm_opp_set_rate(ctrl->dev, ctrl->link->link_params.rate * 1000);
1793	ret = msm_dp_ctrl_link_clk_enable(&ctrl->msm_dp_ctrl);
1794	if (ret)
1795		DRM_ERROR("Unable to start link clocks. ret=%d\n", ret);
1796
1797	drm_dbg_dp(ctrl->drm_dev, "link rate=%d\n", ctrl->link->link_params.rate);
1798
1799	return ret;
1800}
1801
1802static void msm_dp_ctrl_enable_sdp(struct msm_dp_ctrl_private *ctrl)
1803{
1804	/* trigger sdp */
1805	msm_dp_write_link(ctrl, MMSS_DP_SDP_CFG3, UPDATE_SDP);
1806	msm_dp_write_link(ctrl, MMSS_DP_SDP_CFG3, 0x0);
1807}
1808
1809static void msm_dp_ctrl_psr_enter(struct msm_dp_ctrl_private *ctrl)
1810{
1811	u32 cmd;
1812
1813	cmd = msm_dp_read_link(ctrl, REG_PSR_CMD);
1814
1815	cmd &= ~(PSR_ENTER | PSR_EXIT);
1816	cmd |= PSR_ENTER;
1817
1818	msm_dp_ctrl_enable_sdp(ctrl);
1819	msm_dp_write_link(ctrl, REG_PSR_CMD, cmd);
1820}
1821
1822static void msm_dp_ctrl_psr_exit(struct msm_dp_ctrl_private *ctrl)
1823{
1824	u32 cmd;
1825
1826	cmd = msm_dp_read_link(ctrl, REG_PSR_CMD);
1827
1828	cmd &= ~(PSR_ENTER | PSR_EXIT);
1829	cmd |= PSR_EXIT;
1830
1831	msm_dp_ctrl_enable_sdp(ctrl);
1832	msm_dp_write_link(ctrl, REG_PSR_CMD, cmd);
1833}
1834
1835void msm_dp_ctrl_config_psr(struct msm_dp_ctrl *msm_dp_ctrl)
1836{
1837	struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl,
1838			struct msm_dp_ctrl_private, msm_dp_ctrl);
1839	u32 cfg;
1840
1841	if (!ctrl->panel->psr_cap.version)
1842		return;
1843
1844	/* enable PSR1 function */
1845	cfg = msm_dp_read_link(ctrl, REG_PSR_CONFIG);
1846	cfg |= PSR1_SUPPORTED;
1847	msm_dp_write_link(ctrl, REG_PSR_CONFIG, cfg);
1848
1849	msm_dp_ctrl_config_psr_interrupt(ctrl);
1850	msm_dp_ctrl_enable_sdp(ctrl);
1851
1852	cfg = DP_PSR_ENABLE;
1853	drm_dp_dpcd_write(ctrl->aux, DP_PSR_EN_CFG, &cfg, 1);
1854}
1855
1856void msm_dp_ctrl_set_psr(struct msm_dp_ctrl *msm_dp_ctrl, bool enter)
1857{
1858	struct msm_dp_ctrl_private *ctrl = container_of(msm_dp_ctrl,
1859			struct msm_dp_ctrl_private, msm_dp_ctrl);
1860
1861	if (!ctrl->panel->psr_cap.version)
1862		return;
1863
1864	/*
1865	 * When entering PSR,
1866	 * 1. Send PSR enter SDP and wait for the PSR_UPDATE_INT
1867	 * 2. Turn off video
1868	 * 3. Disable the mainlink
1869	 *
1870	 * When exiting PSR,
1871	 * 1. Enable the mainlink
1872	 * 2. Send the PSR exit SDP
1873	 */
1874	if (enter) {
1875		reinit_completion(&ctrl->psr_op_comp);
1876		msm_dp_ctrl_psr_enter(ctrl);
1877
1878		if (!wait_for_completion_timeout(&ctrl->psr_op_comp,
1879			PSR_OPERATION_COMPLETION_TIMEOUT_JIFFIES)) {
1880			DRM_ERROR("PSR_ENTRY timedout\n");
1881			msm_dp_ctrl_psr_exit(ctrl);
1882			return;
1883		}
1884
1885		msm_dp_ctrl_push_idle(msm_dp_ctrl);
1886		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0);
1887
1888		msm_dp_ctrl_psr_mainlink_disable(ctrl);
1889	} else {
1890		msm_dp_ctrl_psr_mainlink_enable(ctrl);
1891
1892		msm_dp_ctrl_psr_exit(ctrl);
1893		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO);
1894		msm_dp_ctrl_wait4video_ready(ctrl);
1895		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0);
1896	}
1897}
1898
1899static void msm_dp_ctrl_phy_reset(struct msm_dp_ctrl_private *ctrl)
1900{
1901	msm_dp_write_ahb(ctrl, REG_DP_PHY_CTRL,
1902			DP_PHY_CTRL_SW_RESET | DP_PHY_CTRL_SW_RESET_PLL);
1903	usleep_range(1000, 1100); /* h/w recommended delay */
1904	msm_dp_write_ahb(ctrl, REG_DP_PHY_CTRL, 0x0);
1905}
1906
1907void msm_dp_ctrl_phy_init(struct msm_dp_ctrl *msm_dp_ctrl)
1908{
1909	struct msm_dp_ctrl_private *ctrl;
1910	struct phy *phy;
1911
1912	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1913	phy = ctrl->phy;
1914
1915	msm_dp_ctrl_phy_reset(ctrl);
1916	phy_init(phy);
1917
1918	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
1919			phy, phy->init_count, phy->power_count);
1920}
1921
1922void msm_dp_ctrl_phy_exit(struct msm_dp_ctrl *msm_dp_ctrl)
1923{
1924	struct msm_dp_ctrl_private *ctrl;
1925	struct phy *phy;
1926
1927	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
1928	phy = ctrl->phy;
1929
1930	msm_dp_ctrl_phy_reset(ctrl);
1931	phy_exit(phy);
1932	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
1933			phy, phy->init_count, phy->power_count);
1934}
1935
1936static int msm_dp_ctrl_reinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
1937{
1938	struct phy *phy = ctrl->phy;
1939	int ret = 0;
1940
1941	msm_dp_ctrl_mainlink_disable(ctrl);
1942	ctrl->phy_opts.dp.lanes = ctrl->link->link_params.num_lanes;
1943	phy_configure(phy, &ctrl->phy_opts);
1944	/*
1945	 * Disable and re-enable the mainlink clock since the
1946	 * link clock might have been adjusted as part of the
1947	 * link maintenance.
1948	 */
1949	dev_pm_opp_set_rate(ctrl->dev, 0);
1950
1951	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
1952
1953	phy_power_off(phy);
1954	/* hw recommended delay before re-enabling clocks */
1955	msleep(20);
1956
1957	ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
1958	if (ret) {
1959		DRM_ERROR("Failed to enable mainlink clks. ret=%d\n", ret);
1960		return ret;
1961	}
1962
1963	return ret;
1964}
1965
1966static int msm_dp_ctrl_deinitialize_mainlink(struct msm_dp_ctrl_private *ctrl)
1967{
1968	struct phy *phy;
1969
1970	phy = ctrl->phy;
1971
1972	msm_dp_ctrl_mainlink_disable(ctrl);
1973
1974	msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl);
1975
1976	dev_pm_opp_set_rate(ctrl->dev, 0);
1977	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
1978
1979	phy_power_off(phy);
1980
1981	/* aux channel down, reinit phy */
1982	phy_exit(phy);
1983	phy_init(phy);
1984
1985	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
1986			phy, phy->init_count, phy->power_count);
1987	return 0;
1988}
1989
1990static int msm_dp_ctrl_link_maintenance(struct msm_dp_ctrl_private *ctrl)
1991{
1992	int ret = 0;
1993	int training_step = DP_TRAINING_NONE;
1994
1995	msm_dp_ctrl_push_idle(&ctrl->msm_dp_ctrl);
1996
1997	ctrl->link->phy_params.p_level = 0;
1998	ctrl->link->phy_params.v_level = 0;
1999
2000	ret = msm_dp_ctrl_setup_main_link(ctrl, &training_step);
2001	if (ret)
2002		goto end;
2003
2004	msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX);
2005
2006	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO);
2007
2008	ret = msm_dp_ctrl_wait4video_ready(ctrl);
2009end:
2010	return ret;
2011}
2012
2013#define SCRAMBLER_RESET_COUNT_VALUE		0xFC
2014
2015static void msm_dp_ctrl_send_phy_pattern(struct msm_dp_ctrl_private *ctrl,
2016				     u32 pattern)
2017{
2018	u32 value = 0x0;
2019
2020	/* Make sure to clear the current pattern before starting a new one */
2021	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, 0x0);
2022
2023	drm_dbg_dp(ctrl->drm_dev, "pattern: %#x\n", pattern);
2024	switch (pattern) {
2025	case DP_PHY_TEST_PATTERN_D10_2:
2026		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2027			      DP_STATE_CTRL_LINK_TRAINING_PATTERN1);
2028		break;
2029
2030	case DP_PHY_TEST_PATTERN_ERROR_COUNT:
2031		value &= ~(1 << 16);
2032		msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
2033			      value);
2034		value |= SCRAMBLER_RESET_COUNT_VALUE;
2035		msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
2036			      value);
2037		msm_dp_write_link(ctrl, REG_DP_MAINLINK_LEVELS,
2038			      DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
2039		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2040			      DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
2041		break;
2042
2043	case DP_PHY_TEST_PATTERN_PRBS7:
2044		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2045			      DP_STATE_CTRL_LINK_PRBS7);
2046		break;
2047
2048	case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
2049		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2050			      DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN);
2051		/* 00111110000011111000001111100000 */
2052		msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG0,
2053			      0x3E0F83E0);
2054		/* 00001111100000111110000011111000 */
2055		msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG1,
2056			      0x0F83E0F8);
2057		/* 1111100000111110 */
2058		msm_dp_write_link(ctrl, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2,
2059			      0x0000F83E);
2060		break;
2061
2062	case DP_PHY_TEST_PATTERN_CP2520:
2063		value = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
2064		value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER;
2065		msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, value);
2066
2067		value = DP_HBR2_ERM_PATTERN;
2068		msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
2069			      value);
2070		value |= SCRAMBLER_RESET_COUNT_VALUE;
2071		msm_dp_write_link(ctrl, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
2072			      value);
2073		msm_dp_write_link(ctrl, REG_DP_MAINLINK_LEVELS,
2074			      DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
2075		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2076			      DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
2077		value = msm_dp_read_link(ctrl, REG_DP_MAINLINK_CTRL);
2078		value |= DP_MAINLINK_CTRL_ENABLE;
2079		msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL, value);
2080		break;
2081
2082	case DP_PHY_TEST_PATTERN_SEL_MASK:
2083		msm_dp_write_link(ctrl, REG_DP_MAINLINK_CTRL,
2084			      DP_MAINLINK_CTRL_ENABLE);
2085		msm_dp_write_link(ctrl, REG_DP_STATE_CTRL,
2086			      DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
2087		break;
2088
2089	default:
2090		drm_dbg_dp(ctrl->drm_dev,
2091			   "No valid test pattern requested: %#x\n", pattern);
2092	break;
2093	}
2094}
2095
2096static bool msm_dp_ctrl_send_phy_test_pattern(struct msm_dp_ctrl_private *ctrl)
2097{
2098	bool success = false;
2099	u32 pattern_sent = 0x0;
2100	u32 pattern_requested = ctrl->link->phy_params.phy_test_pattern_sel;
2101
2102	drm_dbg_dp(ctrl->drm_dev, "request: 0x%x\n", pattern_requested);
2103
2104	if (msm_dp_ctrl_set_vx_px(ctrl,
2105			ctrl->link->phy_params.v_level,
2106			ctrl->link->phy_params.p_level)) {
2107		DRM_ERROR("Failed to set v/p levels\n");
2108		return false;
2109	}
2110	msm_dp_ctrl_send_phy_pattern(ctrl, pattern_requested);
2111	msm_dp_ctrl_update_phy_vx_px(ctrl, DP_PHY_DPRX);
2112	msm_dp_link_send_test_response(ctrl->link);
2113
2114	pattern_sent = msm_dp_read_link(ctrl, REG_DP_MAINLINK_READY);
2115
2116	switch (pattern_sent) {
2117	case MR_LINK_TRAINING1:
2118		success = (pattern_requested ==
2119				DP_PHY_TEST_PATTERN_D10_2);
2120		break;
2121	case MR_LINK_SYMBOL_ERM:
2122		success = ((pattern_requested ==
2123			DP_PHY_TEST_PATTERN_ERROR_COUNT) ||
2124				(pattern_requested ==
2125				DP_PHY_TEST_PATTERN_CP2520));
2126		break;
2127	case MR_LINK_PRBS7:
2128		success = (pattern_requested ==
2129				DP_PHY_TEST_PATTERN_PRBS7);
2130		break;
2131	case MR_LINK_CUSTOM80:
2132		success = (pattern_requested ==
2133				DP_PHY_TEST_PATTERN_80BIT_CUSTOM);
2134		break;
2135	case MR_LINK_TRAINING4:
2136		success = (pattern_requested ==
2137				DP_PHY_TEST_PATTERN_SEL_MASK);
2138		break;
2139	default:
2140		success = false;
2141	}
2142
2143	drm_dbg_dp(ctrl->drm_dev, "%s: test->0x%x\n",
2144		success ? "success" : "failed", pattern_requested);
2145	return success;
2146}
2147
2148static int msm_dp_ctrl_process_phy_test_request(struct msm_dp_ctrl_private *ctrl)
2149{
2150	int ret;
2151	unsigned long pixel_rate;
2152
2153	if (!ctrl->link->phy_params.phy_test_pattern_sel) {
2154		drm_dbg_dp(ctrl->drm_dev,
2155			"no test pattern selected by sink\n");
2156		return 0;
2157	}
2158
2159	/*
2160	 * The global reset will need DP link related clocks to be
2161	 * running. Add the global reset just before disabling the
2162	 * link clocks and core clocks.
2163	 */
2164	msm_dp_ctrl_off(&ctrl->msm_dp_ctrl);
2165
2166	ret = msm_dp_ctrl_on_link(&ctrl->msm_dp_ctrl);
2167	if (ret) {
2168		DRM_ERROR("failed to enable DP link controller\n");
2169		return ret;
2170	}
2171
2172	pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock;
2173	ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);
2174	if (ret) {
2175		DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);
2176		return ret;
2177	}
2178
2179	if (ctrl->stream_clks_on) {
2180		drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n");
2181	} else {
2182		ret = clk_prepare_enable(ctrl->pixel_clk);
2183		if (ret) {
2184			DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
2185			return ret;
2186		}
2187		ctrl->stream_clks_on = true;
2188	}
2189
2190	msm_dp_ctrl_send_phy_test_pattern(ctrl);
2191
2192	return 0;
2193}
2194
2195void msm_dp_ctrl_handle_sink_request(struct msm_dp_ctrl *msm_dp_ctrl)
2196{
2197	struct msm_dp_ctrl_private *ctrl;
2198	u32 sink_request = 0x0;
2199
2200	if (!msm_dp_ctrl) {
2201		DRM_ERROR("invalid input\n");
2202		return;
2203	}
2204
2205	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2206	sink_request = ctrl->link->sink_request;
2207
2208	if (sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
2209		drm_dbg_dp(ctrl->drm_dev, "PHY_TEST_PATTERN request\n");
2210		if (msm_dp_ctrl_process_phy_test_request(ctrl)) {
2211			DRM_ERROR("process phy_test_req failed\n");
2212			return;
2213		}
2214	}
2215
2216	if (sink_request & DP_LINK_STATUS_UPDATED) {
2217		if (msm_dp_ctrl_link_maintenance(ctrl)) {
2218			DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
2219			return;
2220		}
2221	}
2222
2223	if (sink_request & DP_TEST_LINK_TRAINING) {
2224		msm_dp_link_send_test_response(ctrl->link);
2225		if (msm_dp_ctrl_link_maintenance(ctrl)) {
2226			DRM_ERROR("LM failed: TEST_LINK_TRAINING\n");
2227			return;
2228		}
2229	}
2230}
2231
2232static bool msm_dp_ctrl_clock_recovery_any_ok(
2233			const u8 link_status[DP_LINK_STATUS_SIZE],
2234			int lane_count)
2235{
2236	int reduced_cnt;
2237
2238	if (lane_count <= 1)
2239		return false;
2240
2241	/*
2242	 * only interested in the lane number after reduced
2243	 * lane_count = 4, then only interested in 2 lanes
2244	 * lane_count = 2, then only interested in 1 lane
2245	 */
2246	reduced_cnt = lane_count >> 1;
2247
2248	return drm_dp_clock_recovery_ok(link_status, reduced_cnt);
2249}
2250
2251static bool msm_dp_ctrl_channel_eq_ok(struct msm_dp_ctrl_private *ctrl)
2252{
2253	u8 link_status[DP_LINK_STATUS_SIZE];
2254	int num_lanes = ctrl->link->link_params.num_lanes;
2255
2256	drm_dp_dpcd_read_link_status(ctrl->aux, link_status);
2257
2258	return drm_dp_channel_eq_ok(link_status, num_lanes);
2259}
2260
2261int msm_dp_ctrl_on_link(struct msm_dp_ctrl *msm_dp_ctrl)
2262{
2263	int rc = 0;
2264	struct msm_dp_ctrl_private *ctrl;
2265	u32 rate;
2266	int link_train_max_retries = 5;
2267	u32 const phy_cts_pixel_clk_khz = 148500;
2268	u8 link_status[DP_LINK_STATUS_SIZE];
2269	unsigned int training_step;
2270	unsigned long pixel_rate;
2271
2272	if (!msm_dp_ctrl)
2273		return -EINVAL;
2274
2275	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2276
2277	rate = ctrl->panel->link_info.rate;
2278	pixel_rate = ctrl->panel->msm_dp_mode.drm_mode.clock;
2279
2280	msm_dp_ctrl_core_clk_enable(&ctrl->msm_dp_ctrl);
2281
2282	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
2283		drm_dbg_dp(ctrl->drm_dev,
2284				"using phy test link parameters\n");
2285		if (!pixel_rate)
2286			pixel_rate = phy_cts_pixel_clk_khz;
2287	} else {
2288		ctrl->link->link_params.rate = rate;
2289		ctrl->link->link_params.num_lanes =
2290			ctrl->panel->link_info.num_lanes;
2291		if (ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
2292			pixel_rate >>= 1;
2293	}
2294
2295	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
2296		ctrl->link->link_params.rate, ctrl->link->link_params.num_lanes,
2297		pixel_rate);
2298
2299	rc = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
2300	if (rc)
2301		return rc;
2302
2303	while (--link_train_max_retries) {
2304		training_step = DP_TRAINING_NONE;
2305		rc = msm_dp_ctrl_setup_main_link(ctrl, &training_step);
2306		if (rc == 0) {
2307			/* training completed successfully */
2308			break;
2309		} else if (training_step == DP_TRAINING_1) {
2310			/* link train_1 failed */
2311			if (!msm_dp_aux_is_link_connected(ctrl->aux))
2312				break;
2313
2314			drm_dp_dpcd_read_link_status(ctrl->aux, link_status);
2315
2316			rc = msm_dp_ctrl_link_rate_down_shift(ctrl);
2317			if (rc < 0) { /* already in RBR = 1.6G */
2318				if (msm_dp_ctrl_clock_recovery_any_ok(link_status,
2319					ctrl->link->link_params.num_lanes)) {
2320					/*
2321					 * some lanes are ready,
2322					 * reduce lane number
2323					 */
2324					rc = msm_dp_ctrl_link_lane_down_shift(ctrl);
2325					if (rc < 0) { /* lane == 1 already */
2326						/* end with failure */
2327						break;
2328					}
2329				} else {
2330					/* end with failure */
2331					break; /* lane == 1 already */
2332				}
2333			}
2334		} else if (training_step == DP_TRAINING_2) {
2335			/* link train_2 failed */
2336			if (!msm_dp_aux_is_link_connected(ctrl->aux))
2337				break;
2338
2339			drm_dp_dpcd_read_link_status(ctrl->aux, link_status);
2340
2341			if (!drm_dp_clock_recovery_ok(link_status,
2342					ctrl->link->link_params.num_lanes))
2343				rc = msm_dp_ctrl_link_rate_down_shift(ctrl);
2344			else
2345				rc = msm_dp_ctrl_link_lane_down_shift(ctrl);
2346
2347			if (rc < 0) {
2348				/* end with failure */
2349				break; /* lane == 1 already */
2350			}
2351
2352			/* stop link training before start re training  */
2353			msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX);
2354		}
2355
2356		rc = msm_dp_ctrl_reinitialize_mainlink(ctrl);
2357		if (rc) {
2358			DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc);
2359			break;
2360		}
2361	}
2362
2363	if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN)
2364		return rc;
2365
2366	if (rc == 0) {  /* link train successfully */
2367		/*
2368		 * do not stop train pattern here
2369		 * stop link training at on_stream
2370		 * to pass compliance test
2371		 */
2372	} else  {
2373		/*
2374		 * link training failed
2375		 * end txing train pattern here
2376		 */
2377		msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX);
2378
2379		msm_dp_ctrl_deinitialize_mainlink(ctrl);
2380		rc = -ECONNRESET;
2381	}
2382
2383	return rc;
2384}
2385
2386static int msm_dp_ctrl_link_retrain(struct msm_dp_ctrl_private *ctrl)
2387{
2388	int training_step = DP_TRAINING_NONE;
2389
2390	return msm_dp_ctrl_setup_main_link(ctrl, &training_step);
2391}
2392
2393static void msm_dp_ctrl_config_msa(struct msm_dp_ctrl_private *ctrl,
2394			       u32 rate, u32 stream_rate_khz,
2395			       bool is_ycbcr_420)
2396{
2397	u32 pixel_m, pixel_n;
2398	u32 mvid, nvid, pixel_div, dispcc_input_rate;
2399	u32 const nvid_fixed = DP_LINK_CONSTANT_N_VALUE;
2400	u32 const link_rate_hbr2 = 540000;
2401	u32 const link_rate_hbr3 = 810000;
2402	unsigned long den, num;
2403
2404	switch (rate) {
2405	case link_rate_hbr3:
2406		pixel_div = 6;
2407		break;
2408	case link_rate_hbr2:
2409		pixel_div = 4;
2410		break;
2411	case 162000:
2412	case 270000:
2413		pixel_div = 2;
2414		break;
2415	default:
2416		/*
2417		 * This cannot be reached but the compiler is not able to know
2418		 * that statically so return early to avoid a possibly invalid
2419		 * division.
2420		 */
2421		DRM_ERROR("Invalid pixel mux divider\n");
2422		return;
2423	}
2424
2425	dispcc_input_rate = (rate * 10) / pixel_div;
2426
2427	rational_best_approximation(dispcc_input_rate, stream_rate_khz,
2428			(unsigned long)(1 << 16) - 1,
2429			(unsigned long)(1 << 16) - 1, &den, &num);
2430
2431	den = ~(den - num);
2432	den = den & 0xFFFF;
2433	pixel_m = num;
2434	pixel_n = den;
2435
2436	mvid = (pixel_m & 0xFFFF) * 5;
2437	nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
2438
2439	if (nvid < nvid_fixed) {
2440		u32 temp;
2441
2442		temp = (nvid_fixed / nvid) * nvid;
2443		mvid = (nvid_fixed / nvid) * mvid;
2444		nvid = temp;
2445	}
2446
2447	if (is_ycbcr_420)
2448		mvid /= 2;
2449
2450	if (link_rate_hbr2 == rate)
2451		nvid *= 2;
2452
2453	if (link_rate_hbr3 == rate)
2454		nvid *= 3;
2455
2456	drm_dbg_dp(ctrl->drm_dev, "mvid=0x%x, nvid=0x%x\n", mvid, nvid);
2457	msm_dp_write_link(ctrl, REG_DP_SOFTWARE_MVID, mvid);
2458	msm_dp_write_link(ctrl, REG_DP_SOFTWARE_NVID, nvid);
2459}
2460
2461int msm_dp_ctrl_on_stream(struct msm_dp_ctrl *msm_dp_ctrl, bool force_link_train)
2462{
2463	int ret = 0;
2464	bool mainlink_ready = false;
2465	struct msm_dp_ctrl_private *ctrl;
2466	unsigned long pixel_rate;
2467	unsigned long pixel_rate_orig;
2468
2469	if (!msm_dp_ctrl)
2470		return -EINVAL;
2471
2472	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2473
2474	pixel_rate = pixel_rate_orig = ctrl->panel->msm_dp_mode.drm_mode.clock;
2475
2476	if (msm_dp_ctrl->wide_bus_en || ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420)
2477		pixel_rate >>= 1;
2478
2479	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
2480		ctrl->link->link_params.rate,
2481		ctrl->link->link_params.num_lanes, pixel_rate);
2482
2483	drm_dbg_dp(ctrl->drm_dev,
2484		"core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
2485		ctrl->core_clks_on, ctrl->link_clks_on, ctrl->stream_clks_on);
2486
2487	if (!ctrl->link_clks_on) { /* link clk is off */
2488		ret = msm_dp_ctrl_enable_mainlink_clocks(ctrl);
2489		if (ret) {
2490			DRM_ERROR("Failed to start link clocks. ret=%d\n", ret);
2491			goto end;
2492		}
2493	}
2494
2495	ret = clk_set_rate(ctrl->pixel_clk, pixel_rate * 1000);
2496	if (ret) {
2497		DRM_ERROR("Failed to set pixel clock rate. ret=%d\n", ret);
2498		goto end;
2499	}
2500
2501	if (ctrl->stream_clks_on) {
2502		drm_dbg_dp(ctrl->drm_dev, "pixel clks already enabled\n");
2503	} else {
2504		ret = clk_prepare_enable(ctrl->pixel_clk);
2505		if (ret) {
2506			DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
2507			goto end;
2508		}
2509		ctrl->stream_clks_on = true;
2510	}
2511
2512	if (force_link_train || !msm_dp_ctrl_channel_eq_ok(ctrl))
2513		msm_dp_ctrl_link_retrain(ctrl);
2514
2515	/* stop txing train pattern to end link training */
2516	msm_dp_ctrl_clear_training_pattern(ctrl, DP_PHY_DPRX);
2517
2518	/*
2519	 * Set up transfer unit values and set controller state to send
2520	 * video.
2521	 */
2522	reinit_completion(&ctrl->video_comp);
2523
2524	msm_dp_ctrl_configure_source_params(ctrl);
2525
2526	msm_dp_ctrl_config_msa(ctrl,
2527		ctrl->link->link_params.rate,
2528		pixel_rate_orig,
2529		ctrl->panel->msm_dp_mode.out_fmt_is_yuv_420);
2530
2531	msm_dp_panel_clear_dsc_dto(ctrl->panel);
2532
2533	msm_dp_ctrl_setup_tr_unit(ctrl);
2534
2535	msm_dp_write_link(ctrl, REG_DP_STATE_CTRL, DP_STATE_CTRL_SEND_VIDEO);
2536
2537	ret = msm_dp_ctrl_wait4video_ready(ctrl);
2538	if (ret)
2539		return ret;
2540
2541	mainlink_ready = msm_dp_ctrl_mainlink_ready(ctrl);
2542	drm_dbg_dp(ctrl->drm_dev,
2543		"mainlink %s\n", mainlink_ready ? "READY" : "NOT READY");
2544
2545end:
2546	return ret;
2547}
2548
2549void msm_dp_ctrl_off_link_stream(struct msm_dp_ctrl *msm_dp_ctrl)
2550{
2551	struct msm_dp_ctrl_private *ctrl;
2552	struct phy *phy;
2553
2554	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2555	phy = ctrl->phy;
2556
2557	msm_dp_panel_disable_vsc_sdp(ctrl->panel);
2558
2559	/* set dongle to D3 (power off) mode */
2560	msm_dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
2561
2562	msm_dp_ctrl_mainlink_disable(ctrl);
2563
2564	if (ctrl->stream_clks_on) {
2565		clk_disable_unprepare(ctrl->pixel_clk);
2566		ctrl->stream_clks_on = false;
2567	}
2568
2569	dev_pm_opp_set_rate(ctrl->dev, 0);
2570	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
2571
2572	phy_power_off(phy);
2573
2574	/* aux channel down, reinit phy */
2575	phy_exit(phy);
2576	phy_init(phy);
2577
2578	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
2579			phy, phy->init_count, phy->power_count);
2580}
2581
2582void msm_dp_ctrl_off_link(struct msm_dp_ctrl *msm_dp_ctrl)
2583{
2584	struct msm_dp_ctrl_private *ctrl;
2585	struct phy *phy;
2586
2587	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2588	phy = ctrl->phy;
2589
2590	msm_dp_ctrl_mainlink_disable(ctrl);
2591
2592	dev_pm_opp_set_rate(ctrl->dev, 0);
2593	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
2594
2595	DRM_DEBUG_DP("Before, phy=%p init_count=%d power_on=%d\n",
2596		phy, phy->init_count, phy->power_count);
2597
2598	phy_power_off(phy);
2599
2600	DRM_DEBUG_DP("After, phy=%p init_count=%d power_on=%d\n",
2601		phy, phy->init_count, phy->power_count);
2602}
2603
2604void msm_dp_ctrl_off(struct msm_dp_ctrl *msm_dp_ctrl)
2605{
2606	struct msm_dp_ctrl_private *ctrl;
2607	struct phy *phy;
2608
2609	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2610	phy = ctrl->phy;
2611
2612	msm_dp_panel_disable_vsc_sdp(ctrl->panel);
2613
2614	msm_dp_ctrl_mainlink_disable(ctrl);
2615
2616	msm_dp_ctrl_reset(&ctrl->msm_dp_ctrl);
2617
2618	if (ctrl->stream_clks_on) {
2619		clk_disable_unprepare(ctrl->pixel_clk);
2620		ctrl->stream_clks_on = false;
2621	}
2622
2623	dev_pm_opp_set_rate(ctrl->dev, 0);
2624	msm_dp_ctrl_link_clk_disable(&ctrl->msm_dp_ctrl);
2625
2626	phy_power_off(phy);
2627	drm_dbg_dp(ctrl->drm_dev, "phy=%p init=%d power_on=%d\n",
2628			phy, phy->init_count, phy->power_count);
2629}
2630
2631irqreturn_t msm_dp_ctrl_isr(struct msm_dp_ctrl *msm_dp_ctrl)
2632{
2633	struct msm_dp_ctrl_private *ctrl;
2634	u32 isr;
2635	irqreturn_t ret = IRQ_NONE;
2636
2637	if (!msm_dp_ctrl)
2638		return IRQ_NONE;
2639
2640	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2641
2642	if (ctrl->panel->psr_cap.version) {
2643		isr = msm_dp_ctrl_get_psr_interrupt(ctrl);
2644
2645		if (isr)
2646			complete(&ctrl->psr_op_comp);
2647
2648		if (isr & PSR_EXIT_INT)
2649			drm_dbg_dp(ctrl->drm_dev, "PSR exit done\n");
2650
2651		if (isr & PSR_UPDATE_INT)
2652			drm_dbg_dp(ctrl->drm_dev, "PSR frame update done\n");
2653
2654		if (isr & PSR_CAPTURE_INT)
2655			drm_dbg_dp(ctrl->drm_dev, "PSR frame capture done\n");
2656	}
2657
2658	isr = msm_dp_ctrl_get_interrupt(ctrl);
2659
2660	if (isr & DP_CTRL_INTR_READY_FOR_VIDEO) {
2661		drm_dbg_dp(ctrl->drm_dev, "dp_video_ready\n");
2662		complete(&ctrl->video_comp);
2663		ret = IRQ_HANDLED;
2664	}
2665
2666	if (isr & DP_CTRL_INTR_IDLE_PATTERN_SENT) {
2667		drm_dbg_dp(ctrl->drm_dev, "idle_patterns_sent\n");
2668		complete(&ctrl->idle_comp);
2669		ret = IRQ_HANDLED;
2670	}
2671
2672	/* DP aux isr */
2673	isr = msm_dp_ctrl_get_aux_interrupt(ctrl);
2674	if (isr)
2675		ret |= msm_dp_aux_isr(ctrl->aux, isr);
2676
2677	return ret;
2678}
2679
2680static const char *core_clks[] = {
2681	"core_iface",
2682	"core_aux",
2683};
2684
2685static const char *ctrl_clks[] = {
2686	"ctrl_link",
2687	"ctrl_link_iface",
2688};
2689
2690static int msm_dp_ctrl_clk_init(struct msm_dp_ctrl *msm_dp_ctrl)
2691{
2692	struct msm_dp_ctrl_private *ctrl;
2693	struct device *dev;
2694	int i, rc;
2695
2696	ctrl = container_of(msm_dp_ctrl, struct msm_dp_ctrl_private, msm_dp_ctrl);
2697	dev = ctrl->dev;
2698
2699	ctrl->num_core_clks = ARRAY_SIZE(core_clks);
2700	ctrl->core_clks = devm_kcalloc(dev, ctrl->num_core_clks, sizeof(*ctrl->core_clks), GFP_KERNEL);
2701	if (!ctrl->core_clks)
2702		return -ENOMEM;
2703
2704	for (i = 0; i < ctrl->num_core_clks; i++)
2705		ctrl->core_clks[i].id = core_clks[i];
2706
2707	rc = devm_clk_bulk_get(dev, ctrl->num_core_clks, ctrl->core_clks);
2708	if (rc)
2709		return rc;
2710
2711	ctrl->num_link_clks = ARRAY_SIZE(ctrl_clks);
2712	ctrl->link_clks = devm_kcalloc(dev, ctrl->num_link_clks, sizeof(*ctrl->link_clks), GFP_KERNEL);
2713	if (!ctrl->link_clks)
2714		return -ENOMEM;
2715
2716	for (i = 0; i < ctrl->num_link_clks; i++)
2717		ctrl->link_clks[i].id = ctrl_clks[i];
2718
2719	rc = devm_clk_bulk_get(dev, ctrl->num_link_clks, ctrl->link_clks);
2720	if (rc)
2721		return rc;
2722
2723	ctrl->pixel_clk = devm_clk_get(dev, "stream_pixel");
2724	if (IS_ERR(ctrl->pixel_clk))
2725		return PTR_ERR(ctrl->pixel_clk);
2726
2727	return 0;
2728}
2729
2730struct msm_dp_ctrl *msm_dp_ctrl_get(struct device *dev, struct msm_dp_link *link,
2731			struct msm_dp_panel *panel,	struct drm_dp_aux *aux,
2732			struct phy *phy,
2733			void __iomem *ahb_base,
2734			void __iomem *link_base)
2735{
2736	struct msm_dp_ctrl_private *ctrl;
2737	int ret;
2738
2739	if (!dev || !panel || !aux || !link) {
2740		DRM_ERROR("invalid input\n");
2741		return ERR_PTR(-EINVAL);
2742	}
2743
2744	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
2745	if (!ctrl) {
2746		DRM_ERROR("Mem allocation failure\n");
2747		return ERR_PTR(-ENOMEM);
2748	}
2749
2750	ret = devm_pm_opp_set_clkname(dev, "ctrl_link");
2751	if (ret) {
2752		dev_err(dev, "invalid DP OPP table in device tree\n");
2753		/* caller do PTR_ERR(opp_table) */
2754		return (struct msm_dp_ctrl *)ERR_PTR(ret);
2755	}
2756
2757	/* OPP table is optional */
2758	ret = devm_pm_opp_of_add_table(dev);
2759	if (ret)
2760		dev_err(dev, "failed to add DP OPP table\n");
2761
2762	init_completion(&ctrl->idle_comp);
2763	init_completion(&ctrl->psr_op_comp);
2764	init_completion(&ctrl->video_comp);
2765
2766	/* in parameters */
2767	ctrl->panel    = panel;
2768	ctrl->aux      = aux;
2769	ctrl->link     = link;
2770	ctrl->dev      = dev;
2771	ctrl->phy      = phy;
2772	ctrl->ahb_base = ahb_base;
2773	ctrl->link_base = link_base;
2774
2775	ret = msm_dp_ctrl_clk_init(&ctrl->msm_dp_ctrl);
2776	if (ret) {
2777		dev_err(dev, "failed to init clocks\n");
2778		return ERR_PTR(ret);
2779	}
2780
2781	return &ctrl->msm_dp_ctrl;
2782}
~/ Read-only file preview.