Loading drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +47 −29 Original line number Diff line number Diff line Loading @@ -138,47 +138,68 @@ static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) return clk_forced_on; } static void apply_dynamic_ot_limit(u32 *ot_lim, struct sde_mdp_set_ot_params *params) u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_mdp_format_params *fmt; u32 ot_lim; u32 is_yuv; u32 res; ot_lim = (is_rd) ? mdata->default_ot_rd_limit : mdata->default_ot_wr_limit; /* * If default ot is not set from dt, * then do not configure it. */ if (ot_lim == 0) goto exit; /* Modify the limits if the target and the use case requires it */ if (false == test_bit(SDE_QOS_OTLIM, mdata->sde_qos_map)) return; goto exit; res = params->width * params->height; res = width * height; SDEROT_DBG("w:%d h:%d rot:%d yuv:%d wb:%d res:%d\n", params->width, params->height, params->is_rot, params->is_yuv, params->is_wb, res); fmt = sde_get_format_params(pixfmt); if ((params->is_rot && params->is_yuv) || params->is_wb) { if (res <= RES_1080p) { *ot_lim = 2; } else if (res <= RES_UHD) { if (params->is_rot && params->is_yuv) *ot_lim = 8; else *ot_lim = 16; } if (!fmt) { SDEROT_WARN("invalid format %8.8x\n", pixfmt); goto exit; } is_yuv = sde_mdp_is_yuv_format(fmt); SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%d rd:%d\n", width, height, fps, pixfmt, is_yuv, res, is_rd); if (!is_yuv) goto exit; if ((res <= RES_1080p) && (fps <= 30)) ot_lim = 2; else if ((res <= RES_1080p) && (fps <= 60)) ot_lim = 4; else if ((res <= RES_UHD) && (fps <= 30)) ot_lim = 8; exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); return ot_lim; } static u32 get_ot_limit(u32 reg_off, u32 bit_off, struct sde_mdp_set_ot_params *params) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 ot_lim = 0; u32 ot_lim; u32 val; if (mdata->default_ot_wr_limit && (params->reg_off_vbif_lim_conf == MMSS_VBIF_WR_LIM_CONF)) ot_lim = mdata->default_ot_wr_limit; else if (mdata->default_ot_rd_limit && (params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF)) ot_lim = mdata->default_ot_rd_limit; ot_lim = sde_mdp_get_ot_limit( params->width, params->height, params->fmt, params->fps, params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF); /* * If default ot is not set from dt, Loading @@ -187,9 +208,6 @@ static u32 get_ot_limit(u32 reg_off, u32 bit_off, if (ot_lim == 0) goto exit; /* Modify the limits if the target and the use case requires it */ apply_dynamic_ot_limit(&ot_lim, params); val = SDE_VBIF_READ(mdata, reg_off); val &= (0xFF << bit_off); val = val >> bit_off; Loading drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +4 −3 Original line number Diff line number Diff line Loading @@ -34,9 +34,8 @@ struct sde_mdp_set_ot_params { u32 num; u32 width; u32 height; bool is_rot; bool is_wb; bool is_yuv; u32 fps; u32 fmt; u32 reg_off_vbif_lim_conf; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; Loading Loading @@ -143,6 +142,8 @@ u32 sde_apply_comp_ratio_factor(u32 quota, struct sde_mdp_format_params *fmt, struct sde_mult_factor *factor); u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd); void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params); #define SDE_VBIF_WRITE(mdata, offset, value) \ Loading drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +134 −20 Original line number Diff line number Diff line Loading @@ -607,59 +607,165 @@ static int sde_rotator_import_data(struct sde_rot_mgr *mgr, return ret; } /* * sde_rotator_require_reconfiguration - check if reconfiguration is required * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * @entry: Pointer to next rotation entry * * Parameters are validated by caller. */ static int sde_rotator_require_reconfiguration(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw, struct sde_rot_entry *entry) { /* OT setting change may impact queued entries */ if (entry->perf && (entry->perf->rdot_limit != mgr->rdot_limit || entry->perf->wrot_limit != mgr->wrot_limit)) return true; return false; } /* * sde_rotator_is_hw_idle - check if hw block is not processing request * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * * Parameters are validated by caller. */ static int sde_rotator_is_hw_idle(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw) { int i; /* * Wait until all queues are idle in order to update global * setting such as VBIF QoS. This check can be relaxed if global * settings can be updated individually by entries already * queued in hw queue, i.e. REGDMA can update VBIF directly. */ for (i = 0; i < mgr->queue_count; i++) { struct sde_rot_hw_resource *hw_res = mgr->commitq[i].hw; if (hw_res && atomic_read(&hw_res->num_active)) return false; } return true; } /* * sde_rotator_is_hw_available - check if hw is available for the given entry * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * @entry: Pointer to rotation entry * * Parameters are validated by caller. */ static int sde_rotator_is_hw_available(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw, struct sde_rot_entry *entry) { /* * Wait until hw is idle if reconfiguration is required; otherwise, * wait until free queue entry is available */ if (sde_rotator_require_reconfiguration(mgr, hw, entry)) { SDEROT_DBG( "wait4idle active=%d pending=%d rdot:%u/%u wrot:%u/%u s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, mgr->rdot_limit, entry->perf->rdot_limit, mgr->wrot_limit, entry->perf->wrot_limit, entry->item.session_id, entry->item.sequence_id); return sde_rotator_is_hw_idle(mgr, hw); } else { return (atomic_read(&hw->num_active) < hw->max_active); } } /* * sde_rotator_get_hw_resource - block waiting for hw availability or timeout * @queue: Pointer to rotator queue * @entry: Pointer to rotation entry */ static struct sde_rot_hw_resource *sde_rotator_get_hw_resource( struct sde_rot_queue *queue, struct sde_rot_entry *entry) { struct sde_rot_hw_resource *hw = queue->hw; struct sde_rot_hw_resource *hw; struct sde_rot_mgr *mgr; int ret; if (!hw) { SDEROT_ERR("no hw in the queue\n"); if (!queue || !entry || !queue->hw) { SDEROT_ERR("null parameters\n"); return NULL; } hw = queue->hw; mgr = entry->private->mgr; BUG_ON(atomic_read(&hw->num_active) > hw->max_active); while (atomic_read(&hw->num_active) >= hw->max_active) { sde_rot_mgr_unlock(entry->private->mgr); while (!sde_rotator_is_hw_available(mgr, hw, entry)) { sde_rot_mgr_unlock(mgr); ret = wait_event_timeout(hw->wait_queue, (atomic_read(&hw->num_active) < hw->max_active), sde_rotator_is_hw_available(mgr, hw, entry), msecs_to_jiffies(mgr->hwacquire_timeout)); sde_rot_mgr_lock(entry->private->mgr); sde_rot_mgr_lock(mgr); if (!ret) { SDEROT_ERR( "timeout waiting for hw resource, a:%d p:%d\n", atomic_read(&hw->num_active), hw->pending_count); if (hw->workload) SDEROT_ERR("possible faulty workload s:%d.%d\n", hw->workload->item.session_id, hw->workload->item.sequence_id); return NULL; } } atomic_inc(&hw->num_active); SDEROT_DBG("active=%d pending=%d s:%d.%d\n", SDEROT_DBG("active=%d pending=%d rdot=%u/%u wrot=%u/%u s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, mgr->rdot_limit, entry->perf->rdot_limit, mgr->wrot_limit, entry->perf->wrot_limit, entry->item.session_id, entry->item.sequence_id); hw->workload = entry; mgr->rdot_limit = entry->perf->rdot_limit; mgr->wrot_limit = entry->perf->wrot_limit; return hw; } /* * sde_rotator_put_hw_resource - return hw resource and wake up waiting clients * @queue: Pointer to rotator queue * @entry: Pointer to rotation entry * @hw: Pointer to hw resource to be returned */ static void sde_rotator_put_hw_resource(struct sde_rot_queue *queue, struct sde_rot_hw_resource *hw) struct sde_rot_entry *entry, struct sde_rot_hw_resource *hw) { struct sde_rot_entry *entry = hw->workload; struct sde_rot_mgr *mgr; int i; if (!queue || !entry || !hw) { SDEROT_ERR("null parameters\n"); return; } mgr = entry->private->mgr; BUG_ON(atomic_read(&hw->num_active) < 1); hw->workload = NULL; if (!atomic_add_unless(&hw->num_active, -1, 0)) SDEROT_ERR("underflow active=%d pending=%d s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, entry->item.session_id, entry->item.sequence_id); wake_up(&hw->wait_queue); /* * Wake up all queues in case any entry is waiting for hw idle, * in order to update global settings, such as VBIF QoS. * This can be relaxed to the given hw resource if global * settings can be updated individually by entries already * queued in hw queue. */ for (i = 0; i < mgr->queue_count; i++) { struct sde_rot_hw_resource *hw_res = mgr->commitq[i].hw; if (hw_res) wake_up(&hw_res->wait_queue); } SDEROT_DBG("active=%d pending=%d s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, entry->item.session_id, entry->item.sequence_id); Loading Loading @@ -908,6 +1014,14 @@ static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, &config->output.comp_ratio); perf->bw = read_bw + write_bw; perf->rdot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, config->input.format, config->frame_rate, true); perf->wrot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, config->input.format, config->frame_rate, false); return 0; } Loading Loading @@ -1069,7 +1183,7 @@ static void sde_rotator_commit_handler(struct work_struct *work) sde_rot_mgr_unlock(mgr); return; error: sde_rotator_put_hw_resource(entry->commitq, hw); sde_rotator_put_hw_resource(entry->commitq, entry, hw); get_hw_res_err: sde_rotator_signal_output(entry); sde_rotator_release_entry(mgr, entry); Loading Loading @@ -1141,7 +1255,7 @@ static void sde_rotator_done_handler(struct work_struct *work) entry->item.dst_rect.w, entry->item.dst_rect.h); sde_rot_mgr_lock(mgr); sde_rotator_put_hw_resource(entry->commitq, entry->commitq->hw); sde_rotator_put_hw_resource(entry->commitq, entry, entry->commitq->hw); sde_rotator_signal_output(entry); sde_rotator_release_entry(mgr, entry); atomic_dec(&request->pending_count); Loading Loading @@ -2275,7 +2389,7 @@ int sde_rotator_core_init(struct sde_rot_mgr **pmgr, sde_rotator_clk_ctrl(mgr, true); mdata->mdss_version = SDE_REG_READ(mdata, SDE_REG_HW_VERSION); SDEROT_INFO("mdss revision %x\n", mdata->mdss_version); SDEROT_DBG("mdss revision %x\n", mdata->mdss_version); if ((mdata->mdss_version & 0xFFFF0000) == 0x10070000) { mgr->ops_hw_init = sde_rotator_r1_init; Loading drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +4 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,6 @@ struct sde_rot_hw_resource { atomic_t num_active; int max_active; wait_queue_head_t wait_queue; struct sde_rot_entry *workload; }; struct sde_rot_queue { Loading Loading @@ -225,6 +224,8 @@ struct sde_rot_perf { struct mutex work_dis_lock; u32 *work_distribution; int last_wb_idx; /* last known wb index, used when above count is 0 */ u32 rdot_limit; u32 wrot_limit; }; struct sde_rot_file_private { Loading Loading @@ -275,6 +276,8 @@ struct sde_rot_mgr { struct sde_rot_clk *rot_clk; int num_rot_clk; int core_clk_idx; u32 rdot_limit; u32 wrot_limit; u32 hwacquire_timeout; struct sde_mult_factor pixel_per_clk; Loading drivers/media/platform/msm/sde/rotator/sde_rotator_r1_internal.h +1 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,7 @@ struct sde_mdp_pipe { struct sde_mdp_plane_sizes src_planes; struct sde_mdp_mixer *mixer_left; struct sde_mdp_mixer *mixer_right; struct sde_mdp_shared_reg_ctrl clk_ctrl; u32 params_changed; u32 offset; }; Loading Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +47 −29 Original line number Diff line number Diff line Loading @@ -138,47 +138,68 @@ static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) return clk_forced_on; } static void apply_dynamic_ot_limit(u32 *ot_lim, struct sde_mdp_set_ot_params *params) u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct sde_mdp_format_params *fmt; u32 ot_lim; u32 is_yuv; u32 res; ot_lim = (is_rd) ? mdata->default_ot_rd_limit : mdata->default_ot_wr_limit; /* * If default ot is not set from dt, * then do not configure it. */ if (ot_lim == 0) goto exit; /* Modify the limits if the target and the use case requires it */ if (false == test_bit(SDE_QOS_OTLIM, mdata->sde_qos_map)) return; goto exit; res = params->width * params->height; res = width * height; SDEROT_DBG("w:%d h:%d rot:%d yuv:%d wb:%d res:%d\n", params->width, params->height, params->is_rot, params->is_yuv, params->is_wb, res); fmt = sde_get_format_params(pixfmt); if ((params->is_rot && params->is_yuv) || params->is_wb) { if (res <= RES_1080p) { *ot_lim = 2; } else if (res <= RES_UHD) { if (params->is_rot && params->is_yuv) *ot_lim = 8; else *ot_lim = 16; } if (!fmt) { SDEROT_WARN("invalid format %8.8x\n", pixfmt); goto exit; } is_yuv = sde_mdp_is_yuv_format(fmt); SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%d rd:%d\n", width, height, fps, pixfmt, is_yuv, res, is_rd); if (!is_yuv) goto exit; if ((res <= RES_1080p) && (fps <= 30)) ot_lim = 2; else if ((res <= RES_1080p) && (fps <= 60)) ot_lim = 4; else if ((res <= RES_UHD) && (fps <= 30)) ot_lim = 8; exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); return ot_lim; } static u32 get_ot_limit(u32 reg_off, u32 bit_off, struct sde_mdp_set_ot_params *params) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 ot_lim = 0; u32 ot_lim; u32 val; if (mdata->default_ot_wr_limit && (params->reg_off_vbif_lim_conf == MMSS_VBIF_WR_LIM_CONF)) ot_lim = mdata->default_ot_wr_limit; else if (mdata->default_ot_rd_limit && (params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF)) ot_lim = mdata->default_ot_rd_limit; ot_lim = sde_mdp_get_ot_limit( params->width, params->height, params->fmt, params->fps, params->reg_off_vbif_lim_conf == MMSS_VBIF_RD_LIM_CONF); /* * If default ot is not set from dt, Loading @@ -187,9 +208,6 @@ static u32 get_ot_limit(u32 reg_off, u32 bit_off, if (ot_lim == 0) goto exit; /* Modify the limits if the target and the use case requires it */ apply_dynamic_ot_limit(&ot_lim, params); val = SDE_VBIF_READ(mdata, reg_off); val &= (0xFF << bit_off); val = val >> bit_off; Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +4 −3 Original line number Diff line number Diff line Loading @@ -34,9 +34,8 @@ struct sde_mdp_set_ot_params { u32 num; u32 width; u32 height; bool is_rot; bool is_wb; bool is_yuv; u32 fps; u32 fmt; u32 reg_off_vbif_lim_conf; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; Loading Loading @@ -143,6 +142,8 @@ u32 sde_apply_comp_ratio_factor(u32 quota, struct sde_mdp_format_params *fmt, struct sde_mult_factor *factor); u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd); void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params); #define SDE_VBIF_WRITE(mdata, offset, value) \ Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +134 −20 Original line number Diff line number Diff line Loading @@ -607,59 +607,165 @@ static int sde_rotator_import_data(struct sde_rot_mgr *mgr, return ret; } /* * sde_rotator_require_reconfiguration - check if reconfiguration is required * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * @entry: Pointer to next rotation entry * * Parameters are validated by caller. */ static int sde_rotator_require_reconfiguration(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw, struct sde_rot_entry *entry) { /* OT setting change may impact queued entries */ if (entry->perf && (entry->perf->rdot_limit != mgr->rdot_limit || entry->perf->wrot_limit != mgr->wrot_limit)) return true; return false; } /* * sde_rotator_is_hw_idle - check if hw block is not processing request * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * * Parameters are validated by caller. */ static int sde_rotator_is_hw_idle(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw) { int i; /* * Wait until all queues are idle in order to update global * setting such as VBIF QoS. This check can be relaxed if global * settings can be updated individually by entries already * queued in hw queue, i.e. REGDMA can update VBIF directly. */ for (i = 0; i < mgr->queue_count; i++) { struct sde_rot_hw_resource *hw_res = mgr->commitq[i].hw; if (hw_res && atomic_read(&hw_res->num_active)) return false; } return true; } /* * sde_rotator_is_hw_available - check if hw is available for the given entry * @mgr: Pointer to rotator manager * @hw: Pointer to rotator hw resource * @entry: Pointer to rotation entry * * Parameters are validated by caller. */ static int sde_rotator_is_hw_available(struct sde_rot_mgr *mgr, struct sde_rot_hw_resource *hw, struct sde_rot_entry *entry) { /* * Wait until hw is idle if reconfiguration is required; otherwise, * wait until free queue entry is available */ if (sde_rotator_require_reconfiguration(mgr, hw, entry)) { SDEROT_DBG( "wait4idle active=%d pending=%d rdot:%u/%u wrot:%u/%u s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, mgr->rdot_limit, entry->perf->rdot_limit, mgr->wrot_limit, entry->perf->wrot_limit, entry->item.session_id, entry->item.sequence_id); return sde_rotator_is_hw_idle(mgr, hw); } else { return (atomic_read(&hw->num_active) < hw->max_active); } } /* * sde_rotator_get_hw_resource - block waiting for hw availability or timeout * @queue: Pointer to rotator queue * @entry: Pointer to rotation entry */ static struct sde_rot_hw_resource *sde_rotator_get_hw_resource( struct sde_rot_queue *queue, struct sde_rot_entry *entry) { struct sde_rot_hw_resource *hw = queue->hw; struct sde_rot_hw_resource *hw; struct sde_rot_mgr *mgr; int ret; if (!hw) { SDEROT_ERR("no hw in the queue\n"); if (!queue || !entry || !queue->hw) { SDEROT_ERR("null parameters\n"); return NULL; } hw = queue->hw; mgr = entry->private->mgr; BUG_ON(atomic_read(&hw->num_active) > hw->max_active); while (atomic_read(&hw->num_active) >= hw->max_active) { sde_rot_mgr_unlock(entry->private->mgr); while (!sde_rotator_is_hw_available(mgr, hw, entry)) { sde_rot_mgr_unlock(mgr); ret = wait_event_timeout(hw->wait_queue, (atomic_read(&hw->num_active) < hw->max_active), sde_rotator_is_hw_available(mgr, hw, entry), msecs_to_jiffies(mgr->hwacquire_timeout)); sde_rot_mgr_lock(entry->private->mgr); sde_rot_mgr_lock(mgr); if (!ret) { SDEROT_ERR( "timeout waiting for hw resource, a:%d p:%d\n", atomic_read(&hw->num_active), hw->pending_count); if (hw->workload) SDEROT_ERR("possible faulty workload s:%d.%d\n", hw->workload->item.session_id, hw->workload->item.sequence_id); return NULL; } } atomic_inc(&hw->num_active); SDEROT_DBG("active=%d pending=%d s:%d.%d\n", SDEROT_DBG("active=%d pending=%d rdot=%u/%u wrot=%u/%u s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, mgr->rdot_limit, entry->perf->rdot_limit, mgr->wrot_limit, entry->perf->wrot_limit, entry->item.session_id, entry->item.sequence_id); hw->workload = entry; mgr->rdot_limit = entry->perf->rdot_limit; mgr->wrot_limit = entry->perf->wrot_limit; return hw; } /* * sde_rotator_put_hw_resource - return hw resource and wake up waiting clients * @queue: Pointer to rotator queue * @entry: Pointer to rotation entry * @hw: Pointer to hw resource to be returned */ static void sde_rotator_put_hw_resource(struct sde_rot_queue *queue, struct sde_rot_hw_resource *hw) struct sde_rot_entry *entry, struct sde_rot_hw_resource *hw) { struct sde_rot_entry *entry = hw->workload; struct sde_rot_mgr *mgr; int i; if (!queue || !entry || !hw) { SDEROT_ERR("null parameters\n"); return; } mgr = entry->private->mgr; BUG_ON(atomic_read(&hw->num_active) < 1); hw->workload = NULL; if (!atomic_add_unless(&hw->num_active, -1, 0)) SDEROT_ERR("underflow active=%d pending=%d s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, entry->item.session_id, entry->item.sequence_id); wake_up(&hw->wait_queue); /* * Wake up all queues in case any entry is waiting for hw idle, * in order to update global settings, such as VBIF QoS. * This can be relaxed to the given hw resource if global * settings can be updated individually by entries already * queued in hw queue. */ for (i = 0; i < mgr->queue_count; i++) { struct sde_rot_hw_resource *hw_res = mgr->commitq[i].hw; if (hw_res) wake_up(&hw_res->wait_queue); } SDEROT_DBG("active=%d pending=%d s:%d.%d\n", atomic_read(&hw->num_active), hw->pending_count, entry->item.session_id, entry->item.sequence_id); Loading Loading @@ -908,6 +1014,14 @@ static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, &config->output.comp_ratio); perf->bw = read_bw + write_bw; perf->rdot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, config->input.format, config->frame_rate, true); perf->wrot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, config->input.format, config->frame_rate, false); return 0; } Loading Loading @@ -1069,7 +1183,7 @@ static void sde_rotator_commit_handler(struct work_struct *work) sde_rot_mgr_unlock(mgr); return; error: sde_rotator_put_hw_resource(entry->commitq, hw); sde_rotator_put_hw_resource(entry->commitq, entry, hw); get_hw_res_err: sde_rotator_signal_output(entry); sde_rotator_release_entry(mgr, entry); Loading Loading @@ -1141,7 +1255,7 @@ static void sde_rotator_done_handler(struct work_struct *work) entry->item.dst_rect.w, entry->item.dst_rect.h); sde_rot_mgr_lock(mgr); sde_rotator_put_hw_resource(entry->commitq, entry->commitq->hw); sde_rotator_put_hw_resource(entry->commitq, entry, entry->commitq->hw); sde_rotator_signal_output(entry); sde_rotator_release_entry(mgr, entry); atomic_dec(&request->pending_count); Loading Loading @@ -2275,7 +2389,7 @@ int sde_rotator_core_init(struct sde_rot_mgr **pmgr, sde_rotator_clk_ctrl(mgr, true); mdata->mdss_version = SDE_REG_READ(mdata, SDE_REG_HW_VERSION); SDEROT_INFO("mdss revision %x\n", mdata->mdss_version); SDEROT_DBG("mdss revision %x\n", mdata->mdss_version); if ((mdata->mdss_version & 0xFFFF0000) == 0x10070000) { mgr->ops_hw_init = sde_rotator_r1_init; Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_core.h +4 −1 Original line number Diff line number Diff line Loading @@ -169,7 +169,6 @@ struct sde_rot_hw_resource { atomic_t num_active; int max_active; wait_queue_head_t wait_queue; struct sde_rot_entry *workload; }; struct sde_rot_queue { Loading Loading @@ -225,6 +224,8 @@ struct sde_rot_perf { struct mutex work_dis_lock; u32 *work_distribution; int last_wb_idx; /* last known wb index, used when above count is 0 */ u32 rdot_limit; u32 wrot_limit; }; struct sde_rot_file_private { Loading Loading @@ -275,6 +276,8 @@ struct sde_rot_mgr { struct sde_rot_clk *rot_clk; int num_rot_clk; int core_clk_idx; u32 rdot_limit; u32 wrot_limit; u32 hwacquire_timeout; struct sde_mult_factor pixel_per_clk; Loading
drivers/media/platform/msm/sde/rotator/sde_rotator_r1_internal.h +1 −0 Original line number Diff line number Diff line Loading @@ -116,6 +116,7 @@ struct sde_mdp_pipe { struct sde_mdp_plane_sizes src_planes; struct sde_mdp_mixer *mixer_left; struct sde_mdp_mixer *mixer_right; struct sde_mdp_shared_reg_ctrl clk_ctrl; u32 params_changed; u32 offset; }; Loading