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 #include "dp_hw.h" 17 18 #define HIBMC_DP_LANE_NUM_MAX 2 19 20 struct hibmc_link_status { 21 bool clock_recovered; 22 bool channel_equalized; 23 }; 24 25 struct hibmc_link_cap { 26 u8 link_rate; 27 u8 lanes; 28 }; 29 30 struct hibmc_dp_link { 31 struct hibmc_link_status status; 32 u8 train_set[HIBMC_DP_LANE_NUM_MAX]; 33 struct hibmc_link_cap cap; 34 }; 35 36 struct hibmc_dp_dev { 37 struct drm_dp_aux *aux; 38 struct drm_device *dev; 39 void __iomem *base; 40 struct mutex lock; /* protects concurrent RW in hibmc_dp_reg_write_field() */ 41 struct hibmc_dp_link link; 42 u8 dpcd[DP_RECEIVER_CAP_SIZE]; 43 void __iomem *serdes_base; 44 }; 45 46 #define dp_field_modify(reg_value, mask, val) \ 47 do { \ 48 (reg_value) &= ~(mask); \ 49 (reg_value) |= FIELD_PREP(mask, val); \ 50 } while (0) \ 51 52 #define hibmc_dp_reg_write_field(dp, offset, mask, val) \ 53 do { \ 54 typeof(dp) _dp = dp; \ 55 typeof(_dp->base) addr = (_dp->base + (offset)); \ 56 mutex_lock(&_dp->lock); \ 57 u32 reg_value = readl(addr); \ 58 dp_field_modify(reg_value, mask, val); \ 59 writel(reg_value, addr); \ 60 mutex_unlock(&_dp->lock); \ 61 } while (0) 62 63 void hibmc_dp_aux_init(struct hibmc_dp *dp); 64 int hibmc_dp_link_training(struct hibmc_dp_dev *dp); 65 int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp); 66 int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp); 67 int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]); 68 69 #endif 70