From patchwork Tue Dec 16 08:05:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: vandana.kannan@intel.com X-Patchwork-Id: 5499641 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7C7079F1D4 for ; Tue, 16 Dec 2014 07:47:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5985D20A1C for ; Tue, 16 Dec 2014 07:47:56 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id E809320A18 for ; Tue, 16 Dec 2014 07:47:54 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D8E086E733; Mon, 15 Dec 2014 23:47:53 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTP id C3B856E733 for ; Mon, 15 Dec 2014 23:47:52 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga102.fm.intel.com with ESMTP; 15 Dec 2014 23:47:50 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,585,1413270000"; d="scan'208";a="648291786" Received: from vkannan-desktop.iind.intel.com ([10.223.25.137]) by fmsmga002.fm.intel.com with ESMTP; 15 Dec 2014 23:47:49 -0800 From: Vandana Kannan To: intel-gfx@lists.freedesktop.org Date: Tue, 16 Dec 2014 13:35:30 +0530 Message-Id: <1418717130-28057-1-git-send-email-vandana.kannan@intel.com> X-Mailer: git-send-email 2.0.1 Subject: [Intel-gfx] [PATCH] drm/i915: Parsing logic for the Mipi sequence block X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: vkorjani New parsing logic for the mipi sequence block for GOP version 3 and above. The new version of the GOP includes the pmic, power on/off sequence which are newly adding to the existing sequences which are present. Also, there are new fields which are added in the sequence to indicate the sequence size. Signed-off-by: vkorjani Signed-off-by: Deepak M Signed-off-by: Rafael Barbalho Cc:Daniel Vetter Cc:Jani Nikula --- drivers/gpu/drm/i915/intel_bios.c | 112 ++++++++++++++++++++++++----- drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 7 ++ 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 3f17825..42300db 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -41,8 +41,10 @@ find_section(struct bdb_header *bdb, int section_id) { u8 *base = (u8 *)bdb; int index = 0; - u16 total, current_size; + u16 total; + u32 current_size; u8 current_id; + u8 version; /* skip to first section */ index += bdb->header_size; @@ -53,7 +55,16 @@ find_section(struct bdb_header *bdb, int section_id) current_id = *(base + index); index++; - current_size = *((u16 *)(base + index)); + if (current_id == BDB_MIPI_SEQUENCE) { + version = *(base + index + 2); + if (version >= 3) + current_size = *((u32 *)(base + index + 3)); + else + current_size = *((u16 *)(base + index)); + } else { + current_size = *((u16 *)(base + index)); + } + index += 2; if (index + current_size > total) @@ -775,6 +786,51 @@ static u8 *goto_next_sequence(u8 *data, int *size) return data; } +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 size */ + data = data + 5; + while (*data != 0) { + u8 element_type = *data++; + switch (element_type) { + default: + DRM_ERROR("Unknown element type %d\n", element_type); + case MIPI_SEQ_ELEM_SEND_PKT: + case MIPI_SEQ_ELEM_DELAY: + case MIPI_SEQ_ELEM_GPIO: + /* + * 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, struct bdb_header *bdb) { @@ -783,7 +839,7 @@ parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb) struct mipi_config *config; struct mipi_pps_data *pps; u8 *data, *seq_data; - int i, panel_id, seq_size; + int i, panel_id, panel_seq_size; u16 block_size; /* parse MIPI blocks only if LFP type is MIPI */ @@ -840,29 +896,40 @@ parse_mipi(struct drm_i915_private *dev_priv, 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\n"); + DRM_ERROR("Corrupted sequence block\n"); return; } } @@ -874,13 +941,12 @@ parse_mipi(struct drm_i915_private *dev_priv, 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; @@ -889,29 +955,37 @@ parse_mipi(struct drm_i915_private *dev_priv, 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; + 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"); diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 5493aef..f7e3777b 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -234,6 +234,8 @@ static const char * const seq_name[] = { static void generic_exec_sequence(struct intel_dsi *intel_dsi, char *sequence) { + struct drm_device *dev = intel_dsi->base.base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; u8 *data = sequence; fn_mipi_elem_exec mipi_elem_exec; int index; @@ -245,6 +247,8 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, char *sequence) /* 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) { @@ -258,6 +262,9 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, char *sequence) /* 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);