]>
Commit | Line | Data |
---|---|---|
2ab8b458 SK |
1 | /* |
2 | * Copyright © 2014 Intel Corporation | |
3 | * | |
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: | |
10 | * | |
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 | |
13 | * Software. | |
14 | * | |
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. | |
22 | * | |
23 | * Author: Shobhit Kumar <shobhit.kumar@intel.com> | |
24 | * | |
25 | */ | |
26 | ||
213e08ad | 27 | #include <linux/gpio/consumer.h> |
4e8052af | 28 | #include <linux/mfd/intel_soc_pmic.h> |
2ab8b458 | 29 | #include <linux/slab.h> |
56c5098f | 30 | |
2ab8b458 | 31 | #include <asm/intel-mid.h> |
4e8052af | 32 | #include <asm/unaligned.h> |
56c5098f CW |
33 | |
34 | #include <drm/drm_crtc.h> | |
35 | #include <drm/drm_edid.h> | |
36 | #include <drm/i915_drm.h> | |
37 | ||
38 | #include <video/mipi_display.h> | |
39 | ||
2ab8b458 SK |
40 | #include "i915_drv.h" |
41 | #include "intel_drv.h" | |
42 | #include "intel_dsi.h" | |
56c5098f | 43 | #include "intel_sideband.h" |
2ab8b458 SK |
44 | |
45 | #define MIPI_TRANSFER_MODE_SHIFT 0 | |
46 | #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 | |
47 | #define MIPI_PORT_SHIFT 3 | |
48 | ||
49 | #define PREPARE_CNT_MAX 0x3F | |
50 | #define EXIT_ZERO_CNT_MAX 0x3F | |
51 | #define CLK_ZERO_CNT_MAX 0xFF | |
52 | #define TRAIL_CNT_MAX 0x1F | |
53 | ||
54 | #define NS_KHZ_RATIO 1000000 | |
55 | ||
b0c91cd0 JN |
56 | /* base offsets for gpio pads */ |
57 | #define VLV_GPIO_NC_0_HV_DDI0_HPD 0x4130 | |
58 | #define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120 | |
59 | #define VLV_GPIO_NC_2_HV_DDI0_DDC_SCL 0x4110 | |
60 | #define VLV_GPIO_NC_3_PANEL0_VDDEN 0x4140 | |
61 | #define VLV_GPIO_NC_4_PANEL0_BKLTEN 0x4150 | |
62 | #define VLV_GPIO_NC_5_PANEL0_BKLTCTL 0x4160 | |
63 | #define VLV_GPIO_NC_6_HV_DDI1_HPD 0x4180 | |
64 | #define VLV_GPIO_NC_7_HV_DDI1_DDC_SDA 0x4190 | |
65 | #define VLV_GPIO_NC_8_HV_DDI1_DDC_SCL 0x4170 | |
66 | #define VLV_GPIO_NC_9_PANEL1_VDDEN 0x4100 | |
67 | #define VLV_GPIO_NC_10_PANEL1_BKLTEN 0x40E0 | |
68 | #define VLV_GPIO_NC_11_PANEL1_BKLTCTL 0x40F0 | |
69 | ||
70 | #define VLV_GPIO_PCONF0(base_offset) (base_offset) | |
71 | #define VLV_GPIO_PAD_VAL(base_offset) ((base_offset) + 8) | |
2ab8b458 | 72 | |
b13d8e28 | 73 | struct gpio_map { |
b0c91cd0 JN |
74 | u16 base_offset; |
75 | bool init; | |
2ab8b458 SK |
76 | }; |
77 | ||
b13d8e28 | 78 | static struct gpio_map vlv_gpio_table[] = { |
b0c91cd0 JN |
79 | { VLV_GPIO_NC_0_HV_DDI0_HPD }, |
80 | { VLV_GPIO_NC_1_HV_DDI0_DDC_SDA }, | |
81 | { VLV_GPIO_NC_2_HV_DDI0_DDC_SCL }, | |
82 | { VLV_GPIO_NC_3_PANEL0_VDDEN }, | |
83 | { VLV_GPIO_NC_4_PANEL0_BKLTEN }, | |
84 | { VLV_GPIO_NC_5_PANEL0_BKLTCTL }, | |
85 | { VLV_GPIO_NC_6_HV_DDI1_HPD }, | |
86 | { VLV_GPIO_NC_7_HV_DDI1_DDC_SDA }, | |
87 | { VLV_GPIO_NC_8_HV_DDI1_DDC_SCL }, | |
88 | { VLV_GPIO_NC_9_PANEL1_VDDEN }, | |
89 | { VLV_GPIO_NC_10_PANEL1_BKLTEN }, | |
90 | { VLV_GPIO_NC_11_PANEL1_BKLTCTL }, | |
2ab8b458 SK |
91 | }; |
92 | ||
a0a6d4ff JN |
93 | #define CHV_GPIO_IDX_START_N 0 |
94 | #define CHV_GPIO_IDX_START_E 73 | |
95 | #define CHV_GPIO_IDX_START_SW 100 | |
96 | #define CHV_GPIO_IDX_START_SE 198 | |
97 | ||
98 | #define CHV_VBT_MAX_PINS_PER_FMLY 15 | |
99 | ||
100 | #define CHV_GPIO_PAD_CFG0(f, i) (0x4400 + (f) * 0x400 + (i) * 8) | |
101 | #define CHV_GPIO_GPIOEN (1 << 15) | |
102 | #define CHV_GPIO_GPIOCFG_GPIO (0 << 8) | |
103 | #define CHV_GPIO_GPIOCFG_GPO (1 << 8) | |
104 | #define CHV_GPIO_GPIOCFG_GPI (2 << 8) | |
105 | #define CHV_GPIO_GPIOCFG_HIZ (3 << 8) | |
106 | #define CHV_GPIO_GPIOTXSTATE(state) ((!!(state)) << 1) | |
107 | ||
108 | #define CHV_GPIO_PAD_CFG1(f, i) (0x4400 + (f) * 0x400 + (i) * 8 + 4) | |
109 | #define CHV_GPIO_CFGLOCK (1 << 31) | |
110 | ||
56b7b1aa MC |
111 | /* ICL DSI Display GPIO Pins */ |
112 | #define ICL_GPIO_DDSP_HPD_A 0 | |
113 | #define ICL_GPIO_L_VDDEN_1 1 | |
114 | #define ICL_GPIO_L_BKLTEN_1 2 | |
115 | #define ICL_GPIO_DDPA_CTRLCLK_1 3 | |
116 | #define ICL_GPIO_DDPA_CTRLDATA_1 4 | |
117 | #define ICL_GPIO_DDSP_HPD_B 5 | |
118 | #define ICL_GPIO_L_VDDEN_2 6 | |
119 | #define ICL_GPIO_L_BKLTEN_2 7 | |
120 | #define ICL_GPIO_DDPA_CTRLCLK_2 8 | |
121 | #define ICL_GPIO_DDPA_CTRLDATA_2 9 | |
122 | ||
8f4d2683 GS |
123 | static inline enum port intel_dsi_seq_port_to_port(u8 port) |
124 | { | |
125 | return port ? PORT_C : PORT_A; | |
126 | } | |
127 | ||
5b48ca0f JN |
128 | static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, |
129 | const u8 *data) | |
2ab8b458 | 130 | { |
f968c85b | 131 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); |
759d10c2 JN |
132 | struct mipi_dsi_device *dsi_device; |
133 | u8 type, flags, seq_port; | |
2ab8b458 | 134 | u16 len; |
8f4d2683 | 135 | enum port port; |
2ab8b458 | 136 | |
0b9407c3 JN |
137 | DRM_DEBUG_KMS("\n"); |
138 | ||
759d10c2 JN |
139 | flags = *data++; |
140 | type = *data++; | |
141 | ||
142 | len = *((u16 *) data); | |
143 | data += 2; | |
144 | ||
145 | seq_port = (flags >> MIPI_PORT_SHIFT) & 3; | |
2ab8b458 | 146 | |
f915084e GS |
147 | /* For DSI single link on Port A & C, the seq_port value which is |
148 | * parsed from Sequence Block#53 of VBT has been set to 0 | |
149 | * Now, read/write of packets for the DSI single link on Port A and | |
150 | * Port C will based on the DVO port from VBT block 2. | |
151 | */ | |
152 | if (intel_dsi->ports == (1 << PORT_C)) | |
153 | port = PORT_C; | |
154 | else | |
155 | port = intel_dsi_seq_port_to_port(seq_port); | |
2ab8b458 | 156 | |
759d10c2 JN |
157 | dsi_device = intel_dsi->dsi_hosts[port]->device; |
158 | if (!dsi_device) { | |
159 | DRM_DEBUG_KMS("no dsi device for port %c\n", port_name(port)); | |
160 | goto out; | |
161 | } | |
2ab8b458 | 162 | |
759d10c2 JN |
163 | if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1) |
164 | dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM; | |
165 | else | |
166 | dsi_device->mode_flags |= MIPI_DSI_MODE_LPM; | |
167 | ||
168 | dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3; | |
2ab8b458 SK |
169 | |
170 | switch (type) { | |
171 | case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: | |
759d10c2 | 172 | mipi_dsi_generic_write(dsi_device, NULL, 0); |
2ab8b458 SK |
173 | break; |
174 | case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: | |
759d10c2 | 175 | mipi_dsi_generic_write(dsi_device, data, 1); |
2ab8b458 SK |
176 | break; |
177 | case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: | |
759d10c2 | 178 | mipi_dsi_generic_write(dsi_device, data, 2); |
2ab8b458 SK |
179 | break; |
180 | case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: | |
181 | case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: | |
182 | case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: | |
183 | DRM_DEBUG_DRIVER("Generic Read not yet implemented or used\n"); | |
184 | break; | |
185 | case MIPI_DSI_GENERIC_LONG_WRITE: | |
759d10c2 | 186 | mipi_dsi_generic_write(dsi_device, data, len); |
2ab8b458 SK |
187 | break; |
188 | case MIPI_DSI_DCS_SHORT_WRITE: | |
759d10c2 | 189 | mipi_dsi_dcs_write_buffer(dsi_device, data, 1); |
2ab8b458 SK |
190 | break; |
191 | case MIPI_DSI_DCS_SHORT_WRITE_PARAM: | |
759d10c2 | 192 | mipi_dsi_dcs_write_buffer(dsi_device, data, 2); |
2ab8b458 SK |
193 | break; |
194 | case MIPI_DSI_DCS_READ: | |
195 | DRM_DEBUG_DRIVER("DCS Read not yet implemented or used\n"); | |
196 | break; | |
197 | case MIPI_DSI_DCS_LONG_WRITE: | |
759d10c2 | 198 | mipi_dsi_dcs_write_buffer(dsi_device, data, len); |
2ab8b458 | 199 | break; |
b5fbcd98 | 200 | } |
2ab8b458 | 201 | |
2dd24a9c | 202 | if (INTEL_GEN(dev_priv) < 11) |
f968c85b | 203 | vlv_dsi_wait_for_fifo_empty(intel_dsi, port); |
3870b89a | 204 | |
759d10c2 | 205 | out: |
2ab8b458 SK |
206 | data += len; |
207 | ||
208 | return data; | |
209 | } | |
210 | ||
5b48ca0f | 211 | static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) |
2ab8b458 | 212 | { |
5b48ca0f | 213 | u32 delay = *((const u32 *) data); |
2ab8b458 | 214 | |
0b9407c3 JN |
215 | DRM_DEBUG_KMS("\n"); |
216 | ||
2ab8b458 SK |
217 | usleep_range(delay, delay + 10); |
218 | data += 4; | |
219 | ||
220 | return data; | |
221 | } | |
222 | ||
515d07de JN |
223 | static void vlv_exec_gpio(struct drm_i915_private *dev_priv, |
224 | u8 gpio_source, u8 gpio_index, bool value) | |
2ab8b458 | 225 | { |
b13d8e28 | 226 | struct gpio_map *map; |
b0c91cd0 | 227 | u16 pconf0, padval; |
515d07de JN |
228 | u32 tmp; |
229 | u8 port; | |
2ab8b458 | 230 | |
b0c91cd0 | 231 | if (gpio_index >= ARRAY_SIZE(vlv_gpio_table)) { |
e37788fd | 232 | DRM_DEBUG_KMS("unknown gpio index %u\n", gpio_index); |
515d07de | 233 | return; |
96afef1d JN |
234 | } |
235 | ||
b13d8e28 JN |
236 | map = &vlv_gpio_table[gpio_index]; |
237 | ||
96afef1d | 238 | if (dev_priv->vbt.dsi.seq_version >= 3) { |
4b541efe JN |
239 | /* XXX: this assumes vlv_gpio_table only has NC GPIOs. */ |
240 | port = IOSF_PORT_GPIO_NC; | |
1d96a4a8 JN |
241 | } else { |
242 | if (gpio_source == 0) { | |
243 | port = IOSF_PORT_GPIO_NC; | |
244 | } else if (gpio_source == 1) { | |
060d4c33 JN |
245 | DRM_DEBUG_KMS("SC gpio not supported\n"); |
246 | return; | |
1d96a4a8 JN |
247 | } else { |
248 | DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source); | |
515d07de | 249 | return; |
1d96a4a8 | 250 | } |
96afef1d JN |
251 | } |
252 | ||
b13d8e28 JN |
253 | pconf0 = VLV_GPIO_PCONF0(map->base_offset); |
254 | padval = VLV_GPIO_PAD_VAL(map->base_offset); | |
2ab8b458 | 255 | |
221c7862 | 256 | vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO)); |
b13d8e28 | 257 | if (!map->init) { |
2ab8b458 | 258 | /* FIXME: remove constant below */ |
b0c91cd0 | 259 | vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00); |
b13d8e28 | 260 | map->init = true; |
2ab8b458 SK |
261 | } |
262 | ||
515d07de JN |
263 | tmp = 0x4 | value; |
264 | vlv_iosf_sb_write(dev_priv, port, padval, tmp); | |
221c7862 | 265 | vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO)); |
515d07de JN |
266 | } |
267 | ||
a0a6d4ff JN |
268 | static void chv_exec_gpio(struct drm_i915_private *dev_priv, |
269 | u8 gpio_source, u8 gpio_index, bool value) | |
270 | { | |
271 | u16 cfg0, cfg1; | |
272 | u16 family_num; | |
273 | u8 port; | |
274 | ||
275 | if (dev_priv->vbt.dsi.seq_version >= 3) { | |
276 | if (gpio_index >= CHV_GPIO_IDX_START_SE) { | |
277 | /* XXX: it's unclear whether 255->57 is part of SE. */ | |
278 | gpio_index -= CHV_GPIO_IDX_START_SE; | |
279 | port = CHV_IOSF_PORT_GPIO_SE; | |
280 | } else if (gpio_index >= CHV_GPIO_IDX_START_SW) { | |
281 | gpio_index -= CHV_GPIO_IDX_START_SW; | |
282 | port = CHV_IOSF_PORT_GPIO_SW; | |
283 | } else if (gpio_index >= CHV_GPIO_IDX_START_E) { | |
284 | gpio_index -= CHV_GPIO_IDX_START_E; | |
285 | port = CHV_IOSF_PORT_GPIO_E; | |
286 | } else { | |
287 | port = CHV_IOSF_PORT_GPIO_N; | |
288 | } | |
289 | } else { | |
290 | /* XXX: The spec is unclear about CHV GPIO on seq v2 */ | |
291 | if (gpio_source != 0) { | |
292 | DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source); | |
293 | return; | |
294 | } | |
295 | ||
296 | if (gpio_index >= CHV_GPIO_IDX_START_E) { | |
297 | DRM_DEBUG_KMS("invalid gpio index %u for GPIO N\n", | |
298 | gpio_index); | |
299 | return; | |
300 | } | |
301 | ||
302 | port = CHV_IOSF_PORT_GPIO_N; | |
303 | } | |
304 | ||
305 | family_num = gpio_index / CHV_VBT_MAX_PINS_PER_FMLY; | |
306 | gpio_index = gpio_index % CHV_VBT_MAX_PINS_PER_FMLY; | |
307 | ||
308 | cfg0 = CHV_GPIO_PAD_CFG0(family_num, gpio_index); | |
309 | cfg1 = CHV_GPIO_PAD_CFG1(family_num, gpio_index); | |
310 | ||
221c7862 | 311 | vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO)); |
a0a6d4ff JN |
312 | vlv_iosf_sb_write(dev_priv, port, cfg1, 0); |
313 | vlv_iosf_sb_write(dev_priv, port, cfg0, | |
b2b45fcd HG |
314 | CHV_GPIO_GPIOEN | CHV_GPIO_GPIOCFG_GPO | |
315 | CHV_GPIO_GPIOTXSTATE(value)); | |
221c7862 | 316 | vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO)); |
a0a6d4ff JN |
317 | } |
318 | ||
213e08ad JN |
319 | static void bxt_exec_gpio(struct drm_i915_private *dev_priv, |
320 | u8 gpio_source, u8 gpio_index, bool value) | |
321 | { | |
322 | /* XXX: this table is a quick ugly hack. */ | |
323 | static struct gpio_desc *bxt_gpio_table[U8_MAX + 1]; | |
324 | struct gpio_desc *gpio_desc = bxt_gpio_table[gpio_index]; | |
325 | ||
326 | if (!gpio_desc) { | |
327 | gpio_desc = devm_gpiod_get_index(dev_priv->drm.dev, | |
cd55a1fb | 328 | NULL, gpio_index, |
213e08ad JN |
329 | value ? GPIOD_OUT_LOW : |
330 | GPIOD_OUT_HIGH); | |
331 | ||
332 | if (IS_ERR_OR_NULL(gpio_desc)) { | |
333 | DRM_ERROR("GPIO index %u request failed (%ld)\n", | |
334 | gpio_index, PTR_ERR(gpio_desc)); | |
335 | return; | |
336 | } | |
337 | ||
338 | bxt_gpio_table[gpio_index] = gpio_desc; | |
339 | } | |
340 | ||
341 | gpiod_set_value(gpio_desc, value); | |
342 | } | |
343 | ||
690c318e JN |
344 | static void icl_exec_gpio(struct drm_i915_private *dev_priv, |
345 | u8 gpio_source, u8 gpio_index, bool value) | |
346 | { | |
347 | DRM_DEBUG_KMS("Skipping ICL GPIO element execution\n"); | |
348 | } | |
349 | ||
515d07de JN |
350 | static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) |
351 | { | |
352 | struct drm_device *dev = intel_dsi->base.base.dev; | |
fac5e23e | 353 | struct drm_i915_private *dev_priv = to_i915(dev); |
213e08ad | 354 | u8 gpio_source, gpio_index = 0, gpio_number; |
515d07de JN |
355 | bool value; |
356 | ||
0b9407c3 JN |
357 | DRM_DEBUG_KMS("\n"); |
358 | ||
515d07de | 359 | if (dev_priv->vbt.dsi.seq_version >= 3) |
213e08ad | 360 | gpio_index = *data++; |
515d07de | 361 | |
213e08ad | 362 | gpio_number = *data++; |
515d07de JN |
363 | |
364 | /* gpio source in sequence v2 only */ | |
365 | if (dev_priv->vbt.dsi.seq_version == 2) | |
366 | gpio_source = (*data >> 1) & 3; | |
367 | else | |
368 | gpio_source = 0; | |
2ab8b458 SK |
369 | |
370 | /* pull up/down */ | |
515d07de JN |
371 | value = *data++ & 1; |
372 | ||
2dd24a9c | 373 | if (INTEL_GEN(dev_priv) >= 11) |
690c318e JN |
374 | icl_exec_gpio(dev_priv, gpio_source, gpio_index, value); |
375 | else if (IS_VALLEYVIEW(dev_priv)) | |
213e08ad | 376 | vlv_exec_gpio(dev_priv, gpio_source, gpio_number, value); |
a0a6d4ff | 377 | else if (IS_CHERRYVIEW(dev_priv)) |
213e08ad | 378 | chv_exec_gpio(dev_priv, gpio_source, gpio_number, value); |
515d07de | 379 | else |
213e08ad | 380 | bxt_exec_gpio(dev_priv, gpio_source, gpio_index, value); |
2ab8b458 SK |
381 | |
382 | return data; | |
383 | } | |
384 | ||
0b9407c3 | 385 | static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) |
29bbdcb0 | 386 | { |
0b9407c3 JN |
387 | DRM_DEBUG_KMS("Skipping I2C element execution\n"); |
388 | ||
29bbdcb0 JN |
389 | return data + *(data + 6) + 7; |
390 | } | |
391 | ||
044aad65 JN |
392 | static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data) |
393 | { | |
394 | DRM_DEBUG_KMS("Skipping SPI element execution\n"); | |
395 | ||
396 | return data + *(data + 5) + 6; | |
397 | } | |
398 | ||
399 | static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data) | |
400 | { | |
4e8052af HG |
401 | #ifdef CONFIG_PMIC_OPREGION |
402 | u32 value, mask, reg_address; | |
403 | u16 i2c_address; | |
404 | int ret; | |
405 | ||
406 | /* byte 0 aka PMIC Flag is reserved */ | |
407 | i2c_address = get_unaligned_le16(data + 1); | |
408 | reg_address = get_unaligned_le32(data + 3); | |
409 | value = get_unaligned_le32(data + 7); | |
410 | mask = get_unaligned_le32(data + 11); | |
411 | ||
412 | ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_address, | |
413 | reg_address, | |
414 | value, mask); | |
415 | if (ret) | |
416 | DRM_ERROR("%s failed, error: %d\n", __func__, ret); | |
417 | #else | |
418 | DRM_ERROR("Your hardware requires CONFIG_PMIC_OPREGION and it is not set\n"); | |
419 | #endif | |
044aad65 JN |
420 | |
421 | return data + 15; | |
422 | } | |
423 | ||
5b48ca0f JN |
424 | typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, |
425 | const u8 *data); | |
2ab8b458 | 426 | static const fn_mipi_elem_exec exec_elem[] = { |
28c72840 JN |
427 | [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, |
428 | [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, | |
429 | [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, | |
0b9407c3 | 430 | [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, |
044aad65 JN |
431 | [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi, |
432 | [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic, | |
2ab8b458 SK |
433 | }; |
434 | ||
435 | /* | |
436 | * MIPI Sequence from VBT #53 parsing logic | |
437 | * We have already separated each seqence during bios parsing | |
438 | * Following is generic execution function for any sequence | |
439 | */ | |
440 | ||
441 | static const char * const seq_name[] = { | |
2b8208ac | 442 | [MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET", |
5cda0d20 JN |
443 | [MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP", |
444 | [MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON", | |
445 | [MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF", | |
2b8208ac | 446 | [MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET", |
bc95ce7f JN |
447 | [MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON", |
448 | [MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF", | |
449 | [MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON", | |
450 | [MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF", | |
451 | [MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON", | |
452 | [MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF", | |
2ab8b458 SK |
453 | }; |
454 | ||
5cda0d20 JN |
455 | static const char *sequence_name(enum mipi_seq seq_id) |
456 | { | |
457 | if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id]) | |
458 | return seq_name[seq_id]; | |
459 | else | |
460 | return "(unknown)"; | |
461 | } | |
462 | ||
b0dd6887 | 463 | void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi, |
18a00095 | 464 | enum mipi_seq seq_id) |
2ab8b458 | 465 | { |
2a33d934 | 466 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); |
c67fed85 | 467 | const u8 *data; |
2ab8b458 | 468 | fn_mipi_elem_exec mipi_elem_exec; |
2ab8b458 | 469 | |
c67fed85 | 470 | if (WARN_ON(seq_id >= ARRAY_SIZE(dev_priv->vbt.dsi.sequence))) |
2ab8b458 SK |
471 | return; |
472 | ||
c67fed85 | 473 | data = dev_priv->vbt.dsi.sequence[seq_id]; |
f7d3c970 | 474 | if (!data) |
c67fed85 | 475 | return; |
2ab8b458 | 476 | |
c67fed85 JN |
477 | WARN_ON(*data != seq_id); |
478 | ||
479 | DRM_DEBUG_KMS("Starting MIPI sequence %d - %s\n", | |
480 | seq_id, sequence_name(seq_id)); | |
481 | ||
482 | /* Skip Sequence Byte. */ | |
2ab8b458 SK |
483 | data++; |
484 | ||
2a33d934 JN |
485 | /* Skip Size of Sequence. */ |
486 | if (dev_priv->vbt.dsi.seq_version >= 3) | |
487 | data += 4; | |
488 | ||
2ab8b458 | 489 | while (1) { |
28c72840 | 490 | u8 operation_byte = *data++; |
40795782 JN |
491 | u8 operation_size = 0; |
492 | ||
493 | if (operation_byte == MIPI_SEQ_ELEM_END) | |
494 | break; | |
495 | ||
496 | if (operation_byte < ARRAY_SIZE(exec_elem)) | |
497 | mipi_elem_exec = exec_elem[operation_byte]; | |
498 | else | |
499 | mipi_elem_exec = NULL; | |
500 | ||
501 | /* Size of Operation. */ | |
502 | if (dev_priv->vbt.dsi.seq_version >= 3) | |
503 | operation_size = *data++; | |
504 | ||
505 | if (mipi_elem_exec) { | |
8e4f768c JN |
506 | const u8 *next = data + operation_size; |
507 | ||
40795782 | 508 | data = mipi_elem_exec(intel_dsi, data); |
8e4f768c JN |
509 | |
510 | /* Consistency check if we have size. */ | |
511 | if (operation_size && data != next) { | |
512 | DRM_ERROR("Inconsistent operation size\n"); | |
513 | return; | |
514 | } | |
40795782 JN |
515 | } else if (operation_size) { |
516 | /* We have size, skip. */ | |
517 | DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", | |
518 | operation_byte); | |
519 | data += operation_size; | |
520 | } else { | |
521 | /* No size, can't skip without parsing. */ | |
28c72840 JN |
522 | DRM_ERROR("Unsupported MIPI operation byte %u\n", |
523 | operation_byte); | |
2ab8b458 SK |
524 | return; |
525 | } | |
2ab8b458 SK |
526 | } |
527 | } | |
528 | ||
b687c198 MC |
529 | void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec) |
530 | { | |
531 | struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); | |
532 | ||
533 | /* For v3 VBTs in vid-mode the delays are part of the VBT sequences */ | |
534 | if (is_vid_mode(intel_dsi) && dev_priv->vbt.dsi.seq_version >= 3) | |
535 | return; | |
536 | ||
537 | msleep(msec); | |
538 | } | |
539 | ||
e72cce53 MC |
540 | #define ICL_PREPARE_CNT_MAX 0x7 |
541 | #define ICL_CLK_ZERO_CNT_MAX 0xf | |
542 | #define ICL_TRAIL_CNT_MAX 0x7 | |
543 | #define ICL_TCLK_PRE_CNT_MAX 0x3 | |
544 | #define ICL_TCLK_POST_CNT_MAX 0x7 | |
545 | #define ICL_HS_ZERO_CNT_MAX 0xf | |
546 | #define ICL_EXIT_ZERO_CNT_MAX 0x7 | |
547 | ||
548 | static void icl_dphy_param_init(struct intel_dsi *intel_dsi) | |
549 | { | |
550 | struct drm_device *dev = intel_dsi->base.base.dev; | |
551 | struct drm_i915_private *dev_priv = to_i915(dev); | |
552 | struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; | |
553 | u32 tlpx_ns; | |
554 | u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt; | |
555 | u32 ths_prepare_ns, tclk_trail_ns; | |
556 | u32 hs_zero_cnt; | |
557 | u32 tclk_pre_cnt, tclk_post_cnt; | |
558 | ||
559 | tlpx_ns = intel_dsi_tlpx_ns(intel_dsi); | |
560 | ||
561 | tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail); | |
562 | ths_prepare_ns = max(mipi_config->ths_prepare, | |
563 | mipi_config->tclk_prepare); | |
564 | ||
565 | /* | |
566 | * prepare cnt in escape clocks | |
567 | * this field represents a hexadecimal value with a precision | |
568 | * of 1.2 – i.e. the most significant bit is the integer | |
569 | * and the least significant 2 bits are fraction bits. | |
570 | * so, the field can represent a range of 0.25 to 1.75 | |
571 | */ | |
572 | prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns); | |
573 | if (prepare_cnt > ICL_PREPARE_CNT_MAX) { | |
574 | DRM_DEBUG_KMS("prepare_cnt out of range (%d)\n", prepare_cnt); | |
575 | prepare_cnt = ICL_PREPARE_CNT_MAX; | |
576 | } | |
577 | ||
578 | /* clk zero count in escape clocks */ | |
579 | clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero - | |
580 | ths_prepare_ns, tlpx_ns); | |
581 | if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) { | |
582 | DRM_DEBUG_KMS("clk_zero_cnt out of range (%d)\n", clk_zero_cnt); | |
583 | clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX; | |
584 | } | |
585 | ||
586 | /* trail cnt in escape clocks*/ | |
587 | trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns); | |
588 | if (trail_cnt > ICL_TRAIL_CNT_MAX) { | |
589 | DRM_DEBUG_KMS("trail_cnt out of range (%d)\n", trail_cnt); | |
590 | trail_cnt = ICL_TRAIL_CNT_MAX; | |
591 | } | |
592 | ||
593 | /* tclk pre count in escape clocks */ | |
594 | tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns); | |
595 | if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) { | |
596 | DRM_DEBUG_KMS("tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt); | |
597 | tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX; | |
598 | } | |
599 | ||
600 | /* tclk post count in escape clocks */ | |
601 | tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns); | |
602 | if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) { | |
603 | DRM_DEBUG_KMS("tclk_post_cnt out of range (%d)\n", tclk_post_cnt); | |
604 | tclk_post_cnt = ICL_TCLK_POST_CNT_MAX; | |
605 | } | |
606 | ||
607 | /* hs zero cnt in escape clocks */ | |
608 | hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero - | |
609 | ths_prepare_ns, tlpx_ns); | |
610 | if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) { | |
611 | DRM_DEBUG_KMS("hs_zero_cnt out of range (%d)\n", hs_zero_cnt); | |
612 | hs_zero_cnt = ICL_HS_ZERO_CNT_MAX; | |
613 | } | |
614 | ||
615 | /* hs exit zero cnt in escape clocks */ | |
616 | exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns); | |
617 | if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) { | |
618 | DRM_DEBUG_KMS("exit_zero_cnt out of range (%d)\n", exit_zero_cnt); | |
619 | exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX; | |
620 | } | |
621 | ||
622 | /* clock lane dphy timings */ | |
623 | intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE | | |
624 | CLK_PREPARE(prepare_cnt) | | |
625 | CLK_ZERO_OVERRIDE | | |
626 | CLK_ZERO(clk_zero_cnt) | | |
627 | CLK_PRE_OVERRIDE | | |
628 | CLK_PRE(tclk_pre_cnt) | | |
629 | CLK_POST_OVERRIDE | | |
630 | CLK_POST(tclk_post_cnt) | | |
631 | CLK_TRAIL_OVERRIDE | | |
632 | CLK_TRAIL(trail_cnt)); | |
633 | ||
634 | /* data lanes dphy timings */ | |
635 | intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE | | |
636 | HS_PREPARE(prepare_cnt) | | |
637 | HS_ZERO_OVERRIDE | | |
638 | HS_ZERO(hs_zero_cnt) | | |
639 | HS_TRAIL_OVERRIDE | | |
640 | HS_TRAIL(trail_cnt) | | |
641 | HS_EXIT_OVERRIDE | | |
642 | HS_EXIT(exit_zero_cnt)); | |
643 | } | |
644 | ||
67551a70 | 645 | static void vlv_dphy_param_init(struct intel_dsi *intel_dsi) |
2ab8b458 | 646 | { |
2ab8b458 | 647 | struct drm_device *dev = intel_dsi->base.base.dev; |
fac5e23e | 648 | struct drm_i915_private *dev_priv = to_i915(dev); |
2ab8b458 | 649 | struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; |
2bf3f59d | 650 | u32 tlpx_ns, extra_byte_count, tlpx_ui; |
2ab8b458 SK |
651 | u32 ui_num, ui_den; |
652 | u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt; | |
653 | u32 ths_prepare_ns, tclk_trail_ns; | |
654 | u32 tclk_prepare_clkzero, ths_prepare_hszero; | |
655 | u32 lp_to_hs_switch, hs_to_lp_switch; | |
39299838 | 656 | u32 mul; |
7f0c8605 | 657 | |
9ec9a87b | 658 | tlpx_ns = intel_dsi_tlpx_ns(intel_dsi); |
2ab8b458 SK |
659 | |
660 | switch (intel_dsi->lane_count) { | |
661 | case 1: | |
662 | case 2: | |
663 | extra_byte_count = 2; | |
664 | break; | |
665 | case 3: | |
666 | extra_byte_count = 4; | |
667 | break; | |
668 | case 4: | |
669 | default: | |
670 | extra_byte_count = 3; | |
671 | break; | |
672 | } | |
673 | ||
2ab8b458 SK |
674 | /* in Kbps */ |
675 | ui_num = NS_KHZ_RATIO; | |
2bf3f59d | 676 | ui_den = intel_dsi_bitrate(intel_dsi); |
2ab8b458 SK |
677 | |
678 | tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero; | |
679 | ths_prepare_hszero = mipi_config->ths_prepare_hszero; | |
680 | ||
681 | /* | |
682 | * B060 | |
683 | * LP byte clock = TLPX/ (8UI) | |
684 | */ | |
685 | intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num); | |
686 | ||
39299838 D |
687 | /* DDR clock period = 2 * UI |
688 | * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ) | |
689 | * UI(nsec) = 10^6 / bitrate | |
690 | * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate | |
691 | * DDR clock count = ns_value / DDR clock period | |
2ab8b458 | 692 | * |
39299838 D |
693 | * For GEMINILAKE dphy_param_reg will be programmed in terms of |
694 | * HS byte clock count for other platform in HS ddr clock count | |
2ab8b458 | 695 | */ |
39299838 | 696 | mul = IS_GEMINILAKE(dev_priv) ? 8 : 2; |
b5fbcd98 SK |
697 | ths_prepare_ns = max(mipi_config->ths_prepare, |
698 | mipi_config->tclk_prepare); | |
39299838 D |
699 | |
700 | /* prepare count */ | |
701 | prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul); | |
2ab8b458 | 702 | |
e307126a JN |
703 | if (prepare_cnt > PREPARE_CNT_MAX) { |
704 | DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt); | |
705 | prepare_cnt = PREPARE_CNT_MAX; | |
706 | } | |
707 | ||
2ab8b458 SK |
708 | /* exit zero count */ |
709 | exit_zero_cnt = DIV_ROUND_UP( | |
710 | (ths_prepare_hszero - ths_prepare_ns) * ui_den, | |
39299838 | 711 | ui_num * mul |
2ab8b458 SK |
712 | ); |
713 | ||
714 | /* | |
ebe69dd3 | 715 | * Exit zero is unified val ths_zero and ths_exit |
2ab8b458 SK |
716 | * minimum value for ths_exit = 110ns |
717 | * min (exit_zero_cnt * 2) = 110/UI | |
718 | * exit_zero_cnt = 55/UI | |
719 | */ | |
ebe69dd3 CW |
720 | if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num) |
721 | exit_zero_cnt += 1; | |
2ab8b458 | 722 | |
e307126a JN |
723 | if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) { |
724 | DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt); | |
725 | exit_zero_cnt = EXIT_ZERO_CNT_MAX; | |
726 | } | |
727 | ||
2ab8b458 SK |
728 | /* clk zero count */ |
729 | clk_zero_cnt = DIV_ROUND_UP( | |
39299838 D |
730 | (tclk_prepare_clkzero - ths_prepare_ns) |
731 | * ui_den, ui_num * mul); | |
2ab8b458 | 732 | |
e307126a JN |
733 | if (clk_zero_cnt > CLK_ZERO_CNT_MAX) { |
734 | DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt); | |
735 | clk_zero_cnt = CLK_ZERO_CNT_MAX; | |
736 | } | |
737 | ||
2ab8b458 SK |
738 | /* trail count */ |
739 | tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail); | |
39299838 | 740 | trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul); |
2ab8b458 | 741 | |
e307126a JN |
742 | if (trail_cnt > TRAIL_CNT_MAX) { |
743 | DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt); | |
2ab8b458 | 744 | trail_cnt = TRAIL_CNT_MAX; |
e307126a | 745 | } |
2ab8b458 SK |
746 | |
747 | /* B080 */ | |
748 | intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 | | |
749 | clk_zero_cnt << 8 | prepare_cnt; | |
750 | ||
751 | /* | |
1fdd783e MC |
752 | * LP to HS switch count = 4TLPX + PREP_COUNT * mul + EXIT_ZERO_COUNT * |
753 | * mul + 10UI + Extra Byte Count | |
2ab8b458 SK |
754 | * |
755 | * HS to LP switch count = THS-TRAIL + 2TLPX + Extra Byte Count | |
756 | * Extra Byte Count is calculated according to number of lanes. | |
757 | * High Low Switch Count is the Max of LP to HS and | |
758 | * HS to LP switch count | |
759 | * | |
760 | */ | |
761 | tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num); | |
762 | ||
763 | /* B044 */ | |
764 | /* FIXME: | |
765 | * The comment above does not match with the code */ | |
1fdd783e MC |
766 | lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul + |
767 | exit_zero_cnt * mul + 10, 8); | |
2ab8b458 SK |
768 | |
769 | hs_to_lp_switch = DIV_ROUND_UP(mipi_config->ths_trail + 2 * tlpx_ui, 8); | |
770 | ||
771 | intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch); | |
772 | intel_dsi->hs_to_lp_count += extra_byte_count; | |
773 | ||
774 | /* B088 */ | |
775 | /* LP -> HS for clock lanes | |
776 | * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero + | |
777 | * extra byte count | |
778 | * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt * | |
779 | * 2(in UI) + extra byte count | |
780 | * In byteclks = (4TLPX + prepare_cnt * 2 + clk_zero_cnt *2 (in UI)) / | |
781 | * 8 + extra byte count | |
782 | */ | |
783 | intel_dsi->clk_lp_to_hs_count = | |
784 | DIV_ROUND_UP( | |
785 | 4 * tlpx_ui + prepare_cnt * 2 + | |
786 | clk_zero_cnt * 2, | |
787 | 8); | |
788 | ||
789 | intel_dsi->clk_lp_to_hs_count += extra_byte_count; | |
790 | ||
791 | /* HS->LP for Clock Lanes | |
792 | * Low Power clock synchronisations + 1Tx byteclk + tclk_trail + | |
793 | * Extra byte count | |
794 | * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count | |
795 | * In byteclks = (2*TLpx(in UI) + trail_count*2 +8)(in UI)/8 + | |
796 | * Extra byte count | |
797 | */ | |
798 | intel_dsi->clk_hs_to_lp_count = | |
799 | DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8, | |
800 | 8); | |
801 | intel_dsi->clk_hs_to_lp_count += extra_byte_count; | |
67551a70 JN |
802 | } |
803 | ||
804 | bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) | |
805 | { | |
806 | struct drm_device *dev = intel_dsi->base.base.dev; | |
807 | struct drm_i915_private *dev_priv = to_i915(dev); | |
808 | struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; | |
809 | struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps; | |
810 | struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode; | |
811 | u16 burst_mode_ratio; | |
812 | enum port port; | |
813 | ||
814 | DRM_DEBUG_KMS("\n"); | |
815 | ||
816 | intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1; | |
817 | intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0; | |
818 | intel_dsi->lane_count = mipi_config->lane_cnt + 1; | |
819 | intel_dsi->pixel_format = | |
820 | pixel_format_from_register_bits( | |
821 | mipi_config->videomode_color_format << 7); | |
822 | ||
823 | intel_dsi->dual_link = mipi_config->dual_link; | |
824 | intel_dsi->pixel_overlap = mipi_config->pixel_overlap; | |
825 | intel_dsi->operation_mode = mipi_config->is_cmd_mode; | |
826 | intel_dsi->video_mode_format = mipi_config->video_transfer_mode; | |
827 | intel_dsi->escape_clk_div = mipi_config->byte_clk_sel; | |
828 | intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout; | |
5a4712f4 | 829 | intel_dsi->hs_tx_timeout = mipi_config->hs_tx_timeout; |
67551a70 JN |
830 | intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout; |
831 | intel_dsi->rst_timer_val = mipi_config->device_reset_timer; | |
832 | intel_dsi->init_count = mipi_config->master_init_timer; | |
833 | intel_dsi->bw_timer = mipi_config->dbi_bw_timer; | |
834 | intel_dsi->video_frmt_cfg_bits = | |
835 | mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0; | |
d364dc66 | 836 | intel_dsi->bgr_enabled = mipi_config->rgb_flip; |
67551a70 JN |
837 | |
838 | /* Starting point, adjusted depending on dual link and burst mode */ | |
839 | intel_dsi->pclk = mode->clock; | |
840 | ||
841 | /* In dual link mode each port needs half of pixel clock */ | |
842 | if (intel_dsi->dual_link) { | |
843 | intel_dsi->pclk /= 2; | |
844 | ||
845 | /* we can enable pixel_overlap if needed by panel. In this | |
846 | * case we need to increase the pixelclock for extra pixels | |
847 | */ | |
848 | if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { | |
849 | intel_dsi->pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap * 60, 1000); | |
850 | } | |
851 | } | |
852 | ||
853 | /* Burst Mode Ratio | |
854 | * Target ddr frequency from VBT / non burst ddr freq | |
855 | * multiply by 100 to preserve remainder | |
856 | */ | |
857 | if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) { | |
858 | if (mipi_config->target_burst_mode_freq) { | |
859 | u32 bitrate = intel_dsi_bitrate(intel_dsi); | |
860 | ||
2c1c5525 HG |
861 | /* |
862 | * Sometimes the VBT contains a slightly lower clock, | |
863 | * then the bitrate we have calculated, in this case | |
864 | * just replace it with the calculated bitrate. | |
865 | */ | |
866 | if (mipi_config->target_burst_mode_freq < bitrate && | |
867 | intel_fuzzy_clock_check( | |
868 | mipi_config->target_burst_mode_freq, | |
869 | bitrate)) | |
870 | mipi_config->target_burst_mode_freq = bitrate; | |
871 | ||
67551a70 JN |
872 | if (mipi_config->target_burst_mode_freq < bitrate) { |
873 | DRM_ERROR("Burst mode freq is less than computed\n"); | |
874 | return false; | |
875 | } | |
876 | ||
877 | burst_mode_ratio = DIV_ROUND_UP( | |
878 | mipi_config->target_burst_mode_freq * 100, | |
879 | bitrate); | |
880 | ||
881 | intel_dsi->pclk = DIV_ROUND_UP(intel_dsi->pclk * burst_mode_ratio, 100); | |
882 | } else { | |
883 | DRM_ERROR("Burst mode target is not set\n"); | |
884 | return false; | |
885 | } | |
886 | } else | |
887 | burst_mode_ratio = 100; | |
888 | ||
889 | intel_dsi->burst_mode_ratio = burst_mode_ratio; | |
890 | ||
2dd24a9c | 891 | if (INTEL_GEN(dev_priv) >= 11) |
e72cce53 MC |
892 | icl_dphy_param_init(intel_dsi); |
893 | else | |
894 | vlv_dphy_param_init(intel_dsi); | |
2ab8b458 | 895 | |
64d83e34 VS |
896 | DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk); |
897 | DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap); | |
898 | DRM_DEBUG_KMS("Lane count %d\n", intel_dsi->lane_count); | |
899 | DRM_DEBUG_KMS("DPHY param reg 0x%x\n", intel_dsi->dphy_reg); | |
900 | DRM_DEBUG_KMS("Video mode format %s\n", | |
901 | intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE ? | |
902 | "non-burst with sync pulse" : | |
903 | intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS ? | |
904 | "non-burst with sync events" : | |
905 | intel_dsi->video_mode_format == VIDEO_MODE_BURST ? | |
906 | "burst" : "<unknown>"); | |
907 | DRM_DEBUG_KMS("Burst mode ratio %d\n", intel_dsi->burst_mode_ratio); | |
908 | DRM_DEBUG_KMS("Reset timer %d\n", intel_dsi->rst_timer_val); | |
08c4d7fc TU |
909 | DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt)); |
910 | DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop)); | |
2ab8b458 | 911 | DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video"); |
a9da9bce GS |
912 | if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) |
913 | DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n"); | |
914 | else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT) | |
915 | DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n"); | |
916 | else | |
917 | DRM_DEBUG_KMS("Dual link: NONE\n"); | |
2ab8b458 SK |
918 | DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format); |
919 | DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div); | |
920 | DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout); | |
921 | DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val); | |
922 | DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count); | |
923 | DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count); | |
924 | DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk); | |
925 | DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer); | |
926 | DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count); | |
927 | DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count); | |
928 | DRM_DEBUG_KMS("BTA %s\n", | |
08c4d7fc | 929 | enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA))); |
2ab8b458 SK |
930 | |
931 | /* delays in VBT are in unit of 100us, so need to convert | |
932 | * here in ms | |
933 | * Delay (100us) * 100 /1000 = Delay / 10 (ms) */ | |
934 | intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10; | |
935 | intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10; | |
936 | intel_dsi->panel_on_delay = pps->panel_on_delay / 10; | |
937 | intel_dsi->panel_off_delay = pps->panel_off_delay / 10; | |
938 | intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10; | |
939 | ||
759d10c2 JN |
940 | /* a regular driver would get the device in probe */ |
941 | for_each_dsi_port(port, intel_dsi->ports) { | |
942 | mipi_dsi_attach(intel_dsi->dsi_hosts[port]->device); | |
943 | } | |
944 | ||
3f751d65 | 945 | return true; |
2ab8b458 | 946 | } |