| .. | .. |
|---|
| 246 | 246 | struct phy *dcphy; |
|---|
| 247 | 247 | union phy_configure_opts phy_opts; |
|---|
| 248 | 248 | |
|---|
| 249 | + bool disable_hold_mode; |
|---|
| 250 | + bool auto_calc_mode; |
|---|
| 249 | 251 | bool c_option; |
|---|
| 250 | 252 | bool scrambling_en; |
|---|
| 251 | 253 | unsigned int slice_width; |
|---|
| .. | .. |
|---|
| 270 | 272 | u32 lanes; |
|---|
| 271 | 273 | u32 format; |
|---|
| 272 | 274 | unsigned long mode_flags; |
|---|
| 273 | | - |
|---|
| 275 | + u64 mipi_pixel_rate; |
|---|
| 274 | 276 | const struct dw_mipi_dsi2_plat_data *pdata; |
|---|
| 275 | 277 | struct rockchip_drm_sub_dev sub_dev; |
|---|
| 276 | 278 | |
|---|
| .. | .. |
|---|
| 609 | 611 | |
|---|
| 610 | 612 | static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) |
|---|
| 611 | 613 | { |
|---|
| 612 | | - struct drm_display_mode *mode = &dsi2->mode; |
|---|
| 613 | 614 | u64 sys_clk = clk_get_rate(dsi2->sys_clk); |
|---|
| 614 | | - u64 pixel_clk, ipi_clk, phy_hsclk; |
|---|
| 615 | + u64 ipi_clk, phy_hsclk; |
|---|
| 615 | 616 | u64 tmp; |
|---|
| 616 | 617 | |
|---|
| 617 | 618 | /* |
|---|
| .. | .. |
|---|
| 625 | 626 | phy_hsclk = DIV_ROUND_CLOSEST_ULL(dsi2->lane_hs_rate * MSEC_PER_SEC, 16); |
|---|
| 626 | 627 | |
|---|
| 627 | 628 | /* IPI_RATIO_MAN_CFG = PHY_HSTX_CLK / IPI_CLK */ |
|---|
| 628 | | - pixel_clk = mode->crtc_clock * MSEC_PER_SEC; |
|---|
| 629 | | - ipi_clk = pixel_clk / 4; |
|---|
| 629 | + ipi_clk = dsi2->mipi_pixel_rate; |
|---|
| 630 | + if (!sys_clk || !ipi_clk) |
|---|
| 631 | + return; |
|---|
| 630 | 632 | |
|---|
| 631 | 633 | tmp = DIV_ROUND_CLOSEST_ULL(phy_hsclk << 16, ipi_clk); |
|---|
| 632 | 634 | regmap_write(dsi2->regmap, DSI2_PHY_IPI_RATIO_MAN_CFG, |
|---|
| .. | .. |
|---|
| 666 | 668 | { |
|---|
| 667 | 669 | dw_mipi_dsi2_phy_mode_cfg(dsi2); |
|---|
| 668 | 670 | dw_mipi_dsi2_phy_clk_mode_cfg(dsi2); |
|---|
| 671 | + |
|---|
| 672 | + if (dsi2->auto_calc_mode) |
|---|
| 673 | + return; |
|---|
| 674 | + |
|---|
| 669 | 675 | dw_mipi_dsi2_phy_ratio_cfg(dsi2); |
|---|
| 670 | 676 | dw_mipi_dsi2_lp2hs_or_hs2lp_cfg(dsi2); |
|---|
| 671 | 677 | |
|---|
| .. | .. |
|---|
| 733 | 739 | regmap_write(dsi2->regmap, DSI2_IPI_PIX_PKT_CFG, MAX_PIX_PKT(val)); |
|---|
| 734 | 740 | |
|---|
| 735 | 741 | dw_mipi_dsi2_ipi_color_coding_cfg(dsi2); |
|---|
| 742 | + |
|---|
| 743 | + if (dsi2->auto_calc_mode) |
|---|
| 744 | + return; |
|---|
| 736 | 745 | |
|---|
| 737 | 746 | /* |
|---|
| 738 | 747 | * if the controller is intended to operate in data stream mode, |
|---|
| .. | .. |
|---|
| 807 | 816 | |
|---|
| 808 | 817 | /* there may be some timeout registers may be configured if desired */ |
|---|
| 809 | 818 | |
|---|
| 810 | | - dw_mipi_dsi2_work_mode(dsi2, MANUAL_MODE_EN); |
|---|
| 819 | + dw_mipi_dsi2_work_mode(dsi2, dsi2->auto_calc_mode ? 0 : MANUAL_MODE_EN); |
|---|
| 811 | 820 | dw_mipi_dsi2_phy_init(dsi2); |
|---|
| 812 | 821 | dw_mipi_dsi2_tx_option_set(dsi2); |
|---|
| 813 | 822 | dw_mipi_dsi2_irq_enable(dsi2, 1); |
|---|
| .. | .. |
|---|
| 830 | 839 | |
|---|
| 831 | 840 | static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2) |
|---|
| 832 | 841 | { |
|---|
| 842 | + u32 mode; |
|---|
| 843 | + int ret; |
|---|
| 844 | + |
|---|
| 833 | 845 | dw_mipi_dsi2_ipi_set(dsi2); |
|---|
| 846 | + |
|---|
| 847 | + if (dsi2->auto_calc_mode) { |
|---|
| 848 | + regmap_write(dsi2->regmap, DSI2_MODE_CTRL, AUTOCALC_MODE); |
|---|
| 849 | + ret = regmap_read_poll_timeout(dsi2->regmap, DSI2_MODE_STATUS, |
|---|
| 850 | + mode, mode == IDLE_MODE, |
|---|
| 851 | + 1000, MODE_STATUS_TIMEOUT_US); |
|---|
| 852 | + if (ret < 0) |
|---|
| 853 | + dev_err(dsi2->dev, "auto calculation training failed\n"); |
|---|
| 854 | + } |
|---|
| 834 | 855 | |
|---|
| 835 | 856 | if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO) |
|---|
| 836 | 857 | dw_mipi_dsi2_set_vid_mode(dsi2); |
|---|
| .. | .. |
|---|
| 841 | 862 | dw_mipi_dsi2_enable(dsi2->slave); |
|---|
| 842 | 863 | } |
|---|
| 843 | 864 | |
|---|
| 865 | +static void dw_mipi_dsi2_get_mipi_pixel_clk(struct dw_mipi_dsi2 *dsi2, |
|---|
| 866 | + struct rockchip_crtc_state *s) |
|---|
| 867 | +{ |
|---|
| 868 | + struct drm_display_mode *mode = &dsi2->mode; |
|---|
| 869 | + u8 k = dsi2->slave ? 2 : 1; |
|---|
| 870 | + |
|---|
| 871 | + /* 1.When MIPI works in uncompressed mode: |
|---|
| 872 | + * (Video Timing Pixel Rate)/(4)=(MIPI Pixel ClockxK)=(dclk_out×K)=dclk_core |
|---|
| 873 | + * 2.When MIPI works in compressed mode: |
|---|
| 874 | + * MIPI Pixel Clock = cds_clk / 2 |
|---|
| 875 | + * MIPI is configured as double channel display mode, K=2, otherwise K=1. |
|---|
| 876 | + */ |
|---|
| 877 | + if (dsi2->dsc_enable) { |
|---|
| 878 | + dsi2->mipi_pixel_rate = s->dsc_cds_clk_rate / 2; |
|---|
| 879 | + if (dsi2->slave) |
|---|
| 880 | + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; |
|---|
| 881 | + |
|---|
| 882 | + return; |
|---|
| 883 | + } |
|---|
| 884 | + |
|---|
| 885 | + dsi2->mipi_pixel_rate = (mode->crtc_clock * MSEC_PER_SEC) / (4 * k); |
|---|
| 886 | + if (dsi2->slave) |
|---|
| 887 | + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; |
|---|
| 888 | +} |
|---|
| 889 | + |
|---|
| 844 | 890 | static int dw_mipi_dsi2_encoder_mode_set(struct dw_mipi_dsi2 *dsi2, |
|---|
| 845 | 891 | struct drm_atomic_state *state) |
|---|
| 846 | 892 | { |
|---|
| .. | .. |
|---|
| 848 | 894 | struct drm_connector *connector; |
|---|
| 849 | 895 | struct drm_connector_state *conn_state; |
|---|
| 850 | 896 | struct drm_crtc_state *crtc_state; |
|---|
| 897 | + struct rockchip_crtc_state *vcstate; |
|---|
| 851 | 898 | const struct drm_display_mode *adjusted_mode; |
|---|
| 852 | 899 | struct drm_display_mode *mode = &dsi2->mode; |
|---|
| 853 | 900 | |
|---|
| .. | .. |
|---|
| 865 | 912 | return -ENODEV; |
|---|
| 866 | 913 | } |
|---|
| 867 | 914 | |
|---|
| 915 | + vcstate = to_rockchip_crtc_state(crtc_state); |
|---|
| 868 | 916 | adjusted_mode = &crtc_state->adjusted_mode; |
|---|
| 869 | 917 | drm_mode_copy(mode, adjusted_mode); |
|---|
| 870 | 918 | |
|---|
| .. | .. |
|---|
| 873 | 921 | |
|---|
| 874 | 922 | if (dsi2->slave) |
|---|
| 875 | 923 | drm_mode_copy(&dsi2->slave->mode, mode); |
|---|
| 924 | + |
|---|
| 925 | + dw_mipi_dsi2_get_mipi_pixel_clk(dsi2, vcstate); |
|---|
| 876 | 926 | |
|---|
| 877 | 927 | return 0; |
|---|
| 878 | 928 | } |
|---|
| .. | .. |
|---|
| 954 | 1004 | if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO)) { |
|---|
| 955 | 1005 | s->output_flags |= ROCKCHIP_OUTPUT_MIPI_DS_MODE; |
|---|
| 956 | 1006 | s->soft_te = dsi2->te_gpio ? true : false; |
|---|
| 957 | | - s->hold_mode = true; |
|---|
| 1007 | + s->hold_mode = dsi2->disable_hold_mode ? false : true; |
|---|
| 958 | 1008 | } |
|---|
| 959 | 1009 | |
|---|
| 960 | 1010 | if (dsi2->slave) { |
|---|
| .. | .. |
|---|
| 1164 | 1214 | dsi2->slave->master = dsi2; |
|---|
| 1165 | 1215 | dsi2->lanes /= 2; |
|---|
| 1166 | 1216 | |
|---|
| 1217 | + dsi2->slave->auto_calc_mode = dsi2->auto_calc_mode; |
|---|
| 1167 | 1218 | dsi2->slave->lanes = dsi2->lanes; |
|---|
| 1168 | 1219 | dsi2->slave->channel = dsi2->channel; |
|---|
| 1169 | 1220 | dsi2->slave->format = dsi2->format; |
|---|
| .. | .. |
|---|
| 1639 | 1690 | dsi2->pdata = of_device_get_match_data(dev); |
|---|
| 1640 | 1691 | platform_set_drvdata(pdev, dsi2); |
|---|
| 1641 | 1692 | |
|---|
| 1693 | + if (device_property_read_bool(dev, "auto-calculation-mode")) |
|---|
| 1694 | + dsi2->auto_calc_mode = true; |
|---|
| 1695 | + |
|---|
| 1696 | + if (device_property_read_bool(dev, "disable-hold-mode")) |
|---|
| 1697 | + dsi2->disable_hold_mode = true; |
|---|
| 1698 | + |
|---|
| 1642 | 1699 | if (device_property_read_bool(dev, "dual-connector-split")) { |
|---|
| 1643 | 1700 | dsi2->dual_connector_split = true; |
|---|
| 1644 | 1701 | |
|---|