@@ -712,7 +712,7 @@ static u8 *goto_next_sequence(u8 *data, int *size)
break;
case MIPI_SEQ_ELEM_I2C:
/* skip by this element payload size */
- data += 6;
+ data += 7;
len = *data;
data += len + 1;
break;
@@ -155,6 +155,9 @@ static void intel_dsi_enable(struct intel_encoder *encoder)
if (intel_dsi->dev.dev_ops->enable)
intel_dsi->dev.dev_ops->enable(&intel_dsi->dev);
+ if (intel_dsi->dev.dev_ops->enable_backlight)
+ intel_dsi->dev.dev_ops->enable_backlight(&intel_dsi->dev);
+
wait_for_dsi_fifo_empty(intel_dsi);
/* assert ip_tg_enable signal */
@@ -51,6 +51,8 @@ struct intel_dsi_dev_ops {
/* This callback must be able to assume DSI commands can be sent */
void (*disable)(struct intel_dsi_device *dsi);
+ void (*enable_backlight)(struct intel_dsi_device *dsi);
+
int (*mode_valid)(struct intel_dsi_device *dsi,
struct drm_display_mode *mode);
@@ -30,6 +30,7 @@
#include <drm/i915_drm.h>
#include <linux/slab.h>
#include <video/mipi_display.h>
+#include <linux/i2c.h>
#include <asm/intel-mid.h>
#include <video/mipi_display.h>
#include "i915_drv.h"
@@ -193,12 +194,70 @@ static u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, u8 *data)
return data;
}
+static u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, u8 *data)
+{
+ struct i2c_adapter *adapter;
+ int ret;
+ u8 reg_offset, payload_size, retries = 5;
+ struct i2c_msg msg;
+ u8 *transmit_buffer = NULL;
+
+ u8 flag = *data++;
+ u8 index = *data++;
+ u8 bus_number = *data++;
+ u16 slave_add = *(u16 *)(data);
+ data = data + 2;
+ reg_offset = *data++;
+ payload_size = *data++;
+
+ adapter = i2c_get_adapter(bus_number);
+
+ if (!adapter) {
+ DRM_ERROR("i2c_get_adapter(%u) failed, index:%u flag: %u\n",
+ (bus_number + 1), index, flag);
+ goto out;
+ }
+
+ transmit_buffer = kmalloc(1 + payload_size, GFP_TEMPORARY);
+
+ if (!transmit_buffer)
+ goto out;
+
+ transmit_buffer[0] = reg_offset;
+ memcpy(&transmit_buffer[1], data, (size_t)payload_size);
+
+ msg.addr = slave_add;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = &transmit_buffer[0];
+
+ do {
+ ret = i2c_transfer(adapter, &msg, 1);
+ if (ret == -EAGAIN)
+ usleep_range(1000, 2500);
+ else if (ret != 1) {
+ DRM_ERROR("i2c transfer failed %d\n", ret);
+ break;
+ }
+ } while (retries--);
+
+ if (retries == 0)
+ DRM_ERROR("i2c transfer failed");
+
+out:
+ kfree(transmit_buffer);
+
+ data = data + payload_size;
+ return data;
+}
+
typedef u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, u8 *data);
static const fn_mipi_elem_exec exec_elem[] = {
NULL, /* reserved */
mipi_exec_send_packet,
mipi_exec_delay,
mipi_exec_gpio,
+ mipi_exec_i2c,
NULL, /* status read; later */
};
@@ -214,7 +273,10 @@ static const char * const seq_name[] = {
"MIPI_SEQ_INIT_OTP",
"MIPI_SEQ_DISPLAY_ON",
"MIPI_SEQ_DISPLAY_OFF",
- "MIPI_SEQ_DEASSERT_RESET"
+ "MIPI_SEQ_DEASSERT_RESET",
+ "MIPI_BACKLIGHT_ON",
+ "MIPI_BACKLIGHT_OFF",
+ "MIPI_TEAR_ON",
};
static void generic_exec_sequence(struct intel_dsi *intel_dsi, char *sequence)
@@ -586,6 +648,16 @@ static void generic_disable(struct intel_dsi_device *dsi)
generic_exec_sequence(intel_dsi, sequence);
}
+void generic_enable_bklt(struct intel_dsi_device *dsi)
+{
+ struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev);
+ struct drm_device *dev = intel_dsi->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_BACKLIGHT_ON];
+ generic_exec_sequence(intel_dsi, sequence);
+}
+
static enum drm_connector_status generic_detect(struct intel_dsi_device *dsi)
{
return connector_status_connected;
@@ -618,6 +690,7 @@ struct intel_dsi_dev_ops vbt_generic_dsi_display_ops = {
.send_otp_cmds = generic_send_otp_cmds,
.enable = generic_enable,
.disable = generic_disable,
+ .enable_backlight = generic_enable_bklt,
.detect = generic_detect,
.get_hw_state = generic_get_hw_state,
.get_modes = generic_get_modes,