diff --git a/msm/vidc/hfi_common.c b/msm/vidc/hfi_common.c index 1e543970eed3..0a0d15796195 100644 --- a/msm/vidc/hfi_common.c +++ b/msm/vidc/hfi_common.c @@ -787,6 +787,51 @@ void __write_register(struct venus_hfi_device *device, wmb(); } +/* + * Argument mask is used to specify which bits to update. In case mask is 0x11, + * only bits 0 & 4 will be updated with corresponding bits from value. To update + * entire register with value, set mask = 0xFFFFFFFF. + */ +void __write_register_masked(struct venus_hfi_device *device, + u32 reg, u32 value, u32 mask, u32 sid) +{ + u32 prev_val, new_val; + u8 *base_addr; + + if (!device) { + s_vpr_e(sid, "%s: invalid params\n", __func__); + return; + } + + __strict_check(device); + + if (!device->power_enabled) { + s_vpr_e(sid, "%s: register write failed, power is off\n", + __func__); + msm_vidc_res_handle_fatal_hw_error(device->res, true); + return; + } + + base_addr = device->hal_data->register_base; + base_addr += reg; + + prev_val = readl_relaxed(base_addr); + /* + * Memory barrier to ensure register read is correct + */ + rmb(); + + new_val = (prev_val & ~mask) | (value & mask); + s_vpr_l(sid, + "Base addr: %pK, writing to: %#x, previous-value: %#x, value: %#x, mask: %#x, new-value: %#x...\n", + base_addr, reg, prev_val, value, mask, new_val); + writel_relaxed(new_val, base_addr); + /* + * Memory barrier to make sure value is written into the register. + */ + wmb(); +} + int __read_register(struct venus_hfi_device *device, u32 reg, u32 sid) { int rc = 0; @@ -831,8 +876,9 @@ static void __set_registers(struct venus_hfi_device *device, u32 sid) reg_set = &device->res->reg_set; for (i = 0; i < reg_set->count; i++) { - __write_register(device, reg_set->reg_tbl[i].reg, - reg_set->reg_tbl[i].value, sid); + __write_register_masked(device, reg_set->reg_tbl[i].reg, + reg_set->reg_tbl[i].value, + reg_set->reg_tbl[i].mask, sid); } } diff --git a/msm/vidc/hfi_common.h b/msm/vidc/hfi_common.h index 2583db939fe4..6043db6e7473 100644 --- a/msm/vidc/hfi_common.h +++ b/msm/vidc/hfi_common.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef __HFI_COMMON_H__ @@ -296,6 +296,8 @@ void __dump(struct dump dump[], int len, u32 sid); void __write_register(struct venus_hfi_device *device, u32 reg, u32 value, u32 sid); +void __write_register_masked(struct venus_hfi_device *device, + u32 reg, u32 value, u32 mask, u32 sid); int __read_register(struct venus_hfi_device *device, u32 reg, u32 sid); void __disable_unprepare_clks(struct venus_hfi_device *device); int __disable_regulators(struct venus_hfi_device *device); diff --git a/msm/vidc/msm_vidc_res_parse.c b/msm/vidc/msm_vidc_res_parse.c index 223343a00294..27fe80f5b9d3 100644 --- a/msm/vidc/msm_vidc_res_parse.c +++ b/msm/vidc/msm_vidc_res_parse.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #include @@ -151,15 +151,15 @@ static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res) } if (of_property_read_u32_array(pdev->dev.of_node, "qcom,reg-presets", - (u32 *)reg_set->reg_tbl, reg_set->count * 2)) { + (u32 *)reg_set->reg_tbl, reg_set->count * 3)) { d_vpr_e("Failed to read register table\n"); msm_vidc_free_reg_table(res); return -EINVAL; } for (i = 0; i < reg_set->count; i++) { - d_vpr_h("reg = %x, value = %x\n", - reg_set->reg_tbl[i].reg, reg_set->reg_tbl[i].value - ); + d_vpr_h("reg = %#x, value = %#x, mask = %#x\n", + reg_set->reg_tbl[i].reg, reg_set->reg_tbl[i].value, + reg_set->reg_tbl[i].mask); } return rc; } diff --git a/msm/vidc/msm_vidc_resources.h b/msm/vidc/msm_vidc_resources.h index a64575d189e7..aa2fb29f16ce 100644 --- a/msm/vidc/msm_vidc_resources.h +++ b/msm/vidc/msm_vidc_resources.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. */ #ifndef __MSM_VIDC_RESOURCES_H__ @@ -15,6 +15,7 @@ struct reg_value_pair { u32 reg; u32 value; + u32 mask; }; struct reg_set {