@@ -745,6 +745,72 @@ static u8 *goto_next_sequence(u8 *data, int *size)
return data;
}
+
+/*
+ * Structure of single sequence in v3 version.
+ * ___________ _________ __________ ________ ________ _________
+ * | | | First |Size of |Payload | |End of |
+ * | Sequence | Size of | Opreation|First Op|First Op| |Current|
+ * | byte | Sequence| byte |byte |byte | |Seq(00)|
+ * |___________|_________|__________|________|________| ...|_______|
+ * | 1 byte | 4 Bytes | 1 byte |1 bytes | Y byte | |1 byte |
+ * | | (X) | | (Y) | | | |
+ * |___________|_________|__________|________|________| |_______|
+ *
+ * |<--Y--->|
+ * |<-----------------------X--------------->|
+ */
+
+static u8 *goto_next_sequence_v3(u8 *data, int *size)
+{
+ int tmp = *size;
+ int op_size;
+
+ if (--tmp < 0)
+ return NULL;
+
+ /* Skip the panel id and the sequence byte */
+ data = data + 5;
+ tmp = tmp - 5;
+ while (*data != 0) {
+ u8 operation_type = *data++;
+
+ switch (operation_type) {
+ default:
+ DRM_ERROR("Unknown operation type %d\n", operation_type);
+ case MIPI_SEQ_ELEM_SEND_PKT:
+ case MIPI_SEQ_ELEM_DELAY:
+ case MIPI_SEQ_ELEM_GPIO:
+ case MIPI_SEQ_ELEM_I2C:
+ case MIPI_SEQ_ELEM_SPI:
+ case MIPI_SEQ_ELEM_PMIC:
+ /*
+ * skip by this element payload size
+ * skip elem id, command flag and data type
+ */
+ op_size = *data++;
+ tmp = tmp - (op_size + 1);
+ if (tmp < 0)
+ return NULL;
+
+ /* skip by len */
+ data += op_size;
+ break;
+ }
+ }
+
+ /* goto next sequence or end of block byte */
+ if (--tmp < 0)
+ return NULL;
+
+ /* Skip the end element marker */
+ data++;
+
+ /* update amount of data left for the sequence block to be parsed */
+ *size = tmp;
+ return data;
+}
+
static void
parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
{
@@ -754,8 +820,8 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
const struct mipi_pps_data *pps;
u8 *data;
const u8 *seq_data;
- int i, panel_id, seq_size;
- u16 block_size;
+ int i, panel_id, panel_seq_size;
+ u32 block_size;
/* parse MIPI blocks only if LFP type is MIPI */
if (!dev_priv->vbt.has_mipi)
@@ -817,29 +883,40 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
- block_size = get_blocksize(sequence);
-
/*
* parse the sequence block for individual sequences
*/
dev_priv->vbt.dsi.seq_version = sequence->version;
seq_data = &sequence->data[0];
+ if (dev_priv->vbt.dsi.seq_version >= 3) {
+ block_size = *((unsigned int *)seq_data);
+ seq_data = seq_data + 4;
+ } else
+ block_size = get_blocksize(sequence);
/*
* sequence block is variable length and hence we need to parse and
* get the sequence data for specific panel id
*/
for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) {
- panel_id = *seq_data;
- seq_size = *((u16 *) (seq_data + 1));
+ panel_id = *seq_data++;
+ if (dev_priv->vbt.dsi.seq_version >= 3) {
+ panel_seq_size = *((u32 *)seq_data);
+ seq_data += sizeof(u32);
+ } else {
+ panel_seq_size = *((u16 *)seq_data);
+ seq_data += sizeof(u16);
+ }
+
if (panel_id == panel_type)
break;
- /* skip the sequence including seq header of 3 bytes */
- seq_data = seq_data + 3 + seq_size;
+ seq_data += panel_seq_size;
+
if ((seq_data - &sequence->data[0]) > block_size) {
- DRM_ERROR("Sequence start is beyond sequence block size, corrupted sequence block\n");
+ DRM_ERROR("Sequence start is beyond seq block size \
+ corrupted sequence block\n");
return;
}
}
@@ -851,13 +928,14 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
/* check if found sequence is completely within the sequence block
* just being paranoid */
- if (seq_size > block_size) {
+ if (panel_seq_size > block_size) {
DRM_ERROR("Corrupted sequence/size, bailing out\n");
return;
}
- /* skip the panel id(1 byte) and seq size(2 bytes) */
- dev_priv->vbt.dsi.data = kmemdup(seq_data + 3, seq_size, GFP_KERNEL);
+
+ dev_priv->vbt.dsi.data = kmemdup(seq_data, panel_seq_size, GFP_KERNEL);
+
if (!dev_priv->vbt.dsi.data)
return;
@@ -866,29 +944,36 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
* There are only 5 types of sequences as of now
*/
data = dev_priv->vbt.dsi.data;
- dev_priv->vbt.dsi.size = seq_size;
+ dev_priv->vbt.dsi.size = panel_seq_size;
/* two consecutive 0x00 indicate end of all sequences */
- while (1) {
+ while (*data != 0) {
int seq_id = *data;
+ int seq_size;
+
if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED) {
dev_priv->vbt.dsi.sequence[seq_id] = data;
DRM_DEBUG_DRIVER("Found mipi sequence - %d\n", seq_id);
} else {
- DRM_ERROR("undefined sequence\n");
- goto err;
+ DRM_ERROR("undefined sequence - %d\n", seq_id);
+ seq_size = *(data + 1);
+ if (dev_priv->vbt.dsi.seq_version >= 3) {
+ data = data + seq_size + 1;
+ continue;
+ } else
+ goto err;
}
/* partial parsing to skip elements */
- data = goto_next_sequence(data, &seq_size);
+ if (dev_priv->vbt.dsi.seq_version >= 3)
+ data = goto_next_sequence_v3(data, &panel_seq_size);
+ else
+ data = goto_next_sequence(data, &panel_seq_size);
if (data == NULL) {
DRM_ERROR("Sequence elements going beyond block itself. Sequence block parsing failed\n");
goto err;
}
-
- if (*data == 0)
- break; /* end of sequence reached */
}
DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n");
@@ -946,6 +946,12 @@ enum mipi_seq {
MIPI_SEQ_DISPLAY_ON,
MIPI_SEQ_DISPLAY_OFF,
MIPI_SEQ_DEASSERT_RESET,
+ MIPI_SEQ_BACKLIGHT_ON,
+ MIPI_SEQ_BACKLIGHT_OFF,
+ MIPI_SEQ_TEAR_ON,
+ MIPI_SEQ_TEAR_OFF,
+ MIPI_SEQ_POWER_ON,
+ MIPI_SEQ_POWER_OFF,
MIPI_SEQ_MAX
};
@@ -955,7 +961,8 @@ enum mipi_seq_element {
MIPI_SEQ_ELEM_DELAY,
MIPI_SEQ_ELEM_GPIO,
MIPI_SEQ_ELEM_I2C,
- MIPI_SEQ_ELEM_STATUS,
+ MIPI_SEQ_ELEM_SPI,
+ MIPI_SEQ_ELEM_PMIC,
MIPI_SEQ_ELEM_MAX
};
@@ -316,6 +316,8 @@ static const char * const seq_name[] = {
static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data)
{
+ struct drm_device *dev = intel_dsi->base.base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
fn_mipi_elem_exec mipi_elem_exec;
int index;
@@ -326,6 +328,8 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data)
/* go to the first element of the sequence */
data++;
+ if (dev_priv->vbt.dsi.seq_version >= 3)
+ data = data + 4;
/* parse each byte till we reach end of sequence byte - 0x00 */
while (1) {
@@ -339,6 +343,9 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data)
/* goto element payload */
data++;
+ if (dev_priv->vbt.dsi.seq_version >= 3)
+ data++;
+
/* execute the element specific rotines */
data = mipi_elem_exec(intel_dsi, data);