GNU Linux-libre 4.19.264-gnu1
[releases.git] / drivers / gpu / drm / sun4i / sun6i_mipi_dsi.c
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_crtc_helper.h>
23 #include <drm/drm_mipi_dsi.h>
24 #include <drm/drm_panel.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         u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + 1;
361
362         if (delay > mode->vtotal)
363                 delay = delay % mode->vtotal;
364
365         return max_t(u16, delay, 1);
366 }
367
368 static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
369                                   struct drm_display_mode *mode)
370 {
371         struct mipi_dsi_device *device = dsi->device;
372         u32 val = 0;
373
374         if ((mode->hsync_end - mode->hdisplay) > 20) {
375                 /* Maaaaaagic */
376                 u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
377
378                 drq *= mipi_dsi_pixel_format_to_bpp(device->format);
379                 drq /= 32;
380
381                 val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
382                        SUN6I_DSI_TCON_DRQ_SET(drq));
383         }
384
385         regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val);
386 }
387
388 static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
389                                       struct drm_display_mode *mode)
390 {
391         u16 delay = 50 - 1;
392
393         regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
394                      SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
395                      SUN6I_DSI_INST_LOOP_NUM_N1(delay));
396         regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(1),
397                      SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
398                      SUN6I_DSI_INST_LOOP_NUM_N1(delay));
399 }
400
401 static void sun6i_dsi_setup_format(struct sun6i_dsi *dsi,
402                                    struct drm_display_mode *mode)
403 {
404         struct mipi_dsi_device *device = dsi->device;
405         u32 val = SUN6I_DSI_PIXEL_PH_VC(device->channel);
406         u8 dt, fmt;
407         u16 wc;
408
409         /*
410          * TODO: The format defines are only valid in video mode and
411          * change in command mode.
412          */
413         switch (device->format) {
414         case MIPI_DSI_FMT_RGB888:
415                 dt = MIPI_DSI_PACKED_PIXEL_STREAM_24;
416                 fmt = 8;
417                 break;
418         case MIPI_DSI_FMT_RGB666:
419                 dt = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
420                 fmt = 9;
421                 break;
422         case MIPI_DSI_FMT_RGB666_PACKED:
423                 dt = MIPI_DSI_PACKED_PIXEL_STREAM_18;
424                 fmt = 10;
425                 break;
426         case MIPI_DSI_FMT_RGB565:
427                 dt = MIPI_DSI_PACKED_PIXEL_STREAM_16;
428                 fmt = 11;
429                 break;
430         default:
431                 return;
432         }
433         val |= SUN6I_DSI_PIXEL_PH_DT(dt);
434
435         wc = mode->hdisplay * mipi_dsi_pixel_format_to_bpp(device->format) / 8;
436         val |= SUN6I_DSI_PIXEL_PH_WC(wc);
437         val |= SUN6I_DSI_PIXEL_PH_ECC(sun6i_dsi_ecc_compute(val));
438
439         regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PH_REG, val);
440
441         regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF0_REG,
442                      SUN6I_DSI_PIXEL_PF0_CRC_FORCE(0xffff));
443
444         regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF1_REG,
445                      SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINE0(0xffff) |
446                      SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINEN(0xffff));
447
448         regmap_write(dsi->regs, SUN6I_DSI_PIXEL_CTL0_REG,
449                      SUN6I_DSI_PIXEL_CTL0_PD_PLUG_DISABLE |
450                      SUN6I_DSI_PIXEL_CTL0_FORMAT(fmt));
451 }
452
453 static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
454                                     struct drm_display_mode *mode)
455 {
456         struct mipi_dsi_device *device = dsi->device;
457         unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
458         u16 hbp, hfp, hsa, hblk, vblk;
459         size_t bytes;
460         u8 *buffer;
461
462         /* Do all timing calculations up front to allocate buffer space */
463
464         /*
465          * A sync period is composed of a blanking packet (4 bytes +
466          * payload + 2 bytes) and a sync event packet (4 bytes). Its
467          * minimal size is therefore 10 bytes
468          */
469 #define HSA_PACKET_OVERHEAD     10
470         hsa = max((unsigned int)HSA_PACKET_OVERHEAD,
471                   (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
472
473         /*
474          * The backporch is set using a blanking packet (4 bytes +
475          * payload + 2 bytes). Its minimal size is therefore 6 bytes
476          */
477 #define HBP_PACKET_OVERHEAD     6
478         hbp = max((unsigned int)HBP_PACKET_OVERHEAD,
479                   (mode->hsync_start - mode->hdisplay) * Bpp - HBP_PACKET_OVERHEAD);
480
481         /*
482          * The frontporch is set using a blanking packet (4 bytes +
483          * payload + 2 bytes). Its minimal size is therefore 6 bytes
484          */
485 #define HFP_PACKET_OVERHEAD     6
486         hfp = max((unsigned int)HFP_PACKET_OVERHEAD,
487                   (mode->htotal - mode->hsync_end) * Bpp - HFP_PACKET_OVERHEAD);
488
489         /*
490          * hblk seems to be the line + porches length.
491          */
492         hblk = mode->htotal * Bpp - hsa;
493
494         /*
495          * And I'm not entirely sure what vblk is about. The driver in
496          * Allwinner BSP is using a rather convoluted calculation
497          * there only for 4 lanes. However, using 0 (the !4 lanes
498          * case) even with a 4 lanes screen seems to work...
499          */
500         vblk = 0;
501
502         /* How many bytes do we need to send all payloads? */
503         bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
504         buffer = kmalloc(bytes, GFP_KERNEL);
505         if (WARN_ON(!buffer))
506                 return;
507
508         regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, 0);
509
510         regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG,
511                      sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
512                                               device->channel,
513                                               0, 0));
514
515         regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSE_REG,
516                      sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_END,
517                                               device->channel,
518                                               0, 0));
519
520         regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSS_REG,
521                      sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_START,
522                                               device->channel,
523                                               0, 0));
524
525         regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSE_REG,
526                      sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_END,
527                                               device->channel,
528                                               0, 0));
529
530         regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE0_REG,
531                      SUN6I_DSI_BASIC_SIZE0_VSA(mode->vsync_end -
532                                                mode->vsync_start) |
533                      SUN6I_DSI_BASIC_SIZE0_VBP(mode->vsync_start -
534                                                mode->vdisplay));
535
536         regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE1_REG,
537                      SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
538                      SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal));
539
540         /* sync */
541         regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG,
542                      sun6i_dsi_build_blk0_pkt(device->channel, hsa));
543         regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG,
544                      sun6i_dsi_build_blk1_pkt(0, buffer, hsa));
545
546         /* backporch */
547         regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG,
548                      sun6i_dsi_build_blk0_pkt(device->channel, hbp));
549         regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG,
550                      sun6i_dsi_build_blk1_pkt(0, buffer, hbp));
551
552         /* frontporch */
553         regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG,
554                      sun6i_dsi_build_blk0_pkt(device->channel, hfp));
555         regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG,
556                      sun6i_dsi_build_blk1_pkt(0, buffer, hfp));
557
558         /* hblk */
559         regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG,
560                      sun6i_dsi_build_blk0_pkt(device->channel, hblk));
561         regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG,
562                      sun6i_dsi_build_blk1_pkt(0, buffer, hblk));
563
564         /* vblk */
565         regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG,
566                      sun6i_dsi_build_blk0_pkt(device->channel, vblk));
567         regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG,
568                      sun6i_dsi_build_blk1_pkt(0, buffer, vblk));
569
570         kfree(buffer);
571 }
572
573 static int sun6i_dsi_start(struct sun6i_dsi *dsi,
574                            enum sun6i_dsi_start_inst func)
575 {
576         switch (func) {
577         case DSI_START_LPTX:
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_END  << (4 * DSI_INST_ID_LPDT));
581                 break;
582         case DSI_START_LPRX:
583                 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
584                              DSI_INST_ID_LPDT << (4 * DSI_INST_ID_LP11) |
585                              DSI_INST_ID_DLY  << (4 * DSI_INST_ID_LPDT) |
586                              DSI_INST_ID_TBA  << (4 * DSI_INST_ID_DLY) |
587                              DSI_INST_ID_END  << (4 * DSI_INST_ID_TBA));
588                 break;
589         case DSI_START_HSC:
590                 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
591                              DSI_INST_ID_HSC  << (4 * DSI_INST_ID_LP11) |
592                              DSI_INST_ID_END  << (4 * DSI_INST_ID_HSC));
593                 break;
594         case DSI_START_HSD:
595                 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
596                              DSI_INST_ID_NOP  << (4 * DSI_INST_ID_LP11) |
597                              DSI_INST_ID_HSD  << (4 * DSI_INST_ID_NOP) |
598                              DSI_INST_ID_DLY  << (4 * DSI_INST_ID_HSD) |
599                              DSI_INST_ID_NOP  << (4 * DSI_INST_ID_DLY) |
600                              DSI_INST_ID_END  << (4 * DSI_INST_ID_HSCEXIT));
601                 break;
602         default:
603                 regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
604                              DSI_INST_ID_END  << (4 * DSI_INST_ID_LP11));
605                 break;
606         }
607
608         sun6i_dsi_inst_abort(dsi);
609         sun6i_dsi_inst_commit(dsi);
610
611         if (func == DSI_START_HSC)
612                 regmap_write_bits(dsi->regs,
613                                   SUN6I_DSI_INST_FUNC_REG(DSI_INST_ID_LP11),
614                                   SUN6I_DSI_INST_FUNC_LANE_CEN, 0);
615
616         return 0;
617 }
618
619 static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
620 {
621         struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
622         struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
623         struct mipi_dsi_device *device = dsi->device;
624         u16 delay;
625
626         DRM_DEBUG_DRIVER("Enabling DSI output\n");
627
628         pm_runtime_get_sync(dsi->dev);
629
630         delay = sun6i_dsi_get_video_start_delay(dsi, mode);
631         regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL1_REG,
632                      SUN6I_DSI_BASIC_CTL1_VIDEO_ST_DELAY(delay) |
633                      SUN6I_DSI_BASIC_CTL1_VIDEO_FILL |
634                      SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION |
635                      SUN6I_DSI_BASIC_CTL1_VIDEO_MODE);
636
637         sun6i_dsi_setup_burst(dsi, mode);
638         sun6i_dsi_setup_inst_loop(dsi, mode);
639         sun6i_dsi_setup_format(dsi, mode);
640         sun6i_dsi_setup_timings(dsi, mode);
641
642         sun6i_dphy_init(dsi->dphy, device->lanes);
643         sun6i_dphy_power_on(dsi->dphy, device->lanes);
644
645         if (!IS_ERR(dsi->panel))
646                 drm_panel_prepare(dsi->panel);
647
648         /*
649          * FIXME: This should be moved after the switch to HS mode.
650          *
651          * Unfortunately, once in HS mode, it seems like we're not
652          * able to send DCS commands anymore, which would prevent any
653          * panel to send any DCS command as part as their enable
654          * method, which is quite common.
655          *
656          * I haven't seen any artifact due to that sub-optimal
657          * ordering on the panels I've tested it with, so I guess this
658          * will do for now, until that IP is better understood.
659          */
660         if (!IS_ERR(dsi->panel))
661                 drm_panel_enable(dsi->panel);
662
663         sun6i_dsi_start(dsi, DSI_START_HSC);
664
665         udelay(1000);
666
667         sun6i_dsi_start(dsi, DSI_START_HSD);
668 }
669
670 static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
671 {
672         struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
673
674         DRM_DEBUG_DRIVER("Disabling DSI output\n");
675
676         if (!IS_ERR(dsi->panel)) {
677                 drm_panel_disable(dsi->panel);
678                 drm_panel_unprepare(dsi->panel);
679         }
680
681         sun6i_dphy_power_off(dsi->dphy);
682         sun6i_dphy_exit(dsi->dphy);
683
684         pm_runtime_put(dsi->dev);
685 }
686
687 static int sun6i_dsi_get_modes(struct drm_connector *connector)
688 {
689         struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
690
691         return drm_panel_get_modes(dsi->panel);
692 }
693
694 static struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = {
695         .get_modes      = sun6i_dsi_get_modes,
696 };
697
698 static enum drm_connector_status
699 sun6i_dsi_connector_detect(struct drm_connector *connector, bool force)
700 {
701         return connector_status_connected;
702 }
703
704 static const struct drm_connector_funcs sun6i_dsi_connector_funcs = {
705         .detect                 = sun6i_dsi_connector_detect,
706         .fill_modes             = drm_helper_probe_single_connector_modes,
707         .destroy                = drm_connector_cleanup,
708         .reset                  = drm_atomic_helper_connector_reset,
709         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
710         .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
711 };
712
713 static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
714         .disable        = sun6i_dsi_encoder_disable,
715         .enable         = sun6i_dsi_encoder_enable,
716 };
717
718 static const struct drm_encoder_funcs sun6i_dsi_enc_funcs = {
719         .destroy        = drm_encoder_cleanup,
720 };
721
722 static u32 sun6i_dsi_dcs_build_pkt_hdr(struct sun6i_dsi *dsi,
723                                        const struct mipi_dsi_msg *msg)
724 {
725         u32 pkt = msg->type;
726
727         if (msg->type == MIPI_DSI_DCS_LONG_WRITE) {
728                 pkt |= ((msg->tx_len + 1) & 0xffff) << 8;
729                 pkt |= (((msg->tx_len + 1) >> 8) & 0xffff) << 16;
730         } else {
731                 pkt |= (((u8 *)msg->tx_buf)[0] << 8);
732                 if (msg->tx_len > 1)
733                         pkt |= (((u8 *)msg->tx_buf)[1] << 16);
734         }
735
736         pkt |= sun6i_dsi_ecc_compute(pkt) << 24;
737
738         return pkt;
739 }
740
741 static int sun6i_dsi_dcs_write_short(struct sun6i_dsi *dsi,
742                                      const struct mipi_dsi_msg *msg)
743 {
744         regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
745                      sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
746         regmap_write_bits(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
747                           0xff, (4 - 1));
748
749         sun6i_dsi_start(dsi, DSI_START_LPTX);
750
751         return msg->tx_len;
752 }
753
754 static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
755                                     const struct mipi_dsi_msg *msg)
756 {
757         int ret, len = 0;
758         u8 *bounce;
759         u16 crc;
760
761         regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
762                      sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
763
764         bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL);
765         if (!bounce)
766                 return -ENOMEM;
767
768         memcpy(bounce, msg->tx_buf, msg->tx_len);
769         len += msg->tx_len;
770
771         crc = sun6i_dsi_crc_compute(bounce, msg->tx_len);
772         memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
773         len += sizeof(crc);
774
775         regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4));
776         regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
777         kfree(bounce);
778
779         sun6i_dsi_start(dsi, DSI_START_LPTX);
780
781         ret = sun6i_dsi_inst_wait_for_completion(dsi);
782         if (ret < 0) {
783                 sun6i_dsi_inst_abort(dsi);
784                 return ret;
785         }
786
787         /*
788          * TODO: There's some bits (reg 0x200, bits 8/9) that
789          * apparently can be used to check whether the data have been
790          * sent, but I couldn't get it to work reliably.
791          */
792         return msg->tx_len;
793 }
794
795 static int sun6i_dsi_dcs_read(struct sun6i_dsi *dsi,
796                               const struct mipi_dsi_msg *msg)
797 {
798         u32 val;
799         int ret;
800         u8 byte0;
801
802         regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
803                      sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
804         regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
805                      (4 - 1));
806
807         sun6i_dsi_start(dsi, DSI_START_LPRX);
808
809         ret = sun6i_dsi_inst_wait_for_completion(dsi);
810         if (ret < 0) {
811                 sun6i_dsi_inst_abort(dsi);
812                 return ret;
813         }
814
815         /*
816          * TODO: There's some bits (reg 0x200, bits 24/25) that
817          * apparently can be used to check whether the data have been
818          * received, but I couldn't get it to work reliably.
819          */
820         regmap_read(dsi->regs, SUN6I_DSI_CMD_CTL_REG, &val);
821         if (val & SUN6I_DSI_CMD_CTL_RX_OVERFLOW)
822                 return -EIO;
823
824         regmap_read(dsi->regs, SUN6I_DSI_CMD_RX_REG(0), &val);
825         byte0 = val & 0xff;
826         if (byte0 == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT)
827                 return -EIO;
828
829         ((u8 *)msg->rx_buf)[0] = (val >> 8);
830
831         return 1;
832 }
833
834 static int sun6i_dsi_attach(struct mipi_dsi_host *host,
835                             struct mipi_dsi_device *device)
836 {
837         struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
838
839         dsi->device = device;
840         dsi->panel = of_drm_find_panel(device->dev.of_node);
841         if (IS_ERR(dsi->panel))
842                 return PTR_ERR(dsi->panel);
843
844         dev_info(host->dev, "Attached device %s\n", device->name);
845
846         return 0;
847 }
848
849 static int sun6i_dsi_detach(struct mipi_dsi_host *host,
850                             struct mipi_dsi_device *device)
851 {
852         struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
853
854         dsi->panel = NULL;
855         dsi->device = NULL;
856
857         return 0;
858 }
859
860 static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
861                                   const struct mipi_dsi_msg *msg)
862 {
863         struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
864         int ret;
865
866         ret = sun6i_dsi_inst_wait_for_completion(dsi);
867         if (ret < 0)
868                 sun6i_dsi_inst_abort(dsi);
869
870         regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
871                      SUN6I_DSI_CMD_CTL_RX_OVERFLOW |
872                      SUN6I_DSI_CMD_CTL_RX_FLAG |
873                      SUN6I_DSI_CMD_CTL_TX_FLAG);
874
875         switch (msg->type) {
876         case MIPI_DSI_DCS_SHORT_WRITE:
877         case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
878                 ret = sun6i_dsi_dcs_write_short(dsi, msg);
879                 break;
880
881         case MIPI_DSI_DCS_LONG_WRITE:
882                 ret = sun6i_dsi_dcs_write_long(dsi, msg);
883                 break;
884
885         case MIPI_DSI_DCS_READ:
886                 if (msg->rx_len == 1) {
887                         ret = sun6i_dsi_dcs_read(dsi, msg);
888                         break;
889                 }
890
891         default:
892                 ret = -EINVAL;
893         }
894
895         return ret;
896 }
897
898 static const struct mipi_dsi_host_ops sun6i_dsi_host_ops = {
899         .attach         = sun6i_dsi_attach,
900         .detach         = sun6i_dsi_detach,
901         .transfer       = sun6i_dsi_transfer,
902 };
903
904 static const struct regmap_config sun6i_dsi_regmap_config = {
905         .reg_bits       = 32,
906         .val_bits       = 32,
907         .reg_stride     = 4,
908         .max_register   = SUN6I_DSI_CMD_TX_REG(255),
909         .name           = "mipi-dsi",
910 };
911
912 static int sun6i_dsi_bind(struct device *dev, struct device *master,
913                          void *data)
914 {
915         struct drm_device *drm = data;
916         struct sun4i_drv *drv = drm->dev_private;
917         struct sun6i_dsi *dsi = dev_get_drvdata(dev);
918         int ret;
919
920         if (!dsi->panel)
921                 return -EPROBE_DEFER;
922
923         dsi->drv = drv;
924
925         drm_encoder_helper_add(&dsi->encoder,
926                                &sun6i_dsi_enc_helper_funcs);
927         ret = drm_encoder_init(drm,
928                                &dsi->encoder,
929                                &sun6i_dsi_enc_funcs,
930                                DRM_MODE_ENCODER_DSI,
931                                NULL);
932         if (ret) {
933                 dev_err(dsi->dev, "Couldn't initialise the DSI encoder\n");
934                 return ret;
935         }
936         dsi->encoder.possible_crtcs = BIT(0);
937
938         drm_connector_helper_add(&dsi->connector,
939                                  &sun6i_dsi_connector_helper_funcs);
940         ret = drm_connector_init(drm, &dsi->connector,
941                                  &sun6i_dsi_connector_funcs,
942                                  DRM_MODE_CONNECTOR_DSI);
943         if (ret) {
944                 dev_err(dsi->dev,
945                         "Couldn't initialise the DSI connector\n");
946                 goto err_cleanup_connector;
947         }
948
949         drm_connector_attach_encoder(&dsi->connector, &dsi->encoder);
950         drm_panel_attach(dsi->panel, &dsi->connector);
951
952         return 0;
953
954 err_cleanup_connector:
955         drm_encoder_cleanup(&dsi->encoder);
956         return ret;
957 }
958
959 static void sun6i_dsi_unbind(struct device *dev, struct device *master,
960                             void *data)
961 {
962         struct sun6i_dsi *dsi = dev_get_drvdata(dev);
963
964         drm_panel_detach(dsi->panel);
965 }
966
967 static const struct component_ops sun6i_dsi_ops = {
968         .bind   = sun6i_dsi_bind,
969         .unbind = sun6i_dsi_unbind,
970 };
971
972 static int sun6i_dsi_probe(struct platform_device *pdev)
973 {
974         struct device *dev = &pdev->dev;
975         struct device_node *dphy_node;
976         struct sun6i_dsi *dsi;
977         struct resource *res;
978         void __iomem *base;
979         int ret;
980
981         dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
982         if (!dsi)
983                 return -ENOMEM;
984         dev_set_drvdata(dev, dsi);
985         dsi->dev = dev;
986         dsi->host.ops = &sun6i_dsi_host_ops;
987         dsi->host.dev = dev;
988
989         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
990         base = devm_ioremap_resource(dev, res);
991         if (IS_ERR(base)) {
992                 dev_err(dev, "Couldn't map the DSI encoder registers\n");
993                 return PTR_ERR(base);
994         }
995
996         dsi->regs = devm_regmap_init_mmio_clk(dev, "bus", base,
997                                               &sun6i_dsi_regmap_config);
998         if (IS_ERR(dsi->regs)) {
999                 dev_err(dev, "Couldn't create the DSI encoder regmap\n");
1000                 return PTR_ERR(dsi->regs);
1001         }
1002
1003         dsi->reset = devm_reset_control_get_shared(dev, NULL);
1004         if (IS_ERR(dsi->reset)) {
1005                 dev_err(dev, "Couldn't get our reset line\n");
1006                 return PTR_ERR(dsi->reset);
1007         }
1008
1009         dsi->mod_clk = devm_clk_get(dev, "mod");
1010         if (IS_ERR(dsi->mod_clk)) {
1011                 dev_err(dev, "Couldn't get the DSI mod clock\n");
1012                 return PTR_ERR(dsi->mod_clk);
1013         }
1014
1015         /*
1016          * In order to operate properly, that clock seems to be always
1017          * set to 297MHz.
1018          */
1019         clk_set_rate_exclusive(dsi->mod_clk, 297000000);
1020
1021         dphy_node = of_parse_phandle(dev->of_node, "phys", 0);
1022         ret = sun6i_dphy_probe(dsi, dphy_node);
1023         of_node_put(dphy_node);
1024         if (ret) {
1025                 dev_err(dev, "Couldn't get the MIPI D-PHY\n");
1026                 goto err_unprotect_clk;
1027         }
1028
1029         pm_runtime_enable(dev);
1030
1031         ret = mipi_dsi_host_register(&dsi->host);
1032         if (ret) {
1033                 dev_err(dev, "Couldn't register MIPI-DSI host\n");
1034                 goto err_remove_phy;
1035         }
1036
1037         ret = component_add(&pdev->dev, &sun6i_dsi_ops);
1038         if (ret) {
1039                 dev_err(dev, "Couldn't register our component\n");
1040                 goto err_remove_dsi_host;
1041         }
1042
1043         return 0;
1044
1045 err_remove_dsi_host:
1046         mipi_dsi_host_unregister(&dsi->host);
1047 err_remove_phy:
1048         pm_runtime_disable(dev);
1049         sun6i_dphy_remove(dsi);
1050 err_unprotect_clk:
1051         clk_rate_exclusive_put(dsi->mod_clk);
1052         return ret;
1053 }
1054
1055 static int sun6i_dsi_remove(struct platform_device *pdev)
1056 {
1057         struct device *dev = &pdev->dev;
1058         struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1059
1060         component_del(&pdev->dev, &sun6i_dsi_ops);
1061         mipi_dsi_host_unregister(&dsi->host);
1062         pm_runtime_disable(dev);
1063         sun6i_dphy_remove(dsi);
1064         clk_rate_exclusive_put(dsi->mod_clk);
1065
1066         return 0;
1067 }
1068
1069 static int __maybe_unused sun6i_dsi_runtime_resume(struct device *dev)
1070 {
1071         struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1072
1073         reset_control_deassert(dsi->reset);
1074         clk_prepare_enable(dsi->mod_clk);
1075
1076         /*
1077          * Enable the DSI block.
1078          *
1079          * Some part of it can only be done once we get a number of
1080          * lanes, see sun6i_dsi_inst_init
1081          */
1082         regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN);
1083
1084         regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
1085                      SUN6I_DSI_BASIC_CTL0_ECC_EN | SUN6I_DSI_BASIC_CTL0_CRC_EN);
1086
1087         regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10);
1088         regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0);
1089
1090         if (dsi->device)
1091                 sun6i_dsi_inst_init(dsi, dsi->device);
1092
1093         regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff);
1094
1095         return 0;
1096 }
1097
1098 static int __maybe_unused sun6i_dsi_runtime_suspend(struct device *dev)
1099 {
1100         struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1101
1102         clk_disable_unprepare(dsi->mod_clk);
1103         reset_control_assert(dsi->reset);
1104
1105         return 0;
1106 }
1107
1108 static const struct dev_pm_ops sun6i_dsi_pm_ops = {
1109         SET_RUNTIME_PM_OPS(sun6i_dsi_runtime_suspend,
1110                            sun6i_dsi_runtime_resume,
1111                            NULL)
1112 };
1113
1114 static const struct of_device_id sun6i_dsi_of_table[] = {
1115         { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
1116         { }
1117 };
1118 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
1119
1120 static struct platform_driver sun6i_dsi_platform_driver = {
1121         .probe          = sun6i_dsi_probe,
1122         .remove         = sun6i_dsi_remove,
1123         .driver         = {
1124                 .name           = "sun6i-mipi-dsi",
1125                 .of_match_table = sun6i_dsi_of_table,
1126                 .pm             = &sun6i_dsi_pm_ops,
1127         },
1128 };
1129 module_platform_driver(sun6i_dsi_platform_driver);
1130
1131 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1132 MODULE_DESCRIPTION("Allwinner A31 DSI Driver");
1133 MODULE_LICENSE("GPL");