diff options
Diffstat (limited to 'drivers/staging/gma500/mdfld_dsi_dbi.c')
-rw-r--r-- | drivers/staging/gma500/mdfld_dsi_dbi.c | 761 |
1 files changed, 0 insertions, 761 deletions
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c deleted file mode 100644 index fd211f3467c4..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi.c +++ /dev/null @@ -1,761 +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: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dbi_dpu.h" -#include "mdfld_dsi_pkg_sender.h" - -#include "power.h" -#include <linux/pm_runtime.h> - -int enable_gfx_rtpm; - -extern struct drm_device *gpDrmDevice; -extern int gfxrtdelay; -int enter_dsr; -struct mdfld_dsi_dbi_output *gdbi_output; -extern bool gbgfxsuspended; -extern int enable_gfx_rtpm; -extern int gfxrtdelay; - -#define MDFLD_DSR_MAX_IDLE_COUNT 2 - -/* - * set refreshing area - */ -int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, - u16 x1, u16 y1, u16 x2, u16 y2) -{ - struct mdfld_dsi_pkg_sender *sender = - mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); - u8 param[4]; - u8 cmd; - int err; - - if (!sender) { - WARN_ON(1); - return -EINVAL; - } - - /* Set column */ - cmd = DCS_SET_COLUMN_ADDRESS; - param[0] = x1 >> 8; - param[1] = x1; - param[2] = x2 >> 8; - param[3] = x2; - - err = mdfld_dsi_send_dcs(sender, - cmd, - param, - 4, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); - goto err_out; - } - - /* Set page */ - cmd = DCS_SET_PAGE_ADDRESS; - param[0] = y1 >> 8; - param[1] = y1; - param[2] = y2 >> 8; - param[3] = y2; - - err = mdfld_dsi_send_dcs(sender, - cmd, - param, - 4, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); - goto err_out; - } - - /*update screen*/ - err = mdfld_dsi_send_dcs(sender, - write_mem_start, - NULL, - 0, - CMD_DATA_SRC_PIPE, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); - goto err_out; - } - mdfld_dsi_cmds_kick_out(sender); -err_out: - return err; -} - -/* - * set panel's power state - */ -int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, - int mode) -{ - struct drm_device *dev = dbi_output->dev; - struct mdfld_dsi_pkg_sender *sender = - mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); - u8 param = 0; - u32 err = 0; - - if (!sender) { - WARN_ON(1); - return -EINVAL; - } - - if (mode == DRM_MODE_DPMS_ON) { - /* Exit sleep mode */ - err = mdfld_dsi_send_dcs(sender, - DCS_EXIT_SLEEP_MODE, - NULL, - 0, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_EXIT_SLEEP_MODE); - goto power_err; - } - - /* Set display on */ - err = mdfld_dsi_send_dcs(sender, - DCS_SET_DISPLAY_ON, - NULL, - 0, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_SET_DISPLAY_ON); - goto power_err; - } - - /* set tear effect on */ - err = mdfld_dsi_send_dcs(sender, - DCS_SET_TEAR_ON, - ¶m, - 1, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - set_tear_on); - goto power_err; - } - - /** - * FIXME: remove this later - */ - err = mdfld_dsi_send_dcs(sender, - DCS_WRITE_MEM_START, - NULL, - 0, - CMD_DATA_SRC_PIPE, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_WRITE_MEM_START); - goto power_err; - } - } else { - /* Set tear effect off */ - err = mdfld_dsi_send_dcs(sender, - DCS_SET_TEAR_OFF, - NULL, - 0, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_SET_TEAR_OFF); - goto power_err; - } - - /* Turn display off */ - err = mdfld_dsi_send_dcs(sender, - DCS_SET_DISPLAY_OFF, - NULL, - 0, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_SET_DISPLAY_OFF); - goto power_err; - } - - /* Now enter sleep mode */ - err = mdfld_dsi_send_dcs(sender, - DCS_ENTER_SLEEP_MODE, - NULL, - 0, - CMD_DATA_SRC_SYSTEM_MEM, - MDFLD_DSI_QUEUE_PACKAGE); - if (err) { - dev_err(dev->dev, "DCS 0x%x sent failed\n", - DCS_ENTER_SLEEP_MODE); - goto power_err; - } - } - mdfld_dsi_cmds_kick_out(sender); -power_err: - return err; -} - -/* - * send a generic DCS command with a parameter list - */ -int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, - u8 dcs, u8 *param, u32 num, u8 data_src) -{ - struct mdfld_dsi_pkg_sender *sender = - mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); - int ret; - - if (!sender) { - WARN_ON(1); - return -EINVAL; - } - - ret = mdfld_dsi_send_dcs(sender, - dcs, - param, - num, - data_src, - MDFLD_DSI_SEND_PACKAGE); - - return ret; -} - -/* - * Enter DSR - */ -void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe) -{ - u32 reg_val; - struct drm_device *dev = dbi_output->dev; - struct drm_psb_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = dbi_output->base.base.crtc; - struct psb_intel_crtc *psb_crtc = (crtc) ? - to_psb_intel_crtc(crtc) : NULL; - u32 dpll_reg = MRST_DPLL_A; - u32 pipeconf_reg = PIPEACONF; - u32 dspcntr_reg = DSPACNTR; - - if (!dbi_output) - return; - - /* FIXME check if can go */ - dev_priv->is_in_idle = true; - - gdbi_output = dbi_output; - if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || - (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) - return; - - if (pipe == 2) { - dpll_reg = MRST_DPLL_A; - pipeconf_reg = PIPECCONF; - dspcntr_reg = DSPCCNTR; - } - - if (!gma_power_begin(dev, true)) { - dev_err(dev->dev, "hw begin failed\n"); - return; - } - /* Disable te interrupts */ - mdfld_disable_te(dev, pipe); - - /* Disable plane */ - reg_val = REG_READ(dspcntr_reg); - if (!(reg_val & DISPLAY_PLANE_ENABLE)) { - REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE); - REG_READ(dspcntr_reg); - } - - /* Disable pipe */ - reg_val = REG_READ(pipeconf_reg); - if (!(reg_val & DISPLAY_PLANE_ENABLE)) { - reg_val &= ~DISPLAY_PLANE_ENABLE; - reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF); - REG_WRITE(pipeconf_reg, reg_val); - REG_READ(pipeconf_reg); - mdfldWaitForPipeDisable(dev, pipe); - } - - /* Disable DPLL */ - reg_val = REG_READ(dpll_reg); - if (!(reg_val & DPLL_VCO_ENABLE)) { - reg_val &= ~DPLL_VCO_ENABLE; - REG_WRITE(dpll_reg, reg_val); - REG_READ(dpll_reg); - udelay(500); - } - - gma_power_end(dev); - dbi_output->mode_flags |= MODE_SETTING_IN_DSR; - if (pipe == 2) { - enter_dsr = 1; - /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ - } -} - -static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, - int pipe) -{ - struct drm_device *dev = dbi_output->dev; - struct drm_crtc *crtc = dbi_output->base.base.crtc; - struct psb_intel_crtc *psb_crtc = (crtc) ? - to_psb_intel_crtc(crtc) : NULL; - u32 reg_val; - u32 dpll_reg = MRST_DPLL_A; - u32 pipeconf_reg = PIPEACONF; - u32 dspcntr_reg = DSPACNTR; - u32 reg_offset = 0; - - /*if mode setting on-going, back off*/ - if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || - (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) - return; - - if (pipe == 2) { - dpll_reg = MRST_DPLL_A; - pipeconf_reg = PIPECCONF; - dspcntr_reg = DSPCCNTR; - reg_offset = MIPIC_REG_OFFSET; - } - - if (!gma_power_begin(dev, true)) { - dev_err(dev->dev, "hw begin failed\n"); - return; - } - - /* Enable DPLL */ - reg_val = REG_READ(dpll_reg); - if (!(reg_val & DPLL_VCO_ENABLE)) { - if (reg_val & MDFLD_PWR_GATE_EN) { - reg_val &= ~MDFLD_PWR_GATE_EN; - REG_WRITE(dpll_reg, reg_val); - REG_READ(dpll_reg); - udelay(500); - } - - reg_val |= DPLL_VCO_ENABLE; - REG_WRITE(dpll_reg, reg_val); - REG_READ(dpll_reg); - udelay(500); - - /* Add timeout */ - while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) - cpu_relax(); - } - - /* Enable pipe */ - reg_val = REG_READ(pipeconf_reg); - if (!(reg_val & PIPEACONF_ENABLE)) { - reg_val |= PIPEACONF_ENABLE; - REG_WRITE(pipeconf_reg, reg_val); - REG_READ(pipeconf_reg); - udelay(500); - mdfldWaitForPipeEnable(dev, pipe); - } - - /* Enable plane */ - reg_val = REG_READ(dspcntr_reg); - if (!(reg_val & DISPLAY_PLANE_ENABLE)) { - reg_val |= DISPLAY_PLANE_ENABLE; - REG_WRITE(dspcntr_reg, reg_val); - REG_READ(dspcntr_reg); - udelay(500); - } - - /* Enable TE interrupt on this pipe */ - mdfld_enable_te(dev, pipe); - gma_power_end(dev); - - /*clean IN_DSR flag*/ - dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; -} - -/* - * Exit from DSR - */ -void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - struct mdfld_dsi_dbi_output **dbi_output; - int i; - int pipe; - - /* FIXME can go ? */ - dev_priv->is_in_idle = false; - dbi_output = dsr_info->dbi_outputs; - -#ifdef CONFIG_PM_RUNTIME - if (!enable_gfx_rtpm) { -/* pm_runtime_allow(&gpDrmDevice->pdev->dev); */ -/* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */ - } -#endif - - /* For each output, exit dsr */ - for (i = 0; i < dsr_info->dbi_output_num; i++) { - /* If panel has been turned off, skip */ - if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on) - continue; - pipe = dbi_output[i]->channel_num ? 2 : 0; - enter_dsr = 0; - mdfld_dbi_output_exit_dsr(dbi_output[i], pipe); - } - dev_priv->dsr_fb_update |= update_src; -} - -static bool mdfld_dbi_is_in_dsr(struct drm_device *dev) -{ - if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE) - return false; - if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) || - (REG_READ(PIPECCONF) & PIPEACONF_ENABLE)) - return false; - if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) || - (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE)) - return false; - - return true; -} - -/* Periodically update dbi panel */ -void mdfld_dbi_update_panel(struct drm_device *dev, int pipe) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - struct mdfld_dsi_dbi_output **dbi_outputs; - struct mdfld_dsi_dbi_output *dbi_output; - int i; - int can_enter_dsr = 0; - u32 damage_mask; - - dbi_outputs = dsr_info->dbi_outputs; - dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0]; - - if (!dbi_output) - return; - - if (pipe == 0) - damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0; - else if (pipe == 2) - damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2; - else - return; - - /* If FB is damaged and panel is on update on-panel FB */ - if (damage_mask && dbi_output->dbi_panel_on) { - dbi_output->dsr_fb_update_done = false; - - if (dbi_output->p_funcs->update_fb) - dbi_output->p_funcs->update_fb(dbi_output, pipe); - - if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done) - dev_priv->dsr_fb_update &= ~damage_mask; - - /*clean IN_DSR flag*/ - dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; - - dbi_output->dsr_idle_count = 0; - } else { - dbi_output->dsr_idle_count++; - } - - switch (dsr_info->dbi_output_num) { - case 1: - if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) - can_enter_dsr = 1; - break; - case 2: - if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT - && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) - can_enter_dsr = 1; - break; - default: - DRM_ERROR("Wrong DBI output number\n"); - } - - /* Try to enter DSR */ - if (can_enter_dsr) { - for (i = 0; i < dsr_info->dbi_output_num; i++) { - if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] && - !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) { - mdfld_dsi_dbi_enter_dsr(dbi_outputs[i], - dbi_outputs[i]->channel_num ? 2 : 0); -#if 0 - enter_dsr = 1; - pr_err("%s: enter_dsr = 1\n", __func__); -#endif - } - } - /*schedule rpm suspend after gfxrtdelay*/ -#ifdef CONFIG_GFX_RTPM - if (!dev_priv->rpm_enabled - || !enter_dsr - /* || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */ - || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay)) - dev_warn(dev->dev, - "Runtime PM schedule suspend failed, rpm %d\n", - dev_priv->rpm_enabled); -#endif - } -} - -int mdfld_dbi_dsr_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - - if (!dsr_info || IS_ERR(dsr_info)) { - dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), - GFP_KERNEL); - if (!dsr_info) { - dev_err(dev->dev, "No memory\n"); - return -ENOMEM; - } - dev_priv->dbi_dsr_info = dsr_info; - } - return 0; -} - -void mdfld_dbi_dsr_exit(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - - if (dsr_info) { - kfree(dsr_info); - dev_priv->dbi_dsr_info = NULL; - } -} - -void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, - int pipe) -{ - struct drm_device *dev = dsi_config->dev; - u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; - int lane_count = dsi_config->lane_count; - u32 val = 0; - - dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); - - /* Un-ready device */ - REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); - - /* Init dsi adapter before kicking off */ - REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); - - /* TODO: figure out how to setup these registers */ - REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); - REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), - 0x000a0014); - REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); - REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); - REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); - - /* Enable all interrupts */ - REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); - /* Max value: 20 clock cycles of txclkesc */ - REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); - /* Min 21 txclkesc, max: ffffh */ - REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); - /* Min: 7d0 max: 4e20 */ - REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); - - /* Set up func_prg */ - val |= lane_count; - val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); - val |= DSI_DBI_COLOR_FORMAT_OPTION2; - REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); - - REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); - REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); - - /* De-assert dbi_stall when half of DBI FIFO is empty */ - /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ - - REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); - REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); - REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); - REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -#if 0 -/*DBI encoder helper funcs*/ -static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { - .dpms = mdfld_dsi_dbi_dpms, - .mode_fixup = mdfld_dsi_dbi_mode_fixup, - .prepare = mdfld_dsi_dbi_prepare, - .mode_set = mdfld_dsi_dbi_mode_set, - .commit = mdfld_dsi_dbi_commit, -}; - -/*DBI encoder funcs*/ -static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -#endif - -/* - * Init DSI DBI encoder. - * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector - * return pointer of newly allocated DBI encoder, NULL on error - */ -struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, - struct mdfld_dsi_connector *dsi_connector, - struct panel_funcs *p_funcs) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - struct mdfld_dsi_dbi_output *dbi_output = NULL; - struct mdfld_dsi_config *dsi_config; - struct drm_connector *connector = NULL; - struct drm_encoder *encoder = NULL; - struct drm_display_mode *fixed_mode = NULL; - struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL; - struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; - struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; - u32 data = 0; - int pipe; - int ret; - - if (!pg || !dsi_connector || !p_funcs) { - WARN_ON(1); - return NULL; - } - - dsi_config = mdfld_dsi_get_config(dsi_connector); - pipe = dsi_connector->pipe; - - /*panel hard-reset*/ - if (p_funcs->reset) { - ret = p_funcs->reset(pipe); - if (ret) { - DRM_ERROR("Panel %d hard-reset failed\n", pipe); - return NULL; - } - } - /* Panel drvIC init */ - if (p_funcs->drv_ic_init) - p_funcs->drv_ic_init(dsi_config, pipe); - - /* Panel power mode detect */ - ret = mdfld_dsi_get_power_mode(dsi_config, - &data, - MDFLD_DSI_HS_TRANSMISSION); - if (ret) { - DRM_ERROR("Panel %d get power mode failed\n", pipe); - dsi_connector->status = connector_status_disconnected; - } else { - DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); - dsi_connector->status = connector_status_connected; - } - - /*TODO: get panel info from DDB*/ - - dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); - if (!dbi_output) { - dev_err(dev->dev, "No memory\n"); - return NULL; - } - - if (dsi_connector->pipe == 0) { - dbi_output->channel_num = 0; - dev_priv->dbi_output = dbi_output; - } else if (dsi_connector->pipe == 2) { - dbi_output->channel_num = 1; - dev_priv->dbi_output2 = dbi_output; - } else { - dev_err(dev->dev, "only support 2 DSI outputs\n"); - goto out_err1; - } - - dbi_output->dev = dev; - dbi_output->p_funcs = p_funcs; - fixed_mode = dsi_config->fixed_mode; - dbi_output->panel_fixed_mode = fixed_mode; - - /* Create drm encoder object */ - connector = &dsi_connector->base.base; - encoder = &dbi_output->base.base; - /* Review this if we ever get MIPI-HDMI bridges or similar */ - drm_encoder_init(dev, - encoder, - p_funcs->encoder_funcs, - DRM_MODE_ENCODER_LVDS); - drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs); - - /* Attach to given connector */ - drm_mode_connector_attach_encoder(connector, encoder); - - /* Set possible CRTCs and clones */ - if (dsi_connector->pipe) { - encoder->possible_crtcs = (1 << 2); - encoder->possible_clones = (1 << 1); - } else { - encoder->possible_crtcs = (1 << 0); - encoder->possible_clones = (1 << 0); - } - - dev_priv->dsr_fb_update = 0; - dev_priv->dsr_enable = false; - dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; - - dbi_output->first_boot = true; - dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; - - /* Add this output to dpu_info if in DPU mode */ - if (dpu_info && dsi_connector->status == connector_status_connected) { - if (dsi_connector->pipe == 0) - dpu_info->dbi_outputs[0] = dbi_output; - else - dpu_info->dbi_outputs[1] = dbi_output; - - dpu_info->dbi_output_num++; - } else if (dsi_connector->status == connector_status_connected) { - /* Add this output to dsr_info if not */ - if (dsi_connector->pipe == 0) - dsr_info->dbi_outputs[0] = dbi_output; - else - dsr_info->dbi_outputs[1] = dbi_output; - - dsr_info->dbi_output_num++; - } - return &dbi_output->base; -out_err1: - kfree(dbi_output); - return NULL; -} |