cdns-mhdp8546-core.h 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Cadence MHDP8546 DP bridge driver.
 *
 * Copyright (C) 2020 Cadence Design Systems, Inc.
 *
 * Author: Quentin Schulz <quentin.schulz@free-electrons.com>
 *         Swapnil Jakhade <sjakhade@cadence.com>
 */

#ifndef CDNS_MHDP8546_CORE_H
#define CDNS_MHDP8546_CORE_H

#include <linux/bits.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>

#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
#include <drm/drm_dp_helper.h>

struct clk;
struct device;
struct phy;

/* Register offsets */
#define CDNS_APB_CTRL				0x00000
#define CDNS_CPU_STALL				BIT(3)

#define CDNS_MAILBOX_FULL			0x00008
#define CDNS_MAILBOX_EMPTY			0x0000c
#define CDNS_MAILBOX_TX_DATA			0x00010
#define CDNS_MAILBOX_RX_DATA			0x00014
#define CDNS_KEEP_ALIVE				0x00018
#define CDNS_KEEP_ALIVE_MASK			GENMASK(7, 0)

#define CDNS_VER_L				0x0001C
#define CDNS_VER_H				0x00020
#define CDNS_LIB_L_ADDR				0x00024
#define CDNS_LIB_H_ADDR				0x00028

#define CDNS_MB_INT_MASK			0x00034
#define CDNS_MB_INT_STATUS			0x00038

#define CDNS_SW_CLK_L				0x0003c
#define CDNS_SW_CLK_H				0x00040

#define CDNS_SW_EVENT0				0x00044
#define CDNS_DPTX_HPD				BIT(0)

#define CDNS_SW_EVENT1				0x00048
#define CDNS_SW_EVENT2				0x0004c
#define CDNS_SW_EVENT3				0x00050

#define CDNS_APB_INT_MASK			0x0006C
#define CDNS_APB_INT_MASK_MAILBOX_INT		BIT(0)
#define CDNS_APB_INT_MASK_SW_EVENT_INT		BIT(1)

#define CDNS_APB_INT_STATUS			0x00070

#define CDNS_DPTX_CAR				0x00904
#define CDNS_VIF_CLK_EN				BIT(0)
#define CDNS_VIF_CLK_RSTN			BIT(1)

#define CDNS_SOURCE_VIDEO_IF(s)			(0x00b00 + ((s) * 0x20))
#define CDNS_BND_HSYNC2VSYNC(s)			(CDNS_SOURCE_VIDEO_IF(s) + \
						 0x00)
#define CDNS_IP_DTCT_WIN			GENMASK(11, 0)
#define CDNS_IP_DET_INTERLACE_FORMAT		BIT(12)
#define CDNS_IP_BYPASS_V_INTERFACE		BIT(13)

#define CDNS_HSYNC2VSYNC_POL_CTRL(s)		(CDNS_SOURCE_VIDEO_IF(s) + \
						 0x10)
#define CDNS_H2V_HSYNC_POL_ACTIVE_LOW		BIT(1)
#define CDNS_H2V_VSYNC_POL_ACTIVE_LOW		BIT(2)

#define CDNS_DPTX_PHY_CONFIG			0x02000
#define CDNS_PHY_TRAINING_EN			BIT(0)
#define CDNS_PHY_TRAINING_TYPE(x)		(((x) & GENMASK(3, 0)) << 1)
#define CDNS_PHY_SCRAMBLER_BYPASS		BIT(5)
#define CDNS_PHY_ENCODER_BYPASS			BIT(6)
#define CDNS_PHY_SKEW_BYPASS			BIT(7)
#define CDNS_PHY_TRAINING_AUTO			BIT(8)
#define CDNS_PHY_LANE0_SKEW(x)			(((x) & GENMASK(2, 0)) << 9)
#define CDNS_PHY_LANE1_SKEW(x)			(((x) & GENMASK(2, 0)) << 12)
#define CDNS_PHY_LANE2_SKEW(x)			(((x) & GENMASK(2, 0)) << 15)
#define CDNS_PHY_LANE3_SKEW(x)			(((x) & GENMASK(2, 0)) << 18)
#define CDNS_PHY_COMMON_CONFIG			(CDNS_PHY_LANE1_SKEW(1) | \
						CDNS_PHY_LANE2_SKEW(2) |  \
						CDNS_PHY_LANE3_SKEW(3))
#define CDNS_PHY_10BIT_EN			BIT(21)

#define CDNS_DP_FRAMER_GLOBAL_CONFIG		0x02200
#define CDNS_DP_NUM_LANES(x)			((x) - 1)
#define CDNS_DP_MST_EN				BIT(2)
#define CDNS_DP_FRAMER_EN			BIT(3)
#define CDNS_DP_RATE_GOVERNOR_EN		BIT(4)
#define CDNS_DP_NO_VIDEO_MODE			BIT(5)
#define CDNS_DP_DISABLE_PHY_RST			BIT(6)
#define CDNS_DP_WR_FAILING_EDGE_VSYNC		BIT(7)

#define CDNS_DP_FRAMER_TU			0x02208
#define CDNS_DP_FRAMER_TU_SIZE(x)		(((x) & GENMASK(6, 0)) << 8)
#define CDNS_DP_FRAMER_TU_VS(x)			((x) & GENMASK(5, 0))
#define CDNS_DP_FRAMER_TU_CNT_RST_EN		BIT(15)

#define CDNS_DP_MTPH_CONTROL			0x02264
#define CDNS_DP_MTPH_ECF_EN			BIT(0)
#define CDNS_DP_MTPH_ACT_EN			BIT(1)
#define CDNS_DP_MTPH_LVP_EN			BIT(2)

#define CDNS_DP_MTPH_STATUS			0x0226C
#define CDNS_DP_MTPH_ACT_STATUS			BIT(0)

#define CDNS_DP_LANE_EN				0x02300
#define CDNS_DP_LANE_EN_LANES(x)		GENMASK((x) - 1, 0)

#define CDNS_DP_ENHNCD				0x02304

#define CDNS_DPTX_STREAM(s)			(0x03000 + (s) * 0x80)
#define CDNS_DP_MSA_HORIZONTAL_0(s)		(CDNS_DPTX_STREAM(s) + 0x00)
#define CDNS_DP_MSAH0_H_TOTAL(x)		(x)
#define CDNS_DP_MSAH0_HSYNC_START(x)		((x) << 16)

#define CDNS_DP_MSA_HORIZONTAL_1(s)		(CDNS_DPTX_STREAM(s) + 0x04)
#define CDNS_DP_MSAH1_HSYNC_WIDTH(x)		(x)
#define CDNS_DP_MSAH1_HSYNC_POL_LOW		BIT(15)
#define CDNS_DP_MSAH1_HDISP_WIDTH(x)		((x) << 16)

#define CDNS_DP_MSA_VERTICAL_0(s)		(CDNS_DPTX_STREAM(s) + 0x08)
#define CDNS_DP_MSAV0_V_TOTAL(x)		(x)
#define CDNS_DP_MSAV0_VSYNC_START(x)		((x) << 16)

#define CDNS_DP_MSA_VERTICAL_1(s)		(CDNS_DPTX_STREAM(s) + 0x0c)
#define CDNS_DP_MSAV1_VSYNC_WIDTH(x)		(x)
#define CDNS_DP_MSAV1_VSYNC_POL_LOW		BIT(15)
#define CDNS_DP_MSAV1_VDISP_WIDTH(x)		((x) << 16)

#define CDNS_DP_MSA_MISC(s)			(CDNS_DPTX_STREAM(s) + 0x10)
#define CDNS_DP_STREAM_CONFIG(s)		(CDNS_DPTX_STREAM(s) + 0x14)
#define CDNS_DP_STREAM_CONFIG_2(s)		(CDNS_DPTX_STREAM(s) + 0x2c)
#define CDNS_DP_SC2_TU_VS_DIFF(x)		((x) << 8)

#define CDNS_DP_HORIZONTAL(s)			(CDNS_DPTX_STREAM(s) + 0x30)
#define CDNS_DP_H_HSYNC_WIDTH(x)		(x)
#define CDNS_DP_H_H_TOTAL(x)			((x) << 16)

#define CDNS_DP_VERTICAL_0(s)			(CDNS_DPTX_STREAM(s) + 0x34)
#define CDNS_DP_V0_VHEIGHT(x)			(x)
#define CDNS_DP_V0_VSTART(x)			((x) << 16)

#define CDNS_DP_VERTICAL_1(s)			(CDNS_DPTX_STREAM(s) + 0x38)
#define CDNS_DP_V1_VTOTAL(x)			(x)
#define CDNS_DP_V1_VTOTAL_EVEN			BIT(16)

#define CDNS_DP_MST_SLOT_ALLOCATE(s)		(CDNS_DPTX_STREAM(s) + 0x44)
#define CDNS_DP_S_ALLOC_START_SLOT(x)		(x)
#define CDNS_DP_S_ALLOC_END_SLOT(x)		((x) << 8)

#define CDNS_DP_RATE_GOVERNING(s)		(CDNS_DPTX_STREAM(s) + 0x48)
#define CDNS_DP_RG_TARG_AV_SLOTS_Y(x)		(x)
#define CDNS_DP_RG_TARG_AV_SLOTS_X(x)		((x) << 4)
#define CDNS_DP_RG_ENABLE			BIT(10)

#define CDNS_DP_FRAMER_PXL_REPR(s)		(CDNS_DPTX_STREAM(s) + 0x4c)
#define CDNS_DP_FRAMER_6_BPC			BIT(0)
#define CDNS_DP_FRAMER_8_BPC			BIT(1)
#define CDNS_DP_FRAMER_10_BPC			BIT(2)
#define CDNS_DP_FRAMER_12_BPC			BIT(3)
#define CDNS_DP_FRAMER_16_BPC			BIT(4)
#define CDNS_DP_FRAMER_PXL_FORMAT		0x8
#define CDNS_DP_FRAMER_RGB			BIT(0)
#define CDNS_DP_FRAMER_YCBCR444			BIT(1)
#define CDNS_DP_FRAMER_YCBCR422			BIT(2)
#define CDNS_DP_FRAMER_YCBCR420			BIT(3)
#define CDNS_DP_FRAMER_Y_ONLY			BIT(4)

#define CDNS_DP_FRAMER_SP(s)			(CDNS_DPTX_STREAM(s) + 0x50)
#define CDNS_DP_FRAMER_VSYNC_POL_LOW		BIT(0)
#define CDNS_DP_FRAMER_HSYNC_POL_LOW		BIT(1)
#define CDNS_DP_FRAMER_INTERLACE		BIT(2)

#define CDNS_DP_LINE_THRESH(s)			(CDNS_DPTX_STREAM(s) + 0x64)
#define CDNS_DP_ACTIVE_LINE_THRESH(x)		(x)

#define CDNS_DP_VB_ID(s)			(CDNS_DPTX_STREAM(s) + 0x68)
#define CDNS_DP_VB_ID_INTERLACED		BIT(2)
#define CDNS_DP_VB_ID_COMPRESSED		BIT(6)

#define CDNS_DP_FRONT_BACK_PORCH(s)		(CDNS_DPTX_STREAM(s) + 0x78)
#define CDNS_DP_BACK_PORCH(x)			(x)
#define CDNS_DP_FRONT_PORCH(x)			((x) << 16)

#define CDNS_DP_BYTE_COUNT(s)			(CDNS_DPTX_STREAM(s) + 0x7c)
#define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT	16

/* mailbox */
#define MAILBOX_RETRY_US			1000
#define MAILBOX_TIMEOUT_US			2000000

#define MB_OPCODE_ID				0
#define MB_MODULE_ID				1
#define MB_SIZE_MSB_ID				2
#define MB_SIZE_LSB_ID				3
#define MB_DATA_ID				4

#define MB_MODULE_ID_DP_TX			0x01
#define MB_MODULE_ID_HDCP_TX			0x07
#define MB_MODULE_ID_HDCP_RX			0x08
#define MB_MODULE_ID_HDCP_GENERAL		0x09
#define MB_MODULE_ID_GENERAL			0x0a

/* firmware and opcodes */
#define FW_NAME					"cadence/mhdp8546.bin"
#define CDNS_MHDP_IMEM				0x10000

#define GENERAL_MAIN_CONTROL			0x01
#define GENERAL_TEST_ECHO			0x02
#define GENERAL_BUS_SETTINGS			0x03
#define GENERAL_TEST_ACCESS			0x04
#define GENERAL_REGISTER_READ			0x07

#define DPTX_SET_POWER_MNG			0x00
#define DPTX_GET_EDID				0x02
#define DPTX_READ_DPCD				0x03
#define DPTX_WRITE_DPCD				0x04
#define DPTX_ENABLE_EVENT			0x05
#define DPTX_WRITE_REGISTER			0x06
#define DPTX_READ_REGISTER			0x07
#define DPTX_WRITE_FIELD			0x08
#define DPTX_READ_EVENT				0x0a
#define DPTX_GET_LAST_AUX_STAUS			0x0e
#define DPTX_HPD_STATE				0x11
#define DPTX_ADJUST_LT				0x12

#define FW_STANDBY				0
#define FW_ACTIVE				1

/* HPD */
#define DPTX_READ_EVENT_HPD_TO_HIGH             BIT(0)
#define DPTX_READ_EVENT_HPD_TO_LOW              BIT(1)
#define DPTX_READ_EVENT_HPD_PULSE               BIT(2)
#define DPTX_READ_EVENT_HPD_STATE               BIT(3)

/* general */
#define CDNS_DP_TRAINING_PATTERN_4		0x7

#define CDNS_KEEP_ALIVE_TIMEOUT			2000

#define CDNS_VOLT_SWING(x)			((x) & GENMASK(1, 0))
#define CDNS_FORCE_VOLT_SWING			BIT(2)

#define CDNS_PRE_EMPHASIS(x)			((x) & GENMASK(1, 0))
#define CDNS_FORCE_PRE_EMPHASIS			BIT(2)

#define CDNS_SUPPORT_TPS(x)			BIT((x) - 1)

#define CDNS_FAST_LINK_TRAINING			BIT(0)

#define CDNS_LANE_MAPPING_TYPE_C_LANE_0(x)	((x) & GENMASK(1, 0))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_1(x)	((x) & GENMASK(3, 2))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_2(x)	((x) & GENMASK(5, 4))
#define CDNS_LANE_MAPPING_TYPE_C_LANE_3(x)	((x) & GENMASK(7, 6))
#define CDNS_LANE_MAPPING_NORMAL		0xe4
#define CDNS_LANE_MAPPING_FLIPPED		0x1b

#define CDNS_DP_MAX_NUM_LANES			4
#define CDNS_DP_TEST_VSC_SDP			BIT(6) /* 1.3+ */
#define CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY	BIT(7)

#define CDNS_MHDP_MAX_STREAMS			4

#define DP_LINK_CAP_ENHANCED_FRAMING		BIT(0)

struct cdns_mhdp_link {
	unsigned char revision;
	unsigned int rate;
	unsigned int num_lanes;
	unsigned long capabilities;
};

struct cdns_mhdp_host {
	unsigned int link_rate;
	u8 lanes_cnt;
	u8 volt_swing;
	u8 pre_emphasis;
	u8 pattern_supp;
	u8 lane_mapping;
	bool fast_link;
	bool enhanced;
	bool scrambler;
	bool ssc;
};

struct cdns_mhdp_sink {
	unsigned int link_rate;
	u8 lanes_cnt;
	u8 pattern_supp;
	bool fast_link;
	bool enhanced;
	bool ssc;
};

struct cdns_mhdp_display_fmt {
	u32 color_format;
	u32 bpc;
	bool y_only;
};

/*
 * These enums present MHDP hw initialization state
 * Legal state transitions are:
 * MHDP_HW_READY <-> MHDP_HW_STOPPED
 */
enum mhdp_hw_state {
	MHDP_HW_READY = 1,	/* HW ready, FW active */
	MHDP_HW_STOPPED		/* Driver removal FW to be stopped */
};

struct cdns_mhdp_device;

struct mhdp_platform_ops {
	int (*init)(struct cdns_mhdp_device *mhdp);
	void (*exit)(struct cdns_mhdp_device *mhdp);
	void (*enable)(struct cdns_mhdp_device *mhdp);
	void (*disable)(struct cdns_mhdp_device *mhdp);
};

struct cdns_mhdp_bridge_state {
	struct drm_bridge_state base;
	struct drm_display_mode *current_mode;
};

struct cdns_mhdp_platform_info {
	const struct drm_bridge_timings *timings;
	const struct mhdp_platform_ops *ops;
};

#define to_cdns_mhdp_bridge_state(s) \
		container_of(s, struct cdns_mhdp_bridge_state, base)

struct cdns_mhdp_device {
	void __iomem *regs;
344
	void __iomem *j721e_regs;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

	struct device *dev;
	struct clk *clk;
	struct phy *phy;

	const struct cdns_mhdp_platform_info *info;

	/* This is to protect mailbox communications with the firmware */
	struct mutex mbox_mutex;

	/*
	 * "link_mutex" protects the access to all the link parameters
	 * including the link training process. Link training will be
	 * invoked both from threaded interrupt handler and from atomic
	 * callbacks when link_up is not set. So this mutex protects
	 * flags such as link_up, bridge_enabled, link.num_lanes,
	 * link.rate etc.
	 */
	struct mutex link_mutex;

	struct drm_connector connector;
	struct drm_bridge bridge;

	struct cdns_mhdp_link link;
	struct drm_dp_aux aux;

	struct cdns_mhdp_host host;
	struct cdns_mhdp_sink sink;
	struct cdns_mhdp_display_fmt display_fmt;
	u8 stream_id;

	bool link_up;
	bool plugged;

	/*
	 * "start_lock" protects the access to bridge_attached and
	 * hw_state data members that control the delayed firmware
	 * loading and attaching the bridge. They are accessed from
	 * both the DRM core and cdns_mhdp_fw_cb(). In most cases just
	 * protecting the data members is enough, but the irq mask
	 * setting needs to be protected when enabling the FW.
	 */
	spinlock_t start_lock;
	bool bridge_attached;
	bool bridge_enabled;
	enum mhdp_hw_state hw_state;
	wait_queue_head_t fw_load_wq;

	/* Work struct to schedule a uevent on link train failure */
	struct work_struct modeset_retry_work;
};

#define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
#define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge)

#endif