[Intel-gfx] [PATCH 2/2] drm/i915: Add generic i2c mipi parsing
Vandana Kannan
vandana.kannan at intel.com
Sun Dec 7 06:27:33 PST 2014
From: vkorjani <vikas.korjani at intel.com>
The VBT now contains i2c sequences to allow the graphics driver to
bring up the device by directly writing to any devices that need to be
programmed.
Signed-off-by: vkorjani <vikas.korjani at intel.com>
Signed-off-by: Nabendu Maiti <nabendu.bikash.maiti at intel.com>
Signed-off-by: Deepak M <m.deepak at intel.com>
Signed-off-by: Rafael Barbalho <rafael.barbalho at intel.com>
---
drivers/gpu/drm/i915/intel_bios.c | 2 +-
drivers/gpu/drm/i915/intel_dsi.c | 3 ++
drivers/gpu/drm/i915/intel_dsi.h | 2 +
drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 75 +++++++++++++++++++++++++++++-
4 files changed, 80 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index c27cc6d..bb50c1a 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -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;
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 0b18407..193ac18 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -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 */
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index 657eb5c..493bd22 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -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);
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
index f6bdd44..25c05b7 100644
--- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
+++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
@@ -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,
--
2.0.1
More information about the Intel-gfx
mailing list