xref: /linux/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h (revision e3610441d1fb47b1f00e4c38bdf333176e824729)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /* Copyright (c) 2024 Hisilicon Limited. */
3 
4 #ifndef DP_COMM_H
5 #define DP_COMM_H
6 
7 #include <linux/types.h>
8 #include <linux/bitops.h>
9 #include <linux/errno.h>
10 #include <linux/mutex.h>
11 #include <linux/kernel.h>
12 #include <linux/bitfield.h>
13 #include <linux/io.h>
14 #include <drm/display/drm_dp_helper.h>
15 
16 #define HIBMC_DP_LANE_NUM_MAX 2
17 
18 struct hibmc_link_status {
19 	bool clock_recovered;
20 	bool channel_equalized;
21 };
22 
23 struct hibmc_link_cap {
24 	u8 link_rate;
25 	u8 lanes;
26 };
27 
28 struct hibmc_dp_link {
29 	struct hibmc_link_status status;
30 	u8 train_set[HIBMC_DP_LANE_NUM_MAX];
31 	struct hibmc_link_cap cap;
32 };
33 
34 struct hibmc_dp_dev {
35 	struct drm_dp_aux aux;
36 	struct drm_device *dev;
37 	void __iomem *base;
38 	struct mutex lock; /* protects concurrent RW in hibmc_dp_reg_write_field() */
39 	struct hibmc_dp_link link;
40 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
41 };
42 
43 #define dp_field_modify(reg_value, mask, val)				\
44 	do {								\
45 		(reg_value) &= ~(mask);					\
46 		(reg_value) |= FIELD_PREP(mask, val);			\
47 	} while (0)							\
48 
49 #define hibmc_dp_reg_write_field(dp, offset, mask, val)			\
50 	do {								\
51 		typeof(dp) _dp = dp;					\
52 		typeof(_dp->base) addr = (_dp->base + (offset));	\
53 		mutex_lock(&_dp->lock);					\
54 		u32 reg_value = readl(addr);				\
55 		dp_field_modify(reg_value, mask, val);			\
56 		writel(reg_value, addr);				\
57 		mutex_unlock(&_dp->lock);				\
58 	} while (0)
59 
60 void hibmc_dp_aux_init(struct hibmc_dp_dev *dp);
61 int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
62 
63 #endif
64