Lines Matching +full:dw +full:- +full:mipi +full:- +full:dsi

1 // SPDX-License-Identifier: GPL-2.0+
6 * This generic Synopsys DesignWare MIPI DSI2 host driver is based on the
7 * Rockchip version from rockchip/dw-mipi-dsi2.c converted to use bridge APIs.
13 #include <linux/media-bus-format.h>
69 #define PHY_LANES(x) FIELD_PREP(GENMASK(5, 4), (x) - 1)
226 ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_CORE_STATUS, sts, in cri_fifos_wait_avail()
229 dev_err(dsi2->dev, "command interface is busy\n"); in cri_fifos_wait_avail()
241 if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HFP) in dw_mipi_dsi2_set_vid_mode()
244 if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HBP) in dw_mipi_dsi2_set_vid_mode()
247 if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HSA) in dw_mipi_dsi2_set_vid_mode()
250 if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) in dw_mipi_dsi2_set_vid_mode()
252 else if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) in dw_mipi_dsi2_set_vid_mode()
257 regmap_write(dsi2->regmap, DSI2_DSI_VID_TX_CFG, val); in dw_mipi_dsi2_set_vid_mode()
259 regmap_write(dsi2->regmap, DSI2_MODE_CTRL, VIDEO_MODE); in dw_mipi_dsi2_set_vid_mode()
260 ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, in dw_mipi_dsi2_set_vid_mode()
264 dev_err(dsi2->dev, "failed to enter video mode\n"); in dw_mipi_dsi2_set_vid_mode()
272 regmap_write(dsi2->regmap, DSI2_MODE_CTRL, DATA_STREAM_MODE); in dw_mipi_dsi2_set_data_stream_mode()
273 ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, in dw_mipi_dsi2_set_data_stream_mode()
277 dev_err(dsi2->dev, "failed to enter data stream mode\n"); in dw_mipi_dsi2_set_data_stream_mode()
285 regmap_write(dsi2->regmap, DSI2_MODE_CTRL, COMMAND_MODE); in dw_mipi_dsi2_set_cmd_mode()
286 ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, in dw_mipi_dsi2_set_cmd_mode()
290 dev_err(dsi2->dev, "failed to enter data stream mode\n"); in dw_mipi_dsi2_set_cmd_mode()
295 regmap_write(dsi2->regmap, DSI2_SOFT_RESET, 0x0); in dw_mipi_dsi2_host_softrst()
297 regmap_write(dsi2->regmap, DSI2_SOFT_RESET, in dw_mipi_dsi2_host_softrst()
313 sys_clk = clk_get_rate(dsi2->sys_clk) / USEC_PER_SEC; in dw_mipi_dsi2_phy_clk_mode_cfg()
317 regmap_write(dsi2->regmap, DSI2_PHY_CLK_CFG, val); in dw_mipi_dsi2_phy_clk_mode_cfg()
322 struct drm_display_mode *mode = &dsi2->mode; in dw_mipi_dsi2_phy_ratio_cfg()
323 u64 sys_clk = clk_get_rate(dsi2->sys_clk); in dw_mipi_dsi2_phy_ratio_cfg()
328 * in DPHY mode, the phy_hstx_clk is exactly 1/16 the Lane high-speed in dw_mipi_dsi2_phy_ratio_cfg()
332 phy_hsclk = DIV_ROUND_CLOSEST_ULL(dsi2->lane_mbps * USEC_PER_SEC, 16); in dw_mipi_dsi2_phy_ratio_cfg()
335 pixel_clk = mode->crtc_clock * MSEC_PER_SEC; in dw_mipi_dsi2_phy_ratio_cfg()
339 regmap_write(dsi2->regmap, DSI2_PHY_IPI_RATIO_MAN_CFG, in dw_mipi_dsi2_phy_ratio_cfg()
346 regmap_write(dsi2->regmap, DSI2_PHY_SYS_RATIO_MAN_CFG, in dw_mipi_dsi2_phy_ratio_cfg()
352 const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops; in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
356 ret = phy_ops->get_timing(dsi2->plat_data->priv_data, in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
357 dsi2->lane_mbps, &timing); in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
359 dev_err(dsi2->dev, "Retrieving phy timings failed\n"); in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
361 regmap_write(dsi2->regmap, DSI2_PHY_LP2HS_MAN_CFG, PHY_LP2HS_TIME(timing.data_lp2hs)); in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
362 regmap_write(dsi2->regmap, DSI2_PHY_HS2LP_MAN_CFG, PHY_HS2LP_TIME(timing.data_hs2lp)); in dw_mipi_dsi2_lp2hs_or_hs2lp_cfg()
367 const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops; in dw_mipi_dsi2_phy_init()
371 phy_ops->get_interface(dsi2->plat_data->priv_data, &iface); in dw_mipi_dsi2_phy_init()
388 val |= PHY_LANES(dsi2->lanes); in dw_mipi_dsi2_phy_init()
390 regmap_write(dsi2->regmap, DSI2_PHY_MODE_CFG, val); in dw_mipi_dsi2_phy_init()
396 /* phy configuration 8 - 10 */ in dw_mipi_dsi2_phy_init()
405 if (dsi2->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) in dw_mipi_dsi2_tx_option_set()
408 regmap_write(dsi2->regmap, DSI2_DSI_GENERAL_CFG, val); in dw_mipi_dsi2_tx_option_set()
409 regmap_write(dsi2->regmap, DSI2_DSI_VCID_CFG, TX_VCID(dsi2->channel)); in dw_mipi_dsi2_tx_option_set()
416 switch (dsi2->format) { in dw_mipi_dsi2_ipi_color_coding_cfg()
432 regmap_write(dsi2->regmap, DSI2_IPI_COLOR_MAN_CFG, val); in dw_mipi_dsi2_ipi_color_coding_cfg()
440 vactive = mode->vdisplay; in dw_mipi_dsi2_vertical_timing_config()
441 vsa = mode->vsync_end - mode->vsync_start; in dw_mipi_dsi2_vertical_timing_config()
442 vfp = mode->vsync_start - mode->vdisplay; in dw_mipi_dsi2_vertical_timing_config()
443 vbp = mode->vtotal - mode->vsync_end; in dw_mipi_dsi2_vertical_timing_config()
445 regmap_write(dsi2->regmap, DSI2_IPI_VID_VSA_MAN_CFG, VID_VSA_LINES(vsa)); in dw_mipi_dsi2_vertical_timing_config()
446 regmap_write(dsi2->regmap, DSI2_IPI_VID_VBP_MAN_CFG, VID_VBP_LINES(vbp)); in dw_mipi_dsi2_vertical_timing_config()
447 regmap_write(dsi2->regmap, DSI2_IPI_VID_VACT_MAN_CFG, VID_VACT_LINES(vactive)); in dw_mipi_dsi2_vertical_timing_config()
448 regmap_write(dsi2->regmap, DSI2_IPI_VID_VFP_MAN_CFG, VID_VFP_LINES(vfp)); in dw_mipi_dsi2_vertical_timing_config()
453 struct drm_display_mode *mode = &dsi2->mode; in dw_mipi_dsi2_ipi_set()
459 val = mode->hdisplay; in dw_mipi_dsi2_ipi_set()
461 regmap_write(dsi2->regmap, DSI2_IPI_PIX_PKT_CFG, MAX_PIX_PKT(val)); in dw_mipi_dsi2_ipi_set()
469 if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO)) in dw_mipi_dsi2_ipi_set()
472 hact = mode->hdisplay; in dw_mipi_dsi2_ipi_set()
473 hsa = mode->hsync_end - mode->hsync_start; in dw_mipi_dsi2_ipi_set()
474 hbp = mode->htotal - mode->hsync_end; in dw_mipi_dsi2_ipi_set()
475 hline = mode->htotal; in dw_mipi_dsi2_ipi_set()
477 pixel_clk = mode->crtc_clock * MSEC_PER_SEC; in dw_mipi_dsi2_ipi_set()
479 phy_hs_clk = DIV_ROUND_CLOSEST_ULL(dsi2->lane_mbps * USEC_PER_SEC, 16); in dw_mipi_dsi2_ipi_set()
483 regmap_write(dsi2->regmap, DSI2_IPI_VID_HSA_MAN_CFG, VID_HSA_TIME(hsa_time)); in dw_mipi_dsi2_ipi_set()
487 regmap_write(dsi2->regmap, DSI2_IPI_VID_HBP_MAN_CFG, VID_HBP_TIME(hbp_time)); in dw_mipi_dsi2_ipi_set()
491 regmap_write(dsi2->regmap, DSI2_IPI_VID_HACT_MAN_CFG, VID_HACT_TIME(hact_time)); in dw_mipi_dsi2_ipi_set()
495 regmap_write(dsi2->regmap, DSI2_IPI_VID_HLINE_MAN_CFG, VID_HLINE_TIME(hline_time)); in dw_mipi_dsi2_ipi_set()
508 regmap_write(dsi2->regmap, MANUAL_MODE_CFG, mode); in dw_mipi_dsi2_work_mode()
515 const struct dw_mipi_dsi2_plat_data *pdata = dsi2->plat_data; in dw_mipi_dsi2_host_attach()
519 if (device->lanes > dsi2->plat_data->max_data_lanes) { in dw_mipi_dsi2_host_attach()
520 dev_err(dsi2->dev, "the number of data lanes(%u) is too many\n", in dw_mipi_dsi2_host_attach()
521 device->lanes); in dw_mipi_dsi2_host_attach()
522 return -EINVAL; in dw_mipi_dsi2_host_attach()
525 dsi2->lanes = device->lanes; in dw_mipi_dsi2_host_attach()
526 dsi2->channel = device->channel; in dw_mipi_dsi2_host_attach()
527 dsi2->format = device->format; in dw_mipi_dsi2_host_attach()
528 dsi2->mode_flags = device->mode_flags; in dw_mipi_dsi2_host_attach()
530 bridge = devm_drm_of_get_bridge(dsi2->dev, dsi2->dev->of_node, 1, 0); in dw_mipi_dsi2_host_attach()
534 bridge->pre_enable_prev_first = true; in dw_mipi_dsi2_host_attach()
535 dsi2->panel_bridge = bridge; in dw_mipi_dsi2_host_attach()
537 drm_bridge_add(&dsi2->bridge); in dw_mipi_dsi2_host_attach()
539 if (pdata->host_ops && pdata->host_ops->attach) { in dw_mipi_dsi2_host_attach()
540 ret = pdata->host_ops->attach(pdata->priv_data, device); in dw_mipi_dsi2_host_attach()
552 const struct dw_mipi_dsi2_plat_data *pdata = dsi2->plat_data; in dw_mipi_dsi2_host_detach()
555 if (pdata->host_ops && pdata->host_ops->detach) { in dw_mipi_dsi2_host_detach()
556 ret = pdata->host_ops->detach(pdata->priv_data, device); in dw_mipi_dsi2_host_detach()
561 drm_bridge_remove(&dsi2->bridge); in dw_mipi_dsi2_host_detach()
563 drm_of_panel_bridge_remove(host->dev->of_node, 1, 0); in dw_mipi_dsi2_host_detach()
573 regmap_write(dsi2->regmap, DSI2_CRI_TX_HDR, hdr_val | CMD_TX_MODE(lpm)); in dw_mipi_dsi2_gen_pkt_hdr_write()
577 dev_err(dsi2->dev, "failed to write command header\n"); in dw_mipi_dsi2_gen_pkt_hdr_write()
587 const u8 *tx_buf = packet->payload; in dw_mipi_dsi2_write()
588 int len = packet->payload_length, pld_data_bytes = sizeof(u32); in dw_mipi_dsi2_write()
596 regmap_write(dsi2->regmap, DSI2_CRI_TX_PLD, le32_to_cpu(word)); in dw_mipi_dsi2_write()
600 regmap_write(dsi2->regmap, DSI2_CRI_TX_PLD, le32_to_cpu(word)); in dw_mipi_dsi2_write()
602 len -= pld_data_bytes; in dw_mipi_dsi2_write()
607 memcpy(&word, packet->header, sizeof(packet->header)); in dw_mipi_dsi2_write()
614 u8 *payload = msg->rx_buf; in dw_mipi_dsi2_read()
615 int i, j, ret, len = msg->rx_len; in dw_mipi_dsi2_read()
620 ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_CORE_STATUS, in dw_mipi_dsi2_read()
624 dev_err(dsi2->dev, "CRI has no available read data\n"); in dw_mipi_dsi2_read()
628 regmap_read(dsi2->regmap, DSI2_CRI_RX_HDR, &val); in dw_mipi_dsi2_read()
641 regmap_read(dsi2->regmap, DSI2_CRI_RX_PLD, &val); in dw_mipi_dsi2_read()
653 bool lpm = msg->flags & MIPI_DSI_MSG_USE_LPM; in dw_mipi_dsi2_host_transfer()
657 regmap_update_bits(dsi2->regmap, DSI2_DSI_VID_TX_CFG, in dw_mipi_dsi2_host_transfer()
661 /* create a packet to the DSI protocol */ in dw_mipi_dsi2_host_transfer()
664 dev_err(dsi2->dev, "failed to create packet: %d\n", ret); in dw_mipi_dsi2_host_transfer()
676 if (msg->rx_buf && msg->rx_len) { in dw_mipi_dsi2_host_transfer()
680 nb_bytes = msg->rx_len; in dw_mipi_dsi2_host_transfer()
703 const struct dw_mipi_dsi2_plat_data *pdata = dsi2->plat_data; in dw_mipi_dsi2_bridge_atomic_get_input_bus_fmts()
706 if (pdata->get_input_bus_fmts) in dw_mipi_dsi2_bridge_atomic_get_input_bus_fmts()
707 return pdata->get_input_bus_fmts(pdata->priv_data, in dw_mipi_dsi2_bridge_atomic_get_input_bus_fmts()
728 const struct dw_mipi_dsi2_plat_data *pdata = dsi2->plat_data; in dw_mipi_dsi2_bridge_atomic_check()
731 bridge_state->input_bus_cfg.flags = in dw_mipi_dsi2_bridge_atomic_check()
734 if (pdata->mode_fixup) { in dw_mipi_dsi2_bridge_atomic_check()
735 ret = pdata->mode_fixup(pdata->priv_data, &crtc_state->mode, in dw_mipi_dsi2_bridge_atomic_check()
736 &crtc_state->adjusted_mode); in dw_mipi_dsi2_bridge_atomic_check()
739 DRM_MODE_ARG(&crtc_state->mode)); in dw_mipi_dsi2_bridge_atomic_check()
740 return -EINVAL; in dw_mipi_dsi2_bridge_atomic_check()
751 const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops; in dw_mipi_dsi2_bridge_post_atomic_disable()
753 regmap_write(dsi2->regmap, DSI2_IPI_PIX_PKT_CFG, 0); in dw_mipi_dsi2_bridge_post_atomic_disable()
756 * Switch to command mode before panel-bridge post_disable & in dw_mipi_dsi2_bridge_post_atomic_disable()
758 * Note: panel-bridge disable & panel disable has been called in dw_mipi_dsi2_bridge_post_atomic_disable()
763 regmap_write(dsi2->regmap, DSI2_PWR_UP, RESET); in dw_mipi_dsi2_bridge_post_atomic_disable()
765 if (phy_ops->power_off) in dw_mipi_dsi2_bridge_post_atomic_disable()
766 phy_ops->power_off(dsi2->plat_data->priv_data); in dw_mipi_dsi2_bridge_post_atomic_disable()
768 clk_disable_unprepare(dsi2->sys_clk); in dw_mipi_dsi2_bridge_post_atomic_disable()
769 clk_disable_unprepare(dsi2->pclk); in dw_mipi_dsi2_bridge_post_atomic_disable()
770 pm_runtime_put(dsi2->dev); in dw_mipi_dsi2_bridge_post_atomic_disable()
775 /* single-dsi, so no other instance to consider */ in dw_mipi_dsi2_get_lanes()
776 return dsi2->lanes; in dw_mipi_dsi2_get_lanes()
782 const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops; in dw_mipi_dsi2_mode_set()
783 void *priv_data = dsi2->plat_data->priv_data; in dw_mipi_dsi2_mode_set()
787 clk_prepare_enable(dsi2->pclk); in dw_mipi_dsi2_mode_set()
788 clk_prepare_enable(dsi2->sys_clk); in dw_mipi_dsi2_mode_set()
790 ret = phy_ops->get_lane_mbps(priv_data, adjusted_mode, dsi2->mode_flags, in dw_mipi_dsi2_mode_set()
791 lanes, dsi2->format, &dsi2->lane_mbps); in dw_mipi_dsi2_mode_set()
795 pm_runtime_get_sync(dsi2->dev); in dw_mipi_dsi2_mode_set()
798 regmap_write(dsi2->regmap, DSI2_PWR_UP, RESET); in dw_mipi_dsi2_mode_set()
803 if (phy_ops->power_on) in dw_mipi_dsi2_mode_set()
804 phy_ops->power_on(dsi2->plat_data->priv_data); in dw_mipi_dsi2_mode_set()
813 regmap_update_bits(dsi2->regmap, DSI2_PHY_CLK_CFG, CLK_TYPE_MASK, in dw_mipi_dsi2_mode_set()
814 dsi2->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS ? NON_CONTINUOUS_CLK : in dw_mipi_dsi2_mode_set()
817 regmap_write(dsi2->regmap, DSI2_PWR_UP, POWER_UP); in dw_mipi_dsi2_mode_set()
828 /* Power up the dsi ctl into a command mode */ in dw_mipi_dsi2_bridge_atomic_pre_enable()
829 dw_mipi_dsi2_mode_set(dsi2, &dsi2->mode); in dw_mipi_dsi2_bridge_atomic_pre_enable()
839 drm_mode_copy(&dsi2->mode, adjusted_mode); in dw_mipi_dsi2_bridge_mode_set()
847 /* Switch to video mode for panel-bridge enable & panel enable */ in dw_mipi_dsi2_bridge_atomic_enable()
848 if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO) in dw_mipi_dsi2_bridge_atomic_enable()
860 const struct dw_mipi_dsi2_plat_data *pdata = dsi2->plat_data; in dw_mipi_dsi2_bridge_mode_valid()
863 if (pdata->mode_valid) in dw_mipi_dsi2_bridge_mode_valid()
864 mode_status = pdata->mode_valid(pdata->priv_data, mode, in dw_mipi_dsi2_bridge_mode_valid()
865 dsi2->mode_flags, in dw_mipi_dsi2_bridge_mode_valid()
867 dsi2->format); in dw_mipi_dsi2_bridge_mode_valid()
878 bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI; in dw_mipi_dsi2_bridge_attach()
880 /* Attach the panel-bridge to the dsi bridge */ in dw_mipi_dsi2_bridge_attach()
881 return drm_bridge_attach(bridge->encoder, dsi2->panel_bridge, bridge, in dw_mipi_dsi2_bridge_attach()
900 .name = "dsi2-host",
911 struct device *dev = &pdev->dev; in __dw_mipi_dsi2_probe()
918 return ERR_PTR(-ENOMEM); in __dw_mipi_dsi2_probe()
920 dsi2->dev = dev; in __dw_mipi_dsi2_probe()
921 dsi2->plat_data = plat_data; in __dw_mipi_dsi2_probe()
923 if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps || in __dw_mipi_dsi2_probe()
924 !plat_data->phy_ops->get_timing) in __dw_mipi_dsi2_probe()
925 return dev_err_ptr_probe(dev, -ENODEV, "Phy not properly configured\n"); in __dw_mipi_dsi2_probe()
927 if (!plat_data->regmap) { in __dw_mipi_dsi2_probe()
933 dsi2->regmap = devm_regmap_init_mmio(dev, base, in __dw_mipi_dsi2_probe()
935 if (IS_ERR(dsi2->regmap)) in __dw_mipi_dsi2_probe()
936 return dev_err_cast_probe(dev, dsi2->regmap, "failed to init regmap\n"); in __dw_mipi_dsi2_probe()
938 dsi2->regmap = plat_data->regmap; in __dw_mipi_dsi2_probe()
941 dsi2->pclk = devm_clk_get(dev, "pclk"); in __dw_mipi_dsi2_probe()
942 if (IS_ERR(dsi2->pclk)) in __dw_mipi_dsi2_probe()
943 return dev_err_cast_probe(dev, dsi2->pclk, "Unable to get pclk\n"); in __dw_mipi_dsi2_probe()
945 dsi2->sys_clk = devm_clk_get(dev, "sys"); in __dw_mipi_dsi2_probe()
946 if (IS_ERR(dsi2->sys_clk)) in __dw_mipi_dsi2_probe()
947 return dev_err_cast_probe(dev, dsi2->sys_clk, "Unable to get sys_clk\n"); in __dw_mipi_dsi2_probe()
958 ret = clk_prepare_enable(dsi2->pclk); in __dw_mipi_dsi2_probe()
968 clk_disable_unprepare(dsi2->pclk); in __dw_mipi_dsi2_probe()
973 dsi2->dsi_host.ops = &dw_mipi_dsi2_host_ops; in __dw_mipi_dsi2_probe()
974 dsi2->dsi_host.dev = dev; in __dw_mipi_dsi2_probe()
975 ret = mipi_dsi_host_register(&dsi2->dsi_host); in __dw_mipi_dsi2_probe()
977 dev_err(dev, "Failed to register MIPI host: %d\n", ret); in __dw_mipi_dsi2_probe()
982 dsi2->bridge.driver_private = dsi2; in __dw_mipi_dsi2_probe()
983 dsi2->bridge.funcs = &dw_mipi_dsi2_bridge_funcs; in __dw_mipi_dsi2_probe()
984 dsi2->bridge.of_node = pdev->dev.of_node; in __dw_mipi_dsi2_probe()
991 mipi_dsi_host_unregister(&dsi2->dsi_host); in __dw_mipi_dsi2_remove()
1017 return drm_bridge_attach(encoder, &dsi2->bridge, NULL, 0); in dw_mipi_dsi2_bind()
1026 MODULE_AUTHOR("Guochun Huang <hero.huang@rock-chips.com>");
1028 MODULE_DESCRIPTION("DW MIPI DSI2 host controller driver");
1030 MODULE_ALIAS("platform:dw-mipi-dsi2");