xref: /dflybsd-src/sys/dev/drm/i915/intel_dsi_vbt.c (revision 3f2dd94a569761201b5b0a18b2f697f97fe1b9dc)
1a85cb24fSFrançois Tigeot /*
2a85cb24fSFrançois Tigeot  * Copyright © 2014 Intel Corporation
3a85cb24fSFrançois Tigeot  *
4a85cb24fSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5a85cb24fSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6a85cb24fSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7a85cb24fSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a85cb24fSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9a85cb24fSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10a85cb24fSFrançois Tigeot  *
11a85cb24fSFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12a85cb24fSFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13a85cb24fSFrançois Tigeot  * Software.
14a85cb24fSFrançois Tigeot  *
15a85cb24fSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16a85cb24fSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17a85cb24fSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18a85cb24fSFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19a85cb24fSFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20a85cb24fSFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21a85cb24fSFrançois Tigeot  * DEALINGS IN THE SOFTWARE.
22a85cb24fSFrançois Tigeot  *
23a85cb24fSFrançois Tigeot  * Author: Shobhit Kumar <shobhit.kumar@intel.com>
24a85cb24fSFrançois Tigeot  *
25a85cb24fSFrançois Tigeot  */
26a85cb24fSFrançois Tigeot 
27a85cb24fSFrançois Tigeot #include <drm/drmP.h>
28a85cb24fSFrançois Tigeot #include <drm/drm_crtc.h>
29a85cb24fSFrançois Tigeot #include <drm/drm_edid.h>
30a85cb24fSFrançois Tigeot #include <drm/i915_drm.h>
31a85cb24fSFrançois Tigeot #include <linux/gpio/consumer.h>
32a85cb24fSFrançois Tigeot #include <linux/slab.h>
33a85cb24fSFrançois Tigeot #include <video/mipi_display.h>
34a85cb24fSFrançois Tigeot #include <asm/intel-mid.h>
35a85cb24fSFrançois Tigeot #include <video/mipi_display.h>
36a85cb24fSFrançois Tigeot #include "i915_drv.h"
37a85cb24fSFrançois Tigeot #include "intel_drv.h"
38a85cb24fSFrançois Tigeot #include "intel_dsi.h"
39a85cb24fSFrançois Tigeot 
40a85cb24fSFrançois Tigeot #define MIPI_TRANSFER_MODE_SHIFT	0
41a85cb24fSFrançois Tigeot #define MIPI_VIRTUAL_CHANNEL_SHIFT	1
42a85cb24fSFrançois Tigeot #define MIPI_PORT_SHIFT			3
43a85cb24fSFrançois Tigeot 
44a85cb24fSFrançois Tigeot #define PREPARE_CNT_MAX		0x3F
45a85cb24fSFrançois Tigeot #define EXIT_ZERO_CNT_MAX	0x3F
46a85cb24fSFrançois Tigeot #define CLK_ZERO_CNT_MAX	0xFF
47a85cb24fSFrançois Tigeot #define TRAIL_CNT_MAX		0x1F
48a85cb24fSFrançois Tigeot 
49a85cb24fSFrançois Tigeot #define NS_KHZ_RATIO 1000000
50a85cb24fSFrançois Tigeot 
51a85cb24fSFrançois Tigeot /* base offsets for gpio pads */
52a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_0_HV_DDI0_HPD	0x4130
53a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA	0x4120
54a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_2_HV_DDI0_DDC_SCL	0x4110
55a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_3_PANEL0_VDDEN	0x4140
56a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_4_PANEL0_BKLTEN	0x4150
57a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_5_PANEL0_BKLTCTL	0x4160
58a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_6_HV_DDI1_HPD	0x4180
59a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_7_HV_DDI1_DDC_SDA	0x4190
60a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_8_HV_DDI1_DDC_SCL	0x4170
61a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_9_PANEL1_VDDEN	0x4100
62a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_10_PANEL1_BKLTEN	0x40E0
63a85cb24fSFrançois Tigeot #define VLV_GPIO_NC_11_PANEL1_BKLTCTL	0x40F0
64a85cb24fSFrançois Tigeot 
65a85cb24fSFrançois Tigeot #define VLV_GPIO_PCONF0(base_offset)	(base_offset)
66a85cb24fSFrançois Tigeot #define VLV_GPIO_PAD_VAL(base_offset)	((base_offset) + 8)
67a85cb24fSFrançois Tigeot 
68a85cb24fSFrançois Tigeot struct gpio_map {
69a85cb24fSFrançois Tigeot 	u16 base_offset;
70a85cb24fSFrançois Tigeot 	bool init;
71a85cb24fSFrançois Tigeot };
72a85cb24fSFrançois Tigeot 
73a85cb24fSFrançois Tigeot static struct gpio_map vlv_gpio_table[] = {
74a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_0_HV_DDI0_HPD },
75a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_1_HV_DDI0_DDC_SDA },
76a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_2_HV_DDI0_DDC_SCL },
77a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_3_PANEL0_VDDEN },
78a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_4_PANEL0_BKLTEN },
79a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_5_PANEL0_BKLTCTL },
80a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_6_HV_DDI1_HPD },
81a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_7_HV_DDI1_DDC_SDA },
82a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_8_HV_DDI1_DDC_SCL },
83a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_9_PANEL1_VDDEN },
84a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_10_PANEL1_BKLTEN },
85a85cb24fSFrançois Tigeot 	{ VLV_GPIO_NC_11_PANEL1_BKLTCTL },
86a85cb24fSFrançois Tigeot };
87a85cb24fSFrançois Tigeot 
88a85cb24fSFrançois Tigeot #define CHV_GPIO_IDX_START_N		0
89a85cb24fSFrançois Tigeot #define CHV_GPIO_IDX_START_E		73
90a85cb24fSFrançois Tigeot #define CHV_GPIO_IDX_START_SW		100
91a85cb24fSFrançois Tigeot #define CHV_GPIO_IDX_START_SE		198
92a85cb24fSFrançois Tigeot 
93a85cb24fSFrançois Tigeot #define CHV_VBT_MAX_PINS_PER_FMLY	15
94a85cb24fSFrançois Tigeot 
95a85cb24fSFrançois Tigeot #define CHV_GPIO_PAD_CFG0(f, i)		(0x4400 + (f) * 0x400 + (i) * 8)
96a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOEN		(1 << 15)
97a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOCFG_GPIO		(0 << 8)
98a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOCFG_GPO		(1 << 8)
99a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOCFG_GPI		(2 << 8)
100a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOCFG_HIZ		(3 << 8)
101a85cb24fSFrançois Tigeot #define  CHV_GPIO_GPIOTXSTATE(state)	((!!(state)) << 1)
102a85cb24fSFrançois Tigeot 
103a85cb24fSFrançois Tigeot #define CHV_GPIO_PAD_CFG1(f, i)		(0x4400 + (f) * 0x400 + (i) * 8 + 4)
104a85cb24fSFrançois Tigeot #define  CHV_GPIO_CFGLOCK		(1 << 31)
105a85cb24fSFrançois Tigeot 
intel_dsi_seq_port_to_port(u8 port)106a85cb24fSFrançois Tigeot static inline enum port intel_dsi_seq_port_to_port(u8 port)
107a85cb24fSFrançois Tigeot {
108a85cb24fSFrançois Tigeot 	return port ? PORT_C : PORT_A;
109a85cb24fSFrançois Tigeot }
110a85cb24fSFrançois Tigeot 
mipi_exec_send_packet(struct intel_dsi * intel_dsi,const u8 * data)111a85cb24fSFrançois Tigeot static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
112a85cb24fSFrançois Tigeot 				       const u8 *data)
113a85cb24fSFrançois Tigeot {
114a85cb24fSFrançois Tigeot 	struct mipi_dsi_device *dsi_device;
115a85cb24fSFrançois Tigeot 	u8 type, flags, seq_port;
116a85cb24fSFrançois Tigeot 	u16 len;
117a85cb24fSFrançois Tigeot 	enum port port;
118a85cb24fSFrançois Tigeot 
119a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("\n");
120a85cb24fSFrançois Tigeot 
121a85cb24fSFrançois Tigeot 	flags = *data++;
122a85cb24fSFrançois Tigeot 	type = *data++;
123a85cb24fSFrançois Tigeot 
124a85cb24fSFrançois Tigeot 	len = *((u16 *) data);
125a85cb24fSFrançois Tigeot 	data += 2;
126a85cb24fSFrançois Tigeot 
127a85cb24fSFrançois Tigeot 	seq_port = (flags >> MIPI_PORT_SHIFT) & 3;
128a85cb24fSFrançois Tigeot 
129a85cb24fSFrançois Tigeot 	/* For DSI single link on Port A & C, the seq_port value which is
130a85cb24fSFrançois Tigeot 	 * parsed from Sequence Block#53 of VBT has been set to 0
131a85cb24fSFrançois Tigeot 	 * Now, read/write of packets for the DSI single link on Port A and
132a85cb24fSFrançois Tigeot 	 * Port C will based on the DVO port from VBT block 2.
133a85cb24fSFrançois Tigeot 	 */
134a85cb24fSFrançois Tigeot 	if (intel_dsi->ports == (1 << PORT_C))
135a85cb24fSFrançois Tigeot 		port = PORT_C;
136a85cb24fSFrançois Tigeot 	else
137a85cb24fSFrançois Tigeot 		port = intel_dsi_seq_port_to_port(seq_port);
138a85cb24fSFrançois Tigeot 
139a85cb24fSFrançois Tigeot 	dsi_device = intel_dsi->dsi_hosts[port]->device;
140a85cb24fSFrançois Tigeot 	if (!dsi_device) {
141a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("no dsi device for port %c\n", port_name(port));
142a85cb24fSFrançois Tigeot 		goto out;
143a85cb24fSFrançois Tigeot 	}
144a85cb24fSFrançois Tigeot 
145a85cb24fSFrançois Tigeot 	if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1)
146a85cb24fSFrançois Tigeot 		dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
147a85cb24fSFrançois Tigeot 	else
148a85cb24fSFrançois Tigeot 		dsi_device->mode_flags |= MIPI_DSI_MODE_LPM;
149a85cb24fSFrançois Tigeot 
150a85cb24fSFrançois Tigeot 	dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3;
151a85cb24fSFrançois Tigeot 
152a85cb24fSFrançois Tigeot 	switch (type) {
153a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
154a85cb24fSFrançois Tigeot 		mipi_dsi_generic_write(dsi_device, NULL, 0);
155a85cb24fSFrançois Tigeot 		break;
156a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
157a85cb24fSFrançois Tigeot 		mipi_dsi_generic_write(dsi_device, data, 1);
158a85cb24fSFrançois Tigeot 		break;
159a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
160a85cb24fSFrançois Tigeot 		mipi_dsi_generic_write(dsi_device, data, 2);
161a85cb24fSFrançois Tigeot 		break;
162a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
163a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
164a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
165a85cb24fSFrançois Tigeot 		DRM_DEBUG_DRIVER("Generic Read not yet implemented or used\n");
166a85cb24fSFrançois Tigeot 		break;
167a85cb24fSFrançois Tigeot 	case MIPI_DSI_GENERIC_LONG_WRITE:
168a85cb24fSFrançois Tigeot 		mipi_dsi_generic_write(dsi_device, data, len);
169a85cb24fSFrançois Tigeot 		break;
170a85cb24fSFrançois Tigeot 	case MIPI_DSI_DCS_SHORT_WRITE:
171a85cb24fSFrançois Tigeot 		mipi_dsi_dcs_write_buffer(dsi_device, data, 1);
172a85cb24fSFrançois Tigeot 		break;
173a85cb24fSFrançois Tigeot 	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
174a85cb24fSFrançois Tigeot 		mipi_dsi_dcs_write_buffer(dsi_device, data, 2);
175a85cb24fSFrançois Tigeot 		break;
176a85cb24fSFrançois Tigeot 	case MIPI_DSI_DCS_READ:
177a85cb24fSFrançois Tigeot 		DRM_DEBUG_DRIVER("DCS Read not yet implemented or used\n");
178a85cb24fSFrançois Tigeot 		break;
179a85cb24fSFrançois Tigeot 	case MIPI_DSI_DCS_LONG_WRITE:
180a85cb24fSFrançois Tigeot 		mipi_dsi_dcs_write_buffer(dsi_device, data, len);
181a85cb24fSFrançois Tigeot 		break;
182a85cb24fSFrançois Tigeot 	}
183a85cb24fSFrançois Tigeot 
184a85cb24fSFrançois Tigeot 	wait_for_dsi_fifo_empty(intel_dsi, port);
185a85cb24fSFrançois Tigeot 
186a85cb24fSFrançois Tigeot out:
187a85cb24fSFrançois Tigeot 	data += len;
188a85cb24fSFrançois Tigeot 
189a85cb24fSFrançois Tigeot 	return data;
190a85cb24fSFrançois Tigeot }
191a85cb24fSFrançois Tigeot 
mipi_exec_delay(struct intel_dsi * intel_dsi,const u8 * data)192a85cb24fSFrançois Tigeot static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data)
193a85cb24fSFrançois Tigeot {
194a85cb24fSFrançois Tigeot 	u32 delay = *((const u32 *) data);
195a85cb24fSFrançois Tigeot 
196a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("\n");
197a85cb24fSFrançois Tigeot 
198a85cb24fSFrançois Tigeot 	usleep_range(delay, delay + 10);
199a85cb24fSFrançois Tigeot 	data += 4;
200a85cb24fSFrançois Tigeot 
201a85cb24fSFrançois Tigeot 	return data;
202a85cb24fSFrançois Tigeot }
203a85cb24fSFrançois Tigeot 
vlv_exec_gpio(struct drm_i915_private * dev_priv,u8 gpio_source,u8 gpio_index,bool value)204a85cb24fSFrançois Tigeot static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
205a85cb24fSFrançois Tigeot 			  u8 gpio_source, u8 gpio_index, bool value)
206a85cb24fSFrançois Tigeot {
207a85cb24fSFrançois Tigeot 	struct gpio_map *map;
208a85cb24fSFrançois Tigeot 	u16 pconf0, padval;
209a85cb24fSFrançois Tigeot 	u32 tmp;
210a85cb24fSFrançois Tigeot 	u8 port;
211a85cb24fSFrançois Tigeot 
212a85cb24fSFrançois Tigeot 	if (gpio_index >= ARRAY_SIZE(vlv_gpio_table)) {
213a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("unknown gpio index %u\n", gpio_index);
214a85cb24fSFrançois Tigeot 		return;
215a85cb24fSFrançois Tigeot 	}
216a85cb24fSFrançois Tigeot 
217a85cb24fSFrançois Tigeot 	map = &vlv_gpio_table[gpio_index];
218a85cb24fSFrançois Tigeot 
219a85cb24fSFrançois Tigeot 	if (dev_priv->vbt.dsi.seq_version >= 3) {
220a85cb24fSFrançois Tigeot 		/* XXX: this assumes vlv_gpio_table only has NC GPIOs. */
221a85cb24fSFrançois Tigeot 		port = IOSF_PORT_GPIO_NC;
222a85cb24fSFrançois Tigeot 	} else {
223a85cb24fSFrançois Tigeot 		if (gpio_source == 0) {
224a85cb24fSFrançois Tigeot 			port = IOSF_PORT_GPIO_NC;
225a85cb24fSFrançois Tigeot 		} else if (gpio_source == 1) {
226a85cb24fSFrançois Tigeot 			DRM_DEBUG_KMS("SC gpio not supported\n");
227a85cb24fSFrançois Tigeot 			return;
228a85cb24fSFrançois Tigeot 		} else {
229a85cb24fSFrançois Tigeot 			DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source);
230a85cb24fSFrançois Tigeot 			return;
231a85cb24fSFrançois Tigeot 		}
232a85cb24fSFrançois Tigeot 	}
233a85cb24fSFrançois Tigeot 
234a85cb24fSFrançois Tigeot 	pconf0 = VLV_GPIO_PCONF0(map->base_offset);
235a85cb24fSFrançois Tigeot 	padval = VLV_GPIO_PAD_VAL(map->base_offset);
236a85cb24fSFrançois Tigeot 
237a85cb24fSFrançois Tigeot 	mutex_lock(&dev_priv->sb_lock);
238a85cb24fSFrançois Tigeot 	if (!map->init) {
239a85cb24fSFrançois Tigeot 		/* FIXME: remove constant below */
240a85cb24fSFrançois Tigeot 		vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00);
241a85cb24fSFrançois Tigeot 		map->init = true;
242a85cb24fSFrançois Tigeot 	}
243a85cb24fSFrançois Tigeot 
244a85cb24fSFrançois Tigeot 	tmp = 0x4 | value;
245a85cb24fSFrançois Tigeot 	vlv_iosf_sb_write(dev_priv, port, padval, tmp);
246a85cb24fSFrançois Tigeot 	mutex_unlock(&dev_priv->sb_lock);
247a85cb24fSFrançois Tigeot }
248a85cb24fSFrançois Tigeot 
chv_exec_gpio(struct drm_i915_private * dev_priv,u8 gpio_source,u8 gpio_index,bool value)249a85cb24fSFrançois Tigeot static void chv_exec_gpio(struct drm_i915_private *dev_priv,
250a85cb24fSFrançois Tigeot 			  u8 gpio_source, u8 gpio_index, bool value)
251a85cb24fSFrançois Tigeot {
252a85cb24fSFrançois Tigeot 	u16 cfg0, cfg1;
253a85cb24fSFrançois Tigeot 	u16 family_num;
254a85cb24fSFrançois Tigeot 	u8 port;
255a85cb24fSFrançois Tigeot 
256a85cb24fSFrançois Tigeot 	if (dev_priv->vbt.dsi.seq_version >= 3) {
257a85cb24fSFrançois Tigeot 		if (gpio_index >= CHV_GPIO_IDX_START_SE) {
258a85cb24fSFrançois Tigeot 			/* XXX: it's unclear whether 255->57 is part of SE. */
259a85cb24fSFrançois Tigeot 			gpio_index -= CHV_GPIO_IDX_START_SE;
260a85cb24fSFrançois Tigeot 			port = CHV_IOSF_PORT_GPIO_SE;
261a85cb24fSFrançois Tigeot 		} else if (gpio_index >= CHV_GPIO_IDX_START_SW) {
262a85cb24fSFrançois Tigeot 			gpio_index -= CHV_GPIO_IDX_START_SW;
263a85cb24fSFrançois Tigeot 			port = CHV_IOSF_PORT_GPIO_SW;
264a85cb24fSFrançois Tigeot 		} else if (gpio_index >= CHV_GPIO_IDX_START_E) {
265a85cb24fSFrançois Tigeot 			gpio_index -= CHV_GPIO_IDX_START_E;
266a85cb24fSFrançois Tigeot 			port = CHV_IOSF_PORT_GPIO_E;
267a85cb24fSFrançois Tigeot 		} else {
268a85cb24fSFrançois Tigeot 			port = CHV_IOSF_PORT_GPIO_N;
269a85cb24fSFrançois Tigeot 		}
270a85cb24fSFrançois Tigeot 	} else {
271a85cb24fSFrançois Tigeot 		/* XXX: The spec is unclear about CHV GPIO on seq v2 */
272a85cb24fSFrançois Tigeot 		if (gpio_source != 0) {
273a85cb24fSFrançois Tigeot 			DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source);
274a85cb24fSFrançois Tigeot 			return;
275a85cb24fSFrançois Tigeot 		}
276a85cb24fSFrançois Tigeot 
277a85cb24fSFrançois Tigeot 		if (gpio_index >= CHV_GPIO_IDX_START_E) {
278a85cb24fSFrançois Tigeot 			DRM_DEBUG_KMS("invalid gpio index %u for GPIO N\n",
279a85cb24fSFrançois Tigeot 				      gpio_index);
280a85cb24fSFrançois Tigeot 			return;
281a85cb24fSFrançois Tigeot 		}
282a85cb24fSFrançois Tigeot 
283a85cb24fSFrançois Tigeot 		port = CHV_IOSF_PORT_GPIO_N;
284a85cb24fSFrançois Tigeot 	}
285a85cb24fSFrançois Tigeot 
286a85cb24fSFrançois Tigeot 	family_num = gpio_index / CHV_VBT_MAX_PINS_PER_FMLY;
287a85cb24fSFrançois Tigeot 	gpio_index = gpio_index % CHV_VBT_MAX_PINS_PER_FMLY;
288a85cb24fSFrançois Tigeot 
289a85cb24fSFrançois Tigeot 	cfg0 = CHV_GPIO_PAD_CFG0(family_num, gpio_index);
290a85cb24fSFrançois Tigeot 	cfg1 = CHV_GPIO_PAD_CFG1(family_num, gpio_index);
291a85cb24fSFrançois Tigeot 
292a85cb24fSFrançois Tigeot 	mutex_lock(&dev_priv->sb_lock);
293a85cb24fSFrançois Tigeot 	vlv_iosf_sb_write(dev_priv, port, cfg1, 0);
294a85cb24fSFrançois Tigeot 	vlv_iosf_sb_write(dev_priv, port, cfg0,
295a85cb24fSFrançois Tigeot 			  CHV_GPIO_GPIOEN | CHV_GPIO_GPIOCFG_GPO |
296a85cb24fSFrançois Tigeot 			  CHV_GPIO_GPIOTXSTATE(value));
297a85cb24fSFrançois Tigeot 	mutex_unlock(&dev_priv->sb_lock);
298a85cb24fSFrançois Tigeot }
299a85cb24fSFrançois Tigeot 
bxt_exec_gpio(struct drm_i915_private * dev_priv,u8 gpio_source,u8 gpio_index,bool value)300a85cb24fSFrançois Tigeot static void bxt_exec_gpio(struct drm_i915_private *dev_priv,
301a85cb24fSFrançois Tigeot 			  u8 gpio_source, u8 gpio_index, bool value)
302a85cb24fSFrançois Tigeot {
303a85cb24fSFrançois Tigeot 	/* XXX: this table is a quick ugly hack. */
304a85cb24fSFrançois Tigeot 	static struct gpio_desc *bxt_gpio_table[U8_MAX + 1];
305a85cb24fSFrançois Tigeot 	struct gpio_desc *gpio_desc = bxt_gpio_table[gpio_index];
306a85cb24fSFrançois Tigeot 
307a85cb24fSFrançois Tigeot 	if (!gpio_desc) {
308a85cb24fSFrançois Tigeot 		gpio_desc = devm_gpiod_get_index(dev_priv->drm.dev,
309*3f2dd94aSFrançois Tigeot 						 NULL, gpio_index,
310a85cb24fSFrançois Tigeot 						 value ? GPIOD_OUT_LOW :
311a85cb24fSFrançois Tigeot 						 GPIOD_OUT_HIGH);
312a85cb24fSFrançois Tigeot 
313a85cb24fSFrançois Tigeot 		if (IS_ERR_OR_NULL(gpio_desc)) {
314a85cb24fSFrançois Tigeot 			DRM_ERROR("GPIO index %u request failed (%ld)\n",
315a85cb24fSFrançois Tigeot 				  gpio_index, PTR_ERR(gpio_desc));
316a85cb24fSFrançois Tigeot 			return;
317a85cb24fSFrançois Tigeot 		}
318a85cb24fSFrançois Tigeot 
319a85cb24fSFrançois Tigeot 		bxt_gpio_table[gpio_index] = gpio_desc;
320a85cb24fSFrançois Tigeot 	}
321a85cb24fSFrançois Tigeot 
322a85cb24fSFrançois Tigeot 	gpiod_set_value(gpio_desc, value);
323a85cb24fSFrançois Tigeot }
324a85cb24fSFrançois Tigeot 
mipi_exec_gpio(struct intel_dsi * intel_dsi,const u8 * data)325a85cb24fSFrançois Tigeot static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
326a85cb24fSFrançois Tigeot {
327a85cb24fSFrançois Tigeot 	struct drm_device *dev = intel_dsi->base.base.dev;
328a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
329a85cb24fSFrançois Tigeot 	u8 gpio_source, gpio_index = 0, gpio_number;
330a85cb24fSFrançois Tigeot 	bool value;
331a85cb24fSFrançois Tigeot 
332a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("\n");
333a85cb24fSFrançois Tigeot 
334a85cb24fSFrançois Tigeot 	if (dev_priv->vbt.dsi.seq_version >= 3)
335a85cb24fSFrançois Tigeot 		gpio_index = *data++;
336a85cb24fSFrançois Tigeot 
337a85cb24fSFrançois Tigeot 	gpio_number = *data++;
338a85cb24fSFrançois Tigeot 
339a85cb24fSFrançois Tigeot 	/* gpio source in sequence v2 only */
340a85cb24fSFrançois Tigeot 	if (dev_priv->vbt.dsi.seq_version == 2)
341a85cb24fSFrançois Tigeot 		gpio_source = (*data >> 1) & 3;
342a85cb24fSFrançois Tigeot 	else
343a85cb24fSFrançois Tigeot 		gpio_source = 0;
344a85cb24fSFrançois Tigeot 
345a85cb24fSFrançois Tigeot 	/* pull up/down */
346a85cb24fSFrançois Tigeot 	value = *data++ & 1;
347a85cb24fSFrançois Tigeot 
348a85cb24fSFrançois Tigeot 	if (IS_VALLEYVIEW(dev_priv))
349a85cb24fSFrançois Tigeot 		vlv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
350a85cb24fSFrançois Tigeot 	else if (IS_CHERRYVIEW(dev_priv))
351a85cb24fSFrançois Tigeot 		chv_exec_gpio(dev_priv, gpio_source, gpio_number, value);
352a85cb24fSFrançois Tigeot 	else
353a85cb24fSFrançois Tigeot 		bxt_exec_gpio(dev_priv, gpio_source, gpio_index, value);
354a85cb24fSFrançois Tigeot 
355a85cb24fSFrançois Tigeot 	return data;
356a85cb24fSFrançois Tigeot }
357a85cb24fSFrançois Tigeot 
mipi_exec_i2c(struct intel_dsi * intel_dsi,const u8 * data)358a85cb24fSFrançois Tigeot static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data)
359a85cb24fSFrançois Tigeot {
360a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Skipping I2C element execution\n");
361a85cb24fSFrançois Tigeot 
362a85cb24fSFrançois Tigeot 	return data + *(data + 6) + 7;
363a85cb24fSFrançois Tigeot }
364a85cb24fSFrançois Tigeot 
mipi_exec_spi(struct intel_dsi * intel_dsi,const u8 * data)365a85cb24fSFrançois Tigeot static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data)
366a85cb24fSFrançois Tigeot {
367a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Skipping SPI element execution\n");
368a85cb24fSFrançois Tigeot 
369a85cb24fSFrançois Tigeot 	return data + *(data + 5) + 6;
370a85cb24fSFrançois Tigeot }
371a85cb24fSFrançois Tigeot 
mipi_exec_pmic(struct intel_dsi * intel_dsi,const u8 * data)372a85cb24fSFrançois Tigeot static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data)
373a85cb24fSFrançois Tigeot {
374a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Skipping PMIC element execution\n");
375a85cb24fSFrançois Tigeot 
376a85cb24fSFrançois Tigeot 	return data + 15;
377a85cb24fSFrançois Tigeot }
378a85cb24fSFrançois Tigeot 
379a85cb24fSFrançois Tigeot typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi,
380a85cb24fSFrançois Tigeot 					const u8 *data);
381a85cb24fSFrançois Tigeot static const fn_mipi_elem_exec exec_elem[] = {
382a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet,
383a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay,
384a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio,
385a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c,
386a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_SPI] = mipi_exec_spi,
387a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic,
388a85cb24fSFrançois Tigeot };
389a85cb24fSFrançois Tigeot 
390a85cb24fSFrançois Tigeot /*
391a85cb24fSFrançois Tigeot  * MIPI Sequence from VBT #53 parsing logic
392a85cb24fSFrançois Tigeot  * We have already separated each seqence during bios parsing
393a85cb24fSFrançois Tigeot  * Following is generic execution function for any sequence
394a85cb24fSFrançois Tigeot  */
395a85cb24fSFrançois Tigeot 
396a85cb24fSFrançois Tigeot static const char * const seq_name[] = {
397a85cb24fSFrançois Tigeot 	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
398a85cb24fSFrançois Tigeot 	[MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
399a85cb24fSFrançois Tigeot 	[MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
400a85cb24fSFrançois Tigeot 	[MIPI_SEQ_DISPLAY_OFF]  = "MIPI_SEQ_DISPLAY_OFF",
401a85cb24fSFrançois Tigeot 	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
402a85cb24fSFrançois Tigeot 	[MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
403a85cb24fSFrançois Tigeot 	[MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
404a85cb24fSFrançois Tigeot 	[MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
405a85cb24fSFrançois Tigeot 	[MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF",
406a85cb24fSFrançois Tigeot 	[MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON",
407a85cb24fSFrançois Tigeot 	[MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF",
408a85cb24fSFrançois Tigeot };
409a85cb24fSFrançois Tigeot 
sequence_name(enum mipi_seq seq_id)410a85cb24fSFrançois Tigeot static const char *sequence_name(enum mipi_seq seq_id)
411a85cb24fSFrançois Tigeot {
412a85cb24fSFrançois Tigeot 	if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id])
413a85cb24fSFrançois Tigeot 		return seq_name[seq_id];
414a85cb24fSFrançois Tigeot 	else
415a85cb24fSFrançois Tigeot 		return "(unknown)";
416a85cb24fSFrançois Tigeot }
417a85cb24fSFrançois Tigeot 
intel_dsi_vbt_exec_sequence(struct intel_dsi * intel_dsi,enum mipi_seq seq_id)418a85cb24fSFrançois Tigeot void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
419a85cb24fSFrançois Tigeot 				 enum mipi_seq seq_id)
420a85cb24fSFrançois Tigeot {
421a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
422a85cb24fSFrançois Tigeot 	const u8 *data;
423a85cb24fSFrançois Tigeot 	fn_mipi_elem_exec mipi_elem_exec;
424a85cb24fSFrançois Tigeot 
425a85cb24fSFrançois Tigeot 	if (WARN_ON(seq_id >= ARRAY_SIZE(dev_priv->vbt.dsi.sequence)))
426a85cb24fSFrançois Tigeot 		return;
427a85cb24fSFrançois Tigeot 
428a85cb24fSFrançois Tigeot 	data = dev_priv->vbt.dsi.sequence[seq_id];
429a85cb24fSFrançois Tigeot 	if (!data)
430a85cb24fSFrançois Tigeot 		return;
431a85cb24fSFrançois Tigeot 
432a85cb24fSFrançois Tigeot 	WARN_ON(*data != seq_id);
433a85cb24fSFrançois Tigeot 
434a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Starting MIPI sequence %d - %s\n",
435a85cb24fSFrançois Tigeot 		      seq_id, sequence_name(seq_id));
436a85cb24fSFrançois Tigeot 
437a85cb24fSFrançois Tigeot 	/* Skip Sequence Byte. */
438a85cb24fSFrançois Tigeot 	data++;
439a85cb24fSFrançois Tigeot 
440a85cb24fSFrançois Tigeot 	/* Skip Size of Sequence. */
441a85cb24fSFrançois Tigeot 	if (dev_priv->vbt.dsi.seq_version >= 3)
442a85cb24fSFrançois Tigeot 		data += 4;
443a85cb24fSFrançois Tigeot 
444a85cb24fSFrançois Tigeot 	while (1) {
445a85cb24fSFrançois Tigeot 		u8 operation_byte = *data++;
446a85cb24fSFrançois Tigeot 		u8 operation_size = 0;
447a85cb24fSFrançois Tigeot 
448a85cb24fSFrançois Tigeot 		if (operation_byte == MIPI_SEQ_ELEM_END)
449a85cb24fSFrançois Tigeot 			break;
450a85cb24fSFrançois Tigeot 
451a85cb24fSFrançois Tigeot 		if (operation_byte < ARRAY_SIZE(exec_elem))
452a85cb24fSFrançois Tigeot 			mipi_elem_exec = exec_elem[operation_byte];
453a85cb24fSFrançois Tigeot 		else
454a85cb24fSFrançois Tigeot 			mipi_elem_exec = NULL;
455a85cb24fSFrançois Tigeot 
456a85cb24fSFrançois Tigeot 		/* Size of Operation. */
457a85cb24fSFrançois Tigeot 		if (dev_priv->vbt.dsi.seq_version >= 3)
458a85cb24fSFrançois Tigeot 			operation_size = *data++;
459a85cb24fSFrançois Tigeot 
460a85cb24fSFrançois Tigeot 		if (mipi_elem_exec) {
461a85cb24fSFrançois Tigeot 			const u8 *next = data + operation_size;
462a85cb24fSFrançois Tigeot 
463a85cb24fSFrançois Tigeot 			data = mipi_elem_exec(intel_dsi, data);
464a85cb24fSFrançois Tigeot 
465a85cb24fSFrançois Tigeot 			/* Consistency check if we have size. */
466a85cb24fSFrançois Tigeot 			if (operation_size && data != next) {
467a85cb24fSFrançois Tigeot 				DRM_ERROR("Inconsistent operation size\n");
468a85cb24fSFrançois Tigeot 				return;
469a85cb24fSFrançois Tigeot 			}
470a85cb24fSFrançois Tigeot 		} else if (operation_size) {
471a85cb24fSFrançois Tigeot 			/* We have size, skip. */
472a85cb24fSFrançois Tigeot 			DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n",
473a85cb24fSFrançois Tigeot 				      operation_byte);
474a85cb24fSFrançois Tigeot 			data += operation_size;
475a85cb24fSFrançois Tigeot 		} else {
476a85cb24fSFrançois Tigeot 			/* No size, can't skip without parsing. */
477a85cb24fSFrançois Tigeot 			DRM_ERROR("Unsupported MIPI operation byte %u\n",
478a85cb24fSFrançois Tigeot 				  operation_byte);
479a85cb24fSFrançois Tigeot 			return;
480a85cb24fSFrançois Tigeot 		}
481a85cb24fSFrançois Tigeot 	}
482a85cb24fSFrançois Tigeot }
483a85cb24fSFrançois Tigeot 
intel_dsi_vbt_get_modes(struct intel_dsi * intel_dsi)484a85cb24fSFrançois Tigeot int intel_dsi_vbt_get_modes(struct intel_dsi *intel_dsi)
485a85cb24fSFrançois Tigeot {
486a85cb24fSFrançois Tigeot 	struct intel_connector *connector = intel_dsi->attached_connector;
487a85cb24fSFrançois Tigeot 	struct drm_device *dev = intel_dsi->base.base.dev;
488a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
489a85cb24fSFrançois Tigeot 	struct drm_display_mode *mode;
490a85cb24fSFrançois Tigeot 
491a85cb24fSFrançois Tigeot 	mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
492a85cb24fSFrançois Tigeot 	if (!mode)
493a85cb24fSFrançois Tigeot 		return 0;
494a85cb24fSFrançois Tigeot 
495a85cb24fSFrançois Tigeot 	mode->type |= DRM_MODE_TYPE_PREFERRED;
496a85cb24fSFrançois Tigeot 
497a85cb24fSFrançois Tigeot 	drm_mode_probed_add(&connector->base, mode);
498a85cb24fSFrançois Tigeot 
499a85cb24fSFrançois Tigeot 	return 1;
500a85cb24fSFrançois Tigeot }
501a85cb24fSFrançois Tigeot 
intel_dsi_vbt_init(struct intel_dsi * intel_dsi,u16 panel_id)502a85cb24fSFrançois Tigeot bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
503a85cb24fSFrançois Tigeot {
504a85cb24fSFrançois Tigeot 	struct drm_device *dev = intel_dsi->base.base.dev;
505a85cb24fSFrançois Tigeot 	struct drm_i915_private *dev_priv = to_i915(dev);
506a85cb24fSFrançois Tigeot 	struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
507a85cb24fSFrançois Tigeot 	struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
508a85cb24fSFrançois Tigeot 	struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
509a85cb24fSFrançois Tigeot 	u32 bpp;
510a85cb24fSFrançois Tigeot 	u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
511a85cb24fSFrançois Tigeot 	u32 ui_num, ui_den;
512a85cb24fSFrançois Tigeot 	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
513a85cb24fSFrançois Tigeot 	u32 ths_prepare_ns, tclk_trail_ns;
514a85cb24fSFrançois Tigeot 	u32 tclk_prepare_clkzero, ths_prepare_hszero;
515a85cb24fSFrançois Tigeot 	u32 lp_to_hs_switch, hs_to_lp_switch;
516a85cb24fSFrançois Tigeot 	u32 pclk, computed_ddr;
517a85cb24fSFrançois Tigeot 	u32 mul;
518a85cb24fSFrançois Tigeot 	u16 burst_mode_ratio;
519a85cb24fSFrançois Tigeot 	enum port port;
520a85cb24fSFrançois Tigeot 
521a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("\n");
522a85cb24fSFrançois Tigeot 
523a85cb24fSFrançois Tigeot 	intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
524a85cb24fSFrançois Tigeot 	intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
525a85cb24fSFrançois Tigeot 	intel_dsi->lane_count = mipi_config->lane_cnt + 1;
526a85cb24fSFrançois Tigeot 	intel_dsi->pixel_format =
527a85cb24fSFrançois Tigeot 			pixel_format_from_register_bits(
528a85cb24fSFrançois Tigeot 				mipi_config->videomode_color_format << 7);
529a85cb24fSFrançois Tigeot 	bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
530a85cb24fSFrançois Tigeot 
531a85cb24fSFrançois Tigeot 	intel_dsi->dual_link = mipi_config->dual_link;
532a85cb24fSFrançois Tigeot 	intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
533a85cb24fSFrançois Tigeot 	intel_dsi->operation_mode = mipi_config->is_cmd_mode;
534a85cb24fSFrançois Tigeot 	intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
535a85cb24fSFrançois Tigeot 	intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
536a85cb24fSFrançois Tigeot 	intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
537a85cb24fSFrançois Tigeot 	intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
538a85cb24fSFrançois Tigeot 	intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
539a85cb24fSFrançois Tigeot 	intel_dsi->init_count = mipi_config->master_init_timer;
540a85cb24fSFrançois Tigeot 	intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
541a85cb24fSFrançois Tigeot 	intel_dsi->video_frmt_cfg_bits =
542a85cb24fSFrançois Tigeot 		mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
543a85cb24fSFrançois Tigeot 
544a85cb24fSFrançois Tigeot 	pclk = mode->clock;
545a85cb24fSFrançois Tigeot 
546a85cb24fSFrançois Tigeot 	/* In dual link mode each port needs half of pixel clock */
547a85cb24fSFrançois Tigeot 	if (intel_dsi->dual_link) {
548a85cb24fSFrançois Tigeot 		pclk = pclk / 2;
549a85cb24fSFrançois Tigeot 
550a85cb24fSFrançois Tigeot 		/* we can enable pixel_overlap if needed by panel. In this
551a85cb24fSFrançois Tigeot 		 * case we need to increase the pixelclock for extra pixels
552a85cb24fSFrançois Tigeot 		 */
553a85cb24fSFrançois Tigeot 		if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
554a85cb24fSFrançois Tigeot 			pclk += DIV_ROUND_UP(mode->vtotal *
555a85cb24fSFrançois Tigeot 						intel_dsi->pixel_overlap *
556a85cb24fSFrançois Tigeot 						60, 1000);
557a85cb24fSFrançois Tigeot 		}
558a85cb24fSFrançois Tigeot 	}
559a85cb24fSFrançois Tigeot 
560a85cb24fSFrançois Tigeot 	/* Burst Mode Ratio
561a85cb24fSFrançois Tigeot 	 * Target ddr frequency from VBT / non burst ddr freq
562a85cb24fSFrançois Tigeot 	 * multiply by 100 to preserve remainder
563a85cb24fSFrançois Tigeot 	 */
564a85cb24fSFrançois Tigeot 	if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
565a85cb24fSFrançois Tigeot 		if (mipi_config->target_burst_mode_freq) {
566a85cb24fSFrançois Tigeot 			computed_ddr = (pclk * bpp) / intel_dsi->lane_count;
567a85cb24fSFrançois Tigeot 
568a85cb24fSFrançois Tigeot 			if (mipi_config->target_burst_mode_freq <
569a85cb24fSFrançois Tigeot 								computed_ddr) {
570a85cb24fSFrançois Tigeot 				DRM_ERROR("Burst mode freq is less than computed\n");
571a85cb24fSFrançois Tigeot 				return false;
572a85cb24fSFrançois Tigeot 			}
573a85cb24fSFrançois Tigeot 
574a85cb24fSFrançois Tigeot 			burst_mode_ratio = DIV_ROUND_UP(
575a85cb24fSFrançois Tigeot 				mipi_config->target_burst_mode_freq * 100,
576a85cb24fSFrançois Tigeot 				computed_ddr);
577a85cb24fSFrançois Tigeot 
578a85cb24fSFrançois Tigeot 			pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100);
579a85cb24fSFrançois Tigeot 		} else {
580a85cb24fSFrançois Tigeot 			DRM_ERROR("Burst mode target is not set\n");
581a85cb24fSFrançois Tigeot 			return false;
582a85cb24fSFrançois Tigeot 		}
583a85cb24fSFrançois Tigeot 	} else
584a85cb24fSFrançois Tigeot 		burst_mode_ratio = 100;
585a85cb24fSFrançois Tigeot 
586a85cb24fSFrançois Tigeot 	intel_dsi->burst_mode_ratio = burst_mode_ratio;
587a85cb24fSFrançois Tigeot 	intel_dsi->pclk = pclk;
588a85cb24fSFrançois Tigeot 
589a85cb24fSFrançois Tigeot 	bitrate = (pclk * bpp) / intel_dsi->lane_count;
590a85cb24fSFrançois Tigeot 
591a85cb24fSFrançois Tigeot 	switch (intel_dsi->escape_clk_div) {
592a85cb24fSFrançois Tigeot 	case 0:
593a85cb24fSFrançois Tigeot 		tlpx_ns = 50;
594a85cb24fSFrançois Tigeot 		break;
595a85cb24fSFrançois Tigeot 	case 1:
596a85cb24fSFrançois Tigeot 		tlpx_ns = 100;
597a85cb24fSFrançois Tigeot 		break;
598a85cb24fSFrançois Tigeot 
599a85cb24fSFrançois Tigeot 	case 2:
600a85cb24fSFrançois Tigeot 		tlpx_ns = 200;
601a85cb24fSFrançois Tigeot 		break;
602a85cb24fSFrançois Tigeot 	default:
603a85cb24fSFrançois Tigeot 		tlpx_ns = 50;
604a85cb24fSFrançois Tigeot 		break;
605a85cb24fSFrançois Tigeot 	}
606a85cb24fSFrançois Tigeot 
607a85cb24fSFrançois Tigeot 	switch (intel_dsi->lane_count) {
608a85cb24fSFrançois Tigeot 	case 1:
609a85cb24fSFrançois Tigeot 	case 2:
610a85cb24fSFrançois Tigeot 		extra_byte_count = 2;
611a85cb24fSFrançois Tigeot 		break;
612a85cb24fSFrançois Tigeot 	case 3:
613a85cb24fSFrançois Tigeot 		extra_byte_count = 4;
614a85cb24fSFrançois Tigeot 		break;
615a85cb24fSFrançois Tigeot 	case 4:
616a85cb24fSFrançois Tigeot 	default:
617a85cb24fSFrançois Tigeot 		extra_byte_count = 3;
618a85cb24fSFrançois Tigeot 		break;
619a85cb24fSFrançois Tigeot 	}
620a85cb24fSFrançois Tigeot 
621a85cb24fSFrançois Tigeot 	/* in Kbps */
622a85cb24fSFrançois Tigeot 	ui_num = NS_KHZ_RATIO;
623a85cb24fSFrançois Tigeot 	ui_den = bitrate;
624a85cb24fSFrançois Tigeot 
625a85cb24fSFrançois Tigeot 	tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
626a85cb24fSFrançois Tigeot 	ths_prepare_hszero = mipi_config->ths_prepare_hszero;
627a85cb24fSFrançois Tigeot 
628a85cb24fSFrançois Tigeot 	/*
629a85cb24fSFrançois Tigeot 	 * B060
630a85cb24fSFrançois Tigeot 	 * LP byte clock = TLPX/ (8UI)
631a85cb24fSFrançois Tigeot 	 */
632a85cb24fSFrançois Tigeot 	intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
633a85cb24fSFrançois Tigeot 
634a85cb24fSFrançois Tigeot 	/* DDR clock period = 2 * UI
635a85cb24fSFrançois Tigeot 	 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
636a85cb24fSFrançois Tigeot 	 * UI(nsec) = 10^6 / bitrate
637a85cb24fSFrançois Tigeot 	 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
638a85cb24fSFrançois Tigeot 	 * DDR clock count  = ns_value / DDR clock period
639a85cb24fSFrançois Tigeot 	 *
640a85cb24fSFrançois Tigeot 	 * For GEMINILAKE dphy_param_reg will be programmed in terms of
641a85cb24fSFrançois Tigeot 	 * HS byte clock count for other platform in HS ddr clock count
642a85cb24fSFrançois Tigeot 	 */
643a85cb24fSFrançois Tigeot 	mul = IS_GEMINILAKE(dev_priv) ? 8 : 2;
644a85cb24fSFrançois Tigeot 	ths_prepare_ns = max(mipi_config->ths_prepare,
645a85cb24fSFrançois Tigeot 			     mipi_config->tclk_prepare);
646a85cb24fSFrançois Tigeot 
647a85cb24fSFrançois Tigeot 	/* prepare count */
648a85cb24fSFrançois Tigeot 	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul);
649a85cb24fSFrançois Tigeot 
650a85cb24fSFrançois Tigeot 	/* exit zero count */
651a85cb24fSFrançois Tigeot 	exit_zero_cnt = DIV_ROUND_UP(
652a85cb24fSFrançois Tigeot 				(ths_prepare_hszero - ths_prepare_ns) * ui_den,
653a85cb24fSFrançois Tigeot 				ui_num * mul
654a85cb24fSFrançois Tigeot 				);
655a85cb24fSFrançois Tigeot 
656a85cb24fSFrançois Tigeot 	/*
657a85cb24fSFrançois Tigeot 	 * Exit zero is unified val ths_zero and ths_exit
658a85cb24fSFrançois Tigeot 	 * minimum value for ths_exit = 110ns
659a85cb24fSFrançois Tigeot 	 * min (exit_zero_cnt * 2) = 110/UI
660a85cb24fSFrançois Tigeot 	 * exit_zero_cnt = 55/UI
661a85cb24fSFrançois Tigeot 	 */
662a85cb24fSFrançois Tigeot 	if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num)
663a85cb24fSFrançois Tigeot 		exit_zero_cnt += 1;
664a85cb24fSFrançois Tigeot 
665a85cb24fSFrançois Tigeot 	/* clk zero count */
666a85cb24fSFrançois Tigeot 	clk_zero_cnt = DIV_ROUND_UP(
667a85cb24fSFrançois Tigeot 				(tclk_prepare_clkzero -	ths_prepare_ns)
668a85cb24fSFrançois Tigeot 				* ui_den, ui_num * mul);
669a85cb24fSFrançois Tigeot 
670a85cb24fSFrançois Tigeot 	/* trail count */
671a85cb24fSFrançois Tigeot 	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
672a85cb24fSFrançois Tigeot 	trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
673a85cb24fSFrançois Tigeot 
674a85cb24fSFrançois Tigeot 	if (prepare_cnt > PREPARE_CNT_MAX ||
675a85cb24fSFrançois Tigeot 		exit_zero_cnt > EXIT_ZERO_CNT_MAX ||
676a85cb24fSFrançois Tigeot 		clk_zero_cnt > CLK_ZERO_CNT_MAX ||
677a85cb24fSFrançois Tigeot 		trail_cnt > TRAIL_CNT_MAX)
678a85cb24fSFrançois Tigeot 		DRM_DEBUG_DRIVER("Values crossing maximum limits, restricting to max values\n");
679a85cb24fSFrançois Tigeot 
680a85cb24fSFrançois Tigeot 	if (prepare_cnt > PREPARE_CNT_MAX)
681a85cb24fSFrançois Tigeot 		prepare_cnt = PREPARE_CNT_MAX;
682a85cb24fSFrançois Tigeot 
683a85cb24fSFrançois Tigeot 	if (exit_zero_cnt > EXIT_ZERO_CNT_MAX)
684a85cb24fSFrançois Tigeot 		exit_zero_cnt = EXIT_ZERO_CNT_MAX;
685a85cb24fSFrançois Tigeot 
686a85cb24fSFrançois Tigeot 	if (clk_zero_cnt > CLK_ZERO_CNT_MAX)
687a85cb24fSFrançois Tigeot 		clk_zero_cnt = CLK_ZERO_CNT_MAX;
688a85cb24fSFrançois Tigeot 
689a85cb24fSFrançois Tigeot 	if (trail_cnt > TRAIL_CNT_MAX)
690a85cb24fSFrançois Tigeot 		trail_cnt = TRAIL_CNT_MAX;
691a85cb24fSFrançois Tigeot 
692a85cb24fSFrançois Tigeot 	/* B080 */
693a85cb24fSFrançois Tigeot 	intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
694a85cb24fSFrançois Tigeot 						clk_zero_cnt << 8 | prepare_cnt;
695a85cb24fSFrançois Tigeot 
696a85cb24fSFrançois Tigeot 	/*
697*3f2dd94aSFrançois Tigeot 	 * LP to HS switch count = 4TLPX + PREP_COUNT * mul + EXIT_ZERO_COUNT *
698*3f2dd94aSFrançois Tigeot 	 *					mul + 10UI + Extra Byte Count
699a85cb24fSFrançois Tigeot 	 *
700a85cb24fSFrançois Tigeot 	 * HS to LP switch count = THS-TRAIL + 2TLPX + Extra Byte Count
701a85cb24fSFrançois Tigeot 	 * Extra Byte Count is calculated according to number of lanes.
702a85cb24fSFrançois Tigeot 	 * High Low Switch Count is the Max of LP to HS and
703a85cb24fSFrançois Tigeot 	 * HS to LP switch count
704a85cb24fSFrançois Tigeot 	 *
705a85cb24fSFrançois Tigeot 	 */
706a85cb24fSFrançois Tigeot 	tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
707a85cb24fSFrançois Tigeot 
708a85cb24fSFrançois Tigeot 	/* B044 */
709a85cb24fSFrançois Tigeot 	/* FIXME:
710a85cb24fSFrançois Tigeot 	 * The comment above does not match with the code */
711*3f2dd94aSFrançois Tigeot 	lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul +
712*3f2dd94aSFrançois Tigeot 						exit_zero_cnt * mul + 10, 8);
713a85cb24fSFrançois Tigeot 
714a85cb24fSFrançois Tigeot 	hs_to_lp_switch = DIV_ROUND_UP(mipi_config->ths_trail + 2 * tlpx_ui, 8);
715a85cb24fSFrançois Tigeot 
716a85cb24fSFrançois Tigeot 	intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
717a85cb24fSFrançois Tigeot 	intel_dsi->hs_to_lp_count += extra_byte_count;
718a85cb24fSFrançois Tigeot 
719a85cb24fSFrançois Tigeot 	/* B088 */
720a85cb24fSFrançois Tigeot 	/* LP -> HS for clock lanes
721a85cb24fSFrançois Tigeot 	 * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
722a85cb24fSFrançois Tigeot 	 *						extra byte count
723a85cb24fSFrançois Tigeot 	 * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
724a85cb24fSFrançois Tigeot 	 *					2(in UI) + extra byte count
725a85cb24fSFrançois Tigeot 	 * In byteclks = (4TLPX + prepare_cnt * 2 + clk_zero_cnt *2 (in UI)) /
726a85cb24fSFrançois Tigeot 	 *					8 + extra byte count
727a85cb24fSFrançois Tigeot 	 */
728a85cb24fSFrançois Tigeot 	intel_dsi->clk_lp_to_hs_count =
729a85cb24fSFrançois Tigeot 		DIV_ROUND_UP(
730a85cb24fSFrançois Tigeot 			4 * tlpx_ui + prepare_cnt * 2 +
731a85cb24fSFrançois Tigeot 			clk_zero_cnt * 2,
732a85cb24fSFrançois Tigeot 			8);
733a85cb24fSFrançois Tigeot 
734a85cb24fSFrançois Tigeot 	intel_dsi->clk_lp_to_hs_count += extra_byte_count;
735a85cb24fSFrançois Tigeot 
736a85cb24fSFrançois Tigeot 	/* HS->LP for Clock Lanes
737a85cb24fSFrançois Tigeot 	 * Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
738a85cb24fSFrançois Tigeot 	 *						Extra byte count
739a85cb24fSFrançois Tigeot 	 * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
740a85cb24fSFrançois Tigeot 	 * In byteclks = (2*TLpx(in UI) + trail_count*2 +8)(in UI)/8 +
741a85cb24fSFrançois Tigeot 	 *						Extra byte count
742a85cb24fSFrançois Tigeot 	 */
743a85cb24fSFrançois Tigeot 	intel_dsi->clk_hs_to_lp_count =
744a85cb24fSFrançois Tigeot 		DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8,
745a85cb24fSFrançois Tigeot 			8);
746a85cb24fSFrançois Tigeot 	intel_dsi->clk_hs_to_lp_count += extra_byte_count;
747a85cb24fSFrançois Tigeot 
748a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk);
749a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap);
750a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Lane count %d\n", intel_dsi->lane_count);
751a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("DPHY param reg 0x%x\n", intel_dsi->dphy_reg);
752a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Video mode format %s\n",
753a85cb24fSFrançois Tigeot 		      intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE ?
754a85cb24fSFrançois Tigeot 		      "non-burst with sync pulse" :
755a85cb24fSFrançois Tigeot 		      intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS ?
756a85cb24fSFrançois Tigeot 		      "non-burst with sync events" :
757a85cb24fSFrançois Tigeot 		      intel_dsi->video_mode_format == VIDEO_MODE_BURST ?
758a85cb24fSFrançois Tigeot 		      "burst" : "<unknown>");
759a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Burst mode ratio %d\n", intel_dsi->burst_mode_ratio);
760a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Reset timer %d\n", intel_dsi->rst_timer_val);
761a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt));
762a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop));
763a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
764a85cb24fSFrançois Tigeot 	if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
765a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
766a85cb24fSFrançois Tigeot 	else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
767a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
768a85cb24fSFrançois Tigeot 	else
769a85cb24fSFrançois Tigeot 		DRM_DEBUG_KMS("Dual link: NONE\n");
770a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
771a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
772a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);
773a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val);
774a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count);
775a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count);
776a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
777a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
778a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
779a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
780a85cb24fSFrançois Tigeot 	DRM_DEBUG_KMS("BTA %s\n",
781a85cb24fSFrançois Tigeot 			enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
782a85cb24fSFrançois Tigeot 
783a85cb24fSFrançois Tigeot 	/* delays in VBT are in unit of 100us, so need to convert
784a85cb24fSFrançois Tigeot 	 * here in ms
785a85cb24fSFrançois Tigeot 	 * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
786a85cb24fSFrançois Tigeot 	intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
787a85cb24fSFrançois Tigeot 	intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
788a85cb24fSFrançois Tigeot 	intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
789a85cb24fSFrançois Tigeot 	intel_dsi->panel_off_delay = pps->panel_off_delay / 10;
790a85cb24fSFrançois Tigeot 	intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10;
791a85cb24fSFrançois Tigeot 
792a85cb24fSFrançois Tigeot 	/* a regular driver would get the device in probe */
793a85cb24fSFrançois Tigeot 	for_each_dsi_port(port, intel_dsi->ports) {
794a85cb24fSFrançois Tigeot 		mipi_dsi_attach(intel_dsi->dsi_hosts[port]->device);
795a85cb24fSFrançois Tigeot 	}
796a85cb24fSFrançois Tigeot 
797a85cb24fSFrançois Tigeot 	return true;
798a85cb24fSFrançois Tigeot }
799