xref: /linux/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1057e7797SBaihan Li /* SPDX-License-Identifier: GPL-2.0-or-later */
2057e7797SBaihan Li /* Copyright (c) 2024 Hisilicon Limited. */
3057e7797SBaihan Li 
4057e7797SBaihan Li #ifndef DP_COMM_H
5057e7797SBaihan Li #define DP_COMM_H
6057e7797SBaihan Li 
7057e7797SBaihan Li #include <linux/types.h>
8057e7797SBaihan Li #include <linux/bitops.h>
9057e7797SBaihan Li #include <linux/errno.h>
10057e7797SBaihan Li #include <linux/mutex.h>
11057e7797SBaihan Li #include <linux/kernel.h>
12057e7797SBaihan Li #include <linux/bitfield.h>
13057e7797SBaihan Li #include <linux/io.h>
14057e7797SBaihan Li #include <drm/display/drm_dp_helper.h>
15057e7797SBaihan Li 
16*1e7f3551SBaihan Li #include "dp_hw.h"
17*1e7f3551SBaihan Li 
1854063d86SBaihan Li #define HIBMC_DP_LANE_NUM_MAX 2
1954063d86SBaihan Li 
2054063d86SBaihan Li struct hibmc_link_status {
2154063d86SBaihan Li 	bool clock_recovered;
2254063d86SBaihan Li 	bool channel_equalized;
2354063d86SBaihan Li };
2454063d86SBaihan Li 
2554063d86SBaihan Li struct hibmc_link_cap {
2654063d86SBaihan Li 	u8 link_rate;
2754063d86SBaihan Li 	u8 lanes;
2854063d86SBaihan Li };
2954063d86SBaihan Li 
3054063d86SBaihan Li struct hibmc_dp_link {
3154063d86SBaihan Li 	struct hibmc_link_status status;
3254063d86SBaihan Li 	u8 train_set[HIBMC_DP_LANE_NUM_MAX];
3354063d86SBaihan Li 	struct hibmc_link_cap cap;
3454063d86SBaihan Li };
3554063d86SBaihan Li 
36057e7797SBaihan Li struct hibmc_dp_dev {
37*1e7f3551SBaihan Li 	struct drm_dp_aux *aux;
38057e7797SBaihan Li 	struct drm_device *dev;
39057e7797SBaihan Li 	void __iomem *base;
40057e7797SBaihan Li 	struct mutex lock; /* protects concurrent RW in hibmc_dp_reg_write_field() */
4154063d86SBaihan Li 	struct hibmc_dp_link link;
4254063d86SBaihan Li 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
439e736cd4SBaihan Li 	void __iomem *serdes_base;
44057e7797SBaihan Li };
45057e7797SBaihan Li 
46057e7797SBaihan Li #define dp_field_modify(reg_value, mask, val)				\
47057e7797SBaihan Li 	do {								\
48057e7797SBaihan Li 		(reg_value) &= ~(mask);					\
49057e7797SBaihan Li 		(reg_value) |= FIELD_PREP(mask, val);			\
50057e7797SBaihan Li 	} while (0)							\
51057e7797SBaihan Li 
52057e7797SBaihan Li #define hibmc_dp_reg_write_field(dp, offset, mask, val)			\
53057e7797SBaihan Li 	do {								\
54057e7797SBaihan Li 		typeof(dp) _dp = dp;					\
55057e7797SBaihan Li 		typeof(_dp->base) addr = (_dp->base + (offset));	\
56057e7797SBaihan Li 		mutex_lock(&_dp->lock);					\
57057e7797SBaihan Li 		u32 reg_value = readl(addr);				\
58057e7797SBaihan Li 		dp_field_modify(reg_value, mask, val);			\
59057e7797SBaihan Li 		writel(reg_value, addr);				\
60057e7797SBaihan Li 		mutex_unlock(&_dp->lock);				\
61057e7797SBaihan Li 	} while (0)
62057e7797SBaihan Li 
63*1e7f3551SBaihan Li void hibmc_dp_aux_init(struct hibmc_dp *dp);
6454063d86SBaihan Li int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
659e736cd4SBaihan Li int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp);
669e736cd4SBaihan Li int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp);
679e736cd4SBaihan Li int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]);
68057e7797SBaihan Li 
69057e7797SBaihan Li #endif
70