hc
2024-08-09 3d911568f3069a842249d4de3843d281d5af84d6
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
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __KIRIN_DRM_DSI_H__
#define __KIRIN_DRM_DSI_H__
 
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/of_graph.h>
#include <linux/iopoll.h>
#include <video/mipi_display.h>
#include <linux/gpio/consumer.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
 
#include <drm/drm_of.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_encoder_slave.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
 
#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
#define PHY_REF_CLK_RATE 19200000
#define PHY_REF_CLK_PERIOD_PS (1000000000 / (PHY_REF_CLK_RATE / 1000))
 
#define encoder_to_dsi(encoder) container_of(encoder, struct dw_dsi, encoder)
#define host_to_dsi(host) container_of(host, struct dw_dsi, host)
#define connector_to_dsi(connector)                                            \
   container_of(connector, struct dw_dsi, connector)
 
enum dsi_output_client { OUT_HDMI = 0, OUT_PANEL, OUT_MAX };
 
struct dsi_phy_range {
   u32 min_range_kHz;
   u32 max_range_kHz;
   u32 pll_vco_750M;
   u32 hstx_ckg_sel;
};
 
static const struct dsi_phy_range dphy_range_info[] = {
   {   46875,    62500,   1,    7 },
   {   62500,    93750,   0,    7 },
   {   93750,   125000,   1,    6 },
   {  125000,   187500,   0,    6 },
   {  187500,   250000,   1,    5 },
   {  250000,   375000,   0,    5 },
   {  375000,   500000,   1,    4 },
   {  500000,   750000,   0,    4 },
   {  750000,  1000000,   1,    0 },
   { 1000000,  1500000,   0,    0 }
};
 
struct dsi_hw_ctx {
   void __iomem *base;
   char __iomem *peri_crg_base;
 
   struct clk *pclk;
   struct clk *dss_dphy0_ref_clk;
   struct clk *dss_dphy1_ref_clk;
   struct clk *dss_dphy0_cfg_clk;
   struct clk *dss_dphy1_cfg_clk;
   struct clk *dss_pclk_dsi0_clk;
   struct clk *dss_pclk_dsi1_clk;
};
 
struct mipi_panel_info {
   u8 dsi_version;
   u8 vc;
   u8 lane_nums;
   u8 lane_nums_select_support;
   u8 color_mode;
   u32 dsi_bit_clk; /* clock lane(p/n) */
   u32 burst_mode;
   u32 max_tx_esc_clk;
   u8 non_continue_en;
 
   u32 dsi_bit_clk_val1;
   u32 dsi_bit_clk_val2;
   u32 dsi_bit_clk_val3;
   u32 dsi_bit_clk_val4;
   u32 dsi_bit_clk_val5;
   u32 dsi_bit_clk_upt;
   /*uint32_t dsi_pclk_rate;*/
 
   u32 hs_wr_to_time;
 
   /* dphy config parameter adjust*/
   u32 clk_post_adjust;
   u32 clk_pre_adjust;
   u32 clk_pre_delay_adjust;
   u32 clk_t_hs_exit_adjust;
   u32 clk_t_hs_trial_adjust;
   u32 clk_t_hs_prepare_adjust;
   int clk_t_lpx_adjust;
   u32 clk_t_hs_zero_adjust;
   u32 data_post_delay_adjust;
   int data_t_lpx_adjust;
   u32 data_t_hs_prepare_adjust;
   u32 data_t_hs_zero_adjust;
   u32 data_t_hs_trial_adjust;
   u32 rg_vrefsel_vcm_adjust;
 
   /*only for Chicago<3660> use*/
   u32 rg_vrefsel_vcm_clk_adjust;
   u32 rg_vrefsel_vcm_data_adjust;
};
 
struct mipi_phy_params {
   u32 clk_t_lpx;
   u32 clk_t_hs_prepare;
   u32 clk_t_hs_zero;
   u32 clk_t_hs_trial;
   u32 clk_t_wakeup;
   u32 data_t_lpx;
   u32 data_t_hs_prepare;
   u32 data_t_hs_zero;
   u32 data_t_hs_trial;
   u32 data_t_ta_go;
   u32 data_t_ta_get;
   u32 data_t_wakeup;
   u32 hstx_ckg_sel;
   u32 pll_fbd_div5f;
   u32 pll_fbd_div1f;
   u32 pll_fbd_2p;
   u32 pll_enbwt;
   u32 pll_fbd_p;
   u32 pll_fbd_s;
   u32 pll_pre_div1p;
   u32 pll_pre_p;
   u32 pll_vco_750M;
   u32 pll_lpf_rs;
   u32 pll_lpf_cs;
   u32 clk_division;
   /********for hikey620************/
   u32 clklp2hs_time;
   u32 clkhs2lp_time;
   u32 lp2hs_time;
   u32 hs2lp_time;
   u32 clk_to_data_delay;
   u32 data_to_clk_delay;
   u32 lane_byte_clk_kHz;
   /*****************/
 
   /****for hikey960*****/
   u64 lane_byte_clk;
 
   u32 clk_lane_lp2hs_time;
   u32 clk_lane_hs2lp_time;
   u32 data_lane_lp2hs_time;
   u32 data_lane_hs2lp_time;
   u32 clk2data_delay;
   u32 data2clk_delay;
 
   u32 clk_pre_delay;
   u32 clk_post_delay;
   u32 data_pre_delay;
   u32 data_post_delay;
   u32 phy_stop_wait_time;
   u32 rg_vrefsel_vcm;
 
   u32 rg_pll_enswc;
   u32 rg_pll_chp;
 
   u32 pll_register_override;        /*0x1E[0]*/
   u32 pll_power_down;            /*0x1E[1]*/
   u32 rg_band_sel;                /*0x1E[2]*/
   u32 rg_phase_gen_en;        /*0x1E[3]*/
   u32 reload_sel;                /*0x1E[4]*/
   u32 rg_pll_cp_p;                /*0x1E[7:5]*/
   u32 rg_pll_refsel;                /*0x16[1:0]*/
   u32 rg_pll_cp;                /*0x16[7:5]*/
   u32 load_command;
   /*********/
};
 
struct ldi_panel_info {
   u32 h_back_porch;
   u32 h_front_porch;
   u32 h_pulse_width;
 
   /*
    * note: vbp > 8 if used overlay compose,
    * also lcd vbp > 8 in lcd power on sequence
    */
   u32 v_back_porch;
   u32 v_front_porch;
   u32 v_pulse_width;
 
   u8 hsync_plr;
   u8 vsync_plr;
   u8 pixelclk_plr;
   u8 data_en_plr;
 
   /* for cabc */
   u8 dpi0_overlap_size;
   u8 dpi1_overlap_size;
};
 
struct dw_dsi_client {
   u32 lanes;
   u32 phy_clock; /* in kHz */
   enum mipi_dsi_pixel_format format;
   unsigned long mode_flags;
};
 
struct dw_dsi {
   struct drm_encoder encoder;
   struct drm_bridge *bridge;
   struct drm_panel *panel;
   struct mipi_dsi_host host;
   struct drm_connector connector; /* connector for panel */
   struct drm_display_mode cur_mode;
   struct dsi_hw_ctx *ctx;
   struct mipi_phy_params phy;
   struct mipi_panel_info mipi;
   struct ldi_panel_info ldi;
   u32 lanes;
   enum mipi_dsi_pixel_format format;
   unsigned long mode_flags;
   struct gpio_desc *gpio_mux;
   struct dw_dsi_client client[OUT_MAX];
   enum dsi_output_client cur_client;
   bool enable;
};
 
struct dsi_data {
   struct dw_dsi dsi;
   struct dsi_hw_ctx ctx;
};
 
enum kirin_dsi_version {
   KIRIN620_DSI = 0,
   KIRIN960_DSI
};
 
/* display controller init/cleanup ops */
struct kirin_dsi_ops {
   enum kirin_dsi_version version;
   int (*parse_dt)(struct platform_device *pdev, struct dw_dsi *dsi);
   int (*host_init)(struct device *dev, struct dw_dsi *dsi);
   void (*encoder_enable)(struct drm_encoder *encoder);
   enum drm_mode_status (*encoder_valid)(
       struct drm_encoder *encoder,
       const struct drm_display_mode *mode);
};
 
#ifdef CONFIG_DRM_HISI_KIRIN960
extern const struct kirin_dsi_ops kirin_dsi_960;
#endif
#ifdef CONFIG_DRM_HISI_KIRIN620
extern const struct kirin_dsi_ops kirin_dsi_620;
#endif
 
#endif /* __KIRIN_DRM_DSI_H__ */