2 * Copyright © 2018 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Madhav Chauhan <madhav.chauhan@intel.com>
25 * Jani Nikula <jani.nikula@intel.com>
28 #include "intel_dsi.h"
30 static void gen11_dsi_program_esc_clk_div(struct intel_encoder
*encoder
)
32 struct drm_i915_private
*dev_priv
= to_i915(encoder
->base
.dev
);
33 struct intel_dsi
*intel_dsi
= enc_to_intel_dsi(&encoder
->base
);
35 u32 bpp
= mipi_dsi_pixel_format_to_bpp(intel_dsi
->pixel_format
);
36 u32 afe_clk_khz
; /* 8X Clock */
39 afe_clk_khz
= DIV_ROUND_CLOSEST(intel_dsi
->pclk
* bpp
,
40 intel_dsi
->lane_count
);
42 esc_clk_div_m
= DIV_ROUND_UP(afe_clk_khz
, DSI_MAX_ESC_CLK
);
44 for_each_dsi_port(port
, intel_dsi
->ports
) {
45 I915_WRITE(ICL_DSI_ESC_CLK_DIV(port
),
46 esc_clk_div_m
& ICL_ESC_CLK_DIV_MASK
);
47 POSTING_READ(ICL_DSI_ESC_CLK_DIV(port
));
50 for_each_dsi_port(port
, intel_dsi
->ports
) {
51 I915_WRITE(ICL_DPHY_ESC_CLK_DIV(port
),
52 esc_clk_div_m
& ICL_ESC_CLK_DIV_MASK
);
53 POSTING_READ(ICL_DPHY_ESC_CLK_DIV(port
));
57 static void gen11_dsi_enable_io_power(struct intel_encoder
*encoder
)
59 struct drm_i915_private
*dev_priv
= to_i915(encoder
->base
.dev
);
60 struct intel_dsi
*intel_dsi
= enc_to_intel_dsi(&encoder
->base
);
64 for_each_dsi_port(port
, intel_dsi
->ports
) {
65 tmp
= I915_READ(ICL_DSI_IO_MODECTL(port
));
66 tmp
|= COMBO_PHY_MODE_DSI
;
67 I915_WRITE(ICL_DSI_IO_MODECTL(port
), tmp
);
70 for_each_dsi_port(port
, intel_dsi
->ports
) {
71 intel_display_power_get(dev_priv
, port
== PORT_A
?
72 POWER_DOMAIN_PORT_DDI_A_IO
:
73 POWER_DOMAIN_PORT_DDI_B_IO
);
77 static void gen11_dsi_power_up_lanes(struct intel_encoder
*encoder
)
79 struct drm_i915_private
*dev_priv
= to_i915(encoder
->base
.dev
);
80 struct intel_dsi
*intel_dsi
= enc_to_intel_dsi(&encoder
->base
);
85 switch (intel_dsi
->lane_count
) {
87 lane_mask
= PWR_DOWN_LN_3_1_0
;
90 lane_mask
= PWR_DOWN_LN_3_1
;
93 lane_mask
= PWR_DOWN_LN_3
;
97 lane_mask
= PWR_UP_ALL_LANES
;
101 for_each_dsi_port(port
, intel_dsi
->ports
) {
102 tmp
= I915_READ(ICL_PORT_CL_DW10(port
));
103 tmp
&= ~PWR_DOWN_LN_MASK
;
104 I915_WRITE(ICL_PORT_CL_DW10(port
), tmp
| lane_mask
);
108 static void gen11_dsi_enable_port_and_phy(struct intel_encoder
*encoder
)
110 /* step 4a: power up all lanes of the DDI used by DSI */
111 gen11_dsi_power_up_lanes(encoder
);
114 static void __attribute__((unused
))
115 gen11_dsi_pre_enable(struct intel_encoder
*encoder
,
116 const struct intel_crtc_state
*pipe_config
,
117 const struct drm_connector_state
*conn_state
)
119 /* step2: enable IO power */
120 gen11_dsi_enable_io_power(encoder
);
122 /* step3: enable DSI PLL */
123 gen11_dsi_program_esc_clk_div(encoder
);
125 /* step4: enable DSI port and DPHY */
126 gen11_dsi_enable_port_and_phy(encoder
);