Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (c) 2016 Allwinnertech Co., Ltd.
0004  * Copyright (C) 2017-2018 Bootlin
0005  *
0006  * Maxime Ripard <maxime.ripard@bootlin.com>
0007  */
0008 
0009 #include <linux/clk.h>
0010 #include <linux/component.h>
0011 #include <linux/crc-ccitt.h>
0012 #include <linux/module.h>
0013 #include <linux/of_address.h>
0014 #include <linux/phy/phy-mipi-dphy.h>
0015 #include <linux/phy/phy.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/regmap.h>
0018 #include <linux/regulator/consumer.h>
0019 #include <linux/reset.h>
0020 #include <linux/slab.h>
0021 
0022 #include <drm/drm_atomic_helper.h>
0023 #include <drm/drm_mipi_dsi.h>
0024 #include <drm/drm_panel.h>
0025 #include <drm/drm_print.h>
0026 #include <drm/drm_probe_helper.h>
0027 #include <drm/drm_simple_kms_helper.h>
0028 
0029 #include "sun4i_crtc.h"
0030 #include "sun4i_tcon.h"
0031 #include "sun6i_mipi_dsi.h"
0032 
0033 #include <video/mipi_display.h>
0034 
0035 #define SUN6I_DSI_CTL_REG       0x000
0036 #define SUN6I_DSI_CTL_EN            BIT(0)
0037 
0038 #define SUN6I_DSI_BASIC_CTL_REG     0x00c
0039 #define SUN6I_DSI_BASIC_CTL_TRAIL_INV(n)        (((n) & 0xf) << 4)
0040 #define SUN6I_DSI_BASIC_CTL_TRAIL_FILL      BIT(3)
0041 #define SUN6I_DSI_BASIC_CTL_HBP_DIS     BIT(2)
0042 #define SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS     BIT(1)
0043 #define SUN6I_DSI_BASIC_CTL_VIDEO_BURST     BIT(0)
0044 
0045 #define SUN6I_DSI_BASIC_CTL0_REG    0x010
0046 #define SUN6I_DSI_BASIC_CTL0_HS_EOTP_EN     BIT(18)
0047 #define SUN6I_DSI_BASIC_CTL0_CRC_EN     BIT(17)
0048 #define SUN6I_DSI_BASIC_CTL0_ECC_EN     BIT(16)
0049 #define SUN6I_DSI_BASIC_CTL0_INST_ST        BIT(0)
0050 
0051 #define SUN6I_DSI_BASIC_CTL1_REG    0x014
0052 #define SUN6I_DSI_BASIC_CTL1_VIDEO_ST_DELAY(n)  (((n) & 0x1fff) << 4)
0053 #define SUN6I_DSI_BASIC_CTL1_VIDEO_FILL     BIT(2)
0054 #define SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION    BIT(1)
0055 #define SUN6I_DSI_BASIC_CTL1_VIDEO_MODE     BIT(0)
0056 
0057 #define SUN6I_DSI_BASIC_SIZE0_REG   0x018
0058 #define SUN6I_DSI_BASIC_SIZE0_VBP(n)        (((n) & 0xfff) << 16)
0059 #define SUN6I_DSI_BASIC_SIZE0_VSA(n)        ((n) & 0xfff)
0060 
0061 #define SUN6I_DSI_BASIC_SIZE1_REG   0x01c
0062 #define SUN6I_DSI_BASIC_SIZE1_VT(n)     (((n) & 0xfff) << 16)
0063 #define SUN6I_DSI_BASIC_SIZE1_VACT(n)       ((n) & 0xfff)
0064 
0065 #define SUN6I_DSI_INST_FUNC_REG(n)  (0x020 + (n) * 0x04)
0066 #define SUN6I_DSI_INST_FUNC_INST_MODE(n)    (((n) & 0xf) << 28)
0067 #define SUN6I_DSI_INST_FUNC_ESCAPE_ENTRY(n) (((n) & 0xf) << 24)
0068 #define SUN6I_DSI_INST_FUNC_TRANS_PACKET(n) (((n) & 0xf) << 20)
0069 #define SUN6I_DSI_INST_FUNC_LANE_CEN        BIT(4)
0070 #define SUN6I_DSI_INST_FUNC_LANE_DEN(n)     ((n) & 0xf)
0071 
0072 #define SUN6I_DSI_INST_LOOP_SEL_REG 0x040
0073 
0074 #define SUN6I_DSI_INST_LOOP_NUM_REG(n)  (0x044 + (n) * 0x10)
0075 #define SUN6I_DSI_INST_LOOP_NUM_N1(n)       (((n) & 0xfff) << 16)
0076 #define SUN6I_DSI_INST_LOOP_NUM_N0(n)       ((n) & 0xfff)
0077 
0078 #define SUN6I_DSI_INST_JUMP_SEL_REG 0x048
0079 
0080 #define SUN6I_DSI_INST_JUMP_CFG_REG(n)  (0x04c + (n) * 0x04)
0081 #define SUN6I_DSI_INST_JUMP_CFG_TO(n)       (((n) & 0xf) << 20)
0082 #define SUN6I_DSI_INST_JUMP_CFG_POINT(n)    (((n) & 0xf) << 16)
0083 #define SUN6I_DSI_INST_JUMP_CFG_NUM(n)      ((n) & 0xffff)
0084 
0085 #define SUN6I_DSI_TRANS_START_REG   0x060
0086 
0087 #define SUN6I_DSI_TRANS_ZERO_REG    0x078
0088 
0089 #define SUN6I_DSI_TCON_DRQ_REG      0x07c
0090 #define SUN6I_DSI_TCON_DRQ_ENABLE_MODE      BIT(28)
0091 #define SUN6I_DSI_TCON_DRQ_SET(n)       ((n) & 0x3ff)
0092 
0093 #define SUN6I_DSI_PIXEL_CTL0_REG    0x080
0094 #define SUN6I_DSI_PIXEL_CTL0_PD_PLUG_DISABLE    BIT(16)
0095 #define SUN6I_DSI_PIXEL_CTL0_FORMAT(n)      ((n) & 0xf)
0096 
0097 #define SUN6I_DSI_PIXEL_CTL1_REG    0x084
0098 
0099 #define SUN6I_DSI_PIXEL_PH_REG      0x090
0100 #define SUN6I_DSI_PIXEL_PH_ECC(n)       (((n) & 0xff) << 24)
0101 #define SUN6I_DSI_PIXEL_PH_WC(n)        (((n) & 0xffff) << 8)
0102 #define SUN6I_DSI_PIXEL_PH_VC(n)        (((n) & 3) << 6)
0103 #define SUN6I_DSI_PIXEL_PH_DT(n)        ((n) & 0x3f)
0104 
0105 #define SUN6I_DSI_PIXEL_PF0_REG     0x098
0106 #define SUN6I_DSI_PIXEL_PF0_CRC_FORCE(n)    ((n) & 0xffff)
0107 
0108 #define SUN6I_DSI_PIXEL_PF1_REG     0x09c
0109 #define SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINEN(n)   (((n) & 0xffff) << 16)
0110 #define SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINE0(n)   ((n) & 0xffff)
0111 
0112 #define SUN6I_DSI_SYNC_HSS_REG      0x0b0
0113 
0114 #define SUN6I_DSI_SYNC_HSE_REG      0x0b4
0115 
0116 #define SUN6I_DSI_SYNC_VSS_REG      0x0b8
0117 
0118 #define SUN6I_DSI_SYNC_VSE_REG      0x0bc
0119 
0120 #define SUN6I_DSI_BLK_HSA0_REG      0x0c0
0121 
0122 #define SUN6I_DSI_BLK_HSA1_REG      0x0c4
0123 #define SUN6I_DSI_BLK_PF(n)         (((n) & 0xffff) << 16)
0124 #define SUN6I_DSI_BLK_PD(n)         ((n) & 0xff)
0125 
0126 #define SUN6I_DSI_BLK_HBP0_REG      0x0c8
0127 
0128 #define SUN6I_DSI_BLK_HBP1_REG      0x0cc
0129 
0130 #define SUN6I_DSI_BLK_HFP0_REG      0x0d0
0131 
0132 #define SUN6I_DSI_BLK_HFP1_REG      0x0d4
0133 
0134 #define SUN6I_DSI_BLK_HBLK0_REG     0x0e0
0135 
0136 #define SUN6I_DSI_BLK_HBLK1_REG     0x0e4
0137 
0138 #define SUN6I_DSI_BLK_VBLK0_REG     0x0e8
0139 
0140 #define SUN6I_DSI_BLK_VBLK1_REG     0x0ec
0141 
0142 #define SUN6I_DSI_BURST_LINE_REG    0x0f0
0143 #define SUN6I_DSI_BURST_LINE_SYNC_POINT(n)  (((n) & 0xffff) << 16)
0144 #define SUN6I_DSI_BURST_LINE_NUM(n)     ((n) & 0xffff)
0145 
0146 #define SUN6I_DSI_BURST_DRQ_REG     0x0f4
0147 #define SUN6I_DSI_BURST_DRQ_EDGE1(n)        (((n) & 0xffff) << 16)
0148 #define SUN6I_DSI_BURST_DRQ_EDGE0(n)        ((n) & 0xffff)
0149 
0150 #define SUN6I_DSI_CMD_CTL_REG       0x200
0151 #define SUN6I_DSI_CMD_CTL_RX_OVERFLOW       BIT(26)
0152 #define SUN6I_DSI_CMD_CTL_RX_FLAG       BIT(25)
0153 #define SUN6I_DSI_CMD_CTL_TX_FLAG       BIT(9)
0154 
0155 #define SUN6I_DSI_CMD_RX_REG(n)     (0x240 + (n) * 0x04)
0156 
0157 #define SUN6I_DSI_DEBUG_DATA_REG    0x2f8
0158 
0159 #define SUN6I_DSI_CMD_TX_REG(n)     (0x300 + (n) * 0x04)
0160 
0161 #define SUN6I_DSI_SYNC_POINT        40
0162 
0163 enum sun6i_dsi_start_inst {
0164     DSI_START_LPRX,
0165     DSI_START_LPTX,
0166     DSI_START_HSC,
0167     DSI_START_HSD,
0168 };
0169 
0170 enum sun6i_dsi_inst_id {
0171     DSI_INST_ID_LP11    = 0,
0172     DSI_INST_ID_TBA,
0173     DSI_INST_ID_HSC,
0174     DSI_INST_ID_HSD,
0175     DSI_INST_ID_LPDT,
0176     DSI_INST_ID_HSCEXIT,
0177     DSI_INST_ID_NOP,
0178     DSI_INST_ID_DLY,
0179     DSI_INST_ID_END     = 15,
0180 };
0181 
0182 enum sun6i_dsi_inst_mode {
0183     DSI_INST_MODE_STOP  = 0,
0184     DSI_INST_MODE_TBA,
0185     DSI_INST_MODE_HS,
0186     DSI_INST_MODE_ESCAPE,
0187     DSI_INST_MODE_HSCEXIT,
0188     DSI_INST_MODE_NOP,
0189 };
0190 
0191 enum sun6i_dsi_inst_escape {
0192     DSI_INST_ESCA_LPDT  = 0,
0193     DSI_INST_ESCA_ULPS,
0194     DSI_INST_ESCA_UN1,
0195     DSI_INST_ESCA_UN2,
0196     DSI_INST_ESCA_RESET,
0197     DSI_INST_ESCA_UN3,
0198     DSI_INST_ESCA_UN4,
0199     DSI_INST_ESCA_UN5,
0200 };
0201 
0202 enum sun6i_dsi_inst_packet {
0203     DSI_INST_PACK_PIXEL = 0,
0204     DSI_INST_PACK_COMMAND,
0205 };
0206 
0207 static const u32 sun6i_dsi_ecc_array[] = {
0208     [0] = (BIT(0) | BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(7) | BIT(10) |
0209            BIT(11) | BIT(13) | BIT(16) | BIT(20) | BIT(21) | BIT(22) |
0210            BIT(23)),
0211     [1] = (BIT(0) | BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(8) | BIT(10) |
0212            BIT(12) | BIT(14) | BIT(17) | BIT(20) | BIT(21) | BIT(22) |
0213            BIT(23)),
0214     [2] = (BIT(0) | BIT(2) | BIT(3) | BIT(5) | BIT(6) | BIT(9) | BIT(11) |
0215            BIT(12) | BIT(15) | BIT(18) | BIT(20) | BIT(21) | BIT(22)),
0216     [3] = (BIT(1) | BIT(2) | BIT(3) | BIT(7) | BIT(8) | BIT(9) | BIT(13) |
0217            BIT(14) | BIT(15) | BIT(19) | BIT(20) | BIT(21) | BIT(23)),
0218     [4] = (BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(16) |
0219            BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(22) | BIT(23)),
0220     [5] = (BIT(10) | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) |
0221            BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(21) | BIT(22) |
0222            BIT(23)),
0223 };
0224 
0225 static u32 sun6i_dsi_ecc_compute(unsigned int data)
0226 {
0227     int i;
0228     u8 ecc = 0;
0229 
0230     for (i = 0; i < ARRAY_SIZE(sun6i_dsi_ecc_array); i++) {
0231         u32 field = sun6i_dsi_ecc_array[i];
0232         bool init = false;
0233         u8 val = 0;
0234         int j;
0235 
0236         for (j = 0; j < 24; j++) {
0237             if (!(BIT(j) & field))
0238                 continue;
0239 
0240             if (!init) {
0241                 val = (BIT(j) & data) ? 1 : 0;
0242                 init = true;
0243             } else {
0244                 val ^= (BIT(j) & data) ? 1 : 0;
0245             }
0246         }
0247 
0248         ecc |= val << i;
0249     }
0250 
0251     return ecc;
0252 }
0253 
0254 static u16 sun6i_dsi_crc_compute(u8 const *buffer, size_t len)
0255 {
0256     return crc_ccitt(0xffff, buffer, len);
0257 }
0258 
0259 static u16 sun6i_dsi_crc_repeat(u8 pd, u8 *buffer, size_t len)
0260 {
0261     memset(buffer, pd, len);
0262 
0263     return sun6i_dsi_crc_compute(buffer, len);
0264 }
0265 
0266 static u32 sun6i_dsi_build_sync_pkt(u8 dt, u8 vc, u8 d0, u8 d1)
0267 {
0268     u32 val = dt & 0x3f;
0269 
0270     val |= (vc & 3) << 6;
0271     val |= (d0 & 0xff) << 8;
0272     val |= (d1 & 0xff) << 16;
0273     val |= sun6i_dsi_ecc_compute(val) << 24;
0274 
0275     return val;
0276 }
0277 
0278 static u32 sun6i_dsi_build_blk0_pkt(u8 vc, u16 wc)
0279 {
0280     return sun6i_dsi_build_sync_pkt(MIPI_DSI_BLANKING_PACKET, vc,
0281                     wc & 0xff, wc >> 8);
0282 }
0283 
0284 static u32 sun6i_dsi_build_blk1_pkt(u16 pd, u8 *buffer, size_t len)
0285 {
0286     u32 val = SUN6I_DSI_BLK_PD(pd);
0287 
0288     return val | SUN6I_DSI_BLK_PF(sun6i_dsi_crc_repeat(pd, buffer, len));
0289 }
0290 
0291 static void sun6i_dsi_inst_abort(struct sun6i_dsi *dsi)
0292 {
0293     regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
0294                SUN6I_DSI_BASIC_CTL0_INST_ST, 0);
0295 }
0296 
0297 static void sun6i_dsi_inst_commit(struct sun6i_dsi *dsi)
0298 {
0299     regmap_update_bits(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
0300                SUN6I_DSI_BASIC_CTL0_INST_ST,
0301                SUN6I_DSI_BASIC_CTL0_INST_ST);
0302 }
0303 
0304 static int sun6i_dsi_inst_wait_for_completion(struct sun6i_dsi *dsi)
0305 {
0306     u32 val;
0307 
0308     return regmap_read_poll_timeout(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
0309                     val,
0310                     !(val & SUN6I_DSI_BASIC_CTL0_INST_ST),
0311                     100, 5000);
0312 }
0313 
0314 static void sun6i_dsi_inst_setup(struct sun6i_dsi *dsi,
0315                  enum sun6i_dsi_inst_id id,
0316                  enum sun6i_dsi_inst_mode mode,
0317                  bool clock, u8 data,
0318                  enum sun6i_dsi_inst_packet packet,
0319                  enum sun6i_dsi_inst_escape escape)
0320 {
0321     regmap_write(dsi->regs, SUN6I_DSI_INST_FUNC_REG(id),
0322              SUN6I_DSI_INST_FUNC_INST_MODE(mode) |
0323              SUN6I_DSI_INST_FUNC_ESCAPE_ENTRY(escape) |
0324              SUN6I_DSI_INST_FUNC_TRANS_PACKET(packet) |
0325              (clock ? SUN6I_DSI_INST_FUNC_LANE_CEN : 0) |
0326              SUN6I_DSI_INST_FUNC_LANE_DEN(data));
0327 }
0328 
0329 static void sun6i_dsi_inst_init(struct sun6i_dsi *dsi,
0330                 struct mipi_dsi_device *device)
0331 {
0332     u8 lanes_mask = GENMASK(device->lanes - 1, 0);
0333 
0334     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LP11, DSI_INST_MODE_STOP,
0335                  true, lanes_mask, 0, 0);
0336 
0337     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_TBA, DSI_INST_MODE_TBA,
0338                  false, 1, 0, 0);
0339 
0340     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSC, DSI_INST_MODE_HS,
0341                  true, 0, DSI_INST_PACK_PIXEL, 0);
0342 
0343     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSD, DSI_INST_MODE_HS,
0344                  false, lanes_mask, DSI_INST_PACK_PIXEL, 0);
0345 
0346     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_LPDT, DSI_INST_MODE_ESCAPE,
0347                  false, 1, DSI_INST_PACK_COMMAND,
0348                  DSI_INST_ESCA_LPDT);
0349 
0350     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_HSCEXIT, DSI_INST_MODE_HSCEXIT,
0351                  true, 0, 0, 0);
0352 
0353     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_NOP, DSI_INST_MODE_STOP,
0354                  false, lanes_mask, 0, 0);
0355 
0356     sun6i_dsi_inst_setup(dsi, DSI_INST_ID_DLY, DSI_INST_MODE_NOP,
0357                  true, lanes_mask, 0, 0);
0358 
0359     regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_CFG_REG(0),
0360              SUN6I_DSI_INST_JUMP_CFG_POINT(DSI_INST_ID_NOP) |
0361              SUN6I_DSI_INST_JUMP_CFG_TO(DSI_INST_ID_HSCEXIT) |
0362              SUN6I_DSI_INST_JUMP_CFG_NUM(1));
0363 };
0364 
0365 static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
0366                        struct drm_display_mode *mode)
0367 {
0368     u16 delay = mode->vtotal - (mode->vsync_start - mode->vdisplay) + 1;
0369 
0370     if (delay > mode->vtotal)
0371         delay = delay % mode->vtotal;
0372 
0373     return max_t(u16, delay, 1);
0374 }
0375 
0376 static u16 sun6i_dsi_get_line_num(struct sun6i_dsi *dsi,
0377                   struct drm_display_mode *mode)
0378 {
0379     struct mipi_dsi_device *device = dsi->device;
0380     unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
0381 
0382     return mode->htotal * Bpp / device->lanes;
0383 }
0384 
0385 static u16 sun6i_dsi_get_drq_edge0(struct sun6i_dsi *dsi,
0386                    struct drm_display_mode *mode,
0387                    u16 line_num, u16 edge1)
0388 {
0389     u16 edge0 = edge1;
0390 
0391     edge0 += (mode->hdisplay + 40) * SUN6I_DSI_TCON_DIV / 8;
0392 
0393     if (edge0 > line_num)
0394         return edge0 - line_num;
0395 
0396     return 1;
0397 }
0398 
0399 static u16 sun6i_dsi_get_drq_edge1(struct sun6i_dsi *dsi,
0400                    struct drm_display_mode *mode,
0401                    u16 line_num)
0402 {
0403     struct mipi_dsi_device *device = dsi->device;
0404     unsigned int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
0405     unsigned int hbp = mode->htotal - mode->hsync_end;
0406     u16 edge1;
0407 
0408     edge1 = SUN6I_DSI_SYNC_POINT;
0409     edge1 += (mode->hdisplay + hbp + 20) * Bpp / device->lanes;
0410 
0411     if (edge1 > line_num)
0412         return line_num;
0413 
0414     return edge1;
0415 }
0416 
0417 static void sun6i_dsi_setup_burst(struct sun6i_dsi *dsi,
0418                   struct drm_display_mode *mode)
0419 {
0420     struct mipi_dsi_device *device = dsi->device;
0421     u32 val = 0;
0422 
0423     if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
0424         u16 line_num = sun6i_dsi_get_line_num(dsi, mode);
0425         u16 edge0, edge1;
0426 
0427         edge1 = sun6i_dsi_get_drq_edge1(dsi, mode, line_num);
0428         edge0 = sun6i_dsi_get_drq_edge0(dsi, mode, line_num, edge1);
0429 
0430         regmap_write(dsi->regs, SUN6I_DSI_BURST_DRQ_REG,
0431                  SUN6I_DSI_BURST_DRQ_EDGE0(edge0) |
0432                  SUN6I_DSI_BURST_DRQ_EDGE1(edge1));
0433 
0434         regmap_write(dsi->regs, SUN6I_DSI_BURST_LINE_REG,
0435                  SUN6I_DSI_BURST_LINE_NUM(line_num) |
0436                  SUN6I_DSI_BURST_LINE_SYNC_POINT(SUN6I_DSI_SYNC_POINT));
0437 
0438         val = SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
0439     } else if ((mode->hsync_start - mode->hdisplay) > 20) {
0440         /* Maaaaaagic */
0441         u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
0442 
0443         drq *= mipi_dsi_pixel_format_to_bpp(device->format);
0444         drq /= 32;
0445 
0446         val = (SUN6I_DSI_TCON_DRQ_ENABLE_MODE |
0447                SUN6I_DSI_TCON_DRQ_SET(drq));
0448     }
0449 
0450     regmap_write(dsi->regs, SUN6I_DSI_TCON_DRQ_REG, val);
0451 }
0452 
0453 static void sun6i_dsi_setup_inst_loop(struct sun6i_dsi *dsi,
0454                       struct drm_display_mode *mode)
0455 {
0456     struct mipi_dsi_device *device = dsi->device;
0457     u16 delay = 50 - 1;
0458 
0459     if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
0460         u32 hsync_porch = (mode->htotal - mode->hdisplay) * 150;
0461 
0462         delay = (hsync_porch / ((mode->clock / 1000) * 8));
0463         delay -= 50;
0464     }
0465 
0466     regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_SEL_REG,
0467              2 << (4 * DSI_INST_ID_LP11) |
0468              3 << (4 * DSI_INST_ID_DLY));
0469 
0470     regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(0),
0471              SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
0472              SUN6I_DSI_INST_LOOP_NUM_N1(delay));
0473     regmap_write(dsi->regs, SUN6I_DSI_INST_LOOP_NUM_REG(1),
0474              SUN6I_DSI_INST_LOOP_NUM_N0(50 - 1) |
0475              SUN6I_DSI_INST_LOOP_NUM_N1(delay));
0476 }
0477 
0478 static void sun6i_dsi_setup_format(struct sun6i_dsi *dsi,
0479                    struct drm_display_mode *mode)
0480 {
0481     struct mipi_dsi_device *device = dsi->device;
0482     u32 val = SUN6I_DSI_PIXEL_PH_VC(device->channel);
0483     u8 dt, fmt;
0484     u16 wc;
0485 
0486     /*
0487      * TODO: The format defines are only valid in video mode and
0488      * change in command mode.
0489      */
0490     switch (device->format) {
0491     case MIPI_DSI_FMT_RGB888:
0492         dt = MIPI_DSI_PACKED_PIXEL_STREAM_24;
0493         fmt = 8;
0494         break;
0495     case MIPI_DSI_FMT_RGB666:
0496         dt = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
0497         fmt = 9;
0498         break;
0499     case MIPI_DSI_FMT_RGB666_PACKED:
0500         dt = MIPI_DSI_PACKED_PIXEL_STREAM_18;
0501         fmt = 10;
0502         break;
0503     case MIPI_DSI_FMT_RGB565:
0504         dt = MIPI_DSI_PACKED_PIXEL_STREAM_16;
0505         fmt = 11;
0506         break;
0507     default:
0508         return;
0509     }
0510     val |= SUN6I_DSI_PIXEL_PH_DT(dt);
0511 
0512     wc = mode->hdisplay * mipi_dsi_pixel_format_to_bpp(device->format) / 8;
0513     val |= SUN6I_DSI_PIXEL_PH_WC(wc);
0514     val |= SUN6I_DSI_PIXEL_PH_ECC(sun6i_dsi_ecc_compute(val));
0515 
0516     regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PH_REG, val);
0517 
0518     regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF0_REG,
0519              SUN6I_DSI_PIXEL_PF0_CRC_FORCE(0xffff));
0520 
0521     regmap_write(dsi->regs, SUN6I_DSI_PIXEL_PF1_REG,
0522              SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINE0(0xffff) |
0523              SUN6I_DSI_PIXEL_PF1_CRC_INIT_LINEN(0xffff));
0524 
0525     regmap_write(dsi->regs, SUN6I_DSI_PIXEL_CTL0_REG,
0526              SUN6I_DSI_PIXEL_CTL0_PD_PLUG_DISABLE |
0527              SUN6I_DSI_PIXEL_CTL0_FORMAT(fmt));
0528 }
0529 
0530 static void sun6i_dsi_setup_timings(struct sun6i_dsi *dsi,
0531                     struct drm_display_mode *mode)
0532 {
0533     struct mipi_dsi_device *device = dsi->device;
0534     int Bpp = mipi_dsi_pixel_format_to_bpp(device->format) / 8;
0535     u16 hbp = 0, hfp = 0, hsa = 0, hblk = 0, vblk = 0;
0536     u32 basic_ctl = 0;
0537     size_t bytes;
0538     u8 *buffer;
0539 
0540     /* Do all timing calculations up front to allocate buffer space */
0541 
0542     if (device->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
0543         hblk = mode->hdisplay * Bpp;
0544         basic_ctl = SUN6I_DSI_BASIC_CTL_VIDEO_BURST |
0545                 SUN6I_DSI_BASIC_CTL_HSA_HSE_DIS |
0546                 SUN6I_DSI_BASIC_CTL_HBP_DIS;
0547 
0548         if (device->lanes == 4)
0549             basic_ctl |= SUN6I_DSI_BASIC_CTL_TRAIL_FILL |
0550                      SUN6I_DSI_BASIC_CTL_TRAIL_INV(0xc);
0551     } else {
0552         /*
0553          * A sync period is composed of a blanking packet (4
0554          * bytes + payload + 2 bytes) and a sync event packet
0555          * (4 bytes). Its minimal size is therefore 10 bytes
0556          */
0557 #define HSA_PACKET_OVERHEAD 10
0558         hsa = max(HSA_PACKET_OVERHEAD,
0559               (mode->hsync_end - mode->hsync_start) * Bpp - HSA_PACKET_OVERHEAD);
0560 
0561         /*
0562          * The backporch is set using a blanking packet (4
0563          * bytes + payload + 2 bytes). Its minimal size is
0564          * therefore 6 bytes
0565          */
0566 #define HBP_PACKET_OVERHEAD 6
0567         hbp = max(HBP_PACKET_OVERHEAD,
0568               (mode->htotal - mode->hsync_end) * Bpp - HBP_PACKET_OVERHEAD);
0569 
0570         /*
0571          * The frontporch is set using a sync event (4 bytes)
0572          * and two blanking packets (each one is 4 bytes +
0573          * payload + 2 bytes). Its minimal size is therefore
0574          * 16 bytes
0575          */
0576 #define HFP_PACKET_OVERHEAD 16
0577         hfp = max(HFP_PACKET_OVERHEAD,
0578               (mode->hsync_start - mode->hdisplay) * Bpp - HFP_PACKET_OVERHEAD);
0579 
0580         /*
0581          * The blanking is set using a sync event (4 bytes)
0582          * and a blanking packet (4 bytes + payload + 2
0583          * bytes). Its minimal size is therefore 10 bytes.
0584          */
0585 #define HBLK_PACKET_OVERHEAD    10
0586         hblk = max(HBLK_PACKET_OVERHEAD,
0587                (mode->htotal - (mode->hsync_end - mode->hsync_start)) * Bpp -
0588                HBLK_PACKET_OVERHEAD);
0589 
0590         /*
0591          * And I'm not entirely sure what vblk is about. The driver in
0592          * Allwinner BSP is using a rather convoluted calculation
0593          * there only for 4 lanes. However, using 0 (the !4 lanes
0594          * case) even with a 4 lanes screen seems to work...
0595          */
0596         vblk = 0;
0597     }
0598 
0599     /* How many bytes do we need to send all payloads? */
0600     bytes = max_t(size_t, max(max(hfp, hblk), max(hsa, hbp)), vblk);
0601     buffer = kmalloc(bytes, GFP_KERNEL);
0602     if (WARN_ON(!buffer))
0603         return;
0604 
0605     regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL_REG, basic_ctl);
0606 
0607     regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSS_REG,
0608              sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_START,
0609                           device->channel,
0610                           0, 0));
0611 
0612     regmap_write(dsi->regs, SUN6I_DSI_SYNC_HSE_REG,
0613              sun6i_dsi_build_sync_pkt(MIPI_DSI_H_SYNC_END,
0614                           device->channel,
0615                           0, 0));
0616 
0617     regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSS_REG,
0618              sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_START,
0619                           device->channel,
0620                           0, 0));
0621 
0622     regmap_write(dsi->regs, SUN6I_DSI_SYNC_VSE_REG,
0623              sun6i_dsi_build_sync_pkt(MIPI_DSI_V_SYNC_END,
0624                           device->channel,
0625                           0, 0));
0626 
0627     regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE0_REG,
0628              SUN6I_DSI_BASIC_SIZE0_VSA(mode->vsync_end -
0629                            mode->vsync_start) |
0630              SUN6I_DSI_BASIC_SIZE0_VBP(mode->vtotal -
0631                            mode->vsync_end));
0632 
0633     regmap_write(dsi->regs, SUN6I_DSI_BASIC_SIZE1_REG,
0634              SUN6I_DSI_BASIC_SIZE1_VACT(mode->vdisplay) |
0635              SUN6I_DSI_BASIC_SIZE1_VT(mode->vtotal));
0636 
0637     /* sync */
0638     regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA0_REG,
0639              sun6i_dsi_build_blk0_pkt(device->channel, hsa));
0640     regmap_write(dsi->regs, SUN6I_DSI_BLK_HSA1_REG,
0641              sun6i_dsi_build_blk1_pkt(0, buffer, hsa));
0642 
0643     /* backporch */
0644     regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP0_REG,
0645              sun6i_dsi_build_blk0_pkt(device->channel, hbp));
0646     regmap_write(dsi->regs, SUN6I_DSI_BLK_HBP1_REG,
0647              sun6i_dsi_build_blk1_pkt(0, buffer, hbp));
0648 
0649     /* frontporch */
0650     regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP0_REG,
0651              sun6i_dsi_build_blk0_pkt(device->channel, hfp));
0652     regmap_write(dsi->regs, SUN6I_DSI_BLK_HFP1_REG,
0653              sun6i_dsi_build_blk1_pkt(0, buffer, hfp));
0654 
0655     /* hblk */
0656     regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK0_REG,
0657              sun6i_dsi_build_blk0_pkt(device->channel, hblk));
0658     regmap_write(dsi->regs, SUN6I_DSI_BLK_HBLK1_REG,
0659              sun6i_dsi_build_blk1_pkt(0, buffer, hblk));
0660 
0661     /* vblk */
0662     regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK0_REG,
0663              sun6i_dsi_build_blk0_pkt(device->channel, vblk));
0664     regmap_write(dsi->regs, SUN6I_DSI_BLK_VBLK1_REG,
0665              sun6i_dsi_build_blk1_pkt(0, buffer, vblk));
0666 
0667     kfree(buffer);
0668 }
0669 
0670 static int sun6i_dsi_start(struct sun6i_dsi *dsi,
0671                enum sun6i_dsi_start_inst func)
0672 {
0673     switch (func) {
0674     case DSI_START_LPTX:
0675         regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
0676                  DSI_INST_ID_LPDT << (4 * DSI_INST_ID_LP11) |
0677                  DSI_INST_ID_END  << (4 * DSI_INST_ID_LPDT));
0678         break;
0679     case DSI_START_LPRX:
0680         regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
0681                  DSI_INST_ID_LPDT << (4 * DSI_INST_ID_LP11) |
0682                  DSI_INST_ID_DLY  << (4 * DSI_INST_ID_LPDT) |
0683                  DSI_INST_ID_TBA  << (4 * DSI_INST_ID_DLY) |
0684                  DSI_INST_ID_END  << (4 * DSI_INST_ID_TBA));
0685         break;
0686     case DSI_START_HSC:
0687         regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
0688                  DSI_INST_ID_HSC  << (4 * DSI_INST_ID_LP11) |
0689                  DSI_INST_ID_END  << (4 * DSI_INST_ID_HSC));
0690         break;
0691     case DSI_START_HSD:
0692         regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
0693                  DSI_INST_ID_NOP  << (4 * DSI_INST_ID_LP11) |
0694                  DSI_INST_ID_HSD  << (4 * DSI_INST_ID_NOP) |
0695                  DSI_INST_ID_DLY  << (4 * DSI_INST_ID_HSD) |
0696                  DSI_INST_ID_NOP  << (4 * DSI_INST_ID_DLY) |
0697                  DSI_INST_ID_END  << (4 * DSI_INST_ID_HSCEXIT));
0698         break;
0699     default:
0700         regmap_write(dsi->regs, SUN6I_DSI_INST_JUMP_SEL_REG,
0701                  DSI_INST_ID_END  << (4 * DSI_INST_ID_LP11));
0702         break;
0703     }
0704 
0705     sun6i_dsi_inst_abort(dsi);
0706     sun6i_dsi_inst_commit(dsi);
0707 
0708     if (func == DSI_START_HSC)
0709         regmap_write_bits(dsi->regs,
0710                   SUN6I_DSI_INST_FUNC_REG(DSI_INST_ID_LP11),
0711                   SUN6I_DSI_INST_FUNC_LANE_CEN, 0);
0712 
0713     return 0;
0714 }
0715 
0716 static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
0717 {
0718     struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
0719     struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
0720     struct mipi_dsi_device *device = dsi->device;
0721     union phy_configure_opts opts = { };
0722     struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
0723     u16 delay;
0724     int err;
0725 
0726     DRM_DEBUG_DRIVER("Enabling DSI output\n");
0727 
0728     err = regulator_enable(dsi->regulator);
0729     if (err)
0730         dev_warn(dsi->dev, "failed to enable VCC-DSI supply: %d\n", err);
0731 
0732     reset_control_deassert(dsi->reset);
0733     clk_prepare_enable(dsi->mod_clk);
0734 
0735     /*
0736      * Enable the DSI block.
0737      */
0738     regmap_write(dsi->regs, SUN6I_DSI_CTL_REG, SUN6I_DSI_CTL_EN);
0739 
0740     regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL0_REG,
0741              SUN6I_DSI_BASIC_CTL0_ECC_EN | SUN6I_DSI_BASIC_CTL0_CRC_EN);
0742 
0743     regmap_write(dsi->regs, SUN6I_DSI_TRANS_START_REG, 10);
0744     regmap_write(dsi->regs, SUN6I_DSI_TRANS_ZERO_REG, 0);
0745 
0746     sun6i_dsi_inst_init(dsi, dsi->device);
0747 
0748     regmap_write(dsi->regs, SUN6I_DSI_DEBUG_DATA_REG, 0xff);
0749 
0750     delay = sun6i_dsi_get_video_start_delay(dsi, mode);
0751     regmap_write(dsi->regs, SUN6I_DSI_BASIC_CTL1_REG,
0752              SUN6I_DSI_BASIC_CTL1_VIDEO_ST_DELAY(delay) |
0753              SUN6I_DSI_BASIC_CTL1_VIDEO_FILL |
0754              SUN6I_DSI_BASIC_CTL1_VIDEO_PRECISION |
0755              SUN6I_DSI_BASIC_CTL1_VIDEO_MODE);
0756 
0757     sun6i_dsi_setup_burst(dsi, mode);
0758     sun6i_dsi_setup_inst_loop(dsi, mode);
0759     sun6i_dsi_setup_format(dsi, mode);
0760     sun6i_dsi_setup_timings(dsi, mode);
0761 
0762     phy_init(dsi->dphy);
0763 
0764     phy_mipi_dphy_get_default_config(mode->clock * 1000,
0765                      mipi_dsi_pixel_format_to_bpp(device->format),
0766                      device->lanes, cfg);
0767 
0768     phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
0769     phy_configure(dsi->dphy, &opts);
0770     phy_power_on(dsi->dphy);
0771 
0772     if (dsi->panel)
0773         drm_panel_prepare(dsi->panel);
0774 
0775     /*
0776      * FIXME: This should be moved after the switch to HS mode.
0777      *
0778      * Unfortunately, once in HS mode, it seems like we're not
0779      * able to send DCS commands anymore, which would prevent any
0780      * panel to send any DCS command as part as their enable
0781      * method, which is quite common.
0782      *
0783      * I haven't seen any artifact due to that sub-optimal
0784      * ordering on the panels I've tested it with, so I guess this
0785      * will do for now, until that IP is better understood.
0786      */
0787     if (dsi->panel)
0788         drm_panel_enable(dsi->panel);
0789 
0790     sun6i_dsi_start(dsi, DSI_START_HSC);
0791 
0792     udelay(1000);
0793 
0794     sun6i_dsi_start(dsi, DSI_START_HSD);
0795 }
0796 
0797 static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder)
0798 {
0799     struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
0800 
0801     DRM_DEBUG_DRIVER("Disabling DSI output\n");
0802 
0803     if (dsi->panel) {
0804         drm_panel_disable(dsi->panel);
0805         drm_panel_unprepare(dsi->panel);
0806     }
0807 
0808     phy_power_off(dsi->dphy);
0809     phy_exit(dsi->dphy);
0810 
0811     clk_disable_unprepare(dsi->mod_clk);
0812     reset_control_assert(dsi->reset);
0813     regulator_disable(dsi->regulator);
0814 }
0815 
0816 static int sun6i_dsi_get_modes(struct drm_connector *connector)
0817 {
0818     struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
0819 
0820     return drm_panel_get_modes(dsi->panel, connector);
0821 }
0822 
0823 static const struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = {
0824     .get_modes  = sun6i_dsi_get_modes,
0825 };
0826 
0827 static enum drm_connector_status
0828 sun6i_dsi_connector_detect(struct drm_connector *connector, bool force)
0829 {
0830     struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector);
0831 
0832     return dsi->panel ? connector_status_connected :
0833                 connector_status_disconnected;
0834 }
0835 
0836 static const struct drm_connector_funcs sun6i_dsi_connector_funcs = {
0837     .detect         = sun6i_dsi_connector_detect,
0838     .fill_modes     = drm_helper_probe_single_connector_modes,
0839     .destroy        = drm_connector_cleanup,
0840     .reset          = drm_atomic_helper_connector_reset,
0841     .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
0842     .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
0843 };
0844 
0845 static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = {
0846     .disable    = sun6i_dsi_encoder_disable,
0847     .enable     = sun6i_dsi_encoder_enable,
0848 };
0849 
0850 static u32 sun6i_dsi_dcs_build_pkt_hdr(struct sun6i_dsi *dsi,
0851                        const struct mipi_dsi_msg *msg)
0852 {
0853     u32 pkt = msg->type;
0854 
0855     if (msg->type == MIPI_DSI_DCS_LONG_WRITE) {
0856         pkt |= ((msg->tx_len) & 0xffff) << 8;
0857         pkt |= (((msg->tx_len) >> 8) & 0xffff) << 16;
0858     } else {
0859         pkt |= (((u8 *)msg->tx_buf)[0] << 8);
0860         if (msg->tx_len > 1)
0861             pkt |= (((u8 *)msg->tx_buf)[1] << 16);
0862     }
0863 
0864     pkt |= sun6i_dsi_ecc_compute(pkt) << 24;
0865 
0866     return pkt;
0867 }
0868 
0869 static int sun6i_dsi_dcs_write_short(struct sun6i_dsi *dsi,
0870                      const struct mipi_dsi_msg *msg)
0871 {
0872     regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
0873              sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
0874     regmap_write_bits(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
0875               0xff, (4 - 1));
0876 
0877     sun6i_dsi_start(dsi, DSI_START_LPTX);
0878 
0879     return msg->tx_len;
0880 }
0881 
0882 static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi,
0883                     const struct mipi_dsi_msg *msg)
0884 {
0885     int ret, len = 0;
0886     u8 *bounce;
0887     u16 crc;
0888 
0889     regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
0890              sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
0891 
0892     bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL);
0893     if (!bounce)
0894         return -ENOMEM;
0895 
0896     memcpy(bounce, msg->tx_buf, msg->tx_len);
0897     len += msg->tx_len;
0898 
0899     crc = sun6i_dsi_crc_compute(bounce, msg->tx_len);
0900     memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
0901     len += sizeof(crc);
0902 
0903     regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4));
0904     regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
0905     kfree(bounce);
0906 
0907     sun6i_dsi_start(dsi, DSI_START_LPTX);
0908 
0909     ret = sun6i_dsi_inst_wait_for_completion(dsi);
0910     if (ret < 0) {
0911         sun6i_dsi_inst_abort(dsi);
0912         return ret;
0913     }
0914 
0915     /*
0916      * TODO: There's some bits (reg 0x200, bits 8/9) that
0917      * apparently can be used to check whether the data have been
0918      * sent, but I couldn't get it to work reliably.
0919      */
0920     return msg->tx_len;
0921 }
0922 
0923 static int sun6i_dsi_dcs_read(struct sun6i_dsi *dsi,
0924                   const struct mipi_dsi_msg *msg)
0925 {
0926     u32 val;
0927     int ret;
0928     u8 byte0;
0929 
0930     regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
0931              sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
0932     regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG,
0933              (4 - 1));
0934 
0935     sun6i_dsi_start(dsi, DSI_START_LPRX);
0936 
0937     ret = sun6i_dsi_inst_wait_for_completion(dsi);
0938     if (ret < 0) {
0939         sun6i_dsi_inst_abort(dsi);
0940         return ret;
0941     }
0942 
0943     /*
0944      * TODO: There's some bits (reg 0x200, bits 24/25) that
0945      * apparently can be used to check whether the data have been
0946      * received, but I couldn't get it to work reliably.
0947      */
0948     regmap_read(dsi->regs, SUN6I_DSI_CMD_CTL_REG, &val);
0949     if (val & SUN6I_DSI_CMD_CTL_RX_OVERFLOW)
0950         return -EIO;
0951 
0952     regmap_read(dsi->regs, SUN6I_DSI_CMD_RX_REG(0), &val);
0953     byte0 = val & 0xff;
0954     if (byte0 == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT)
0955         return -EIO;
0956 
0957     ((u8 *)msg->rx_buf)[0] = (val >> 8);
0958 
0959     return 1;
0960 }
0961 
0962 static int sun6i_dsi_attach(struct mipi_dsi_host *host,
0963                 struct mipi_dsi_device *device)
0964 {
0965     struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
0966     struct drm_panel *panel = of_drm_find_panel(device->dev.of_node);
0967 
0968     if (IS_ERR(panel))
0969         return PTR_ERR(panel);
0970     if (!dsi->drm || !dsi->drm->registered)
0971         return -EPROBE_DEFER;
0972 
0973     dsi->panel = panel;
0974     dsi->device = device;
0975 
0976     drm_kms_helper_hotplug_event(dsi->drm);
0977 
0978     dev_info(host->dev, "Attached device %s\n", device->name);
0979 
0980     return 0;
0981 }
0982 
0983 static int sun6i_dsi_detach(struct mipi_dsi_host *host,
0984                 struct mipi_dsi_device *device)
0985 {
0986     struct sun6i_dsi *dsi = host_to_sun6i_dsi(host);
0987 
0988     dsi->panel = NULL;
0989     dsi->device = NULL;
0990 
0991     drm_kms_helper_hotplug_event(dsi->drm);
0992 
0993     return 0;
0994 }
0995 
0996 static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host,
0997                   const struct mipi_dsi_msg *msg)
0998 {
0999     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 
1036 static 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 
1042 static 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 
1050 static 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 
1084 err_cleanup_connector:
1085     drm_encoder_cleanup(&dsi->encoder);
1086     return ret;
1087 }
1088 
1089 static 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 
1097 static const struct component_ops sun6i_dsi_ops = {
1098     .bind   = sun6i_dsi_bind,
1099     .unbind = sun6i_dsi_unbind,
1100 };
1101 
1102 static int sun6i_dsi_probe(struct platform_device *pdev)
1103 {
1104     struct device *dev = &pdev->dev;
1105     const char *bus_clk_name = NULL;
1106     struct sun6i_dsi *dsi;
1107     void __iomem *base;
1108     int ret;
1109 
1110     dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
1111     if (!dsi)
1112         return -ENOMEM;
1113     dev_set_drvdata(dev, dsi);
1114     dsi->dev = dev;
1115     dsi->host.ops = &sun6i_dsi_host_ops;
1116     dsi->host.dev = dev;
1117 
1118     if (of_device_is_compatible(dev->of_node,
1119                     "allwinner,sun6i-a31-mipi-dsi"))
1120         bus_clk_name = "bus";
1121 
1122     base = devm_platform_ioremap_resource(pdev, 0);
1123     if (IS_ERR(base)) {
1124         dev_err(dev, "Couldn't map the DSI encoder registers\n");
1125         return PTR_ERR(base);
1126     }
1127 
1128     dsi->regulator = devm_regulator_get(dev, "vcc-dsi");
1129     if (IS_ERR(dsi->regulator))
1130         return dev_err_probe(dev, PTR_ERR(dsi->regulator),
1131                      "Couldn't get VCC-DSI supply\n");
1132 
1133     dsi->reset = devm_reset_control_get_shared(dev, NULL);
1134     if (IS_ERR(dsi->reset)) {
1135         dev_err(dev, "Couldn't get our reset line\n");
1136         return PTR_ERR(dsi->reset);
1137     }
1138 
1139     dsi->regs = devm_regmap_init_mmio(dev, base, &sun6i_dsi_regmap_config);
1140     if (IS_ERR(dsi->regs)) {
1141         dev_err(dev, "Couldn't init regmap\n");
1142         return PTR_ERR(dsi->regs);
1143     }
1144 
1145     dsi->bus_clk = devm_clk_get(dev, bus_clk_name);
1146     if (IS_ERR(dsi->bus_clk))
1147         return dev_err_probe(dev, PTR_ERR(dsi->bus_clk),
1148                      "Couldn't get the DSI bus clock\n");
1149 
1150     ret = regmap_mmio_attach_clk(dsi->regs, dsi->bus_clk);
1151     if (ret)
1152         return ret;
1153 
1154     if (of_device_is_compatible(dev->of_node,
1155                     "allwinner,sun6i-a31-mipi-dsi")) {
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     /*
1165      * In order to operate properly, that clock seems to be always
1166      * set to 297MHz.
1167      */
1168     clk_set_rate_exclusive(dsi->mod_clk, 297000000);
1169 
1170     dsi->dphy = devm_phy_get(dev, "dphy");
1171     if (IS_ERR(dsi->dphy)) {
1172         dev_err(dev, "Couldn't get the MIPI D-PHY\n");
1173         ret = PTR_ERR(dsi->dphy);
1174         goto err_unprotect_clk;
1175     }
1176 
1177     ret = mipi_dsi_host_register(&dsi->host);
1178     if (ret) {
1179         dev_err(dev, "Couldn't register MIPI-DSI host\n");
1180         goto err_unprotect_clk;
1181     }
1182 
1183     ret = component_add(&pdev->dev, &sun6i_dsi_ops);
1184     if (ret) {
1185         dev_err(dev, "Couldn't register our component\n");
1186         goto err_remove_dsi_host;
1187     }
1188 
1189     return 0;
1190 
1191 err_remove_dsi_host:
1192     mipi_dsi_host_unregister(&dsi->host);
1193 err_unprotect_clk:
1194     clk_rate_exclusive_put(dsi->mod_clk);
1195 err_attach_clk:
1196     regmap_mmio_detach_clk(dsi->regs);
1197 
1198     return ret;
1199 }
1200 
1201 static int sun6i_dsi_remove(struct platform_device *pdev)
1202 {
1203     struct device *dev = &pdev->dev;
1204     struct sun6i_dsi *dsi = dev_get_drvdata(dev);
1205 
1206     component_del(&pdev->dev, &sun6i_dsi_ops);
1207     mipi_dsi_host_unregister(&dsi->host);
1208     clk_rate_exclusive_put(dsi->mod_clk);
1209 
1210     regmap_mmio_detach_clk(dsi->regs);
1211 
1212     return 0;
1213 }
1214 
1215 static const struct of_device_id sun6i_dsi_of_table[] = {
1216     { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
1217     { .compatible = "allwinner,sun50i-a64-mipi-dsi" },
1218     { }
1219 };
1220 MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
1221 
1222 static struct platform_driver sun6i_dsi_platform_driver = {
1223     .probe      = sun6i_dsi_probe,
1224     .remove     = sun6i_dsi_remove,
1225     .driver     = {
1226         .name       = "sun6i-mipi-dsi",
1227         .of_match_table = sun6i_dsi_of_table,
1228     },
1229 };
1230 module_platform_driver(sun6i_dsi_platform_driver);
1231 
1232 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
1233 MODULE_DESCRIPTION("Allwinner A31 DSI Driver");
1234 MODULE_LICENSE("GPL");