The parser extracts the config block(#52) and sequence(#53) data
and store in private data structures.

Signed-off-by: Shobhit Kumar <shobhit.ku...@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h   |   6 ++
 drivers/gpu/drm/i915/intel_bios.c | 175 ++++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_bios.h |  34 ++++++++
 drivers/gpu/drm/i915/intel_dsi.h  |   1 +
 4 files changed, 211 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 728b9c3..9bede78 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1250,7 +1250,13 @@ struct intel_vbt_data {
 
        /* MIPI DSI */
        struct {
+               u8 seq_version;
                u16 panel_id;
+               struct mipi_config *config;
+               struct mipi_pps_data *pps;
+               u32 size;
+               u8 *data;
+               u8 *sequence[MIPI_SEQ_MAX];
        } dsi;
 
        int crt_ddc_pin;
diff --git a/drivers/gpu/drm/i915/intel_bios.c 
b/drivers/gpu/drm/i915/intel_bios.c
index cf0b25d..9d6d063 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -595,19 +595,184 @@ parse_edp(struct drm_i915_private *dev_priv, struct 
bdb_header *bdb)
        }
 }
 
+u8 *goto_next_sequence(u8 *data)
+{
+       u16 len;
+       /* goto first element */
+       data++;
+       while (1) {
+               switch (*data++) {
+               case MIPI_SEQ_ELEM_SEND_PKT:
+                       /* skip by this element payload size
+                        * skip command flag and data type */
+                       data += 2;
+                       len = *((u16 *)data);
+                       /* skip by len */
+                       data = data + 2 + len;
+                       break;
+               case MIPI_SEQ_ELEM_DELAY:
+                       data += 4;
+                       break;
+               case MIPI_SEQ_ELEM_GPIO:
+                       data += 2;
+                       break;
+               default:
+                       DRM_ERROR("Unknown element\n");
+                       break;
+               }
+
+               /* end of sequence ? */
+               if (*data == 0)
+                       break;
+       }
+       /* goto next sequence or end of block byte */
+       data++;
+       return data;
+}
+
 static void
 parse_mipi(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 {
-       struct bdb_mipi *mipi;
+       struct bdb_mipi_config *start;
+       struct bdb_mipi_sequence *sequence;
+       struct mipi_config *config;
+       struct mipi_pps_data *pps;
+       char *data, *seq_data, *seq_start;
+       int i, panel_id, seq_size;
+
+       /* Initialize this to undefined indicating no generic MIPI support */
+       dev_priv->vbt.dsi.panel_id = MIPI_DSI_UNDEFINED_PANEL_ID;
+
+       /* Block #40 is already parsed and panel_fixed_mode is
+        * stored in dev_priv->lfp_lvds_vbt_mode
+        * resuse this when needed
+        */
 
-       mipi = find_section(bdb, BDB_MIPI_CONFIG);
-       if (!mipi) {
-               DRM_DEBUG_KMS("No MIPI BDB found");
+       /* Parse #52 for panel index used from panel_type already
+        * parsed
+        */
+       start = find_section(bdb, BDB_MIPI_CONFIG);
+       if (!start) {
+               DRM_DEBUG_KMS("No MIPI config BDB found");
                return;
        }
 
-       /* XXX: add more info */
+       DRM_DEBUG_DRIVER("Found MIPI Config block, panel index = %d\n",
+                                                               panel_type);
+
+       /*
+        * get hold of the correct configuration block and pps data as per
+        * the panel_type as index
+        */
+       config = &start->config[panel_type];
+       pps = (struct mipi_pps_data *) &start->config[MAX_MIPI_CONFIGURATIONS];
+       pps = &pps[panel_type];
+
+       /* store as of now full data. Trim when we realise all is not needed */
+       dev_priv->vbt.dsi.config =
+                       kzalloc(sizeof(struct mipi_config), GFP_KERNEL);
+       if (!dev_priv->vbt.dsi.config)
+               return;
+
+       dev_priv->vbt.dsi.pps =
+                       kzalloc(sizeof(struct mipi_pps_data), GFP_KERNEL);
+       if (!dev_priv->vbt.dsi.pps) {
+               kfree(dev_priv->vbt.dsi.config);
+               return;
+       }
+
+       memcpy(dev_priv->vbt.dsi.config, config, sizeof(*config));
+       memcpy(dev_priv->vbt.dsi.pps, pps, sizeof(*pps));
+
+       /* We have mandatory mipi config blocks. Initialize as generic panel */
        dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
+
+       /* Check if we have sequence block as well */
+       sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+       if (!sequence) {
+               DRM_DEBUG_KMS("No MIPI Sequnece BDB found");
+               DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n");
+               return;
+       }
+
+       DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
+
+       /*
+        * parse the sequence block for individual sequences
+        */
+       dev_priv->vbt.dsi.seq_version = sequence->version;
+
+       seq_data = (char *)((char *)sequence + 1);
+
+       /* sequnec block is variable length and hence we need to parse and
+        * get the sequnece data for specific panel id */
+       for (i = 0; i < MAX_MIPI_CONFIGURATIONS; i++) {
+               panel_id = *seq_data;
+               seq_size = *((u16 *) (seq_data + 1));
+               if (panel_id == panel_type) {
+                       seq_start = (char *) (seq_data + 3);
+                       break;
+               }
+
+               /* skip the sequence including seq header of 3 bytes */
+               seq_data = seq_data + 3 + seq_size;
+       }
+
+       if (i == MAX_MIPI_CONFIGURATIONS)
+               return;
+
+       dev_priv->vbt.dsi.data = kzalloc(seq_size, GFP_KERNEL);
+       if (!dev_priv->vbt.dsi.data)
+               return;
+
+       memcpy(dev_priv->vbt.dsi.data, seq_start, seq_size);
+
+       /*
+        * loop into the sequence data and split into multiple sequneces
+        * There are only 5 types of sequences as of now
+        */
+       data = dev_priv->vbt.dsi.data;
+       dev_priv->vbt.dsi.size = seq_size;
+
+       /* two consecutive 0x00 inidcate end of all sequences */
+       while (1) {
+               switch (*data) {
+               case MIPI_SEQ_ASSERT_RESET:
+                       dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] =
+                                                                       data;
+                       DRM_DEBUG_DRIVER("Found MIPI_SEQ_ASSERT_RESET\n");
+                       break;
+               case MIPI_SEQ_INIT_OTP:
+                       dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = data;
+                       DRM_DEBUG_DRIVER("Found MIPI_SEQ_INIT_OTP\n");
+                       break;
+               case MIPI_SEQ_DISPLAY_ON:
+                       dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON] = data;
+                       DRM_DEBUG_DRIVER("Found MIPI_SEQ_DISPLAY_ON\n");
+                       break;
+               case MIPI_SEQ_DISPLAY_OFF:
+                       dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF] = data;
+                       DRM_DEBUG_DRIVER("Found MIPI_SEQ_DISPLAY_OFF\n");
+                       break;
+               case MIPI_SEQ_DEASSERT_RESET:
+                       dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] =
+                                                                       data;
+                       DRM_DEBUG_DRIVER("Found MIPI_SEQ_DEASSERT_RESET\n");
+                       break;
+               case MIPI_SEQ_UNDEFINED:
+               default:
+                       DRM_ERROR("undefined sequnce\n");
+                       continue;
+               }
+
+               /* partial parsing to skip elements */
+               data = goto_next_sequence(data);
+
+               if (*data == 0)
+                       break; /* end of sequence reached */
+       }
+
+       DRM_DEBUG_DRIVER("MIPI related vbt parsing complete\n");
 }
 
 static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
diff --git a/drivers/gpu/drm/i915/intel_bios.h 
b/drivers/gpu/drm/i915/intel_bios.h
index 8345e0e..dcc4bc5 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -849,4 +849,38 @@ struct bdb_mipi_sequence {
        void *data;
 };
 
+/* 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_STATUS,
+       MIPI_SEQ_ELEM_MAX
+
+};
+
+enum MIPI_GPIO_PIN_INDEX {
+       MIPI_GPIO_UNDEFINED = 0,
+       MIPI_GPIO_PANEL_ENABLE,
+       MIPI_GPIO_BL_ENABLE,
+       MIPI_GPIO_PWM_ENABLE,
+       MIPI_GPIO_RESET_N,
+       MIPI_GPIO_PWR_DOWN_R,
+       MIPI_GPIO_STDBY_RST_N,
+       MIPI_GPIO_MAX
+
+};
+
 #endif /* _I830_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index a0e42db..01b6752 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -120,6 +120,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct 
drm_encoder *encoder)
 extern void vlv_enable_dsi_pll(struct intel_encoder *encoder);
 extern void vlv_disable_dsi_pll(struct intel_encoder *encoder);
 
+#define MIPI_DSI_UNDEFINED_PANEL_ID    0
 #define MIPI_DSI_GENERIC_PANEL_ID      1
 
 #endif /* _INTEL_DSI_H */
-- 
1.8.3.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to