Skip to content

Commit 94ee73e

Browse files
Baihan Lilumag
authored andcommitted
drm/hisilicon/hibmc: add dp hw moduel in hibmc driver
Build a dp level that hibmc driver can enable dp by calling their functions. Signed-off-by: Baihan Li <[email protected]> Signed-off-by: Yongbang Shi <[email protected]> Reviewed-by: Dmitry Baryshkov <[email protected]> Reviewed-by: Tian Tao <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent 54063d8 commit 94ee73e

File tree

5 files changed

+309
-1
lines changed

5 files changed

+309
-1
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_i2c.o \
3-
dp/dp_aux.o dp/dp_link.o
3+
dp/dp_aux.o dp/dp_link.o dp/dp_hw.o
44

55
obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/* Copyright (c) 2024 Hisilicon Limited. */
3+
4+
#ifndef DP_CONFIG_H
5+
#define DP_CONFIG_H
6+
7+
#define HIBMC_DP_BPP 24
8+
#define HIBMC_DP_SYMBOL_PER_FCLK 4
9+
#define HIBMC_DP_MSA1 0x20
10+
#define HIBMC_DP_MSA2 0x845c00
11+
#define HIBMC_DP_OFFSET 0x1e0000
12+
#define HIBMC_DP_HDCP 0x2
13+
#define HIBMC_DP_INT_RST 0xffff
14+
#define HIBMC_DP_DPTX_RST 0x3ff
15+
#define HIBMC_DP_CLK_EN 0x7
16+
#define HIBMC_DP_SYNC_EN_MASK 0x3
17+
#define HIBMC_DP_LINK_RATE_CAL 27
18+
19+
#endif
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
// Copyright (c) 2024 Hisilicon Limited.
3+
4+
#include <linux/io.h>
5+
#include <linux/delay.h>
6+
#include "dp_config.h"
7+
#include "dp_comm.h"
8+
#include "dp_reg.h"
9+
#include "dp_hw.h"
10+
11+
static void hibmc_dp_set_tu(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
12+
{
13+
u32 tu_symbol_frac_size;
14+
u32 tu_symbol_size;
15+
u32 rate_ks;
16+
u8 lane_num;
17+
u32 value;
18+
u32 bpp;
19+
20+
lane_num = dp->link.cap.lanes;
21+
if (lane_num == 0) {
22+
drm_err(dp->dev, "set tu failed, lane num cannot be 0!\n");
23+
return;
24+
}
25+
26+
bpp = HIBMC_DP_BPP;
27+
rate_ks = dp->link.cap.link_rate * HIBMC_DP_LINK_RATE_CAL;
28+
value = (mode->clock * bpp * 5) / (61 * lane_num * rate_ks);
29+
30+
if (value % 10 == 9) { /* 9 carry */
31+
tu_symbol_size = value / 10 + 1;
32+
tu_symbol_frac_size = 0;
33+
} else {
34+
tu_symbol_size = value / 10;
35+
tu_symbol_frac_size = value % 10 + 1;
36+
}
37+
38+
drm_dbg_dp(dp->dev, "tu value: %u.%u value: %u\n",
39+
tu_symbol_size, tu_symbol_frac_size, value);
40+
41+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_PACKET,
42+
HIBMC_DP_CFG_STREAM_TU_SYMBOL_SIZE, tu_symbol_size);
43+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_PACKET,
44+
HIBMC_DP_CFG_STREAM_TU_SYMBOL_FRAC_SIZE, tu_symbol_frac_size);
45+
}
46+
47+
static void hibmc_dp_set_sst(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
48+
{
49+
u32 hblank_size;
50+
u32 htotal_size;
51+
u32 htotal_int;
52+
u32 hblank_int;
53+
u32 fclk; /* flink_clock */
54+
55+
fclk = dp->link.cap.link_rate * HIBMC_DP_LINK_RATE_CAL;
56+
57+
/* Considering the effect of spread spectrum, the value may be deviated.
58+
* The coefficient (0.9947) is used to offset the deviation.
59+
*/
60+
htotal_int = mode->htotal * 9947 / 10000;
61+
htotal_size = htotal_int * fclk / (HIBMC_DP_SYMBOL_PER_FCLK * (mode->clock / 1000));
62+
63+
hblank_int = mode->htotal - mode->hdisplay - mode->hdisplay * 53 / 10000;
64+
hblank_size = hblank_int * fclk * 9947 /
65+
(mode->clock * 10 * HIBMC_DP_SYMBOL_PER_FCLK);
66+
67+
drm_dbg_dp(dp->dev, "h_active %u v_active %u htotal_size %u hblank_size %u",
68+
mode->hdisplay, mode->vdisplay, htotal_size, hblank_size);
69+
drm_dbg_dp(dp->dev, "flink_clock %u pixel_clock %d", fclk, mode->clock / 1000);
70+
71+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_HORIZONTAL_SIZE,
72+
HIBMC_DP_CFG_STREAM_HTOTAL_SIZE, htotal_size);
73+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_HORIZONTAL_SIZE,
74+
HIBMC_DP_CFG_STREAM_HBLANK_SIZE, hblank_size);
75+
}
76+
77+
static void hibmc_dp_link_cfg(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
78+
{
79+
u32 timing_delay;
80+
u32 vblank;
81+
u32 hstart;
82+
u32 vstart;
83+
84+
vblank = mode->vtotal - mode->vdisplay;
85+
timing_delay = mode->htotal - mode->hsync_start;
86+
hstart = mode->htotal - mode->hsync_start;
87+
vstart = mode->vtotal - mode->vsync_start;
88+
89+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG0,
90+
HIBMC_DP_CFG_TIMING_GEN0_HBLANK, mode->htotal - mode->hdisplay);
91+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG0,
92+
HIBMC_DP_CFG_TIMING_GEN0_HACTIVE, mode->hdisplay);
93+
94+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG2,
95+
HIBMC_DP_CFG_TIMING_GEN0_VBLANK, vblank);
96+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG2,
97+
HIBMC_DP_CFG_TIMING_GEN0_VACTIVE, mode->vdisplay);
98+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG3,
99+
HIBMC_DP_CFG_TIMING_GEN0_VFRONT_PORCH,
100+
mode->vsync_start - mode->vdisplay);
101+
102+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG0,
103+
HIBMC_DP_CFG_STREAM_HACTIVE, mode->hdisplay);
104+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG0,
105+
HIBMC_DP_CFG_STREAM_HBLANK, mode->htotal - mode->hdisplay);
106+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG2,
107+
HIBMC_DP_CFG_STREAM_HSYNC_WIDTH,
108+
mode->hsync_end - mode->hsync_start);
109+
110+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG1,
111+
HIBMC_DP_CFG_STREAM_VACTIVE, mode->vdisplay);
112+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG1,
113+
HIBMC_DP_CFG_STREAM_VBLANK, vblank);
114+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG3,
115+
HIBMC_DP_CFG_STREAM_VFRONT_PORCH,
116+
mode->vsync_start - mode->vdisplay);
117+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG3,
118+
HIBMC_DP_CFG_STREAM_VSYNC_WIDTH,
119+
mode->vsync_end - mode->vsync_start);
120+
121+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_MSA0,
122+
HIBMC_DP_CFG_STREAM_VSTART, vstart);
123+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_MSA0,
124+
HIBMC_DP_CFG_STREAM_HSTART, hstart);
125+
126+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_VSYNC_POLARITY,
127+
mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 : 0);
128+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_HSYNC_POLARITY,
129+
mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 : 0);
130+
131+
/* MSA mic 0 and 1 */
132+
writel(HIBMC_DP_MSA1, dp->base + HIBMC_DP_VIDEO_MSA1);
133+
writel(HIBMC_DP_MSA2, dp->base + HIBMC_DP_VIDEO_MSA2);
134+
135+
hibmc_dp_set_tu(dp, mode);
136+
137+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_RGB_ENABLE, 0x1);
138+
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_VIDEO_MAPPING, 0);
139+
140+
/* divide 2: up even */
141+
if (timing_delay % 2)
142+
timing_delay++;
143+
144+
hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_MODEL_CTRL,
145+
HIBMC_DP_CFG_PIXEL_NUM_TIMING_MODE_SEL1, timing_delay);
146+
147+
hibmc_dp_set_sst(dp, mode);
148+
}
149+
150+
int hibmc_dp_hw_init(struct hibmc_dp *dp)
151+
{
152+
struct drm_device *drm_dev = dp->drm_dev;
153+
struct hibmc_dp_dev *dp_dev;
154+
155+
dp_dev = devm_kzalloc(drm_dev->dev, sizeof(struct hibmc_dp_dev), GFP_KERNEL);
156+
if (!dp_dev)
157+
return -ENOMEM;
158+
159+
mutex_init(&dp_dev->lock);
160+
161+
dp->dp_dev = dp_dev;
162+
163+
dp_dev->dev = drm_dev;
164+
dp_dev->base = dp->mmio + HIBMC_DP_OFFSET;
165+
166+
hibmc_dp_aux_init(dp_dev);
167+
168+
dp_dev->link.cap.lanes = 0x2;
169+
dp_dev->link.cap.link_rate = DP_LINK_BW_2_7;
170+
171+
/* hdcp data */
172+
writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
173+
/* int init */
174+
writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
175+
writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
176+
/* rst */
177+
writel(HIBMC_DP_DPTX_RST, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
178+
/* clock enable */
179+
writel(HIBMC_DP_CLK_EN, dp_dev->base + HIBMC_DP_DPTX_CLK_CTRL);
180+
181+
return 0;
182+
}
183+
184+
void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable)
185+
{
186+
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
187+
188+
if (enable) {
189+
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, BIT(0), 0x1);
190+
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
191+
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0, BIT(10), 0x1);
192+
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
193+
} else {
194+
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0, BIT(10), 0);
195+
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
196+
hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, BIT(0), 0);
197+
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
198+
}
199+
200+
msleep(50);
201+
}
202+
203+
int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode)
204+
{
205+
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
206+
int ret;
207+
208+
if (!dp_dev->link.status.channel_equalized) {
209+
ret = hibmc_dp_link_training(dp_dev);
210+
if (ret) {
211+
drm_err(dp->drm_dev, "dp link training failed, ret: %d\n", ret);
212+
return ret;
213+
}
214+
}
215+
216+
hibmc_dp_display_en(dp, false);
217+
hibmc_dp_link_cfg(dp_dev, mode);
218+
219+
return 0;
220+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/* Copyright (c) 2024 Hisilicon Limited. */
3+
4+
#ifndef DP_KAPI_H
5+
#define DP_KAPI_H
6+
7+
#include <linux/types.h>
8+
#include <linux/delay.h>
9+
#include <drm/drm_device.h>
10+
#include <drm/drm_encoder.h>
11+
#include <drm/drm_connector.h>
12+
#include <drm/drm_print.h>
13+
14+
struct hibmc_dp_dev;
15+
16+
struct hibmc_dp {
17+
struct hibmc_dp_dev *dp_dev;
18+
struct drm_device *drm_dev;
19+
struct drm_encoder encoder;
20+
struct drm_connector connector;
21+
void __iomem *mmio;
22+
};
23+
24+
int hibmc_dp_hw_init(struct hibmc_dp *dp);
25+
int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode);
26+
void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable);
27+
28+
#endif

drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,26 @@
1414
#define HIBMC_DP_AUX_STATUS 0x78
1515
#define HIBMC_DP_PHYIF_CTRL0 0xa0
1616
#define HIBMC_DP_VIDEO_CTRL 0x100
17+
#define HIBMC_DP_VIDEO_CONFIG0 0x104
18+
#define HIBMC_DP_VIDEO_CONFIG1 0x108
19+
#define HIBMC_DP_VIDEO_CONFIG2 0x10c
20+
#define HIBMC_DP_VIDEO_CONFIG3 0x110
21+
#define HIBMC_DP_VIDEO_PACKET 0x114
22+
#define HIBMC_DP_VIDEO_MSA0 0x118
23+
#define HIBMC_DP_VIDEO_MSA1 0x11c
24+
#define HIBMC_DP_VIDEO_MSA2 0x120
25+
#define HIBMC_DP_VIDEO_HORIZONTAL_SIZE 0X124
26+
#define HIBMC_DP_TIMING_GEN_CONFIG0 0x26c
27+
#define HIBMC_DP_TIMING_GEN_CONFIG2 0x274
28+
#define HIBMC_DP_TIMING_GEN_CONFIG3 0x278
29+
#define HIBMC_DP_HDCP_CFG 0x600
1730
#define HIBMC_DP_DPTX_RST_CTRL 0x700
31+
#define HIBMC_DP_DPTX_CLK_CTRL 0x704
1832
#define HIBMC_DP_DPTX_GCTL0 0x708
33+
#define HIBMC_DP_INTR_ENABLE 0x720
34+
#define HIBMC_DP_INTR_ORIGINAL_STATUS 0x728
35+
#define HIBMC_DP_TIMING_MODEL_CTRL 0x884
36+
#define HIBMC_DP_TIMING_SYNC_CTRL 0xFF0
1937

2038
#define HIBMC_DP_CFG_AUX_SYNC_LEN_SEL BIT(1)
2139
#define HIBMC_DP_CFG_AUX_TIMER_TIMEOUT BIT(2)
@@ -31,5 +49,28 @@
3149
#define HIBMC_DP_CFG_AUX_STATUS GENMASK(11, 4)
3250
#define HIBMC_DP_CFG_SCRAMBLE_EN BIT(0)
3351
#define HIBMC_DP_CFG_PAT_SEL GENMASK(7, 4)
52+
#define HIBMC_DP_CFG_TIMING_GEN0_HACTIVE GENMASK(31, 16)
53+
#define HIBMC_DP_CFG_TIMING_GEN0_HBLANK GENMASK(15, 0)
54+
#define HIBMC_DP_CFG_TIMING_GEN0_VACTIVE GENMASK(31, 16)
55+
#define HIBMC_DP_CFG_TIMING_GEN0_VBLANK GENMASK(15, 0)
56+
#define HIBMC_DP_CFG_TIMING_GEN0_VFRONT_PORCH GENMASK(31, 16)
57+
#define HIBMC_DP_CFG_STREAM_HACTIVE GENMASK(31, 16)
58+
#define HIBMC_DP_CFG_STREAM_HBLANK GENMASK(15, 0)
59+
#define HIBMC_DP_CFG_STREAM_HSYNC_WIDTH GENMASK(15, 0)
60+
#define HIBMC_DP_CFG_STREAM_VACTIVE GENMASK(31, 16)
61+
#define HIBMC_DP_CFG_STREAM_VBLANK GENMASK(15, 0)
62+
#define HIBMC_DP_CFG_STREAM_VFRONT_PORCH GENMASK(31, 16)
63+
#define HIBMC_DP_CFG_STREAM_VSYNC_WIDTH GENMASK(15, 0)
64+
#define HIBMC_DP_CFG_STREAM_VSTART GENMASK(31, 16)
65+
#define HIBMC_DP_CFG_STREAM_HSTART GENMASK(15, 0)
66+
#define HIBMC_DP_CFG_STREAM_VSYNC_POLARITY BIT(8)
67+
#define HIBMC_DP_CFG_STREAM_HSYNC_POLARITY BIT(7)
68+
#define HIBMC_DP_CFG_STREAM_RGB_ENABLE BIT(1)
69+
#define HIBMC_DP_CFG_STREAM_VIDEO_MAPPING GENMASK(5, 2)
70+
#define HIBMC_DP_CFG_PIXEL_NUM_TIMING_MODE_SEL1 GENMASK(31, 16)
71+
#define HIBMC_DP_CFG_STREAM_TU_SYMBOL_SIZE GENMASK(5, 0)
72+
#define HIBMC_DP_CFG_STREAM_TU_SYMBOL_FRAC_SIZE GENMASK(9, 6)
73+
#define HIBMC_DP_CFG_STREAM_HTOTAL_SIZE GENMASK(31, 16)
74+
#define HIBMC_DP_CFG_STREAM_HBLANK_SIZE GENMASK(15, 0)
3475

3576
#endif

0 commit comments

Comments
 (0)