Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / gpu / drm / gma500 / mdfld_dsi_pkg_sender.c
diff --git a/kernel/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/kernel/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
new file mode 100644 (file)
index 0000000..6b43ae3
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include <linux/freezer.h>
+#include <video/mipi_display.h>
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "mdfld_dsi_dpi.h"
+
+#define MDFLD_DSI_READ_MAX_COUNT               5000
+
+enum {
+       MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
+};
+
+enum {
+       MDFLD_DSI_PKG_SENDER_FREE = 0x0,
+       MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
+};
+
+static const char *const dsi_errors[] = {
+       "RX SOT Error",
+       "RX SOT Sync Error",
+       "RX EOT Sync Error",
+       "RX Escape Mode Entry Error",
+       "RX LP TX Sync Error",
+       "RX HS Receive Timeout Error",
+       "RX False Control Error",
+       "RX ECC Single Bit Error",
+       "RX ECC Multibit Error",
+       "RX Checksum Error",
+       "RX DSI Data Type Not Recognised",
+       "RX DSI VC ID Invalid",
+       "TX False Control Error",
+       "TX ECC Single Bit Error",
+       "TX ECC Multibit Error",
+       "TX Checksum Error",
+       "TX DSI Data Type Not Recognised",
+       "TX DSI VC ID invalid",
+       "High Contention",
+       "Low contention",
+       "DPI FIFO Under run",
+       "HS TX Timeout",
+       "LP RX Timeout",
+       "Turn Around ACK Timeout",
+       "ACK With No Error",
+       "RX Invalid TX Length",
+       "RX Prot Violation",
+       "HS Generic Write FIFO Full",
+       "LP Generic Write FIFO Full",
+       "Generic Read Data Avail"
+       "Special Packet Sent",
+       "Tearing Effect",
+};
+
+static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
+                                               u32 mask)
+{
+       struct drm_device *dev = sender->dev;
+       u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
+       int retry = 0xffff;
+
+       while (retry--) {
+               if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
+                       return 0;
+               udelay(100);
+       }
+       DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
+       return -EIO;
+}
+
+static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
+                                               BIT(26) | BIT(27) | BIT(28)));
+}
+
+static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
+}
+
+static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+       return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
+}
+
+static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
+{
+       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+       struct drm_device *dev = sender->dev;
+
+       dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
+
+       switch (mask) {
+       case BIT(0):
+       case BIT(1):
+       case BIT(2):
+       case BIT(3):
+       case BIT(4):
+       case BIT(5):
+       case BIT(6):
+       case BIT(7):
+       case BIT(8):
+       case BIT(9):
+       case BIT(10):
+       case BIT(11):
+       case BIT(12):
+       case BIT(13):
+               dev_dbg(sender->dev->dev, "No Action required\n");
+               break;
+       case BIT(14):
+               /*wait for all fifo empty*/
+               /*wait_for_all_fifos_empty(sender)*/
+               break;
+       case BIT(15):
+               dev_dbg(sender->dev->dev, "No Action required\n");
+               break;
+       case BIT(16):
+               break;
+       case BIT(17):
+               break;
+       case BIT(18):
+       case BIT(19):
+               dev_dbg(sender->dev->dev, "High/Low contention detected\n");
+               /*wait for contention recovery time*/
+               /*mdelay(10);*/
+               /*wait for all fifo empty*/
+               if (0)
+                       wait_for_all_fifos_empty(sender);
+               break;
+       case BIT(20):
+               dev_dbg(sender->dev->dev, "No Action required\n");
+               break;
+       case BIT(21):
+               /*wait for all fifo empty*/
+               /*wait_for_all_fifos_empty(sender);*/
+               break;
+       case BIT(22):
+               break;
+       case BIT(23):
+       case BIT(24):
+       case BIT(25):
+       case BIT(26):
+       case BIT(27):
+               dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
+               REG_WRITE(intr_stat_reg, mask);
+               wait_for_hs_fifos_empty(sender);
+               break;
+       case BIT(28):
+               dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
+               REG_WRITE(intr_stat_reg, mask);
+               wait_for_lp_fifos_empty(sender);
+               break;
+       case BIT(29):
+       case BIT(30):
+       case BIT(31):
+               dev_dbg(sender->dev->dev, "No Action required\n");
+               break;
+       }
+
+       if (mask & REG_READ(intr_stat_reg))
+               dev_dbg(sender->dev->dev,
+                               "Cannot clean interrupt 0x%08x\n", mask);
+       return 0;
+}
+
+static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
+{
+       struct drm_device *dev = sender->dev;
+       u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+       u32 mask;
+       u32 intr_stat;
+       int i;
+       int err = 0;
+
+       intr_stat = REG_READ(intr_stat_reg);
+
+       for (i = 0; i < 32; i++) {
+               mask = (0x00000001UL) << i;
+               if (intr_stat & mask) {
+                       dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
+                       err = handle_dsi_error(sender, mask);
+                       if (err)
+                               DRM_ERROR("Cannot handle error\n");
+               }
+       }
+       return err;
+}
+
+static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 cmd, u8 param, bool hs)
+{
+       struct drm_device *dev = sender->dev;
+       u32 ctrl_reg;
+       u32 val;
+       u8 virtual_channel = 0;
+
+       if (hs) {
+               ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+
+               /* FIXME: wait_for_hs_fifos_empty(sender); */
+       } else {
+               ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+
+               /* FIXME: wait_for_lp_fifos_empty(sender); */
+       }
+
+       val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
+               FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
+
+       REG_WRITE(ctrl_reg, val);
+
+       return 0;
+}
+
+static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, int len, bool hs)
+{
+       struct drm_device *dev = sender->dev;
+       u32 ctrl_reg;
+       u32 data_reg;
+       u32 val;
+       u8 *p;
+       u8 b1, b2, b3, b4;
+       u8 virtual_channel = 0;
+       int i;
+
+       if (hs) {
+               ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+               data_reg = sender->mipi_hs_gen_data_reg;
+
+               /* FIXME: wait_for_hs_fifos_empty(sender); */
+       } else {
+               ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+               data_reg = sender->mipi_lp_gen_data_reg;
+
+               /* FIXME: wait_for_lp_fifos_empty(sender); */
+       }
+
+       p = data;
+       for (i = 0; i < len / 4; i++) {
+               b1 = *p++;
+               b2 = *p++;
+               b3 = *p++;
+               b4 = *p++;
+
+               REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
+       }
+
+       i = len % 4;
+       if (i) {
+               b1 = 0; b2 = 0; b3 = 0;
+
+               switch (i) {
+               case 3:
+                       b1 = *p++;
+                       b2 = *p++;
+                       b3 = *p++;
+                       break;
+               case 2:
+                       b1 = *p++;
+                       b2 = *p++;
+                       break;
+               case 1:
+                       b1 = *p++;
+                       break;
+               }
+
+               REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
+       }
+
+       val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
+               FLD_VAL(data_type, 5, 0);
+
+       REG_WRITE(ctrl_reg, val);
+
+       return 0;
+}
+
+static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len)
+{
+       u8 cmd;
+
+       switch (data_type) {
+       case MIPI_DSI_DCS_SHORT_WRITE:
+       case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+       case MIPI_DSI_DCS_LONG_WRITE:
+               cmd = *data;
+               break;
+       default:
+               return 0;
+       }
+
+       /*this prevents other package sending while doing msleep*/
+       sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
+
+       /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
+       if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       }
+
+       if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       }
+       return 0;
+}
+
+static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len)
+{
+       u8 cmd;
+
+       switch (data_type) {
+       case MIPI_DSI_DCS_SHORT_WRITE:
+       case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+       case MIPI_DSI_DCS_LONG_WRITE:
+               cmd = *data;
+               break;
+       default:
+               return 0;
+       }
+
+       /*update panel status*/
+       if (unlikely(cmd == MIPI_DCS_ENTER_SLEEP_MODE)) {
+               sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       } else if (unlikely(cmd == MIPI_DCS_EXIT_SLEEP_MODE)) {
+               sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
+               /*TODO: replace it with msleep later*/
+               mdelay(120);
+       } else if (unlikely(cmd == MIPI_DCS_SOFT_RESET)) {
+               /*TODO: replace it with msleep later*/
+               mdelay(5);
+       }
+
+       sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+       return 0;
+}
+
+static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+               u8 *data, u16 len, bool hs)
+{
+       int ret;
+
+       /*handle DSI error*/
+       ret = dsi_error_handler(sender);
+       if (ret) {
+               DRM_ERROR("Error handling failed\n");
+               return -EAGAIN;
+       }
+
+       /* send pkg */
+       if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
+               DRM_ERROR("sender is busy\n");
+               return -EAGAIN;
+       }
+
+       ret = send_pkg_prepare(sender, data_type, data, len);
+       if (ret) {
+               DRM_ERROR("send_pkg_prepare error\n");
+               return ret;
+       }
+
+       switch (data_type) {
+       case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
+       case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
+       case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
+       case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
+       case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
+       case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
+       case MIPI_DSI_DCS_SHORT_WRITE:
+       case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+       case MIPI_DSI_DCS_READ:
+               ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
+               break;
+       case MIPI_DSI_GENERIC_LONG_WRITE:
+       case MIPI_DSI_DCS_LONG_WRITE:
+               ret = send_long_pkg(sender, data_type, data, len, hs);
+               break;
+       }
+
+       send_pkg_done(sender, data_type, data, len);
+
+       /*FIXME: should I query complete and fifo empty here?*/
+
+       return ret;
+}
+
+int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs)
+{
+       unsigned long flags;
+
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, MIPI_DSI_DCS_LONG_WRITE, data, len, hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+                       u8 param, u8 param_num, bool hs)
+{
+       u8 data[2];
+       unsigned long flags;
+       u8 data_type;
+
+       if (!sender) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       data[0] = cmd;
+
+       if (param_num) {
+               data_type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+               data[1] = param;
+       } else {
+               data_type = MIPI_DSI_DCS_SHORT_WRITE;
+               data[1] = 0;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, data_type, data, sizeof(data), hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+                       u8 param1, u8 param_num, bool hs)
+{
+       u8 data[2];
+       unsigned long flags;
+       u8 data_type;
+
+       if (!sender || param_num > 2) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       switch (param_num) {
+       case 0:
+               data_type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
+               data[0] = 0;
+               data[1] = 0;
+               break;
+       case 1:
+               data_type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
+               data[0] = param0;
+               data[1] = 0;
+               break;
+       case 2:
+               data_type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
+               data[0] = param0;
+               data[1] = param1;
+               break;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, data_type, data, sizeof(data), hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+                       u32 len, bool hs)
+{
+       unsigned long flags;
+
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&sender->lock, flags);
+       send_pkg(sender, MIPI_DSI_GENERIC_LONG_WRITE, data, len, hs);
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+                       u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
+{
+       unsigned long flags;
+       struct drm_device *dev = sender->dev;
+       int i;
+       u32 gen_data_reg;
+       int retry = MDFLD_DSI_READ_MAX_COUNT;
+
+       if (!sender || !data_out || !len_out) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       /**
+        * do reading.
+        * 0) send out generic read request
+        * 1) polling read data avail interrupt
+        * 2) read data
+        */
+       spin_lock_irqsave(&sender->lock, flags);
+
+       REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+       if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
+               DRM_ERROR("Can NOT clean read data valid interrupt\n");
+
+       /*send out read request*/
+       send_pkg(sender, data_type, data, len, hs);
+
+       /*polling read data avail interrupt*/
+       while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
+               udelay(100);
+               retry--;
+       }
+
+       if (!retry) {
+               spin_unlock_irqrestore(&sender->lock, flags);
+               return -ETIMEDOUT;
+       }
+
+       REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+       /*read data*/
+       if (hs)
+               gen_data_reg = sender->mipi_hs_gen_data_reg;
+       else
+               gen_data_reg = sender->mipi_lp_gen_data_reg;
+
+       for (i = 0; i < len_out; i++)
+               *(data_out + i) = REG_READ(gen_data_reg);
+
+       spin_unlock_irqrestore(&sender->lock, flags);
+
+       return 0;
+}
+
+int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+               u32 *data, u16 len, bool hs)
+{
+       if (!sender || !data || !len) {
+               DRM_ERROR("Invalid parameters\n");
+               return -EINVAL;
+       }
+
+       return __read_panel_data(sender, MIPI_DSI_DCS_READ, &cmd, 1,
+                               data, len, hs);
+}
+
+int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
+                                                               int pipe)
+{
+       struct mdfld_dsi_pkg_sender *pkg_sender;
+       struct mdfld_dsi_config *dsi_config =
+                               mdfld_dsi_get_config(dsi_connector);
+       struct drm_device *dev = dsi_config->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       const struct psb_offset *map = &dev_priv->regmap[pipe];
+       u32 mipi_val = 0;
+
+       if (!dsi_connector) {
+               DRM_ERROR("Invalid parameter\n");
+               return -EINVAL;
+       }
+
+       pkg_sender = dsi_connector->pkg_sender;
+
+       if (!pkg_sender || IS_ERR(pkg_sender)) {
+               pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
+                                                               GFP_KERNEL);
+               if (!pkg_sender) {
+                       DRM_ERROR("Create DSI pkg sender failed\n");
+                       return -ENOMEM;
+               }
+               dsi_connector->pkg_sender = (void *)pkg_sender;
+       }
+
+       pkg_sender->dev = dev;
+       pkg_sender->dsi_connector = dsi_connector;
+       pkg_sender->pipe = pipe;
+       pkg_sender->pkg_num = 0;
+       pkg_sender->panel_mode = 0;
+       pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+       /*init regs*/
+       /* FIXME: should just copy the regmap ptr ? */
+       pkg_sender->dpll_reg = map->dpll;
+       pkg_sender->dspcntr_reg = map->cntr;
+       pkg_sender->pipeconf_reg = map->conf;
+       pkg_sender->dsplinoff_reg = map->linoff;
+       pkg_sender->dspsurf_reg = map->surf;
+       pkg_sender->pipestat_reg = map->status;
+
+       pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
+       pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
+       pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
+       pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
+       pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
+       pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+       pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
+       pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
+       pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
+       pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
+
+       /*init lock*/
+       spin_lock_init(&pkg_sender->lock);
+
+       if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
+               /**
+                * For video mode, don't enable DPI timing output here,
+                * will init the DPI timing output during mode setting.
+                */
+               mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+
+               if (pipe == 0)
+                       mipi_val |= 0x2;
+
+               REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
+               REG_READ(MIPI_PORT_CONTROL(pipe));
+
+               /* do dsi controller init */
+               mdfld_dsi_controller_init(dsi_config, pipe);
+       }
+
+       return 0;
+}
+
+void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
+{
+       if (!sender || IS_ERR(sender))
+               return;
+
+       /*free*/
+       kfree(sender);
+}
+
+