Allow ECC and CRC for a packet to be calculated in software. Signed-off-by: Sean Paul <seanpaul@xxxxxxxxxxxx> --- drivers/gpu/drm/drm_mipi_dsi.c | 56 ++++++++++++++++++++++++++++++++++++++++-- include/drm/drm_mipi_dsi.h | 6 +++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index 2d5ca8ee..77390e6 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -312,6 +312,54 @@ bool mipi_dsi_packet_format_is_long(u8 type) } EXPORT_SYMBOL(mipi_dsi_packet_format_is_long); +#define BIT_VAL(x, nr) ((x & BIT(nr)) >> nr) +#define XOR13(x, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13) \ + (BIT_VAL(x, b1) ^ BIT_VAL(x, b2) ^ BIT_VAL(x, b3) ^ BIT_VAL(x, b4) ^ \ + BIT_VAL(x, b5) ^ BIT_VAL(x, b6) ^ BIT_VAL(x, b7) ^ BIT_VAL(x, b8) ^ \ + BIT_VAL(x, b9) ^ BIT_VAL(x, b10) ^ BIT_VAL(x, b11) ^ \ + BIT_VAL(x, b12) ^ BIT_VAL(x, b13)) +#define XOR14(x, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14) \ + (XOR13(x, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13) ^ \ + BIT_VAL(x, b14)) + +static u8 mipi_dsi_calculate_ecc(const u8 *header) +{ + u8 ecc; + u32 v = header[2] << 16 | header[1] << 8 | header[0]; + + ecc = XOR14(v, 0, 1, 2, 4, 5, 7, 10, 11, 13, 16, 20, 21, 22, 23) | + XOR14(v, 0, 1, 3, 4, 6, 8, 10, 12, 14, 17, 20, 21, 22, 23) << 1 | + XOR13(v, 0, 2, 3, 5, 6, 9, 11, 12, 15, 18, 20, 21, 22) << 2 | + XOR13(v, 1, 2, 3, 7, 8, 9, 13, 14, 15, 19, 20, 21, 23) << 3 | + XOR13(v, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 22, 23) << 4 | + XOR13(v, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23) << 5; + return ecc; +} + +static u16 mipi_dsi_calculate_crc(struct mipi_dsi_packet *packet) +{ + static const u16 gen_code = 0x8408; + size_t i, j; + u16 ret = 0xFFFF; + + /* If the packet is zero-length, return 0xFFFF as the checksum */ + if (packet->payload_length == 0) + return 0xFFFF; + + for (i = 0; i < packet->payload_length; i++) { + u8 d = packet->payload[i]; + + for (j = 0; j < 8; j++) { + if (((ret & 1) ^ (d & 1)) > 0) + ret = ((ret >> 1) & 0x7FFF) ^ gen_code; + else + ret = (ret >> 1) & 0x7FFF; + d = (d >> 1) & 0x7F; + } + } + return ret; +} + /** * mipi_dsi_create_packet - create a packet from a message according to the * DSI protocol @@ -337,8 +385,6 @@ int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, memset(packet, 0, sizeof(*packet)); packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); - /* TODO: compute ECC if hardware support is not available */ - /* * Long write packets contain the word count in header bytes 1 and 2. * The payload follows the header and is word count bytes long. @@ -359,8 +405,14 @@ int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; } + if (msg->flags & MIPI_DSI_MSG_SW_ECC) + packet->header[3] = mipi_dsi_calculate_ecc(packet->header); + packet->size = sizeof(packet->header) + packet->payload_length; + if (msg->flags & MIPI_DSI_MSG_SW_CRC) + packet->checksum = mipi_dsi_calculate_crc(packet); + return 0; } EXPORT_SYMBOL(mipi_dsi_create_packet); diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index f1d8d0d..49d52ba 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -21,6 +21,10 @@ struct mipi_dsi_device; #define MIPI_DSI_MSG_REQ_ACK BIT(0) /* use Low Power Mode to transmit message */ #define MIPI_DSI_MSG_USE_LPM BIT(1) +/* calculate ECC in software */ +#define MIPI_DSI_MSG_SW_ECC BIT(2) +/* calculate checksum in software */ +#define MIPI_DSI_MSG_SW_CRC BIT(3) /** * struct mipi_dsi_msg - read/write DSI buffer @@ -54,12 +58,14 @@ bool mipi_dsi_packet_format_is_long(u8 type); * Packet Data, and ECC) * @payload_length: number of bytes in the payload * @payload: a pointer to a buffer containing the payload, if any + * @checksum: the CRC of the payload (only applies to long packets) */ struct mipi_dsi_packet { size_t size; u8 header[4]; size_t payload_length; const u8 *payload; + u16 checksum; }; int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, -- 2.5.0.rc2.392.g76e840b _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel