Loading drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c +111 −11 Original line number Diff line number Diff line Loading @@ -33,24 +33,52 @@ /* Register Offsets from PLL base address */ #define PLL_ANALOG_CONTROLS_ONE 0x000 #define PLL_ANALOG_CONTROLS_TWO 0x004 #define PLL_INT_LOOP_SETTINGS 0x008 #define PLL_INT_LOOP_SETTINGS_TWO 0x00c #define PLL_ANALOG_CONTROLS_THREE 0x010 #define PLL_ANALOG_CONTROLS_FOUR 0x014 #define PLL_INT_LOOP_CONTROLS 0x018 #define PLL_DSM_DIVIDER 0x01c #define PLL_FEEDBACK_DIVIDER 0x020 #define PLL_SYSTEM_MUXES 0x024 #define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x028 #define PLL_CMODE 0x02c #define PLL_CALIBRATION_SETTINGS 0x030 #define PLL_BAND_SEL_CAL_TIMER_LOW 0x034 #define PLL_BAND_SEL_CAL_TIMER_HIGH 0x038 #define PLL_BAND_SEL_CAL_SETTINGS 0x03c #define PLL_BAND_SEL_MIN 0x040 #define PLL_BAND_SEL_MAX 0x044 #define PLL_BAND_SEL_PFILT 0x048 #define PLL_BAND_SEL_IFILT 0x04c #define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x050 #define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054 #define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x058 #define PLL_BAND_SEL_ICODE_HIGH 0x05c #define PLL_BAND_SEL_ICODE_LOW 0x060 #define PLL_FREQ_DETECT_SETTINGS_ONE 0x064 #define PLL_PFILT 0x07c #define PLL_IFILT 0x080 #define PLL_GAIN 0x084 #define PLL_ICODE_LOW 0x088 #define PLL_ICODE_HIGH 0x08c #define PLL_LOCKDET 0x090 #define PLL_OUTDIV 0x094 #define PLL_FASTLOCK_CONTROL 0x098 #define PLL_PASS_OUT_OVERRIDE_ONE 0x09c #define PLL_PASS_OUT_OVERRIDE_TWO 0x0a0 #define PLL_CORE_OVERRIDE 0x0a4 #define PLL_CORE_INPUT_OVERRIDE 0x0a8 #define PLL_RATE_CHANGE 0x0ac #define PLL_PLL_DIGITAL_TIMERS 0x0b0 #define PLL_PLL_DIGITAL_TIMERS_TWO 0x0b4 #define PLL_DEC_FRAC_MUXES 0x0c8 #define PLL_DECIMAL_DIV_START_1 0x0cc #define PLL_FRAC_DIV_START_LOW_1 0x0d0 #define PLL_FRAC_DIV_START_MID_1 0x0d4 #define PLL_FRAC_DIV_START_HIGH_1 0x0d8 #define PLL_MASH_CONTROL 0x0ec #define PLL_SSC_MUX_CONTROL 0x108 #define PLL_SSC_STEPSIZE_LOW_1 0x10c #define PLL_SSC_STEPSIZE_HIGH_1 0x110 #define PLL_SSC_DIV_PER_LOW_1 0x114 Loading @@ -64,9 +92,16 @@ #define PLL_PLL_BAND_SET_RATE_1 0x154 #define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x15c #define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164 #define PLL_FASTLOCK_EN_BAND 0x16c #define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x17c #define PLL_PLL_LOCK_OVERRIDE 0x180 #define PLL_PLL_LOCK_DELAY 0x184 #define PLL_PLL_LOCK_MIN_DELAY 0x188 #define PLL_CLOCK_INVERTERS 0x18c #define PLL_SPARE_AND_JPC_OVERRIDES 0x190 #define PLL_BIAS_CONTROL_1 0x194 #define PLL_BIAS_CONTROL_2 0x198 #define PLL_ALOG_OBSV_BUS_CTRL_1 0x19c #define PLL_COMMON_STATUS_ONE 0x1a0 /* Register Offsets from PHY base address */ Loading Loading @@ -249,7 +284,7 @@ static inline int pclk_mux_read_sel(void *context, unsigned int reg, if (rc) pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); else *val = (MDSS_PLL_REG_R(rsc->pll_base, reg) & 0x3); *val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3); (void)mdss_pll_resource_enable(rsc, false); return rc; Loading Loading @@ -503,6 +538,49 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll, MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f); } static void dsi_pll_init_val(struct mdss_pll_resources *rsc) { void __iomem *pll_base = rsc->pll_base; MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0); MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80); MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0); MDSS_PLL_REG_W(pll_base, PLL_GAIN, 0x42); MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00); MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00); MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30); MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04); MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00); MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00); MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01); MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08); MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00); MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03); MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0); MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0); MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03); MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0); MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19); MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40); MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20); MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0); } static void dsi_pll_commit(struct dsi_pll_10nm *pll, struct mdss_pll_resources *rsc) { Loading Loading @@ -559,6 +637,8 @@ static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, return rc; } dsi_pll_init_val(rsc); dsi_pll_setup_config(pll, rsc); dsi_pll_calc_dec_frac(pll, rsc); Loading Loading @@ -741,12 +821,32 @@ static void vco_10nm_unprepare(struct clk_hw *hw) pr_err("dsi pll resources not available\n"); return; } pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); /* * During unprepare in continuous splash use case we want driver * to pick all dividers instead of retaining bootloader configurations. */ if (!pll->handoff_resources) { pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, pll->cached_cfg1, pll->cached_outdiv); pll->vco_cached_rate = clk_hw_get_rate(hw); } /* * When continuous splash screen feature is enabled, we need to cache * the mux configuration for the pixel_clk_src mux clock. The clock * framework does not call back to re-configure the mux value if it is * does not change.For such usecases, we need to ensure that the cached * value is programmed prior to PLL being locked */ if (pll->handoff_resources) pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1); dsi_pll_disable(vco); mdss_pll_resource_enable(pll, false); } Loading Loading @@ -1026,8 +1126,8 @@ static struct regmap_bus pll_regmap_bus = { .reg_read = pll_reg_read, }; static struct regmap_bus pclk_mux_regmap_bus = { .reg_read = phy_reg_read, static struct regmap_bus pclk_src_mux_regmap_bus = { .reg_read = pclk_mux_read_sel, .reg_write = pclk_mux_write_sel, }; Loading Loading @@ -1472,7 +1572,7 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev, pll_res, &dsi_pll_10nm_config); dsi0pll_pclk_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi0pll_pclk_src_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, Loading Loading @@ -1510,11 +1610,11 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_src.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_src_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, Loading drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, dsi_ctrl_hw_14_reg_dump_to_buffer; ctrl->ops.schedule_dma_cmd = NULL; ctrl->ops.get_cont_splash_status = NULL; ctrl->ops.kickoff_command_non_embedded_mode = NULL; break; case DSI_CTRL_VERSION_2_0: ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; Loading @@ -97,6 +98,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, ctrl->ops.clamp_disable = NULL; ctrl->ops.schedule_dma_cmd = NULL; ctrl->ops.get_cont_splash_status = NULL; ctrl->ops.kickoff_command_non_embedded_mode = NULL; break; case DSI_CTRL_VERSION_2_2: ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config; Loading @@ -113,6 +115,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, ctrl->ops.clamp_enable = NULL; ctrl->ops.clamp_disable = NULL; ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd; ctrl->ops.kickoff_command_non_embedded_mode = dsi_ctrl_hw_kickoff_non_embedded_mode; break; default: break; Loading drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -213,6 +213,9 @@ int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, char *buf, u32 size); void dsi_ctrl_hw_kickoff_non_embedded_mode(struct dsi_ctrl_hw *ctrl, struct dsi_ctrl_cmd_dma_info *cmd, u32 flags); /* Definitions specific to 2.2 DSI controller hardware */ bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl); Loading drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +134 −31 Original line number Diff line number Diff line Loading @@ -940,6 +940,62 @@ static void dsi_ctrl_wait_for_video_done(struct dsi_ctrl *dsi_ctrl) udelay(sleep_ms * 1000); } void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags) { /** * Setup the mode of transmission * override cmd fetch mode during secure session */ if (dsi_ctrl->secure_mode) { *flags &= ~DSI_CTRL_CMD_FETCH_MEMORY; *flags |= DSI_CTRL_CMD_FIFO_STORE; pr_debug("[%s] override to TPG during secure session\n", dsi_ctrl->name); return; } /* Check to see if cmd len plus header is greater than fifo size */ if ((cmd_len + 4) > DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES) { *flags |= DSI_CTRL_CMD_NON_EMBEDDED_MODE; pr_debug("[%s] override to non-embedded mode,cmd len =%d\n", dsi_ctrl->name, cmd_len); return; } } int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags) { int rc = 0; if (*flags & DSI_CTRL_CMD_FIFO_STORE) { /* if command size plus header is greater than fifo size */ if ((cmd_len + 4) > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE) { pr_err("Cannot transfer Cmd in FIFO config\n"); return -ENOTSUPP; } if (!dsi_ctrl->hw.ops.kickoff_fifo_command) { pr_err("Cannot transfer command,ops not defined\n"); return -ENOTSUPP; } } if (*flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { if (*flags & DSI_CTRL_CMD_BROADCAST) { pr_err("Non embedded not supported with broadcast\n"); return -ENOTSUPP; } if (!dsi_ctrl->hw.ops.kickoff_command_non_embedded_mode) { pr_err(" Cannot transfer command,ops not defined\n"); return -ENOTSUPP; } } return rc; } static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, const struct mipi_dsi_msg *msg, u32 flags) Loading @@ -954,28 +1010,41 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, u32 cnt = 0, line_no = 0x1; u8 *cmdbuf; struct dsi_mode_info *timing; struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops; /* override cmd fetch mode during secure session */ if (dsi_ctrl->secure_mode) { flags &= ~DSI_CTRL_CMD_FETCH_MEMORY; flags |= DSI_CTRL_CMD_FIFO_STORE; pr_debug("[%s] override to TPG during secure session\n", dsi_ctrl->name); } /* Select the tx mode to transfer the command */ dsi_message_setup_tx_mode(dsi_ctrl, msg->tx_len, &flags); rc = mipi_dsi_create_packet(&packet, msg); /* Validate the mode before sending the command */ rc = dsi_message_validate_tx_mode(dsi_ctrl, msg->tx_len, &flags); if (rc) { pr_err("Failed to create message packet, rc=%d\n", rc); pr_err(" Cmd tx validation failed, cannot transfer cmd\n"); rc = -ENOTSUPP; goto error; } /* fail cmds more than the supported size in TPG mode */ if ((flags & DSI_CTRL_CMD_FIFO_STORE) && (msg->tx_len > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE)) { pr_err("[%s] TPG cmd size:%zd not supported, secure:%d\n", dsi_ctrl->name, msg->tx_len, dsi_ctrl->secure_mode); rc = -ENOTSUPP; if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { cmd_mem.offset = dsi_ctrl->cmd_buffer_iova; cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? true : false; cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ? true : false; cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? true : false; cmd_mem.datatype = msg->type; cmd_mem.length = msg->tx_len; dsi_ctrl->cmd_len = msg->tx_len; memcpy(dsi_ctrl->vaddr, msg->tx_buf, msg->tx_len); pr_debug(" non-embedded mode , size of command =%zd\n", msg->tx_len); goto kickoff; } rc = mipi_dsi_create_packet(&packet, msg); if (rc) { pr_err("Failed to create message packet, rc=%d\n", rc); goto error; } Loading @@ -993,6 +1062,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, buffer[3] |= BIT(7);//set the last cmd bit in header. if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { /* Embedded mode config is selected */ cmd_mem.offset = dsi_ctrl->cmd_buffer_iova; cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? true : false; Loading @@ -1006,6 +1076,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, for (cnt = 0; cnt < length; cnt++) cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt]; msm_gem_sync(dsi_ctrl->tx_cmd_buf); dsi_ctrl->cmd_len += length; if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) { Loading @@ -1026,15 +1097,16 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, true : false; } kickoff: timing = &(dsi_ctrl->host_config.video_timing); if (timing) line_no += timing->v_back_porch + timing->v_sync_width + timing->v_active; if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) && dsi_ctrl->hw.ops.schedule_dma_cmd && dsi_hw_ops.schedule_dma_cmd && (dsi_ctrl->current_state.vid_engine_state == DSI_CTRL_ENGINE_ON)) dsi_ctrl->hw.ops.schedule_dma_cmd(&dsi_ctrl->hw, dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw, line_no); hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ? Loading @@ -1045,11 +1117,19 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) { if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.kickoff_command_non_embedded_mode( &dsi_ctrl->hw, &cmd_mem, hw_flags); } else { dsi_hw_ops.kickoff_command( &dsi_ctrl->hw, &cmd_mem, hw_flags); } } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw, &cmd, hw_flags); } Loading @@ -1059,17 +1139,25 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, dsi_ctrl_wait_for_video_done(dsi_ctrl); dsi_ctrl_enable_status_interrupt(dsi_ctrl, DSI_SINT_CMD_MODE_DMA_DONE, NULL); if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, if (dsi_hw_ops.mask_error_intr) dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), true); reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done); if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.kickoff_command_non_embedded_mode( &dsi_ctrl->hw, &cmd_mem, hw_flags); } else { dsi_hw_ops.kickoff_command( &dsi_ctrl->hw, &cmd_mem, hw_flags); } } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw, &cmd, hw_flags); } Loading @@ -1079,14 +1167,14 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, msecs_to_jiffies(DSI_CTRL_TX_TO_MS)); if (ret == 0) { u32 status = dsi_ctrl->hw.ops.get_interrupt_status( u32 status = dsi_hw_ops.get_interrupt_status( &dsi_ctrl->hw); u32 mask = DSI_CMD_MODE_DMA_DONE; if (status & mask) { status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE); dsi_ctrl->hw.ops.clear_interrupt_status( dsi_hw_ops.clear_interrupt_status( &dsi_ctrl->hw, status); dsi_ctrl_disable_status_interrupt(dsi_ctrl, Loading @@ -1102,10 +1190,20 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, } } if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, if (dsi_hw_ops.mask_error_intr) dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw); dsi_hw_ops.reset_cmd_fifo(&dsi_ctrl->hw); /* * DSI 2.2 needs a soft reset whenever we send non-embedded * mode command followed by embedded mode. Otherwise it will * result in smmu write faults with DSI as client. */ if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.soft_reset(&dsi_ctrl->hw); dsi_ctrl->cmd_len = 0; } } error: if (buffer) Loading Loading @@ -2682,6 +2780,11 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); dsi_ctrl->cmd_len = 0; } } mutex_unlock(&dsi_ctrl->ctrl_lock); Loading drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +23 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ * and transfer it. * @DSI_CTRL_CMD_LAST_COMMAND: Trigger the DMA cmd transfer if this is last * command in the batch. * @DSI_CTRL_CMD_NON_EMBEDDED_MODE:Transfer cmd packets in non embedded mode. */ #define DSI_CTRL_CMD_READ 0x1 #define DSI_CTRL_CMD_BROADCAST 0x2 Loading @@ -45,6 +46,12 @@ #define DSI_CTRL_CMD_FIFO_STORE 0x10 #define DSI_CTRL_CMD_FETCH_MEMORY 0x20 #define DSI_CTRL_CMD_LAST_COMMAND 0x40 #define DSI_CTRL_CMD_NON_EMBEDDED_MODE 0x80 /* DSI embedded mode fifo size * If the command is greater than 256 bytes it is sent in non-embedded mode. */ #define DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES 256 /* max size supported for dsi cmd transfer using TPG */ #define DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE 64 Loading Loading @@ -680,4 +687,20 @@ int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl); */ int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on); /** * @dsi_ctrl: DSI controller handle. * cmd_len: Length of command. * flags: Config mode flags. */ void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags); /** * @dsi_ctrl: DSI controller handle. * cmd_len: Length of command. * flags: Config mode flags. */ int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags); #endif /* _DSI_CTRL_H_ */ Loading
drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c +111 −11 Original line number Diff line number Diff line Loading @@ -33,24 +33,52 @@ /* Register Offsets from PLL base address */ #define PLL_ANALOG_CONTROLS_ONE 0x000 #define PLL_ANALOG_CONTROLS_TWO 0x004 #define PLL_INT_LOOP_SETTINGS 0x008 #define PLL_INT_LOOP_SETTINGS_TWO 0x00c #define PLL_ANALOG_CONTROLS_THREE 0x010 #define PLL_ANALOG_CONTROLS_FOUR 0x014 #define PLL_INT_LOOP_CONTROLS 0x018 #define PLL_DSM_DIVIDER 0x01c #define PLL_FEEDBACK_DIVIDER 0x020 #define PLL_SYSTEM_MUXES 0x024 #define PLL_FREQ_UPDATE_CONTROL_OVERRIDES 0x028 #define PLL_CMODE 0x02c #define PLL_CALIBRATION_SETTINGS 0x030 #define PLL_BAND_SEL_CAL_TIMER_LOW 0x034 #define PLL_BAND_SEL_CAL_TIMER_HIGH 0x038 #define PLL_BAND_SEL_CAL_SETTINGS 0x03c #define PLL_BAND_SEL_MIN 0x040 #define PLL_BAND_SEL_MAX 0x044 #define PLL_BAND_SEL_PFILT 0x048 #define PLL_BAND_SEL_IFILT 0x04c #define PLL_BAND_SEL_CAL_SETTINGS_TWO 0x050 #define PLL_BAND_SEL_CAL_SETTINGS_THREE 0x054 #define PLL_BAND_SEL_CAL_SETTINGS_FOUR 0x058 #define PLL_BAND_SEL_ICODE_HIGH 0x05c #define PLL_BAND_SEL_ICODE_LOW 0x060 #define PLL_FREQ_DETECT_SETTINGS_ONE 0x064 #define PLL_PFILT 0x07c #define PLL_IFILT 0x080 #define PLL_GAIN 0x084 #define PLL_ICODE_LOW 0x088 #define PLL_ICODE_HIGH 0x08c #define PLL_LOCKDET 0x090 #define PLL_OUTDIV 0x094 #define PLL_FASTLOCK_CONTROL 0x098 #define PLL_PASS_OUT_OVERRIDE_ONE 0x09c #define PLL_PASS_OUT_OVERRIDE_TWO 0x0a0 #define PLL_CORE_OVERRIDE 0x0a4 #define PLL_CORE_INPUT_OVERRIDE 0x0a8 #define PLL_RATE_CHANGE 0x0ac #define PLL_PLL_DIGITAL_TIMERS 0x0b0 #define PLL_PLL_DIGITAL_TIMERS_TWO 0x0b4 #define PLL_DEC_FRAC_MUXES 0x0c8 #define PLL_DECIMAL_DIV_START_1 0x0cc #define PLL_FRAC_DIV_START_LOW_1 0x0d0 #define PLL_FRAC_DIV_START_MID_1 0x0d4 #define PLL_FRAC_DIV_START_HIGH_1 0x0d8 #define PLL_MASH_CONTROL 0x0ec #define PLL_SSC_MUX_CONTROL 0x108 #define PLL_SSC_STEPSIZE_LOW_1 0x10c #define PLL_SSC_STEPSIZE_HIGH_1 0x110 #define PLL_SSC_DIV_PER_LOW_1 0x114 Loading @@ -64,9 +92,16 @@ #define PLL_PLL_BAND_SET_RATE_1 0x154 #define PLL_PLL_INT_GAIN_IFILT_BAND_1 0x15c #define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1 0x164 #define PLL_FASTLOCK_EN_BAND 0x16c #define PLL_FREQ_TUNE_ACCUM_INIT_MUX 0x17c #define PLL_PLL_LOCK_OVERRIDE 0x180 #define PLL_PLL_LOCK_DELAY 0x184 #define PLL_PLL_LOCK_MIN_DELAY 0x188 #define PLL_CLOCK_INVERTERS 0x18c #define PLL_SPARE_AND_JPC_OVERRIDES 0x190 #define PLL_BIAS_CONTROL_1 0x194 #define PLL_BIAS_CONTROL_2 0x198 #define PLL_ALOG_OBSV_BUS_CTRL_1 0x19c #define PLL_COMMON_STATUS_ONE 0x1a0 /* Register Offsets from PHY base address */ Loading Loading @@ -249,7 +284,7 @@ static inline int pclk_mux_read_sel(void *context, unsigned int reg, if (rc) pr_err("Failed to enable dsi pll resources, rc=%d\n", rc); else *val = (MDSS_PLL_REG_R(rsc->pll_base, reg) & 0x3); *val = (MDSS_PLL_REG_R(rsc->phy_base, reg) & 0x3); (void)mdss_pll_resource_enable(rsc, false); return rc; Loading Loading @@ -503,6 +538,49 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_10nm *pll, MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f); } static void dsi_pll_init_val(struct mdss_pll_resources *rsc) { void __iomem *pll_base = rsc->pll_base; MDSS_PLL_REG_W(pll_base, PLL_CORE_INPUT_OVERRIDE, 0x10); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS, 0x3f); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_SETTINGS_TWO, 0x0); MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_FOUR, 0x0); MDSS_PLL_REG_W(pll_base, PLL_INT_LOOP_CONTROLS, 0x80); MDSS_PLL_REG_W(pll_base, PLL_FREQ_UPDATE_CONTROL_OVERRIDES, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_LOW, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_TIMER_HIGH, 0x02); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS, 0x82); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MIN, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_MAX, 0xff); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_PFILT, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_IFILT, 0x00); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_TWO, 0x25); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_FOUR, 0x4f); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_HIGH, 0x0a); MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_ICODE_LOW, 0x0); MDSS_PLL_REG_W(pll_base, PLL_GAIN, 0x42); MDSS_PLL_REG_W(pll_base, PLL_ICODE_LOW, 0x00); MDSS_PLL_REG_W(pll_base, PLL_ICODE_HIGH, 0x00); MDSS_PLL_REG_W(pll_base, PLL_LOCKDET, 0x30); MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_CONTROL, 0x04); MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_ONE, 0x00); MDSS_PLL_REG_W(pll_base, PLL_PASS_OUT_OVERRIDE_TWO, 0x00); MDSS_PLL_REG_W(pll_base, PLL_RATE_CHANGE, 0x01); MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS, 0x08); MDSS_PLL_REG_W(pll_base, PLL_DEC_FRAC_MUXES, 0x00); MDSS_PLL_REG_W(pll_base, PLL_MASH_CONTROL, 0x03); MDSS_PLL_REG_W(pll_base, PLL_SSC_MUX_CONTROL, 0x0); MDSS_PLL_REG_W(pll_base, PLL_SSC_CONTROL, 0x0); MDSS_PLL_REG_W(pll_base, PLL_FASTLOCK_EN_BAND, 0x03); MDSS_PLL_REG_W(pll_base, PLL_FREQ_TUNE_ACCUM_INIT_MUX, 0x0); MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_MIN_DELAY, 0x19); MDSS_PLL_REG_W(pll_base, PLL_SPARE_AND_JPC_OVERRIDES, 0x0); MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_1, 0x40); MDSS_PLL_REG_W(pll_base, PLL_BIAS_CONTROL_2, 0x20); MDSS_PLL_REG_W(pll_base, PLL_ALOG_OBSV_BUS_CTRL_1, 0x0); } static void dsi_pll_commit(struct dsi_pll_10nm *pll, struct mdss_pll_resources *rsc) { Loading Loading @@ -559,6 +637,8 @@ static int vco_10nm_set_rate(struct clk_hw *hw, unsigned long rate, return rc; } dsi_pll_init_val(rsc); dsi_pll_setup_config(pll, rsc); dsi_pll_calc_dec_frac(pll, rsc); Loading Loading @@ -741,12 +821,32 @@ static void vco_10nm_unprepare(struct clk_hw *hw) pr_err("dsi pll resources not available\n"); return; } pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); /* * During unprepare in continuous splash use case we want driver * to pick all dividers instead of retaining bootloader configurations. */ if (!pll->handoff_resources) { pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0); pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE); pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0, pll->cached_cfg1, pll->cached_outdiv); pll->vco_cached_rate = clk_hw_get_rate(hw); } /* * When continuous splash screen feature is enabled, we need to cache * the mux configuration for the pixel_clk_src mux clock. The clock * framework does not call back to re-configure the mux value if it is * does not change.For such usecases, we need to ensure that the cached * value is programmed prior to PLL being locked */ if (pll->handoff_resources) pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1); dsi_pll_disable(vco); mdss_pll_resource_enable(pll, false); } Loading Loading @@ -1026,8 +1126,8 @@ static struct regmap_bus pll_regmap_bus = { .reg_read = pll_reg_read, }; static struct regmap_bus pclk_mux_regmap_bus = { .reg_read = phy_reg_read, static struct regmap_bus pclk_src_mux_regmap_bus = { .reg_read = pclk_mux_read_sel, .reg_write = pclk_mux_write_sel, }; Loading Loading @@ -1472,7 +1572,7 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev, pll_res, &dsi_pll_10nm_config); dsi0pll_pclk_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi0pll_pclk_src_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, Loading Loading @@ -1510,11 +1610,11 @@ int dsi_pll_clock_register_10nm(struct platform_device *pdev, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_src.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, rmap = devm_regmap_init(&pdev->dev, &pclk_src_mux_regmap_bus, pll_res, &dsi_pll_10nm_config); dsi1pll_pclk_src_mux.clkr.regmap = rmap; rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus, Loading
drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c +4 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, dsi_ctrl_hw_14_reg_dump_to_buffer; ctrl->ops.schedule_dma_cmd = NULL; ctrl->ops.get_cont_splash_status = NULL; ctrl->ops.kickoff_command_non_embedded_mode = NULL; break; case DSI_CTRL_VERSION_2_0: ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map; Loading @@ -97,6 +98,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, ctrl->ops.clamp_disable = NULL; ctrl->ops.schedule_dma_cmd = NULL; ctrl->ops.get_cont_splash_status = NULL; ctrl->ops.kickoff_command_non_embedded_mode = NULL; break; case DSI_CTRL_VERSION_2_2: ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config; Loading @@ -113,6 +115,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl, ctrl->ops.clamp_enable = NULL; ctrl->ops.clamp_disable = NULL; ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd; ctrl->ops.kickoff_command_non_embedded_mode = dsi_ctrl_hw_kickoff_non_embedded_mode; break; default: break; Loading
drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h +3 −0 Original line number Diff line number Diff line Loading @@ -213,6 +213,9 @@ int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes); ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl, char *buf, u32 size); void dsi_ctrl_hw_kickoff_non_embedded_mode(struct dsi_ctrl_hw *ctrl, struct dsi_ctrl_cmd_dma_info *cmd, u32 flags); /* Definitions specific to 2.2 DSI controller hardware */ bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl); Loading
drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +134 −31 Original line number Diff line number Diff line Loading @@ -940,6 +940,62 @@ static void dsi_ctrl_wait_for_video_done(struct dsi_ctrl *dsi_ctrl) udelay(sleep_ms * 1000); } void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags) { /** * Setup the mode of transmission * override cmd fetch mode during secure session */ if (dsi_ctrl->secure_mode) { *flags &= ~DSI_CTRL_CMD_FETCH_MEMORY; *flags |= DSI_CTRL_CMD_FIFO_STORE; pr_debug("[%s] override to TPG during secure session\n", dsi_ctrl->name); return; } /* Check to see if cmd len plus header is greater than fifo size */ if ((cmd_len + 4) > DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES) { *flags |= DSI_CTRL_CMD_NON_EMBEDDED_MODE; pr_debug("[%s] override to non-embedded mode,cmd len =%d\n", dsi_ctrl->name, cmd_len); return; } } int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags) { int rc = 0; if (*flags & DSI_CTRL_CMD_FIFO_STORE) { /* if command size plus header is greater than fifo size */ if ((cmd_len + 4) > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE) { pr_err("Cannot transfer Cmd in FIFO config\n"); return -ENOTSUPP; } if (!dsi_ctrl->hw.ops.kickoff_fifo_command) { pr_err("Cannot transfer command,ops not defined\n"); return -ENOTSUPP; } } if (*flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { if (*flags & DSI_CTRL_CMD_BROADCAST) { pr_err("Non embedded not supported with broadcast\n"); return -ENOTSUPP; } if (!dsi_ctrl->hw.ops.kickoff_command_non_embedded_mode) { pr_err(" Cannot transfer command,ops not defined\n"); return -ENOTSUPP; } } return rc; } static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, const struct mipi_dsi_msg *msg, u32 flags) Loading @@ -954,28 +1010,41 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, u32 cnt = 0, line_no = 0x1; u8 *cmdbuf; struct dsi_mode_info *timing; struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops; /* override cmd fetch mode during secure session */ if (dsi_ctrl->secure_mode) { flags &= ~DSI_CTRL_CMD_FETCH_MEMORY; flags |= DSI_CTRL_CMD_FIFO_STORE; pr_debug("[%s] override to TPG during secure session\n", dsi_ctrl->name); } /* Select the tx mode to transfer the command */ dsi_message_setup_tx_mode(dsi_ctrl, msg->tx_len, &flags); rc = mipi_dsi_create_packet(&packet, msg); /* Validate the mode before sending the command */ rc = dsi_message_validate_tx_mode(dsi_ctrl, msg->tx_len, &flags); if (rc) { pr_err("Failed to create message packet, rc=%d\n", rc); pr_err(" Cmd tx validation failed, cannot transfer cmd\n"); rc = -ENOTSUPP; goto error; } /* fail cmds more than the supported size in TPG mode */ if ((flags & DSI_CTRL_CMD_FIFO_STORE) && (msg->tx_len > DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE)) { pr_err("[%s] TPG cmd size:%zd not supported, secure:%d\n", dsi_ctrl->name, msg->tx_len, dsi_ctrl->secure_mode); rc = -ENOTSUPP; if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { cmd_mem.offset = dsi_ctrl->cmd_buffer_iova; cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? true : false; cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ? true : false; cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ? true : false; cmd_mem.datatype = msg->type; cmd_mem.length = msg->tx_len; dsi_ctrl->cmd_len = msg->tx_len; memcpy(dsi_ctrl->vaddr, msg->tx_buf, msg->tx_len); pr_debug(" non-embedded mode , size of command =%zd\n", msg->tx_len); goto kickoff; } rc = mipi_dsi_create_packet(&packet, msg); if (rc) { pr_err("Failed to create message packet, rc=%d\n", rc); goto error; } Loading @@ -993,6 +1062,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, buffer[3] |= BIT(7);//set the last cmd bit in header. if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { /* Embedded mode config is selected */ cmd_mem.offset = dsi_ctrl->cmd_buffer_iova; cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ? true : false; Loading @@ -1006,6 +1076,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, for (cnt = 0; cnt < length; cnt++) cmdbuf[dsi_ctrl->cmd_len + cnt] = buffer[cnt]; msm_gem_sync(dsi_ctrl->tx_cmd_buf); dsi_ctrl->cmd_len += length; if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) { Loading @@ -1026,15 +1097,16 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, true : false; } kickoff: timing = &(dsi_ctrl->host_config.video_timing); if (timing) line_no += timing->v_back_porch + timing->v_sync_width + timing->v_active; if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) && dsi_ctrl->hw.ops.schedule_dma_cmd && dsi_hw_ops.schedule_dma_cmd && (dsi_ctrl->current_state.vid_engine_state == DSI_CTRL_ENGINE_ON)) dsi_ctrl->hw.ops.schedule_dma_cmd(&dsi_ctrl->hw, dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw, line_no); hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ? Loading @@ -1045,11 +1117,19 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) { if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.kickoff_command_non_embedded_mode( &dsi_ctrl->hw, &cmd_mem, hw_flags); } else { dsi_hw_ops.kickoff_command( &dsi_ctrl->hw, &cmd_mem, hw_flags); } } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw, &cmd, hw_flags); } Loading @@ -1059,17 +1139,25 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, dsi_ctrl_wait_for_video_done(dsi_ctrl); dsi_ctrl_enable_status_interrupt(dsi_ctrl, DSI_SINT_CMD_MODE_DMA_DONE, NULL); if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, if (dsi_hw_ops.mask_error_intr) dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), true); reinit_completion(&dsi_ctrl->irq_info.cmd_dma_done); if (flags & DSI_CTRL_CMD_FETCH_MEMORY) { dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw, if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.kickoff_command_non_embedded_mode( &dsi_ctrl->hw, &cmd_mem, hw_flags); } else { dsi_hw_ops.kickoff_command( &dsi_ctrl->hw, &cmd_mem, hw_flags); } } else if (flags & DSI_CTRL_CMD_FIFO_STORE) { dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw, dsi_hw_ops.kickoff_fifo_command(&dsi_ctrl->hw, &cmd, hw_flags); } Loading @@ -1079,14 +1167,14 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, msecs_to_jiffies(DSI_CTRL_TX_TO_MS)); if (ret == 0) { u32 status = dsi_ctrl->hw.ops.get_interrupt_status( u32 status = dsi_hw_ops.get_interrupt_status( &dsi_ctrl->hw); u32 mask = DSI_CMD_MODE_DMA_DONE; if (status & mask) { status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE); dsi_ctrl->hw.ops.clear_interrupt_status( dsi_hw_ops.clear_interrupt_status( &dsi_ctrl->hw, status); dsi_ctrl_disable_status_interrupt(dsi_ctrl, Loading @@ -1102,10 +1190,20 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, } } if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, if (dsi_hw_ops.mask_error_intr) dsi_hw_ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw); dsi_hw_ops.reset_cmd_fifo(&dsi_ctrl->hw); /* * DSI 2.2 needs a soft reset whenever we send non-embedded * mode command followed by embedded mode. Otherwise it will * result in smmu write faults with DSI as client. */ if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_hw_ops.soft_reset(&dsi_ctrl->hw); dsi_ctrl->cmd_len = 0; } } error: if (buffer) Loading Loading @@ -2682,6 +2780,11 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags) if (dsi_ctrl->hw.ops.mask_error_intr) dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, BIT(DSI_FIFO_OVERFLOW), false); if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) { dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw); dsi_ctrl->cmd_len = 0; } } mutex_unlock(&dsi_ctrl->ctrl_lock); Loading
drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h +23 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ * and transfer it. * @DSI_CTRL_CMD_LAST_COMMAND: Trigger the DMA cmd transfer if this is last * command in the batch. * @DSI_CTRL_CMD_NON_EMBEDDED_MODE:Transfer cmd packets in non embedded mode. */ #define DSI_CTRL_CMD_READ 0x1 #define DSI_CTRL_CMD_BROADCAST 0x2 Loading @@ -45,6 +46,12 @@ #define DSI_CTRL_CMD_FIFO_STORE 0x10 #define DSI_CTRL_CMD_FETCH_MEMORY 0x20 #define DSI_CTRL_CMD_LAST_COMMAND 0x40 #define DSI_CTRL_CMD_NON_EMBEDDED_MODE 0x80 /* DSI embedded mode fifo size * If the command is greater than 256 bytes it is sent in non-embedded mode. */ #define DSI_EMBEDDED_MODE_DMA_MAX_SIZE_BYTES 256 /* max size supported for dsi cmd transfer using TPG */ #define DSI_CTRL_MAX_CMD_FIFO_STORE_SIZE 64 Loading Loading @@ -680,4 +687,20 @@ int dsi_ctrl_get_hw_version(struct dsi_ctrl *dsi_ctrl); */ int dsi_ctrl_vid_engine_en(struct dsi_ctrl *dsi_ctrl, bool on); /** * @dsi_ctrl: DSI controller handle. * cmd_len: Length of command. * flags: Config mode flags. */ void dsi_message_setup_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags); /** * @dsi_ctrl: DSI controller handle. * cmd_len: Length of command. * flags: Config mode flags. */ int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl, u32 cmd_len, u32 *flags); #endif /* _DSI_CTRL_H_ */