Loading Documentation/devicetree/bindings/display/msm/sde-rsc.txt 0 → 100644 +72 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. SDE RSC Snapdragon Display Engine implements display rsc to driver display core to different modes for power saving Required properties - compatible: Must be "qcom,sde-rsc" - reg: Offset and length of the register set for the device. - reg-names: Names to refer to register sets related to this device Optional properties: - clocks: List of phandles for clock device nodes needed by the device. - clock-names: List of clock names needed by the device. - vdd-supply: phandle for vdd regulator device node. - qcom,sde-rsc-version: U32 property represents the rsc version. It helps to select correct sequence for sde rsc based on version. - qcom,sde-dram-channels: U32 property represents the number of channels in the Bus memory controller. - qcom,sde-num-nrt-paths: U32 property represents the number of non-realtime paths in each Bus Scaling Usecase. This value depends on number of AXI ports that are dedicated to non-realtime VBIF for particular chipset. These paths must be defined after rt-paths in "qcom,msm-bus,vectors-KBps" vector request. Bus Scaling Subnodes: - qcom,sde-data-bus: Property to provide Bus scaling for data bus access for sde blocks. Bus Scaling Data: - qcom,msm-bus,name: String property describing client name. - qcom,msm-bus,active-only: Boolean context flag for requests in active or dual (active & sleep) contex - qcom,msm-bus,num-cases: This is the number of Bus Scaling use cases defined in the vectors property. - qcom,msm-bus,num-paths: This represents the number of paths in each Bus Scaling Usecase. - qcom,msm-bus,vectors-KBps: * A series of 4 cell properties, with a format of (src, dst, ab, ib) which is defined at Documentation/devicetree/bindings/arm/msm/msm_bus.txt * Current values of src & dst are defined at include/linux/msm-bus-board.h Example: sde_rscc { cell-index = <0>; compatible = "qcom,sde-rsc"; reg = <0xaf20000 0x1c44>, <0xaf30000 0x3fd4>; reg-names = "drv", "wrapper"; clocks = <&clock_mmss clk_mdss_ahb_clk>, <&clock_mmss clk_mdss_axi_clk>; clock-names = "iface_clk", "bus_clk"; vdd-supply = <&gdsc_mdss>; qcom,sde-rsc-version = <1>; qcom,sde-dram-channels = <2>; qcom,sde-num-nrt-paths = <1>; qcom,sde-data-bus { qcom,msm-bus,name = "sde_rsc"; qcom,msm-bus,active-only; qcom,msm-bus,num-cases = <3>; qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = <22 512 0 0>, <23 512 0 0>, <22 512 0 6400000>, <23 512 0 6400000>, <22 512 0 6400000>, <23 512 0 6400000>; }; }; drivers/gpu/drm/msm/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ msm_drm-y := \ sde_io_util.o \ sde/sde_hw_reg_dma_v1_color_proc.o \ sde/sde_hw_color_proc_v4.o \ sde_rsc.o \ sde_rsc_hw.o \ # use drm gpu driver only if qcom_kgsl driver not available ifneq ($(CONFIG_QCOM_KGSL),y) Loading drivers/gpu/drm/msm/dsi-staging/dsi_display.c +1 −0 Original line number Diff line number Diff line Loading @@ -2683,6 +2683,7 @@ int dsi_display_get_info(struct msm_display_info *info, void *disp) info->h_tile_instance[i] = display->ctrl[i].ctrl->index; info->is_connected = true; info->is_primary = true; info->width_mm = phy_props.panel_width_mm; info->height_mm = phy_props.panel_height_mm; info->max_width = 1920; Loading drivers/gpu/drm/msm/msm_drv.h +2 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ enum msm_display_caps { * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles * @is_connected: Set to true if display is connected * @is_primary: Set to true if display is primary display * @width_mm: Physical width * @height_mm: Physical height * @max_width: Max width of display. In case of hot pluggable display Loading @@ -215,6 +216,7 @@ struct msm_display_info { uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_connected; bool is_primary; unsigned int width_mm; unsigned int height_mm; Loading drivers/gpu/drm/msm/sde/sde_encoder.c +62 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ #include "sde_formats.h" #include "sde_encoder_phys.h" #include "sde_color_processing.h" #include "sde_rsc.h" #include "sde_power_handle.h" #define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\ (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) Loading Loading @@ -111,6 +114,9 @@ struct sde_encoder_virt { atomic_t frame_done_timeout; struct timer_list frame_done_timer; struct sde_rsc_client *rsc_client; struct msm_display_info disp_info; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) Loading Loading @@ -157,6 +163,8 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); mutex_lock(&sde_enc->enc_lock); sde_rsc_client_destroy(sde_enc->rsc_client); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading Loading @@ -367,7 +375,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) struct sde_encoder_virt *sde_enc = NULL; struct msm_drm_private *priv; struct sde_kms *sde_kms; int i = 0; int i = 0, ret; enum sde_rsc_state rsc_state; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); Loading @@ -390,6 +399,9 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true); sde_enc->cur_master = NULL; rsc_state = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE ? SDE_RSC_CMD_STATE : SDE_RSC_VID_STATE; for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading @@ -411,6 +423,19 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) SDE_ERROR("virt encoder has no master! num_phys %d\n", i); else if (sde_enc->cur_master->ops.enable) sde_enc->cur_master->ops.enable(sde_enc->cur_master); /** * this should be after interface enable because interface enable api * turns on panel, configure the TE for command mode and turns on * timing engine for video mode. The RSC api call is going to wait * for vsync after it switches the mode - that requires te/timing engine * enabled. */ ret = sde_rsc_client_state_update(sde_enc->rsc_client, rsc_state, NULL, drm_enc->crtc ? drm_enc->crtc->index : -1); if (ret) SDE_ERROR("sde rsc client update failed ret:%d\n", ret); } static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) Loading Loading @@ -462,6 +487,8 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_rm_release(&sde_kms->rm, drm_enc); sde_rsc_client_state_update(sde_enc->rsc_client, SDE_RSC_IDLE_STATE, NULL, -1); sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); } Loading Loading @@ -821,6 +848,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) struct sde_encoder_phys *phys; bool needs_hw_reset = false; unsigned int i; int ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); Loading @@ -831,6 +859,15 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); if (sde_enc->disp_info.is_primary) { ret = sde_rsc_client_vote(sde_enc->rsc_client, SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA, SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA, true); if (ret) SDE_ERROR("sde rsc client vote failed ret:%d\n", ret); } /* prepare for next kickoff, may include waiting on previous kickoff */ for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; Loading Loading @@ -1310,6 +1347,7 @@ struct drm_encoder *sde_encoder_init( struct drm_encoder *drm_enc = NULL; struct sde_encoder_virt *sde_enc = NULL; int drm_enc_mode = DRM_MODE_ENCODER_NONE; char name[SDE_NAME_SIZE]; int ret = 0; sde_enc = kzalloc(sizeof(*sde_enc), GFP_KERNEL); Loading @@ -1336,6 +1374,16 @@ struct drm_encoder *sde_encoder_init( _sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms); snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); sde_enc->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX, name, disp_info->is_primary); if (IS_ERR_OR_NULL(sde_enc->rsc_client)) { SDE_ERROR("sde rsc client create failed :%ld\n", PTR_ERR(sde_enc->rsc_client)); sde_enc->rsc_client = NULL; } memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info)); SDE_DEBUG_ENC(sde_enc, "created\n"); return drm_enc; Loading Loading @@ -1400,3 +1448,16 @@ enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder) return INTF_MODE_NONE; } bool sde_encoder_get_intf_primary(struct drm_encoder *encoder) { struct sde_encoder_virt *sde_enc = NULL; if (!encoder) { SDE_ERROR("invalid encoder\n"); return INTF_MODE_NONE; } sde_enc = to_sde_encoder_virt(encoder); return sde_enc->disp_info.is_primary; } Loading
Documentation/devicetree/bindings/display/msm/sde-rsc.txt 0 → 100644 +72 −0 Original line number Diff line number Diff line Qualcomm Technologies, Inc. SDE RSC Snapdragon Display Engine implements display rsc to driver display core to different modes for power saving Required properties - compatible: Must be "qcom,sde-rsc" - reg: Offset and length of the register set for the device. - reg-names: Names to refer to register sets related to this device Optional properties: - clocks: List of phandles for clock device nodes needed by the device. - clock-names: List of clock names needed by the device. - vdd-supply: phandle for vdd regulator device node. - qcom,sde-rsc-version: U32 property represents the rsc version. It helps to select correct sequence for sde rsc based on version. - qcom,sde-dram-channels: U32 property represents the number of channels in the Bus memory controller. - qcom,sde-num-nrt-paths: U32 property represents the number of non-realtime paths in each Bus Scaling Usecase. This value depends on number of AXI ports that are dedicated to non-realtime VBIF for particular chipset. These paths must be defined after rt-paths in "qcom,msm-bus,vectors-KBps" vector request. Bus Scaling Subnodes: - qcom,sde-data-bus: Property to provide Bus scaling for data bus access for sde blocks. Bus Scaling Data: - qcom,msm-bus,name: String property describing client name. - qcom,msm-bus,active-only: Boolean context flag for requests in active or dual (active & sleep) contex - qcom,msm-bus,num-cases: This is the number of Bus Scaling use cases defined in the vectors property. - qcom,msm-bus,num-paths: This represents the number of paths in each Bus Scaling Usecase. - qcom,msm-bus,vectors-KBps: * A series of 4 cell properties, with a format of (src, dst, ab, ib) which is defined at Documentation/devicetree/bindings/arm/msm/msm_bus.txt * Current values of src & dst are defined at include/linux/msm-bus-board.h Example: sde_rscc { cell-index = <0>; compatible = "qcom,sde-rsc"; reg = <0xaf20000 0x1c44>, <0xaf30000 0x3fd4>; reg-names = "drv", "wrapper"; clocks = <&clock_mmss clk_mdss_ahb_clk>, <&clock_mmss clk_mdss_axi_clk>; clock-names = "iface_clk", "bus_clk"; vdd-supply = <&gdsc_mdss>; qcom,sde-rsc-version = <1>; qcom,sde-dram-channels = <2>; qcom,sde-num-nrt-paths = <1>; qcom,sde-data-bus { qcom,msm-bus,name = "sde_rsc"; qcom,msm-bus,active-only; qcom,msm-bus,num-cases = <3>; qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = <22 512 0 0>, <23 512 0 0>, <22 512 0 6400000>, <23 512 0 6400000>, <22 512 0 6400000>, <23 512 0 6400000>; }; };
drivers/gpu/drm/msm/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ msm_drm-y := \ sde_io_util.o \ sde/sde_hw_reg_dma_v1_color_proc.o \ sde/sde_hw_color_proc_v4.o \ sde_rsc.o \ sde_rsc_hw.o \ # use drm gpu driver only if qcom_kgsl driver not available ifneq ($(CONFIG_QCOM_KGSL),y) Loading
drivers/gpu/drm/msm/dsi-staging/dsi_display.c +1 −0 Original line number Diff line number Diff line Loading @@ -2683,6 +2683,7 @@ int dsi_display_get_info(struct msm_display_info *info, void *disp) info->h_tile_instance[i] = display->ctrl[i].ctrl->index; info->is_connected = true; info->is_primary = true; info->width_mm = phy_props.panel_width_mm; info->height_mm = phy_props.panel_height_mm; info->max_width = 1920; Loading
drivers/gpu/drm/msm/msm_drv.h +2 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ enum msm_display_caps { * @h_tile_instance: Controller instance used per tile. Number of elements is * based on num_of_h_tiles * @is_connected: Set to true if display is connected * @is_primary: Set to true if display is primary display * @width_mm: Physical width * @height_mm: Physical height * @max_width: Max width of display. In case of hot pluggable display Loading @@ -215,6 +216,7 @@ struct msm_display_info { uint32_t h_tile_instance[MAX_H_TILES_PER_DISPLAY]; bool is_connected; bool is_primary; unsigned int width_mm; unsigned int height_mm; Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +62 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ #include "sde_formats.h" #include "sde_encoder_phys.h" #include "sde_color_processing.h" #include "sde_rsc.h" #include "sde_power_handle.h" #define SDE_DEBUG_ENC(e, fmt, ...) SDE_DEBUG("enc%d " fmt,\ (e) ? (e)->base.base.id : -1, ##__VA_ARGS__) Loading Loading @@ -111,6 +114,9 @@ struct sde_encoder_virt { atomic_t frame_done_timeout; struct timer_list frame_done_timer; struct sde_rsc_client *rsc_client; struct msm_display_info disp_info; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) Loading Loading @@ -157,6 +163,8 @@ void sde_encoder_destroy(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); mutex_lock(&sde_enc->enc_lock); sde_rsc_client_destroy(sde_enc->rsc_client); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading Loading @@ -367,7 +375,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) struct sde_encoder_virt *sde_enc = NULL; struct msm_drm_private *priv; struct sde_kms *sde_kms; int i = 0; int i = 0, ret; enum sde_rsc_state rsc_state; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); Loading @@ -390,6 +399,9 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true); sde_enc->cur_master = NULL; rsc_state = sde_enc->disp_info.capabilities & MSM_DISPLAY_CAP_CMD_MODE ? SDE_RSC_CMD_STATE : SDE_RSC_VID_STATE; for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; Loading @@ -411,6 +423,19 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc) SDE_ERROR("virt encoder has no master! num_phys %d\n", i); else if (sde_enc->cur_master->ops.enable) sde_enc->cur_master->ops.enable(sde_enc->cur_master); /** * this should be after interface enable because interface enable api * turns on panel, configure the TE for command mode and turns on * timing engine for video mode. The RSC api call is going to wait * for vsync after it switches the mode - that requires te/timing engine * enabled. */ ret = sde_rsc_client_state_update(sde_enc->rsc_client, rsc_state, NULL, drm_enc->crtc ? drm_enc->crtc->index : -1); if (ret) SDE_ERROR("sde rsc client update failed ret:%d\n", ret); } static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) Loading Loading @@ -462,6 +487,8 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_rm_release(&sde_kms->rm, drm_enc); sde_rsc_client_state_update(sde_enc->rsc_client, SDE_RSC_IDLE_STATE, NULL, -1); sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false); } Loading Loading @@ -821,6 +848,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) struct sde_encoder_phys *phys; bool needs_hw_reset = false; unsigned int i; int ret; if (!drm_enc) { SDE_ERROR("invalid encoder\n"); Loading @@ -831,6 +859,15 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc) SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); if (sde_enc->disp_info.is_primary) { ret = sde_rsc_client_vote(sde_enc->rsc_client, SDE_POWER_HANDLE_DATA_BUS_IB_QUOTA, SDE_POWER_HANDLE_DATA_BUS_AB_QUOTA, true); if (ret) SDE_ERROR("sde rsc client vote failed ret:%d\n", ret); } /* prepare for next kickoff, may include waiting on previous kickoff */ for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; Loading Loading @@ -1310,6 +1347,7 @@ struct drm_encoder *sde_encoder_init( struct drm_encoder *drm_enc = NULL; struct sde_encoder_virt *sde_enc = NULL; int drm_enc_mode = DRM_MODE_ENCODER_NONE; char name[SDE_NAME_SIZE]; int ret = 0; sde_enc = kzalloc(sizeof(*sde_enc), GFP_KERNEL); Loading @@ -1336,6 +1374,16 @@ struct drm_encoder *sde_encoder_init( _sde_encoder_init_debugfs(drm_enc, sde_enc, sde_kms); snprintf(name, SDE_NAME_SIZE, "rsc_enc%u", drm_enc->base.id); sde_enc->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX, name, disp_info->is_primary); if (IS_ERR_OR_NULL(sde_enc->rsc_client)) { SDE_ERROR("sde rsc client create failed :%ld\n", PTR_ERR(sde_enc->rsc_client)); sde_enc->rsc_client = NULL; } memcpy(&sde_enc->disp_info, disp_info, sizeof(*disp_info)); SDE_DEBUG_ENC(sde_enc, "created\n"); return drm_enc; Loading Loading @@ -1400,3 +1448,16 @@ enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder) return INTF_MODE_NONE; } bool sde_encoder_get_intf_primary(struct drm_encoder *encoder) { struct sde_encoder_virt *sde_enc = NULL; if (!encoder) { SDE_ERROR("invalid encoder\n"); return INTF_MODE_NONE; } sde_enc = to_sde_encoder_virt(encoder); return sde_enc->disp_info.is_primary; }