1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (c) 2015 MediaTek Inc. |
4 | */ |
5 | |
6 | #include <linux/bitfield.h> |
7 | #include <linux/clk.h> |
8 | #include <linux/component.h> |
9 | #include <linux/iopoll.h> |
10 | #include <linux/irq.h> |
11 | #include <linux/of.h> |
12 | #include <linux/of_platform.h> |
13 | #include <linux/phy/phy.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/reset.h> |
16 | #include <linux/units.h> |
17 | |
18 | #include <video/mipi_display.h> |
19 | #include <video/videomode.h> |
20 | |
21 | #include <drm/drm_atomic_helper.h> |
22 | #include <drm/drm_bridge.h> |
23 | #include <drm/drm_bridge_connector.h> |
24 | #include <drm/drm_mipi_dsi.h> |
25 | #include <drm/drm_of.h> |
26 | #include <drm/drm_panel.h> |
27 | #include <drm/drm_print.h> |
28 | #include <drm/drm_probe_helper.h> |
29 | #include <drm/drm_simple_kms_helper.h> |
30 | |
31 | #include "mtk_disp_drv.h" |
32 | #include "mtk_drm_ddp_comp.h" |
33 | #include "mtk_drm_drv.h" |
34 | |
35 | #define DSI_START 0x00 |
36 | |
37 | #define DSI_INTEN 0x08 |
38 | |
39 | #define DSI_INTSTA 0x0c |
40 | #define LPRX_RD_RDY_INT_FLAG BIT(0) |
41 | #define CMD_DONE_INT_FLAG BIT(1) |
42 | #define TE_RDY_INT_FLAG BIT(2) |
43 | #define VM_DONE_INT_FLAG BIT(3) |
44 | #define EXT_TE_RDY_INT_FLAG BIT(4) |
45 | #define DSI_BUSY BIT(31) |
46 | |
47 | #define DSI_CON_CTRL 0x10 |
48 | #define DSI_RESET BIT(0) |
49 | #define DSI_EN BIT(1) |
50 | #define DPHY_RESET BIT(2) |
51 | |
52 | #define DSI_MODE_CTRL 0x14 |
53 | #define MODE (3) |
54 | #define CMD_MODE 0 |
55 | #define SYNC_PULSE_MODE 1 |
56 | #define SYNC_EVENT_MODE 2 |
57 | #define BURST_MODE 3 |
58 | #define FRM_MODE BIT(16) |
59 | #define MIX_MODE BIT(17) |
60 | |
61 | #define DSI_TXRX_CTRL 0x18 |
62 | #define VC_NUM BIT(1) |
63 | #define LANE_NUM GENMASK(5, 2) |
64 | #define DIS_EOT BIT(6) |
65 | #define NULL_EN BIT(7) |
66 | #define TE_FREERUN BIT(8) |
67 | #define EXT_TE_EN BIT(9) |
68 | #define EXT_TE_EDGE BIT(10) |
69 | #define MAX_RTN_SIZE GENMASK(15, 12) |
70 | #define HSTX_CKLP_EN BIT(16) |
71 | |
72 | #define DSI_PSCTRL 0x1c |
73 | #define DSI_PS_WC GENMASK(13, 0) |
74 | #define DSI_PS_SEL GENMASK(17, 16) |
75 | #define PACKED_PS_16BIT_RGB565 0 |
76 | #define PACKED_PS_18BIT_RGB666 1 |
77 | #define LOOSELY_PS_24BIT_RGB666 2 |
78 | #define PACKED_PS_24BIT_RGB888 3 |
79 | |
80 | #define DSI_VSA_NL 0x20 |
81 | #define DSI_VBP_NL 0x24 |
82 | #define DSI_VFP_NL 0x28 |
83 | #define DSI_VACT_NL 0x2C |
84 | #define VACT_NL GENMASK(14, 0) |
85 | #define DSI_SIZE_CON 0x38 |
86 | #define DSI_HEIGHT GENMASK(30, 16) |
87 | #define DSI_WIDTH GENMASK(14, 0) |
88 | #define DSI_HSA_WC 0x50 |
89 | #define DSI_HBP_WC 0x54 |
90 | #define DSI_HFP_WC 0x58 |
91 | |
92 | #define DSI_CMDQ_SIZE 0x60 |
93 | #define CMDQ_SIZE 0x3f |
94 | #define CMDQ_SIZE_SEL BIT(15) |
95 | |
96 | #define DSI_HSTX_CKL_WC 0x64 |
97 | |
98 | #define DSI_RX_DATA0 0x74 |
99 | #define DSI_RX_DATA1 0x78 |
100 | #define DSI_RX_DATA2 0x7c |
101 | #define DSI_RX_DATA3 0x80 |
102 | |
103 | #define DSI_RACK 0x84 |
104 | #define RACK BIT(0) |
105 | |
106 | #define DSI_PHY_LCCON 0x104 |
107 | #define LC_HS_TX_EN BIT(0) |
108 | #define LC_ULPM_EN BIT(1) |
109 | #define LC_WAKEUP_EN BIT(2) |
110 | |
111 | #define DSI_PHY_LD0CON 0x108 |
112 | #define LD0_HS_TX_EN BIT(0) |
113 | #define LD0_ULPM_EN BIT(1) |
114 | #define LD0_WAKEUP_EN BIT(2) |
115 | |
116 | #define DSI_PHY_TIMECON0 0x110 |
117 | #define LPX GENMASK(7, 0) |
118 | #define HS_PREP GENMASK(15, 8) |
119 | #define HS_ZERO GENMASK(23, 16) |
120 | #define HS_TRAIL GENMASK(31, 24) |
121 | |
122 | #define DSI_PHY_TIMECON1 0x114 |
123 | #define TA_GO GENMASK(7, 0) |
124 | #define TA_SURE GENMASK(15, 8) |
125 | #define TA_GET GENMASK(23, 16) |
126 | #define DA_HS_EXIT GENMASK(31, 24) |
127 | |
128 | #define DSI_PHY_TIMECON2 0x118 |
129 | #define CONT_DET GENMASK(7, 0) |
130 | #define DA_HS_SYNC GENMASK(15, 8) |
131 | #define CLK_ZERO GENMASK(23, 16) |
132 | #define CLK_TRAIL GENMASK(31, 24) |
133 | |
134 | #define DSI_PHY_TIMECON3 0x11c |
135 | #define CLK_HS_PREP GENMASK(7, 0) |
136 | #define CLK_HS_POST GENMASK(15, 8) |
137 | #define CLK_HS_EXIT GENMASK(23, 16) |
138 | |
139 | #define DSI_VM_CMD_CON 0x130 |
140 | #define VM_CMD_EN BIT(0) |
141 | #define TS_VFP_EN BIT(5) |
142 | |
143 | #define DSI_SHADOW_DEBUG 0x190U |
144 | #define FORCE_COMMIT BIT(0) |
145 | #define BYPASS_SHADOW BIT(1) |
146 | |
147 | /* CMDQ related bits */ |
148 | #define CONFIG GENMASK(7, 0) |
149 | #define SHORT_PACKET 0 |
150 | #define LONG_PACKET 2 |
151 | #define BTA BIT(2) |
152 | #define DATA_ID GENMASK(15, 8) |
153 | #define DATA_0 GENMASK(23, 16) |
154 | #define DATA_1 GENMASK(31, 24) |
155 | |
156 | #define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) |
157 | |
158 | #define MTK_DSI_HOST_IS_READ(type) \ |
159 | ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \ |
160 | (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \ |
161 | (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \ |
162 | (type == MIPI_DSI_DCS_READ)) |
163 | |
164 | struct mtk_phy_timing { |
165 | u32 lpx; |
166 | u32 da_hs_prepare; |
167 | u32 da_hs_zero; |
168 | u32 da_hs_trail; |
169 | |
170 | u32 ta_go; |
171 | u32 ta_sure; |
172 | u32 ta_get; |
173 | u32 da_hs_exit; |
174 | |
175 | u32 clk_hs_zero; |
176 | u32 clk_hs_trail; |
177 | |
178 | u32 clk_hs_prepare; |
179 | u32 clk_hs_post; |
180 | u32 clk_hs_exit; |
181 | }; |
182 | |
183 | struct phy; |
184 | |
185 | struct mtk_dsi_driver_data { |
186 | const u32 reg_cmdq_off; |
187 | bool has_shadow_ctl; |
188 | bool has_size_ctl; |
189 | bool cmdq_long_packet_ctl; |
190 | }; |
191 | |
192 | struct mtk_dsi { |
193 | struct device *dev; |
194 | struct mipi_dsi_host host; |
195 | struct drm_encoder encoder; |
196 | struct drm_bridge bridge; |
197 | struct drm_bridge *next_bridge; |
198 | struct drm_connector *connector; |
199 | struct phy *phy; |
200 | |
201 | void __iomem *regs; |
202 | |
203 | struct clk *engine_clk; |
204 | struct clk *digital_clk; |
205 | struct clk *hs_clk; |
206 | |
207 | u32 data_rate; |
208 | |
209 | unsigned long mode_flags; |
210 | enum mipi_dsi_pixel_format format; |
211 | unsigned int lanes; |
212 | struct videomode vm; |
213 | struct mtk_phy_timing phy_timing; |
214 | int refcount; |
215 | bool enabled; |
216 | bool lanes_ready; |
217 | u32 irq_data; |
218 | wait_queue_head_t irq_wait_queue; |
219 | const struct mtk_dsi_driver_data *driver_data; |
220 | }; |
221 | |
222 | static inline struct mtk_dsi *bridge_to_dsi(struct drm_bridge *b) |
223 | { |
224 | return container_of(b, struct mtk_dsi, bridge); |
225 | } |
226 | |
227 | static inline struct mtk_dsi *host_to_dsi(struct mipi_dsi_host *h) |
228 | { |
229 | return container_of(h, struct mtk_dsi, host); |
230 | } |
231 | |
232 | static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data) |
233 | { |
234 | u32 temp = readl(addr: dsi->regs + offset); |
235 | |
236 | writel(val: (temp & ~mask) | (data & mask), addr: dsi->regs + offset); |
237 | } |
238 | |
239 | static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) |
240 | { |
241 | u32 timcon0, timcon1, timcon2, timcon3; |
242 | u32 data_rate_mhz = DIV_ROUND_UP(dsi->data_rate, HZ_PER_MHZ); |
243 | struct mtk_phy_timing *timing = &dsi->phy_timing; |
244 | |
245 | timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1; |
246 | timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000; |
247 | timing->da_hs_zero = (170 * data_rate_mhz + 10 * 1000) / 8000 + 1 - |
248 | timing->da_hs_prepare; |
249 | timing->da_hs_trail = timing->da_hs_prepare + 1; |
250 | |
251 | timing->ta_go = 4 * timing->lpx - 2; |
252 | timing->ta_sure = timing->lpx + 2; |
253 | timing->ta_get = 4 * timing->lpx; |
254 | timing->da_hs_exit = 2 * timing->lpx + 1; |
255 | |
256 | timing->clk_hs_prepare = 70 * data_rate_mhz / (8 * 1000); |
257 | timing->clk_hs_post = timing->clk_hs_prepare + 8; |
258 | timing->clk_hs_trail = timing->clk_hs_prepare; |
259 | timing->clk_hs_zero = timing->clk_hs_trail * 4; |
260 | timing->clk_hs_exit = 2 * timing->clk_hs_trail; |
261 | |
262 | timcon0 = FIELD_PREP(LPX, timing->lpx) | |
263 | FIELD_PREP(HS_PREP, timing->da_hs_prepare) | |
264 | FIELD_PREP(HS_ZERO, timing->da_hs_zero) | |
265 | FIELD_PREP(HS_TRAIL, timing->da_hs_trail); |
266 | |
267 | timcon1 = FIELD_PREP(TA_GO, timing->ta_go) | |
268 | FIELD_PREP(TA_SURE, timing->ta_sure) | |
269 | FIELD_PREP(TA_GET, timing->ta_get) | |
270 | FIELD_PREP(DA_HS_EXIT, timing->da_hs_exit); |
271 | |
272 | timcon2 = FIELD_PREP(DA_HS_SYNC, 1) | |
273 | FIELD_PREP(CLK_ZERO, timing->clk_hs_zero) | |
274 | FIELD_PREP(CLK_TRAIL, timing->clk_hs_trail); |
275 | |
276 | timcon3 = FIELD_PREP(CLK_HS_PREP, timing->clk_hs_prepare) | |
277 | FIELD_PREP(CLK_HS_POST, timing->clk_hs_post) | |
278 | FIELD_PREP(CLK_HS_EXIT, timing->clk_hs_exit); |
279 | |
280 | writel(val: timcon0, addr: dsi->regs + DSI_PHY_TIMECON0); |
281 | writel(val: timcon1, addr: dsi->regs + DSI_PHY_TIMECON1); |
282 | writel(val: timcon2, addr: dsi->regs + DSI_PHY_TIMECON2); |
283 | writel(val: timcon3, addr: dsi->regs + DSI_PHY_TIMECON3); |
284 | } |
285 | |
286 | static void mtk_dsi_enable(struct mtk_dsi *dsi) |
287 | { |
288 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN); |
289 | } |
290 | |
291 | static void mtk_dsi_disable(struct mtk_dsi *dsi) |
292 | { |
293 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, data: 0); |
294 | } |
295 | |
296 | static void mtk_dsi_reset_engine(struct mtk_dsi *dsi) |
297 | { |
298 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET); |
299 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, data: 0); |
300 | } |
301 | |
302 | static void mtk_dsi_reset_dphy(struct mtk_dsi *dsi) |
303 | { |
304 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, DPHY_RESET); |
305 | mtk_dsi_mask(dsi, DSI_CON_CTRL, DPHY_RESET, data: 0); |
306 | } |
307 | |
308 | static void mtk_dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi) |
309 | { |
310 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, data: 0); |
311 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, data: 0); |
312 | } |
313 | |
314 | static void mtk_dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi) |
315 | { |
316 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, data: 0); |
317 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN); |
318 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, data: 0); |
319 | } |
320 | |
321 | static void mtk_dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi) |
322 | { |
323 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, data: 0); |
324 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, data: 0); |
325 | } |
326 | |
327 | static void mtk_dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi) |
328 | { |
329 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, data: 0); |
330 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN); |
331 | mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, data: 0); |
332 | } |
333 | |
334 | static bool mtk_dsi_clk_hs_state(struct mtk_dsi *dsi) |
335 | { |
336 | return readl(addr: dsi->regs + DSI_PHY_LCCON) & LC_HS_TX_EN; |
337 | } |
338 | |
339 | static void mtk_dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter) |
340 | { |
341 | if (enter && !mtk_dsi_clk_hs_state(dsi)) |
342 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN); |
343 | else if (!enter && mtk_dsi_clk_hs_state(dsi)) |
344 | mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, data: 0); |
345 | } |
346 | |
347 | static void mtk_dsi_set_mode(struct mtk_dsi *dsi) |
348 | { |
349 | u32 vid_mode = CMD_MODE; |
350 | |
351 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { |
352 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) |
353 | vid_mode = BURST_MODE; |
354 | else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) |
355 | vid_mode = SYNC_PULSE_MODE; |
356 | else |
357 | vid_mode = SYNC_EVENT_MODE; |
358 | } |
359 | |
360 | writel(val: vid_mode, addr: dsi->regs + DSI_MODE_CTRL); |
361 | } |
362 | |
363 | static void mtk_dsi_set_vm_cmd(struct mtk_dsi *dsi) |
364 | { |
365 | mtk_dsi_mask(dsi, DSI_VM_CMD_CON, VM_CMD_EN, VM_CMD_EN); |
366 | mtk_dsi_mask(dsi, DSI_VM_CMD_CON, TS_VFP_EN, TS_VFP_EN); |
367 | } |
368 | |
369 | static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi) |
370 | { |
371 | u32 regval, tmp_reg = 0; |
372 | u8 i; |
373 | |
374 | /* Number of DSI lanes (max 4 lanes), each bit enables one DSI lane. */ |
375 | for (i = 0; i < dsi->lanes; i++) |
376 | tmp_reg |= BIT(i); |
377 | |
378 | regval = FIELD_PREP(LANE_NUM, tmp_reg); |
379 | |
380 | if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) |
381 | regval |= HSTX_CKLP_EN; |
382 | |
383 | if (dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) |
384 | regval |= DIS_EOT; |
385 | |
386 | writel(val: regval, addr: dsi->regs + DSI_TXRX_CTRL); |
387 | } |
388 | |
389 | static void mtk_dsi_ps_control(struct mtk_dsi *dsi, bool config_vact) |
390 | { |
391 | u32 dsi_buf_bpp, ps_val, ps_wc, vact_nl; |
392 | |
393 | if (dsi->format == MIPI_DSI_FMT_RGB565) |
394 | dsi_buf_bpp = 2; |
395 | else |
396 | dsi_buf_bpp = 3; |
397 | |
398 | /* Word count */ |
399 | ps_wc = FIELD_PREP(DSI_PS_WC, dsi->vm.hactive * dsi_buf_bpp); |
400 | ps_val = ps_wc; |
401 | |
402 | /* Pixel Stream type */ |
403 | switch (dsi->format) { |
404 | default: |
405 | fallthrough; |
406 | case MIPI_DSI_FMT_RGB888: |
407 | ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_24BIT_RGB888); |
408 | break; |
409 | case MIPI_DSI_FMT_RGB666: |
410 | ps_val |= FIELD_PREP(DSI_PS_SEL, LOOSELY_PS_24BIT_RGB666); |
411 | break; |
412 | case MIPI_DSI_FMT_RGB666_PACKED: |
413 | ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_18BIT_RGB666); |
414 | break; |
415 | case MIPI_DSI_FMT_RGB565: |
416 | ps_val |= FIELD_PREP(DSI_PS_SEL, PACKED_PS_16BIT_RGB565); |
417 | break; |
418 | } |
419 | |
420 | if (config_vact) { |
421 | vact_nl = FIELD_PREP(VACT_NL, dsi->vm.vactive); |
422 | writel(val: vact_nl, addr: dsi->regs + DSI_VACT_NL); |
423 | writel(val: ps_wc, addr: dsi->regs + DSI_HSTX_CKL_WC); |
424 | } |
425 | writel(val: ps_val, addr: dsi->regs + DSI_PSCTRL); |
426 | } |
427 | |
428 | static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) |
429 | { |
430 | u32 horizontal_sync_active_byte; |
431 | u32 horizontal_backporch_byte; |
432 | u32 horizontal_frontporch_byte; |
433 | u32 horizontal_front_back_byte; |
434 | u32 data_phy_cycles_byte; |
435 | u32 dsi_tmp_buf_bpp, data_phy_cycles; |
436 | u32 delta; |
437 | struct mtk_phy_timing *timing = &dsi->phy_timing; |
438 | |
439 | struct videomode *vm = &dsi->vm; |
440 | |
441 | if (dsi->format == MIPI_DSI_FMT_RGB565) |
442 | dsi_tmp_buf_bpp = 2; |
443 | else |
444 | dsi_tmp_buf_bpp = 3; |
445 | |
446 | writel(val: vm->vsync_len, addr: dsi->regs + DSI_VSA_NL); |
447 | writel(val: vm->vback_porch, addr: dsi->regs + DSI_VBP_NL); |
448 | writel(val: vm->vfront_porch, addr: dsi->regs + DSI_VFP_NL); |
449 | writel(val: vm->vactive, addr: dsi->regs + DSI_VACT_NL); |
450 | |
451 | if (dsi->driver_data->has_size_ctl) |
452 | writel(FIELD_PREP(DSI_HEIGHT, vm->vactive) | |
453 | FIELD_PREP(DSI_WIDTH, vm->hactive), |
454 | addr: dsi->regs + DSI_SIZE_CON); |
455 | |
456 | horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10); |
457 | |
458 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) |
459 | horizontal_backporch_byte = vm->hback_porch * dsi_tmp_buf_bpp - 10; |
460 | else |
461 | horizontal_backporch_byte = (vm->hback_porch + vm->hsync_len) * |
462 | dsi_tmp_buf_bpp - 10; |
463 | |
464 | data_phy_cycles = timing->lpx + timing->da_hs_prepare + |
465 | timing->da_hs_zero + timing->da_hs_exit + 3; |
466 | |
467 | delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12; |
468 | delta += dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET ? 0 : 2; |
469 | |
470 | horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp; |
471 | horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte; |
472 | data_phy_cycles_byte = data_phy_cycles * dsi->lanes + delta; |
473 | |
474 | if (horizontal_front_back_byte > data_phy_cycles_byte) { |
475 | horizontal_frontporch_byte -= data_phy_cycles_byte * |
476 | horizontal_frontporch_byte / |
477 | horizontal_front_back_byte; |
478 | |
479 | horizontal_backporch_byte -= data_phy_cycles_byte * |
480 | horizontal_backporch_byte / |
481 | horizontal_front_back_byte; |
482 | } else { |
483 | DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n" ); |
484 | } |
485 | |
486 | if ((dsi->mode_flags & MIPI_DSI_HS_PKT_END_ALIGNED) && |
487 | (dsi->lanes == 4)) { |
488 | horizontal_sync_active_byte = |
489 | roundup(horizontal_sync_active_byte, dsi->lanes) - 2; |
490 | horizontal_frontporch_byte = |
491 | roundup(horizontal_frontporch_byte, dsi->lanes) - 2; |
492 | horizontal_backporch_byte = |
493 | roundup(horizontal_backporch_byte, dsi->lanes) - 2; |
494 | horizontal_backporch_byte -= |
495 | (vm->hactive * dsi_tmp_buf_bpp + 2) % dsi->lanes; |
496 | } |
497 | |
498 | writel(val: horizontal_sync_active_byte, addr: dsi->regs + DSI_HSA_WC); |
499 | writel(val: horizontal_backporch_byte, addr: dsi->regs + DSI_HBP_WC); |
500 | writel(val: horizontal_frontporch_byte, addr: dsi->regs + DSI_HFP_WC); |
501 | |
502 | mtk_dsi_ps_control(dsi, config_vact: false); |
503 | } |
504 | |
505 | static void mtk_dsi_start(struct mtk_dsi *dsi) |
506 | { |
507 | writel(val: 0, addr: dsi->regs + DSI_START); |
508 | writel(val: 1, addr: dsi->regs + DSI_START); |
509 | } |
510 | |
511 | static void mtk_dsi_stop(struct mtk_dsi *dsi) |
512 | { |
513 | writel(val: 0, addr: dsi->regs + DSI_START); |
514 | } |
515 | |
516 | static void mtk_dsi_set_cmd_mode(struct mtk_dsi *dsi) |
517 | { |
518 | writel(CMD_MODE, addr: dsi->regs + DSI_MODE_CTRL); |
519 | } |
520 | |
521 | static void mtk_dsi_set_interrupt_enable(struct mtk_dsi *dsi) |
522 | { |
523 | u32 inten = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; |
524 | |
525 | writel(val: inten, addr: dsi->regs + DSI_INTEN); |
526 | } |
527 | |
528 | static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit) |
529 | { |
530 | dsi->irq_data |= irq_bit; |
531 | } |
532 | |
533 | static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) |
534 | { |
535 | dsi->irq_data &= ~irq_bit; |
536 | } |
537 | |
538 | static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, |
539 | unsigned int timeout) |
540 | { |
541 | s32 ret = 0; |
542 | unsigned long jiffies = msecs_to_jiffies(m: timeout); |
543 | |
544 | ret = wait_event_interruptible_timeout(dsi->irq_wait_queue, |
545 | dsi->irq_data & irq_flag, |
546 | jiffies); |
547 | if (ret == 0) { |
548 | DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n" , irq_flag); |
549 | |
550 | mtk_dsi_enable(dsi); |
551 | mtk_dsi_reset_engine(dsi); |
552 | } |
553 | |
554 | return ret; |
555 | } |
556 | |
557 | static irqreturn_t mtk_dsi_irq(int irq, void *dev_id) |
558 | { |
559 | struct mtk_dsi *dsi = dev_id; |
560 | u32 status, tmp; |
561 | u32 flag = LPRX_RD_RDY_INT_FLAG | CMD_DONE_INT_FLAG | VM_DONE_INT_FLAG; |
562 | |
563 | status = readl(addr: dsi->regs + DSI_INTSTA) & flag; |
564 | |
565 | if (status) { |
566 | do { |
567 | mtk_dsi_mask(dsi, DSI_RACK, RACK, RACK); |
568 | tmp = readl(addr: dsi->regs + DSI_INTSTA); |
569 | } while (tmp & DSI_BUSY); |
570 | |
571 | mtk_dsi_mask(dsi, DSI_INTSTA, mask: status, data: 0); |
572 | mtk_dsi_irq_data_set(dsi, irq_bit: status); |
573 | wake_up_interruptible(&dsi->irq_wait_queue); |
574 | } |
575 | |
576 | return IRQ_HANDLED; |
577 | } |
578 | |
579 | static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t) |
580 | { |
581 | mtk_dsi_irq_data_clear(dsi, irq_bit: irq_flag); |
582 | mtk_dsi_set_cmd_mode(dsi); |
583 | |
584 | if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, timeout: t)) { |
585 | DRM_ERROR("failed to switch cmd mode\n" ); |
586 | return -ETIME; |
587 | } else { |
588 | return 0; |
589 | } |
590 | } |
591 | |
592 | static int mtk_dsi_poweron(struct mtk_dsi *dsi) |
593 | { |
594 | struct device *dev = dsi->host.dev; |
595 | int ret; |
596 | u32 bit_per_pixel; |
597 | |
598 | if (++dsi->refcount != 1) |
599 | return 0; |
600 | |
601 | ret = mipi_dsi_pixel_format_to_bpp(fmt: dsi->format); |
602 | if (ret < 0) { |
603 | dev_err(dev, "Unknown MIPI DSI format %d\n" , dsi->format); |
604 | return ret; |
605 | } |
606 | bit_per_pixel = ret; |
607 | |
608 | dsi->data_rate = DIV_ROUND_UP_ULL(dsi->vm.pixelclock * bit_per_pixel, |
609 | dsi->lanes); |
610 | |
611 | ret = clk_set_rate(clk: dsi->hs_clk, rate: dsi->data_rate); |
612 | if (ret < 0) { |
613 | dev_err(dev, "Failed to set data rate: %d\n" , ret); |
614 | goto err_refcount; |
615 | } |
616 | |
617 | phy_power_on(phy: dsi->phy); |
618 | |
619 | ret = clk_prepare_enable(clk: dsi->engine_clk); |
620 | if (ret < 0) { |
621 | dev_err(dev, "Failed to enable engine clock: %d\n" , ret); |
622 | goto err_phy_power_off; |
623 | } |
624 | |
625 | ret = clk_prepare_enable(clk: dsi->digital_clk); |
626 | if (ret < 0) { |
627 | dev_err(dev, "Failed to enable digital clock: %d\n" , ret); |
628 | goto err_disable_engine_clk; |
629 | } |
630 | |
631 | mtk_dsi_enable(dsi); |
632 | |
633 | if (dsi->driver_data->has_shadow_ctl) |
634 | writel(FORCE_COMMIT | BYPASS_SHADOW, |
635 | addr: dsi->regs + DSI_SHADOW_DEBUG); |
636 | |
637 | mtk_dsi_reset_engine(dsi); |
638 | mtk_dsi_phy_timconfig(dsi); |
639 | |
640 | mtk_dsi_ps_control(dsi, config_vact: true); |
641 | mtk_dsi_set_vm_cmd(dsi); |
642 | mtk_dsi_config_vdo_timing(dsi); |
643 | mtk_dsi_set_interrupt_enable(dsi); |
644 | |
645 | return 0; |
646 | err_disable_engine_clk: |
647 | clk_disable_unprepare(clk: dsi->engine_clk); |
648 | err_phy_power_off: |
649 | phy_power_off(phy: dsi->phy); |
650 | err_refcount: |
651 | dsi->refcount--; |
652 | return ret; |
653 | } |
654 | |
655 | static void mtk_dsi_poweroff(struct mtk_dsi *dsi) |
656 | { |
657 | if (WARN_ON(dsi->refcount == 0)) |
658 | return; |
659 | |
660 | if (--dsi->refcount != 0) |
661 | return; |
662 | |
663 | /* |
664 | * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since |
665 | * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(), |
666 | * which needs irq for vblank, and mtk_dsi_stop() will disable irq. |
667 | * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(), |
668 | * after dsi is fully set. |
669 | */ |
670 | mtk_dsi_stop(dsi); |
671 | |
672 | mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, t: 500); |
673 | mtk_dsi_reset_engine(dsi); |
674 | mtk_dsi_lane0_ulp_mode_enter(dsi); |
675 | mtk_dsi_clk_ulp_mode_enter(dsi); |
676 | /* set the lane number as 0 to pull down mipi */ |
677 | writel(val: 0, addr: dsi->regs + DSI_TXRX_CTRL); |
678 | |
679 | mtk_dsi_disable(dsi); |
680 | |
681 | clk_disable_unprepare(clk: dsi->engine_clk); |
682 | clk_disable_unprepare(clk: dsi->digital_clk); |
683 | |
684 | phy_power_off(phy: dsi->phy); |
685 | |
686 | dsi->lanes_ready = false; |
687 | } |
688 | |
689 | static void mtk_dsi_lane_ready(struct mtk_dsi *dsi) |
690 | { |
691 | if (!dsi->lanes_ready) { |
692 | dsi->lanes_ready = true; |
693 | mtk_dsi_rxtx_control(dsi); |
694 | usleep_range(min: 30, max: 100); |
695 | mtk_dsi_reset_dphy(dsi); |
696 | mtk_dsi_clk_ulp_mode_leave(dsi); |
697 | mtk_dsi_lane0_ulp_mode_leave(dsi); |
698 | mtk_dsi_clk_hs_mode(dsi, enter: 0); |
699 | usleep_range(min: 1000, max: 3000); |
700 | /* The reaction time after pulling up the mipi signal for dsi_rx */ |
701 | } |
702 | } |
703 | |
704 | static void mtk_output_dsi_enable(struct mtk_dsi *dsi) |
705 | { |
706 | if (dsi->enabled) |
707 | return; |
708 | |
709 | mtk_dsi_lane_ready(dsi); |
710 | mtk_dsi_set_mode(dsi); |
711 | mtk_dsi_clk_hs_mode(dsi, enter: 1); |
712 | |
713 | mtk_dsi_start(dsi); |
714 | |
715 | dsi->enabled = true; |
716 | } |
717 | |
718 | static void mtk_output_dsi_disable(struct mtk_dsi *dsi) |
719 | { |
720 | if (!dsi->enabled) |
721 | return; |
722 | |
723 | dsi->enabled = false; |
724 | } |
725 | |
726 | static int mtk_dsi_bridge_attach(struct drm_bridge *bridge, |
727 | enum drm_bridge_attach_flags flags) |
728 | { |
729 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
730 | |
731 | /* Attach the panel or bridge to the dsi bridge */ |
732 | return drm_bridge_attach(encoder: bridge->encoder, bridge: dsi->next_bridge, |
733 | previous: &dsi->bridge, flags); |
734 | } |
735 | |
736 | static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge, |
737 | const struct drm_display_mode *mode, |
738 | const struct drm_display_mode *adjusted) |
739 | { |
740 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
741 | |
742 | drm_display_mode_to_videomode(dmode: adjusted, vm: &dsi->vm); |
743 | } |
744 | |
745 | static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge, |
746 | struct drm_bridge_state *old_bridge_state) |
747 | { |
748 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
749 | |
750 | mtk_output_dsi_disable(dsi); |
751 | } |
752 | |
753 | static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge, |
754 | struct drm_bridge_state *old_bridge_state) |
755 | { |
756 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
757 | |
758 | if (dsi->refcount == 0) |
759 | return; |
760 | |
761 | mtk_output_dsi_enable(dsi); |
762 | } |
763 | |
764 | static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge, |
765 | struct drm_bridge_state *old_bridge_state) |
766 | { |
767 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
768 | int ret; |
769 | |
770 | ret = mtk_dsi_poweron(dsi); |
771 | if (ret < 0) |
772 | DRM_ERROR("failed to power on dsi\n" ); |
773 | } |
774 | |
775 | static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge, |
776 | struct drm_bridge_state *old_bridge_state) |
777 | { |
778 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
779 | |
780 | mtk_dsi_poweroff(dsi); |
781 | } |
782 | |
783 | static enum drm_mode_status |
784 | mtk_dsi_bridge_mode_valid(struct drm_bridge *bridge, |
785 | const struct drm_display_info *info, |
786 | const struct drm_display_mode *mode) |
787 | { |
788 | struct mtk_dsi *dsi = bridge_to_dsi(b: bridge); |
789 | int bpp; |
790 | |
791 | bpp = mipi_dsi_pixel_format_to_bpp(fmt: dsi->format); |
792 | if (bpp < 0) |
793 | return MODE_ERROR; |
794 | |
795 | if (mode->clock * bpp / dsi->lanes > 1500000) |
796 | return MODE_CLOCK_HIGH; |
797 | |
798 | return MODE_OK; |
799 | } |
800 | |
801 | static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = { |
802 | .attach = mtk_dsi_bridge_attach, |
803 | .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, |
804 | .atomic_disable = mtk_dsi_bridge_atomic_disable, |
805 | .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, |
806 | .atomic_enable = mtk_dsi_bridge_atomic_enable, |
807 | .atomic_pre_enable = mtk_dsi_bridge_atomic_pre_enable, |
808 | .atomic_post_disable = mtk_dsi_bridge_atomic_post_disable, |
809 | .atomic_reset = drm_atomic_helper_bridge_reset, |
810 | .mode_valid = mtk_dsi_bridge_mode_valid, |
811 | .mode_set = mtk_dsi_bridge_mode_set, |
812 | }; |
813 | |
814 | void mtk_dsi_ddp_start(struct device *dev) |
815 | { |
816 | struct mtk_dsi *dsi = dev_get_drvdata(dev); |
817 | |
818 | mtk_dsi_poweron(dsi); |
819 | } |
820 | |
821 | void mtk_dsi_ddp_stop(struct device *dev) |
822 | { |
823 | struct mtk_dsi *dsi = dev_get_drvdata(dev); |
824 | |
825 | mtk_dsi_poweroff(dsi); |
826 | } |
827 | |
828 | static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) |
829 | { |
830 | int ret; |
831 | |
832 | ret = drm_simple_encoder_init(dev: drm, encoder: &dsi->encoder, |
833 | DRM_MODE_ENCODER_DSI); |
834 | if (ret) { |
835 | DRM_ERROR("Failed to encoder init to drm\n" ); |
836 | return ret; |
837 | } |
838 | |
839 | dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dev: dsi->host.dev); |
840 | |
841 | ret = drm_bridge_attach(encoder: &dsi->encoder, bridge: &dsi->bridge, NULL, |
842 | flags: DRM_BRIDGE_ATTACH_NO_CONNECTOR); |
843 | if (ret) |
844 | goto err_cleanup_encoder; |
845 | |
846 | dsi->connector = drm_bridge_connector_init(drm, encoder: &dsi->encoder); |
847 | if (IS_ERR(ptr: dsi->connector)) { |
848 | DRM_ERROR("Unable to create bridge connector\n" ); |
849 | ret = PTR_ERR(ptr: dsi->connector); |
850 | goto err_cleanup_encoder; |
851 | } |
852 | drm_connector_attach_encoder(connector: dsi->connector, encoder: &dsi->encoder); |
853 | |
854 | return 0; |
855 | |
856 | err_cleanup_encoder: |
857 | drm_encoder_cleanup(encoder: &dsi->encoder); |
858 | return ret; |
859 | } |
860 | |
861 | unsigned int mtk_dsi_encoder_index(struct device *dev) |
862 | { |
863 | struct mtk_dsi *dsi = dev_get_drvdata(dev); |
864 | unsigned int encoder_index = drm_encoder_index(encoder: &dsi->encoder); |
865 | |
866 | dev_dbg(dev, "encoder index:%d\n" , encoder_index); |
867 | return encoder_index; |
868 | } |
869 | |
870 | static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) |
871 | { |
872 | int ret; |
873 | struct drm_device *drm = data; |
874 | struct mtk_dsi *dsi = dev_get_drvdata(dev); |
875 | |
876 | ret = mtk_dsi_encoder_init(drm, dsi); |
877 | if (ret) |
878 | return ret; |
879 | |
880 | return device_reset_optional(dev); |
881 | } |
882 | |
883 | static void mtk_dsi_unbind(struct device *dev, struct device *master, |
884 | void *data) |
885 | { |
886 | struct mtk_dsi *dsi = dev_get_drvdata(dev); |
887 | |
888 | drm_encoder_cleanup(encoder: &dsi->encoder); |
889 | } |
890 | |
891 | static const struct component_ops mtk_dsi_component_ops = { |
892 | .bind = mtk_dsi_bind, |
893 | .unbind = mtk_dsi_unbind, |
894 | }; |
895 | |
896 | static int mtk_dsi_host_attach(struct mipi_dsi_host *host, |
897 | struct mipi_dsi_device *device) |
898 | { |
899 | struct mtk_dsi *dsi = host_to_dsi(h: host); |
900 | struct device *dev = host->dev; |
901 | int ret; |
902 | |
903 | dsi->lanes = device->lanes; |
904 | dsi->format = device->format; |
905 | dsi->mode_flags = device->mode_flags; |
906 | dsi->next_bridge = devm_drm_of_get_bridge(dev, node: dev->of_node, port: 0, endpoint: 0); |
907 | if (IS_ERR(ptr: dsi->next_bridge)) |
908 | return PTR_ERR(ptr: dsi->next_bridge); |
909 | |
910 | drm_bridge_add(bridge: &dsi->bridge); |
911 | |
912 | ret = component_add(host->dev, &mtk_dsi_component_ops); |
913 | if (ret) { |
914 | DRM_ERROR("failed to add dsi_host component: %d\n" , ret); |
915 | drm_bridge_remove(bridge: &dsi->bridge); |
916 | return ret; |
917 | } |
918 | |
919 | return 0; |
920 | } |
921 | |
922 | static int mtk_dsi_host_detach(struct mipi_dsi_host *host, |
923 | struct mipi_dsi_device *device) |
924 | { |
925 | struct mtk_dsi *dsi = host_to_dsi(h: host); |
926 | |
927 | component_del(host->dev, &mtk_dsi_component_ops); |
928 | drm_bridge_remove(bridge: &dsi->bridge); |
929 | return 0; |
930 | } |
931 | |
932 | static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi) |
933 | { |
934 | int ret; |
935 | u32 val; |
936 | |
937 | ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY), |
938 | 4, 2000000); |
939 | if (ret) { |
940 | DRM_WARN("polling dsi wait not busy timeout!\n" ); |
941 | |
942 | mtk_dsi_enable(dsi); |
943 | mtk_dsi_reset_engine(dsi); |
944 | } |
945 | } |
946 | |
947 | static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data) |
948 | { |
949 | switch (type) { |
950 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: |
951 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: |
952 | return 1; |
953 | case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: |
954 | case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: |
955 | return 2; |
956 | case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: |
957 | case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: |
958 | return read_data[1] + read_data[2] * 16; |
959 | case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: |
960 | DRM_INFO("type is 0x02, try again\n" ); |
961 | break; |
962 | default: |
963 | DRM_INFO("type(0x%x) not recognized\n" , type); |
964 | break; |
965 | } |
966 | |
967 | return 0; |
968 | } |
969 | |
970 | static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg) |
971 | { |
972 | const char *tx_buf = msg->tx_buf; |
973 | u8 config, cmdq_size, cmdq_off, type = msg->type; |
974 | u32 reg_val, cmdq_mask, i; |
975 | u32 reg_cmdq_off = dsi->driver_data->reg_cmdq_off; |
976 | |
977 | if (MTK_DSI_HOST_IS_READ(type)) |
978 | config = BTA; |
979 | else |
980 | config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET; |
981 | |
982 | if (msg->tx_len > 2) { |
983 | cmdq_size = 1 + (msg->tx_len + 3) / 4; |
984 | cmdq_off = 4; |
985 | cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1; |
986 | reg_val = (msg->tx_len << 16) | (type << 8) | config; |
987 | } else { |
988 | cmdq_size = 1; |
989 | cmdq_off = 2; |
990 | cmdq_mask = CONFIG | DATA_ID; |
991 | reg_val = (type << 8) | config; |
992 | } |
993 | |
994 | for (i = 0; i < msg->tx_len; i++) |
995 | mtk_dsi_mask(dsi, offset: (reg_cmdq_off + cmdq_off + i) & (~0x3U), |
996 | mask: (0xffUL << (((i + cmdq_off) & 3U) * 8U)), |
997 | data: tx_buf[i] << (((i + cmdq_off) & 3U) * 8U)); |
998 | |
999 | mtk_dsi_mask(dsi, offset: reg_cmdq_off, mask: cmdq_mask, data: reg_val); |
1000 | mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, data: cmdq_size); |
1001 | if (dsi->driver_data->cmdq_long_packet_ctl) { |
1002 | /* Disable setting cmdq_size automatically for long packets */ |
1003 | mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE_SEL, CMDQ_SIZE_SEL); |
1004 | } |
1005 | } |
1006 | |
1007 | static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi, |
1008 | const struct mipi_dsi_msg *msg, u8 flag) |
1009 | { |
1010 | mtk_dsi_wait_for_idle(dsi); |
1011 | mtk_dsi_irq_data_clear(dsi, irq_bit: flag); |
1012 | mtk_dsi_cmdq(dsi, msg); |
1013 | mtk_dsi_start(dsi); |
1014 | |
1015 | if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag: flag, timeout: 2000)) |
1016 | return -ETIME; |
1017 | else |
1018 | return 0; |
1019 | } |
1020 | |
1021 | static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host, |
1022 | const struct mipi_dsi_msg *msg) |
1023 | { |
1024 | struct mtk_dsi *dsi = host_to_dsi(h: host); |
1025 | u32 recv_cnt, i; |
1026 | u8 read_data[16]; |
1027 | void *src_addr; |
1028 | u8 irq_flag = CMD_DONE_INT_FLAG; |
1029 | u32 dsi_mode; |
1030 | int ret; |
1031 | |
1032 | dsi_mode = readl(addr: dsi->regs + DSI_MODE_CTRL); |
1033 | if (dsi_mode & MODE) { |
1034 | mtk_dsi_stop(dsi); |
1035 | ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, t: 500); |
1036 | if (ret) |
1037 | goto restore_dsi_mode; |
1038 | } |
1039 | |
1040 | if (MTK_DSI_HOST_IS_READ(msg->type)) |
1041 | irq_flag |= LPRX_RD_RDY_INT_FLAG; |
1042 | |
1043 | mtk_dsi_lane_ready(dsi); |
1044 | |
1045 | ret = mtk_dsi_host_send_cmd(dsi, msg, flag: irq_flag); |
1046 | if (ret) |
1047 | goto restore_dsi_mode; |
1048 | |
1049 | if (!MTK_DSI_HOST_IS_READ(msg->type)) { |
1050 | recv_cnt = 0; |
1051 | goto restore_dsi_mode; |
1052 | } |
1053 | |
1054 | if (!msg->rx_buf) { |
1055 | DRM_ERROR("dsi receive buffer size may be NULL\n" ); |
1056 | ret = -EINVAL; |
1057 | goto restore_dsi_mode; |
1058 | } |
1059 | |
1060 | for (i = 0; i < 16; i++) |
1061 | *(read_data + i) = readb(addr: dsi->regs + DSI_RX_DATA0 + i); |
1062 | |
1063 | recv_cnt = mtk_dsi_recv_cnt(type: read_data[0], read_data); |
1064 | |
1065 | if (recv_cnt > 2) |
1066 | src_addr = &read_data[4]; |
1067 | else |
1068 | src_addr = &read_data[1]; |
1069 | |
1070 | if (recv_cnt > 10) |
1071 | recv_cnt = 10; |
1072 | |
1073 | if (recv_cnt > msg->rx_len) |
1074 | recv_cnt = msg->rx_len; |
1075 | |
1076 | if (recv_cnt) |
1077 | memcpy(msg->rx_buf, src_addr, recv_cnt); |
1078 | |
1079 | DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n" , |
1080 | recv_cnt, *((u8 *)(msg->tx_buf))); |
1081 | |
1082 | restore_dsi_mode: |
1083 | if (dsi_mode & MODE) { |
1084 | mtk_dsi_set_mode(dsi); |
1085 | mtk_dsi_start(dsi); |
1086 | } |
1087 | |
1088 | return ret < 0 ? ret : recv_cnt; |
1089 | } |
1090 | |
1091 | static const struct mipi_dsi_host_ops mtk_dsi_ops = { |
1092 | .attach = mtk_dsi_host_attach, |
1093 | .detach = mtk_dsi_host_detach, |
1094 | .transfer = mtk_dsi_host_transfer, |
1095 | }; |
1096 | |
1097 | static int mtk_dsi_probe(struct platform_device *pdev) |
1098 | { |
1099 | struct mtk_dsi *dsi; |
1100 | struct device *dev = &pdev->dev; |
1101 | struct resource *regs; |
1102 | int irq_num; |
1103 | int ret; |
1104 | |
1105 | dsi = devm_kzalloc(dev, size: sizeof(*dsi), GFP_KERNEL); |
1106 | if (!dsi) |
1107 | return -ENOMEM; |
1108 | |
1109 | dsi->driver_data = of_device_get_match_data(dev); |
1110 | |
1111 | dsi->engine_clk = devm_clk_get(dev, id: "engine" ); |
1112 | if (IS_ERR(ptr: dsi->engine_clk)) |
1113 | return dev_err_probe(dev, err: PTR_ERR(ptr: dsi->engine_clk), |
1114 | fmt: "Failed to get engine clock\n" ); |
1115 | |
1116 | |
1117 | dsi->digital_clk = devm_clk_get(dev, id: "digital" ); |
1118 | if (IS_ERR(ptr: dsi->digital_clk)) |
1119 | return dev_err_probe(dev, err: PTR_ERR(ptr: dsi->digital_clk), |
1120 | fmt: "Failed to get digital clock\n" ); |
1121 | |
1122 | dsi->hs_clk = devm_clk_get(dev, id: "hs" ); |
1123 | if (IS_ERR(ptr: dsi->hs_clk)) |
1124 | return dev_err_probe(dev, err: PTR_ERR(ptr: dsi->hs_clk), fmt: "Failed to get hs clock\n" ); |
1125 | |
1126 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1127 | dsi->regs = devm_ioremap_resource(dev, res: regs); |
1128 | if (IS_ERR(ptr: dsi->regs)) |
1129 | return dev_err_probe(dev, err: PTR_ERR(ptr: dsi->regs), fmt: "Failed to ioremap memory\n" ); |
1130 | |
1131 | dsi->phy = devm_phy_get(dev, string: "dphy" ); |
1132 | if (IS_ERR(ptr: dsi->phy)) |
1133 | return dev_err_probe(dev, err: PTR_ERR(ptr: dsi->phy), fmt: "Failed to get MIPI-DPHY\n" ); |
1134 | |
1135 | irq_num = platform_get_irq(pdev, 0); |
1136 | if (irq_num < 0) |
1137 | return irq_num; |
1138 | |
1139 | dsi->host.ops = &mtk_dsi_ops; |
1140 | dsi->host.dev = dev; |
1141 | ret = mipi_dsi_host_register(host: &dsi->host); |
1142 | if (ret < 0) |
1143 | return dev_err_probe(dev, err: ret, fmt: "Failed to register DSI host\n" ); |
1144 | |
1145 | ret = devm_request_irq(dev: &pdev->dev, irq: irq_num, handler: mtk_dsi_irq, |
1146 | IRQF_TRIGGER_NONE, devname: dev_name(dev: &pdev->dev), dev_id: dsi); |
1147 | if (ret) { |
1148 | mipi_dsi_host_unregister(host: &dsi->host); |
1149 | return dev_err_probe(dev: &pdev->dev, err: ret, fmt: "Failed to request DSI irq\n" ); |
1150 | } |
1151 | |
1152 | init_waitqueue_head(&dsi->irq_wait_queue); |
1153 | |
1154 | platform_set_drvdata(pdev, data: dsi); |
1155 | |
1156 | dsi->bridge.funcs = &mtk_dsi_bridge_funcs; |
1157 | dsi->bridge.of_node = dev->of_node; |
1158 | dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; |
1159 | |
1160 | return 0; |
1161 | } |
1162 | |
1163 | static void mtk_dsi_remove(struct platform_device *pdev) |
1164 | { |
1165 | struct mtk_dsi *dsi = platform_get_drvdata(pdev); |
1166 | |
1167 | mtk_output_dsi_disable(dsi); |
1168 | mipi_dsi_host_unregister(host: &dsi->host); |
1169 | } |
1170 | |
1171 | static const struct mtk_dsi_driver_data mt8173_dsi_driver_data = { |
1172 | .reg_cmdq_off = 0x200, |
1173 | }; |
1174 | |
1175 | static const struct mtk_dsi_driver_data mt2701_dsi_driver_data = { |
1176 | .reg_cmdq_off = 0x180, |
1177 | }; |
1178 | |
1179 | static const struct mtk_dsi_driver_data mt8183_dsi_driver_data = { |
1180 | .reg_cmdq_off = 0x200, |
1181 | .has_shadow_ctl = true, |
1182 | .has_size_ctl = true, |
1183 | }; |
1184 | |
1185 | static const struct mtk_dsi_driver_data mt8186_dsi_driver_data = { |
1186 | .reg_cmdq_off = 0xd00, |
1187 | .has_shadow_ctl = true, |
1188 | .has_size_ctl = true, |
1189 | }; |
1190 | |
1191 | static const struct mtk_dsi_driver_data mt8188_dsi_driver_data = { |
1192 | .reg_cmdq_off = 0xd00, |
1193 | .has_shadow_ctl = true, |
1194 | .has_size_ctl = true, |
1195 | .cmdq_long_packet_ctl = true, |
1196 | }; |
1197 | |
1198 | static const struct of_device_id mtk_dsi_of_match[] = { |
1199 | { .compatible = "mediatek,mt2701-dsi" , .data = &mt2701_dsi_driver_data }, |
1200 | { .compatible = "mediatek,mt8173-dsi" , .data = &mt8173_dsi_driver_data }, |
1201 | { .compatible = "mediatek,mt8183-dsi" , .data = &mt8183_dsi_driver_data }, |
1202 | { .compatible = "mediatek,mt8186-dsi" , .data = &mt8186_dsi_driver_data }, |
1203 | { .compatible = "mediatek,mt8188-dsi" , .data = &mt8188_dsi_driver_data }, |
1204 | { /* sentinel */ } |
1205 | }; |
1206 | MODULE_DEVICE_TABLE(of, mtk_dsi_of_match); |
1207 | |
1208 | struct platform_driver mtk_dsi_driver = { |
1209 | .probe = mtk_dsi_probe, |
1210 | .remove_new = mtk_dsi_remove, |
1211 | .driver = { |
1212 | .name = "mtk-dsi" , |
1213 | .of_match_table = mtk_dsi_of_match, |
1214 | }, |
1215 | }; |
1216 | |