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>
This commit is contained in:
Gaurav K Singh 2014-07-16 19:39:33 +05:30 committed by Damien Lespiau
parent 525044ba32
commit ac31f19264
2 changed files with 298 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include <stdint.h>
struct vbt_header {
char signature[20]; /**< Always starts with 'VBT$' */
uint16_t version; /**< decimal */
@ -729,6 +730,31 @@ struct bdb_mipi_config {
struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS];
} __attribute__ ((packed));
/* variable number of these - max 6 */
struct bdb_mipi_sequence {
uint8_t version;
uint8_t data[0];
} __attribute__ ((packed));
/* MIPI Sequnece Block definitions */
enum MIPI_SEQ {
MIPI_SEQ_UNDEFINED = 0,
MIPI_SEQ_ASSERT_RESET,
MIPI_SEQ_INIT_OTP,
MIPI_SEQ_DISPLAY_ON,
MIPI_SEQ_DISPLAY_OFF,
MIPI_SEQ_DEASSERT_RESET,
MIPI_SEQ_MAX
};
enum MIPI_SEQ_ELEMENT {
MIPI_SEQ_ELEM_UNDEFINED = 0,
MIPI_SEQ_ELEM_SEND_PKT,
MIPI_SEQ_ELEM_DELAY,
MIPI_SEQ_ELEM_GPIO,
MIPI_SEQ_ELEM_MAX
};
/*
* Driver<->VBIOS interaction occurs through scratch bits in
* GR18 & SWF*.

View File

@ -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);