0001
0002
0003
0004
0005
0006
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
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
0488
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
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
0554
0555
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
0563
0564
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
0572
0573
0574
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
0582
0583
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
0592
0593
0594
0595
0596 vblk = 0;
0597 }
0598
0599
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
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
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
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
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
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
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
0777
0778
0779
0780
0781
0782
0783
0784
0785
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
0917
0918
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
0945
0946
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
1166
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");