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 | |
27 | #include <linux/gpio/consumer.h> |
28 | #include <linux/gpio/machine.h> |
29 | #include <linux/mfd/intel_soc_pmic.h> |
30 | #include <linux/pinctrl/consumer.h> |
31 | #include <linux/pinctrl/machine.h> |
32 | #include <linux/slab.h> |
33 | #include <linux/string_helpers.h> |
34 | |
35 | #include <asm/unaligned.h> |
36 | |
37 | #include <drm/drm_crtc.h> |
38 | #include <drm/drm_edid.h> |
39 | |
40 | #include <video/mipi_display.h> |
41 | |
42 | #include "i915_drv.h" |
43 | #include "i915_reg.h" |
44 | #include "intel_de.h" |
45 | #include "intel_display_types.h" |
46 | #include "intel_dsi.h" |
47 | #include "intel_dsi_vbt.h" |
48 | #include "intel_gmbus_regs.h" |
49 | #include "intel_pps_regs.h" |
50 | #include "vlv_dsi.h" |
51 | #include "vlv_dsi_regs.h" |
52 | #include "vlv_sideband.h" |
53 | |
54 | #define MIPI_TRANSFER_MODE_SHIFT 0 |
55 | #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 |
56 | #define MIPI_PORT_SHIFT 3 |
57 | |
58 | struct i2c_adapter_lookup { |
59 | u16 slave_addr; |
60 | struct intel_dsi *intel_dsi; |
61 | acpi_handle dev_handle; |
62 | }; |
63 | |
64 | #define CHV_GPIO_IDX_START_N 0 |
65 | #define CHV_GPIO_IDX_START_E 73 |
66 | #define CHV_GPIO_IDX_START_SW 100 |
67 | #define CHV_GPIO_IDX_START_SE 198 |
68 | |
69 | /* ICL DSI Display GPIO Pins */ |
70 | #define ICL_GPIO_DDSP_HPD_A 0 |
71 | #define ICL_GPIO_L_VDDEN_1 1 |
72 | #define ICL_GPIO_L_BKLTEN_1 2 |
73 | #define ICL_GPIO_DDPA_CTRLCLK_1 3 |
74 | #define ICL_GPIO_DDPA_CTRLDATA_1 4 |
75 | #define ICL_GPIO_DDSP_HPD_B 5 |
76 | #define ICL_GPIO_L_VDDEN_2 6 |
77 | #define ICL_GPIO_L_BKLTEN_2 7 |
78 | #define ICL_GPIO_DDPA_CTRLCLK_2 8 |
79 | #define ICL_GPIO_DDPA_CTRLDATA_2 9 |
80 | |
81 | static enum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi, |
82 | u8 seq_port) |
83 | { |
84 | /* |
85 | * If single link DSI is being used on any port, the VBT sequence block |
86 | * send packet apparently always has 0 for the port. Just use the port |
87 | * we have configured, and ignore the sequence block port. |
88 | */ |
89 | if (hweight8(intel_dsi->ports) == 1) |
90 | return ffs(intel_dsi->ports) - 1; |
91 | |
92 | if (seq_port) { |
93 | if (intel_dsi->ports & BIT(PORT_B)) |
94 | return PORT_B; |
95 | if (intel_dsi->ports & BIT(PORT_C)) |
96 | return PORT_C; |
97 | } |
98 | |
99 | return PORT_A; |
100 | } |
101 | |
102 | static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, |
103 | const u8 *data) |
104 | { |
105 | struct drm_i915_private *dev_priv = to_i915(dev: intel_dsi->base.base.dev); |
106 | struct mipi_dsi_device *dsi_device; |
107 | u8 type, flags, seq_port; |
108 | u16 len; |
109 | enum port port; |
110 | |
111 | drm_dbg_kms(&dev_priv->drm, "\n" ); |
112 | |
113 | flags = *data++; |
114 | type = *data++; |
115 | |
116 | len = *((u16 *) data); |
117 | data += 2; |
118 | |
119 | seq_port = (flags >> MIPI_PORT_SHIFT) & 3; |
120 | |
121 | port = intel_dsi_seq_port_to_port(intel_dsi, seq_port); |
122 | |
123 | if (drm_WARN_ON(&dev_priv->drm, !intel_dsi->dsi_hosts[port])) |
124 | goto out; |
125 | |
126 | dsi_device = intel_dsi->dsi_hosts[port]->device; |
127 | if (!dsi_device) { |
128 | drm_dbg_kms(&dev_priv->drm, "no dsi device for port %c\n" , |
129 | port_name(port)); |
130 | goto out; |
131 | } |
132 | |
133 | if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1) |
134 | dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM; |
135 | else |
136 | dsi_device->mode_flags |= MIPI_DSI_MODE_LPM; |
137 | |
138 | dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3; |
139 | |
140 | switch (type) { |
141 | case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: |
142 | mipi_dsi_generic_write(dsi: dsi_device, NULL, size: 0); |
143 | break; |
144 | case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: |
145 | mipi_dsi_generic_write(dsi: dsi_device, payload: data, size: 1); |
146 | break; |
147 | case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: |
148 | mipi_dsi_generic_write(dsi: dsi_device, payload: data, size: 2); |
149 | break; |
150 | case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: |
151 | case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: |
152 | case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: |
153 | drm_dbg(&dev_priv->drm, |
154 | "Generic Read not yet implemented or used\n" ); |
155 | break; |
156 | case MIPI_DSI_GENERIC_LONG_WRITE: |
157 | mipi_dsi_generic_write(dsi: dsi_device, payload: data, size: len); |
158 | break; |
159 | case MIPI_DSI_DCS_SHORT_WRITE: |
160 | mipi_dsi_dcs_write_buffer(dsi: dsi_device, data, len: 1); |
161 | break; |
162 | case MIPI_DSI_DCS_SHORT_WRITE_PARAM: |
163 | mipi_dsi_dcs_write_buffer(dsi: dsi_device, data, len: 2); |
164 | break; |
165 | case MIPI_DSI_DCS_READ: |
166 | drm_dbg(&dev_priv->drm, |
167 | "DCS Read not yet implemented or used\n" ); |
168 | break; |
169 | case MIPI_DSI_DCS_LONG_WRITE: |
170 | mipi_dsi_dcs_write_buffer(dsi: dsi_device, data, len); |
171 | break; |
172 | } |
173 | |
174 | if (DISPLAY_VER(dev_priv) < 11) |
175 | vlv_dsi_wait_for_fifo_empty(intel_dsi, port); |
176 | |
177 | out: |
178 | data += len; |
179 | |
180 | return data; |
181 | } |
182 | |
183 | static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) |
184 | { |
185 | struct drm_i915_private *i915 = to_i915(dev: intel_dsi->base.base.dev); |
186 | u32 delay = *((const u32 *) data); |
187 | |
188 | drm_dbg_kms(&i915->drm, "%d usecs\n" , delay); |
189 | |
190 | usleep_range(min: delay, max: delay + 10); |
191 | data += 4; |
192 | |
193 | return data; |
194 | } |
195 | |
196 | static void soc_gpio_set_value(struct intel_connector *connector, u8 gpio_index, |
197 | const char *con_id, u8 idx, bool value) |
198 | { |
199 | struct drm_i915_private *dev_priv = to_i915(dev: connector->base.dev); |
200 | /* XXX: this table is a quick ugly hack. */ |
201 | static struct gpio_desc *soc_gpio_table[U8_MAX + 1]; |
202 | struct gpio_desc *gpio_desc = soc_gpio_table[gpio_index]; |
203 | |
204 | if (gpio_desc) { |
205 | gpiod_set_value(desc: gpio_desc, value); |
206 | } else { |
207 | gpio_desc = devm_gpiod_get_index(dev: dev_priv->drm.dev, con_id, idx, |
208 | flags: value ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW); |
209 | if (IS_ERR(ptr: gpio_desc)) { |
210 | drm_err(&dev_priv->drm, |
211 | "GPIO index %u request failed (%pe)\n" , |
212 | gpio_index, gpio_desc); |
213 | return; |
214 | } |
215 | |
216 | soc_gpio_table[gpio_index] = gpio_desc; |
217 | } |
218 | } |
219 | |
220 | static void soc_opaque_gpio_set_value(struct intel_connector *connector, |
221 | u8 gpio_index, const char *chip, |
222 | const char *con_id, u8 idx, bool value) |
223 | { |
224 | struct gpiod_lookup_table *lookup; |
225 | |
226 | lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL); |
227 | if (!lookup) |
228 | return; |
229 | |
230 | lookup->dev_id = "0000:00:02.0" ; |
231 | lookup->table[0] = |
232 | GPIO_LOOKUP_IDX(chip, idx, con_id, idx, GPIO_ACTIVE_HIGH); |
233 | |
234 | gpiod_add_lookup_table(table: lookup); |
235 | |
236 | soc_gpio_set_value(connector, gpio_index, con_id, idx, value); |
237 | |
238 | gpiod_remove_lookup_table(table: lookup); |
239 | kfree(objp: lookup); |
240 | } |
241 | |
242 | static void vlv_gpio_set_value(struct intel_connector *connector, |
243 | u8 gpio_source, u8 gpio_index, bool value) |
244 | { |
245 | struct drm_i915_private *dev_priv = to_i915(dev: connector->base.dev); |
246 | |
247 | /* XXX: this assumes vlv_gpio_table only has NC GPIOs. */ |
248 | if (connector->panel.vbt.dsi.seq_version < 3) { |
249 | if (gpio_source == 1) { |
250 | drm_dbg_kms(&dev_priv->drm, "SC gpio not supported\n" ); |
251 | return; |
252 | } |
253 | if (gpio_source > 1) { |
254 | drm_dbg_kms(&dev_priv->drm, |
255 | "unknown gpio source %u\n" , gpio_source); |
256 | return; |
257 | } |
258 | } |
259 | |
260 | soc_opaque_gpio_set_value(connector, gpio_index, |
261 | chip: "INT33FC:01" , con_id: "Panel N" , idx: gpio_index, value); |
262 | } |
263 | |
264 | static void chv_gpio_set_value(struct intel_connector *connector, |
265 | u8 gpio_source, u8 gpio_index, bool value) |
266 | { |
267 | struct drm_i915_private *dev_priv = to_i915(dev: connector->base.dev); |
268 | |
269 | if (connector->panel.vbt.dsi.seq_version >= 3) { |
270 | if (gpio_index >= CHV_GPIO_IDX_START_SE) { |
271 | /* XXX: it's unclear whether 255->57 is part of SE. */ |
272 | soc_opaque_gpio_set_value(connector, gpio_index, chip: "INT33FF:03" , con_id: "Panel SE" , |
273 | idx: gpio_index - CHV_GPIO_IDX_START_SE, value); |
274 | } else if (gpio_index >= CHV_GPIO_IDX_START_SW) { |
275 | soc_opaque_gpio_set_value(connector, gpio_index, chip: "INT33FF:00" , con_id: "Panel SW" , |
276 | idx: gpio_index - CHV_GPIO_IDX_START_SW, value); |
277 | } else if (gpio_index >= CHV_GPIO_IDX_START_E) { |
278 | soc_opaque_gpio_set_value(connector, gpio_index, chip: "INT33FF:02" , con_id: "Panel E" , |
279 | idx: gpio_index - CHV_GPIO_IDX_START_E, value); |
280 | } else { |
281 | soc_opaque_gpio_set_value(connector, gpio_index, chip: "INT33FF:01" , con_id: "Panel N" , |
282 | idx: gpio_index - CHV_GPIO_IDX_START_N, value); |
283 | } |
284 | } else { |
285 | /* XXX: The spec is unclear about CHV GPIO on seq v2 */ |
286 | if (gpio_source != 0) { |
287 | drm_dbg_kms(&dev_priv->drm, |
288 | "unknown gpio source %u\n" , gpio_source); |
289 | return; |
290 | } |
291 | |
292 | if (gpio_index >= CHV_GPIO_IDX_START_E) { |
293 | drm_dbg_kms(&dev_priv->drm, |
294 | "invalid gpio index %u for GPIO N\n" , |
295 | gpio_index); |
296 | return; |
297 | } |
298 | |
299 | soc_opaque_gpio_set_value(connector, gpio_index, chip: "INT33FF:01" , con_id: "Panel N" , |
300 | idx: gpio_index - CHV_GPIO_IDX_START_N, value); |
301 | } |
302 | } |
303 | |
304 | static void bxt_gpio_set_value(struct intel_connector *connector, |
305 | u8 gpio_index, bool value) |
306 | { |
307 | soc_gpio_set_value(connector, gpio_index, NULL, idx: gpio_index, value); |
308 | } |
309 | |
310 | enum { |
311 | MIPI_RESET_1 = 0, |
312 | MIPI_AVDD_EN_1, |
313 | MIPI_BKLT_EN_1, |
314 | MIPI_AVEE_EN_1, |
315 | MIPI_VIO_EN_1, |
316 | MIPI_RESET_2, |
317 | MIPI_AVDD_EN_2, |
318 | MIPI_BKLT_EN_2, |
319 | MIPI_AVEE_EN_2, |
320 | MIPI_VIO_EN_2, |
321 | }; |
322 | |
323 | static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, |
324 | int gpio, bool value) |
325 | { |
326 | int index; |
327 | |
328 | if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2)) |
329 | return; |
330 | |
331 | switch (gpio) { |
332 | case MIPI_RESET_1: |
333 | case MIPI_RESET_2: |
334 | index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B; |
335 | |
336 | /* |
337 | * Disable HPD to set the pin to output, and set output |
338 | * value. The HPD pin should not be enabled for DSI anyway, |
339 | * assuming the board design and VBT are sane, and the pin isn't |
340 | * used by a non-DSI encoder. |
341 | * |
342 | * The locking protects against concurrent SHOTPLUG_CTL_DDI |
343 | * modifications in irq setup and handling. |
344 | */ |
345 | spin_lock_irq(lock: &dev_priv->irq_lock); |
346 | intel_de_rmw(i915: dev_priv, SHOTPLUG_CTL_DDI, |
347 | SHOTPLUG_CTL_DDI_HPD_ENABLE(index) | |
348 | SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index), |
349 | set: value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0); |
350 | spin_unlock_irq(lock: &dev_priv->irq_lock); |
351 | break; |
352 | case MIPI_AVDD_EN_1: |
353 | case MIPI_AVDD_EN_2: |
354 | index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; |
355 | |
356 | intel_de_rmw(i915: dev_priv, PP_CONTROL(index), PANEL_POWER_ON, |
357 | set: value ? PANEL_POWER_ON : 0); |
358 | break; |
359 | case MIPI_BKLT_EN_1: |
360 | case MIPI_BKLT_EN_2: |
361 | index = gpio == MIPI_BKLT_EN_1 ? 0 : 1; |
362 | |
363 | intel_de_rmw(i915: dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, |
364 | set: value ? EDP_BLC_ENABLE : 0); |
365 | break; |
366 | case MIPI_AVEE_EN_1: |
367 | case MIPI_AVEE_EN_2: |
368 | index = gpio == MIPI_AVEE_EN_1 ? 1 : 2; |
369 | |
370 | intel_de_rmw(i915: dev_priv, GPIO(dev_priv, index), |
371 | GPIO_CLOCK_VAL_OUT, |
372 | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT | |
373 | GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0)); |
374 | break; |
375 | case MIPI_VIO_EN_1: |
376 | case MIPI_VIO_EN_2: |
377 | index = gpio == MIPI_VIO_EN_1 ? 1 : 2; |
378 | |
379 | intel_de_rmw(i915: dev_priv, GPIO(dev_priv, index), |
380 | GPIO_DATA_VAL_OUT, |
381 | GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT | |
382 | GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0)); |
383 | break; |
384 | default: |
385 | MISSING_CASE(gpio); |
386 | } |
387 | } |
388 | |
389 | static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) |
390 | { |
391 | struct drm_device *dev = intel_dsi->base.base.dev; |
392 | struct drm_i915_private *i915 = to_i915(dev); |
393 | struct intel_connector *connector = intel_dsi->attached_connector; |
394 | u8 gpio_source = 0, gpio_index = 0, gpio_number; |
395 | bool value; |
396 | int size; |
397 | bool native = DISPLAY_VER(i915) >= 11; |
398 | |
399 | if (connector->panel.vbt.dsi.seq_version >= 3) { |
400 | size = 3; |
401 | |
402 | gpio_index = data[0]; |
403 | gpio_number = data[1]; |
404 | value = data[2] & BIT(0); |
405 | |
406 | if (connector->panel.vbt.dsi.seq_version >= 4 && data[2] & BIT(1)) |
407 | native = false; |
408 | } else { |
409 | size = 2; |
410 | |
411 | gpio_number = data[0]; |
412 | value = data[1] & BIT(0); |
413 | |
414 | if (connector->panel.vbt.dsi.seq_version == 2) |
415 | gpio_source = (data[1] >> 1) & 3; |
416 | } |
417 | |
418 | drm_dbg_kms(&i915->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n" , |
419 | gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value)); |
420 | |
421 | if (native) |
422 | icl_native_gpio_set_value(dev_priv: i915, gpio: gpio_number, value); |
423 | else if (DISPLAY_VER(i915) >= 9) |
424 | bxt_gpio_set_value(connector, gpio_index, value); |
425 | else if (IS_VALLEYVIEW(i915)) |
426 | vlv_gpio_set_value(connector, gpio_source, gpio_index: gpio_number, value); |
427 | else if (IS_CHERRYVIEW(i915)) |
428 | chv_gpio_set_value(connector, gpio_source, gpio_index: gpio_number, value); |
429 | |
430 | return data + size; |
431 | } |
432 | |
433 | #ifdef CONFIG_ACPI |
434 | static int i2c_adapter_lookup(struct acpi_resource *ares, void *data) |
435 | { |
436 | struct i2c_adapter_lookup *lookup = data; |
437 | struct intel_dsi *intel_dsi = lookup->intel_dsi; |
438 | struct acpi_resource_i2c_serialbus *sb; |
439 | struct i2c_adapter *adapter; |
440 | acpi_handle adapter_handle; |
441 | acpi_status status; |
442 | |
443 | if (!i2c_acpi_get_i2c_resource(ares, i2c: &sb)) |
444 | return 1; |
445 | |
446 | if (lookup->slave_addr != sb->slave_address) |
447 | return 1; |
448 | |
449 | status = acpi_get_handle(parent: lookup->dev_handle, |
450 | pathname: sb->resource_source.string_ptr, |
451 | ret_handle: &adapter_handle); |
452 | if (ACPI_FAILURE(status)) |
453 | return 1; |
454 | |
455 | adapter = i2c_acpi_find_adapter_by_handle(handle: adapter_handle); |
456 | if (adapter) |
457 | intel_dsi->i2c_bus_num = adapter->nr; |
458 | |
459 | return 1; |
460 | } |
461 | |
462 | static void i2c_acpi_find_adapter(struct intel_dsi *intel_dsi, |
463 | const u16 slave_addr) |
464 | { |
465 | struct drm_device *drm_dev = intel_dsi->base.base.dev; |
466 | struct acpi_device *adev = ACPI_COMPANION(drm_dev->dev); |
467 | struct i2c_adapter_lookup lookup = { |
468 | .slave_addr = slave_addr, |
469 | .intel_dsi = intel_dsi, |
470 | .dev_handle = acpi_device_handle(adev), |
471 | }; |
472 | LIST_HEAD(resource_list); |
473 | |
474 | acpi_dev_get_resources(adev, list: &resource_list, preproc: i2c_adapter_lookup, preproc_data: &lookup); |
475 | acpi_dev_free_resource_list(list: &resource_list); |
476 | } |
477 | #else |
478 | static inline void i2c_acpi_find_adapter(struct intel_dsi *intel_dsi, |
479 | const u16 slave_addr) |
480 | { |
481 | } |
482 | #endif |
483 | |
484 | static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) |
485 | { |
486 | struct drm_i915_private *i915 = to_i915(dev: intel_dsi->base.base.dev); |
487 | struct i2c_adapter *adapter; |
488 | struct i2c_msg msg; |
489 | int ret; |
490 | u8 vbt_i2c_bus_num = *(data + 2); |
491 | u16 slave_addr = *(u16 *)(data + 3); |
492 | u8 reg_offset = *(data + 5); |
493 | u8 payload_size = *(data + 6); |
494 | u8 *payload_data; |
495 | |
496 | drm_dbg_kms(&i915->drm, "bus %d client-addr 0x%02x reg 0x%02x data %*ph\n" , |
497 | vbt_i2c_bus_num, slave_addr, reg_offset, payload_size, data + 7); |
498 | |
499 | if (intel_dsi->i2c_bus_num < 0) { |
500 | intel_dsi->i2c_bus_num = vbt_i2c_bus_num; |
501 | i2c_acpi_find_adapter(intel_dsi, slave_addr); |
502 | } |
503 | |
504 | adapter = i2c_get_adapter(nr: intel_dsi->i2c_bus_num); |
505 | if (!adapter) { |
506 | drm_err(&i915->drm, "Cannot find a valid i2c bus for xfer\n" ); |
507 | goto err_bus; |
508 | } |
509 | |
510 | payload_data = kzalloc(size: payload_size + 1, GFP_KERNEL); |
511 | if (!payload_data) |
512 | goto err_alloc; |
513 | |
514 | payload_data[0] = reg_offset; |
515 | memcpy(&payload_data[1], (data + 7), payload_size); |
516 | |
517 | msg.addr = slave_addr; |
518 | msg.flags = 0; |
519 | msg.len = payload_size + 1; |
520 | msg.buf = payload_data; |
521 | |
522 | ret = i2c_transfer(adap: adapter, msgs: &msg, num: 1); |
523 | if (ret < 0) |
524 | drm_err(&i915->drm, |
525 | "Failed to xfer payload of size (%u) to reg (%u)\n" , |
526 | payload_size, reg_offset); |
527 | |
528 | kfree(objp: payload_data); |
529 | err_alloc: |
530 | i2c_put_adapter(adap: adapter); |
531 | err_bus: |
532 | return data + payload_size + 7; |
533 | } |
534 | |
535 | static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data) |
536 | { |
537 | struct drm_i915_private *i915 = to_i915(dev: intel_dsi->base.base.dev); |
538 | |
539 | drm_dbg_kms(&i915->drm, "Skipping SPI element execution\n" ); |
540 | |
541 | return data + *(data + 5) + 6; |
542 | } |
543 | |
544 | static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data) |
545 | { |
546 | struct drm_i915_private *i915 = to_i915(dev: intel_dsi->base.base.dev); |
547 | #ifdef CONFIG_PMIC_OPREGION |
548 | u32 value, mask, reg_address; |
549 | u16 i2c_address; |
550 | int ret; |
551 | |
552 | /* byte 0 aka PMIC Flag is reserved */ |
553 | i2c_address = get_unaligned_le16(p: data + 1); |
554 | reg_address = get_unaligned_le32(p: data + 3); |
555 | value = get_unaligned_le32(p: data + 7); |
556 | mask = get_unaligned_le32(p: data + 11); |
557 | |
558 | ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_address, |
559 | reg_address, |
560 | value, mask); |
561 | if (ret) |
562 | drm_err(&i915->drm, "%s failed, error: %d\n" , __func__, ret); |
563 | #else |
564 | drm_err(&i915->drm, |
565 | "Your hardware requires CONFIG_PMIC_OPREGION and it is not set\n" ); |
566 | #endif |
567 | |
568 | return data + 15; |
569 | } |
570 | |
571 | typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, |
572 | const u8 *data); |
573 | static const fn_mipi_elem_exec exec_elem[] = { |
574 | [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, |
575 | [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, |
576 | [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, |
577 | [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, |
578 | [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi, |
579 | [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic, |
580 | }; |
581 | |
582 | /* |
583 | * MIPI Sequence from VBT #53 parsing logic |
584 | * We have already separated each seqence during bios parsing |
585 | * Following is generic execution function for any sequence |
586 | */ |
587 | |
588 | static const char * const seq_name[] = { |
589 | [MIPI_SEQ_END] = "MIPI_SEQ_END" , |
590 | [MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET" , |
591 | [MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP" , |
592 | [MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON" , |
593 | [MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF" , |
594 | [MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET" , |
595 | [MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON" , |
596 | [MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF" , |
597 | [MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON" , |
598 | [MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF" , |
599 | [MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON" , |
600 | [MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF" , |
601 | }; |
602 | |
603 | static const char *sequence_name(enum mipi_seq seq_id) |
604 | { |
605 | if (seq_id < ARRAY_SIZE(seq_name)) |
606 | return seq_name[seq_id]; |
607 | |
608 | return "(unknown)" ; |
609 | } |
610 | |
611 | static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi, |
612 | enum mipi_seq seq_id) |
613 | { |
614 | struct drm_i915_private *dev_priv = to_i915(dev: intel_dsi->base.base.dev); |
615 | struct intel_connector *connector = intel_dsi->attached_connector; |
616 | const u8 *data; |
617 | fn_mipi_elem_exec mipi_elem_exec; |
618 | |
619 | if (drm_WARN_ON(&dev_priv->drm, |
620 | seq_id >= ARRAY_SIZE(connector->panel.vbt.dsi.sequence))) |
621 | return; |
622 | |
623 | data = connector->panel.vbt.dsi.sequence[seq_id]; |
624 | if (!data) |
625 | return; |
626 | |
627 | drm_WARN_ON(&dev_priv->drm, *data != seq_id); |
628 | |
629 | drm_dbg_kms(&dev_priv->drm, "Starting MIPI sequence %d - %s\n" , |
630 | seq_id, sequence_name(seq_id)); |
631 | |
632 | /* Skip Sequence Byte. */ |
633 | data++; |
634 | |
635 | /* Skip Size of Sequence. */ |
636 | if (connector->panel.vbt.dsi.seq_version >= 3) |
637 | data += 4; |
638 | |
639 | while (*data != MIPI_SEQ_ELEM_END) { |
640 | u8 operation_byte = *data++; |
641 | u8 operation_size = 0; |
642 | |
643 | if (operation_byte < ARRAY_SIZE(exec_elem)) |
644 | mipi_elem_exec = exec_elem[operation_byte]; |
645 | else |
646 | mipi_elem_exec = NULL; |
647 | |
648 | /* Size of Operation. */ |
649 | if (connector->panel.vbt.dsi.seq_version >= 3) |
650 | operation_size = *data++; |
651 | |
652 | if (mipi_elem_exec) { |
653 | const u8 *next = data + operation_size; |
654 | |
655 | data = mipi_elem_exec(intel_dsi, data); |
656 | |
657 | /* Consistency check if we have size. */ |
658 | if (operation_size && data != next) { |
659 | drm_err(&dev_priv->drm, |
660 | "Inconsistent operation size\n" ); |
661 | return; |
662 | } |
663 | } else if (operation_size) { |
664 | /* We have size, skip. */ |
665 | drm_dbg_kms(&dev_priv->drm, |
666 | "Unsupported MIPI operation byte %u\n" , |
667 | operation_byte); |
668 | data += operation_size; |
669 | } else { |
670 | /* No size, can't skip without parsing. */ |
671 | drm_err(&dev_priv->drm, |
672 | "Unsupported MIPI operation byte %u\n" , |
673 | operation_byte); |
674 | return; |
675 | } |
676 | } |
677 | } |
678 | |
679 | void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi, |
680 | enum mipi_seq seq_id) |
681 | { |
682 | if (seq_id == MIPI_SEQ_POWER_ON && intel_dsi->gpio_panel) |
683 | gpiod_set_value_cansleep(desc: intel_dsi->gpio_panel, value: 1); |
684 | if (seq_id == MIPI_SEQ_BACKLIGHT_ON && intel_dsi->gpio_backlight) |
685 | gpiod_set_value_cansleep(desc: intel_dsi->gpio_backlight, value: 1); |
686 | |
687 | intel_dsi_vbt_exec(intel_dsi, seq_id); |
688 | |
689 | if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel) |
690 | gpiod_set_value_cansleep(desc: intel_dsi->gpio_panel, value: 0); |
691 | if (seq_id == MIPI_SEQ_BACKLIGHT_OFF && intel_dsi->gpio_backlight) |
692 | gpiod_set_value_cansleep(desc: intel_dsi->gpio_backlight, value: 0); |
693 | } |
694 | |
695 | void intel_dsi_log_params(struct intel_dsi *intel_dsi) |
696 | { |
697 | struct drm_i915_private *i915 = to_i915(dev: intel_dsi->base.base.dev); |
698 | |
699 | drm_dbg_kms(&i915->drm, "Pclk %d\n" , intel_dsi->pclk); |
700 | drm_dbg_kms(&i915->drm, "Pixel overlap %d\n" , |
701 | intel_dsi->pixel_overlap); |
702 | drm_dbg_kms(&i915->drm, "Lane count %d\n" , intel_dsi->lane_count); |
703 | drm_dbg_kms(&i915->drm, "DPHY param reg 0x%x\n" , intel_dsi->dphy_reg); |
704 | drm_dbg_kms(&i915->drm, "Video mode format %s\n" , |
705 | intel_dsi->video_mode == NON_BURST_SYNC_PULSE ? |
706 | "non-burst with sync pulse" : |
707 | intel_dsi->video_mode == NON_BURST_SYNC_EVENTS ? |
708 | "non-burst with sync events" : |
709 | intel_dsi->video_mode == BURST_MODE ? |
710 | "burst" : "<unknown>" ); |
711 | drm_dbg_kms(&i915->drm, "Burst mode ratio %d\n" , |
712 | intel_dsi->burst_mode_ratio); |
713 | drm_dbg_kms(&i915->drm, "Reset timer %d\n" , intel_dsi->rst_timer_val); |
714 | drm_dbg_kms(&i915->drm, "Eot %s\n" , |
715 | str_enabled_disabled(intel_dsi->eotp_pkt)); |
716 | drm_dbg_kms(&i915->drm, "Clockstop %s\n" , |
717 | str_enabled_disabled(!intel_dsi->clock_stop)); |
718 | drm_dbg_kms(&i915->drm, "Mode %s\n" , |
719 | intel_dsi->operation_mode ? "command" : "video" ); |
720 | if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) |
721 | drm_dbg_kms(&i915->drm, |
722 | "Dual link: DSI_DUAL_LINK_FRONT_BACK\n" ); |
723 | else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT) |
724 | drm_dbg_kms(&i915->drm, |
725 | "Dual link: DSI_DUAL_LINK_PIXEL_ALT\n" ); |
726 | else |
727 | drm_dbg_kms(&i915->drm, "Dual link: NONE\n" ); |
728 | drm_dbg_kms(&i915->drm, "Pixel Format %d\n" , intel_dsi->pixel_format); |
729 | drm_dbg_kms(&i915->drm, "TLPX %d\n" , intel_dsi->escape_clk_div); |
730 | drm_dbg_kms(&i915->drm, "LP RX Timeout 0x%x\n" , |
731 | intel_dsi->lp_rx_timeout); |
732 | drm_dbg_kms(&i915->drm, "Turnaround Timeout 0x%x\n" , |
733 | intel_dsi->turn_arnd_val); |
734 | drm_dbg_kms(&i915->drm, "Init Count 0x%x\n" , intel_dsi->init_count); |
735 | drm_dbg_kms(&i915->drm, "HS to LP Count 0x%x\n" , |
736 | intel_dsi->hs_to_lp_count); |
737 | drm_dbg_kms(&i915->drm, "LP Byte Clock %d\n" , intel_dsi->lp_byte_clk); |
738 | drm_dbg_kms(&i915->drm, "DBI BW Timer 0x%x\n" , intel_dsi->bw_timer); |
739 | drm_dbg_kms(&i915->drm, "LP to HS Clock Count 0x%x\n" , |
740 | intel_dsi->clk_lp_to_hs_count); |
741 | drm_dbg_kms(&i915->drm, "HS to LP Clock Count 0x%x\n" , |
742 | intel_dsi->clk_hs_to_lp_count); |
743 | drm_dbg_kms(&i915->drm, "BTA %s\n" , |
744 | str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA))); |
745 | } |
746 | |
747 | bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) |
748 | { |
749 | struct drm_device *dev = intel_dsi->base.base.dev; |
750 | struct drm_i915_private *dev_priv = to_i915(dev); |
751 | struct intel_connector *connector = intel_dsi->attached_connector; |
752 | struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; |
753 | struct mipi_pps_data *pps = connector->panel.vbt.dsi.pps; |
754 | struct drm_display_mode *mode = connector->panel.vbt.lfp_lvds_vbt_mode; |
755 | u16 burst_mode_ratio; |
756 | enum port port; |
757 | |
758 | drm_dbg_kms(&dev_priv->drm, "\n" ); |
759 | |
760 | intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1; |
761 | intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0; |
762 | intel_dsi->lane_count = mipi_config->lane_cnt + 1; |
763 | intel_dsi->pixel_format = |
764 | pixel_format_from_register_bits( |
765 | fmt: mipi_config->videomode_color_format << 7); |
766 | |
767 | intel_dsi->dual_link = mipi_config->dual_link; |
768 | intel_dsi->pixel_overlap = mipi_config->pixel_overlap; |
769 | intel_dsi->operation_mode = mipi_config->is_cmd_mode; |
770 | intel_dsi->video_mode = mipi_config->video_transfer_mode; |
771 | intel_dsi->escape_clk_div = mipi_config->byte_clk_sel; |
772 | intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout; |
773 | intel_dsi->hs_tx_timeout = mipi_config->hs_tx_timeout; |
774 | intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout; |
775 | intel_dsi->rst_timer_val = mipi_config->device_reset_timer; |
776 | intel_dsi->init_count = mipi_config->master_init_timer; |
777 | intel_dsi->bw_timer = mipi_config->dbi_bw_timer; |
778 | intel_dsi->video_frmt_cfg_bits = |
779 | mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0; |
780 | intel_dsi->bgr_enabled = mipi_config->rgb_flip; |
781 | |
782 | /* Starting point, adjusted depending on dual link and burst mode */ |
783 | intel_dsi->pclk = mode->clock; |
784 | |
785 | /* In dual link mode each port needs half of pixel clock */ |
786 | if (intel_dsi->dual_link) { |
787 | intel_dsi->pclk /= 2; |
788 | |
789 | /* we can enable pixel_overlap if needed by panel. In this |
790 | * case we need to increase the pixelclock for extra pixels |
791 | */ |
792 | if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) { |
793 | intel_dsi->pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap * 60, 1000); |
794 | } |
795 | } |
796 | |
797 | /* Burst Mode Ratio |
798 | * Target ddr frequency from VBT / non burst ddr freq |
799 | * multiply by 100 to preserve remainder |
800 | */ |
801 | if (intel_dsi->video_mode == BURST_MODE) { |
802 | u32 bitrate; |
803 | |
804 | if (mipi_config->target_burst_mode_freq == 0) { |
805 | drm_err(&dev_priv->drm, "Burst mode target is not set\n" ); |
806 | return false; |
807 | } |
808 | |
809 | bitrate = intel_dsi_bitrate(intel_dsi); |
810 | |
811 | /* |
812 | * Sometimes the VBT contains a slightly lower clock, then |
813 | * the bitrate we have calculated, in this case just replace it |
814 | * with the calculated bitrate. |
815 | */ |
816 | if (mipi_config->target_burst_mode_freq < bitrate && |
817 | intel_fuzzy_clock_check(clock1: mipi_config->target_burst_mode_freq, |
818 | clock2: bitrate)) |
819 | mipi_config->target_burst_mode_freq = bitrate; |
820 | |
821 | if (mipi_config->target_burst_mode_freq < bitrate) { |
822 | drm_err(&dev_priv->drm, "Burst mode freq is less than computed\n" ); |
823 | return false; |
824 | } |
825 | |
826 | burst_mode_ratio = |
827 | DIV_ROUND_UP(mipi_config->target_burst_mode_freq * 100, bitrate); |
828 | |
829 | intel_dsi->pclk = DIV_ROUND_UP(intel_dsi->pclk * burst_mode_ratio, 100); |
830 | } else |
831 | burst_mode_ratio = 100; |
832 | |
833 | intel_dsi->burst_mode_ratio = burst_mode_ratio; |
834 | |
835 | /* delays in VBT are in unit of 100us, so need to convert |
836 | * here in ms |
837 | * Delay (100us) * 100 /1000 = Delay / 10 (ms) */ |
838 | intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10; |
839 | intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10; |
840 | intel_dsi->panel_on_delay = pps->panel_on_delay / 10; |
841 | intel_dsi->panel_off_delay = pps->panel_off_delay / 10; |
842 | intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10; |
843 | |
844 | intel_dsi->i2c_bus_num = -1; |
845 | |
846 | /* a regular driver would get the device in probe */ |
847 | for_each_dsi_port(port, intel_dsi->ports) { |
848 | mipi_dsi_attach(dsi: intel_dsi->dsi_hosts[port]->device); |
849 | } |
850 | |
851 | return true; |
852 | } |
853 | |
854 | /* |
855 | * On some BYT/CHT devs some sequences are incomplete and we need to manually |
856 | * control some GPIOs. We need to add a GPIO lookup table before we get these. |
857 | * If the GOP did not initialize the panel (HDMI inserted) we may need to also |
858 | * change the pinmux for the SoC's PWM0 pin from GPIO to PWM. |
859 | */ |
860 | static struct gpiod_lookup_table pmic_panel_gpio_table = { |
861 | /* Intel GFX is consumer */ |
862 | .dev_id = "0000:00:02.0" , |
863 | .table = { |
864 | /* Panel EN/DISABLE */ |
865 | GPIO_LOOKUP("gpio_crystalcove" , 94, "panel" , GPIO_ACTIVE_HIGH), |
866 | { } |
867 | }, |
868 | }; |
869 | |
870 | static struct gpiod_lookup_table soc_panel_gpio_table = { |
871 | .dev_id = "0000:00:02.0" , |
872 | .table = { |
873 | GPIO_LOOKUP("INT33FC:01" , 10, "backlight" , GPIO_ACTIVE_HIGH), |
874 | GPIO_LOOKUP("INT33FC:01" , 11, "panel" , GPIO_ACTIVE_HIGH), |
875 | { } |
876 | }, |
877 | }; |
878 | |
879 | static const struct pinctrl_map soc_pwm_pinctrl_map[] = { |
880 | PIN_MAP_MUX_GROUP("0000:00:02.0" , "soc_pwm0" , "INT33FC:00" , |
881 | "pwm0_grp" , "pwm" ), |
882 | }; |
883 | |
884 | void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on) |
885 | { |
886 | struct drm_device *dev = intel_dsi->base.base.dev; |
887 | struct drm_i915_private *dev_priv = to_i915(dev); |
888 | struct intel_connector *connector = intel_dsi->attached_connector; |
889 | struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; |
890 | enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW; |
891 | struct gpiod_lookup_table *gpiod_lookup_table = NULL; |
892 | bool want_backlight_gpio = false; |
893 | bool want_panel_gpio = false; |
894 | struct pinctrl *pinctrl; |
895 | int ret; |
896 | |
897 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
898 | mipi_config->pwm_blc == PPS_BLC_PMIC) { |
899 | gpiod_lookup_table = &pmic_panel_gpio_table; |
900 | want_panel_gpio = true; |
901 | } |
902 | |
903 | if (IS_VALLEYVIEW(dev_priv) && mipi_config->pwm_blc == PPS_BLC_SOC) { |
904 | gpiod_lookup_table = &soc_panel_gpio_table; |
905 | want_panel_gpio = true; |
906 | want_backlight_gpio = true; |
907 | |
908 | /* Ensure PWM0 pin is muxed as PWM instead of GPIO */ |
909 | ret = pinctrl_register_mappings(map: soc_pwm_pinctrl_map, |
910 | ARRAY_SIZE(soc_pwm_pinctrl_map)); |
911 | if (ret) |
912 | drm_err(&dev_priv->drm, |
913 | "Failed to register pwm0 pinmux mapping\n" ); |
914 | |
915 | pinctrl = devm_pinctrl_get_select(dev: dev->dev, name: "soc_pwm0" ); |
916 | if (IS_ERR(ptr: pinctrl)) |
917 | drm_err(&dev_priv->drm, |
918 | "Failed to set pinmux to PWM\n" ); |
919 | } |
920 | |
921 | if (gpiod_lookup_table) |
922 | gpiod_add_lookup_table(table: gpiod_lookup_table); |
923 | |
924 | if (want_panel_gpio) { |
925 | intel_dsi->gpio_panel = devm_gpiod_get(dev: dev->dev, con_id: "panel" , flags); |
926 | if (IS_ERR(ptr: intel_dsi->gpio_panel)) { |
927 | drm_err(&dev_priv->drm, |
928 | "Failed to own gpio for panel control\n" ); |
929 | intel_dsi->gpio_panel = NULL; |
930 | } |
931 | } |
932 | |
933 | if (want_backlight_gpio) { |
934 | intel_dsi->gpio_backlight = |
935 | devm_gpiod_get(dev: dev->dev, con_id: "backlight" , flags); |
936 | if (IS_ERR(ptr: intel_dsi->gpio_backlight)) { |
937 | drm_err(&dev_priv->drm, |
938 | "Failed to own gpio for backlight control\n" ); |
939 | intel_dsi->gpio_backlight = NULL; |
940 | } |
941 | } |
942 | |
943 | if (gpiod_lookup_table) |
944 | gpiod_remove_lookup_table(table: gpiod_lookup_table); |
945 | } |
946 | |