1379bc100SJani Nikula /*
2379bc100SJani Nikula * Copyright © 2014 Intel Corporation
3379bc100SJani Nikula *
4379bc100SJani Nikula * Permission is hereby granted, free of charge, to any person obtaining a
5379bc100SJani Nikula * copy of this software and associated documentation files (the "Software"),
6379bc100SJani Nikula * to deal in the Software without restriction, including without limitation
7379bc100SJani Nikula * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8379bc100SJani Nikula * and/or sell copies of the Software, and to permit persons to whom the
9379bc100SJani Nikula * Software is furnished to do so, subject to the following conditions:
10379bc100SJani Nikula *
11379bc100SJani Nikula * The above copyright notice and this permission notice (including the next
12379bc100SJani Nikula * paragraph) shall be included in all copies or substantial portions of the
13379bc100SJani Nikula * Software.
14379bc100SJani Nikula *
15379bc100SJani Nikula * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16379bc100SJani Nikula * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17379bc100SJani Nikula * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18379bc100SJani Nikula * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19379bc100SJani Nikula * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20379bc100SJani Nikula * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21379bc100SJani Nikula * DEALINGS IN THE SOFTWARE.
22379bc100SJani Nikula *
23379bc100SJani Nikula * Author: Shobhit Kumar <shobhit.kumar@intel.com>
24379bc100SJani Nikula *
25379bc100SJani Nikula */
26379bc100SJani Nikula
27379bc100SJani Nikula #include <linux/gpio/consumer.h>
28067d1cf7SHans de Goede #include <linux/gpio/machine.h>
29379bc100SJani Nikula #include <linux/mfd/intel_soc_pmic.h>
3025e8a383SHans de Goede #include <linux/pinctrl/consumer.h>
3125e8a383SHans de Goede #include <linux/pinctrl/machine.h>
32379bc100SJani Nikula #include <linux/slab.h>
33ff9fbe7cSLucas De Marchi #include <linux/string_helpers.h>
34379bc100SJani Nikula
35379bc100SJani Nikula #include <asm/unaligned.h>
36379bc100SJani Nikula
37379bc100SJani Nikula #include <drm/drm_crtc.h>
38379bc100SJani Nikula #include <drm/drm_edid.h>
39379bc100SJani Nikula
40379bc100SJani Nikula #include <video/mipi_display.h>
41379bc100SJani Nikula
42379bc100SJani Nikula #include "i915_drv.h"
43ce2fce25SMatt Roper #include "i915_reg.h"
44f087cfe6SJani Nikula #include "intel_de.h"
451d455f8dSJani Nikula #include "intel_display_types.h"
46379bc100SJani Nikula #include "intel_dsi.h"
47aebdd742SJani Nikula #include "intel_dsi_vbt.h"
48f087cfe6SJani Nikula #include "intel_gmbus_regs.h"
49065695b3SJani Nikula #include "intel_pps_regs.h"
507570d06dSJani Nikula #include "vlv_dsi.h"
512b72a38cSJani Nikula #include "vlv_dsi_regs.h"
521eecf31eSJani Nikula #include "vlv_sideband.h"
53379bc100SJani Nikula
54379bc100SJani Nikula #define MIPI_TRANSFER_MODE_SHIFT 0
55379bc100SJani Nikula #define MIPI_VIRTUAL_CHANNEL_SHIFT 1
56379bc100SJani Nikula #define MIPI_PORT_SHIFT 3
57379bc100SJani Nikula
58379bc100SJani Nikula /* base offsets for gpio pads */
59379bc100SJani Nikula #define VLV_GPIO_NC_0_HV_DDI0_HPD 0x4130
60379bc100SJani Nikula #define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120
61379bc100SJani Nikula #define VLV_GPIO_NC_2_HV_DDI0_DDC_SCL 0x4110
62379bc100SJani Nikula #define VLV_GPIO_NC_3_PANEL0_VDDEN 0x4140
63379bc100SJani Nikula #define VLV_GPIO_NC_4_PANEL0_BKLTEN 0x4150
64379bc100SJani Nikula #define VLV_GPIO_NC_5_PANEL0_BKLTCTL 0x4160
65379bc100SJani Nikula #define VLV_GPIO_NC_6_HV_DDI1_HPD 0x4180
66379bc100SJani Nikula #define VLV_GPIO_NC_7_HV_DDI1_DDC_SDA 0x4190
67379bc100SJani Nikula #define VLV_GPIO_NC_8_HV_DDI1_DDC_SCL 0x4170
68379bc100SJani Nikula #define VLV_GPIO_NC_9_PANEL1_VDDEN 0x4100
69379bc100SJani Nikula #define VLV_GPIO_NC_10_PANEL1_BKLTEN 0x40E0
70379bc100SJani Nikula #define VLV_GPIO_NC_11_PANEL1_BKLTCTL 0x40F0
71379bc100SJani Nikula
72379bc100SJani Nikula #define VLV_GPIO_PCONF0(base_offset) (base_offset)
73379bc100SJani Nikula #define VLV_GPIO_PAD_VAL(base_offset) ((base_offset) + 8)
74379bc100SJani Nikula
75379bc100SJani Nikula struct gpio_map {
76379bc100SJani Nikula u16 base_offset;
77379bc100SJani Nikula bool init;
78379bc100SJani Nikula };
79379bc100SJani Nikula
80379bc100SJani Nikula static struct gpio_map vlv_gpio_table[] = {
81379bc100SJani Nikula { VLV_GPIO_NC_0_HV_DDI0_HPD },
82379bc100SJani Nikula { VLV_GPIO_NC_1_HV_DDI0_DDC_SDA },
83379bc100SJani Nikula { VLV_GPIO_NC_2_HV_DDI0_DDC_SCL },
84379bc100SJani Nikula { VLV_GPIO_NC_3_PANEL0_VDDEN },
85379bc100SJani Nikula { VLV_GPIO_NC_4_PANEL0_BKLTEN },
86379bc100SJani Nikula { VLV_GPIO_NC_5_PANEL0_BKLTCTL },
87379bc100SJani Nikula { VLV_GPIO_NC_6_HV_DDI1_HPD },
88379bc100SJani Nikula { VLV_GPIO_NC_7_HV_DDI1_DDC_SDA },
89379bc100SJani Nikula { VLV_GPIO_NC_8_HV_DDI1_DDC_SCL },
90379bc100SJani Nikula { VLV_GPIO_NC_9_PANEL1_VDDEN },
91379bc100SJani Nikula { VLV_GPIO_NC_10_PANEL1_BKLTEN },
92379bc100SJani Nikula { VLV_GPIO_NC_11_PANEL1_BKLTCTL },
93379bc100SJani Nikula };
94379bc100SJani Nikula
958cbf89dbSVivek Kasireddy struct i2c_adapter_lookup {
968cbf89dbSVivek Kasireddy u16 slave_addr;
978cbf89dbSVivek Kasireddy struct intel_dsi *intel_dsi;
988cbf89dbSVivek Kasireddy acpi_handle dev_handle;
998cbf89dbSVivek Kasireddy };
1008cbf89dbSVivek Kasireddy
101379bc100SJani Nikula #define CHV_GPIO_IDX_START_N 0
102379bc100SJani Nikula #define CHV_GPIO_IDX_START_E 73
103379bc100SJani Nikula #define CHV_GPIO_IDX_START_SW 100
104379bc100SJani Nikula #define CHV_GPIO_IDX_START_SE 198
105379bc100SJani Nikula
106379bc100SJani Nikula #define CHV_VBT_MAX_PINS_PER_FMLY 15
107379bc100SJani Nikula
108379bc100SJani Nikula #define CHV_GPIO_PAD_CFG0(f, i) (0x4400 + (f) * 0x400 + (i) * 8)
109379bc100SJani Nikula #define CHV_GPIO_GPIOEN (1 << 15)
110379bc100SJani Nikula #define CHV_GPIO_GPIOCFG_GPIO (0 << 8)
111379bc100SJani Nikula #define CHV_GPIO_GPIOCFG_GPO (1 << 8)
112379bc100SJani Nikula #define CHV_GPIO_GPIOCFG_GPI (2 << 8)
113379bc100SJani Nikula #define CHV_GPIO_GPIOCFG_HIZ (3 << 8)
114379bc100SJani Nikula #define CHV_GPIO_GPIOTXSTATE(state) ((!!(state)) << 1)
115379bc100SJani Nikula
116379bc100SJani Nikula #define CHV_GPIO_PAD_CFG1(f, i) (0x4400 + (f) * 0x400 + (i) * 8 + 4)
117379bc100SJani Nikula #define CHV_GPIO_CFGLOCK (1 << 31)
118379bc100SJani Nikula
119379bc100SJani Nikula /* ICL DSI Display GPIO Pins */
120379bc100SJani Nikula #define ICL_GPIO_DDSP_HPD_A 0
121379bc100SJani Nikula #define ICL_GPIO_L_VDDEN_1 1
122379bc100SJani Nikula #define ICL_GPIO_L_BKLTEN_1 2
123379bc100SJani Nikula #define ICL_GPIO_DDPA_CTRLCLK_1 3
124379bc100SJani Nikula #define ICL_GPIO_DDPA_CTRLDATA_1 4
125379bc100SJani Nikula #define ICL_GPIO_DDSP_HPD_B 5
126379bc100SJani Nikula #define ICL_GPIO_L_VDDEN_2 6
127379bc100SJani Nikula #define ICL_GPIO_L_BKLTEN_2 7
128379bc100SJani Nikula #define ICL_GPIO_DDPA_CTRLCLK_2 8
129379bc100SJani Nikula #define ICL_GPIO_DDPA_CTRLDATA_2 9
130379bc100SJani Nikula
intel_dsi_seq_port_to_port(struct intel_dsi * intel_dsi,u8 seq_port)13108c59ddeSJani Nikula static enum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi,
13208c59ddeSJani Nikula u8 seq_port)
133379bc100SJani Nikula {
13408c59ddeSJani Nikula /*
13508c59ddeSJani Nikula * If single link DSI is being used on any port, the VBT sequence block
13608c59ddeSJani Nikula * send packet apparently always has 0 for the port. Just use the port
13708c59ddeSJani Nikula * we have configured, and ignore the sequence block port.
13808c59ddeSJani Nikula */
13908c59ddeSJani Nikula if (hweight8(intel_dsi->ports) == 1)
14008c59ddeSJani Nikula return ffs(intel_dsi->ports) - 1;
14108c59ddeSJani Nikula
14208c59ddeSJani Nikula if (seq_port) {
1438d58bb79SMikko Kovanen if (intel_dsi->ports & BIT(PORT_B))
14408c59ddeSJani Nikula return PORT_B;
1458d58bb79SMikko Kovanen else if (intel_dsi->ports & BIT(PORT_C))
14608c59ddeSJani Nikula return PORT_C;
14708c59ddeSJani Nikula }
14808c59ddeSJani Nikula
14908c59ddeSJani Nikula return PORT_A;
150379bc100SJani Nikula }
151379bc100SJani Nikula
mipi_exec_send_packet(struct intel_dsi * intel_dsi,const u8 * data)152379bc100SJani Nikula static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi,
153379bc100SJani Nikula const u8 *data)
154379bc100SJani Nikula {
155379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
156379bc100SJani Nikula struct mipi_dsi_device *dsi_device;
157379bc100SJani Nikula u8 type, flags, seq_port;
158379bc100SJani Nikula u16 len;
159379bc100SJani Nikula enum port port;
160379bc100SJani Nikula
161e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "\n");
162379bc100SJani Nikula
163379bc100SJani Nikula flags = *data++;
164379bc100SJani Nikula type = *data++;
165379bc100SJani Nikula
166379bc100SJani Nikula len = *((u16 *) data);
167379bc100SJani Nikula data += 2;
168379bc100SJani Nikula
169379bc100SJani Nikula seq_port = (flags >> MIPI_PORT_SHIFT) & 3;
170379bc100SJani Nikula
17108c59ddeSJani Nikula port = intel_dsi_seq_port_to_port(intel_dsi, seq_port);
17208c59ddeSJani Nikula
17308c59ddeSJani Nikula if (drm_WARN_ON(&dev_priv->drm, !intel_dsi->dsi_hosts[port]))
17408c59ddeSJani Nikula goto out;
175379bc100SJani Nikula
176379bc100SJani Nikula dsi_device = intel_dsi->dsi_hosts[port]->device;
177379bc100SJani Nikula if (!dsi_device) {
178e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "no dsi device for port %c\n",
179e8441414SWambui Karuga port_name(port));
180379bc100SJani Nikula goto out;
181379bc100SJani Nikula }
182379bc100SJani Nikula
183379bc100SJani Nikula if ((flags >> MIPI_TRANSFER_MODE_SHIFT) & 1)
184379bc100SJani Nikula dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
185379bc100SJani Nikula else
186379bc100SJani Nikula dsi_device->mode_flags |= MIPI_DSI_MODE_LPM;
187379bc100SJani Nikula
188379bc100SJani Nikula dsi_device->channel = (flags >> MIPI_VIRTUAL_CHANNEL_SHIFT) & 3;
189379bc100SJani Nikula
190379bc100SJani Nikula switch (type) {
191379bc100SJani Nikula case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
192379bc100SJani Nikula mipi_dsi_generic_write(dsi_device, NULL, 0);
193379bc100SJani Nikula break;
194379bc100SJani Nikula case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
195379bc100SJani Nikula mipi_dsi_generic_write(dsi_device, data, 1);
196379bc100SJani Nikula break;
197379bc100SJani Nikula case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
198379bc100SJani Nikula mipi_dsi_generic_write(dsi_device, data, 2);
199379bc100SJani Nikula break;
200379bc100SJani Nikula case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
201379bc100SJani Nikula case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
202379bc100SJani Nikula case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
203e8441414SWambui Karuga drm_dbg(&dev_priv->drm,
204e8441414SWambui Karuga "Generic Read not yet implemented or used\n");
205379bc100SJani Nikula break;
206379bc100SJani Nikula case MIPI_DSI_GENERIC_LONG_WRITE:
207379bc100SJani Nikula mipi_dsi_generic_write(dsi_device, data, len);
208379bc100SJani Nikula break;
209379bc100SJani Nikula case MIPI_DSI_DCS_SHORT_WRITE:
210379bc100SJani Nikula mipi_dsi_dcs_write_buffer(dsi_device, data, 1);
211379bc100SJani Nikula break;
212379bc100SJani Nikula case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
213379bc100SJani Nikula mipi_dsi_dcs_write_buffer(dsi_device, data, 2);
214379bc100SJani Nikula break;
215379bc100SJani Nikula case MIPI_DSI_DCS_READ:
216e8441414SWambui Karuga drm_dbg(&dev_priv->drm,
217e8441414SWambui Karuga "DCS Read not yet implemented or used\n");
218379bc100SJani Nikula break;
219379bc100SJani Nikula case MIPI_DSI_DCS_LONG_WRITE:
220379bc100SJani Nikula mipi_dsi_dcs_write_buffer(dsi_device, data, len);
221379bc100SJani Nikula break;
222379bc100SJani Nikula }
223379bc100SJani Nikula
224005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 11)
225379bc100SJani Nikula vlv_dsi_wait_for_fifo_empty(intel_dsi, port);
226379bc100SJani Nikula
227379bc100SJani Nikula out:
228379bc100SJani Nikula data += len;
229379bc100SJani Nikula
230379bc100SJani Nikula return data;
231379bc100SJani Nikula }
232379bc100SJani Nikula
mipi_exec_delay(struct intel_dsi * intel_dsi,const u8 * data)233379bc100SJani Nikula static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data)
234379bc100SJani Nikula {
235e8441414SWambui Karuga struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
236379bc100SJani Nikula u32 delay = *((const u32 *) data);
237379bc100SJani Nikula
238*ad522086SVille Syrjälä drm_dbg_kms(&i915->drm, "%d usecs\n", delay);
239379bc100SJani Nikula
240379bc100SJani Nikula usleep_range(delay, delay + 10);
241379bc100SJani Nikula data += 4;
242379bc100SJani Nikula
243379bc100SJani Nikula return data;
244379bc100SJani Nikula }
245379bc100SJani Nikula
vlv_exec_gpio(struct intel_connector * connector,u8 gpio_source,u8 gpio_index,bool value)2463cf05076SVille Syrjälä static void vlv_exec_gpio(struct intel_connector *connector,
247379bc100SJani Nikula u8 gpio_source, u8 gpio_index, bool value)
248379bc100SJani Nikula {
2493cf05076SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
250379bc100SJani Nikula struct gpio_map *map;
251379bc100SJani Nikula u16 pconf0, padval;
252379bc100SJani Nikula u32 tmp;
253379bc100SJani Nikula u8 port;
254379bc100SJani Nikula
255379bc100SJani Nikula if (gpio_index >= ARRAY_SIZE(vlv_gpio_table)) {
256e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "unknown gpio index %u\n",
257e8441414SWambui Karuga gpio_index);
258379bc100SJani Nikula return;
259379bc100SJani Nikula }
260379bc100SJani Nikula
261379bc100SJani Nikula map = &vlv_gpio_table[gpio_index];
262379bc100SJani Nikula
2633cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version >= 3) {
264379bc100SJani Nikula /* XXX: this assumes vlv_gpio_table only has NC GPIOs. */
265379bc100SJani Nikula port = IOSF_PORT_GPIO_NC;
266379bc100SJani Nikula } else {
267379bc100SJani Nikula if (gpio_source == 0) {
268379bc100SJani Nikula port = IOSF_PORT_GPIO_NC;
269379bc100SJani Nikula } else if (gpio_source == 1) {
270e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "SC gpio not supported\n");
271379bc100SJani Nikula return;
272379bc100SJani Nikula } else {
273e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm,
274e8441414SWambui Karuga "unknown gpio source %u\n", gpio_source);
275379bc100SJani Nikula return;
276379bc100SJani Nikula }
277379bc100SJani Nikula }
278379bc100SJani Nikula
279379bc100SJani Nikula pconf0 = VLV_GPIO_PCONF0(map->base_offset);
280379bc100SJani Nikula padval = VLV_GPIO_PAD_VAL(map->base_offset);
281379bc100SJani Nikula
282379bc100SJani Nikula vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO));
283379bc100SJani Nikula if (!map->init) {
284379bc100SJani Nikula /* FIXME: remove constant below */
285379bc100SJani Nikula vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00);
286379bc100SJani Nikula map->init = true;
287379bc100SJani Nikula }
288379bc100SJani Nikula
289379bc100SJani Nikula tmp = 0x4 | value;
290379bc100SJani Nikula vlv_iosf_sb_write(dev_priv, port, padval, tmp);
291379bc100SJani Nikula vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
292379bc100SJani Nikula }
293379bc100SJani Nikula
chv_exec_gpio(struct intel_connector * connector,u8 gpio_source,u8 gpio_index,bool value)2943cf05076SVille Syrjälä static void chv_exec_gpio(struct intel_connector *connector,
295379bc100SJani Nikula u8 gpio_source, u8 gpio_index, bool value)
296379bc100SJani Nikula {
2973cf05076SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
298379bc100SJani Nikula u16 cfg0, cfg1;
299379bc100SJani Nikula u16 family_num;
300379bc100SJani Nikula u8 port;
301379bc100SJani Nikula
3023cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version >= 3) {
303379bc100SJani Nikula if (gpio_index >= CHV_GPIO_IDX_START_SE) {
304379bc100SJani Nikula /* XXX: it's unclear whether 255->57 is part of SE. */
305379bc100SJani Nikula gpio_index -= CHV_GPIO_IDX_START_SE;
306379bc100SJani Nikula port = CHV_IOSF_PORT_GPIO_SE;
307379bc100SJani Nikula } else if (gpio_index >= CHV_GPIO_IDX_START_SW) {
308379bc100SJani Nikula gpio_index -= CHV_GPIO_IDX_START_SW;
309379bc100SJani Nikula port = CHV_IOSF_PORT_GPIO_SW;
310379bc100SJani Nikula } else if (gpio_index >= CHV_GPIO_IDX_START_E) {
311379bc100SJani Nikula gpio_index -= CHV_GPIO_IDX_START_E;
312379bc100SJani Nikula port = CHV_IOSF_PORT_GPIO_E;
313379bc100SJani Nikula } else {
314379bc100SJani Nikula port = CHV_IOSF_PORT_GPIO_N;
315379bc100SJani Nikula }
316379bc100SJani Nikula } else {
317379bc100SJani Nikula /* XXX: The spec is unclear about CHV GPIO on seq v2 */
318379bc100SJani Nikula if (gpio_source != 0) {
319e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm,
320e8441414SWambui Karuga "unknown gpio source %u\n", gpio_source);
321379bc100SJani Nikula return;
322379bc100SJani Nikula }
323379bc100SJani Nikula
324379bc100SJani Nikula if (gpio_index >= CHV_GPIO_IDX_START_E) {
325e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm,
326e8441414SWambui Karuga "invalid gpio index %u for GPIO N\n",
327379bc100SJani Nikula gpio_index);
328379bc100SJani Nikula return;
329379bc100SJani Nikula }
330379bc100SJani Nikula
331379bc100SJani Nikula port = CHV_IOSF_PORT_GPIO_N;
332379bc100SJani Nikula }
333379bc100SJani Nikula
334379bc100SJani Nikula family_num = gpio_index / CHV_VBT_MAX_PINS_PER_FMLY;
335379bc100SJani Nikula gpio_index = gpio_index % CHV_VBT_MAX_PINS_PER_FMLY;
336379bc100SJani Nikula
337379bc100SJani Nikula cfg0 = CHV_GPIO_PAD_CFG0(family_num, gpio_index);
338379bc100SJani Nikula cfg1 = CHV_GPIO_PAD_CFG1(family_num, gpio_index);
339379bc100SJani Nikula
340379bc100SJani Nikula vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO));
341379bc100SJani Nikula vlv_iosf_sb_write(dev_priv, port, cfg1, 0);
342379bc100SJani Nikula vlv_iosf_sb_write(dev_priv, port, cfg0,
343379bc100SJani Nikula CHV_GPIO_GPIOEN | CHV_GPIO_GPIOCFG_GPO |
344379bc100SJani Nikula CHV_GPIO_GPIOTXSTATE(value));
345379bc100SJani Nikula vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
346379bc100SJani Nikula }
347379bc100SJani Nikula
bxt_exec_gpio(struct intel_connector * connector,u8 gpio_source,u8 gpio_index,bool value)3483cf05076SVille Syrjälä static void bxt_exec_gpio(struct intel_connector *connector,
349379bc100SJani Nikula u8 gpio_source, u8 gpio_index, bool value)
350379bc100SJani Nikula {
3513cf05076SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
352379bc100SJani Nikula /* XXX: this table is a quick ugly hack. */
353379bc100SJani Nikula static struct gpio_desc *bxt_gpio_table[U8_MAX + 1];
354379bc100SJani Nikula struct gpio_desc *gpio_desc = bxt_gpio_table[gpio_index];
355379bc100SJani Nikula
356379bc100SJani Nikula if (!gpio_desc) {
357379bc100SJani Nikula gpio_desc = devm_gpiod_get_index(dev_priv->drm.dev,
358379bc100SJani Nikula NULL, gpio_index,
359379bc100SJani Nikula value ? GPIOD_OUT_LOW :
360379bc100SJani Nikula GPIOD_OUT_HIGH);
361379bc100SJani Nikula
362379bc100SJani Nikula if (IS_ERR_OR_NULL(gpio_desc)) {
363e8441414SWambui Karuga drm_err(&dev_priv->drm,
364e8441414SWambui Karuga "GPIO index %u request failed (%ld)\n",
365379bc100SJani Nikula gpio_index, PTR_ERR(gpio_desc));
366379bc100SJani Nikula return;
367379bc100SJani Nikula }
368379bc100SJani Nikula
369379bc100SJani Nikula bxt_gpio_table[gpio_index] = gpio_desc;
370379bc100SJani Nikula }
371379bc100SJani Nikula
372379bc100SJani Nikula gpiod_set_value(gpio_desc, value);
373379bc100SJani Nikula }
374379bc100SJani Nikula
icl_exec_gpio(struct intel_connector * connector,u8 gpio_source,u8 gpio_index,bool value)3753cf05076SVille Syrjälä static void icl_exec_gpio(struct intel_connector *connector,
376379bc100SJani Nikula u8 gpio_source, u8 gpio_index, bool value)
377379bc100SJani Nikula {
3783cf05076SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
3793cf05076SVille Syrjälä
380e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n");
381379bc100SJani Nikula }
382379bc100SJani Nikula
383f087cfe6SJani Nikula enum {
384f087cfe6SJani Nikula MIPI_RESET_1 = 0,
385f087cfe6SJani Nikula MIPI_AVDD_EN_1,
386f087cfe6SJani Nikula MIPI_BKLT_EN_1,
387f087cfe6SJani Nikula MIPI_AVEE_EN_1,
388f087cfe6SJani Nikula MIPI_VIO_EN_1,
389f087cfe6SJani Nikula MIPI_RESET_2,
390f087cfe6SJani Nikula MIPI_AVDD_EN_2,
391f087cfe6SJani Nikula MIPI_BKLT_EN_2,
392f087cfe6SJani Nikula MIPI_AVEE_EN_2,
393f087cfe6SJani Nikula MIPI_VIO_EN_2,
394f087cfe6SJani Nikula };
395f087cfe6SJani Nikula
icl_native_gpio_set_value(struct drm_i915_private * dev_priv,int gpio,bool value)396f087cfe6SJani Nikula static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv,
397f087cfe6SJani Nikula int gpio, bool value)
398f087cfe6SJani Nikula {
399f087cfe6SJani Nikula int index;
400f087cfe6SJani Nikula
401f087cfe6SJani Nikula if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2))
402f087cfe6SJani Nikula return;
403f087cfe6SJani Nikula
404f087cfe6SJani Nikula switch (gpio) {
405f087cfe6SJani Nikula case MIPI_RESET_1:
406f087cfe6SJani Nikula case MIPI_RESET_2:
407f087cfe6SJani Nikula index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B;
408f087cfe6SJani Nikula
409f087cfe6SJani Nikula /*
410f087cfe6SJani Nikula * Disable HPD to set the pin to output, and set output
411f087cfe6SJani Nikula * value. The HPD pin should not be enabled for DSI anyway,
412f087cfe6SJani Nikula * assuming the board design and VBT are sane, and the pin isn't
413f087cfe6SJani Nikula * used by a non-DSI encoder.
414f087cfe6SJani Nikula *
415f087cfe6SJani Nikula * The locking protects against concurrent SHOTPLUG_CTL_DDI
416f087cfe6SJani Nikula * modifications in irq setup and handling.
417f087cfe6SJani Nikula */
418f087cfe6SJani Nikula spin_lock_irq(&dev_priv->irq_lock);
419f087cfe6SJani Nikula intel_de_rmw(dev_priv, SHOTPLUG_CTL_DDI,
420f087cfe6SJani Nikula SHOTPLUG_CTL_DDI_HPD_ENABLE(index) |
421f087cfe6SJani Nikula SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index),
422f087cfe6SJani Nikula value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0);
423f087cfe6SJani Nikula spin_unlock_irq(&dev_priv->irq_lock);
424f087cfe6SJani Nikula break;
425f087cfe6SJani Nikula case MIPI_AVDD_EN_1:
426f087cfe6SJani Nikula case MIPI_AVDD_EN_2:
427f087cfe6SJani Nikula index = gpio == MIPI_AVDD_EN_1 ? 0 : 1;
428f087cfe6SJani Nikula
429f087cfe6SJani Nikula intel_de_rmw(dev_priv, PP_CONTROL(index), PANEL_POWER_ON,
430f087cfe6SJani Nikula value ? PANEL_POWER_ON : 0);
431f087cfe6SJani Nikula break;
432f087cfe6SJani Nikula case MIPI_BKLT_EN_1:
433f087cfe6SJani Nikula case MIPI_BKLT_EN_2:
434a561933cSJani Nikula index = gpio == MIPI_BKLT_EN_1 ? 0 : 1;
435f087cfe6SJani Nikula
436f087cfe6SJani Nikula intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE,
437f087cfe6SJani Nikula value ? EDP_BLC_ENABLE : 0);
438f087cfe6SJani Nikula break;
439f087cfe6SJani Nikula case MIPI_AVEE_EN_1:
440f087cfe6SJani Nikula case MIPI_AVEE_EN_2:
441f087cfe6SJani Nikula index = gpio == MIPI_AVEE_EN_1 ? 1 : 2;
442f087cfe6SJani Nikula
443f087cfe6SJani Nikula intel_de_rmw(dev_priv, GPIO(dev_priv, index),
444f087cfe6SJani Nikula GPIO_CLOCK_VAL_OUT,
445f087cfe6SJani Nikula GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT |
446f087cfe6SJani Nikula GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0));
447f087cfe6SJani Nikula break;
448f087cfe6SJani Nikula case MIPI_VIO_EN_1:
449f087cfe6SJani Nikula case MIPI_VIO_EN_2:
450f087cfe6SJani Nikula index = gpio == MIPI_VIO_EN_1 ? 1 : 2;
451f087cfe6SJani Nikula
452f087cfe6SJani Nikula intel_de_rmw(dev_priv, GPIO(dev_priv, index),
453f087cfe6SJani Nikula GPIO_DATA_VAL_OUT,
454f087cfe6SJani Nikula GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT |
455f087cfe6SJani Nikula GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0));
456f087cfe6SJani Nikula break;
457f087cfe6SJani Nikula default:
458f087cfe6SJani Nikula MISSING_CASE(gpio);
459f087cfe6SJani Nikula }
460f087cfe6SJani Nikula }
461f087cfe6SJani Nikula
mipi_exec_gpio(struct intel_dsi * intel_dsi,const u8 * data)462379bc100SJani Nikula static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
463379bc100SJani Nikula {
464379bc100SJani Nikula struct drm_device *dev = intel_dsi->base.base.dev;
465379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(dev);
4663cf05076SVille Syrjälä struct intel_connector *connector = intel_dsi->attached_connector;
467379bc100SJani Nikula u8 gpio_source, gpio_index = 0, gpio_number;
468379bc100SJani Nikula bool value;
469f087cfe6SJani Nikula bool native = DISPLAY_VER(dev_priv) >= 11;
470379bc100SJani Nikula
4713cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version >= 3)
472379bc100SJani Nikula gpio_index = *data++;
473379bc100SJani Nikula
474379bc100SJani Nikula gpio_number = *data++;
475379bc100SJani Nikula
476379bc100SJani Nikula /* gpio source in sequence v2 only */
4773cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version == 2)
478379bc100SJani Nikula gpio_source = (*data >> 1) & 3;
479379bc100SJani Nikula else
480379bc100SJani Nikula gpio_source = 0;
481379bc100SJani Nikula
482f087cfe6SJani Nikula if (connector->panel.vbt.dsi.seq_version >= 4 && *data & BIT(1))
483f087cfe6SJani Nikula native = false;
484f087cfe6SJani Nikula
485379bc100SJani Nikula /* pull up/down */
486379bc100SJani Nikula value = *data++ & 1;
487379bc100SJani Nikula
488f087cfe6SJani Nikula drm_dbg_kms(&dev_priv->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n",
489f087cfe6SJani Nikula gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value));
490f087cfe6SJani Nikula
491f087cfe6SJani Nikula if (native)
492f087cfe6SJani Nikula icl_native_gpio_set_value(dev_priv, gpio_number, value);
493f087cfe6SJani Nikula else if (DISPLAY_VER(dev_priv) >= 11)
4943cf05076SVille Syrjälä icl_exec_gpio(connector, gpio_source, gpio_index, value);
495379bc100SJani Nikula else if (IS_VALLEYVIEW(dev_priv))
4963cf05076SVille Syrjälä vlv_exec_gpio(connector, gpio_source, gpio_number, value);
497379bc100SJani Nikula else if (IS_CHERRYVIEW(dev_priv))
4983cf05076SVille Syrjälä chv_exec_gpio(connector, gpio_source, gpio_number, value);
499379bc100SJani Nikula else
5003cf05076SVille Syrjälä bxt_exec_gpio(connector, gpio_source, gpio_index, value);
501379bc100SJani Nikula
502379bc100SJani Nikula return data;
503379bc100SJani Nikula }
504379bc100SJani Nikula
505960287caSVivek Kasireddy #ifdef CONFIG_ACPI
i2c_adapter_lookup(struct acpi_resource * ares,void * data)5068cbf89dbSVivek Kasireddy static int i2c_adapter_lookup(struct acpi_resource *ares, void *data)
5078cbf89dbSVivek Kasireddy {
5088cbf89dbSVivek Kasireddy struct i2c_adapter_lookup *lookup = data;
5098cbf89dbSVivek Kasireddy struct intel_dsi *intel_dsi = lookup->intel_dsi;
5108cbf89dbSVivek Kasireddy struct acpi_resource_i2c_serialbus *sb;
5118cbf89dbSVivek Kasireddy struct i2c_adapter *adapter;
5128cbf89dbSVivek Kasireddy acpi_handle adapter_handle;
5138cbf89dbSVivek Kasireddy acpi_status status;
5148cbf89dbSVivek Kasireddy
515de409661SVivek Kasireddy if (!i2c_acpi_get_i2c_resource(ares, &sb))
5168cbf89dbSVivek Kasireddy return 1;
5178cbf89dbSVivek Kasireddy
5188cbf89dbSVivek Kasireddy if (lookup->slave_addr != sb->slave_address)
5198cbf89dbSVivek Kasireddy return 1;
5208cbf89dbSVivek Kasireddy
5218cbf89dbSVivek Kasireddy status = acpi_get_handle(lookup->dev_handle,
5228cbf89dbSVivek Kasireddy sb->resource_source.string_ptr,
5238cbf89dbSVivek Kasireddy &adapter_handle);
5248cbf89dbSVivek Kasireddy if (ACPI_FAILURE(status))
5258cbf89dbSVivek Kasireddy return 1;
5268cbf89dbSVivek Kasireddy
5278cbf89dbSVivek Kasireddy adapter = i2c_acpi_find_adapter_by_handle(adapter_handle);
5288cbf89dbSVivek Kasireddy if (adapter)
5298cbf89dbSVivek Kasireddy intel_dsi->i2c_bus_num = adapter->nr;
5308cbf89dbSVivek Kasireddy
5318cbf89dbSVivek Kasireddy return 1;
5328cbf89dbSVivek Kasireddy }
5338cbf89dbSVivek Kasireddy
i2c_acpi_find_adapter(struct intel_dsi * intel_dsi,const u16 slave_addr)534960287caSVivek Kasireddy static void i2c_acpi_find_adapter(struct intel_dsi *intel_dsi,
535960287caSVivek Kasireddy const u16 slave_addr)
536379bc100SJani Nikula {
5378cbf89dbSVivek Kasireddy struct drm_device *drm_dev = intel_dsi->base.base.dev;
538f7747be1SAndy Shevchenko struct acpi_device *adev = ACPI_COMPANION(drm_dev->dev);
539f7747be1SAndy Shevchenko struct i2c_adapter_lookup lookup = {
540f7747be1SAndy Shevchenko .slave_addr = slave_addr,
541f7747be1SAndy Shevchenko .intel_dsi = intel_dsi,
542f7747be1SAndy Shevchenko .dev_handle = acpi_device_handle(adev),
543f7747be1SAndy Shevchenko };
544f7747be1SAndy Shevchenko LIST_HEAD(resource_list);
5458cbf89dbSVivek Kasireddy
546f7747be1SAndy Shevchenko acpi_dev_get_resources(adev, &resource_list, i2c_adapter_lookup, &lookup);
5478cbf89dbSVivek Kasireddy acpi_dev_free_resource_list(&resource_list);
5488cbf89dbSVivek Kasireddy }
549960287caSVivek Kasireddy #else
i2c_acpi_find_adapter(struct intel_dsi * intel_dsi,const u16 slave_addr)550960287caSVivek Kasireddy static inline void i2c_acpi_find_adapter(struct intel_dsi *intel_dsi,
551960287caSVivek Kasireddy const u16 slave_addr)
552960287caSVivek Kasireddy {
553960287caSVivek Kasireddy }
554960287caSVivek Kasireddy #endif
555960287caSVivek Kasireddy
mipi_exec_i2c(struct intel_dsi * intel_dsi,const u8 * data)556960287caSVivek Kasireddy static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data)
557960287caSVivek Kasireddy {
558dd10a80fSJani Nikula struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
559960287caSVivek Kasireddy struct i2c_adapter *adapter;
560960287caSVivek Kasireddy struct i2c_msg msg;
561960287caSVivek Kasireddy int ret;
562960287caSVivek Kasireddy u8 vbt_i2c_bus_num = *(data + 2);
563960287caSVivek Kasireddy u16 slave_addr = *(u16 *)(data + 3);
564960287caSVivek Kasireddy u8 reg_offset = *(data + 5);
565960287caSVivek Kasireddy u8 payload_size = *(data + 6);
566960287caSVivek Kasireddy u8 *payload_data;
567960287caSVivek Kasireddy
568960287caSVivek Kasireddy if (intel_dsi->i2c_bus_num < 0) {
569960287caSVivek Kasireddy intel_dsi->i2c_bus_num = vbt_i2c_bus_num;
570960287caSVivek Kasireddy i2c_acpi_find_adapter(intel_dsi, slave_addr);
571960287caSVivek Kasireddy }
5728cbf89dbSVivek Kasireddy
5738cbf89dbSVivek Kasireddy adapter = i2c_get_adapter(intel_dsi->i2c_bus_num);
5748cbf89dbSVivek Kasireddy if (!adapter) {
575dd10a80fSJani Nikula drm_err(&i915->drm, "Cannot find a valid i2c bus for xfer\n");
5768cbf89dbSVivek Kasireddy goto err_bus;
5778cbf89dbSVivek Kasireddy }
5788cbf89dbSVivek Kasireddy
5798cbf89dbSVivek Kasireddy payload_data = kzalloc(payload_size + 1, GFP_KERNEL);
5808cbf89dbSVivek Kasireddy if (!payload_data)
5818cbf89dbSVivek Kasireddy goto err_alloc;
5828cbf89dbSVivek Kasireddy
5838cbf89dbSVivek Kasireddy payload_data[0] = reg_offset;
5848cbf89dbSVivek Kasireddy memcpy(&payload_data[1], (data + 7), payload_size);
5858cbf89dbSVivek Kasireddy
5868cbf89dbSVivek Kasireddy msg.addr = slave_addr;
5878cbf89dbSVivek Kasireddy msg.flags = 0;
5888cbf89dbSVivek Kasireddy msg.len = payload_size + 1;
5898cbf89dbSVivek Kasireddy msg.buf = payload_data;
5908cbf89dbSVivek Kasireddy
5918cbf89dbSVivek Kasireddy ret = i2c_transfer(adapter, &msg, 1);
5928cbf89dbSVivek Kasireddy if (ret < 0)
593dd10a80fSJani Nikula drm_err(&i915->drm,
5948cbf89dbSVivek Kasireddy "Failed to xfer payload of size (%u) to reg (%u)\n",
5958cbf89dbSVivek Kasireddy payload_size, reg_offset);
5968cbf89dbSVivek Kasireddy
5978cbf89dbSVivek Kasireddy kfree(payload_data);
5988cbf89dbSVivek Kasireddy err_alloc:
5998cbf89dbSVivek Kasireddy i2c_put_adapter(adapter);
6008cbf89dbSVivek Kasireddy err_bus:
6018cbf89dbSVivek Kasireddy return data + payload_size + 7;
602379bc100SJani Nikula }
603379bc100SJani Nikula
mipi_exec_spi(struct intel_dsi * intel_dsi,const u8 * data)604379bc100SJani Nikula static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data)
605379bc100SJani Nikula {
606e8441414SWambui Karuga struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
607e8441414SWambui Karuga
608e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Skipping SPI element execution\n");
609379bc100SJani Nikula
610379bc100SJani Nikula return data + *(data + 5) + 6;
611379bc100SJani Nikula }
612379bc100SJani Nikula
mipi_exec_pmic(struct intel_dsi * intel_dsi,const u8 * data)613379bc100SJani Nikula static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data)
614379bc100SJani Nikula {
615e8441414SWambui Karuga struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
616379bc100SJani Nikula #ifdef CONFIG_PMIC_OPREGION
617379bc100SJani Nikula u32 value, mask, reg_address;
618379bc100SJani Nikula u16 i2c_address;
619379bc100SJani Nikula int ret;
620379bc100SJani Nikula
621379bc100SJani Nikula /* byte 0 aka PMIC Flag is reserved */
622379bc100SJani Nikula i2c_address = get_unaligned_le16(data + 1);
623379bc100SJani Nikula reg_address = get_unaligned_le32(data + 3);
624379bc100SJani Nikula value = get_unaligned_le32(data + 7);
625379bc100SJani Nikula mask = get_unaligned_le32(data + 11);
626379bc100SJani Nikula
627379bc100SJani Nikula ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_address,
628379bc100SJani Nikula reg_address,
629379bc100SJani Nikula value, mask);
630379bc100SJani Nikula if (ret)
631e8441414SWambui Karuga drm_err(&i915->drm, "%s failed, error: %d\n", __func__, ret);
632379bc100SJani Nikula #else
633e8441414SWambui Karuga drm_err(&i915->drm,
634e8441414SWambui Karuga "Your hardware requires CONFIG_PMIC_OPREGION and it is not set\n");
635379bc100SJani Nikula #endif
636379bc100SJani Nikula
637379bc100SJani Nikula return data + 15;
638379bc100SJani Nikula }
639379bc100SJani Nikula
640379bc100SJani Nikula typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi,
641379bc100SJani Nikula const u8 *data);
642379bc100SJani Nikula static const fn_mipi_elem_exec exec_elem[] = {
643379bc100SJani Nikula [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet,
644379bc100SJani Nikula [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay,
645379bc100SJani Nikula [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio,
646379bc100SJani Nikula [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c,
647379bc100SJani Nikula [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi,
648379bc100SJani Nikula [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic,
649379bc100SJani Nikula };
650379bc100SJani Nikula
651379bc100SJani Nikula /*
652379bc100SJani Nikula * MIPI Sequence from VBT #53 parsing logic
653379bc100SJani Nikula * We have already separated each seqence during bios parsing
654379bc100SJani Nikula * Following is generic execution function for any sequence
655379bc100SJani Nikula */
656379bc100SJani Nikula
657379bc100SJani Nikula static const char * const seq_name[] = {
658379bc100SJani Nikula [MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
659379bc100SJani Nikula [MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
660379bc100SJani Nikula [MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
661379bc100SJani Nikula [MIPI_SEQ_DISPLAY_OFF] = "MIPI_SEQ_DISPLAY_OFF",
662379bc100SJani Nikula [MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
663379bc100SJani Nikula [MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
664379bc100SJani Nikula [MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
665379bc100SJani Nikula [MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
666379bc100SJani Nikula [MIPI_SEQ_TEAR_OFF] = "MIPI_SEQ_TEAR_OFF",
667379bc100SJani Nikula [MIPI_SEQ_POWER_ON] = "MIPI_SEQ_POWER_ON",
668379bc100SJani Nikula [MIPI_SEQ_POWER_OFF] = "MIPI_SEQ_POWER_OFF",
669379bc100SJani Nikula };
670379bc100SJani Nikula
sequence_name(enum mipi_seq seq_id)671379bc100SJani Nikula static const char *sequence_name(enum mipi_seq seq_id)
672379bc100SJani Nikula {
673379bc100SJani Nikula if (seq_id < ARRAY_SIZE(seq_name) && seq_name[seq_id])
674379bc100SJani Nikula return seq_name[seq_id];
675379bc100SJani Nikula else
676379bc100SJani Nikula return "(unknown)";
677379bc100SJani Nikula }
678379bc100SJani Nikula
intel_dsi_vbt_exec(struct intel_dsi * intel_dsi,enum mipi_seq seq_id)679ea0fe672SHans de Goede static void intel_dsi_vbt_exec(struct intel_dsi *intel_dsi,
680379bc100SJani Nikula enum mipi_seq seq_id)
681379bc100SJani Nikula {
682379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev);
6833cf05076SVille Syrjälä struct intel_connector *connector = intel_dsi->attached_connector;
684379bc100SJani Nikula const u8 *data;
685379bc100SJani Nikula fn_mipi_elem_exec mipi_elem_exec;
686379bc100SJani Nikula
687f4224a4cSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm,
6883cf05076SVille Syrjälä seq_id >= ARRAY_SIZE(connector->panel.vbt.dsi.sequence)))
689379bc100SJani Nikula return;
690379bc100SJani Nikula
6913cf05076SVille Syrjälä data = connector->panel.vbt.dsi.sequence[seq_id];
692379bc100SJani Nikula if (!data)
693379bc100SJani Nikula return;
694379bc100SJani Nikula
695f4224a4cSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, *data != seq_id);
696379bc100SJani Nikula
697e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "Starting MIPI sequence %d - %s\n",
698379bc100SJani Nikula seq_id, sequence_name(seq_id));
699379bc100SJani Nikula
700379bc100SJani Nikula /* Skip Sequence Byte. */
701379bc100SJani Nikula data++;
702379bc100SJani Nikula
703379bc100SJani Nikula /* Skip Size of Sequence. */
7043cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version >= 3)
705379bc100SJani Nikula data += 4;
706379bc100SJani Nikula
707379bc100SJani Nikula while (1) {
708379bc100SJani Nikula u8 operation_byte = *data++;
709379bc100SJani Nikula u8 operation_size = 0;
710379bc100SJani Nikula
711379bc100SJani Nikula if (operation_byte == MIPI_SEQ_ELEM_END)
712379bc100SJani Nikula break;
713379bc100SJani Nikula
714379bc100SJani Nikula if (operation_byte < ARRAY_SIZE(exec_elem))
715379bc100SJani Nikula mipi_elem_exec = exec_elem[operation_byte];
716379bc100SJani Nikula else
717379bc100SJani Nikula mipi_elem_exec = NULL;
718379bc100SJani Nikula
719379bc100SJani Nikula /* Size of Operation. */
7203cf05076SVille Syrjälä if (connector->panel.vbt.dsi.seq_version >= 3)
721379bc100SJani Nikula operation_size = *data++;
722379bc100SJani Nikula
723379bc100SJani Nikula if (mipi_elem_exec) {
724379bc100SJani Nikula const u8 *next = data + operation_size;
725379bc100SJani Nikula
726379bc100SJani Nikula data = mipi_elem_exec(intel_dsi, data);
727379bc100SJani Nikula
728379bc100SJani Nikula /* Consistency check if we have size. */
729379bc100SJani Nikula if (operation_size && data != next) {
730e8441414SWambui Karuga drm_err(&dev_priv->drm,
731e8441414SWambui Karuga "Inconsistent operation size\n");
732379bc100SJani Nikula return;
733379bc100SJani Nikula }
734379bc100SJani Nikula } else if (operation_size) {
735379bc100SJani Nikula /* We have size, skip. */
736e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm,
737e8441414SWambui Karuga "Unsupported MIPI operation byte %u\n",
738379bc100SJani Nikula operation_byte);
739379bc100SJani Nikula data += operation_size;
740379bc100SJani Nikula } else {
741379bc100SJani Nikula /* No size, can't skip without parsing. */
742e8441414SWambui Karuga drm_err(&dev_priv->drm,
743e8441414SWambui Karuga "Unsupported MIPI operation byte %u\n",
744379bc100SJani Nikula operation_byte);
745379bc100SJani Nikula return;
746379bc100SJani Nikula }
747379bc100SJani Nikula }
748379bc100SJani Nikula }
749379bc100SJani Nikula
intel_dsi_vbt_exec_sequence(struct intel_dsi * intel_dsi,enum mipi_seq seq_id)750ea0fe672SHans de Goede void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
751ea0fe672SHans de Goede enum mipi_seq seq_id)
752ea0fe672SHans de Goede {
753ea0fe672SHans de Goede if (seq_id == MIPI_SEQ_POWER_ON && intel_dsi->gpio_panel)
754ea0fe672SHans de Goede gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
75525e8a383SHans de Goede if (seq_id == MIPI_SEQ_BACKLIGHT_ON && intel_dsi->gpio_backlight)
75625e8a383SHans de Goede gpiod_set_value_cansleep(intel_dsi->gpio_backlight, 1);
757ea0fe672SHans de Goede
758ea0fe672SHans de Goede intel_dsi_vbt_exec(intel_dsi, seq_id);
759ea0fe672SHans de Goede
760ea0fe672SHans de Goede if (seq_id == MIPI_SEQ_POWER_OFF && intel_dsi->gpio_panel)
761ea0fe672SHans de Goede gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
76225e8a383SHans de Goede if (seq_id == MIPI_SEQ_BACKLIGHT_OFF && intel_dsi->gpio_backlight)
76325e8a383SHans de Goede gpiod_set_value_cansleep(intel_dsi->gpio_backlight, 0);
764ea0fe672SHans de Goede }
765ea0fe672SHans de Goede
intel_dsi_log_params(struct intel_dsi * intel_dsi)766379bc100SJani Nikula void intel_dsi_log_params(struct intel_dsi *intel_dsi)
767379bc100SJani Nikula {
768e8441414SWambui Karuga struct drm_i915_private *i915 = to_i915(intel_dsi->base.base.dev);
769e8441414SWambui Karuga
770e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Pclk %d\n", intel_dsi->pclk);
771e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Pixel overlap %d\n",
772e8441414SWambui Karuga intel_dsi->pixel_overlap);
773e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Lane count %d\n", intel_dsi->lane_count);
774e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "DPHY param reg 0x%x\n", intel_dsi->dphy_reg);
775e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Video mode format %s\n",
7768f0991ccSJani Nikula intel_dsi->video_mode == NON_BURST_SYNC_PULSE ?
777379bc100SJani Nikula "non-burst with sync pulse" :
7788f0991ccSJani Nikula intel_dsi->video_mode == NON_BURST_SYNC_EVENTS ?
779379bc100SJani Nikula "non-burst with sync events" :
7808f0991ccSJani Nikula intel_dsi->video_mode == BURST_MODE ?
781379bc100SJani Nikula "burst" : "<unknown>");
782e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Burst mode ratio %d\n",
783e8441414SWambui Karuga intel_dsi->burst_mode_ratio);
784e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Reset timer %d\n", intel_dsi->rst_timer_val);
785e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Eot %s\n",
786ff9fbe7cSLucas De Marchi str_enabled_disabled(intel_dsi->eotp_pkt));
787e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Clockstop %s\n",
788ff9fbe7cSLucas De Marchi str_enabled_disabled(!intel_dsi->clock_stop));
789e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Mode %s\n",
790e8441414SWambui Karuga intel_dsi->operation_mode ? "command" : "video");
791379bc100SJani Nikula if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
792e8441414SWambui Karuga drm_dbg_kms(&i915->drm,
793e8441414SWambui Karuga "Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
794379bc100SJani Nikula else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
795e8441414SWambui Karuga drm_dbg_kms(&i915->drm,
796e8441414SWambui Karuga "Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
797379bc100SJani Nikula else
798e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Dual link: NONE\n");
799e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Pixel Format %d\n", intel_dsi->pixel_format);
800e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "TLPX %d\n", intel_dsi->escape_clk_div);
801e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "LP RX Timeout 0x%x\n",
802e8441414SWambui Karuga intel_dsi->lp_rx_timeout);
803e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Turnaround Timeout 0x%x\n",
804e8441414SWambui Karuga intel_dsi->turn_arnd_val);
805e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "Init Count 0x%x\n", intel_dsi->init_count);
806e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "HS to LP Count 0x%x\n",
807e8441414SWambui Karuga intel_dsi->hs_to_lp_count);
808e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
809e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
810e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "LP to HS Clock Count 0x%x\n",
811e8441414SWambui Karuga intel_dsi->clk_lp_to_hs_count);
812e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "HS to LP Clock Count 0x%x\n",
813e8441414SWambui Karuga intel_dsi->clk_hs_to_lp_count);
814e8441414SWambui Karuga drm_dbg_kms(&i915->drm, "BTA %s\n",
815ff9fbe7cSLucas De Marchi str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
816379bc100SJani Nikula }
817379bc100SJani Nikula
intel_dsi_vbt_init(struct intel_dsi * intel_dsi,u16 panel_id)818379bc100SJani Nikula bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
819379bc100SJani Nikula {
820379bc100SJani Nikula struct drm_device *dev = intel_dsi->base.base.dev;
821379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(dev);
8223cf05076SVille Syrjälä struct intel_connector *connector = intel_dsi->attached_connector;
8233cf05076SVille Syrjälä struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
8243cf05076SVille Syrjälä struct mipi_pps_data *pps = connector->panel.vbt.dsi.pps;
8253cf05076SVille Syrjälä struct drm_display_mode *mode = connector->panel.vbt.lfp_lvds_vbt_mode;
826379bc100SJani Nikula u16 burst_mode_ratio;
827379bc100SJani Nikula enum port port;
828379bc100SJani Nikula
829e8441414SWambui Karuga drm_dbg_kms(&dev_priv->drm, "\n");
830379bc100SJani Nikula
831379bc100SJani Nikula intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
832379bc100SJani Nikula intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
833379bc100SJani Nikula intel_dsi->lane_count = mipi_config->lane_cnt + 1;
834379bc100SJani Nikula intel_dsi->pixel_format =
835379bc100SJani Nikula pixel_format_from_register_bits(
836379bc100SJani Nikula mipi_config->videomode_color_format << 7);
837379bc100SJani Nikula
838379bc100SJani Nikula intel_dsi->dual_link = mipi_config->dual_link;
839379bc100SJani Nikula intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
840379bc100SJani Nikula intel_dsi->operation_mode = mipi_config->is_cmd_mode;
8418f0991ccSJani Nikula intel_dsi->video_mode = mipi_config->video_transfer_mode;
842379bc100SJani Nikula intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
843379bc100SJani Nikula intel_dsi->lp_rx_timeout = mipi_config->lp_rx_timeout;
844379bc100SJani Nikula intel_dsi->hs_tx_timeout = mipi_config->hs_tx_timeout;
845379bc100SJani Nikula intel_dsi->turn_arnd_val = mipi_config->turn_around_timeout;
846379bc100SJani Nikula intel_dsi->rst_timer_val = mipi_config->device_reset_timer;
847379bc100SJani Nikula intel_dsi->init_count = mipi_config->master_init_timer;
848379bc100SJani Nikula intel_dsi->bw_timer = mipi_config->dbi_bw_timer;
849379bc100SJani Nikula intel_dsi->video_frmt_cfg_bits =
850379bc100SJani Nikula mipi_config->bta_enabled ? DISABLE_VIDEO_BTA : 0;
851379bc100SJani Nikula intel_dsi->bgr_enabled = mipi_config->rgb_flip;
852379bc100SJani Nikula
853379bc100SJani Nikula /* Starting point, adjusted depending on dual link and burst mode */
854379bc100SJani Nikula intel_dsi->pclk = mode->clock;
855379bc100SJani Nikula
856379bc100SJani Nikula /* In dual link mode each port needs half of pixel clock */
857379bc100SJani Nikula if (intel_dsi->dual_link) {
858379bc100SJani Nikula intel_dsi->pclk /= 2;
859379bc100SJani Nikula
860379bc100SJani Nikula /* we can enable pixel_overlap if needed by panel. In this
861379bc100SJani Nikula * case we need to increase the pixelclock for extra pixels
862379bc100SJani Nikula */
863379bc100SJani Nikula if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) {
864379bc100SJani Nikula intel_dsi->pclk += DIV_ROUND_UP(mode->vtotal * intel_dsi->pixel_overlap * 60, 1000);
865379bc100SJani Nikula }
866379bc100SJani Nikula }
867379bc100SJani Nikula
868379bc100SJani Nikula /* Burst Mode Ratio
869379bc100SJani Nikula * Target ddr frequency from VBT / non burst ddr freq
870379bc100SJani Nikula * multiply by 100 to preserve remainder
871379bc100SJani Nikula */
8728f0991ccSJani Nikula if (intel_dsi->video_mode == BURST_MODE) {
873379bc100SJani Nikula if (mipi_config->target_burst_mode_freq) {
874379bc100SJani Nikula u32 bitrate = intel_dsi_bitrate(intel_dsi);
875379bc100SJani Nikula
876379bc100SJani Nikula /*
877379bc100SJani Nikula * Sometimes the VBT contains a slightly lower clock,
878379bc100SJani Nikula * then the bitrate we have calculated, in this case
879379bc100SJani Nikula * just replace it with the calculated bitrate.
880379bc100SJani Nikula */
881379bc100SJani Nikula if (mipi_config->target_burst_mode_freq < bitrate &&
882379bc100SJani Nikula intel_fuzzy_clock_check(
883379bc100SJani Nikula mipi_config->target_burst_mode_freq,
884379bc100SJani Nikula bitrate))
885379bc100SJani Nikula mipi_config->target_burst_mode_freq = bitrate;
886379bc100SJani Nikula
887379bc100SJani Nikula if (mipi_config->target_burst_mode_freq < bitrate) {
888e8441414SWambui Karuga drm_err(&dev_priv->drm,
889e8441414SWambui Karuga "Burst mode freq is less than computed\n");
890379bc100SJani Nikula return false;
891379bc100SJani Nikula }
892379bc100SJani Nikula
893379bc100SJani Nikula burst_mode_ratio = DIV_ROUND_UP(
894379bc100SJani Nikula mipi_config->target_burst_mode_freq * 100,
895379bc100SJani Nikula bitrate);
896379bc100SJani Nikula
897379bc100SJani Nikula intel_dsi->pclk = DIV_ROUND_UP(intel_dsi->pclk * burst_mode_ratio, 100);
898379bc100SJani Nikula } else {
899e8441414SWambui Karuga drm_err(&dev_priv->drm,
900e8441414SWambui Karuga "Burst mode target is not set\n");
901379bc100SJani Nikula return false;
902379bc100SJani Nikula }
903379bc100SJani Nikula } else
904379bc100SJani Nikula burst_mode_ratio = 100;
905379bc100SJani Nikula
906379bc100SJani Nikula intel_dsi->burst_mode_ratio = burst_mode_ratio;
907379bc100SJani Nikula
908379bc100SJani Nikula /* delays in VBT are in unit of 100us, so need to convert
909379bc100SJani Nikula * here in ms
910379bc100SJani Nikula * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
911379bc100SJani Nikula intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
912379bc100SJani Nikula intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
913379bc100SJani Nikula intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
914379bc100SJani Nikula intel_dsi->panel_off_delay = pps->panel_off_delay / 10;
915379bc100SJani Nikula intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10;
916379bc100SJani Nikula
9178cbf89dbSVivek Kasireddy intel_dsi->i2c_bus_num = -1;
9188cbf89dbSVivek Kasireddy
919379bc100SJani Nikula /* a regular driver would get the device in probe */
920379bc100SJani Nikula for_each_dsi_port(port, intel_dsi->ports) {
921379bc100SJani Nikula mipi_dsi_attach(intel_dsi->dsi_hosts[port]->device);
922379bc100SJani Nikula }
923379bc100SJani Nikula
924379bc100SJani Nikula return true;
925379bc100SJani Nikula }
926ea0fe672SHans de Goede
927ea0fe672SHans de Goede /*
928ea0fe672SHans de Goede * On some BYT/CHT devs some sequences are incomplete and we need to manually
929067d1cf7SHans de Goede * control some GPIOs. We need to add a GPIO lookup table before we get these.
93025e8a383SHans de Goede * If the GOP did not initialize the panel (HDMI inserted) we may need to also
93125e8a383SHans de Goede * change the pinmux for the SoC's PWM0 pin from GPIO to PWM.
932ea0fe672SHans de Goede */
933067d1cf7SHans de Goede static struct gpiod_lookup_table pmic_panel_gpio_table = {
934067d1cf7SHans de Goede /* Intel GFX is consumer */
935067d1cf7SHans de Goede .dev_id = "0000:00:02.0",
936067d1cf7SHans de Goede .table = {
937067d1cf7SHans de Goede /* Panel EN/DISABLE */
938067d1cf7SHans de Goede GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
939067d1cf7SHans de Goede { }
940067d1cf7SHans de Goede },
941067d1cf7SHans de Goede };
942067d1cf7SHans de Goede
94325e8a383SHans de Goede static struct gpiod_lookup_table soc_panel_gpio_table = {
94425e8a383SHans de Goede .dev_id = "0000:00:02.0",
94525e8a383SHans de Goede .table = {
94625e8a383SHans de Goede GPIO_LOOKUP("INT33FC:01", 10, "backlight", GPIO_ACTIVE_HIGH),
94725e8a383SHans de Goede GPIO_LOOKUP("INT33FC:01", 11, "panel", GPIO_ACTIVE_HIGH),
94825e8a383SHans de Goede { }
94925e8a383SHans de Goede },
95025e8a383SHans de Goede };
95125e8a383SHans de Goede
95225e8a383SHans de Goede static const struct pinctrl_map soc_pwm_pinctrl_map[] = {
95325e8a383SHans de Goede PIN_MAP_MUX_GROUP("0000:00:02.0", "soc_pwm0", "INT33FC:00",
95425e8a383SHans de Goede "pwm0_grp", "pwm"),
95525e8a383SHans de Goede };
95625e8a383SHans de Goede
intel_dsi_vbt_gpio_init(struct intel_dsi * intel_dsi,bool panel_is_on)9576c0a878eSHans de Goede void intel_dsi_vbt_gpio_init(struct intel_dsi *intel_dsi, bool panel_is_on)
958ea0fe672SHans de Goede {
959ea0fe672SHans de Goede struct drm_device *dev = intel_dsi->base.base.dev;
960ea0fe672SHans de Goede struct drm_i915_private *dev_priv = to_i915(dev);
9613cf05076SVille Syrjälä struct intel_connector *connector = intel_dsi->attached_connector;
9623cf05076SVille Syrjälä struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
9636c0a878eSHans de Goede enum gpiod_flags flags = panel_is_on ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
96425e8a383SHans de Goede bool want_backlight_gpio = false;
96525e8a383SHans de Goede bool want_panel_gpio = false;
96625e8a383SHans de Goede struct pinctrl *pinctrl;
96725e8a383SHans de Goede int ret;
968ea0fe672SHans de Goede
969ea0fe672SHans de Goede if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
970ea0fe672SHans de Goede mipi_config->pwm_blc == PPS_BLC_PMIC) {
971067d1cf7SHans de Goede gpiod_add_lookup_table(&pmic_panel_gpio_table);
97225e8a383SHans de Goede want_panel_gpio = true;
97325e8a383SHans de Goede }
974067d1cf7SHans de Goede
97525e8a383SHans de Goede if (IS_VALLEYVIEW(dev_priv) && mipi_config->pwm_blc == PPS_BLC_SOC) {
97625e8a383SHans de Goede gpiod_add_lookup_table(&soc_panel_gpio_table);
97725e8a383SHans de Goede want_panel_gpio = true;
97825e8a383SHans de Goede want_backlight_gpio = true;
97925e8a383SHans de Goede
98025e8a383SHans de Goede /* Ensure PWM0 pin is muxed as PWM instead of GPIO */
98125e8a383SHans de Goede ret = pinctrl_register_mappings(soc_pwm_pinctrl_map,
98225e8a383SHans de Goede ARRAY_SIZE(soc_pwm_pinctrl_map));
98325e8a383SHans de Goede if (ret)
984e8441414SWambui Karuga drm_err(&dev_priv->drm,
985e8441414SWambui Karuga "Failed to register pwm0 pinmux mapping\n");
98625e8a383SHans de Goede
98725e8a383SHans de Goede pinctrl = devm_pinctrl_get_select(dev->dev, "soc_pwm0");
98825e8a383SHans de Goede if (IS_ERR(pinctrl))
989e8441414SWambui Karuga drm_err(&dev_priv->drm,
990e8441414SWambui Karuga "Failed to set pinmux to PWM\n");
99125e8a383SHans de Goede }
99225e8a383SHans de Goede
99325e8a383SHans de Goede if (want_panel_gpio) {
9946c0a878eSHans de Goede intel_dsi->gpio_panel = gpiod_get(dev->dev, "panel", flags);
995ea0fe672SHans de Goede if (IS_ERR(intel_dsi->gpio_panel)) {
996e8441414SWambui Karuga drm_err(&dev_priv->drm,
997e8441414SWambui Karuga "Failed to own gpio for panel control\n");
998ea0fe672SHans de Goede intel_dsi->gpio_panel = NULL;
999ea0fe672SHans de Goede }
1000ea0fe672SHans de Goede }
100125e8a383SHans de Goede
100225e8a383SHans de Goede if (want_backlight_gpio) {
100325e8a383SHans de Goede intel_dsi->gpio_backlight =
100425e8a383SHans de Goede gpiod_get(dev->dev, "backlight", flags);
100525e8a383SHans de Goede if (IS_ERR(intel_dsi->gpio_backlight)) {
1006e8441414SWambui Karuga drm_err(&dev_priv->drm,
1007e8441414SWambui Karuga "Failed to own gpio for backlight control\n");
100825e8a383SHans de Goede intel_dsi->gpio_backlight = NULL;
100925e8a383SHans de Goede }
101025e8a383SHans de Goede }
1011ea0fe672SHans de Goede }
1012ea0fe672SHans de Goede
intel_dsi_vbt_gpio_cleanup(struct intel_dsi * intel_dsi)1013ea0fe672SHans de Goede void intel_dsi_vbt_gpio_cleanup(struct intel_dsi *intel_dsi)
1014ea0fe672SHans de Goede {
1015067d1cf7SHans de Goede struct drm_device *dev = intel_dsi->base.base.dev;
1016067d1cf7SHans de Goede struct drm_i915_private *dev_priv = to_i915(dev);
10173cf05076SVille Syrjälä struct intel_connector *connector = intel_dsi->attached_connector;
10183cf05076SVille Syrjälä struct mipi_config *mipi_config = connector->panel.vbt.dsi.config;
1019067d1cf7SHans de Goede
1020ea0fe672SHans de Goede if (intel_dsi->gpio_panel) {
1021ea0fe672SHans de Goede gpiod_put(intel_dsi->gpio_panel);
1022ea0fe672SHans de Goede intel_dsi->gpio_panel = NULL;
1023ea0fe672SHans de Goede }
1024067d1cf7SHans de Goede
102525e8a383SHans de Goede if (intel_dsi->gpio_backlight) {
102625e8a383SHans de Goede gpiod_put(intel_dsi->gpio_backlight);
102725e8a383SHans de Goede intel_dsi->gpio_backlight = NULL;
102825e8a383SHans de Goede }
102925e8a383SHans de Goede
1030067d1cf7SHans de Goede if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
1031067d1cf7SHans de Goede mipi_config->pwm_blc == PPS_BLC_PMIC)
1032067d1cf7SHans de Goede gpiod_remove_lookup_table(&pmic_panel_gpio_table);
103325e8a383SHans de Goede
103425e8a383SHans de Goede if (IS_VALLEYVIEW(dev_priv) && mipi_config->pwm_blc == PPS_BLC_SOC) {
103525e8a383SHans de Goede pinctrl_unregister_mappings(soc_pwm_pinctrl_map);
103625e8a383SHans de Goede gpiod_remove_lookup_table(&soc_panel_gpio_table);
103725e8a383SHans de Goede }
1038ea0fe672SHans de Goede }
1039