Loading msm/sde/sde_vbif.c +36 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include "sde_vbif.h" #include "sde_hw_vbif.h" #include "sde_trace.h" #include "sde_rotator_vbif.h" #define MAX_XIN_CLIENT 16 Loading Loading @@ -286,6 +287,41 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms, mutex_unlock(&vbif->mutex); } void mdp_vbif_lock(struct platform_device *parent_pdev, bool enable) { struct drm_device *ddev; struct sde_kms *sde_kms; struct sde_hw_vbif *vbif = NULL; int i; ddev = platform_get_drvdata(parent_pdev); if (!ddev || !ddev_to_msm_kms(ddev)) { SDE_ERROR("invalid drm device\n"); return; } sde_kms = to_sde_kms(ddev_to_msm_kms(ddev)); for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) { if (sde_kms->hw_vbif[i] && sde_kms->hw_vbif[i]->idx == VBIF_RT) { vbif = sde_kms->hw_vbif[i]; break; } } if (!vbif) { SDE_DEBUG("invalid vbif structure\n"); return; } if (enable) mutex_lock(&vbif->mutex); else mutex_unlock(&vbif->mutex); } bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms, struct sde_vbif_set_xin_halt_params *params) { Loading rotator/sde_rotator_base.c +109 −12 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" #include "sde_rotator_dev.h" #include "sde_rotator_vbif.h" static inline u64 fudge_factor(u64 val, u32 numer, u32 denom) { Loading Loading @@ -70,6 +71,7 @@ u32 sde_apply_comp_ratio_factor(u32 quota, #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) #define RES_WQXGA (2560*1600) #define XIN_HALT_TIMEOUT_US 0x4000 static int sde_mdp_wait_for_xin_halt(u32 xin_id) Loading Loading @@ -132,18 +134,36 @@ static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) return clk_forced_on; } void vbif_lock(struct platform_device *parent_pdev) { if (!parent_pdev) return; mdp_vbif_lock(parent_pdev, true); } void vbif_unlock(struct platform_device *parent_pdev) { if (!parent_pdev) return; mdp_vbif_lock(parent_pdev, false); } void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 reg_val; bool forced_on; int rc = 0; if (!mdata || !params || !params->reg_off_mdp_clk_ctrl) { SDEROT_ERR("null input parameter\n"); return; } if (params->xin_id > MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1) { if (!mdata->parent_pdev && params->xin_id > MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1) { SDEROT_ERR("xin_id:%d exceed max limit\n", params->xin_id); return; } Loading @@ -151,6 +171,8 @@ void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, true); vbif_lock(mdata->parent_pdev); SDEROT_EVTLOG(forced_on, params->xin_id); reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0); Loading @@ -158,12 +180,16 @@ void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) reg_val | BIT(params->xin_id)); /* this is a polling operation */ sde_mdp_wait_for_xin_halt(params->xin_id); rc = sde_mdp_wait_for_xin_halt(params->xin_id); if (rc == -ETIMEDOUT) params->xin_timeout = BIT(params->xin_id); reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0); SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val & ~BIT(params->xin_id)); vbif_unlock(mdata->parent_pdev); if (forced_on) force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, false); Loading Loading @@ -209,18 +235,36 @@ u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd) SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%llu rd:%d\n", width, height, fps, pixfmt, is_yuv, res, is_rd); if (!is_yuv) goto exit; /* * If (total_source_pixels <= 62208000 && YUV) -> RD/WROT=2 //1080p30 * If (total_source_pixels <= 124416000 && YUV) -> RD/WROT=4 //1080p60 * If (total_source_pixels <= 2160p && YUV && FPS <= 30) -> RD/WROT = 32 */ switch (mdata->mdss_version) { case SDE_MDP_HW_REV_540: if (is_yuv) { if (res <= (RES_1080p * 30)) ot_lim = 2; else if (res <= (RES_1080p * 60)) ot_lim = 4; else if (res <= (RES_WQXGA * 60)) ot_lim = 4; else if (res <= (RES_UHD * 30)) ot_lim = 8; } else if (fmt->bpp == 4 && res <= (RES_WQXGA * 60)) { ot_lim = 16; } break; default: if (is_yuv) { if (res <= (RES_1080p * 30)) ot_lim = 2; else if (res <= (RES_1080p * 60)) ot_lim = 4; } break; } exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); Loading Loading @@ -274,6 +318,8 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) u32 sts; bool forced_on; vbif_lock(mdata->parent_pdev); ot_lim = get_ot_limit( reg_off_vbif_lim_conf, bit_off_vbif_lim_conf, Loading Loading @@ -319,6 +365,7 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) SDEROT_EVTLOG(params->num, params->xin_id, ot_lim); exit: vbif_unlock(mdata->parent_pdev); return; } Loading Loading @@ -465,7 +512,7 @@ static int sde_mdp_parse_dt_handler(struct platform_device *pdev, rc = of_property_read_u32_array(pdev->dev.of_node, prop_name, offsets, len); if (rc) { SDEROT_ERR("Error from prop %s : u32 array read\n", prop_name); SDEROT_DBG("Error from prop %s : u32 array read\n", prop_name); return -EINVAL; } Loading Loading @@ -499,7 +546,7 @@ static void sde_mdp_parse_vbif_memtype(struct platform_device *pdev, "qcom,mdss-rot-vbif-memtype"); mdata->vbif_memtype = kcalloc(mdata->vbif_memtype_count, sizeof(u32), GFP_KERNEL); if (!mdata->vbif_memtype) { if (!mdata->vbif_memtype || !mdata->vbif_memtype_count) { mdata->vbif_memtype_count = 0; return; } Loading Loading @@ -527,7 +574,7 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev, "qcom,mdss-rot-vbif-qos-setting"); mdata->vbif_nrt_qos = kcalloc(mdata->npriority_lvl, sizeof(u32), GFP_KERNEL); if (!mdata->vbif_nrt_qos) { if (!mdata->vbif_nrt_qos || !mdata->npriority_lvl) { mdata->npriority_lvl = 0; return; } Loading @@ -544,6 +591,16 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev, } } static void sde_mdp_parse_vbif_xin_id(struct platform_device *pdev, struct sde_rot_data_type *mdata) { mdata->vbif_xin_id[XIN_SSPP] = XIN_SSPP; mdata->vbif_xin_id[XIN_WRITEBACK] = XIN_WRITEBACK; sde_mdp_parse_dt_handler(pdev, "qcom,mdss-rot-xin-id", mdata->vbif_xin_id, MAX_XIN); } static void sde_mdp_parse_cdp_setting(struct platform_device *pdev, struct sde_rot_data_type *mdata) { Loading Loading @@ -674,6 +731,35 @@ static void sde_mdp_parse_inline_rot_lut_setting(struct platform_device *pdev, } } static void sde_mdp_parse_rt_rotator(struct device_node *np) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct platform_device *pdev; struct of_phandle_args phargs; int rc = 0; rc = of_parse_phandle_with_args(np, "qcom,mdss-rot-parent", "#list-cells", 0, &phargs); if (rc) return; if (!phargs.np || !phargs.args_count) { SDEROT_ERR("invalid args\n"); return; } pdev = of_find_device_by_node(phargs.np); if (pdev) { mdata->parent_pdev = pdev; } else { mdata->parent_pdev = NULL; SDEROT_ERR("Parent mdp node not available\n"); } of_node_put(phargs.np); } static int sde_mdp_parse_dt_misc(struct platform_device *pdev, struct sde_rot_data_type *mdata) { Loading Loading @@ -702,6 +788,8 @@ static int sde_mdp_parse_dt_misc(struct platform_device *pdev, sde_mdp_parse_vbif_qos(pdev, mdata); sde_mdp_parse_vbif_xin_id(pdev, mdata); sde_mdp_parse_vbif_memtype(pdev, mdata); sde_mdp_parse_rot_lut_setting(pdev, mdata); Loading Loading @@ -820,6 +908,13 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata, int rc; struct sde_rot_data_type *mdata; /* if probe deferral happened, return early*/ if (sde_rot_res) { SDEROT_ERR("Rotator data already initialized, skip init\n"); return 0; } mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL); if (mdata == NULL) return -ENOMEM; Loading @@ -846,6 +941,8 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata, SDEROT_DBG("SDE ROT VBIF HW Base addr=%pK len=0x%x\n", mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len); sde_mdp_parse_rt_rotator(pdev->dev.of_node); rc = sde_mdp_parse_dt_misc(pdev, mdata); if (rc) { SDEROT_ERR("Error in device tree : misc\n"); Loading rotator/sde_rotator_base.h +16 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ #include <linux/kref.h> #include <linux/kernel.h> #include <linux/regulator/consumer.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include "sde_rotator_hwio.h" #include "sde_rotator_io_util.h" Loading Loading @@ -41,11 +43,17 @@ #define SDE_MDP_HW_REV_500 SDE_MDP_REV(5, 0, 0) /* sm8150 v1.0 */ #define SDE_MDP_HW_REV_520 SDE_MDP_REV(5, 2, 0) /* sdmmagpie v1.0 */ #define SDE_MDP_HW_REV_530 SDE_MDP_REV(5, 3, 0) /* sm6150 v1.0 */ #define SDE_MDP_HW_REV_540 SDE_MDP_REV(5, 4, 0) /* sdmtrinket v1.0 */ #define SDE_MDP_HW_REV_600 SDE_MDP_REV(6, 0, 0) /* msmnile+ v1.0 */ #define SDE_MDP_VBIF_4_LEVEL_REMAPPER 4 #define SDE_MDP_VBIF_8_LEVEL_REMAPPER 8 /* XIN mapping */ #define XIN_SSPP 0 #define XIN_WRITEBACK 1 #define MAX_XIN 2 struct sde_mult_factor { uint32_t numer; uint32_t denom; Loading @@ -70,11 +78,13 @@ struct sde_mdp_set_ot_params { * @xin_id: xin port number of vbif * @reg_off_mdp_clk_ctrl: reg offset for vbif clock control * @bit_off_mdp_clk_ctrl: bit offset for vbif clock control * @xin_timeout: bit position indicates timeout on corresponding xin id */ struct sde_mdp_vbif_halt_params { u32 xin_id; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; u32 xin_timeout; }; enum sde_bus_vote_type { Loading Loading @@ -220,6 +230,7 @@ struct sde_rot_data_type { u32 mdss_version; struct platform_device *pdev; struct platform_device *parent_pdev; struct sde_io_data sde_io; struct sde_io_data vbif_nrt_io; char __iomem *mdp_base; Loading Loading @@ -248,6 +259,8 @@ struct sde_rot_data_type { u32 *vbif_nrt_qos; u32 npriority_lvl; u32 vbif_xin_id[MAX_XIN]; struct pm_qos_request pm_qos_rot_cpu_req; u32 rot_pm_qos_cpu_count; u32 rot_pm_qos_cpu_mask; Loading Loading @@ -300,6 +313,9 @@ 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); void vbif_lock(struct platform_device *parent_pdev); void vbif_unlock(struct platform_device *parent_pdev); void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params); int sde_mdp_init_vbif(void); Loading rotator/sde_rotator_debug.c +0 −21 Original line number Diff line number Diff line Loading @@ -574,26 +574,6 @@ static ssize_t sde_rot_evtlog_dump_read(struct file *file, char __user *buff, return len; } /* * sde_rot_evtlog_dump_write - debugfs write handler for evtlog dump * @file: file handler * @user_buf: user buffer content from debugfs * @count: size of user buffer * @ppos: position offset of user buffer */ static ssize_t sde_rot_evtlog_dump_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { sde_rot_evtlog_dump_all(); sde_rot_dump_reg_all(); if (sde_rot_dbg_evtlog.panic_on_err) panic("evtlog_dump_write"); return count; } /* * sde_rot_evtlog_dump_helper - helper function for evtlog dump * @dead: boolean indicates panic after dump Loading Loading @@ -959,7 +939,6 @@ static int sde_rotator_core_create_debugfs( static const struct file_operations sde_rot_evtlog_fops = { .open = sde_rot_evtlog_dump_open, .read = sde_rot_evtlog_dump_read, .write = sde_rot_evtlog_dump_write, }; static int sde_rotator_evtlog_create_debugfs( Loading rotator/sde_rotator_r3.c +84 −17 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "sde_rotator_r3_debug.h" #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" #include "sde_rotator_vbif.h" #define RES_UHD (3840*2160) #define MS_TO_US(t) ((t) * USEC_PER_MSEC) Loading @@ -35,10 +36,6 @@ #define TRAFFIC_SHAPE_CLKTICK_12MS 230400 #define TRAFFIC_SHAPE_VSYNC_CLK 19200000 /* XIN mapping */ #define XIN_SSPP 0 #define XIN_WRITEBACK 1 /* wait for at most 2 vsync for lowest refresh rate (24hz) */ #define KOFF_TIMEOUT (42 * 8) Loading Loading @@ -748,23 +745,29 @@ static void sde_hw_rotator_disable_irq(struct sde_hw_rotator *rot) } } static void sde_hw_rotator_halt_vbif_xin_client(void) static int sde_hw_rotator_halt_vbif_xin_client(void) { struct sde_mdp_vbif_halt_params halt_params; int rc = 0; struct sde_rot_data_type *mdata = sde_rot_get_mdata(); memset(&halt_params, 0, sizeof(struct sde_mdp_vbif_halt_params)); halt_params.xin_id = XIN_SSPP; halt_params.xin_id = mdata->vbif_xin_id[XIN_SSPP]; halt_params.reg_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; halt_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN0; sde_mdp_halt_vbif_xin(&halt_params); rc |= halt_params.xin_timeout; memset(&halt_params, 0, sizeof(struct sde_mdp_vbif_halt_params)); halt_params.xin_id = XIN_WRITEBACK; halt_params.xin_id = mdata->vbif_xin_id[XIN_WRITEBACK]; halt_params.reg_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; halt_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1; sde_mdp_halt_vbif_xin(&halt_params); rc |= halt_params.xin_timeout; return rc; } /** Loading Loading @@ -1025,6 +1028,47 @@ static void sde_hw_rotator_unmap_vaddr(struct sde_dbg_buf *dbgbuf) dbgbuf->height = 0; } static void sde_hw_rotator_vbif_rt_setting(void) { u32 reg_high, reg_shift, reg_val, reg_val_lvl, mask, vbif_qos; struct sde_rot_data_type *mdata = sde_rot_get_mdata(); int i, j; vbif_lock(mdata->parent_pdev); for (i = 0; i < mdata->npriority_lvl; i++) { for (j = 0; j < MAX_XIN; j++) { reg_high = ((mdata->vbif_xin_id[j] & 0x8) >> 3) * 4 + (i * 8); reg_shift = mdata->vbif_xin_id[j] * 4; reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + reg_high); reg_val_lvl = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + reg_high); mask = 0x7 << (mdata->vbif_xin_id[j] * 4); vbif_qos = mdata->vbif_nrt_qos[i]; reg_val &= ~mask; reg_val |= (vbif_qos << reg_shift) & mask; reg_val_lvl &= ~mask; reg_val_lvl |= (vbif_qos << reg_shift) & mask; SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + reg_high, reg_val); SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl); } } vbif_unlock(mdata->parent_pdev); } /* * sde_hw_rotator_vbif_setting - helper function to set vbif QoS remapper * levels, enable write gather enable and avoid clk gating setting for Loading Loading @@ -2095,7 +2139,10 @@ static u32 sde_hw_rotator_wait_done_regdma( __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); if (ubwcerr || abort) { spin_unlock_irqrestore(&rot->rotisr_lock, flags); if (ubwcerr || abort || sde_hw_rotator_halt_vbif_xin_client()) { /* * Perform recovery for ROT SSPP UBWC decode * error. Loading @@ -2103,16 +2150,15 @@ static u32 sde_hw_rotator_wait_done_regdma( * - reset TS logic so all pending rotation * in hw queue got done signalled */ spin_unlock_irqrestore(&rot->rotisr_lock, flags); if (!sde_hw_rotator_reset(rot, ctx)) status = REGDMA_INCOMPLETE_CMD; else status = ROT_ERROR_BIT; spin_lock_irqsave(&rot->rotisr_lock, flags); } else { status = ROT_ERROR_BIT; } spin_lock_irqsave(&rot->rotisr_lock, flags); } else { if (rc == 1) SDEROT_WARN( Loading Loading @@ -2829,7 +2875,7 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, struct sde_mdp_set_ot_params ot_params; memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params)); ot_params.xin_id = XIN_SSPP; ot_params.xin_id = mdata->vbif_xin_id[XIN_SSPP]; ot_params.num = 0; /* not used */ ot_params.width = entry->perf->config.input.width; ot_params.height = entry->perf->config.input.height; Loading @@ -2851,7 +2897,7 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, struct sde_mdp_set_ot_params ot_params; memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params)); ot_params.xin_id = XIN_WRITEBACK; ot_params.xin_id = mdata->vbif_xin_id[XIN_WRITEBACK]; ot_params.num = 0; /* not used */ ot_params.width = entry->perf->config.input.width; ot_params.height = entry->perf->config.input.height; Loading @@ -2872,15 +2918,20 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, if (test_bit(SDE_QOS_PER_PIPE_LUT, mdata->sde_qos_map)) { u32 qos_lut = 0; /* low priority for nrt read client */ trace_rot_perf_set_qos_luts(XIN_SSPP, sspp_cfg.fmt->format, qos_lut, sde_mdp_is_linear_format(sspp_cfg.fmt)); trace_rot_perf_set_qos_luts(mdata->vbif_xin_id[XIN_SSPP], sspp_cfg.fmt->format, qos_lut, sde_mdp_is_linear_format(sspp_cfg.fmt)); SDE_ROTREG_WRITE(rot->mdss_base, ROT_SSPP_CREQ_LUT, qos_lut); } /* VBIF QoS and other settings */ if (!ctx->sbuf_mode) if (!ctx->sbuf_mode) { if (mdata->parent_pdev) sde_hw_rotator_vbif_rt_setting(); else sde_hw_rotator_vbif_setting(rot); } return 0; Loading Loading @@ -3178,6 +3229,22 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot) ARRAY_SIZE(sde_hw_rotator_v4_outpixfmts_sbuf); rot->downscale_caps = "LINEAR/1.5/2/4/8/16/32/64 TILE/1.5/2/4 TP10/1.5/2"; } else if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, SDE_MDP_HW_REV_540)) { SDEROT_DBG("Sys cache inline rotation not supported\n"); set_bit(SDE_CAPS_UBWC_2, mdata->sde_caps_map); set_bit(SDE_CAPS_PARTIALWR, mdata->sde_caps_map); set_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map); rot->inpixfmts[SDE_ROTATOR_MODE_OFFLINE] = sde_hw_rotator_v4_inpixfmts; rot->num_inpixfmt[SDE_ROTATOR_MODE_OFFLINE] = ARRAY_SIZE(sde_hw_rotator_v4_inpixfmts); rot->outpixfmts[SDE_ROTATOR_MODE_OFFLINE] = sde_hw_rotator_v4_outpixfmts; rot->num_outpixfmt[SDE_ROTATOR_MODE_OFFLINE] = ARRAY_SIZE(sde_hw_rotator_v4_outpixfmts); rot->downscale_caps = "LINEAR/1.5/2/4/8/16/32/64 TILE/1.5/2/4 TP10/1.5/2"; } else if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, SDE_MDP_HW_REV_400) || IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, Loading Loading
msm/sde/sde_vbif.c +36 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include "sde_vbif.h" #include "sde_hw_vbif.h" #include "sde_trace.h" #include "sde_rotator_vbif.h" #define MAX_XIN_CLIENT 16 Loading Loading @@ -286,6 +287,41 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms, mutex_unlock(&vbif->mutex); } void mdp_vbif_lock(struct platform_device *parent_pdev, bool enable) { struct drm_device *ddev; struct sde_kms *sde_kms; struct sde_hw_vbif *vbif = NULL; int i; ddev = platform_get_drvdata(parent_pdev); if (!ddev || !ddev_to_msm_kms(ddev)) { SDE_ERROR("invalid drm device\n"); return; } sde_kms = to_sde_kms(ddev_to_msm_kms(ddev)); for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) { if (sde_kms->hw_vbif[i] && sde_kms->hw_vbif[i]->idx == VBIF_RT) { vbif = sde_kms->hw_vbif[i]; break; } } if (!vbif) { SDE_DEBUG("invalid vbif structure\n"); return; } if (enable) mutex_lock(&vbif->mutex); else mutex_unlock(&vbif->mutex); } bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms, struct sde_vbif_set_xin_halt_params *params) { Loading
rotator/sde_rotator_base.c +109 −12 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" #include "sde_rotator_dev.h" #include "sde_rotator_vbif.h" static inline u64 fudge_factor(u64 val, u32 numer, u32 denom) { Loading Loading @@ -70,6 +71,7 @@ u32 sde_apply_comp_ratio_factor(u32 quota, #define RES_1080p (1088*1920) #define RES_UHD (3840*2160) #define RES_WQXGA (2560*1600) #define XIN_HALT_TIMEOUT_US 0x4000 static int sde_mdp_wait_for_xin_halt(u32 xin_id) Loading Loading @@ -132,18 +134,36 @@ static bool force_on_xin_clk(u32 bit_off, u32 clk_ctl_reg_off, bool enable) return clk_forced_on; } void vbif_lock(struct platform_device *parent_pdev) { if (!parent_pdev) return; mdp_vbif_lock(parent_pdev, true); } void vbif_unlock(struct platform_device *parent_pdev) { if (!parent_pdev) return; mdp_vbif_lock(parent_pdev, false); } void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); u32 reg_val; bool forced_on; int rc = 0; if (!mdata || !params || !params->reg_off_mdp_clk_ctrl) { SDEROT_ERR("null input parameter\n"); return; } if (params->xin_id > MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1) { if (!mdata->parent_pdev && params->xin_id > MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1) { SDEROT_ERR("xin_id:%d exceed max limit\n", params->xin_id); return; } Loading @@ -151,6 +171,8 @@ void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, true); vbif_lock(mdata->parent_pdev); SDEROT_EVTLOG(forced_on, params->xin_id); reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0); Loading @@ -158,12 +180,16 @@ void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params) reg_val | BIT(params->xin_id)); /* this is a polling operation */ sde_mdp_wait_for_xin_halt(params->xin_id); rc = sde_mdp_wait_for_xin_halt(params->xin_id); if (rc == -ETIMEDOUT) params->xin_timeout = BIT(params->xin_id); reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL0); SDE_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, reg_val & ~BIT(params->xin_id)); vbif_unlock(mdata->parent_pdev); if (forced_on) force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, false); Loading Loading @@ -209,18 +235,36 @@ u32 sde_mdp_get_ot_limit(u32 width, u32 height, u32 pixfmt, u32 fps, u32 is_rd) SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%llu rd:%d\n", width, height, fps, pixfmt, is_yuv, res, is_rd); if (!is_yuv) goto exit; /* * If (total_source_pixels <= 62208000 && YUV) -> RD/WROT=2 //1080p30 * If (total_source_pixels <= 124416000 && YUV) -> RD/WROT=4 //1080p60 * If (total_source_pixels <= 2160p && YUV && FPS <= 30) -> RD/WROT = 32 */ switch (mdata->mdss_version) { case SDE_MDP_HW_REV_540: if (is_yuv) { if (res <= (RES_1080p * 30)) ot_lim = 2; else if (res <= (RES_1080p * 60)) ot_lim = 4; else if (res <= (RES_WQXGA * 60)) ot_lim = 4; else if (res <= (RES_UHD * 30)) ot_lim = 8; } else if (fmt->bpp == 4 && res <= (RES_WQXGA * 60)) { ot_lim = 16; } break; default: if (is_yuv) { if (res <= (RES_1080p * 30)) ot_lim = 2; else if (res <= (RES_1080p * 60)) ot_lim = 4; } break; } exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); Loading Loading @@ -274,6 +318,8 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) u32 sts; bool forced_on; vbif_lock(mdata->parent_pdev); ot_lim = get_ot_limit( reg_off_vbif_lim_conf, bit_off_vbif_lim_conf, Loading Loading @@ -319,6 +365,7 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) SDEROT_EVTLOG(params->num, params->xin_id, ot_lim); exit: vbif_unlock(mdata->parent_pdev); return; } Loading Loading @@ -465,7 +512,7 @@ static int sde_mdp_parse_dt_handler(struct platform_device *pdev, rc = of_property_read_u32_array(pdev->dev.of_node, prop_name, offsets, len); if (rc) { SDEROT_ERR("Error from prop %s : u32 array read\n", prop_name); SDEROT_DBG("Error from prop %s : u32 array read\n", prop_name); return -EINVAL; } Loading Loading @@ -499,7 +546,7 @@ static void sde_mdp_parse_vbif_memtype(struct platform_device *pdev, "qcom,mdss-rot-vbif-memtype"); mdata->vbif_memtype = kcalloc(mdata->vbif_memtype_count, sizeof(u32), GFP_KERNEL); if (!mdata->vbif_memtype) { if (!mdata->vbif_memtype || !mdata->vbif_memtype_count) { mdata->vbif_memtype_count = 0; return; } Loading Loading @@ -527,7 +574,7 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev, "qcom,mdss-rot-vbif-qos-setting"); mdata->vbif_nrt_qos = kcalloc(mdata->npriority_lvl, sizeof(u32), GFP_KERNEL); if (!mdata->vbif_nrt_qos) { if (!mdata->vbif_nrt_qos || !mdata->npriority_lvl) { mdata->npriority_lvl = 0; return; } Loading @@ -544,6 +591,16 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev, } } static void sde_mdp_parse_vbif_xin_id(struct platform_device *pdev, struct sde_rot_data_type *mdata) { mdata->vbif_xin_id[XIN_SSPP] = XIN_SSPP; mdata->vbif_xin_id[XIN_WRITEBACK] = XIN_WRITEBACK; sde_mdp_parse_dt_handler(pdev, "qcom,mdss-rot-xin-id", mdata->vbif_xin_id, MAX_XIN); } static void sde_mdp_parse_cdp_setting(struct platform_device *pdev, struct sde_rot_data_type *mdata) { Loading Loading @@ -674,6 +731,35 @@ static void sde_mdp_parse_inline_rot_lut_setting(struct platform_device *pdev, } } static void sde_mdp_parse_rt_rotator(struct device_node *np) { struct sde_rot_data_type *mdata = sde_rot_get_mdata(); struct platform_device *pdev; struct of_phandle_args phargs; int rc = 0; rc = of_parse_phandle_with_args(np, "qcom,mdss-rot-parent", "#list-cells", 0, &phargs); if (rc) return; if (!phargs.np || !phargs.args_count) { SDEROT_ERR("invalid args\n"); return; } pdev = of_find_device_by_node(phargs.np); if (pdev) { mdata->parent_pdev = pdev; } else { mdata->parent_pdev = NULL; SDEROT_ERR("Parent mdp node not available\n"); } of_node_put(phargs.np); } static int sde_mdp_parse_dt_misc(struct platform_device *pdev, struct sde_rot_data_type *mdata) { Loading Loading @@ -702,6 +788,8 @@ static int sde_mdp_parse_dt_misc(struct platform_device *pdev, sde_mdp_parse_vbif_qos(pdev, mdata); sde_mdp_parse_vbif_xin_id(pdev, mdata); sde_mdp_parse_vbif_memtype(pdev, mdata); sde_mdp_parse_rot_lut_setting(pdev, mdata); Loading Loading @@ -820,6 +908,13 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata, int rc; struct sde_rot_data_type *mdata; /* if probe deferral happened, return early*/ if (sde_rot_res) { SDEROT_ERR("Rotator data already initialized, skip init\n"); return 0; } mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL); if (mdata == NULL) return -ENOMEM; Loading @@ -846,6 +941,8 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata, SDEROT_DBG("SDE ROT VBIF HW Base addr=%pK len=0x%x\n", mdata->vbif_nrt_io.base, mdata->vbif_nrt_io.len); sde_mdp_parse_rt_rotator(pdev->dev.of_node); rc = sde_mdp_parse_dt_misc(pdev, mdata); if (rc) { SDEROT_ERR("Error in device tree : misc\n"); Loading
rotator/sde_rotator_base.h +16 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,8 @@ #include <linux/kref.h> #include <linux/kernel.h> #include <linux/regulator/consumer.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include "sde_rotator_hwio.h" #include "sde_rotator_io_util.h" Loading Loading @@ -41,11 +43,17 @@ #define SDE_MDP_HW_REV_500 SDE_MDP_REV(5, 0, 0) /* sm8150 v1.0 */ #define SDE_MDP_HW_REV_520 SDE_MDP_REV(5, 2, 0) /* sdmmagpie v1.0 */ #define SDE_MDP_HW_REV_530 SDE_MDP_REV(5, 3, 0) /* sm6150 v1.0 */ #define SDE_MDP_HW_REV_540 SDE_MDP_REV(5, 4, 0) /* sdmtrinket v1.0 */ #define SDE_MDP_HW_REV_600 SDE_MDP_REV(6, 0, 0) /* msmnile+ v1.0 */ #define SDE_MDP_VBIF_4_LEVEL_REMAPPER 4 #define SDE_MDP_VBIF_8_LEVEL_REMAPPER 8 /* XIN mapping */ #define XIN_SSPP 0 #define XIN_WRITEBACK 1 #define MAX_XIN 2 struct sde_mult_factor { uint32_t numer; uint32_t denom; Loading @@ -70,11 +78,13 @@ struct sde_mdp_set_ot_params { * @xin_id: xin port number of vbif * @reg_off_mdp_clk_ctrl: reg offset for vbif clock control * @bit_off_mdp_clk_ctrl: bit offset for vbif clock control * @xin_timeout: bit position indicates timeout on corresponding xin id */ struct sde_mdp_vbif_halt_params { u32 xin_id; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; u32 xin_timeout; }; enum sde_bus_vote_type { Loading Loading @@ -220,6 +230,7 @@ struct sde_rot_data_type { u32 mdss_version; struct platform_device *pdev; struct platform_device *parent_pdev; struct sde_io_data sde_io; struct sde_io_data vbif_nrt_io; char __iomem *mdp_base; Loading Loading @@ -248,6 +259,8 @@ struct sde_rot_data_type { u32 *vbif_nrt_qos; u32 npriority_lvl; u32 vbif_xin_id[MAX_XIN]; struct pm_qos_request pm_qos_rot_cpu_req; u32 rot_pm_qos_cpu_count; u32 rot_pm_qos_cpu_mask; Loading Loading @@ -300,6 +313,9 @@ 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); void vbif_lock(struct platform_device *parent_pdev); void vbif_unlock(struct platform_device *parent_pdev); void sde_mdp_halt_vbif_xin(struct sde_mdp_vbif_halt_params *params); int sde_mdp_init_vbif(void); Loading
rotator/sde_rotator_debug.c +0 −21 Original line number Diff line number Diff line Loading @@ -574,26 +574,6 @@ static ssize_t sde_rot_evtlog_dump_read(struct file *file, char __user *buff, return len; } /* * sde_rot_evtlog_dump_write - debugfs write handler for evtlog dump * @file: file handler * @user_buf: user buffer content from debugfs * @count: size of user buffer * @ppos: position offset of user buffer */ static ssize_t sde_rot_evtlog_dump_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { sde_rot_evtlog_dump_all(); sde_rot_dump_reg_all(); if (sde_rot_dbg_evtlog.panic_on_err) panic("evtlog_dump_write"); return count; } /* * sde_rot_evtlog_dump_helper - helper function for evtlog dump * @dead: boolean indicates panic after dump Loading Loading @@ -959,7 +939,6 @@ static int sde_rotator_core_create_debugfs( static const struct file_operations sde_rot_evtlog_fops = { .open = sde_rot_evtlog_dump_open, .read = sde_rot_evtlog_dump_read, .write = sde_rot_evtlog_dump_write, }; static int sde_rotator_evtlog_create_debugfs( Loading
rotator/sde_rotator_r3.c +84 −17 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "sde_rotator_r3_debug.h" #include "sde_rotator_trace.h" #include "sde_rotator_debug.h" #include "sde_rotator_vbif.h" #define RES_UHD (3840*2160) #define MS_TO_US(t) ((t) * USEC_PER_MSEC) Loading @@ -35,10 +36,6 @@ #define TRAFFIC_SHAPE_CLKTICK_12MS 230400 #define TRAFFIC_SHAPE_VSYNC_CLK 19200000 /* XIN mapping */ #define XIN_SSPP 0 #define XIN_WRITEBACK 1 /* wait for at most 2 vsync for lowest refresh rate (24hz) */ #define KOFF_TIMEOUT (42 * 8) Loading Loading @@ -748,23 +745,29 @@ static void sde_hw_rotator_disable_irq(struct sde_hw_rotator *rot) } } static void sde_hw_rotator_halt_vbif_xin_client(void) static int sde_hw_rotator_halt_vbif_xin_client(void) { struct sde_mdp_vbif_halt_params halt_params; int rc = 0; struct sde_rot_data_type *mdata = sde_rot_get_mdata(); memset(&halt_params, 0, sizeof(struct sde_mdp_vbif_halt_params)); halt_params.xin_id = XIN_SSPP; halt_params.xin_id = mdata->vbif_xin_id[XIN_SSPP]; halt_params.reg_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; halt_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN0; sde_mdp_halt_vbif_xin(&halt_params); rc |= halt_params.xin_timeout; memset(&halt_params, 0, sizeof(struct sde_mdp_vbif_halt_params)); halt_params.xin_id = XIN_WRITEBACK; halt_params.xin_id = mdata->vbif_xin_id[XIN_WRITEBACK]; halt_params.reg_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0; halt_params.bit_off_mdp_clk_ctrl = MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0_XIN1; sde_mdp_halt_vbif_xin(&halt_params); rc |= halt_params.xin_timeout; return rc; } /** Loading Loading @@ -1025,6 +1028,47 @@ static void sde_hw_rotator_unmap_vaddr(struct sde_dbg_buf *dbgbuf) dbgbuf->height = 0; } static void sde_hw_rotator_vbif_rt_setting(void) { u32 reg_high, reg_shift, reg_val, reg_val_lvl, mask, vbif_qos; struct sde_rot_data_type *mdata = sde_rot_get_mdata(); int i, j; vbif_lock(mdata->parent_pdev); for (i = 0; i < mdata->npriority_lvl; i++) { for (j = 0; j < MAX_XIN; j++) { reg_high = ((mdata->vbif_xin_id[j] & 0x8) >> 3) * 4 + (i * 8); reg_shift = mdata->vbif_xin_id[j] * 4; reg_val = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + reg_high); reg_val_lvl = SDE_VBIF_READ(mdata, MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + reg_high); mask = 0x7 << (mdata->vbif_xin_id[j] * 4); vbif_qos = mdata->vbif_nrt_qos[i]; reg_val &= ~mask; reg_val |= (vbif_qos << reg_shift) & mask; reg_val_lvl &= ~mask; reg_val_lvl |= (vbif_qos << reg_shift) & mask; SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_QOS_RP_REMAP_000 + reg_high, reg_val); SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_QOS_LVL_REMAP_000 + reg_high, reg_val_lvl); } } vbif_unlock(mdata->parent_pdev); } /* * sde_hw_rotator_vbif_setting - helper function to set vbif QoS remapper * levels, enable write gather enable and avoid clk gating setting for Loading Loading @@ -2095,7 +2139,10 @@ static u32 sde_hw_rotator_wait_done_regdma( __sde_hw_rotator_get_timestamp(rot, ROT_QUEUE_LOW_PRIORITY); if (ubwcerr || abort) { spin_unlock_irqrestore(&rot->rotisr_lock, flags); if (ubwcerr || abort || sde_hw_rotator_halt_vbif_xin_client()) { /* * Perform recovery for ROT SSPP UBWC decode * error. Loading @@ -2103,16 +2150,15 @@ static u32 sde_hw_rotator_wait_done_regdma( * - reset TS logic so all pending rotation * in hw queue got done signalled */ spin_unlock_irqrestore(&rot->rotisr_lock, flags); if (!sde_hw_rotator_reset(rot, ctx)) status = REGDMA_INCOMPLETE_CMD; else status = ROT_ERROR_BIT; spin_lock_irqsave(&rot->rotisr_lock, flags); } else { status = ROT_ERROR_BIT; } spin_lock_irqsave(&rot->rotisr_lock, flags); } else { if (rc == 1) SDEROT_WARN( Loading Loading @@ -2829,7 +2875,7 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, struct sde_mdp_set_ot_params ot_params; memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params)); ot_params.xin_id = XIN_SSPP; ot_params.xin_id = mdata->vbif_xin_id[XIN_SSPP]; ot_params.num = 0; /* not used */ ot_params.width = entry->perf->config.input.width; ot_params.height = entry->perf->config.input.height; Loading @@ -2851,7 +2897,7 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, struct sde_mdp_set_ot_params ot_params; memset(&ot_params, 0, sizeof(struct sde_mdp_set_ot_params)); ot_params.xin_id = XIN_WRITEBACK; ot_params.xin_id = mdata->vbif_xin_id[XIN_WRITEBACK]; ot_params.num = 0; /* not used */ ot_params.width = entry->perf->config.input.width; ot_params.height = entry->perf->config.input.height; Loading @@ -2872,15 +2918,20 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, if (test_bit(SDE_QOS_PER_PIPE_LUT, mdata->sde_qos_map)) { u32 qos_lut = 0; /* low priority for nrt read client */ trace_rot_perf_set_qos_luts(XIN_SSPP, sspp_cfg.fmt->format, qos_lut, sde_mdp_is_linear_format(sspp_cfg.fmt)); trace_rot_perf_set_qos_luts(mdata->vbif_xin_id[XIN_SSPP], sspp_cfg.fmt->format, qos_lut, sde_mdp_is_linear_format(sspp_cfg.fmt)); SDE_ROTREG_WRITE(rot->mdss_base, ROT_SSPP_CREQ_LUT, qos_lut); } /* VBIF QoS and other settings */ if (!ctx->sbuf_mode) if (!ctx->sbuf_mode) { if (mdata->parent_pdev) sde_hw_rotator_vbif_rt_setting(); else sde_hw_rotator_vbif_setting(rot); } return 0; Loading Loading @@ -3178,6 +3229,22 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot) ARRAY_SIZE(sde_hw_rotator_v4_outpixfmts_sbuf); rot->downscale_caps = "LINEAR/1.5/2/4/8/16/32/64 TILE/1.5/2/4 TP10/1.5/2"; } else if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, SDE_MDP_HW_REV_540)) { SDEROT_DBG("Sys cache inline rotation not supported\n"); set_bit(SDE_CAPS_UBWC_2, mdata->sde_caps_map); set_bit(SDE_CAPS_PARTIALWR, mdata->sde_caps_map); set_bit(SDE_CAPS_HW_TIMESTAMP, mdata->sde_caps_map); rot->inpixfmts[SDE_ROTATOR_MODE_OFFLINE] = sde_hw_rotator_v4_inpixfmts; rot->num_inpixfmt[SDE_ROTATOR_MODE_OFFLINE] = ARRAY_SIZE(sde_hw_rotator_v4_inpixfmts); rot->outpixfmts[SDE_ROTATOR_MODE_OFFLINE] = sde_hw_rotator_v4_outpixfmts; rot->num_outpixfmt[SDE_ROTATOR_MODE_OFFLINE] = ARRAY_SIZE(sde_hw_rotator_v4_outpixfmts); rot->downscale_caps = "LINEAR/1.5/2/4/8/16/32/64 TILE/1.5/2/4 TP10/1.5/2"; } else if (IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, SDE_MDP_HW_REV_400) || IS_SDE_MAJOR_MINOR_SAME(mdata->mdss_version, Loading