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