Lines Matching +full:master +full:- +full:dsi
1 // SPDX-License-Identifier: GPL-2.0+
7 * This generic Synopsys DesignWare MIPI DSI host driver is based on the
8 * Rockchip version from rockchip/dw-mipi-dsi.c with phy & bridge APIs.
17 #include <linux/media-bus-format.h>
197 #define N_LANES(n) (((n) - 1) & 0x3)
230 #define VPG_DEFS(name, dsi) \ argument
231 ((void __force *)&((*dsi).vpg_defs.name))
233 #define REGISTER(name, mask, dsi) \ argument
234 { #name, VPG_DEFS(name, dsi), mask, dsi }
240 struct dw_mipi_dsi *dsi; member
269 struct dw_mipi_dsi *master; /* dual-dsi master ptr */ member
270 struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */
277 * Check if either a link to a master or slave is present
279 static inline bool dw_mipi_is_dual_mode(struct dw_mipi_dsi *dsi) in dw_mipi_is_dual_mode() argument
281 return dsi->slave || dsi->master; in dw_mipi_is_dual_mode()
307 static inline void dsi_write(struct dw_mipi_dsi *dsi, u32 reg, u32 val) in dsi_write() argument
309 writel(val, dsi->base + reg); in dsi_write()
312 static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg) in dsi_read() argument
314 return readl(dsi->base + reg); in dsi_read()
320 struct dw_mipi_dsi *dsi = host_to_dsi(host); in dw_mipi_dsi_host_attach() local
321 const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; in dw_mipi_dsi_host_attach()
325 if (device->lanes > dsi->plat_data->max_data_lanes) { in dw_mipi_dsi_host_attach()
326 dev_err(dsi->dev, "the number of data lanes(%u) is too many\n", in dw_mipi_dsi_host_attach()
327 device->lanes); in dw_mipi_dsi_host_attach()
328 return -EINVAL; in dw_mipi_dsi_host_attach()
331 dsi->lanes = device->lanes; in dw_mipi_dsi_host_attach()
332 dsi->channel = device->channel; in dw_mipi_dsi_host_attach()
333 dsi->format = device->format; in dw_mipi_dsi_host_attach()
334 dsi->mode_flags = device->mode_flags; in dw_mipi_dsi_host_attach()
336 bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, 1, 0); in dw_mipi_dsi_host_attach()
340 bridge->pre_enable_prev_first = true; in dw_mipi_dsi_host_attach()
341 dsi->panel_bridge = bridge; in dw_mipi_dsi_host_attach()
343 drm_bridge_add(&dsi->bridge); in dw_mipi_dsi_host_attach()
345 if (pdata->host_ops && pdata->host_ops->attach) { in dw_mipi_dsi_host_attach()
346 ret = pdata->host_ops->attach(pdata->priv_data, device); in dw_mipi_dsi_host_attach()
357 struct dw_mipi_dsi *dsi = host_to_dsi(host); in dw_mipi_dsi_host_detach() local
358 const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; in dw_mipi_dsi_host_detach()
361 if (pdata->host_ops && pdata->host_ops->detach) { in dw_mipi_dsi_host_detach()
362 ret = pdata->host_ops->detach(pdata->priv_data, device); in dw_mipi_dsi_host_detach()
367 drm_of_panel_bridge_remove(host->dev->of_node, 1, 0); in dw_mipi_dsi_host_detach()
369 drm_bridge_remove(&dsi->bridge); in dw_mipi_dsi_host_detach()
374 static void dw_mipi_message_config(struct dw_mipi_dsi *dsi, in dw_mipi_message_config() argument
377 bool lpm = msg->flags & MIPI_DSI_MSG_USE_LPM; in dw_mipi_message_config()
386 dsi_write(dsi, DSI_DPI_LP_CMD_TIM, OUTVACT_LPCMD_TIME(16) in dw_mipi_message_config()
389 if (msg->flags & MIPI_DSI_MSG_REQ_ACK) in dw_mipi_message_config()
394 dsi_write(dsi, DSI_CMD_MODE_CFG, val); in dw_mipi_message_config()
396 val = dsi_read(dsi, DSI_VID_MODE_CFG); in dw_mipi_message_config()
401 dsi_write(dsi, DSI_VID_MODE_CFG, val); in dw_mipi_message_config()
404 static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) in dw_mipi_dsi_gen_pkt_hdr_write() argument
409 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, in dw_mipi_dsi_gen_pkt_hdr_write()
413 dev_err(dsi->dev, "failed to get available command FIFO\n"); in dw_mipi_dsi_gen_pkt_hdr_write()
417 dsi_write(dsi, DSI_GEN_HDR, hdr_val); in dw_mipi_dsi_gen_pkt_hdr_write()
420 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, in dw_mipi_dsi_gen_pkt_hdr_write()
424 dev_err(dsi->dev, "failed to write command FIFO\n"); in dw_mipi_dsi_gen_pkt_hdr_write()
431 static int dw_mipi_dsi_write(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_write() argument
434 const u8 *tx_buf = packet->payload; in dw_mipi_dsi_write()
435 int len = packet->payload_length, pld_data_bytes = sizeof(u32), ret; in dw_mipi_dsi_write()
443 dsi_write(dsi, DSI_GEN_PLD_DATA, le32_to_cpu(word)); in dw_mipi_dsi_write()
447 dsi_write(dsi, DSI_GEN_PLD_DATA, le32_to_cpu(word)); in dw_mipi_dsi_write()
449 len -= pld_data_bytes; in dw_mipi_dsi_write()
452 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, in dw_mipi_dsi_write()
456 dev_err(dsi->dev, in dw_mipi_dsi_write()
463 memcpy(&word, packet->header, sizeof(packet->header)); in dw_mipi_dsi_write()
464 return dw_mipi_dsi_gen_pkt_hdr_write(dsi, le32_to_cpu(word)); in dw_mipi_dsi_write()
467 static int dw_mipi_dsi_read(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_read() argument
470 int i, j, ret, len = msg->rx_len; in dw_mipi_dsi_read()
471 u8 *buf = msg->rx_buf; in dw_mipi_dsi_read()
475 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, in dw_mipi_dsi_read()
479 dev_err(dsi->dev, "Timeout during read operation\n"); in dw_mipi_dsi_read()
485 ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, in dw_mipi_dsi_read()
489 dev_err(dsi->dev, "Read payload FIFO is empty\n"); in dw_mipi_dsi_read()
493 val = dsi_read(dsi, DSI_GEN_PLD_DATA); in dw_mipi_dsi_read()
504 struct dw_mipi_dsi *dsi = host_to_dsi(host); in dw_mipi_dsi_host_transfer() local
510 dev_err(dsi->dev, "failed to create packet: %d\n", ret); in dw_mipi_dsi_host_transfer()
514 dw_mipi_message_config(dsi, msg); in dw_mipi_dsi_host_transfer()
515 if (dsi->slave) in dw_mipi_dsi_host_transfer()
516 dw_mipi_message_config(dsi->slave, msg); in dw_mipi_dsi_host_transfer()
518 ret = dw_mipi_dsi_write(dsi, &packet); in dw_mipi_dsi_host_transfer()
521 if (dsi->slave) { in dw_mipi_dsi_host_transfer()
522 ret = dw_mipi_dsi_write(dsi->slave, &packet); in dw_mipi_dsi_host_transfer()
527 if (msg->rx_buf && msg->rx_len) { in dw_mipi_dsi_host_transfer()
528 ret = dw_mipi_dsi_read(dsi, msg); in dw_mipi_dsi_host_transfer()
531 nb_bytes = msg->rx_len; in dw_mipi_dsi_host_transfer()
553 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_atomic_get_input_bus_fmts() local
554 const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; in dw_mipi_dsi_bridge_atomic_get_input_bus_fmts()
557 if (pdata->get_input_bus_fmts) in dw_mipi_dsi_bridge_atomic_get_input_bus_fmts()
558 return pdata->get_input_bus_fmts(pdata->priv_data, in dw_mipi_dsi_bridge_atomic_get_input_bus_fmts()
578 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_atomic_check() local
579 const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; in dw_mipi_dsi_bridge_atomic_check()
582 bridge_state->input_bus_cfg.flags = in dw_mipi_dsi_bridge_atomic_check()
585 if (pdata->mode_fixup) { in dw_mipi_dsi_bridge_atomic_check()
586 ret = pdata->mode_fixup(pdata->priv_data, &crtc_state->mode, in dw_mipi_dsi_bridge_atomic_check()
587 &crtc_state->adjusted_mode); in dw_mipi_dsi_bridge_atomic_check()
590 DRM_MODE_ARG(&crtc_state->mode)); in dw_mipi_dsi_bridge_atomic_check()
591 return -EINVAL; in dw_mipi_dsi_bridge_atomic_check()
598 static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_video_mode_config() argument
604 * enabling low power is panel-dependent, we should use the in dw_mipi_dsi_video_mode_config()
609 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) in dw_mipi_dsi_video_mode_config()
611 else if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) in dw_mipi_dsi_video_mode_config()
617 if (dsi->vpg_defs.vpg) { in dw_mipi_dsi_video_mode_config()
619 val |= dsi->vpg_defs.vpg_horizontal ? in dw_mipi_dsi_video_mode_config()
621 val |= dsi->vpg_defs.vpg_ber_pattern ? VID_MODE_VPG_MODE : 0; in dw_mipi_dsi_video_mode_config()
625 dsi_write(dsi, DSI_VID_MODE_CFG, val); in dw_mipi_dsi_video_mode_config()
628 static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_set_mode() argument
633 dsi_write(dsi, DSI_PWR_UP, RESET); in dw_mipi_dsi_set_mode()
636 dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE); in dw_mipi_dsi_set_mode()
637 dw_mipi_dsi_video_mode_config(dsi); in dw_mipi_dsi_set_mode()
639 dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); in dw_mipi_dsi_set_mode()
643 if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) in dw_mipi_dsi_set_mode()
645 dsi_write(dsi, DSI_LPCLK_CTRL, val); in dw_mipi_dsi_set_mode()
647 dsi_write(dsi, DSI_PWR_UP, POWERUP); in dw_mipi_dsi_set_mode()
650 static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_disable() argument
652 dsi_write(dsi, DSI_PWR_UP, RESET); in dw_mipi_dsi_disable()
653 dsi_write(dsi, DSI_PHY_RSTZ, PHY_RSTZ); in dw_mipi_dsi_disable()
656 static void dw_mipi_dsi_init(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_init() argument
658 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; in dw_mipi_dsi_init()
667 if (phy_ops->get_esc_clk_rate) { in dw_mipi_dsi_init()
668 ret = phy_ops->get_esc_clk_rate(dsi->plat_data->priv_data, in dw_mipi_dsi_init()
681 esc_clk_division = (dsi->lane_mbps >> 3) / esc_rate + 1; in dw_mipi_dsi_init()
683 dsi_write(dsi, DSI_PWR_UP, RESET); in dw_mipi_dsi_init()
690 dsi_write(dsi, DSI_CLKMGR_CFG, TO_CLK_DIVISION(0) | in dw_mipi_dsi_init()
694 static void dw_mipi_dsi_dpi_config(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_dpi_config() argument
699 switch (dsi->format) { in dw_mipi_dsi_dpi_config()
714 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in dw_mipi_dsi_dpi_config()
716 if (mode->flags & DRM_MODE_FLAG_NHSYNC) in dw_mipi_dsi_dpi_config()
719 dsi_write(dsi, DSI_DPI_VCID, DPI_VCID(dsi->channel)); in dw_mipi_dsi_dpi_config()
720 dsi_write(dsi, DSI_DPI_COLOR_CODING, color); in dw_mipi_dsi_dpi_config()
721 dsi_write(dsi, DSI_DPI_CFG_POL, val); in dw_mipi_dsi_dpi_config()
724 static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_packet_handler_config() argument
728 if (dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET) in dw_mipi_dsi_packet_handler_config()
731 dsi_write(dsi, DSI_PCKHDL_CFG, val); in dw_mipi_dsi_packet_handler_config()
734 static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_video_packet_config() argument
739 * only burst mode is supported here. For non-burst video modes, in dw_mipi_dsi_video_packet_config()
742 * non-burst video modes, see dw_mipi_dsi_video_mode_config()... in dw_mipi_dsi_video_packet_config()
745 dsi_write(dsi, DSI_VID_PKT_SIZE, in dw_mipi_dsi_video_packet_config()
746 dw_mipi_is_dual_mode(dsi) ? in dw_mipi_dsi_video_packet_config()
747 VID_PKT_SIZE(mode->hdisplay / 2) : in dw_mipi_dsi_video_packet_config()
748 VID_PKT_SIZE(mode->hdisplay)); in dw_mipi_dsi_video_packet_config()
751 static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_command_mode_config() argument
758 dsi_write(dsi, DSI_TO_CNT_CFG, HSTX_TO_CNT(0) | LPRX_TO_CNT(0)); in dw_mipi_dsi_command_mode_config()
761 * the Bus-Turn-Around Timeout Counter should be computed in dw_mipi_dsi_command_mode_config()
764 dsi_write(dsi, DSI_BTA_TO_CNT, 0xd00); in dw_mipi_dsi_command_mode_config()
765 dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE); in dw_mipi_dsi_command_mode_config()
770 static inline u32 dw_mipi_dsi_get_minimum_lbcc(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_get_minimum_lbcc() argument
772 return minimum_lbccs[dsi->lanes - 1]; in dw_mipi_dsi_get_minimum_lbcc()
776 static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_get_hcomponent_lbcc() argument
783 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) { in dw_mipi_dsi_get_hcomponent_lbcc()
785 lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8; in dw_mipi_dsi_get_hcomponent_lbcc()
788 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); in dw_mipi_dsi_get_hcomponent_lbcc()
790 dev_err(dsi->dev, "failed to get bpp\n"); in dw_mipi_dsi_get_hcomponent_lbcc()
794 lbcc = div_u64((u64)hcomponent * mode->clock * bpp, dsi->lanes * 8); in dw_mipi_dsi_get_hcomponent_lbcc()
797 frac = lbcc % mode->clock; in dw_mipi_dsi_get_hcomponent_lbcc()
798 lbcc = lbcc / mode->clock; in dw_mipi_dsi_get_hcomponent_lbcc()
802 minimum_lbcc = dw_mipi_dsi_get_minimum_lbcc(dsi); in dw_mipi_dsi_get_hcomponent_lbcc()
810 static void dw_mipi_dsi_line_timer_config(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_line_timer_config() argument
815 htotal = mode->htotal; in dw_mipi_dsi_line_timer_config()
816 hsa = mode->hsync_end - mode->hsync_start; in dw_mipi_dsi_line_timer_config()
817 hbp = mode->htotal - mode->hsync_end; in dw_mipi_dsi_line_timer_config()
823 lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, htotal); in dw_mipi_dsi_line_timer_config()
824 dsi_write(dsi, DSI_VID_HLINE_TIME, lbcc); in dw_mipi_dsi_line_timer_config()
826 lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hsa); in dw_mipi_dsi_line_timer_config()
827 dsi_write(dsi, DSI_VID_HSA_TIME, lbcc); in dw_mipi_dsi_line_timer_config()
829 lbcc = dw_mipi_dsi_get_hcomponent_lbcc(dsi, mode, hbp); in dw_mipi_dsi_line_timer_config()
830 dsi_write(dsi, DSI_VID_HBP_TIME, lbcc); in dw_mipi_dsi_line_timer_config()
833 static void dw_mipi_dsi_vertical_timing_config(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_vertical_timing_config() argument
838 vactive = mode->vdisplay; in dw_mipi_dsi_vertical_timing_config()
839 vsa = mode->vsync_end - mode->vsync_start; in dw_mipi_dsi_vertical_timing_config()
840 vfp = mode->vsync_start - mode->vdisplay; in dw_mipi_dsi_vertical_timing_config()
841 vbp = mode->vtotal - mode->vsync_end; in dw_mipi_dsi_vertical_timing_config()
843 dsi_write(dsi, DSI_VID_VACTIVE_LINES, vactive); in dw_mipi_dsi_vertical_timing_config()
844 dsi_write(dsi, DSI_VID_VSA_LINES, vsa); in dw_mipi_dsi_vertical_timing_config()
845 dsi_write(dsi, DSI_VID_VFP_LINES, vfp); in dw_mipi_dsi_vertical_timing_config()
846 dsi_write(dsi, DSI_VID_VBP_LINES, vbp); in dw_mipi_dsi_vertical_timing_config()
849 static void dw_mipi_dsi_dphy_timing_config(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_dphy_timing_config() argument
851 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; in dw_mipi_dsi_dphy_timing_config()
856 ret = phy_ops->get_timing(dsi->plat_data->priv_data, in dw_mipi_dsi_dphy_timing_config()
857 dsi->lane_mbps, &timing); in dw_mipi_dsi_dphy_timing_config()
859 DRM_DEV_ERROR(dsi->dev, "Retrieving phy timings failed\n"); in dw_mipi_dsi_dphy_timing_config()
869 hw_version = dsi_read(dsi, DSI_VERSION) & VERSION; in dw_mipi_dsi_dphy_timing_config()
872 dsi_write(dsi, DSI_PHY_TMR_CFG, in dw_mipi_dsi_dphy_timing_config()
875 dsi_write(dsi, DSI_PHY_TMR_RD_CFG, MAX_RD_TIME_V131(10000)); in dw_mipi_dsi_dphy_timing_config()
877 dsi_write(dsi, DSI_PHY_TMR_CFG, in dw_mipi_dsi_dphy_timing_config()
883 dsi_write(dsi, DSI_PHY_TMR_LPCLK_CFG, in dw_mipi_dsi_dphy_timing_config()
888 static void dw_mipi_dsi_dphy_interface_config(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_dphy_interface_config() argument
892 * stop wait time should be the maximum between host dsi in dw_mipi_dsi_dphy_interface_config()
895 dsi_write(dsi, DSI_PHY_IF_CFG, PHY_STOP_WAIT_TIME(0x20) | in dw_mipi_dsi_dphy_interface_config()
896 N_LANES(dsi->lanes)); in dw_mipi_dsi_dphy_interface_config()
899 static void dw_mipi_dsi_dphy_init(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_dphy_init() argument
902 dsi_write(dsi, DSI_PHY_RSTZ, PHY_DISFORCEPLL | PHY_DISABLECLK in dw_mipi_dsi_dphy_init()
904 dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); in dw_mipi_dsi_dphy_init()
905 dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLR); in dw_mipi_dsi_dphy_init()
906 dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLR); in dw_mipi_dsi_dphy_init()
909 static void dw_mipi_dsi_dphy_enable(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_dphy_enable() argument
914 dsi_write(dsi, DSI_PHY_RSTZ, PHY_ENFORCEPLL | PHY_ENABLECLK | in dw_mipi_dsi_dphy_enable()
917 ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, in dw_mipi_dsi_dphy_enable()
922 ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, in dw_mipi_dsi_dphy_enable()
929 static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_clear_err() argument
931 dsi_read(dsi, DSI_INT_ST0); in dw_mipi_dsi_clear_err()
932 dsi_read(dsi, DSI_INT_ST1); in dw_mipi_dsi_clear_err()
933 dsi_write(dsi, DSI_INT_MSK0, 0); in dw_mipi_dsi_clear_err()
934 dsi_write(dsi, DSI_INT_MSK1, 0); in dw_mipi_dsi_clear_err()
940 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_post_atomic_disable() local
941 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; in dw_mipi_dsi_bridge_post_atomic_disable()
944 * Switch to command mode before panel-bridge post_disable & in dw_mipi_dsi_bridge_post_atomic_disable()
946 * Note: panel-bridge disable & panel disable has been called in dw_mipi_dsi_bridge_post_atomic_disable()
949 dw_mipi_dsi_set_mode(dsi, 0); in dw_mipi_dsi_bridge_post_atomic_disable()
951 if (phy_ops->power_off) in dw_mipi_dsi_bridge_post_atomic_disable()
952 phy_ops->power_off(dsi->plat_data->priv_data); in dw_mipi_dsi_bridge_post_atomic_disable()
954 if (dsi->slave) { in dw_mipi_dsi_bridge_post_atomic_disable()
955 dw_mipi_dsi_disable(dsi->slave); in dw_mipi_dsi_bridge_post_atomic_disable()
956 clk_disable_unprepare(dsi->slave->pclk); in dw_mipi_dsi_bridge_post_atomic_disable()
957 pm_runtime_put(dsi->slave->dev); in dw_mipi_dsi_bridge_post_atomic_disable()
959 dw_mipi_dsi_disable(dsi); in dw_mipi_dsi_bridge_post_atomic_disable()
961 clk_disable_unprepare(dsi->pclk); in dw_mipi_dsi_bridge_post_atomic_disable()
962 pm_runtime_put(dsi->dev); in dw_mipi_dsi_bridge_post_atomic_disable()
965 static unsigned int dw_mipi_dsi_get_lanes(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_get_lanes() argument
967 /* this instance is the slave, so add the master's lanes */ in dw_mipi_dsi_get_lanes()
968 if (dsi->master) in dw_mipi_dsi_get_lanes()
969 return dsi->master->lanes + dsi->lanes; in dw_mipi_dsi_get_lanes()
971 /* this instance is the master, so add the slave's lanes */ in dw_mipi_dsi_get_lanes()
972 if (dsi->slave) in dw_mipi_dsi_get_lanes()
973 return dsi->lanes + dsi->slave->lanes; in dw_mipi_dsi_get_lanes()
975 /* single-dsi, so no other instance to consider */ in dw_mipi_dsi_get_lanes()
976 return dsi->lanes; in dw_mipi_dsi_get_lanes()
979 static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi, in dw_mipi_dsi_mode_set() argument
982 const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops; in dw_mipi_dsi_mode_set()
983 void *priv_data = dsi->plat_data->priv_data; in dw_mipi_dsi_mode_set()
985 u32 lanes = dw_mipi_dsi_get_lanes(dsi); in dw_mipi_dsi_mode_set()
987 clk_prepare_enable(dsi->pclk); in dw_mipi_dsi_mode_set()
989 ret = phy_ops->get_lane_mbps(priv_data, adjusted_mode, dsi->mode_flags, in dw_mipi_dsi_mode_set()
990 lanes, dsi->format, &dsi->lane_mbps); in dw_mipi_dsi_mode_set()
994 pm_runtime_get_sync(dsi->dev); in dw_mipi_dsi_mode_set()
995 dw_mipi_dsi_init(dsi); in dw_mipi_dsi_mode_set()
996 dw_mipi_dsi_dpi_config(dsi, adjusted_mode); in dw_mipi_dsi_mode_set()
997 dw_mipi_dsi_packet_handler_config(dsi); in dw_mipi_dsi_mode_set()
998 dw_mipi_dsi_video_mode_config(dsi); in dw_mipi_dsi_mode_set()
999 dw_mipi_dsi_video_packet_config(dsi, adjusted_mode); in dw_mipi_dsi_mode_set()
1000 dw_mipi_dsi_command_mode_config(dsi); in dw_mipi_dsi_mode_set()
1001 dw_mipi_dsi_line_timer_config(dsi, adjusted_mode); in dw_mipi_dsi_mode_set()
1002 dw_mipi_dsi_vertical_timing_config(dsi, adjusted_mode); in dw_mipi_dsi_mode_set()
1004 dw_mipi_dsi_dphy_init(dsi); in dw_mipi_dsi_mode_set()
1005 dw_mipi_dsi_dphy_timing_config(dsi); in dw_mipi_dsi_mode_set()
1006 dw_mipi_dsi_dphy_interface_config(dsi); in dw_mipi_dsi_mode_set()
1008 dw_mipi_dsi_clear_err(dsi); in dw_mipi_dsi_mode_set()
1010 ret = phy_ops->init(priv_data); in dw_mipi_dsi_mode_set()
1014 dw_mipi_dsi_dphy_enable(dsi); in dw_mipi_dsi_mode_set()
1018 /* Switch to cmd mode for panel-bridge pre_enable & panel prepare */ in dw_mipi_dsi_mode_set()
1019 dw_mipi_dsi_set_mode(dsi, 0); in dw_mipi_dsi_mode_set()
1021 if (phy_ops->power_on) in dw_mipi_dsi_mode_set()
1022 phy_ops->power_on(dsi->plat_data->priv_data); in dw_mipi_dsi_mode_set()
1028 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_atomic_pre_enable() local
1030 /* Power up the dsi ctl into a command mode */ in dw_mipi_dsi_bridge_atomic_pre_enable()
1031 dw_mipi_dsi_mode_set(dsi, &dsi->mode); in dw_mipi_dsi_bridge_atomic_pre_enable()
1032 if (dsi->slave) in dw_mipi_dsi_bridge_atomic_pre_enable()
1033 dw_mipi_dsi_mode_set(dsi->slave, &dsi->mode); in dw_mipi_dsi_bridge_atomic_pre_enable()
1040 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_mode_set() local
1043 drm_mode_copy(&dsi->mode, adjusted_mode); in dw_mipi_dsi_bridge_mode_set()
1049 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_atomic_enable() local
1051 /* Switch to video mode for panel-bridge enable & panel enable */ in dw_mipi_dsi_bridge_atomic_enable()
1052 dw_mipi_dsi_set_mode(dsi, MIPI_DSI_MODE_VIDEO); in dw_mipi_dsi_bridge_atomic_enable()
1053 if (dsi->slave) in dw_mipi_dsi_bridge_atomic_enable()
1054 dw_mipi_dsi_set_mode(dsi->slave, MIPI_DSI_MODE_VIDEO); in dw_mipi_dsi_bridge_atomic_enable()
1062 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_mode_valid() local
1063 const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data; in dw_mipi_dsi_bridge_mode_valid()
1066 if (pdata->mode_valid) in dw_mipi_dsi_bridge_mode_valid()
1067 mode_status = pdata->mode_valid(pdata->priv_data, mode, in dw_mipi_dsi_bridge_mode_valid()
1068 dsi->mode_flags, in dw_mipi_dsi_bridge_mode_valid()
1069 dw_mipi_dsi_get_lanes(dsi), in dw_mipi_dsi_bridge_mode_valid()
1070 dsi->format); in dw_mipi_dsi_bridge_mode_valid()
1079 struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge); in dw_mipi_dsi_bridge_attach() local
1082 encoder->encoder_type = DRM_MODE_ENCODER_DSI; in dw_mipi_dsi_bridge_attach()
1084 /* Attach the panel-bridge to the dsi bridge */ in dw_mipi_dsi_bridge_attach()
1085 return drm_bridge_attach(encoder, dsi->panel_bridge, bridge, in dw_mipi_dsi_bridge_attach()
1108 struct dw_mipi_dsi *dsi; in dw_mipi_dsi_debugfs_write() local
1112 return -ENODEV; in dw_mipi_dsi_debugfs_write()
1114 dsi = vpg->dsi; in dw_mipi_dsi_debugfs_write()
1116 *vpg->reg = (bool)val; in dw_mipi_dsi_debugfs_write()
1118 mode_cfg = dsi_read(dsi, DSI_VID_MODE_CFG); in dw_mipi_dsi_debugfs_write()
1120 if (*vpg->reg) in dw_mipi_dsi_debugfs_write()
1121 mode_cfg |= vpg->mask; in dw_mipi_dsi_debugfs_write()
1123 mode_cfg &= ~vpg->mask; in dw_mipi_dsi_debugfs_write()
1125 dsi_write(dsi, DSI_VID_MODE_CFG, mode_cfg); in dw_mipi_dsi_debugfs_write()
1135 return -ENODEV; in dw_mipi_dsi_debugfs_show()
1137 *val = *vpg->reg; in dw_mipi_dsi_debugfs_show()
1147 struct dw_mipi_dsi *dsi = data; in debugfs_create_files() local
1149 REGISTER(vpg, VID_MODE_VPG_ENABLE, dsi), in debugfs_create_files()
1150 REGISTER(vpg_horizontal, VID_MODE_VPG_HORIZONTAL, dsi), in debugfs_create_files()
1151 REGISTER(vpg_ber_pattern, VID_MODE_VPG_MODE, dsi), in debugfs_create_files()
1155 dsi->debugfs_vpg = kmemdup(debugfs, sizeof(debugfs), GFP_KERNEL); in debugfs_create_files()
1156 if (!dsi->debugfs_vpg) in debugfs_create_files()
1160 debugfs_create_file(dsi->debugfs_vpg[i].name, 0644, in debugfs_create_files()
1161 dsi->debugfs, &dsi->debugfs_vpg[i], in debugfs_create_files()
1165 static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_debugfs_init() argument
1167 dsi->debugfs = debugfs_create_dir(dev_name(dsi->dev), NULL); in dw_mipi_dsi_debugfs_init()
1168 if (IS_ERR(dsi->debugfs)) { in dw_mipi_dsi_debugfs_init()
1169 dev_err(dsi->dev, "failed to create debugfs root\n"); in dw_mipi_dsi_debugfs_init()
1173 debugfs_create_files(dsi); in dw_mipi_dsi_debugfs_init()
1176 static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_debugfs_remove() argument
1178 debugfs_remove_recursive(dsi->debugfs); in dw_mipi_dsi_debugfs_remove()
1179 kfree(dsi->debugfs_vpg); in dw_mipi_dsi_debugfs_remove()
1184 static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) { } in dw_mipi_dsi_debugfs_init() argument
1185 static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { } in dw_mipi_dsi_debugfs_remove() argument
1193 struct device *dev = &pdev->dev; in __dw_mipi_dsi_probe()
1195 struct dw_mipi_dsi *dsi; in __dw_mipi_dsi_probe() local
1198 dsi = devm_drm_bridge_alloc(dev, struct dw_mipi_dsi, bridge, in __dw_mipi_dsi_probe()
1200 if (IS_ERR(dsi)) in __dw_mipi_dsi_probe()
1201 return ERR_CAST(dsi); in __dw_mipi_dsi_probe()
1203 dsi->dev = dev; in __dw_mipi_dsi_probe()
1204 dsi->plat_data = plat_data; in __dw_mipi_dsi_probe()
1206 if (!plat_data->phy_ops->init || !plat_data->phy_ops->get_lane_mbps || in __dw_mipi_dsi_probe()
1207 !plat_data->phy_ops->get_timing) { in __dw_mipi_dsi_probe()
1209 return ERR_PTR(-ENODEV); in __dw_mipi_dsi_probe()
1212 if (!plat_data->base) { in __dw_mipi_dsi_probe()
1213 dsi->base = devm_platform_ioremap_resource(pdev, 0); in __dw_mipi_dsi_probe()
1214 if (IS_ERR(dsi->base)) in __dw_mipi_dsi_probe()
1215 return ERR_PTR(-ENODEV); in __dw_mipi_dsi_probe()
1218 dsi->base = plat_data->base; in __dw_mipi_dsi_probe()
1221 dsi->pclk = devm_clk_get(dev, "pclk"); in __dw_mipi_dsi_probe()
1222 if (IS_ERR(dsi->pclk)) { in __dw_mipi_dsi_probe()
1223 ret = PTR_ERR(dsi->pclk); in __dw_mipi_dsi_probe()
1236 if (ret != -EPROBE_DEFER) in __dw_mipi_dsi_probe()
1243 ret = clk_prepare_enable(dsi->pclk); in __dw_mipi_dsi_probe()
1253 clk_disable_unprepare(dsi->pclk); in __dw_mipi_dsi_probe()
1256 dw_mipi_dsi_debugfs_init(dsi); in __dw_mipi_dsi_probe()
1259 dsi->dsi_host.ops = &dw_mipi_dsi_host_ops; in __dw_mipi_dsi_probe()
1260 dsi->dsi_host.dev = dev; in __dw_mipi_dsi_probe()
1261 ret = mipi_dsi_host_register(&dsi->dsi_host); in __dw_mipi_dsi_probe()
1265 dw_mipi_dsi_debugfs_remove(dsi); in __dw_mipi_dsi_probe()
1269 dsi->bridge.driver_private = dsi; in __dw_mipi_dsi_probe()
1270 dsi->bridge.of_node = pdev->dev.of_node; in __dw_mipi_dsi_probe()
1272 return dsi; in __dw_mipi_dsi_probe()
1275 static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) in __dw_mipi_dsi_remove() argument
1277 mipi_dsi_host_unregister(&dsi->dsi_host); in __dw_mipi_dsi_remove()
1279 pm_runtime_disable(dsi->dev); in __dw_mipi_dsi_remove()
1280 dw_mipi_dsi_debugfs_remove(dsi); in __dw_mipi_dsi_remove()
1283 void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave) in dw_mipi_dsi_set_slave() argument
1286 dsi->slave = slave; in dw_mipi_dsi_set_slave()
1287 dsi->slave->master = dsi; in dw_mipi_dsi_set_slave()
1290 dsi->slave->lanes = dsi->lanes; in dw_mipi_dsi_set_slave()
1291 dsi->slave->channel = dsi->channel; in dw_mipi_dsi_set_slave()
1292 dsi->slave->format = dsi->format; in dw_mipi_dsi_set_slave()
1293 dsi->slave->mode_flags = dsi->mode_flags; in dw_mipi_dsi_set_slave()
1297 struct drm_bridge *dw_mipi_dsi_get_bridge(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_get_bridge() argument
1299 return &dsi->bridge; in dw_mipi_dsi_get_bridge()
1314 void dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_remove() argument
1316 __dw_mipi_dsi_remove(dsi); in dw_mipi_dsi_remove()
1323 int dw_mipi_dsi_bind(struct dw_mipi_dsi *dsi, struct drm_encoder *encoder) in dw_mipi_dsi_bind() argument
1325 return drm_bridge_attach(encoder, &dsi->bridge, NULL, 0); in dw_mipi_dsi_bind()
1329 void dw_mipi_dsi_unbind(struct dw_mipi_dsi *dsi) in dw_mipi_dsi_unbind() argument
1334 MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
1336 MODULE_DESCRIPTION("DW MIPI DSI host controller driver");
1338 MODULE_ALIAS("platform:dw-mipi-dsi");