0001
0002 #include <linux/clk.h>
0003 #include <linux/component.h>
0004 #include <linux/delay.h>
0005 #include <linux/io.h>
0006 #include <linux/mfd/syscon.h>
0007 #include <linux/module.h>
0008 #include <linux/of.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/regmap.h>
0011 #include <linux/regulator/consumer.h>
0012 #include <video/mipi_display.h>
0013
0014 #include <drm/drm_atomic_helper.h>
0015 #include <drm/drm_bridge.h>
0016 #include <drm/drm_device.h>
0017 #include <drm/drm_drv.h>
0018 #include <drm/drm_encoder.h>
0019 #include <drm/drm_mipi_dsi.h>
0020 #include <drm/drm_modeset_helper_vtables.h>
0021 #include <drm/drm_of.h>
0022 #include <drm/drm_panel.h>
0023 #include <drm/drm_print.h>
0024 #include <drm/drm_probe_helper.h>
0025
0026 #include "mcde_drm.h"
0027 #include "mcde_dsi_regs.h"
0028
0029 #define DSI_DEFAULT_LP_FREQ_HZ 19200000
0030 #define DSI_DEFAULT_HS_FREQ_HZ 420160000
0031
0032
0033 #define PRCM_DSI_SW_RESET 0x324
0034 #define PRCM_DSI_SW_RESET_DSI0_SW_RESETN BIT(0)
0035 #define PRCM_DSI_SW_RESET_DSI1_SW_RESETN BIT(1)
0036 #define PRCM_DSI_SW_RESET_DSI2_SW_RESETN BIT(2)
0037
0038 struct mcde_dsi {
0039 struct device *dev;
0040 struct mcde *mcde;
0041 struct drm_bridge bridge;
0042 struct drm_panel *panel;
0043 struct drm_bridge *bridge_out;
0044 struct mipi_dsi_host dsi_host;
0045 struct mipi_dsi_device *mdsi;
0046 const struct drm_display_mode *mode;
0047 struct clk *hs_clk;
0048 struct clk *lp_clk;
0049 unsigned long hs_freq;
0050 unsigned long lp_freq;
0051 bool unused;
0052
0053 void __iomem *regs;
0054 struct regmap *prcmu;
0055 };
0056
0057 static inline struct mcde_dsi *bridge_to_mcde_dsi(struct drm_bridge *bridge)
0058 {
0059 return container_of(bridge, struct mcde_dsi, bridge);
0060 }
0061
0062 static inline struct mcde_dsi *host_to_mcde_dsi(struct mipi_dsi_host *h)
0063 {
0064 return container_of(h, struct mcde_dsi, dsi_host);
0065 }
0066
0067 bool mcde_dsi_irq(struct mipi_dsi_device *mdsi)
0068 {
0069 struct mcde_dsi *d;
0070 u32 val;
0071 bool te_received = false;
0072
0073 d = host_to_mcde_dsi(mdsi->host);
0074
0075 dev_dbg(d->dev, "%s called\n", __func__);
0076
0077 val = readl(d->regs + DSI_DIRECT_CMD_STS_FLAG);
0078 if (val)
0079 dev_dbg(d->dev, "DSI_DIRECT_CMD_STS_FLAG = %08x\n", val);
0080 if (val & DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
0081 dev_dbg(d->dev, "direct command write completed\n");
0082 if (val & DSI_DIRECT_CMD_STS_TE_RECEIVED) {
0083 te_received = true;
0084 dev_dbg(d->dev, "direct command TE received\n");
0085 }
0086 if (val & DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED)
0087 dev_err(d->dev, "direct command ACK ERR received\n");
0088 if (val & DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR)
0089 dev_err(d->dev, "direct command read ERR received\n");
0090
0091 writel(val, d->regs + DSI_DIRECT_CMD_STS_CLR);
0092
0093 val = readl(d->regs + DSI_CMD_MODE_STS_FLAG);
0094 if (val)
0095 dev_dbg(d->dev, "DSI_CMD_MODE_STS_FLAG = %08x\n", val);
0096 if (val & DSI_CMD_MODE_STS_ERR_NO_TE)
0097
0098 dev_dbg(d->dev, "CMD mode no TE\n");
0099 if (val & DSI_CMD_MODE_STS_ERR_TE_MISS)
0100
0101 dev_dbg(d->dev, "CMD mode TE miss\n");
0102 if (val & DSI_CMD_MODE_STS_ERR_SDI1_UNDERRUN)
0103 dev_err(d->dev, "CMD mode SD1 underrun\n");
0104 if (val & DSI_CMD_MODE_STS_ERR_SDI2_UNDERRUN)
0105 dev_err(d->dev, "CMD mode SD2 underrun\n");
0106 if (val & DSI_CMD_MODE_STS_ERR_UNWANTED_RD)
0107 dev_err(d->dev, "CMD mode unwanted RD\n");
0108 writel(val, d->regs + DSI_CMD_MODE_STS_CLR);
0109
0110 val = readl(d->regs + DSI_DIRECT_CMD_RD_STS_FLAG);
0111 if (val)
0112 dev_dbg(d->dev, "DSI_DIRECT_CMD_RD_STS_FLAG = %08x\n", val);
0113 writel(val, d->regs + DSI_DIRECT_CMD_RD_STS_CLR);
0114
0115 val = readl(d->regs + DSI_TG_STS_FLAG);
0116 if (val)
0117 dev_dbg(d->dev, "DSI_TG_STS_FLAG = %08x\n", val);
0118 writel(val, d->regs + DSI_TG_STS_CLR);
0119
0120 val = readl(d->regs + DSI_VID_MODE_STS_FLAG);
0121 if (val)
0122 dev_dbg(d->dev, "DSI_VID_MODE_STS_FLAG = %08x\n", val);
0123 if (val & DSI_VID_MODE_STS_VSG_RUNNING)
0124 dev_dbg(d->dev, "VID mode VSG running\n");
0125 if (val & DSI_VID_MODE_STS_ERR_MISSING_DATA)
0126 dev_err(d->dev, "VID mode missing data\n");
0127 if (val & DSI_VID_MODE_STS_ERR_MISSING_HSYNC)
0128 dev_err(d->dev, "VID mode missing HSYNC\n");
0129 if (val & DSI_VID_MODE_STS_ERR_MISSING_VSYNC)
0130 dev_err(d->dev, "VID mode missing VSYNC\n");
0131 if (val & DSI_VID_MODE_STS_REG_ERR_SMALL_LENGTH)
0132 dev_err(d->dev, "VID mode less bytes than expected between two HSYNC\n");
0133 if (val & DSI_VID_MODE_STS_REG_ERR_SMALL_HEIGHT)
0134 dev_err(d->dev, "VID mode less lines than expected between two VSYNC\n");
0135 if (val & (DSI_VID_MODE_STS_ERR_BURSTWRITE |
0136 DSI_VID_MODE_STS_ERR_LINEWRITE |
0137 DSI_VID_MODE_STS_ERR_LONGREAD))
0138 dev_err(d->dev, "VID mode read/write error\n");
0139 if (val & DSI_VID_MODE_STS_ERR_VRS_WRONG_LENGTH)
0140 dev_err(d->dev, "VID mode received packets differ from expected size\n");
0141 if (val & DSI_VID_MODE_STS_VSG_RECOVERY)
0142 dev_err(d->dev, "VID mode VSG in recovery mode\n");
0143 writel(val, d->regs + DSI_VID_MODE_STS_CLR);
0144
0145 return te_received;
0146 }
0147
0148 static void mcde_dsi_attach_to_mcde(struct mcde_dsi *d)
0149 {
0150 d->mcde->mdsi = d->mdsi;
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO)
0165 d->mcde->flow_mode = MCDE_VIDEO_FORMATTER_FLOW;
0166 else
0167 d->mcde->flow_mode = MCDE_COMMAND_TE_FLOW;
0168 }
0169
0170 static int mcde_dsi_host_attach(struct mipi_dsi_host *host,
0171 struct mipi_dsi_device *mdsi)
0172 {
0173 struct mcde_dsi *d = host_to_mcde_dsi(host);
0174
0175 if (mdsi->lanes < 1 || mdsi->lanes > 2) {
0176 DRM_ERROR("dsi device params invalid, 1 or 2 lanes supported\n");
0177 return -EINVAL;
0178 }
0179
0180 dev_info(d->dev, "attached DSI device with %d lanes\n", mdsi->lanes);
0181
0182 dev_info(d->dev, "format %08x, %dbpp\n", mdsi->format,
0183 mipi_dsi_pixel_format_to_bpp(mdsi->format));
0184 dev_info(d->dev, "mode flags: %08lx\n", mdsi->mode_flags);
0185
0186 d->mdsi = mdsi;
0187 if (d->mcde)
0188 mcde_dsi_attach_to_mcde(d);
0189
0190 return 0;
0191 }
0192
0193 static int mcde_dsi_host_detach(struct mipi_dsi_host *host,
0194 struct mipi_dsi_device *mdsi)
0195 {
0196 struct mcde_dsi *d = host_to_mcde_dsi(host);
0197
0198 d->mdsi = NULL;
0199 if (d->mcde)
0200 d->mcde->mdsi = NULL;
0201
0202 return 0;
0203 }
0204
0205 #define MCDE_DSI_HOST_IS_READ(type) \
0206 ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
0207 (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
0208 (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
0209 (type == MIPI_DSI_DCS_READ))
0210
0211 static int mcde_dsi_execute_transfer(struct mcde_dsi *d,
0212 const struct mipi_dsi_msg *msg)
0213 {
0214 const u32 loop_delay_us = 10;
0215 u32 loop_counter;
0216 size_t txlen = msg->tx_len;
0217 size_t rxlen = msg->rx_len;
0218 int i;
0219 u32 val;
0220 int ret;
0221
0222 writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR);
0223 writel(~0, d->regs + DSI_CMD_MODE_STS_CLR);
0224
0225 writel(1, d->regs + DSI_DIRECT_CMD_SEND);
0226
0227 loop_counter = 1000 * 1000 / loop_delay_us;
0228 if (MCDE_DSI_HOST_IS_READ(msg->type)) {
0229
0230 while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
0231 (DSI_DIRECT_CMD_STS_READ_COMPLETED |
0232 DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR))
0233 && --loop_counter)
0234 usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);
0235 if (!loop_counter) {
0236 dev_err(d->dev, "DSI read timeout!\n");
0237
0238 return -ETIME;
0239 }
0240 } else {
0241
0242 while (!(readl(d->regs + DSI_DIRECT_CMD_STS) &
0243 DSI_DIRECT_CMD_STS_WRITE_COMPLETED)
0244 && --loop_counter)
0245 usleep_range(loop_delay_us, (loop_delay_us * 3) / 2);
0246
0247 if (!loop_counter) {
0248
0249 dev_err(d->dev, "DSI write timeout!\n");
0250 return -ETIME;
0251 }
0252 }
0253
0254 val = readl(d->regs + DSI_DIRECT_CMD_STS);
0255 if (val & DSI_DIRECT_CMD_STS_READ_COMPLETED_WITH_ERR) {
0256 dev_err(d->dev, "read completed with error\n");
0257 writel(1, d->regs + DSI_DIRECT_CMD_RD_INIT);
0258 return -EIO;
0259 }
0260 if (val & DSI_DIRECT_CMD_STS_ACKNOWLEDGE_WITH_ERR_RECEIVED) {
0261 val >>= DSI_DIRECT_CMD_STS_ACK_VAL_SHIFT;
0262 dev_err(d->dev, "error during transmission: %04x\n",
0263 val);
0264 return -EIO;
0265 }
0266
0267 if (!MCDE_DSI_HOST_IS_READ(msg->type)) {
0268
0269 ret = txlen;
0270 } else {
0271
0272 u32 rdsz;
0273 u32 rddat;
0274 u8 *rx = msg->rx_buf;
0275
0276 rdsz = readl(d->regs + DSI_DIRECT_CMD_RD_PROPERTY);
0277 rdsz &= DSI_DIRECT_CMD_RD_PROPERTY_RD_SIZE_MASK;
0278 rddat = readl(d->regs + DSI_DIRECT_CMD_RDDAT);
0279 if (rdsz < rxlen) {
0280 dev_err(d->dev, "read error, requested %zd got %d\n",
0281 rxlen, rdsz);
0282 return -EIO;
0283 }
0284
0285 for (i = 0; i < 4 && i < rxlen; i++)
0286 rx[i] = (rddat >> (i * 8)) & 0xff;
0287 ret = rdsz;
0288 }
0289
0290
0291 return ret;
0292 }
0293
0294 static ssize_t mcde_dsi_host_transfer(struct mipi_dsi_host *host,
0295 const struct mipi_dsi_msg *msg)
0296 {
0297 struct mcde_dsi *d = host_to_mcde_dsi(host);
0298 const u8 *tx = msg->tx_buf;
0299 size_t txlen = msg->tx_len;
0300 size_t rxlen = msg->rx_len;
0301 unsigned int retries = 0;
0302 u32 val;
0303 int ret;
0304 int i;
0305
0306 if (txlen > 16) {
0307 dev_err(d->dev,
0308 "dunno how to write more than 16 bytes yet\n");
0309 return -EIO;
0310 }
0311 if (rxlen > 4) {
0312 dev_err(d->dev,
0313 "dunno how to read more than 4 bytes yet\n");
0314 return -EIO;
0315 }
0316
0317 dev_dbg(d->dev,
0318 "message to channel %d, write %zd bytes read %zd bytes\n",
0319 msg->channel, txlen, rxlen);
0320
0321
0322 if (MCDE_DSI_HOST_IS_READ(msg->type))
0323
0324 val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_READ;
0325 else
0326 val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_WRITE;
0327
0328
0329
0330
0331
0332
0333 if (mipi_dsi_packet_format_is_long(msg->type))
0334 val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LONGNOTSHORT;
0335 val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT;
0336 val |= txlen << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
0337 val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN;
0338 val |= msg->type << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT;
0339 writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS);
0340
0341
0342 if (txlen > 0) {
0343 val = 0;
0344 for (i = 0; i < 4 && i < txlen; i++)
0345 val |= tx[i] << (i * 8);
0346 }
0347 writel(val, d->regs + DSI_DIRECT_CMD_WRDAT0);
0348 if (txlen > 4) {
0349 val = 0;
0350 for (i = 0; i < 4 && (i + 4) < txlen; i++)
0351 val |= tx[i + 4] << (i * 8);
0352 writel(val, d->regs + DSI_DIRECT_CMD_WRDAT1);
0353 }
0354 if (txlen > 8) {
0355 val = 0;
0356 for (i = 0; i < 4 && (i + 8) < txlen; i++)
0357 val |= tx[i + 8] << (i * 8);
0358 writel(val, d->regs + DSI_DIRECT_CMD_WRDAT2);
0359 }
0360 if (txlen > 12) {
0361 val = 0;
0362 for (i = 0; i < 4 && (i + 12) < txlen; i++)
0363 val |= tx[i + 12] << (i * 8);
0364 writel(val, d->regs + DSI_DIRECT_CMD_WRDAT3);
0365 }
0366
0367 while (retries < 3) {
0368 ret = mcde_dsi_execute_transfer(d, msg);
0369 if (ret >= 0)
0370 break;
0371 retries++;
0372 }
0373 if (ret < 0 && retries)
0374 dev_err(d->dev, "gave up after %d retries\n", retries);
0375
0376
0377 writel(~0, d->regs + DSI_DIRECT_CMD_STS_CLR);
0378 writel(~0, d->regs + DSI_CMD_MODE_STS_CLR);
0379
0380 return ret;
0381 }
0382
0383 static const struct mipi_dsi_host_ops mcde_dsi_host_ops = {
0384 .attach = mcde_dsi_host_attach,
0385 .detach = mcde_dsi_host_detach,
0386 .transfer = mcde_dsi_host_transfer,
0387 };
0388
0389
0390 void mcde_dsi_te_request(struct mipi_dsi_device *mdsi)
0391 {
0392 struct mcde_dsi *d;
0393 u32 val;
0394
0395 d = host_to_mcde_dsi(mdsi->host);
0396
0397
0398 val = DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_NAT_TE_REQ;
0399 val |= 0 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_ID_SHIFT;
0400 val |= 2 << DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_SIZE_SHIFT;
0401 val |= DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_LP_EN;
0402 val |= MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM <<
0403 DSI_DIRECT_CMD_MAIN_SETTINGS_CMD_HEAD_SHIFT;
0404 writel(val, d->regs + DSI_DIRECT_CMD_MAIN_SETTINGS);
0405
0406
0407 writel(DSI_DIRECT_CMD_STS_CLR_TE_RECEIVED_CLR |
0408 DSI_DIRECT_CMD_STS_CLR_ACKNOWLEDGE_WITH_ERR_RECEIVED_CLR,
0409 d->regs + DSI_DIRECT_CMD_STS_CLR);
0410 val = readl(d->regs + DSI_DIRECT_CMD_STS_CTL);
0411 val |= DSI_DIRECT_CMD_STS_CTL_TE_RECEIVED_EN;
0412 val |= DSI_DIRECT_CMD_STS_CTL_ACKNOWLEDGE_WITH_ERR_EN;
0413 writel(val, d->regs + DSI_DIRECT_CMD_STS_CTL);
0414
0415
0416 writel(DSI_CMD_MODE_STS_CLR_ERR_NO_TE_CLR |
0417 DSI_CMD_MODE_STS_CLR_ERR_TE_MISS_CLR,
0418 d->regs + DSI_CMD_MODE_STS_CLR);
0419 val = readl(d->regs + DSI_CMD_MODE_STS_CTL);
0420 val |= DSI_CMD_MODE_STS_CTL_ERR_NO_TE_EN;
0421 val |= DSI_CMD_MODE_STS_CTL_ERR_TE_MISS_EN;
0422 writel(val, d->regs + DSI_CMD_MODE_STS_CTL);
0423
0424
0425 writel(1, d->regs + DSI_DIRECT_CMD_SEND);
0426 }
0427
0428 static void mcde_dsi_setup_video_mode(struct mcde_dsi *d,
0429 const struct drm_display_mode *mode)
0430 {
0431
0432 u8 cpp = mipi_dsi_pixel_format_to_bpp(d->mdsi->format) / 8;
0433 u64 pclk;
0434 u64 bpl;
0435 int hfp;
0436 int hbp;
0437 int hsa;
0438 u32 blkline_pck, line_duration;
0439 u32 val;
0440
0441 val = 0;
0442 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
0443 val |= DSI_VID_MAIN_CTL_BURST_MODE;
0444 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
0445 val |= DSI_VID_MAIN_CTL_SYNC_PULSE_ACTIVE;
0446 val |= DSI_VID_MAIN_CTL_SYNC_PULSE_HORIZONTAL;
0447 }
0448
0449 switch (d->mdsi->format) {
0450 case MIPI_DSI_FMT_RGB565:
0451 val |= MIPI_DSI_PACKED_PIXEL_STREAM_16 <<
0452 DSI_VID_MAIN_CTL_HEADER_SHIFT;
0453 val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_16BITS;
0454 break;
0455 case MIPI_DSI_FMT_RGB666_PACKED:
0456 val |= MIPI_DSI_PACKED_PIXEL_STREAM_18 <<
0457 DSI_VID_MAIN_CTL_HEADER_SHIFT;
0458 val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS;
0459 break;
0460 case MIPI_DSI_FMT_RGB666:
0461 val |= MIPI_DSI_PIXEL_STREAM_3BYTE_18
0462 << DSI_VID_MAIN_CTL_HEADER_SHIFT;
0463 val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_18BITS_LOOSE;
0464 break;
0465 case MIPI_DSI_FMT_RGB888:
0466 val |= MIPI_DSI_PACKED_PIXEL_STREAM_24 <<
0467 DSI_VID_MAIN_CTL_HEADER_SHIFT;
0468 val |= DSI_VID_MAIN_CTL_VID_PIXEL_MODE_24BITS;
0469 break;
0470 default:
0471 dev_err(d->dev, "unknown pixel mode\n");
0472 return;
0473 }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 val |= DSI_VID_MAIN_CTL_REG_BLKLINE_MODE_LP_0;
0486
0487
0488
0489
0490 val |= DSI_VID_MAIN_CTL_REG_BLKEOL_MODE_LP_0;
0491
0492 val |= 1 << DSI_VID_MAIN_CTL_RECOVERY_MODE_SHIFT;
0493
0494 writel(val, d->regs + DSI_VID_MAIN_CTL);
0495
0496
0497 val = mode->vdisplay << DSI_VID_VSIZE_VACT_LENGTH_SHIFT;
0498
0499 val |= (mode->vsync_start - mode->vdisplay)
0500 << DSI_VID_VSIZE_VFP_LENGTH_SHIFT;
0501
0502 val |= (mode->vsync_end - mode->vsync_start)
0503 << DSI_VID_VSIZE_VSA_LENGTH_SHIFT;
0504
0505 val |= (mode->vtotal - mode->vsync_end)
0506 << DSI_VID_VSIZE_VBP_LENGTH_SHIFT;
0507 writel(val, d->regs + DSI_VID_VSIZE);
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521 hfp = (mode->hsync_start - mode->hdisplay) * cpp - 6 - 2;
0522 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
0523
0524
0525
0526
0527
0528 hbp = (mode->htotal - mode->hsync_end) * cpp - 4 - 6;
0529
0530
0531
0532
0533
0534 hsa = (mode->hsync_end - mode->hsync_start) * cpp - 4 - 4 - 6;
0535 } else {
0536
0537
0538
0539
0540
0541
0542 hbp = (mode->htotal - mode->hsync_start) * cpp - 4 - 4 - 6;
0543
0544 hsa = 0;
0545 }
0546 if (hfp < 0) {
0547 dev_info(d->dev, "hfp negative, set to 0\n");
0548 hfp = 0;
0549 }
0550 if (hbp < 0) {
0551 dev_info(d->dev, "hbp negative, set to 0\n");
0552 hbp = 0;
0553 }
0554 if (hsa < 0) {
0555 dev_info(d->dev, "hsa negative, set to 0\n");
0556 hsa = 0;
0557 }
0558 dev_dbg(d->dev, "hfp: %u, hbp: %u, hsa: %u bytes\n",
0559 hfp, hbp, hsa);
0560
0561
0562 val = hsa << DSI_VID_HSIZE1_HSA_LENGTH_SHIFT;
0563
0564 val |= hbp << DSI_VID_HSIZE1_HBP_LENGTH_SHIFT;
0565
0566 val |= hfp << DSI_VID_HSIZE1_HFP_LENGTH_SHIFT;
0567 writel(val, d->regs + DSI_VID_HSIZE1);
0568
0569
0570 val = mode->hdisplay * cpp;
0571 writel(val, d->regs + DSI_VID_HSIZE2);
0572 dev_dbg(d->dev, "RGB length, visible area on a line: %u bytes\n", val);
0573
0574
0575
0576
0577
0578
0579
0580 pclk = DIV_ROUND_UP_ULL(1000000000000, (mode->clock * 1000));
0581 dev_dbg(d->dev, "picoseconds between two pixels: %llu\n",
0582 pclk);
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599 bpl = pclk * mode->htotal;
0600 dev_dbg(d->dev, "picoseconds per line: %llu\n", bpl);
0601
0602 bpl *= (d->mdsi->hs_rate / 8);
0603
0604 bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000);
0605 bpl = DIV_ROUND_DOWN_ULL(bpl, 1000000);
0606
0607 bpl *= d->mdsi->lanes;
0608 dev_dbg(d->dev,
0609 "calculated bytes per line: %llu @ %d Hz with HS %lu Hz\n",
0610 bpl, drm_mode_vrefresh(mode), d->mdsi->hs_rate);
0611
0612
0613
0614
0615
0616 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
0617
0618 writel(0, d->regs + DSI_VID_BLKSIZE1);
0619
0620
0621
0622
0623
0624
0625 blkline_pck = bpl - (mode->hsync_end - mode->hsync_start) - 6;
0626 val = blkline_pck << DSI_VID_BLKSIZE2_BLKLINE_PULSE_PCK_SHIFT;
0627 writel(val, d->regs + DSI_VID_BLKSIZE2);
0628 } else {
0629
0630 writel(0, d->regs + DSI_VID_BLKSIZE2);
0631
0632 blkline_pck = bpl - 4 - 6;
0633 if (blkline_pck > 0x1FFF)
0634 dev_err(d->dev, "blkline_pck too big %d bytes\n",
0635 blkline_pck);
0636 val = blkline_pck << DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_SHIFT;
0637 val &= DSI_VID_BLKSIZE1_BLKLINE_EVENT_PCK_MASK;
0638 writel(val, d->regs + DSI_VID_BLKSIZE1);
0639 }
0640
0641
0642
0643
0644
0645
0646 line_duration = blkline_pck + 6;
0647
0648
0649
0650
0651
0652 if (d->mdsi->lanes == 2 && (hsa & 0x01) && (hfp & 0x01)
0653 && (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
0654 line_duration--;
0655 line_duration = DIV_ROUND_CLOSEST(line_duration, d->mdsi->lanes);
0656 dev_dbg(d->dev, "line duration %u bytes\n", line_duration);
0657 val = line_duration << DSI_VID_DPHY_TIME_REG_LINE_DURATION_SHIFT;
0658
0659
0660
0661
0662
0663
0664 val |= 48 << DSI_VID_DPHY_TIME_REG_WAKEUP_TIME_SHIFT;
0665 writel(val, d->regs + DSI_VID_DPHY_TIME);
0666
0667
0668
0669
0670
0671 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
0672 int blkeol_pck, blkeol_duration;
0673
0674
0675
0676
0677
0678
0679
0680
0681 blkeol_pck = bpl - (mode->htotal * cpp) - 6;
0682 if (blkeol_pck < 0) {
0683 dev_err(d->dev, "video block does not fit on line!\n");
0684 dev_err(d->dev,
0685 "calculated bytes per line: %llu @ %d Hz\n",
0686 bpl, drm_mode_vrefresh(mode));
0687 dev_err(d->dev,
0688 "bytes per line (blkline_pck) %u bytes\n",
0689 blkline_pck);
0690 dev_err(d->dev,
0691 "blkeol_pck becomes %d bytes\n", blkeol_pck);
0692 return;
0693 }
0694 dev_dbg(d->dev, "BLKEOL packet: %d bytes\n", blkeol_pck);
0695
0696 val = readl(d->regs + DSI_VID_BLKSIZE1);
0697 val &= ~DSI_VID_BLKSIZE1_BLKEOL_PCK_MASK;
0698 val |= blkeol_pck << DSI_VID_BLKSIZE1_BLKEOL_PCK_SHIFT;
0699 writel(val, d->regs + DSI_VID_BLKSIZE1);
0700
0701 val = blkeol_pck <<
0702 DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_SHIFT;
0703 val &= DSI_VID_VCA_SETTING2_EXACT_BURST_LIMIT_MASK;
0704 writel(val, d->regs + DSI_VID_VCA_SETTING2);
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721 blkeol_duration = DIV_ROUND_CLOSEST(blkeol_pck + 6,
0722 d->mdsi->lanes);
0723 dev_dbg(d->dev, "BLKEOL duration: %d clock cycles\n",
0724 blkeol_duration);
0725
0726 val = readl(d->regs + DSI_VID_PCK_TIME);
0727 val &= ~DSI_VID_PCK_TIME_BLKEOL_DURATION_MASK;
0728 val |= blkeol_duration <<
0729 DSI_VID_PCK_TIME_BLKEOL_DURATION_SHIFT;
0730 writel(val, d->regs + DSI_VID_PCK_TIME);
0731
0732
0733 val = readl(d->regs + DSI_VID_VCA_SETTING1);
0734 val &= ~DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_MASK;
0735 val |= (blkeol_pck - 6) <<
0736 DSI_VID_VCA_SETTING1_MAX_BURST_LIMIT_SHIFT;
0737 writel(val, d->regs + DSI_VID_VCA_SETTING1);
0738 }
0739
0740
0741 val = readl(d->regs + DSI_VID_VCA_SETTING2);
0742 val &= ~DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_MASK;
0743 val |= (blkline_pck - 6) <<
0744 DSI_VID_VCA_SETTING2_MAX_LINE_LIMIT_SHIFT;
0745 writel(val, d->regs + DSI_VID_VCA_SETTING2);
0746 dev_dbg(d->dev, "blkline pck: %d bytes\n", blkline_pck - 6);
0747 }
0748
0749 static void mcde_dsi_start(struct mcde_dsi *d)
0750 {
0751 unsigned long hs_freq;
0752 u32 val;
0753 int i;
0754
0755
0756 writel(0, d->regs + DSI_MCTL_INTEGRATION_MODE);
0757
0758
0759 val = DSI_MCTL_MAIN_DATA_CTL_LINK_EN |
0760 DSI_MCTL_MAIN_DATA_CTL_BTA_EN |
0761 DSI_MCTL_MAIN_DATA_CTL_READ_EN |
0762 DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN;
0763 if (!(d->mdsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
0764 val |= DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN;
0765 writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
0766
0767
0768 val = 0x3ff << DSI_CMD_MODE_CTL_TE_TIMEOUT_SHIFT;
0769 writel(val, d->regs + DSI_CMD_MODE_CTL);
0770
0771
0772
0773
0774
0775
0776 hs_freq = clk_get_rate(d->hs_clk);
0777 hs_freq /= 1000000;
0778 val = 4000 / hs_freq;
0779 dev_dbg(d->dev, "UI value: %d\n", val);
0780 val <<= DSI_MCTL_DPHY_STATIC_UI_X4_SHIFT;
0781 val &= DSI_MCTL_DPHY_STATIC_UI_X4_MASK;
0782 writel(val, d->regs + DSI_MCTL_DPHY_STATIC);
0783
0784
0785
0786
0787
0788
0789
0790 val = 0x0f << DSI_MCTL_MAIN_PHY_CTL_WAIT_BURST_TIME_SHIFT;
0791 if (d->mdsi->lanes == 2)
0792 val |= DSI_MCTL_MAIN_PHY_CTL_LANE2_EN;
0793 if (!(d->mdsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
0794 val |= DSI_MCTL_MAIN_PHY_CTL_CLK_CONTINUOUS;
0795 val |= DSI_MCTL_MAIN_PHY_CTL_CLK_ULPM_EN |
0796 DSI_MCTL_MAIN_PHY_CTL_DAT1_ULPM_EN |
0797 DSI_MCTL_MAIN_PHY_CTL_DAT2_ULPM_EN;
0798 writel(val, d->regs + DSI_MCTL_MAIN_PHY_CTL);
0799
0800 val = (1 << DSI_MCTL_ULPOUT_TIME_CKLANE_ULPOUT_TIME_SHIFT) |
0801 (1 << DSI_MCTL_ULPOUT_TIME_DATA_ULPOUT_TIME_SHIFT);
0802 writel(val, d->regs + DSI_MCTL_ULPOUT_TIME);
0803
0804 writel(DSI_DPHY_LANES_TRIM_DPHY_SPECS_90_81B_0_90,
0805 d->regs + DSI_DPHY_LANES_TRIM);
0806
0807
0808 val = (0x0f << DSI_MCTL_DPHY_TIMEOUT_CLK_DIV_SHIFT) |
0809 (0x3fff << DSI_MCTL_DPHY_TIMEOUT_HSTX_TO_VAL_SHIFT) |
0810 (0x3fff << DSI_MCTL_DPHY_TIMEOUT_LPRX_TO_VAL_SHIFT);
0811 writel(val, d->regs + DSI_MCTL_DPHY_TIMEOUT);
0812
0813 val = DSI_MCTL_MAIN_EN_PLL_START |
0814 DSI_MCTL_MAIN_EN_CKLANE_EN |
0815 DSI_MCTL_MAIN_EN_DAT1_EN |
0816 DSI_MCTL_MAIN_EN_IF1_EN;
0817 if (d->mdsi->lanes == 2)
0818 val |= DSI_MCTL_MAIN_EN_DAT2_EN;
0819 writel(val, d->regs + DSI_MCTL_MAIN_EN);
0820
0821
0822 i = 0;
0823 val = DSI_MCTL_MAIN_STS_PLL_LOCK |
0824 DSI_MCTL_MAIN_STS_CLKLANE_READY |
0825 DSI_MCTL_MAIN_STS_DAT1_READY;
0826 if (d->mdsi->lanes == 2)
0827 val |= DSI_MCTL_MAIN_STS_DAT2_READY;
0828 while ((readl(d->regs + DSI_MCTL_MAIN_STS) & val) != val) {
0829
0830 usleep_range(1000, 1500);
0831 if (i++ == 100) {
0832 dev_warn(d->dev, "DSI lanes did not start up\n");
0833 return;
0834 }
0835 }
0836
0837
0838
0839
0840 val = readl(d->regs + DSI_CMD_MODE_CTL);
0841
0842
0843
0844
0845 if (d->mdsi->mode_flags & MIPI_DSI_MODE_LPM)
0846 val |= DSI_CMD_MODE_CTL_IF1_LP_EN;
0847 val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK;
0848 writel(val, d->regs + DSI_CMD_MODE_CTL);
0849
0850
0851 usleep_range(100, 200);
0852 dev_info(d->dev, "DSI link enabled\n");
0853 }
0854
0855
0856
0857
0858
0859 void mcde_dsi_enable(struct drm_bridge *bridge)
0860 {
0861 struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
0862 unsigned long hs_freq, lp_freq;
0863 u32 val;
0864 int ret;
0865
0866
0867 if (d->mdsi->lp_rate)
0868 lp_freq = d->mdsi->lp_rate;
0869 else
0870 lp_freq = DSI_DEFAULT_LP_FREQ_HZ;
0871 if (d->mdsi->hs_rate)
0872 hs_freq = d->mdsi->hs_rate;
0873 else
0874 hs_freq = DSI_DEFAULT_HS_FREQ_HZ;
0875
0876
0877 d->lp_freq = clk_round_rate(d->lp_clk, lp_freq);
0878 ret = clk_set_rate(d->lp_clk, d->lp_freq);
0879 if (ret)
0880 dev_err(d->dev, "failed to set LP clock rate %lu Hz\n",
0881 d->lp_freq);
0882
0883 d->hs_freq = clk_round_rate(d->hs_clk, hs_freq);
0884 ret = clk_set_rate(d->hs_clk, d->hs_freq);
0885 if (ret)
0886 dev_err(d->dev, "failed to set HS clock rate %lu Hz\n",
0887 d->hs_freq);
0888
0889
0890 ret = clk_prepare_enable(d->lp_clk);
0891 if (ret)
0892 dev_err(d->dev, "failed to enable LP clock\n");
0893 else
0894 dev_info(d->dev, "DSI LP clock rate %lu Hz\n",
0895 d->lp_freq);
0896 ret = clk_prepare_enable(d->hs_clk);
0897 if (ret)
0898 dev_err(d->dev, "failed to enable HS clock\n");
0899 else
0900 dev_info(d->dev, "DSI HS clock rate %lu Hz\n",
0901 d->hs_freq);
0902
0903
0904
0905 regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
0906 PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0);
0907
0908 usleep_range(100, 200);
0909
0910
0911 regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
0912 PRCM_DSI_SW_RESET_DSI0_SW_RESETN,
0913 PRCM_DSI_SW_RESET_DSI0_SW_RESETN);
0914
0915
0916 mcde_dsi_start(d);
0917
0918 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
0919
0920 mcde_dsi_setup_video_mode(d, d->mode);
0921
0922
0923 val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
0924 val |= DSI_MCTL_MAIN_DATA_CTL_IF1_MODE;
0925 writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
0926
0927
0928 val = readl(d->regs + DSI_CMD_MODE_CTL);
0929 val &= ~DSI_CMD_MODE_CTL_IF1_LP_EN;
0930 writel(val, d->regs + DSI_CMD_MODE_CTL);
0931
0932
0933 val = readl(d->regs + DSI_VID_MODE_STS_CTL);
0934 val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_VSYNC;
0935 val |= DSI_VID_MODE_STS_CTL_ERR_MISSING_DATA;
0936 writel(val, d->regs + DSI_VID_MODE_STS_CTL);
0937
0938
0939 val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
0940 val |= DSI_MCTL_MAIN_DATA_CTL_VID_EN;
0941 writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
0942 } else {
0943
0944 val = readl(d->regs + DSI_CMD_MODE_CTL);
0945
0946
0947
0948
0949 if (d->mdsi->mode_flags & MIPI_DSI_MODE_LPM)
0950 val |= DSI_CMD_MODE_CTL_IF1_LP_EN;
0951 val &= ~DSI_CMD_MODE_CTL_IF1_ID_MASK;
0952 writel(val, d->regs + DSI_CMD_MODE_CTL);
0953 }
0954
0955 dev_info(d->dev, "enabled MCDE DSI master\n");
0956 }
0957
0958 static void mcde_dsi_bridge_mode_set(struct drm_bridge *bridge,
0959 const struct drm_display_mode *mode,
0960 const struct drm_display_mode *adj)
0961 {
0962 struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
0963
0964 if (!d->mdsi) {
0965 dev_err(d->dev, "no DSI device attached to encoder!\n");
0966 return;
0967 }
0968
0969 d->mode = mode;
0970
0971 dev_info(d->dev, "set DSI master to %dx%d %u Hz %s mode\n",
0972 mode->hdisplay, mode->vdisplay, mode->clock * 1000,
0973 (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) ? "VIDEO" : "CMD"
0974 );
0975 }
0976
0977 static void mcde_dsi_wait_for_command_mode_stop(struct mcde_dsi *d)
0978 {
0979 u32 val;
0980 int i;
0981
0982
0983
0984
0985
0986 i = 0;
0987 val = DSI_CMD_MODE_STS_CSM_RUNNING;
0988 while ((readl(d->regs + DSI_CMD_MODE_STS) & val) == val) {
0989
0990 usleep_range(1000, 2000);
0991 if (i++ == 100) {
0992 dev_warn(d->dev,
0993 "could not get out of command mode\n");
0994 return;
0995 }
0996 }
0997 }
0998
0999 static void mcde_dsi_wait_for_video_mode_stop(struct mcde_dsi *d)
1000 {
1001 u32 val;
1002 int i;
1003
1004
1005 i = 0;
1006 val = DSI_VID_MODE_STS_VSG_RUNNING;
1007 while ((readl(d->regs + DSI_VID_MODE_STS) & val) == val) {
1008
1009 usleep_range(1000, 2000);
1010 if (i++ == 100) {
1011 dev_warn(d->dev,
1012 "could not get out of video mode\n");
1013 return;
1014 }
1015 }
1016 }
1017
1018
1019
1020
1021
1022 void mcde_dsi_disable(struct drm_bridge *bridge)
1023 {
1024 struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
1025 u32 val;
1026
1027 if (d->mdsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
1028
1029 val = readl(d->regs + DSI_MCTL_MAIN_DATA_CTL);
1030 val &= ~DSI_MCTL_MAIN_DATA_CTL_VID_EN;
1031 writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
1032 mcde_dsi_wait_for_video_mode_stop(d);
1033 } else {
1034
1035 mcde_dsi_wait_for_command_mode_stop(d);
1036 }
1037
1038
1039
1040
1041
1042
1043
1044
1045 writel(0, d->regs + DSI_VID_MODE_STS_CTL);
1046 clk_disable_unprepare(d->hs_clk);
1047 clk_disable_unprepare(d->lp_clk);
1048 }
1049
1050 static int mcde_dsi_bridge_attach(struct drm_bridge *bridge,
1051 enum drm_bridge_attach_flags flags)
1052 {
1053 struct mcde_dsi *d = bridge_to_mcde_dsi(bridge);
1054 struct drm_device *drm = bridge->dev;
1055
1056 if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
1057 dev_err(d->dev, "we need atomic updates\n");
1058 return -ENOTSUPP;
1059 }
1060
1061
1062 return drm_bridge_attach(bridge->encoder, d->bridge_out, bridge, flags);
1063 }
1064
1065 static const struct drm_bridge_funcs mcde_dsi_bridge_funcs = {
1066 .attach = mcde_dsi_bridge_attach,
1067 .mode_set = mcde_dsi_bridge_mode_set,
1068 };
1069
1070 static int mcde_dsi_bind(struct device *dev, struct device *master,
1071 void *data)
1072 {
1073 struct drm_device *drm = data;
1074 struct mcde *mcde = to_mcde(drm);
1075 struct mcde_dsi *d = dev_get_drvdata(dev);
1076 struct device_node *child;
1077 struct drm_panel *panel = NULL;
1078 struct drm_bridge *bridge = NULL;
1079
1080 if (!of_get_available_child_count(dev->of_node)) {
1081 dev_info(dev, "unused DSI interface\n");
1082 d->unused = true;
1083 return 0;
1084 }
1085 d->mcde = mcde;
1086
1087 if (d->mdsi)
1088 mcde_dsi_attach_to_mcde(d);
1089
1090
1091 d->hs_clk = devm_clk_get(dev, "hs");
1092 if (IS_ERR(d->hs_clk)) {
1093 dev_err(dev, "unable to get HS clock\n");
1094 return PTR_ERR(d->hs_clk);
1095 }
1096
1097 d->lp_clk = devm_clk_get(dev, "lp");
1098 if (IS_ERR(d->lp_clk)) {
1099 dev_err(dev, "unable to get LP clock\n");
1100 return PTR_ERR(d->lp_clk);
1101 }
1102
1103
1104 for_each_available_child_of_node(dev->of_node, child) {
1105 panel = of_drm_find_panel(child);
1106 if (IS_ERR(panel)) {
1107 dev_err(dev, "failed to find panel try bridge (%ld)\n",
1108 PTR_ERR(panel));
1109 panel = NULL;
1110
1111 bridge = of_drm_find_bridge(child);
1112 if (!bridge) {
1113 dev_err(dev, "failed to find bridge\n");
1114 of_node_put(child);
1115 return -EINVAL;
1116 }
1117 }
1118 }
1119 if (panel) {
1120 bridge = drm_panel_bridge_add_typed(panel,
1121 DRM_MODE_CONNECTOR_DSI);
1122 if (IS_ERR(bridge)) {
1123 dev_err(dev, "error adding panel bridge\n");
1124 return PTR_ERR(bridge);
1125 }
1126 dev_info(dev, "connected to panel\n");
1127 d->panel = panel;
1128 } else if (bridge) {
1129
1130 dev_info(dev, "connected to non-panel bridge (unsupported)\n");
1131 return -ENODEV;
1132 } else {
1133 dev_err(dev, "no panel or bridge\n");
1134 return -ENODEV;
1135 }
1136
1137 d->bridge_out = bridge;
1138
1139
1140 d->bridge.funcs = &mcde_dsi_bridge_funcs;
1141 d->bridge.of_node = dev->of_node;
1142 drm_bridge_add(&d->bridge);
1143
1144
1145 mcde->bridge = &d->bridge;
1146
1147 dev_info(dev, "initialized MCDE DSI bridge\n");
1148
1149 return 0;
1150 }
1151
1152 static void mcde_dsi_unbind(struct device *dev, struct device *master,
1153 void *data)
1154 {
1155 struct mcde_dsi *d = dev_get_drvdata(dev);
1156
1157 if (d->panel)
1158 drm_panel_bridge_remove(d->bridge_out);
1159 regmap_update_bits(d->prcmu, PRCM_DSI_SW_RESET,
1160 PRCM_DSI_SW_RESET_DSI0_SW_RESETN, 0);
1161 }
1162
1163 static const struct component_ops mcde_dsi_component_ops = {
1164 .bind = mcde_dsi_bind,
1165 .unbind = mcde_dsi_unbind,
1166 };
1167
1168 static int mcde_dsi_probe(struct platform_device *pdev)
1169 {
1170 struct device *dev = &pdev->dev;
1171 struct mcde_dsi *d;
1172 struct mipi_dsi_host *host;
1173 u32 dsi_id;
1174 int ret;
1175
1176 d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
1177 if (!d)
1178 return -ENOMEM;
1179 d->dev = dev;
1180 platform_set_drvdata(pdev, d);
1181
1182
1183 d->prcmu =
1184 syscon_regmap_lookup_by_compatible("stericsson,db8500-prcmu");
1185 if (IS_ERR(d->prcmu)) {
1186 dev_err(dev, "no PRCMU regmap\n");
1187 return PTR_ERR(d->prcmu);
1188 }
1189
1190 d->regs = devm_platform_ioremap_resource(pdev, 0);
1191 if (IS_ERR(d->regs))
1192 return PTR_ERR(d->regs);
1193
1194 dsi_id = readl(d->regs + DSI_ID_REG);
1195 dev_info(dev, "HW revision 0x%08x\n", dsi_id);
1196
1197 host = &d->dsi_host;
1198 host->dev = dev;
1199 host->ops = &mcde_dsi_host_ops;
1200 ret = mipi_dsi_host_register(host);
1201 if (ret < 0) {
1202 dev_err(dev, "failed to register DSI host: %d\n", ret);
1203 return ret;
1204 }
1205 dev_info(dev, "registered DSI host\n");
1206
1207 platform_set_drvdata(pdev, d);
1208 return component_add(dev, &mcde_dsi_component_ops);
1209 }
1210
1211 static int mcde_dsi_remove(struct platform_device *pdev)
1212 {
1213 struct mcde_dsi *d = platform_get_drvdata(pdev);
1214
1215 component_del(&pdev->dev, &mcde_dsi_component_ops);
1216 mipi_dsi_host_unregister(&d->dsi_host);
1217
1218 return 0;
1219 }
1220
1221 static const struct of_device_id mcde_dsi_of_match[] = {
1222 {
1223 .compatible = "ste,mcde-dsi",
1224 },
1225 {},
1226 };
1227
1228 struct platform_driver mcde_dsi_driver = {
1229 .driver = {
1230 .name = "mcde-dsi",
1231 .of_match_table = of_match_ptr(mcde_dsi_of_match),
1232 },
1233 .probe = mcde_dsi_probe,
1234 .remove = mcde_dsi_remove,
1235 };