diff options
Diffstat (limited to 'drivers/gpu/drm/i915/icl_dsi.c')
-rw-r--r-- | drivers/gpu/drm/i915/icl_dsi.c | 493 |
1 files changed, 482 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c index 01f422df8c23..4dd793b78996 100644 --- a/drivers/gpu/drm/i915/icl_dsi.c +++ b/drivers/gpu/drm/i915/icl_dsi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <drm/drm_mipi_dsi.h> | 28 | #include <drm/drm_mipi_dsi.h> |
29 | #include <drm/drm_atomic_helper.h> | ||
29 | #include "intel_dsi.h" | 30 | #include "intel_dsi.h" |
30 | 31 | ||
31 | static inline int header_credits_available(struct drm_i915_private *dev_priv, | 32 | static inline int header_credits_available(struct drm_i915_private *dev_priv, |
@@ -107,6 +108,90 @@ static void wait_for_cmds_dispatched_to_panel(struct intel_encoder *encoder) | |||
107 | } | 108 | } |
108 | } | 109 | } |
109 | 110 | ||
111 | static bool add_payld_to_queue(struct intel_dsi_host *host, const u8 *data, | ||
112 | u32 len) | ||
113 | { | ||
114 | struct intel_dsi *intel_dsi = host->intel_dsi; | ||
115 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); | ||
116 | enum transcoder dsi_trans = dsi_port_to_transcoder(host->port); | ||
117 | int free_credits; | ||
118 | int i, j; | ||
119 | |||
120 | for (i = 0; i < len; i += 4) { | ||
121 | u32 tmp = 0; | ||
122 | |||
123 | free_credits = payload_credits_available(dev_priv, dsi_trans); | ||
124 | if (free_credits < 1) { | ||
125 | DRM_ERROR("Payload credit not available\n"); | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | for (j = 0; j < min_t(u32, len - i, 4); j++) | ||
130 | tmp |= *data++ << 8 * j; | ||
131 | |||
132 | I915_WRITE(DSI_CMD_TXPYLD(dsi_trans), tmp); | ||
133 | } | ||
134 | |||
135 | return true; | ||
136 | } | ||
137 | |||
138 | static int dsi_send_pkt_hdr(struct intel_dsi_host *host, | ||
139 | struct mipi_dsi_packet pkt, bool enable_lpdt) | ||
140 | { | ||
141 | struct intel_dsi *intel_dsi = host->intel_dsi; | ||
142 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); | ||
143 | enum transcoder dsi_trans = dsi_port_to_transcoder(host->port); | ||
144 | u32 tmp; | ||
145 | int free_credits; | ||
146 | |||
147 | /* check if header credit available */ | ||
148 | free_credits = header_credits_available(dev_priv, dsi_trans); | ||
149 | if (free_credits < 1) { | ||
150 | DRM_ERROR("send pkt header failed, not enough hdr credits\n"); | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | tmp = I915_READ(DSI_CMD_TXHDR(dsi_trans)); | ||
155 | |||
156 | if (pkt.payload) | ||
157 | tmp |= PAYLOAD_PRESENT; | ||
158 | else | ||
159 | tmp &= ~PAYLOAD_PRESENT; | ||
160 | |||
161 | tmp &= ~VBLANK_FENCE; | ||
162 | |||
163 | if (enable_lpdt) | ||
164 | tmp |= LP_DATA_TRANSFER; | ||
165 | |||
166 | tmp &= ~(PARAM_WC_MASK | VC_MASK | DT_MASK); | ||
167 | tmp |= ((pkt.header[0] & VC_MASK) << VC_SHIFT); | ||
168 | tmp |= ((pkt.header[0] & DT_MASK) << DT_SHIFT); | ||
169 | tmp |= (pkt.header[1] << PARAM_WC_LOWER_SHIFT); | ||
170 | tmp |= (pkt.header[2] << PARAM_WC_UPPER_SHIFT); | ||
171 | I915_WRITE(DSI_CMD_TXHDR(dsi_trans), tmp); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int dsi_send_pkt_payld(struct intel_dsi_host *host, | ||
177 | struct mipi_dsi_packet pkt) | ||
178 | { | ||
179 | /* payload queue can accept *256 bytes*, check limit */ | ||
180 | if (pkt.payload_length > MAX_PLOAD_CREDIT * 4) { | ||
181 | DRM_ERROR("payload size exceeds max queue limit\n"); | ||
182 | return -1; | ||
183 | } | ||
184 | |||
185 | /* load data into command payload queue */ | ||
186 | if (!add_payld_to_queue(host, pkt.payload, | ||
187 | pkt.payload_length)) { | ||
188 | DRM_ERROR("adding payload to queue failed\n"); | ||
189 | return -1; | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
110 | static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) | 195 | static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) |
111 | { | 196 | { |
112 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 197 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
@@ -172,6 +257,45 @@ static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder) | |||
172 | } | 257 | } |
173 | } | 258 | } |
174 | 259 | ||
260 | static void configure_dual_link_mode(struct intel_encoder *encoder, | ||
261 | const struct intel_crtc_state *pipe_config) | ||
262 | { | ||
263 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
264 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
265 | u32 dss_ctl1; | ||
266 | |||
267 | dss_ctl1 = I915_READ(DSS_CTL1); | ||
268 | dss_ctl1 |= SPLITTER_ENABLE; | ||
269 | dss_ctl1 &= ~OVERLAP_PIXELS_MASK; | ||
270 | dss_ctl1 |= OVERLAP_PIXELS(intel_dsi->pixel_overlap); | ||
271 | |||
272 | if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { | ||
273 | const struct drm_display_mode *adjusted_mode = | ||
274 | &pipe_config->base.adjusted_mode; | ||
275 | u32 dss_ctl2; | ||
276 | u16 hactive = adjusted_mode->crtc_hdisplay; | ||
277 | u16 dl_buffer_depth; | ||
278 | |||
279 | dss_ctl1 &= ~DUAL_LINK_MODE_INTERLEAVE; | ||
280 | dl_buffer_depth = hactive / 2 + intel_dsi->pixel_overlap; | ||
281 | |||
282 | if (dl_buffer_depth > MAX_DL_BUFFER_TARGET_DEPTH) | ||
283 | DRM_ERROR("DL buffer depth exceed max value\n"); | ||
284 | |||
285 | dss_ctl1 &= ~LEFT_DL_BUF_TARGET_DEPTH_MASK; | ||
286 | dss_ctl1 |= LEFT_DL_BUF_TARGET_DEPTH(dl_buffer_depth); | ||
287 | dss_ctl2 = I915_READ(DSS_CTL2); | ||
288 | dss_ctl2 &= ~RIGHT_DL_BUF_TARGET_DEPTH_MASK; | ||
289 | dss_ctl2 |= RIGHT_DL_BUF_TARGET_DEPTH(dl_buffer_depth); | ||
290 | I915_WRITE(DSS_CTL2, dss_ctl2); | ||
291 | } else { | ||
292 | /* Interleave */ | ||
293 | dss_ctl1 |= DUAL_LINK_MODE_INTERLEAVE; | ||
294 | } | ||
295 | |||
296 | I915_WRITE(DSS_CTL1, dss_ctl1); | ||
297 | } | ||
298 | |||
175 | static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) | 299 | static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder) |
176 | { | 300 | { |
177 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 301 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
@@ -412,6 +536,62 @@ static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder) | |||
412 | } | 536 | } |
413 | } | 537 | } |
414 | 538 | ||
539 | static void gen11_dsi_gate_clocks(struct intel_encoder *encoder) | ||
540 | { | ||
541 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
542 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
543 | u32 tmp; | ||
544 | enum port port; | ||
545 | |||
546 | mutex_lock(&dev_priv->dpll_lock); | ||
547 | tmp = I915_READ(DPCLKA_CFGCR0_ICL); | ||
548 | for_each_dsi_port(port, intel_dsi->ports) { | ||
549 | tmp |= DPCLKA_CFGCR0_DDI_CLK_OFF(port); | ||
550 | } | ||
551 | |||
552 | I915_WRITE(DPCLKA_CFGCR0_ICL, tmp); | ||
553 | mutex_unlock(&dev_priv->dpll_lock); | ||
554 | } | ||
555 | |||
556 | static void gen11_dsi_ungate_clocks(struct intel_encoder *encoder) | ||
557 | { | ||
558 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
559 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
560 | u32 tmp; | ||
561 | enum port port; | ||
562 | |||
563 | mutex_lock(&dev_priv->dpll_lock); | ||
564 | tmp = I915_READ(DPCLKA_CFGCR0_ICL); | ||
565 | for_each_dsi_port(port, intel_dsi->ports) { | ||
566 | tmp &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port); | ||
567 | } | ||
568 | |||
569 | I915_WRITE(DPCLKA_CFGCR0_ICL, tmp); | ||
570 | mutex_unlock(&dev_priv->dpll_lock); | ||
571 | } | ||
572 | |||
573 | static void gen11_dsi_map_pll(struct intel_encoder *encoder, | ||
574 | const struct intel_crtc_state *crtc_state) | ||
575 | { | ||
576 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
577 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
578 | struct intel_shared_dpll *pll = crtc_state->shared_dpll; | ||
579 | enum port port; | ||
580 | u32 val; | ||
581 | |||
582 | mutex_lock(&dev_priv->dpll_lock); | ||
583 | |||
584 | val = I915_READ(DPCLKA_CFGCR0_ICL); | ||
585 | for_each_dsi_port(port, intel_dsi->ports) { | ||
586 | val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); | ||
587 | val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port); | ||
588 | } | ||
589 | I915_WRITE(DPCLKA_CFGCR0_ICL, val); | ||
590 | POSTING_READ(DPCLKA_CFGCR0_ICL); | ||
591 | |||
592 | mutex_unlock(&dev_priv->dpll_lock); | ||
593 | } | ||
594 | |||
415 | static void | 595 | static void |
416 | gen11_dsi_configure_transcoder(struct intel_encoder *encoder, | 596 | gen11_dsi_configure_transcoder(struct intel_encoder *encoder, |
417 | const struct intel_crtc_state *pipe_config) | 597 | const struct intel_crtc_state *pipe_config) |
@@ -506,7 +686,8 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, | |||
506 | I915_WRITE(TRANS_DDI_FUNC_CTL2(dsi_trans), tmp); | 686 | I915_WRITE(TRANS_DDI_FUNC_CTL2(dsi_trans), tmp); |
507 | } | 687 | } |
508 | 688 | ||
509 | //TODO: configure DSS_CTL1 | 689 | /* configure stream splitting */ |
690 | configure_dual_link_mode(encoder, pipe_config); | ||
510 | } | 691 | } |
511 | 692 | ||
512 | for_each_dsi_port(port, intel_dsi->ports) { | 693 | for_each_dsi_port(port, intel_dsi->ports) { |
@@ -758,6 +939,9 @@ gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder, | |||
758 | 939 | ||
759 | /* Step (4h, 4i, 4j, 4k): Configure transcoder */ | 940 | /* Step (4h, 4i, 4j, 4k): Configure transcoder */ |
760 | gen11_dsi_configure_transcoder(encoder, pipe_config); | 941 | gen11_dsi_configure_transcoder(encoder, pipe_config); |
942 | |||
943 | /* Step 4l: Gate DDI clocks */ | ||
944 | gen11_dsi_gate_clocks(encoder); | ||
761 | } | 945 | } |
762 | 946 | ||
763 | static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) | 947 | static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) |
@@ -799,18 +983,25 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) | |||
799 | wait_for_cmds_dispatched_to_panel(encoder); | 983 | wait_for_cmds_dispatched_to_panel(encoder); |
800 | } | 984 | } |
801 | 985 | ||
802 | static void __attribute__((unused)) | 986 | static void gen11_dsi_pre_pll_enable(struct intel_encoder *encoder, |
803 | gen11_dsi_pre_enable(struct intel_encoder *encoder, | 987 | const struct intel_crtc_state *pipe_config, |
804 | const struct intel_crtc_state *pipe_config, | 988 | const struct drm_connector_state *conn_state) |
805 | const struct drm_connector_state *conn_state) | ||
806 | { | 989 | { |
807 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
808 | |||
809 | /* step2: enable IO power */ | 990 | /* step2: enable IO power */ |
810 | gen11_dsi_enable_io_power(encoder); | 991 | gen11_dsi_enable_io_power(encoder); |
811 | 992 | ||
812 | /* step3: enable DSI PLL */ | 993 | /* step3: enable DSI PLL */ |
813 | gen11_dsi_program_esc_clk_div(encoder); | 994 | gen11_dsi_program_esc_clk_div(encoder); |
995 | } | ||
996 | |||
997 | static void gen11_dsi_pre_enable(struct intel_encoder *encoder, | ||
998 | const struct intel_crtc_state *pipe_config, | ||
999 | const struct drm_connector_state *conn_state) | ||
1000 | { | ||
1001 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
1002 | |||
1003 | /* step3b */ | ||
1004 | gen11_dsi_map_pll(encoder, pipe_config); | ||
814 | 1005 | ||
815 | /* step4: enable DSI port and DPHY */ | 1006 | /* step4: enable DSI port and DPHY */ |
816 | gen11_dsi_enable_port_and_phy(encoder, pipe_config); | 1007 | gen11_dsi_enable_port_and_phy(encoder, pipe_config); |
@@ -912,6 +1103,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder) | |||
912 | u32 tmp; | 1103 | u32 tmp; |
913 | enum port port; | 1104 | enum port port; |
914 | 1105 | ||
1106 | gen11_dsi_ungate_clocks(encoder); | ||
915 | for_each_dsi_port(port, intel_dsi->ports) { | 1107 | for_each_dsi_port(port, intel_dsi->ports) { |
916 | tmp = I915_READ(DDI_BUF_CTL(port)); | 1108 | tmp = I915_READ(DDI_BUF_CTL(port)); |
917 | tmp &= ~DDI_BUF_CTL_ENABLE; | 1109 | tmp &= ~DDI_BUF_CTL_ENABLE; |
@@ -923,6 +1115,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder) | |||
923 | DRM_ERROR("DDI port:%c buffer not idle\n", | 1115 | DRM_ERROR("DDI port:%c buffer not idle\n", |
924 | port_name(port)); | 1116 | port_name(port)); |
925 | } | 1117 | } |
1118 | gen11_dsi_ungate_clocks(encoder); | ||
926 | } | 1119 | } |
927 | 1120 | ||
928 | static void gen11_dsi_disable_io_power(struct intel_encoder *encoder) | 1121 | static void gen11_dsi_disable_io_power(struct intel_encoder *encoder) |
@@ -945,10 +1138,9 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder) | |||
945 | } | 1138 | } |
946 | } | 1139 | } |
947 | 1140 | ||
948 | static void __attribute__((unused)) gen11_dsi_disable( | 1141 | static void gen11_dsi_disable(struct intel_encoder *encoder, |
949 | struct intel_encoder *encoder, | 1142 | const struct intel_crtc_state *old_crtc_state, |
950 | const struct intel_crtc_state *old_crtc_state, | 1143 | const struct drm_connector_state *old_conn_state) |
951 | const struct drm_connector_state *old_conn_state) | ||
952 | { | 1144 | { |
953 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | 1145 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
954 | 1146 | ||
@@ -972,10 +1164,289 @@ static void __attribute__((unused)) gen11_dsi_disable( | |||
972 | gen11_dsi_disable_io_power(encoder); | 1164 | gen11_dsi_disable_io_power(encoder); |
973 | } | 1165 | } |
974 | 1166 | ||
1167 | static void gen11_dsi_get_config(struct intel_encoder *encoder, | ||
1168 | struct intel_crtc_state *pipe_config) | ||
1169 | { | ||
1170 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
1171 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
1172 | u32 pll_id; | ||
1173 | |||
1174 | /* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */ | ||
1175 | pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); | ||
1176 | pipe_config->port_clock = cnl_calc_wrpll_link(dev_priv, pll_id); | ||
1177 | pipe_config->base.adjusted_mode.crtc_clock = intel_dsi->pclk; | ||
1178 | pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI); | ||
1179 | } | ||
1180 | |||
1181 | static bool gen11_dsi_compute_config(struct intel_encoder *encoder, | ||
1182 | struct intel_crtc_state *pipe_config, | ||
1183 | struct drm_connector_state *conn_state) | ||
1184 | { | ||
1185 | struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, | ||
1186 | base); | ||
1187 | struct intel_connector *intel_connector = intel_dsi->attached_connector; | ||
1188 | struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc); | ||
1189 | const struct drm_display_mode *fixed_mode = | ||
1190 | intel_connector->panel.fixed_mode; | ||
1191 | struct drm_display_mode *adjusted_mode = | ||
1192 | &pipe_config->base.adjusted_mode; | ||
1193 | |||
1194 | intel_fixed_panel_mode(fixed_mode, adjusted_mode); | ||
1195 | intel_pch_panel_fitting(crtc, pipe_config, conn_state->scaling_mode); | ||
1196 | |||
1197 | adjusted_mode->flags = 0; | ||
1198 | |||
1199 | /* Dual link goes to trancoder DSI'0' */ | ||
1200 | if (intel_dsi->ports == BIT(PORT_B)) | ||
1201 | pipe_config->cpu_transcoder = TRANSCODER_DSI_1; | ||
1202 | else | ||
1203 | pipe_config->cpu_transcoder = TRANSCODER_DSI_0; | ||
1204 | |||
1205 | pipe_config->clock_set = true; | ||
1206 | pipe_config->port_clock = intel_dsi_bitrate(intel_dsi) / 5; | ||
1207 | |||
1208 | return true; | ||
1209 | } | ||
1210 | |||
1211 | static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder, | ||
1212 | struct intel_crtc_state *crtc_state) | ||
1213 | { | ||
1214 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
1215 | u64 domains = 0; | ||
1216 | enum port port; | ||
1217 | |||
1218 | for_each_dsi_port(port, intel_dsi->ports) | ||
1219 | if (port == PORT_A) | ||
1220 | domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO); | ||
1221 | else | ||
1222 | domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO); | ||
1223 | |||
1224 | return domains; | ||
1225 | } | ||
1226 | |||
1227 | static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder, | ||
1228 | enum pipe *pipe) | ||
1229 | { | ||
1230 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
1231 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | ||
1232 | u32 tmp; | ||
1233 | enum port port; | ||
1234 | enum transcoder dsi_trans; | ||
1235 | bool ret = false; | ||
1236 | |||
1237 | if (!intel_display_power_get_if_enabled(dev_priv, | ||
1238 | encoder->power_domain)) | ||
1239 | return false; | ||
1240 | |||
1241 | for_each_dsi_port(port, intel_dsi->ports) { | ||
1242 | dsi_trans = dsi_port_to_transcoder(port); | ||
1243 | tmp = I915_READ(TRANS_DDI_FUNC_CTL(dsi_trans)); | ||
1244 | switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { | ||
1245 | case TRANS_DDI_EDP_INPUT_A_ON: | ||
1246 | *pipe = PIPE_A; | ||
1247 | break; | ||
1248 | case TRANS_DDI_EDP_INPUT_B_ONOFF: | ||
1249 | *pipe = PIPE_B; | ||
1250 | break; | ||
1251 | case TRANS_DDI_EDP_INPUT_C_ONOFF: | ||
1252 | *pipe = PIPE_C; | ||
1253 | break; | ||
1254 | default: | ||
1255 | DRM_ERROR("Invalid PIPE input\n"); | ||
1256 | goto out; | ||
1257 | } | ||
1258 | |||
1259 | tmp = I915_READ(PIPECONF(dsi_trans)); | ||
1260 | ret = tmp & PIPECONF_ENABLE; | ||
1261 | } | ||
1262 | out: | ||
1263 | intel_display_power_put(dev_priv, encoder->power_domain); | ||
1264 | return ret; | ||
1265 | } | ||
1266 | |||
1267 | static void gen11_dsi_encoder_destroy(struct drm_encoder *encoder) | ||
1268 | { | ||
1269 | intel_encoder_destroy(encoder); | ||
1270 | } | ||
1271 | |||
1272 | static const struct drm_encoder_funcs gen11_dsi_encoder_funcs = { | ||
1273 | .destroy = gen11_dsi_encoder_destroy, | ||
1274 | }; | ||
1275 | |||
1276 | static const struct drm_connector_funcs gen11_dsi_connector_funcs = { | ||
1277 | .late_register = intel_connector_register, | ||
1278 | .early_unregister = intel_connector_unregister, | ||
1279 | .destroy = intel_connector_destroy, | ||
1280 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
1281 | .atomic_get_property = intel_digital_connector_atomic_get_property, | ||
1282 | .atomic_set_property = intel_digital_connector_atomic_set_property, | ||
1283 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | ||
1284 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, | ||
1285 | }; | ||
1286 | |||
1287 | static const struct drm_connector_helper_funcs gen11_dsi_connector_helper_funcs = { | ||
1288 | .get_modes = intel_dsi_get_modes, | ||
1289 | .mode_valid = intel_dsi_mode_valid, | ||
1290 | .atomic_check = intel_digital_connector_atomic_check, | ||
1291 | }; | ||
1292 | |||
1293 | static int gen11_dsi_host_attach(struct mipi_dsi_host *host, | ||
1294 | struct mipi_dsi_device *dsi) | ||
1295 | { | ||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | static int gen11_dsi_host_detach(struct mipi_dsi_host *host, | ||
1300 | struct mipi_dsi_device *dsi) | ||
1301 | { | ||
1302 | return 0; | ||
1303 | } | ||
1304 | |||
1305 | static ssize_t gen11_dsi_host_transfer(struct mipi_dsi_host *host, | ||
1306 | const struct mipi_dsi_msg *msg) | ||
1307 | { | ||
1308 | struct intel_dsi_host *intel_dsi_host = to_intel_dsi_host(host); | ||
1309 | struct mipi_dsi_packet dsi_pkt; | ||
1310 | ssize_t ret; | ||
1311 | bool enable_lpdt = false; | ||
1312 | |||
1313 | ret = mipi_dsi_create_packet(&dsi_pkt, msg); | ||
1314 | if (ret < 0) | ||
1315 | return ret; | ||
1316 | |||
1317 | if (msg->flags & MIPI_DSI_MSG_USE_LPM) | ||
1318 | enable_lpdt = true; | ||
1319 | |||
1320 | /* send packet header */ | ||
1321 | ret = dsi_send_pkt_hdr(intel_dsi_host, dsi_pkt, enable_lpdt); | ||
1322 | if (ret < 0) | ||
1323 | return ret; | ||
1324 | |||
1325 | /* only long packet contains payload */ | ||
1326 | if (mipi_dsi_packet_format_is_long(msg->type)) { | ||
1327 | ret = dsi_send_pkt_payld(intel_dsi_host, dsi_pkt); | ||
1328 | if (ret < 0) | ||
1329 | return ret; | ||
1330 | } | ||
1331 | |||
1332 | //TODO: add payload receive code if needed | ||
1333 | |||
1334 | ret = sizeof(dsi_pkt.header) + dsi_pkt.payload_length; | ||
1335 | |||
1336 | return ret; | ||
1337 | } | ||
1338 | |||
1339 | static const struct mipi_dsi_host_ops gen11_dsi_host_ops = { | ||
1340 | .attach = gen11_dsi_host_attach, | ||
1341 | .detach = gen11_dsi_host_detach, | ||
1342 | .transfer = gen11_dsi_host_transfer, | ||
1343 | }; | ||
1344 | |||
975 | void icl_dsi_init(struct drm_i915_private *dev_priv) | 1345 | void icl_dsi_init(struct drm_i915_private *dev_priv) |
976 | { | 1346 | { |
1347 | struct drm_device *dev = &dev_priv->drm; | ||
1348 | struct intel_dsi *intel_dsi; | ||
1349 | struct intel_encoder *encoder; | ||
1350 | struct intel_connector *intel_connector; | ||
1351 | struct drm_connector *connector; | ||
1352 | struct drm_display_mode *scan, *fixed_mode = NULL; | ||
977 | enum port port; | 1353 | enum port port; |
978 | 1354 | ||
979 | if (!intel_bios_is_dsi_present(dev_priv, &port)) | 1355 | if (!intel_bios_is_dsi_present(dev_priv, &port)) |
980 | return; | 1356 | return; |
1357 | |||
1358 | intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL); | ||
1359 | if (!intel_dsi) | ||
1360 | return; | ||
1361 | |||
1362 | intel_connector = intel_connector_alloc(); | ||
1363 | if (!intel_connector) { | ||
1364 | kfree(intel_dsi); | ||
1365 | return; | ||
1366 | } | ||
1367 | |||
1368 | encoder = &intel_dsi->base; | ||
1369 | intel_dsi->attached_connector = intel_connector; | ||
1370 | connector = &intel_connector->base; | ||
1371 | |||
1372 | /* register DSI encoder with DRM subsystem */ | ||
1373 | drm_encoder_init(dev, &encoder->base, &gen11_dsi_encoder_funcs, | ||
1374 | DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port)); | ||
1375 | |||
1376 | encoder->pre_pll_enable = gen11_dsi_pre_pll_enable; | ||
1377 | encoder->pre_enable = gen11_dsi_pre_enable; | ||
1378 | encoder->disable = gen11_dsi_disable; | ||
1379 | encoder->port = port; | ||
1380 | encoder->get_config = gen11_dsi_get_config; | ||
1381 | encoder->compute_config = gen11_dsi_compute_config; | ||
1382 | encoder->get_hw_state = gen11_dsi_get_hw_state; | ||
1383 | encoder->type = INTEL_OUTPUT_DSI; | ||
1384 | encoder->cloneable = 0; | ||
1385 | encoder->crtc_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C); | ||
1386 | encoder->power_domain = POWER_DOMAIN_PORT_DSI; | ||
1387 | encoder->get_power_domains = gen11_dsi_get_power_domains; | ||
1388 | |||
1389 | /* register DSI connector with DRM subsystem */ | ||
1390 | drm_connector_init(dev, connector, &gen11_dsi_connector_funcs, | ||
1391 | DRM_MODE_CONNECTOR_DSI); | ||
1392 | drm_connector_helper_add(connector, &gen11_dsi_connector_helper_funcs); | ||
1393 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
1394 | connector->interlace_allowed = false; | ||
1395 | connector->doublescan_allowed = false; | ||
1396 | intel_connector->get_hw_state = intel_connector_get_hw_state; | ||
1397 | |||
1398 | /* attach connector to encoder */ | ||
1399 | intel_connector_attach_encoder(intel_connector, encoder); | ||
1400 | |||
1401 | /* fill mode info from VBT */ | ||
1402 | mutex_lock(&dev->mode_config.mutex); | ||
1403 | intel_dsi_vbt_get_modes(intel_dsi); | ||
1404 | list_for_each_entry(scan, &connector->probed_modes, head) { | ||
1405 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { | ||
1406 | fixed_mode = drm_mode_duplicate(dev, scan); | ||
1407 | break; | ||
1408 | } | ||
1409 | } | ||
1410 | mutex_unlock(&dev->mode_config.mutex); | ||
1411 | |||
1412 | if (!fixed_mode) { | ||
1413 | DRM_ERROR("DSI fixed mode info missing\n"); | ||
1414 | goto err; | ||
1415 | } | ||
1416 | |||
1417 | connector->display_info.width_mm = fixed_mode->width_mm; | ||
1418 | connector->display_info.height_mm = fixed_mode->height_mm; | ||
1419 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); | ||
1420 | intel_panel_setup_backlight(connector, INVALID_PIPE); | ||
1421 | |||
1422 | |||
1423 | if (dev_priv->vbt.dsi.config->dual_link) | ||
1424 | intel_dsi->ports = BIT(PORT_A) | BIT(PORT_B); | ||
1425 | else | ||
1426 | intel_dsi->ports = BIT(port); | ||
1427 | |||
1428 | intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports; | ||
1429 | intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports; | ||
1430 | |||
1431 | for_each_dsi_port(port, intel_dsi->ports) { | ||
1432 | struct intel_dsi_host *host; | ||
1433 | |||
1434 | host = intel_dsi_host_init(intel_dsi, &gen11_dsi_host_ops, port); | ||
1435 | if (!host) | ||
1436 | goto err; | ||
1437 | |||
1438 | intel_dsi->dsi_hosts[port] = host; | ||
1439 | } | ||
1440 | |||
1441 | if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) { | ||
1442 | DRM_DEBUG_KMS("no device found\n"); | ||
1443 | goto err; | ||
1444 | } | ||
1445 | |||
1446 | return; | ||
1447 | |||
1448 | err: | ||
1449 | drm_encoder_cleanup(&encoder->base); | ||
1450 | kfree(intel_dsi); | ||
1451 | kfree(intel_connector); | ||
981 | } | 1452 | } |