summaryrefslogtreecommitdiff
path: root/tools/intel_bios_reader.c
diff options
context:
space:
mode:
authorGaurav K Singh <gaurav.k.singh@intel.com>2014-07-16 19:39:33 +0530
committerDamien Lespiau <damien.lespiau@intel.com>2014-08-01 17:48:53 +0100
commitac31f19264d45df63fdd6591d66ae57060d1ee5e (patch)
treeb0701960ed1d695280376b34318b0eed8875958c /tools/intel_bios_reader.c
parent525044ba32a9fa848c9fb36e8bd96211d6b38e12 (diff)
intel_bios_reader: Add support to dump MIPI Sequence block #53
Signed-off-by: Gaurav K Singh <gaurav.k.singh@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Diffstat (limited to 'tools/intel_bios_reader.c')
-rw-r--r--tools/intel_bios_reader.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/tools/intel_bios_reader.c b/tools/intel_bios_reader.c
index 9f824817..4fa47a90 100644
--- a/tools/intel_bios_reader.c
+++ b/tools/intel_bios_reader.c
@@ -71,6 +71,15 @@ struct bdb_block {
void *data;
};
+static const char * const seq_name[] = {
+ "UNDEFINED",
+ "MIPI_SEQ_ASSERT_RESET",
+ "MIPI_SEQ_INIT_OTP",
+ "MIPI_SEQ_DISPLAY_ON",
+ "MIPI_SEQ_DISPLAY_OFF",
+ "MIPI_SEQ_DEASSERT_RESET",
+};
+
struct bdb_header *bdb;
struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
static int tv_present;
@@ -784,6 +793,263 @@ static void dump_mipi_config(const struct bdb_block *block)
printf("\t\tPanel power cycle delay: %d\n", pps->panel_power_cycle_delay);
}
+static uint8_t *mipi_dump_send_packet(uint8_t *data)
+{
+ uint8_t type, byte, count;
+ uint16_t len;
+
+ byte = *data++;
+ /* get packet type and increment the pointer */
+ type = *data++;
+
+ len = *((uint16_t *) data);
+ data += 2;
+ printf("\t\t SEND COMMAND: ");
+ printf("0x%x 0x%x 0x%x", byte, type, len);
+ for (count = 0; count < len; count++)
+ printf(" 0x%x",*(data+count));
+ printf("\n");
+ data += len;
+ return data;
+}
+
+static uint8_t *mipi_dump_delay(uint8_t *data)
+{
+ printf("\t\t Delay : 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3]);
+ data += 4;
+ return data;
+}
+
+static uint8_t *mipi_dump_gpio(uint8_t *data)
+{
+ uint8_t gpio, action;
+
+ printf("\t\t GPIO value:");
+ gpio = *data++;
+
+ /* pull up/down */
+ action = *data++;
+ printf(" 0x%x 0x%x\n", gpio, action);
+ return data;
+}
+
+typedef uint8_t * (*fn_mipi_elem_dump)(uint8_t *data);
+
+static const fn_mipi_elem_dump dump_elem[] = {
+ NULL, /* reserved */
+ mipi_dump_send_packet,
+ mipi_dump_delay,
+ mipi_dump_gpio,
+ NULL, /* status read; later */
+};
+
+static void dump_sequence(uint8_t *sequence)
+{
+ uint8_t *data = sequence;
+ fn_mipi_elem_dump mipi_elem_dump;
+ int index_no;
+
+ if (!sequence)
+ return;
+
+ printf("\tSequence Name: %s\n", seq_name[*data]);
+
+ /* go to the first element of the sequence */
+ data++;
+
+ /* parse each byte till we reach end of sequence byte - 0x00 */
+ while (1) {
+ index_no = *data;
+ mipi_elem_dump = dump_elem[index_no];
+ if (!mipi_elem_dump) {
+ printf("Error: Unsupported MIPI element, skipping sequence execution\n");
+ return;
+ }
+ /* goto element payload */
+ data++;
+
+ /* execute the element specifc rotines */
+ data = mipi_elem_dump(data);
+
+ /*
+ * After processing the element, data should point to
+ * next element or end of sequence
+ * check if have we reached end of sequence
+ */
+
+ if (*data == 0x00)
+ break;
+ }
+}
+
+static uint8_t *goto_next_sequence(uint8_t *data, int *size)
+{
+ uint16_t len;
+ int tmp = *size;
+
+ if (--tmp < 0)
+ return NULL;
+
+ /* goto first element */
+ data++;
+ while (1) {
+ switch (*data) {
+ case MIPI_SEQ_ELEM_SEND_PKT:
+ /*
+ * skip by this element payload size
+ * skip elem id, command flag and data type
+ */
+ tmp -= 5;
+ if (tmp < 0)
+ return NULL;
+
+ data += 3;
+ len = *((uint16_t *)data);
+
+ tmp -= len;
+ if (tmp < 0)
+ return NULL;
+
+ /* skip by len */
+ data = data + 2 + len;
+ break;
+ case MIPI_SEQ_ELEM_DELAY:
+ /* skip by elem id, and delay is 4 bytes */
+ tmp -= 5;
+ if (tmp < 0)
+ return NULL;
+
+ data += 5;
+ break;
+ case MIPI_SEQ_ELEM_GPIO:
+ tmp -= 3;
+ if (tmp < 0)
+ return NULL;
+
+ data += 3;
+ break;
+ default:
+ printf("Unknown element\n");
+ return NULL;
+ }
+
+ /* end of sequence ? */
+ if (*data == 0)
+ break;
+ }
+
+ /* goto next sequence or end of block byte */
+ if (--tmp < 0)
+ return NULL;
+
+ data++;
+
+ /* update amount of data left for the sequence block to be parsed */
+ *size = tmp;
+ return data;
+}
+
+static uint16_t get_blocksize(void *p)
+{
+ uint16_t *block_ptr, block_size;
+
+ block_ptr = (uint16_t *)((char *)p - 2);
+ block_size = *block_ptr;
+ return block_size;
+}
+
+static void dump_mipi_sequence(const struct bdb_block *block)
+{
+ struct bdb_mipi_sequence *sequence = block->data;
+ uint8_t *data, *seq_data;
+ int i, panel_id, seq_size;
+ uint16_t block_size;
+
+ /* Check if we have sequence block as well */
+ if (!sequence) {
+ printf("No MIPI Sequence found\n");
+ return;
+ }
+
+ block_size = get_blocksize(sequence);
+
+ /*
+ * parse the sequence block for individual sequences
+ */
+ seq_data = &sequence->data[0];
+
+ /*
+ * 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 = *((uint16_t *) (seq_data + 1));
+ if (panel_id == panel_type)
+ break;
+
+ /* skip the sequence including seq header of 3 bytes */
+ seq_data = seq_data + 3 + seq_size;
+ if ((seq_data - &sequence->data[0]) > block_size) {
+ printf("Sequence start is beyond sequence block size, corrupted sequence block\n");
+ return;
+ }
+ }
+
+ if (i == MAX_MIPI_CONFIGURATIONS) {
+ printf("Sequence block detected but no valid configuration\n");
+ return;
+ }
+
+ /* check if found sequence is completely within the sequence block
+ * just being paranoid */
+ if (seq_size > block_size) {
+ printf("Corrupted sequence/size, bailing out\n");
+ return;
+ }
+
+ /* skip the panel id(1 byte) and seq size(2 bytes) */
+ data = (uint8_t *) calloc(1, seq_size);
+ if (data)
+ memmove(data, seq_data + 3, seq_size);
+ else {
+ printf("Memory not allocated for sequence data\n");
+ return;
+ }
+ /*
+ * loop into the sequence data and split into multiple sequneces
+ * There are only 5 types of sequences as of now
+ */
+
+ /* two consecutive 0x00 indicate end of all sequences */
+ while (1) {
+ int seq_id = *data;
+ if (MIPI_SEQ_MAX > seq_id && seq_id > MIPI_SEQ_UNDEFINED)
+ dump_sequence(data);
+ else {
+ printf("Error:undefined sequence\n");
+ goto err;
+ }
+
+ /* partial parsing to skip elements */
+ data = goto_next_sequence(data, &seq_size);
+
+ if (data == NULL) {
+ printf("Sequence elements going beyond block itself. Sequence block parsing failed\n");
+ goto err;
+ }
+
+ if (*data == 0)
+ break; /* end of sequence reached */
+ }
+ return;
+
+err:
+ free(data);
+ data = NULL;
+}
+
+
static int
get_device_id(unsigned char *bios)
{
@@ -868,6 +1134,11 @@ struct dumper dumpers[] = {
.name = "MIPI configuration block",
.dump = dump_mipi_config,
},
+ {
+ .id = BDB_MIPI_SEQUENCE,
+ .name = "MIPI sequence block",
+ .dump = dump_mipi_sequence,
+ },
};
static void hex_dump(const struct bdb_block *block)
@@ -1042,6 +1313,7 @@ int main(int argc, char **argv)
dump_section(BDB_DRIVER_FEATURES, size);
dump_section(BDB_EDP, size);
dump_section(BDB_MIPI_CONFIG, size);
+ dump_section(BDB_MIPI_SEQUENCE, size);
for (i = 0; i < 256; i++)
dump_section(i, size);