diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt index 7a98e4e8fdd2..0ab4d53f2663 100644 --- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt +++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt @@ -92,6 +92,8 @@ Required properties active in MDP for this configuration. Meant for hardware that has hw cursors support as a source pipe. +- qcom,mdss-rot-xin-id: Array of VBIF clients ids (xins) corresponding + to the respective rotator pipes. - qcom,mdss-pipe-cursor-xin-id: Array of VBIF clients ids (xins) corresponding to the respective cursor pipes. Number of xin ids defined should match the number of offsets @@ -754,6 +756,7 @@ Example: qcom,mdss-pipe-rgb-xin-id = <1 5 9>; qcom,mdss-pipe-dma-xin-id = <2 10>; qcom,mdss-pipe-cursor-xin-id = <7 7>; + qcom,mdss-rot-xin-id = <14 15>; qcom,mdss-pipe-vig-clk-ctrl-offsets = <0x3AC 0 0>, <0x3B4 0 0>, diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c index ff9e7889e431..5149d92e1f6f 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c @@ -423,6 +423,40 @@ static void sde_mdp_parse_vbif_qos(struct platform_device *pdev, } } +static int sde_mdp_parse_vbif_xin_id(struct platform_device *pdev, + struct sde_rot_data_type *mdata) +{ + int rc = 0; + bool default_xin_id = false; + + mdata->nxid = sde_mdp_parse_dt_prop_len(pdev, + "qcom,mdss-rot-xin-id"); + if (!mdata->nxid) { + mdata->nxid = 2; + default_xin_id = true; + } + mdata->vbif_xin_id = kzalloc(sizeof(u32) * + mdata->nxid, GFP_KERNEL); + if (!mdata->vbif_xin_id) { + SDEROT_ERR("xin alloc failure\n"); + return -ENOMEM; + } + if (default_xin_id) { + mdata->vbif_xin_id[XIN_SSPP] = XIN_SSPP; + mdata->vbif_xin_id[XIN_WRITEBACK] = XIN_WRITEBACK; + } else { + rc = sde_mdp_parse_dt_handler(pdev, + "qcom,mdss-rot-xin-id", mdata->vbif_xin_id, + mdata->nxid); + if (rc) { + SDEROT_ERR("vbif xin id setting not found\n"); + return rc; + } + } + + return 0; +} + static int sde_mdp_parse_dt_misc(struct platform_device *pdev, struct sde_rot_data_type *mdata) { @@ -448,6 +482,11 @@ static int sde_mdp_parse_dt_misc(struct platform_device *pdev, "Could not read optional property: highest bank bit\n"); sde_mdp_parse_vbif_qos(pdev, mdata); + rc = sde_mdp_parse_vbif_xin_id(pdev, mdata); + if (rc) { + SDEROT_DBG("vbif xin id dt parse failure\n"); + return rc; + } mdata->mdp_base = mdata->sde_io.base + SDE_MDP_OFFSET; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h index 45802053d427..48d7b0925733 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h @@ -27,6 +27,10 @@ #define MDSS_MDP_HW_REV_320 0x30020000 /* sdm660 */ #define MDSS_MDP_HW_REV_330 0x30030000 /* sdm630 */ +/* XIN mapping */ +#define XIN_SSPP 0 +#define XIN_WRITEBACK 1 + struct sde_mult_factor { uint32_t numer; uint32_t denom; @@ -165,11 +169,16 @@ struct sde_rot_data_type { u32 *vbif_nrt_qos; u32 npriority_lvl; + u32 *vbif_xin_id; + u32 nxid; + int iommu_attached; int iommu_ref_cnt; int (*iommu_ctrl)(int enable); int (*secure_session_ctrl)(int enable); int (*wait_for_transition)(int state, int request); + void (*vbif_reg_lock)(void); + void (*vbif_reg_unlock)(void); struct sde_rot_vbif_debug_bus *nrt_vbif_dbg_bus; u32 nrt_vbif_dbg_bus_size; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h index 051db7863c54..8a8711ea468b 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_hwio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -65,6 +65,8 @@ #define MMSS_VBIF_NRT_VBIF_IN_WR_LIM_CONF2 0x00C8 #define MMSS_VBIF_NRT_VBIF_OUT_RD_LIM_CONF0 0x00D0 #define MMSS_VBIF_NRT_VBIF_OUT_WR_LIM_CONF0 0x00D4 +#define MDSS_VBIF_QOS_RP_REMAP_BASE 0x550 +#define MDSS_VBIF_QOS_LVL_REMAP_BASE 0x570 #define SDE_MDP_REG_TRAFFIC_SHAPER_EN BIT(31) #define SDE_MDP_REG_TRAFFIC_SHAPER_RD_CLIENT(num) (0x030 + (num * 4)) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index 3bb8399da4bf..20104646138c 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -42,9 +42,6 @@ #define TRAFFIC_SHAPE_CLKTICK_14MS 268800 #define TRAFFIC_SHAPE_CLKTICK_12MS 230400 -/* XIN mapping */ -#define XIN_SSPP 0 -#define XIN_WRITEBACK 1 /* wait for at most 2 vsync for lowest refresh rate (24hz) */ #define KOFF_TIMEOUT msecs_to_jiffies(42 * 32) @@ -1691,11 +1688,14 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr, item->input.format, item->output.format); + if (mdata->vbif_reg_lock) + mdata->vbif_reg_lock(); + if (mdata->default_ot_rd_limit) { 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; @@ -1715,7 +1715,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; @@ -1734,36 +1734,61 @@ 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); } if (mdata->npriority_lvl > 0) { - u32 mask, reg_val, i, vbif_qos; + u32 mask, reg_val, i, j, vbif_qos, reg_val_lvl, reg_high; for (i = 0; i < mdata->npriority_lvl; i++) { - reg_val = SDE_VBIF_READ(mdata, - MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4); - mask = 0x3 << (XIN_SSPP * 2); - reg_val &= ~(mask); - vbif_qos = mdata->vbif_nrt_qos[i]; - reg_val |= vbif_qos << (XIN_SSPP * 2); - /* ensure write is issued after the read operation */ - mb(); - SDE_VBIF_WRITE(mdata, - MMSS_VBIF_NRT_VBIF_QOS_REMAP_00 + i*4, - reg_val); + + for (j = 0; j < mdata->nxid; j++) { + reg_high = ((mdata->vbif_xin_id[j] & + 0x8) >> 3) * 4 + (i * 8); + + reg_val = SDE_VBIF_READ(mdata, + MDSS_VBIF_QOS_RP_REMAP_BASE + reg_high); + reg_val_lvl = SDE_VBIF_READ(mdata, + MDSS_VBIF_QOS_LVL_REMAP_BASE + reg_high); + + mask = 0x3 << (mdata->vbif_xin_id[j] * 4); + vbif_qos = mdata->vbif_nrt_qos[i]; + + reg_val &= ~(mask); + reg_val |= vbif_qos << + (mdata->vbif_xin_id[j] * 4); + + reg_val_lvl &= ~(mask); + reg_val_lvl |= vbif_qos << + (mdata->vbif_xin_id[j] * 4); + + pr_debug("idx:%d xin:%d reg:0x%x val:0x%x lvl:0x%x\n", + i, mdata->vbif_xin_id[j], + reg_high, reg_val, reg_val_lvl); + SDE_VBIF_WRITE(mdata, + MDSS_VBIF_QOS_RP_REMAP_BASE + + reg_high, reg_val); + SDE_VBIF_WRITE(mdata, + MDSS_VBIF_QOS_LVL_REMAP_BASE + + reg_high, reg_val_lvl); + } } } /* Enable write gather for writeback to remove write gaps, which * may hang AXI/BIMC/SDE. */ - SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN, - BIT(XIN_WRITEBACK)); + if (!((mdata->mdss_version == MDSS_MDP_HW_REV_320) || + (mdata->mdss_version == MDSS_MDP_HW_REV_330))) + SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN, + BIT(mdata->vbif_xin_id[XIN_WRITEBACK])); + if (mdata->vbif_reg_unlock) + mdata->vbif_reg_unlock(); return 0; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c index 46001fa7b429..f3b5e3e3ec0b 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c @@ -381,6 +381,8 @@ static void sde_smmu_callback(struct mdss_smmu_intf *smmu) /* Copy mmu device info into sde private structure */ mdata->iommu_ctrl = smmu->iommu_ctrl; + mdata->vbif_reg_lock = smmu->reg_lock; + mdata->vbif_reg_unlock = smmu->reg_unlock; mdata->wait_for_transition = smmu->wait_for_transition; mdata->secure_session_ctrl = smmu->secure_session_ctrl; if (smmu->is_secure) { diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 0ab6ae4bb38f..20134c631e61 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -576,6 +576,8 @@ struct mdss_util_intf { int (*iommu_ctrl)(int enable); void (*iommu_lock)(void); void (*iommu_unlock)(void); + void (*vbif_reg_lock)(void); + void (*vbif_reg_unlock)(void); int (*secure_session_ctrl)(int enable); void (*bus_bandwidth_ctrl)(int enable); int (*bus_scale_set_quota)(int client, u64 ab_quota, u64 ib_quota); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 539ae0231a28..d698a2da8744 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -784,6 +784,19 @@ int mdss_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx) } #endif +void mdss_mdp_vbif_reg_lock(void) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + mutex_lock(&mdata->reg_lock); +} + +void mdss_mdp_vbif_reg_unlock(void) +{ + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + mutex_unlock(&mdata->reg_lock); +} static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num) { @@ -2868,6 +2881,8 @@ static int mdss_mdp_probe(struct platform_device *pdev) mdss_res->mdss_util->bus_bandwidth_ctrl = mdss_bus_bandwidth_ctrl; mdss_res->mdss_util->panel_intf_type = mdss_panel_intf_type; mdss_res->mdss_util->panel_intf_status = mdss_panel_get_intf_status; + mdss_res->mdss_util->vbif_reg_lock = mdss_mdp_vbif_reg_lock; + mdss_res->mdss_util->vbif_reg_unlock = mdss_mdp_vbif_reg_unlock; rc = msm_dss_ioremap_byname(pdev, &mdata->mdss_io, "mdp_phys"); if (rc) { diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c index 7ca0cd37d43c..886e5fc6ba7d 100644 --- a/drivers/video/fbdev/msm/mdss_smmu.c +++ b/drivers/video/fbdev/msm/mdss_smmu.c @@ -845,6 +845,8 @@ int mdss_smmu_probe(struct platform_device *pdev) } mdss_smmu->base.iommu_ctrl = mdata->mdss_util->iommu_ctrl; + mdss_smmu->base.reg_lock = mdata->mdss_util->vbif_reg_lock; + mdss_smmu->base.reg_unlock = mdata->mdss_util->vbif_reg_unlock; mdss_smmu->base.secure_session_ctrl = mdata->mdss_util->secure_session_ctrl; mdss_smmu->base.wait_for_transition = mdss_smmu_secure_wait; diff --git a/include/linux/mdss_smmu_ext.h b/include/linux/mdss_smmu_ext.h index 414ab055595a..dedcd34d795c 100644 --- a/include/linux/mdss_smmu_ext.h +++ b/include/linux/mdss_smmu_ext.h @@ -22,6 +22,7 @@ * @iommu_ctrl: iommu ctrl function for enable/disable attach. * @secure_session_ctrl: ctrl function for enable/disable session. * @wait_for_transition:function to wait till secure transtion is complete. + * @reg_lock /reg_unlock: Lock to access shared registers. */ struct mdss_smmu_intf { struct device *dev; @@ -30,6 +31,8 @@ struct mdss_smmu_intf { int (*iommu_ctrl)(int); int (*secure_session_ctrl)(int); int (*wait_for_transition)(int state, int request); + void (*reg_lock)(void); + void (*reg_unlock)(void); }; typedef void (*msm_smmu_handler_t) (struct mdss_smmu_intf *smmu);