Loading Documentation/devicetree/bindings/media/video/msm-vidc.txt +5 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,9 @@ Optional properties: The bitmap is defined as: scalable = 0x1 (if the driver should vary the clock's frequency based on load) power collapsible = 0x2 (if the driver should disable the clock if no load) gate-able = 0x2 (if the driver should disable the clock if no load) - qcom,sw-power-collapse = A bool indicating if video hardware core can be power collapsed in idle state. - qcom,use-non-secure-pil = A bool indicating which type of pil to use to load the fw. - qcom,use-dynamic-bw-update = A bool indicating whether dynamic bandwidth Loading Loading @@ -124,7 +126,8 @@ Example: qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/ qcom,clock-names = "foo_clk", "bar_clk", "baz_clk"; clock-names = "foo_clk", "bar_clk", "baz_clk"; qcom,clock-properties = <0x3 0x1 0x0>; qcom,clock-configs = <0x3 0x1 0x0>; qcom,sw-power-collapse; qcom,buffer-type-tz-usage-table = <0x1 0x1>, <0x1fe 0x2>; qcom,msm-bus-clients { Loading drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +10 −7 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ enum clock_properties { CLOCK_PROP_HAS_SCALING = 1 << 0, CLOCK_PROP_HAS_SW_POWER_COLLAPSE = 1 << 1, CLOCK_PROP_HAS_GATING = 1 << 1, }; static size_t get_u32_array_num_elements(struct platform_device *pdev, Loading Loading @@ -618,16 +618,19 @@ static int msm_vidc_load_clock_table( vc->load_freq_tbl = NULL; } vc->has_sw_power_collapse = !!(clock_props[c] & CLOCK_PROP_HAS_SW_POWER_COLLAPSE); vc->has_gating = !!(clock_props[c] & CLOCK_PROP_HAS_GATING); dprintk(VIDC_DBG, "Found clock %s: scales = %s, s/w collapse = %s\n", vc->name, vc->count ? "yes" : "no", vc->has_sw_power_collapse ? "yes" : "no"); "Found clock %s: scale-able = %s, gate-able = %s\n", vc->name, vc->count ? "yes" : "no", vc->has_gating ? "yes" : "no"); } res->sw_power_collapsible = of_property_read_bool(pdev->dev.of_node, "qcom,sw-power-collapse"); dprintk(VIDC_DBG, "Power collapse supported = %s\n", res->sw_power_collapsible ? "yes" : "no"); return 0; err_load_clk_prop_fail: Loading drivers/media/platform/msm/vidc/msm_vidc_resources.h +2 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ struct clock_info { struct clk *clk; struct load_freq_table *load_freq_tbl; u32 count; /* == has_scaling iff count != 0 */ bool has_sw_power_collapse; bool has_gating; }; struct clock_set { Loading Loading @@ -118,6 +118,7 @@ struct msm_vidc_platform_resources { struct bus_set bus_set; bool dynamic_bw_update; bool use_non_secure_pil; bool sw_power_collapsible; }; struct msm_vidc_idle_time { Loading drivers/media/platform/msm/vidc/venus_hfi.c +16 −10 Original line number Diff line number Diff line Loading @@ -1173,7 +1173,7 @@ static inline int venus_hfi_clk_enable(struct venus_hfi_device *device) } venus_hfi_for_each_clock(device, cl) { if (cl->has_sw_power_collapse) { if (cl->has_gating) { rc = clk_enable(cl->clk); if (rc) { dprintk(VIDC_ERR, "Failed to enable clocks\n"); Loading @@ -1193,7 +1193,7 @@ fail_clk_enable: if (i < 0) break; if (cl->has_sw_power_collapse) { if (cl->has_gating) { usleep(100); clk_disable(cl->clk); } Loading Loading @@ -1222,7 +1222,7 @@ static inline void venus_hfi_clk_disable(struct venus_hfi_device *device) /* We get better power savings if we lower the venus core clock to the * lowest level before disabling it. */ cl = venus_hfi_get_clock(device, "core_clk"); if (cl && cl->has_sw_power_collapse) { if (cl && cl->has_gating) { int rc = clk_set_rate(cl->clk, venus_hfi_get_clock_rate(cl, 0)); if (rc) { Loading @@ -1233,7 +1233,7 @@ static inline void venus_hfi_clk_disable(struct venus_hfi_device *device) } venus_hfi_for_each_clock(device, cl) { if (cl->has_sw_power_collapse) { if (cl->has_gating) { usleep(100); clk_disable(cl->clk); dprintk(VIDC_DBG, "Clock: %s disabled\n", cl->name); Loading Loading @@ -2205,9 +2205,6 @@ static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device) VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK); } venus_hfi_clk_disable(device); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies(msm_vidc_pwr_collapse_delay))) dprintk(VIDC_DBG, "PM work already scheduled\n"); already_disabled: device->clk_state = DISABLED_PREPARED; } Loading Loading @@ -3084,6 +3081,16 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) } switch (rc) { case HFI_MSG_SYS_IDLE: /* Queue worker thread to enable power collapse */ if (device->res->sw_power_collapsible) { if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } dprintk(VIDC_DBG, "Received HFI_MSG_SYS_IDLE\n"); rc = venus_hfi_try_clk_gating(device); Loading Loading @@ -3204,7 +3211,7 @@ static inline int venus_hfi_init_clocks(struct msm_vidc_platform_resources *res, int i = 0; dprintk(VIDC_DBG, "%s: scalable? %d, gate-able? %d\n", cl->name, !!cl->count, cl->has_sw_power_collapse); !!cl->count, cl->has_gating); for (i = 0; i < cl->count; ++i) { dprintk(VIDC_DBG, "\tload = %d, freq = %d\n", cl->load_freq_tbl[i].load, Loading Loading @@ -3267,8 +3274,7 @@ static inline void venus_hfi_disable_unprepare_clks( } WARN_ON(!mutex_is_locked(&device->clk_pwr_lock)); venus_hfi_for_each_clock(device, cl) { if (device->clk_state == DISABLED_PREPARED && cl->has_sw_power_collapse) { if (device->clk_state == DISABLED_PREPARED) { dprintk(VIDC_DBG, "Omitting clk_disable of %s in %s as it's already disabled\n", cl->name, __func__); Loading Loading
Documentation/devicetree/bindings/media/video/msm-vidc.txt +5 −2 Original line number Diff line number Diff line Loading @@ -94,7 +94,9 @@ Optional properties: The bitmap is defined as: scalable = 0x1 (if the driver should vary the clock's frequency based on load) power collapsible = 0x2 (if the driver should disable the clock if no load) gate-able = 0x2 (if the driver should disable the clock if no load) - qcom,sw-power-collapse = A bool indicating if video hardware core can be power collapsed in idle state. - qcom,use-non-secure-pil = A bool indicating which type of pil to use to load the fw. - qcom,use-dynamic-bw-update = A bool indicating whether dynamic bandwidth Loading Loading @@ -124,7 +126,8 @@ Example: qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/ qcom,clock-names = "foo_clk", "bar_clk", "baz_clk"; clock-names = "foo_clk", "bar_clk", "baz_clk"; qcom,clock-properties = <0x3 0x1 0x0>; qcom,clock-configs = <0x3 0x1 0x0>; qcom,sw-power-collapse; qcom,buffer-type-tz-usage-table = <0x1 0x1>, <0x1fe 0x2>; qcom,msm-bus-clients { Loading
drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +10 −7 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ enum clock_properties { CLOCK_PROP_HAS_SCALING = 1 << 0, CLOCK_PROP_HAS_SW_POWER_COLLAPSE = 1 << 1, CLOCK_PROP_HAS_GATING = 1 << 1, }; static size_t get_u32_array_num_elements(struct platform_device *pdev, Loading Loading @@ -618,16 +618,19 @@ static int msm_vidc_load_clock_table( vc->load_freq_tbl = NULL; } vc->has_sw_power_collapse = !!(clock_props[c] & CLOCK_PROP_HAS_SW_POWER_COLLAPSE); vc->has_gating = !!(clock_props[c] & CLOCK_PROP_HAS_GATING); dprintk(VIDC_DBG, "Found clock %s: scales = %s, s/w collapse = %s\n", vc->name, vc->count ? "yes" : "no", vc->has_sw_power_collapse ? "yes" : "no"); "Found clock %s: scale-able = %s, gate-able = %s\n", vc->name, vc->count ? "yes" : "no", vc->has_gating ? "yes" : "no"); } res->sw_power_collapsible = of_property_read_bool(pdev->dev.of_node, "qcom,sw-power-collapse"); dprintk(VIDC_DBG, "Power collapse supported = %s\n", res->sw_power_collapsible ? "yes" : "no"); return 0; err_load_clk_prop_fail: Loading
drivers/media/platform/msm/vidc/msm_vidc_resources.h +2 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,7 @@ struct clock_info { struct clk *clk; struct load_freq_table *load_freq_tbl; u32 count; /* == has_scaling iff count != 0 */ bool has_sw_power_collapse; bool has_gating; }; struct clock_set { Loading Loading @@ -118,6 +118,7 @@ struct msm_vidc_platform_resources { struct bus_set bus_set; bool dynamic_bw_update; bool use_non_secure_pil; bool sw_power_collapsible; }; struct msm_vidc_idle_time { Loading
drivers/media/platform/msm/vidc/venus_hfi.c +16 −10 Original line number Diff line number Diff line Loading @@ -1173,7 +1173,7 @@ static inline int venus_hfi_clk_enable(struct venus_hfi_device *device) } venus_hfi_for_each_clock(device, cl) { if (cl->has_sw_power_collapse) { if (cl->has_gating) { rc = clk_enable(cl->clk); if (rc) { dprintk(VIDC_ERR, "Failed to enable clocks\n"); Loading @@ -1193,7 +1193,7 @@ fail_clk_enable: if (i < 0) break; if (cl->has_sw_power_collapse) { if (cl->has_gating) { usleep(100); clk_disable(cl->clk); } Loading Loading @@ -1222,7 +1222,7 @@ static inline void venus_hfi_clk_disable(struct venus_hfi_device *device) /* We get better power savings if we lower the venus core clock to the * lowest level before disabling it. */ cl = venus_hfi_get_clock(device, "core_clk"); if (cl && cl->has_sw_power_collapse) { if (cl && cl->has_gating) { int rc = clk_set_rate(cl->clk, venus_hfi_get_clock_rate(cl, 0)); if (rc) { Loading @@ -1233,7 +1233,7 @@ static inline void venus_hfi_clk_disable(struct venus_hfi_device *device) } venus_hfi_for_each_clock(device, cl) { if (cl->has_sw_power_collapse) { if (cl->has_gating) { usleep(100); clk_disable(cl->clk); dprintk(VIDC_DBG, "Clock: %s disabled\n", cl->name); Loading Loading @@ -2205,9 +2205,6 @@ static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device) VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK); } venus_hfi_clk_disable(device); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies(msm_vidc_pwr_collapse_delay))) dprintk(VIDC_DBG, "PM work already scheduled\n"); already_disabled: device->clk_state = DISABLED_PREPARED; } Loading Loading @@ -3084,6 +3081,16 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) } switch (rc) { case HFI_MSG_SYS_IDLE: /* Queue worker thread to enable power collapse */ if (device->res->sw_power_collapsible) { if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } dprintk(VIDC_DBG, "Received HFI_MSG_SYS_IDLE\n"); rc = venus_hfi_try_clk_gating(device); Loading Loading @@ -3204,7 +3211,7 @@ static inline int venus_hfi_init_clocks(struct msm_vidc_platform_resources *res, int i = 0; dprintk(VIDC_DBG, "%s: scalable? %d, gate-able? %d\n", cl->name, !!cl->count, cl->has_sw_power_collapse); !!cl->count, cl->has_gating); for (i = 0; i < cl->count; ++i) { dprintk(VIDC_DBG, "\tload = %d, freq = %d\n", cl->load_freq_tbl[i].load, Loading Loading @@ -3267,8 +3274,7 @@ static inline void venus_hfi_disable_unprepare_clks( } WARN_ON(!mutex_is_locked(&device->clk_pwr_lock)); venus_hfi_for_each_clock(device, cl) { if (device->clk_state == DISABLED_PREPARED && cl->has_sw_power_collapse) { if (device->clk_state == DISABLED_PREPARED) { dprintk(VIDC_DBG, "Omitting clk_disable of %s in %s as it's already disabled\n", cl->name, __func__); Loading