1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2016 Allwinnertech Co., Ltd.
4  * Copyright (C) 2017-2018 Bootlin
5  *
6  * Maxime Ripard <maxime.ripard@bootlin.com>
7  */
8 
9 #include <linux/clk.h>
10 #include <linux/component.h>
11 #include <linux/crc-ccitt.h>
12 #include <linux/of_address.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/regmap.h>
15 #include <linux/reset.h>
16 #include <linux/slab.h>
17 
18 #include <linux/phy/phy.h>
19 
20 #include <drm/drmP.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_mipi_dsi.h>
23 #include <drm/drm_panel.h>
24 #include <drm/drm_probe_helper.h>
25 
26 #include "sun4i_drv.h"
27 #include "sun6i_mipi_dsi.h"
28 
29 #include <video/mipi_display.h>
30 
31 #define SUN6I_DSI_CTL_REG		0x000
32 #define SUN6I_DSI_CTL_EN			BIT(0)
33 
34 #define SUN6I_DSI_BASIC_CTL_REG		0x00c
35 #define SUN6I_DSI_BASIC_CTL_HBP_DIS		BIT(2)
36 #define SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS		BIT(1)
37 #define SUN6I_DSI_BASIC_CTL_VIDEO_BURST		BIT(0)
38 
39 #define SUN6I_DSI_BASIC_CTL0_REG	0x010
40 #define SUN6I_DSI_BASIC_CTL0_HS_EOTP_EN		BIT(18)
41 #define SUN6I_DSI_BASIC_CTL0_CRC_EN		BIT(17)
42 #define SUN6I_DSI_BASIC_CTL0_ECC_EN		BIT(16)
43 #define SUN6I_DSI_BASIC_CTL0_INST_ST		BIT(0)
44 
45 #define SUN6I_DSI_BASIC_CTL1_REG	0x014
46 #define SUN6I_DSI_BASIC_CTL1_VIDEO_ST_DELAY(n)	(((n) & 0x1fff) << 4)
47 #define SUN6I_DSI_BASIC_CTL1_VIDEO_FILL		BIT(2)
48 #define SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION	BIT(1)
49 #define SUN6I_DSI_BASIC_CTL1_VIDEO_MODE		BIT(0)
50 
51 #define SUN6I_DSI_BASIC_SIZE0_REG	0x018
52 #define SUN6I_DSI_BASIC_SIZE0_VBP(n)		(((n) & 0xfff) << 16)
53 #define SUN6I_DSI_BASIC_SIZE0_VSA(n)		((n) & 0xfff)
54 
55 #define SUN6I_DSI_BASIC_SIZE1_REG	0x01c
56 #define SUN6I_DSI_BASIC_SIZE1_VT(n)		(((n) & 0xfff) << 16)
57 #define SUN6I_DSI_BASIC_SIZE1_VACT(n)		((n) & 0xfff)
58 
59 #define SUN6I_DSI_INST_FUNC_REG(n)	(0x020 + (n) * 0x04)
60 #define SUN6I_DSI_INST_FUNC_INST_MODE(n)	(((n) & 0xf) << 28)
61 #define SUN6I_DSI_INST_FUNC_ESCAPE_ENTRY(n)	(((n) & 0xf) << 24)
62 #define SUN6I_DSI_INST_FUNC_TRANS_PACKET(n)	(((n) & 0xf) << 20)
63 #define SUN6I_DSI_INST_FUNC_LANE_CEN		BIT(4)
64 #define SUN6I_DSI_INST_FUNC_LANE_DEN(n)		((n) & 0xf)
65 
66 #define SUN6I_DSI_INST_LOOP_SEL_REG	0x040
67 
68 #define SUN6I_DSI_INST_LOOP_NUM_REG(n)	(0x044 + (n) * 0x10)
69 #define SUN6I_DSI_INST_LOOP_NUM_N1(n)		(((n) & 0xfff) << 16)
70 #define SUN6I_DSI_INST_LOOP_NUM_N0(n)		((n) & 0xfff)
71 
72 #define SUN6I_DSI_INST_JUMP_SEL_REG	0x048
73 
74 #define SUN6I_DSI_INST_JUMP_CFG_REG(n)	(0x04c + (n) * 0x04)
75 #define SUN6I_DSI_INST_JUMP_CFG_TO(n)		(((n) & 0xf) << 20)
76 #define SUN6I_DSI_INST_JUMP_CFG_POINT(n)	(((n) & 0xf) << 16)
77 #define SUN6I_DSI_INST_JUMP_CFG_NUM(n)		((n) & 0xffff)
78 
79 #define SUN6I_DSI_TRANS_START_REG	0x060
80 
81 #define SUN6I_DSI_TRANS_ZERO_REG	0x078
82 
83 #define SUN6I_DSI_TCON_DRQ_REG		0x07c
84 #define SUN6I_DSI_TCON_DRQ_ENABLE_MODE		BIT(28)
85 #define SUN6I_DSI_TCON_DRQ_SET(n)		((n) & 0x3ff)
86 
87 #define SUN6I_DSI_PIXEL_CTL0_REG	0x080
88 #define SUN6I_DSI_PIXEL_CTL0_PD_PLUG_DISABLE	BIT(16)
89 #define SUN6I_DSI_PIXEL_CTL0_FORMAT(n)		((n) & 0xf)
90 
91 #define SUN6I_DSI_PIXEL_CTL1_REG	0x084
92 
93 #define SUN6I_DSI_PIXEL_PH_REG		0x090
94 #define SUN6I_DSI_PIXEL_PH_ECC(n)		(((n) & 0xff) << 24)
95 #define SUN6I_DSI_PIXEL_PH_WC(n)		(((n) & 0xffff) << 8)
96 #define SUN6I_DSI_PIXEL_PH_VC(n)		(((n) & 3) << 6)
97 #define SUN6I_DSI_PIXEL_PH_DT(n)		((n) & 0x3f)
98 
99 #define SUN6I_DSI_PIXEL_PF0_REG		0x098
100 #define SUN6I_DSI_PIXEL_PF0_CRC_FORCE(n)	((n) & 0xffff)
101 
102 #define SUN6I_DSI_PIXEL_PF1_REG		0x09c
103 #define SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINEN(n)	(((n) & 0xffff) << 16)
104 #define SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINE0(n)	((n) & 0xffff)
105 
106 #define SUN6I_DSI_SYNC_HSS_REG		0x0b0
107 
108 #define SUN6I_DSI_SYNC_HSE_REG		0x0b4
109 
110 #define SUN6I_DSI_SYNC_VSS_REG		0x0b8
111 
112 #define SUN6I_DSI_SYNC_VSE_REG		0x0bc
113 
114 #define SUN6I_DSI_BLK_HSA0_REG		0x0c0
115 
116 #define SUN6I_DSI_BLK_HSA1_REG		0x0c4
117 #define SUN6I_DSI_BLK_PF(n)			(((n) & 0xffff) << 16)
118 #define SUN6I_DSI_BLK_PD(n)			((n) & 0xff)
119 
120 #define SUN6I_DSI_BLK_HBP0_REG		0x0c8
121 
122 #define SUN6I_DSI_BLK_HBP1_REG		0x0cc
123 
124 #define SUN6I_DSI_BLK_HFP0_REG		0x0d0
125 
126 #define SUN6I_DSI_BLK_HFP1_REG		0x0d4
127 
128 #define SUN6I_DSI_BLK_HBLK0_REG		0x0e0
129 
130 #define SUN6I_DSI_BLK_HBLK1_REG		0x0e4
131 
132 #define SUN6I_DSI_BLK_VBLK0_REG		0x0e8
133 
134 #define SUN6I_DSI_BLK_VBLK1_REG		0x0ec
135 
136 #define SUN6I_DSI_BURST_LINE_REG	0x0f0
137 #define SUN6I_DSI_BURST_LINE_SYNC_POINT(n)	(((n) & 0xffff) << 16)
138 #define SUN6I_DSI_BURST_LINE_NUM(n)		((n) & 0xffff)
139 
140 #define SUN6I_DSI_BURST_DRQ_REG		0x0f4
141 #define SUN6I_DSI_BURST_DRQ_EDGE1(n)		(((n) & 0xffff) << 16)
142 #define SUN6I_DSI_BURST_DRQ_EDGE0(n)		((n) & 0xffff)
143 
144 #define SUN6I_DSI_CMD_CTL_REG		0x200
145 #define SUN6I_DSI_CMD_CTL_RX_OVERFLOW		BIT(26)
146 #define SUN6I_DSI_CMD_CTL_RX_FLAG		BIT(25)
147 #define SUN6I_DSI_CMD_CTL_TX_FLAG		BIT(9)
148 
149 #define SUN6I_DSI_CMD_RX_REG(n)		(0x240 + (n) * 0x04)
150 
151 #define SUN6I_DSI_DEBUG_DATA_REG	0x2f8
152 
153 #define SUN6I_DSI_CMD_TX_REG(n)		(0x300 + (n) * 0x04)
154 
155 enum sun6i_dsi_start_inst {
156 	DSI_START_LPRX,
157 	DSI_START_LPTX,
158 	DSI_START_HSC,
159 	DSI_START_HSD,
160 };
161 
162 enum sun6i_dsi_inst_id {
163 	DSI_INST_ID_LP11	= 0,
164 	DSI_INST_ID_TBA,
165 	DSI_INST_ID_HSC,
166 	DSI_INST_ID_HSD,
167 	DSI_INST_ID_LPDT,
168 	DSI_INST_ID_HSCEXIT,
169 	DSI_INST_ID_NOP,
170 	DSI_INST_ID_DLY,
171 	DSI_INST_ID_END		= 15,
172 };
173 
174 enum sun6i_dsi_inst_mode {
175 	DSI_INST_MODE_STOP	= 0,
176 	DSI_INST_MODE_TBA,
177 	DSI_INST_MODE_HS,
178 	DSI_INST_MODE_ESCAPE,
179 	DSI_INST_MODE_HSCEXIT,
180 	DSI_INST_MODE_NOP,
181 };
182 
183 enum sun6i_dsi_inst_escape {
184 	DSI_INST_ESCA_LPDT	= 0,
185 	DSI_INST_ESCA_ULPS,
186 	DSI_INST_ESCA_UN1,
187 	DSI_INST_ESCA_UN2,
188 	DSI_INST_ESCA_RESET,
189 	DSI_INST_ESCA_UN3,
190 	DSI_INST_ESCA_UN4,
191 	DSI_INST_ESCA_UN5,
192 };
193 
194 enum sun6i_dsi_inst_packet {
195 	DSI_INST_PACK_PIXEL	= 0,
196 	DSI_INST_PACK_COMMAND,
197 };
198 
199 static const u32 sun6i_dsi_ecc_array[] = {
200 	[0] = (BIT(0) | BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(7) | BIT(10) |
201 	       BIT(11) | BIT(13) | BIT(16) | BIT(20) | BIT(21) | BIT(22) |
202 	       BIT(23)),
203 	[1] = (BIT(0) | BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(8) | BIT(10) |
204 	       BIT(12) | BIT(14) | BIT(17) | BIT(20) | BIT(21) | BIT(22) |
205 	       BIT(23)),
206 	[2] = (BIT(0) | BIT(2) | BIT(3) | BIT(5) | BIT(6) | BIT(9) | BIT(11) |
207 	       BIT(12) | BIT(15) | BIT(18) | BIT(20) | BIT(21) | BIT(22)),
208 	[3] = (BIT(1) | BIT(2) | BIT(3) | BIT(7) | BIT(8) | BIT(9) | BIT(13) |
209 	       BIT(14) | BIT(15) | BIT(19) | BIT(20) | BIT(21) | BIT(23)),
210 	[4] = (BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(16) |
211 	       BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(22) | BIT(23)),
212 	[5] = (BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) |
213 	       BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(21) | BIT(22) |
214 	       BIT(23)),
215 };
216 
217 static u32 sun6i_dsi_ecc_compute(unsigned int data)
218 {
219 	int i;
220 	u8 ecc = 0;
221 
222 	for (i = 0; i < ARRAY_SIZE(sun6i_dsi_ecc_array); i++) {
223 		u32 field = sun6i_dsi_ecc_array[i];
224 		bool init = false;
225 		u8 val = 0;
226 		int j;
227 
228 		for (j = 0; j < 24; j++) {
229 			if (!(BIT(j) & field))
230 				continue;
231 
232 			if (!init) {
233 				val = (BIT(j) & data) ? 1 : 0;
234 				init = true;
235 			} else {
236 				val ^= (BIT(j) & data) ? 1 : 0;
237 			}
238 		}
239 
240 		ecc |= val << i;
241 	}
242 
243 	return ecc;
244 }
245 
246 static u16 sun6i_dsi_crc_compute(u8 const *buffer, size_t len)
247 {
248 	return crc_ccitt(0xffff, buffer, len);
249 }
250 
251 static u16 sun6i_dsi_crc_repeat(u8 pd, u8 *buffer, size_t len)
252 {
253 	memset(buffer, pd, len);
254 
255 	return sun6i_dsi_crc_compute(buffer, len);
256 }
257 
258 static u32 sun6i_dsi_build_sync_pkt(u8 dt, u8 vc, u8 d0, u8 d1)
259 {
260 	u32 val = dt & 0x3f;
261 
262 	val |= (vc & 3) << 6;
263 	val |= (d0 & 0xff) << 8;
264 	val |= (d1 & 0xff) << 16;
265 	val |= sun6i_dsi_ecc_compute(val) << 24;
266 
267 	return val;
268 }
269 
270 static u32 sun6i_dsi_build_blk0_pkt(u8 vc, u16 wc)
271 {
272 	return sun6i_dsi_build_sync_pkt(MIPI_DSI_BLANKING_PACKET, vc,
273 					wc & 0xff, wc >> 8);
274 }
275 
276 static u32 sun6i_dsi_build_blk1_pkt(u16 pd, u8 *buffer, size_t len)
277 {
278 	u32 val = SUN6I_DSI_BLK_PD(pd);
279 
280 	return val | SUN6I_DSI_BLK_PF(sun6i_dsi_crc_repeat(pd, buffer, len));
281 }
282 
283 static void sun6i_dsi_inst_abort(struct sun6i_dsi *dsi)
284 {
285 	regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
286 			   SUN6I_DSI_BASIC_CTL0_INST_ST, 0);
287 }
288 
289 static void sun6i_dsi_inst_commit(struct sun6i_dsi *dsi)
290 {
291 	regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
292 			   SUN6I_DSI_BASIC_CTL0_INST_ST,
293 			   SUN6I_DSI_BASIC_CTL0_INST_ST);
294 }
295 
296 static int sun6i_dsi_inst_wait_for_completion(struct sun6i_dsi *dsi)
297 {
298 	u32 val;
299 
300 	return regmap_read_poll_timeout(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
301 					val,
302 					!(val & SUN6I_DSI_BASIC_CTL0_INST_ST),
303 					100, 5000);
304 }
305 
306 static void sun6i_dsi_inst_setup(struct sun6i_dsi *dsi,
307 				 enum sun6i_dsi_inst_id id,
308 				 enum sun6i_dsi_inst_mode mode,
309 				 bool clock, u8 data,
310 				 enum sun6i_dsi_inst_packet packet,
311 				 enum sun6i_dsi_inst_escape escape)
312 {
313 	regmap_write(dsi->regs, SUN6I_DSI_INST_FUNC_REG(id),
314 		     SUN6I_DSI_INST_FUNC_INST_MODE(mode) |
315 		     SUN6I_DSI_INST_FUNC_ESCAPE_ENTRY(escape) |
316 		     SUN6I_DSI_INST_FUNC_TRANS_PACKET(packet) |
317 		     (clock ? SUN6I_DSI_INST_FUNC_LANE_CEN : 0) |
318 		     SUN6I_DSI_INST_FUNC_LANE_DEN(data));
319 }
320 
321 static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
322 				struct mipi_dsi_device *device)
323 {
324 	u8 lanes_mask = GENMASK(device->lanes - 1, 0);
325 
326 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LP11, DSI_INST_MODE_STOP,
327 			     true, lanes_mask, 0, 0);
328 
329 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_TBA, DSI_INST_MODE_TBA,
330 			     false, 1, 0, 0);
331 
332 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSC, DSI_INST_MODE_HS,
333 			     true, 0, DSI_INST_PACK_PIXEL, 0);
334 
335 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSD, DSI_INST_MODE_HS,
336 			     false, lanes_mask, DSI_INST_PACK_PIXEL, 0);
337 
338 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LPDT, DSI_INST_MODE_ESCAPE,
339 			     false, 1, DSI_INST_PACK_COMMAND,
340 			     DSI_INST_ESCA_LPDT);
341 
342 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSCEXIT, DSI_INST_MODE_HSCEXIT,
343 			     true, 0, 0, 0);
344 
345 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_NOP, DSI_INST_MODE_STOP,
346 			     false, lanes_mask, 0, 0);
347 
348 	sun6i_dsi_inst_setup(dsi, DSI_INST_ID_DLY, DSI_INST_MODE_NOP,
349 			     true, lanes_mask, 0, 0);
350 
351 	regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_CFG_REG(0),
352 		     SUN6I_DSI_INST_JUMP_CFG_POINT(DSI_INST_ID_NOP) |
353 		     SUN6I_DSI_INST_JUMP_CFG_TO(DSI_INST_ID_HSCEXIT) |
354 		     SUN6I_DSI_INST_JUMP_CFG_NUM(1));
355 };
356 
357 static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
358 					   struct drm_display_mode *mode)
359 {
360 	return mode->vtotal - (mode->vsync_end - mode->vdisplay) + 1;
361 }
362 
363 static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
364 				  struct drm_display_mode *mode)
365 {
366 	struct mipi_dsi_device *device = dsi->device;
367 	u32 val = 0;
368 
369 	if ((mode->hsync_end - mode->hdisplay) > 20) {
370 		/* Maaaaaagic */
371 		u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
372 
373 		drq *= mipi_dsi_pixel_format_to_bpp(device->format);
374 		drq /= 32;
375 
376 		val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
377 		       SUN6I_DSI_TCON_DRQ_SET(drq));
378 	}
379 
380 	regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val);
381 }
382 
383 static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
384 				      struct drm_display_mode *mode)
385 {
386 	u16 delay = 50 - 1;
387 
388 	regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
389 		     SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
390 		     SUN6I_DSI_INST_LOOP_NUM_N1(delay));
391 	regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(1),
392 		     SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
393 		     SUN6I_DSI_INST_LOOP_NUM_N1(delay));
394 }
395 
396 static void sun6i_dsi_setup_format(struct sun6i_dsi *dsi,
397 				   struct drm_display_mode *mode)
398 {
399 	struct mipi_dsi_device *device = dsi->device;
400 	u32 val = SUN6I_DSI_PIXEL_PH_VC(device->channel);
401 	u8 dt, fmt;
402 	u16 wc;
403 
404 	/*
405 	 * TODO: The format defines are only valid in video mode and
406 	 * change in command mode.
407 	 */
408 	switch (device->format) {
409 	case MIPI_DSI_FMT_RGB888:
410 		dt = MIPI_DSI_PACKED_PIXEL_STREAM_24;
411 		fmt = 8;
412 		break;
413 	case MIPI_DSI_FMT_RGB666:
414 		dt = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
415 		fmt = 9;
416 		break;
417 	case MIPI_DSI_FMT_RGB666_PACKED:
418 		dt = MIPI_DSI_PACKED_PIXEL_STREAM_18;
419 		fmt = 10;
420 		break;
421 	case MIPI_DSI_FMT_RGB565:
422 		dt = MIPI_DSI_PACKED_PIXEL_STREAM_16;
423 		fmt = 11;
424 		break;
425 	default:
426 		return;
427 	}
428 	val |= SUN6I_DSI_PIXEL_PH_DT(dt);
429 
430 	wc = mode->hdisplay * mipi_dsi_pixel_format_to_bpp(device->format) / 8;
431 	val |= SUN6I_DSI_PIXEL_PH_WC(wc);
432 	val |= SUN6I_DSI_PIXEL_PH_ECC(sun6i_dsi_ecc_compute(val));
433 
434 	regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PH_REG, val);
435 
436 	regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF0_REG,
437 		     SUN6I_DSI_PIXEL_PF0_CRC_FORCE(0xffff));
438 
439 	regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF1_REG,
440 		     SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINE0(0xffff) |
441 		     SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINEN(0xffff));
442 
443 	regmap_write(dsi->regs, SUN6I_DSI_PIXEL_CTL0_REG,
444 		     SUN6I_DSI_PIXEL_CTL0_PD_PLUG_DISABLE |
445 		     SUN6I_DSI_PIXEL_CTL0_FORMAT(fmt));
446 }
447 
448 static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
449 				    struct drm_display_mode *mode)
450 {
451 	struct mipi_dsi_device *device = dsi->device;
452 	unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
453 	u16 hbp, hfp, hsa, hblk, vblk;
454 	size_t bytes;
455 	u8 *buffer;
456 
457 	/* Do all timing calculations up front to allocate buffer space */
458 
459 	/*
460 	 * A sync period is composed of a blanking packet (4 bytes +
461 	 * payload + 2 bytes) and a sync event packet (4 bytes). Its
462 	 * minimal size is therefore 10 bytes
463 	 */
464 #define HSA_PACKET_OVERHEAD	10
465 	hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
466 		  (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
467 
468 	/*
469 	 * The backporch is set using a blanking packet (4 bytes +
470 	 * payload + 2 bytes). Its minimal size is therefore 6 bytes
471 	 */
472 #define HBP_PACKET_OVERHEAD	6
473 	hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
474 		  (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
475 
476 	/*
477 	 * The frontporch is set using a blanking packet (4 bytes +
478 	 * payload + 2 bytes). Its minimal size is therefore 6 bytes
479 	 */
480 #define HFP_PACKET_OVERHEAD	6
481 	hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
482 		  (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
483 
484 	/*
485 	 * hblk seems to be the line + porches length.
486 	 */
487 	hblk = mode->htotal * Bpp - hsa;
488 
489 	/*
490 	 * And I'm not entirely sure what vblk is about. The driver in
491 	 * Allwinner BSP is using a rather convoluted calculation
492 	 * there only for 4 lanes. However, using 0 (the !4 lanes
493 	 * case) even with a 4 lanes screen seems to work...
494 	 */
495 	vblk = 0;
496 
497 	/* How many bytes do we need to send all payloads? */
498 	bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
499 	buffer = kmalloc(bytes, GFP_KERNEL);
500 	if (WARN_ON(!buffer))
501 		return;
502 
503 	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, 0);
504 
505 	regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG,
506 		     sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
507 					      device->channel,
508 					      0, 0));
509 
510 	regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSE_REG,
511 		     sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_END,
512 					      device->channel,
513 					      0, 0));
514 
515 	regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSS_REG,
516 		     sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_START,
517 					      device->channel,
518 					      0, 0));
519 
520 	regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSE_REG,
521 		     sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_END,
522 					      device->channel,
523 					      0, 0));
524 
525 	regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE0_REG,
526 		     SUN6I_DSI_BASIC_SIZE0_VSA(mode->vsync_end -
527 					       mode->vsync_start) |
528 		     SUN6I_DSI_BASIC_SIZE0_VBP(mode->vsync_start -
529 					       mode->vdisplay));
530 
531 	regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE1_REG,
532 		     SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
533 		     SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal));
534 
535 	/* sync */
536 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG,
537 		     sun6i_dsi_build_blk0_pkt(device->channel, hsa));
538 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG,
539 		     sun6i_dsi_build_blk1_pkt(0, buffer, hsa));
540 
541 	/* backporch */
542 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG,
543 		     sun6i_dsi_build_blk0_pkt(device->channel, hbp));
544 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG,
545 		     sun6i_dsi_build_blk1_pkt(0, buffer, hbp));
546 
547 	/* frontporch */
548 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG,
549 		     sun6i_dsi_build_blk0_pkt(device->channel, hfp));
550 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG,
551 		     sun6i_dsi_build_blk1_pkt(0, buffer, hfp));
552 
553 	/* hblk */
554 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG,
555 		     sun6i_dsi_build_blk0_pkt(device->channel, hblk));
556 	regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG,
557 		     sun6i_dsi_build_blk1_pkt(0, buffer, hblk));
558 
559 	/* vblk */
560 	regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG,
561 		     sun6i_dsi_build_blk0_pkt(device->channel, vblk));
562 	regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG,
563 		     sun6i_dsi_build_blk1_pkt(0, buffer, vblk));
564 
565 	kfree(buffer);
566 }
567 
568 static int sun6i_dsi_start(struct sun6i_dsi *dsi,
569 			   enum sun6i_dsi_start_inst func)
570 {
571 	switch (func) {
572 	case DSI_START_LPTX:
573 		regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
574 			     DSI_INST_ID_LPDT << (4 * DSI_INST_ID_LP11) |
575 			     DSI_INST_ID_END  << (4 * DSI_INST_ID_LPDT));
576 		break;
577 	case DSI_START_LPRX:
578 		regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
579 			     DSI_INST_ID_LPDT << (4 * DSI_INST_ID_LP11) |
580 			     DSI_INST_ID_DLY  << (4 * DSI_INST_ID_LPDT) |
581 			     DSI_INST_ID_TBA  << (4 * DSI_INST_ID_DLY) |
582 			     DSI_INST_ID_END  << (4 * DSI_INST_ID_TBA));
583 		break;
584 	case DSI_START_HSC:
585 		regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
586 			     DSI_INST_ID_HSC  << (4 * DSI_INST_ID_LP11) |
587 			     DSI_INST_ID_END  << (4 * DSI_INST_ID_HSC));
588 		break;
589 	case DSI_START_HSD:
590 		regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
591 			     DSI_INST_ID_NOP  << (4 * DSI_INST_ID_LP11) |
592 			     DSI_INST_ID_HSD  << (4 * DSI_INST_ID_NOP) |
593 			     DSI_INST_ID_DLY  << (4 * DSI_INST_ID_HSD) |
594 			     DSI_INST_ID_NOP  << (4 * DSI_INST_ID_DLY) |
595 			     DSI_INST_ID_END  << (4 * DSI_INST_ID_HSCEXIT));
596 		break;
597 	default:
598 		regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
599 			     DSI_INST_ID_END  << (4 * DSI_INST_ID_LP11));
600 		break;
601 	}
602 
603 	sun6i_dsi_inst_abort(dsi);
604 	sun6i_dsi_inst_commit(dsi);
605 
606 	if (func == DSI_START_HSC)
607 		regmap_write_bits(dsi->regs,
608 				  SUN6I_DSI_INST_FUNC_REG(DSI_INST_ID_LP11),
609 				  SUN6I_DSI_INST_FUNC_LANE_CEN, 0);
610 
611 	return 0;
612 }
613 
614 static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
615 {
616 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
617 	struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
618 	struct mipi_dsi_device *device = dsi->device;
619 	u16 delay;
620 
621 	DRM_DEBUG_DRIVER("Enabling DSI output\n");
622 
623 	pm_runtime_get_sync(dsi->dev);
624 
625 	delay = sun6i_dsi_get_video_start_delay(dsi, mode);
626 	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL1_REG,
627 		     SUN6I_DSI_BASIC_CTL1_VIDEO_ST_DELAY(delay) |
628 		     SUN6I_DSI_BASIC_CTL1_VIDEO_FILL |
629 		     SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION |
630 		     SUN6I_DSI_BASIC_CTL1_VIDEO_MODE);
631 
632 	sun6i_dsi_setup_burst(dsi, mode);
633 	sun6i_dsi_setup_inst_loop(dsi, mode);
634 	sun6i_dsi_setup_format(dsi, mode);
635 	sun6i_dsi_setup_timings(dsi, mode);
636 
637 	sun6i_dphy_init(dsi->dphy, device->lanes);
638 	sun6i_dphy_power_on(dsi->dphy, device->lanes);
639 
640 	if (!IS_ERR(dsi->panel))
641 		drm_panel_prepare(dsi->panel);
642 
643 	/*
644 	 * FIXME: This should be moved after the switch to HS mode.
645 	 *
646 	 * Unfortunately, once in HS mode, it seems like we're not
647 	 * able to send DCS commands anymore, which would prevent any
648 	 * panel to send any DCS command as part as their enable
649 	 * method, which is quite common.
650 	 *
651 	 * I haven't seen any artifact due to that sub-optimal
652 	 * ordering on the panels I've tested it with, so I guess this
653 	 * will do for now, until that IP is better understood.
654 	 */
655 	if (!IS_ERR(dsi->panel))
656 		drm_panel_enable(dsi->panel);
657 
658 	sun6i_dsi_start(dsi, DSI_START_HSC);
659 
660 	udelay(1000);
661 
662 	sun6i_dsi_start(dsi, DSI_START_HSD);
663 }
664 
665 static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
666 {
667 	struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
668 
669 	DRM_DEBUG_DRIVER("Disabling DSI output\n");
670 
671 	if (!IS_ERR(dsi->panel)) {
672 		drm_panel_disable(dsi->panel);
673 		drm_panel_unprepare(dsi->panel);
674 	}
675 
676 	sun6i_dphy_power_off(dsi->dphy);
677 	sun6i_dphy_exit(dsi->dphy);
678 
679 	pm_runtime_put(dsi->dev);
680 }
681 
682 static int sun6i_dsi_get_modes(struct drm_connector *connector)
683 {
684 	struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
685 
686 	return drm_panel_get_modes(dsi->panel);
687 }
688 
689 static struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = {
690 	.get_modes	= sun6i_dsi_get_modes,
691 };
692 
693 static enum drm_connector_status
694 sun6i_dsi_connector_detect(struct drm_connector *connector, bool force)
695 {
696 	return connector_status_connected;
697 }
698 
699 static const struct drm_connector_funcs sun6i_dsi_connector_funcs = {
700 	.detect			= sun6i_dsi_connector_detect,
701 	.fill_modes		= drm_helper_probe_single_connector_modes,
702 	.destroy		= drm_connector_cleanup,
703 	.reset			= drm_atomic_helper_connector_reset,
704 	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
705 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
706 };
707 
708 static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
709 	.disable	= sun6i_dsi_encoder_disable,
710 	.enable		= sun6i_dsi_encoder_enable,
711 };
712 
713 static const struct drm_encoder_funcs sun6i_dsi_enc_funcs = {
714 	.destroy	= drm_encoder_cleanup,
715 };
716 
717 static u32 sun6i_dsi_dcs_build_pkt_hdr(struct sun6i_dsi *dsi,
718 				       const struct mipi_dsi_msg *msg)
719 {
720 	u32 pkt = msg->type;
721 
722 	if (msg->type == MIPI_DSI_DCS_LONG_WRITE) {
723 		pkt |= ((msg->tx_len + 1) & 0xffff) << 8;
724 		pkt |= (((msg->tx_len + 1) >> 8) & 0xffff) << 16;
725 	} else {
726 		pkt |= (((u8 *)msg->tx_buf)[0] << 8);
727 		if (msg->tx_len > 1)
728 			pkt |= (((u8 *)msg->tx_buf)[1] << 16);
729 	}
730 
731 	pkt |= sun6i_dsi_ecc_compute(pkt) << 24;
732 
733 	return pkt;
734 }
735 
736 static int sun6i_dsi_dcs_write_short(struct sun6i_dsi *dsi,
737 				     const struct mipi_dsi_msg *msg)
738 {
739 	regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
740 		     sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
741 	regmap_write_bits(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
742 			  0xff, (4 - 1));
743 
744 	sun6i_dsi_start(dsi, DSI_START_LPTX);
745 
746 	return msg->tx_len;
747 }
748 
749 static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
750 				    const struct mipi_dsi_msg *msg)
751 {
752 	int ret, len = 0;
753 	u8 *bounce;
754 	u16 crc;
755 
756 	regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
757 		     sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
758 
759 	bounce = kzalloc(msg->tx_len + sizeof(crc), GFP_KERNEL);
760 	if (!bounce)
761 		return -ENOMEM;
762 
763 	memcpy(bounce, msg->tx_buf, msg->tx_len);
764 	len += msg->tx_len;
765 
766 	crc = sun6i_dsi_crc_compute(bounce, msg->tx_len);
767 	memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
768 	len += sizeof(crc);
769 
770 	regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, len);
771 	regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
772 	kfree(bounce);
773 
774 	sun6i_dsi_start(dsi, DSI_START_LPTX);
775 
776 	ret = sun6i_dsi_inst_wait_for_completion(dsi);
777 	if (ret < 0) {
778 		sun6i_dsi_inst_abort(dsi);
779 		return ret;
780 	}
781 
782 	/*
783 	 * TODO: There's some bits (reg 0x200, bits 8/9) that
784 	 * apparently can be used to check whether the data have been
785 	 * sent, but I couldn't get it to work reliably.
786 	 */
787 	return msg->tx_len;
788 }
789 
790 static int sun6i_dsi_dcs_read(struct sun6i_dsi *dsi,
791 			      const struct mipi_dsi_msg *msg)
792 {
793 	u32 val;
794 	int ret;
795 	u8 byte0;
796 
797 	regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
798 		     sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
799 	regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
800 		     (4 - 1));
801 
802 	sun6i_dsi_start(dsi, DSI_START_LPRX);
803 
804 	ret = sun6i_dsi_inst_wait_for_completion(dsi);
805 	if (ret < 0) {
806 		sun6i_dsi_inst_abort(dsi);
807 		return ret;
808 	}
809 
810 	/*
811 	 * TODO: There's some bits (reg 0x200, bits 24/25) that
812 	 * apparently can be used to check whether the data have been
813 	 * received, but I couldn't get it to work reliably.
814 	 */
815 	regmap_read(dsi->regs, SUN6I_DSI_CMD_CTL_REG, &val);
816 	if (val & SUN6I_DSI_CMD_CTL_RX_OVERFLOW)
817 		return -EIO;
818 
819 	regmap_read(dsi->regs, SUN6I_DSI_CMD_RX_REG(0), &val);
820 	byte0 = val & 0xff;
821 	if (byte0 == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT)
822 		return -EIO;
823 
824 	((u8 *)msg->rx_buf)[0] = (val >> 8);
825 
826 	return 1;
827 }
828 
829 static int sun6i_dsi_attach(struct mipi_dsi_host *host,
830 			    struct mipi_dsi_device *device)
831 {
832 	struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
833 
834 	dsi->device = device;
835 	dsi->panel = of_drm_find_panel(device->dev.of_node);
836 	if (IS_ERR(dsi->panel))
837 		return PTR_ERR(dsi->panel);
838 
839 	dev_info(host->dev, "Attached device %s\n", device->name);
840 
841 	return 0;
842 }
843 
844 static int sun6i_dsi_detach(struct mipi_dsi_host *host,
845 			    struct mipi_dsi_device *device)
846 {
847 	struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
848 
849 	dsi->panel = NULL;
850 	dsi->device = NULL;
851 
852 	return 0;
853 }
854 
855 static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
856 				  const struct mipi_dsi_msg *msg)
857 {
858 	struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
859 	int ret;
860 
861 	ret = sun6i_dsi_inst_wait_for_completion(dsi);
862 	if (ret < 0)
863 		sun6i_dsi_inst_abort(dsi);
864 
865 	regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
866 		     SUN6I_DSI_CMD_CTL_RX_OVERFLOW |
867 		     SUN6I_DSI_CMD_CTL_RX_FLAG |
868 		     SUN6I_DSI_CMD_CTL_TX_FLAG);
869 
870 	switch (msg->type) {
871 	case MIPI_DSI_DCS_SHORT_WRITE:
872 	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
873 		ret = sun6i_dsi_dcs_write_short(dsi, msg);
874 		break;
875 
876 	case MIPI_DSI_DCS_LONG_WRITE:
877 		ret = sun6i_dsi_dcs_write_long(dsi, msg);
878 		break;
879 
880 	case MIPI_DSI_DCS_READ:
881 		if (msg->rx_len == 1) {
882 			ret = sun6i_dsi_dcs_read(dsi, msg);
883 			break;
884 		}
885 
886 	default:
887 		ret = -EINVAL;
888 	}
889 
890 	return ret;
891 }
892 
893 static const struct mipi_dsi_host_ops sun6i_dsi_host_ops = {
894 	.attach		= sun6i_dsi_attach,
895 	.detach		= sun6i_dsi_detach,
896 	.transfer	= sun6i_dsi_transfer,
897 };
898 
899 static const struct regmap_config sun6i_dsi_regmap_config = {
900 	.reg_bits	= 32,
901 	.val_bits	= 32,
902 	.reg_stride	= 4,
903 	.max_register	= SUN6I_DSI_CMD_TX_REG(255),
904 	.name		= "mipi-dsi",
905 };
906 
907 static int sun6i_dsi_bind(struct device *dev, struct device *master,
908 			 void *data)
909 {
910 	struct drm_device *drm = data;
911 	struct sun4i_drv *drv = drm->dev_private;
912 	struct sun6i_dsi *dsi = dev_get_drvdata(dev);
913 	int ret;
914 
915 	if (!dsi->panel)
916 		return -EPROBE_DEFER;
917 
918 	dsi->drv = drv;
919 
920 	drm_encoder_helper_add(&dsi->encoder,
921 			       &sun6i_dsi_enc_helper_funcs);
922 	ret = drm_encoder_init(drm,
923 			       &dsi->encoder,
924 			       &sun6i_dsi_enc_funcs,
925 			       DRM_MODE_ENCODER_DSI,
926 			       NULL);
927 	if (ret) {
928 		dev_err(dsi->dev, "Couldn't initialise the DSI encoder\n");
929 		return ret;
930 	}
931 	dsi->encoder.possible_crtcs = BIT(0);
932 
933 	drm_connector_helper_add(&dsi->connector,
934 				 &sun6i_dsi_connector_helper_funcs);
935 	ret = drm_connector_init(drm, &dsi->connector,
936 				 &sun6i_dsi_connector_funcs,
937 				 DRM_MODE_CONNECTOR_DSI);
938 	if (ret) {
939 		dev_err(dsi->dev,
940 			"Couldn't initialise the DSI connector\n");
941 		goto err_cleanup_connector;
942 	}
943 
944 	drm_connector_attach_encoder(&dsi->connector, &dsi->encoder);
945 	drm_panel_attach(dsi->panel, &dsi->connector);
946 
947 	return 0;
948 
949 err_cleanup_connector:
950 	drm_encoder_cleanup(&dsi->encoder);
951 	return ret;
952 }
953 
954 static void sun6i_dsi_unbind(struct device *dev, struct device *master,
955 			    void *data)
956 {
957 	struct sun6i_dsi *dsi = dev_get_drvdata(dev);
958 
959 	drm_panel_detach(dsi->panel);
960 }
961 
962 static const struct component_ops sun6i_dsi_ops = {
963 	.bind	= sun6i_dsi_bind,
964 	.unbind	= sun6i_dsi_unbind,
965 };
966 
967 static int sun6i_dsi_probe(struct platform_device *pdev)
968 {
969 	struct device *dev = &pdev->dev;
970 	struct device_node *dphy_node;
971 	struct sun6i_dsi *dsi;
972 	struct resource *res;
973 	void __iomem *base;
974 	int ret;
975 
976 	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
977 	if (!dsi)
978 		return -ENOMEM;
979 	dev_set_drvdata(dev, dsi);
980 	dsi->dev = dev;
981 	dsi->host.ops = &sun6i_dsi_host_ops;
982 	dsi->host.dev = dev;
983 
984 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
985 	base = devm_ioremap_resource(dev, res);
986 	if (IS_ERR(base)) {
987 		dev_err(dev, "Couldn't map the DSI encoder registers\n");
988 		return PTR_ERR(base);
989 	}
990 
991 	dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
992 					      &sun6i_dsi_regmap_config);
993 	if (IS_ERR(dsi->regs)) {
994 		dev_err(dev, "Couldn't create the DSI encoder regmap\n");
995 		return PTR_ERR(dsi->regs);
996 	}
997 
998 	dsi->reset = devm_reset_control_get_shared(dev, NULL);
999 	if (IS_ERR(dsi->reset)) {
1000 		dev_err(dev, "Couldn't get our reset line\n");
1001 		return PTR_ERR(dsi->reset);
1002 	}
1003 
1004 	dsi->mod_clk = devm_clk_get(dev, "mod");
1005 	if (IS_ERR(dsi->mod_clk)) {
1006 		dev_err(dev, "Couldn't get the DSI mod clock\n");
1007 		return PTR_ERR(dsi->mod_clk);
1008 	}
1009 
1010 	/*
1011 	 * In order to operate properly, that clock seems to be always
1012 	 * set to 297MHz.
1013 	 */
1014 	clk_set_rate_exclusive(dsi->mod_clk, 297000000);
1015 
1016 	dphy_node = of_parse_phandle(dev->of_node, "phys", 0);
1017 	ret = sun6i_dphy_probe(dsi, dphy_node);
1018 	of_node_put(dphy_node);
1019 	if (ret) {
1020 		dev_err(dev, "Couldn't get the MIPI D-PHY\n");
1021 		goto err_unprotect_clk;
1022 	}
1023 
1024 	pm_runtime_enable(dev);
1025 
1026 	ret = mipi_dsi_host_register(&dsi->host);
1027 	if (ret) {
1028 		dev_err(dev, "Couldn't register MIPI-DSI host\n");
1029 		goto err_remove_phy;
1030 	}
1031 
1032 	ret = component_add(&pdev->dev, &sun6i_dsi_ops);
1033 	if (ret) {
1034 		dev_err(dev, "Couldn't register our component\n");
1035 		goto err_remove_dsi_host;
1036 	}
1037 
1038 	return 0;
1039 
1040 err_remove_dsi_host:
1041 	mipi_dsi_host_unregister(&dsi->host);
1042 err_remove_phy:
1043 	pm_runtime_disable(dev);
1044 	sun6i_dphy_remove(dsi);
1045 err_unprotect_clk:
1046 	clk_rate_exclusive_put(dsi->mod_clk);
1047 	return ret;
1048 }
1049 
1050 static int sun6i_dsi_remove(struct platform_device *pdev)
1051 {
1052 	struct device *dev = &pdev->dev;
1053 	struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1054 
1055 	component_del(&pdev->dev, &sun6i_dsi_ops);
1056 	mipi_dsi_host_unregister(&dsi->host);
1057 	pm_runtime_disable(dev);
1058 	sun6i_dphy_remove(dsi);
1059 	clk_rate_exclusive_put(dsi->mod_clk);
1060 
1061 	return 0;
1062 }
1063 
1064 static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
1065 {
1066 	struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1067 
1068 	reset_control_deassert(dsi->reset);
1069 	clk_prepare_enable(dsi->mod_clk);
1070 
1071 	/*
1072 	 * Enable the DSI block.
1073 	 *
1074 	 * Some part of it can only be done once we get a number of
1075 	 * lanes, see sun6i_dsi_inst_init
1076 	 */
1077 	regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN);
1078 
1079 	regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
1080 		     SUN6I_DSI_BASIC_CTL0_ECC_EN | SUN6I_DSI_BASIC_CTL0_CRC_EN);
1081 
1082 	regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10);
1083 	regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0);
1084 
1085 	if (dsi->device)
1086 		sun6i_dsi_inst_init(dsi, dsi->device);
1087 
1088 	regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff);
1089 
1090 	return 0;
1091 }
1092 
1093 static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
1094 {
1095 	struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1096 
1097 	clk_disable_unprepare(dsi->mod_clk);
1098 	reset_control_assert(dsi->reset);
1099 
1100 	return 0;
1101 }
1102 
1103 static const struct dev_pm_ops sun6i_dsi_pm_ops = {
1104 	SET_RUNTIME_PM_OPS(sun6i_dsi_runtime_suspend,
1105 			   sun6i_dsi_runtime_resume,
1106 			   NULL)
1107 };
1108 
1109 static const struct of_device_id sun6i_dsi_of_table[] = {
1110 	{ .compatible = "allwinner,sun6i-a31-mipi-dsi" },
1111 	{ }
1112 };
1113 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
1114 
1115 static struct platform_driver sun6i_dsi_platform_driver = {
1116 	.probe		= sun6i_dsi_probe,
1117 	.remove		= sun6i_dsi_remove,
1118 	.driver		= {
1119 		.name		= "sun6i-mipi-dsi",
1120 		.of_match_table	= sun6i_dsi_of_table,
1121 		.pm		= &sun6i_dsi_pm_ops,
1122 	},
1123 };
1124 module_platform_driver(sun6i_dsi_platform_driver);
1125 
1126 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1127 MODULE_DESCRIPTION("Allwinner A31 DSI Driver");
1128 MODULE_LICENSE("GPL");
1129