diff options
Diffstat (limited to 'drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c')
-rw-r--r-- | drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c deleted file mode 100644 index 6e0de83e9f7d..000000000000 --- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * 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/delay.h> -#include <linux/freezer.h> - -#include <video/mipi_display.h> - -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_dsi_pkg_sender.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; - 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; - } - - dev = sender->dev; - - /** - * 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); -} - - |