diff --git a/msm/Makefile b/msm/Makefile index f71400929de6..d16933a7f464 100644 --- a/msm/Makefile +++ b/msm/Makefile @@ -14,7 +14,10 @@ msm-vidc-objs := vidc/msm_v4l2_vidc.o \ vidc/msm_smem.o \ vidc/msm_vidc_debug.o \ vidc/msm_vidc_res_parse.o \ - vidc/venus_hfi.o \ + vidc/hfi_common.o \ + vidc/hfi_ar50.o \ + vidc/hfi_iris1.o \ + vidc/hfi_iris2.o \ vidc/hfi_response_handler.o \ vidc/hfi_packetization.o \ vidc/vidc_hfi.o \ diff --git a/msm/vidc/hfi_ar50.c b/msm/vidc/hfi_ar50.c new file mode 100644 index 000000000000..a5428dbfe246 --- /dev/null +++ b/msm/vidc/hfi_ar50.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include "hfi_common.h" +#include "hfi_io_common.h" + +void __interrupt_init_ar50(struct venus_hfi_device *device) +{ + __write_register(device, WRAPPER_INTR_MASK, + WRAPPER_INTR_MASK_A2HVCODEC_BMSK); +} diff --git a/msm/vidc/venus_hfi.c b/msm/vidc/hfi_common.c similarity index 90% rename from msm/vidc/venus_hfi.c rename to msm/vidc/hfi_common.c index 43b6a7f08f32..430d07c82330 100644 --- a/msm/vidc/venus_hfi.c +++ b/msm/vidc/hfi_common.c @@ -29,8 +29,8 @@ #include #include "hfi_packetization.h" #include "msm_vidc_debug.h" -#include "venus_hfi.h" -#include "vidc_hfi_io.h" +#include "hfi_common.h" +#include "hfi_io_common.h" #define FIRMWARE_SIZE 0X00A00000 #define REG_ADDR_OFFSET_BITMASK 0x000FFFFF @@ -77,10 +77,8 @@ static void venus_hfi_pm_handler(struct work_struct *work); static DECLARE_DELAYED_WORK(venus_hfi_pm_work, venus_hfi_pm_handler); static inline int __resume(struct venus_hfi_device *device); static inline int __suspend(struct venus_hfi_device *device); -static int __disable_regulators(struct venus_hfi_device *device); static int __enable_regulators(struct venus_hfi_device *device); static inline int __prepare_enable_clks(struct venus_hfi_device *device); -static inline void __disable_unprepare_clks(struct venus_hfi_device *device); static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet); static int __initialize_packetization(struct venus_hfi_device *device); static struct hal_session *__get_session(struct venus_hfi_device *device, @@ -99,43 +97,56 @@ static int __release_subcaches(struct venus_hfi_device *device); static int __disable_subcaches(struct venus_hfi_device *device); static int __power_collapse(struct venus_hfi_device *device, bool force); static int venus_hfi_noc_error_info(void *dev); - -static void interrupt_init_vpu4(struct venus_hfi_device *device); -static void interrupt_init_iris1(struct venus_hfi_device *device); -static void setup_dsp_uc_memmap_iris1(struct venus_hfi_device *device); -static void clock_config_on_enable_iris1(struct venus_hfi_device *device); -static int reset_ahb2axi_bridge(struct venus_hfi_device *device); static int __set_ubwc_config(struct venus_hfi_device *device); -static void power_off_common(struct venus_hfi_device *device); -static void power_off_iris2(struct venus_hfi_device *device); -static void noc_error_info_common(struct venus_hfi_device *device); -static void noc_error_info_iris2(struct venus_hfi_device *device); +static void __power_off_common(struct venus_hfi_device *device); +static int __prepare_pc_common(struct venus_hfi_device *device); +static void __raise_interrupt_common(struct venus_hfi_device *device); +static bool __watchdog_common(u32 intr_status); +static void __noc_error_info_common(struct venus_hfi_device *device); +static void __core_clear_interrupt_common(struct venus_hfi_device *device); +static inline int __boot_firmware_common(struct venus_hfi_device *device); +static void __setup_ucregion_memory_map_common(struct venus_hfi_device *device); struct venus_hfi_vpu_ops vpu4_ops = { - .interrupt_init = interrupt_init_vpu4, - .setup_dsp_uc_memmap = NULL, + .interrupt_init = __interrupt_init_ar50, + .setup_ucregion_memmap = __setup_ucregion_memory_map_common, .clock_config_on_enable = NULL, .reset_ahb2axi_bridge = NULL, - .power_off = power_off_common, - .noc_error_info = noc_error_info_common, + .power_off = __power_off_common, + .prepare_pc = __prepare_pc_common, + .raise_interrupt = __raise_interrupt_common, + .watchdog = __watchdog_common, + .noc_error_info = __noc_error_info_common, + .core_clear_interrupt = __core_clear_interrupt_common, + .boot_firmware = __boot_firmware_common, }; struct venus_hfi_vpu_ops iris1_ops = { - .interrupt_init = interrupt_init_iris1, - .setup_dsp_uc_memmap = setup_dsp_uc_memmap_iris1, - .clock_config_on_enable = clock_config_on_enable_iris1, - .reset_ahb2axi_bridge = reset_ahb2axi_bridge, - .power_off = power_off_common, - .noc_error_info = noc_error_info_common, + .interrupt_init = __interrupt_init_iris1, + .setup_ucregion_memmap = __setup_ucregion_memory_map_iris1, + .clock_config_on_enable = __clock_config_on_enable_iris1, + .reset_ahb2axi_bridge = __reset_ahb2axi_bridge_common, + .power_off = __power_off_common, + .prepare_pc = __prepare_pc_common, + .raise_interrupt = __raise_interrupt_common, + .watchdog = __watchdog_common, + .noc_error_info = __noc_error_info_common, + .core_clear_interrupt = __core_clear_interrupt_common, + .boot_firmware = __boot_firmware_common, }; struct venus_hfi_vpu_ops iris2_ops = { - .interrupt_init = interrupt_init_iris1, - .setup_dsp_uc_memmap = NULL, + .interrupt_init = __interrupt_init_iris2, + .setup_ucregion_memmap = __setup_ucregion_memory_map_iris2, .clock_config_on_enable = NULL, - .reset_ahb2axi_bridge = reset_ahb2axi_bridge, - .power_off = power_off_iris2, - .noc_error_info = noc_error_info_iris2, + .reset_ahb2axi_bridge = __reset_ahb2axi_bridge_common, + .power_off = __power_off_iris2, + .prepare_pc = __prepare_pc_iris2, + .raise_interrupt = __raise_interrupt_iris2, + .watchdog = __watchdog_iris2, + .noc_error_info = __noc_error_info_iris2, + .core_clear_interrupt = __core_clear_interrupt_iris2, + .boot_firmware = __boot_firmware_iris2, }; /** @@ -881,7 +892,7 @@ static void __smem_free(struct venus_hfi_device *dev, struct msm_smem *mem) msm_smem_free(mem); } -static void __write_register(struct venus_hfi_device *device, +void __write_register(struct venus_hfi_device *device, u32 reg, u32 value) { u32 hwiosymaddr = reg; @@ -913,7 +924,7 @@ static void __write_register(struct venus_hfi_device *device, wmb(); } -static int __read_register(struct venus_hfi_device *device, u32 reg) +int __read_register(struct venus_hfi_device *device, u32 reg) { int rc = 0; u8 *base_addr; @@ -964,37 +975,13 @@ static void __set_registers(struct venus_hfi_device *device) } } -/* - * The existence of this function is a hack for 8996 (or certain Venus versions) - * to overcome a hardware bug. Whenever the GDSCs momentarily power collapse - * (after calling __hand_off_regulators()), the values of the threshold - * registers (typically programmed by TZ) are incorrectly reset. As a result - * reprogram these registers at certain agreed upon points. - */ -static void __set_threshold_registers(struct venus_hfi_device *device) -{ - u32 version = __read_register(device, VIDC_WRAPPER_HW_VERSION); - - version &= ~GENMASK(15, 0); - if (version != (0x3 << 28 | 0x43 << 16)) - return; - - if (__tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESTORE_THRESHOLD)) - dprintk(VIDC_ERR, "Failed to restore threshold values\n"); -} - -static int __vote_bandwidth(struct bus_info *bus, - unsigned long *freq) +static int __vote_bandwidth(struct bus_info *bus, unsigned long freq) { int rc = 0; uint64_t ab = 0; - if (*freq) - *freq = clamp_t(typeof(*freq), *freq, bus->range[0], - bus->range[1]); - /* Bus Driver expects values in Bps */ - ab = *freq * 1000; + ab = freq * 1000; dprintk(VIDC_PROF, "Voting bus %s to ab %llu\n", bus->name, ab); rc = msm_bus_scale_update_bw(bus->client, ab, 0); if (rc) @@ -1004,24 +991,17 @@ static int __vote_bandwidth(struct bus_info *bus, return rc; } -static int __unvote_buses(struct venus_hfi_device *device) +int __unvote_buses(struct venus_hfi_device *device) { int rc = 0; struct bus_info *bus = NULL; - unsigned long freq = 0, zero = 0; kfree(device->bus_vote.data); device->bus_vote.data = NULL; device->bus_vote.data_count = 0; venus_hfi_for_each_bus(device, bus) { - if (!bus->is_prfm_mode) { - freq = device->bus_vote.calc_bw(bus, &device->bus_vote); - rc = __vote_bandwidth(bus, &freq); - } - else - rc = __vote_bandwidth(bus, &zero); - + rc = __vote_bandwidth(bus, 0); if (rc) goto err_unknown_device; } @@ -1066,7 +1046,11 @@ no_data_count: else freq = bus->range[1]; - rc = __vote_bandwidth(bus, &freq); + /* ensure freq is within limits */ + freq = clamp_t(typeof(freq), freq, + bus->range[0], bus->range[1]); + + rc = __vote_bandwidth(bus, freq); } else { dprintk(VIDC_ERR, "No BUS to Vote\n"); } @@ -1181,7 +1165,7 @@ static int __tzbsp_set_video_state(enum tzbsp_video_state state) return 0; } -static inline int __boot_firmware(struct venus_hfi_device *device) +static inline int __boot_firmware_common(struct venus_hfi_device *device) { int rc = 0; u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 10000; @@ -1190,10 +1174,10 @@ static inline int __boot_firmware(struct venus_hfi_device *device) if (device->res->domain_cvp) ctrl_init_val |= BIT(1); - __write_register(device, VIDC_CTRL_INIT, ctrl_init_val); + __write_register(device, CTRL_INIT, ctrl_init_val); while (!ctrl_status && count < max_tries) { - ctrl_status = __read_register(device, VIDC_CTRL_STATUS); - if ((ctrl_status & VIDC_CTRL_ERROR_STATUS__M) == 0x4) { + ctrl_status = __read_register(device, CTRL_STATUS); + if ((ctrl_status & CTRL_ERROR_STATUS__M) == 0x4) { dprintk(VIDC_ERR, "invalid setting for UC_REGION\n"); break; } @@ -1207,10 +1191,6 @@ static inline int __boot_firmware(struct venus_hfi_device *device) rc = -ETIME; } - /* Enable interrupt before sending commands to venus */ - __write_register(device, VIDC_CPU_CS_H2XSOFTINTEN, 0x1); - __write_register(device, VIDC_CPU_CS_X2RPMh, 0x0); - return rc; } @@ -1413,17 +1393,19 @@ err_q_null: return result; } +static void __raise_interrupt_common(struct venus_hfi_device *device) +{ + __write_register(device, CPU_IC_SOFTINT, + 1 << CPU_IC_SOFTINT_H2A_SHFT); +} + static int __iface_cmdq_write(struct venus_hfi_device *device, void *pkt) { bool needs_interrupt = false; int rc = __iface_cmdq_write_relaxed(device, pkt, &needs_interrupt); - if (!rc && needs_interrupt) { - /* Consumer of cmdq prefers that we raise an interrupt */ - rc = 0; - __write_register(device, VIDC_CPU_IC_SOFTINT, - 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); - } + if (!rc && needs_interrupt) + call_venus_op(device, raise_interrupt, device); return rc; } @@ -1457,8 +1439,7 @@ static int __iface_msgq_read(struct venus_hfi_device *device, void *pkt) if (!__read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) { __hal_sim_modify_msg_packet((u8 *)pkt, device); if (tx_req_is_set) - __write_register(device, VIDC_CPU_IC_SOFTINT, - 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); + call_venus_op(device, raise_interrupt, device); rc = 0; } else rc = -ENODATA; @@ -1489,8 +1470,7 @@ static int __iface_dbgq_read(struct venus_hfi_device *device, void *pkt) if (!__read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) { if (tx_req_is_set) - __write_register(device, VIDC_CPU_IC_SOFTINT, - 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); + call_venus_op(device, raise_interrupt, device); rc = 0; } else rc = -ENODATA; @@ -1764,21 +1744,20 @@ static int __get_qdss_iommu_virtual_addr(struct venus_hfi_device *dev, return rc; } -static void __setup_ucregion_memory_map(struct venus_hfi_device *device) +static void __setup_ucregion_memory_map_common(struct venus_hfi_device *device) { - __write_register(device, VIDC_UC_REGION_ADDR, + __write_register(device, UC_REGION_ADDR, (u32)device->iface_q_table.align_device_addr); - __write_register(device, VIDC_UC_REGION_SIZE, SHARED_QSIZE); - __write_register(device, VIDC_QTBL_ADDR, + __write_register(device, UC_REGION_SIZE, SHARED_QSIZE); + __write_register(device, QTBL_ADDR, (u32)device->iface_q_table.align_device_addr); - __write_register(device, VIDC_QTBL_INFO, 0x01); + __write_register(device, QTBL_INFO, 0x01); if (device->sfr.align_device_addr) - __write_register(device, VIDC_SFR_ADDR, + __write_register(device, SFR_ADDR, (u32)device->sfr.align_device_addr); if (device->qdss.align_device_addr) - __write_register(device, VIDC_MMAP_ADDR, + __write_register(device, MMAP_ADDR, (u32)device->qdss.align_device_addr); - call_venus_op(device, setup_dsp_uc_memmap, device); } static int __interface_queues_init(struct venus_hfi_device *dev) @@ -1930,7 +1909,7 @@ static int __interface_queues_init(struct venus_hfi_device *dev) } } - __setup_ucregion_memory_map(dev); + call_venus_op(dev, setup_ucregion_memmap, dev); return 0; fail_alloc_queue: return -ENOMEM; @@ -2052,7 +2031,7 @@ static int venus_hfi_core_init(void *device) goto err_core_init; } - rc = __boot_firmware(dev); + rc = call_venus_op(dev, boot_firmware, dev); if (rc) { dprintk(VIDC_ERR, "Failed to start core\n"); rc = -ENODEV; @@ -2164,7 +2143,7 @@ static int __get_q_size(struct venus_hfi_device *dev, unsigned int q_index) return read_ptr - write_ptr; } -static void __core_clear_interrupt(struct venus_hfi_device *device) +static void __core_clear_interrupt_common(struct venus_hfi_device *device) { u32 intr_status = 0, mask = 0; @@ -2173,10 +2152,10 @@ static void __core_clear_interrupt(struct venus_hfi_device *device) return; } - intr_status = __read_register(device, VIDC_WRAPPER_INTR_STATUS); - mask = (VIDC_WRAPPER_INTR_STATUS_A2H_BMSK | - VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK | - VIDC_CTRL_INIT_IDLE_MSG_BMSK); + intr_status = __read_register(device, WRAPPER_INTR_STATUS); + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | + WRAPPER_INTR_STATUS_A2HWD_BMSK | + CTRL_INIT_IDLE_MSG_BMSK); if (intr_status & mask) { device->intr_status |= intr_status; @@ -2188,7 +2167,8 @@ static void __core_clear_interrupt(struct venus_hfi_device *device) device->spur_count++; } - __write_register(device, VIDC_CPU_CS_A2HSOFTINTCLR, 1); + __write_register(device, CPU_CS_A2HSOFTINTCLR, 1); + __write_register(device, WRAPPER_INTR_CLEAR, intr_status); } static int venus_hfi_core_trigger_ssr(void *device, @@ -2984,7 +2964,7 @@ static int __check_core_registered(struct hal_device_data core, device = list_entry(curr, struct venus_hfi_device, list); hal_data = device->hal_data; - if (device && hal_data->irq == irq && + if (hal_data && hal_data->irq == irq && (CONTAINS(hal_data->firmware_base, FIRMWARE_SIZE, fw_addr) || CONTAINS(fw_addr, FIRMWARE_SIZE, @@ -3022,7 +3002,7 @@ static void __process_fatal_error( device->callback(HAL_SYS_ERROR, &cmd_done); } -static int __prepare_pc(struct venus_hfi_device *device) +int __prepare_pc(struct venus_hfi_device *device) { int rc = 0; struct hfi_cmd_sys_pc_prep_packet pkt; @@ -3098,15 +3078,64 @@ static void venus_hfi_pm_handler(struct work_struct *work) } } -static int __power_collapse(struct venus_hfi_device *device, bool force) +static int __prepare_pc_common(struct venus_hfi_device *device) { int rc = 0; u32 wfi_status = 0, idle_status = 0, pc_ready = 0; u32 ctrl_status = 0; - u32 flags = 0; int count = 0; const int max_tries = 10; + ctrl_status = __read_register(device, CTRL_STATUS); + pc_ready = ctrl_status & CTRL_STATUS_PC_READY; + idle_status = ctrl_status & BIT(30); + + if (pc_ready) { + dprintk(VIDC_DBG, "Already in pc_ready state\n"); + return 0; + } + + wfi_status = BIT(0) & __read_register(device, + WRAPPER_CPU_STATUS); + if (!wfi_status || !idle_status) { + dprintk(VIDC_WARN, "Skipping PC, wfi status not set\n"); + goto skip_power_off; + } + + rc = __prepare_pc(device); + if (rc) { + dprintk(VIDC_WARN, "Failed __prepare_pc %d\n", rc); + goto skip_power_off; + } + + while (count < max_tries) { + wfi_status = BIT(0) & __read_register(device, + WRAPPER_CPU_STATUS); + ctrl_status = __read_register(device, CTRL_STATUS); + if (wfi_status && (ctrl_status & CTRL_STATUS_PC_READY)) + break; + usleep_range(150, 250); + count++; + } + + if (count == max_tries) { + dprintk(VIDC_ERR, "Skip PC. Core is not in right state\n"); + goto skip_power_off; + } + + return rc; + +skip_power_off: + dprintk(VIDC_WARN, "Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n", + wfi_status, idle_status, pc_ready, ctrl_status); + return -EAGAIN; +} + +static int __power_collapse(struct venus_hfi_device *device, bool force) +{ + int rc = 0; + u32 flags = 0; + if (!device) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); return -EINVAL; @@ -3128,45 +3157,9 @@ static int __power_collapse(struct venus_hfi_device *device, bool force) else if (rc) goto skip_power_off; - ctrl_status = __read_register(device, VIDC_CTRL_STATUS); - pc_ready = ctrl_status & VIDC_CTRL_STATUS_PC_READY; - idle_status = ctrl_status & BIT(30); - - if (!pc_ready) { - wfi_status = BIT(0) & - __read_register(device, - VIDC_WRAPPER_TZ_CPU_STATUS); - if (!wfi_status || !idle_status) { - dprintk(VIDC_WARN, - "Skipping PC, wfi or idle status not set.\n"); - goto skip_power_off; - } - - rc = __prepare_pc(device); - if (rc) { - dprintk(VIDC_WARN, "Failed __prepare_pc %d\n", rc); - goto skip_power_off; - } - - while (count < max_tries) { - wfi_status = BIT(0) & - __read_register(device, - VIDC_WRAPPER_TZ_CPU_STATUS); - ctrl_status = __read_register(device, - VIDC_CTRL_STATUS); - if (wfi_status && - (ctrl_status & VIDC_CTRL_STATUS_PC_READY)) - break; - usleep_range(150, 250); - count++; - } - - if (count == max_tries) { - dprintk(VIDC_ERR, - "Skip PC. Core is not in right state.\n"); - goto skip_power_off; - } - } + rc = call_venus_op(device, prepare_pc, device); + if (rc) + goto skip_power_off; __flush_debug_queue(device, device->raw_packet); @@ -3178,9 +3171,6 @@ exit: return rc; skip_power_off: - dprintk(VIDC_WARN, "Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n", - wfi_status, idle_status, pc_ready, ctrl_status); - return -EAGAIN; } @@ -3294,6 +3284,16 @@ static struct hal_session *__get_session(struct venus_hfi_device *device, return NULL; } +static bool __watchdog_common(u32 intr_status) +{ + bool rc = false; + + if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) + rc = true; + + return rc; +} + static int __response_handler(struct venus_hfi_device *device) { struct msm_vidc_cb_info *packets; @@ -3310,12 +3310,12 @@ static int __response_handler(struct venus_hfi_device *device) if (!raw_packet || !packets) { dprintk(VIDC_ERR, - "%s: Invalid args : Res packet = %p, Raw packet = %p\n", + "%s: Invalid args : Res packet = %pK, Raw packet = %pK\n", __func__, packets, raw_packet); return 0; } - if (device->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK) { + if (call_venus_op(device, watchdog, device->intr_status)) { struct hfi_sfr_struct *vsfr = (struct hfi_sfr_struct *) device->sfr.align_virtual_addr; struct msm_vidc_cb_info info = { @@ -3361,14 +3361,6 @@ static int __response_handler(struct venus_hfi_device *device) dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n"); break; case HAL_SESSION_LOAD_RESOURCE_DONE: - /* - * Work around for H/W bug, need to re-program these - * registers as part of a handshake agreement with the - * firmware. This strictly only needs to be done for - * decoder secure sessions, but there's no harm in doing - * so for all sessions as it's at worst a NO-OP. - */ - __set_threshold_registers(device); break; default: break; @@ -3491,7 +3483,7 @@ static void venus_hfi_core_work_handler(struct work_struct *work) goto err_no_work; } - __core_clear_interrupt(device); + call_venus_op(device, core_clear_interrupt, device); num_responses = __response_handler(device); err_no_work: @@ -3521,7 +3513,7 @@ err_no_work: } /* We need re-enable the irq which was disabled in ISR handler */ - if (!(intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) + if (!call_venus_op(device, watchdog, intr_status)) enable_irq(device->hal_data->irq); /* @@ -3703,7 +3695,7 @@ failed_to_reset: return rc; } -static inline void __disable_unprepare_clks(struct venus_hfi_device *device) +void __disable_unprepare_clks(struct venus_hfi_device *device) { struct clock_info *cl; int rc = 0; @@ -3732,7 +3724,7 @@ static inline void __disable_unprepare_clks(struct venus_hfi_device *device) } } -static int reset_ahb2axi_bridge(struct venus_hfi_device *device) +int __reset_ahb2axi_bridge_common(struct venus_hfi_device *device) { int rc, i; @@ -4179,7 +4171,7 @@ err_reg_enable_failed: return rc; } -static int __disable_regulators(struct venus_hfi_device *device) +int __disable_regulators(struct venus_hfi_device *device) { struct regulator_info *rinfo; @@ -4355,50 +4347,6 @@ static int __disable_subcaches(struct venus_hfi_device *device) return 0; } -static void interrupt_init_iris1(struct venus_hfi_device *device) -{ - u32 mask_val = 0; - - /* All interrupts should be disabled initially 0x1F6 : Reset value */ - mask_val = __read_register(device, VIDC_WRAPPER_INTR_MASK); - - /* Write 0 to unmask CPU and WD interrupts */ - mask_val &= ~(VIDC_WRAPPER_INTR_MASK_A2HWD_BMSK | - VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK); - __write_register(device, VIDC_WRAPPER_INTR_MASK, mask_val); -} - -static void interrupt_init_vpu4(struct venus_hfi_device *device) -{ - __write_register(device, VIDC_WRAPPER_INTR_MASK, - VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK); -} - -static void setup_dsp_uc_memmap_iris1(struct venus_hfi_device *device) -{ - /* initialize DSP QTBL & UCREGION with CPU queues */ - __write_register(device, HFI_DSP_QTBL_ADDR, - (u32)device->iface_q_table.align_device_addr); - __write_register(device, HFI_DSP_UC_REGION_ADDR, - (u32)device->iface_q_table.align_device_addr); - __write_register(device, HFI_DSP_UC_REGION_SIZE, SHARED_QSIZE); - if (device->res->domain_cvp) { - __write_register(device, HFI_DSP_QTBL_ADDR, - (u32)device->dsp_iface_q_table.align_device_addr); - __write_register(device, HFI_DSP_UC_REGION_ADDR, - (u32)device->dsp_iface_q_table.align_device_addr); - __write_register(device, HFI_DSP_UC_REGION_SIZE, - device->dsp_iface_q_table.mem_data.size); - } -} - -static void clock_config_on_enable_iris1(struct venus_hfi_device *device) -{ - __write_register(device, VIDC_WRAPPER_CPU_CGC_DIS, 0); - __write_register(device, VIDC_WRAPPER_CPU_CLOCK_CONFIG, 0); -} - - static int __set_ubwc_config(struct venus_hfi_device *device) { u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE]; @@ -4503,12 +4451,12 @@ fail_vote_buses: return rc; } -static void power_off_common(struct venus_hfi_device *device) +static void __power_off_common(struct venus_hfi_device *device) { if (!device->power_enabled) return; - if (!(device->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) + if (!(device->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK)) disable_irq_nosync(device->hal_data->irq); device->intr_status = 0; @@ -4524,93 +4472,6 @@ static void power_off_common(struct venus_hfi_device *device) device->power_enabled = false; } -static void power_off_iris2(struct venus_hfi_device *device) -{ - u32 lpi_status, reg_status = 0, count = 0, max_count = 10; - - if (!device->power_enabled) - return; - - if (!(device->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) - disable_irq_nosync(device->hal_data->irq); - device->intr_status = 0; - - /* HPG 6.1.2 Step 1 */ - __write_register(device, VIDC_CPU_CS_X2RPMh, 0x3); - - /* HPG 6.1.2 Step 2, noc to low power */ - __write_register(device, VIDC_AON_WRAPPER_MVP_NOC_LPI_CONTROL, 0x1); - while (!reg_status && count < max_count) { - lpi_status = - __read_register(device, - VIDC_AON_WRAPPER_MVP_NOC_LPI_STATUS); - reg_status = lpi_status & BIT(0); - dprintk(VIDC_DBG, - "Noc: lpi_status %d noc_status %d (count %d)\n", - lpi_status, reg_status, count); - usleep_range(50, 100); - count++; - } - if (count == max_count) { - dprintk(VIDC_ERR, - "NOC not in qaccept status %d\n", reg_status); - } - - /* HPG 6.1.2 Step 3, debug bridge to low power */ - __write_register(device, - VIDC_WRAPPER_DEBUG_BRIDGE_LPI_CONTROL, 0x7); - reg_status = 0; - count = 0; - while ((reg_status != 0x7) && count < max_count) { - lpi_status = __read_register(device, - VIDC_WRAPPER_DEBUG_BRIDGE_LPI_STATUS); - reg_status = lpi_status & 0x7; - dprintk(VIDC_DBG, - "DBLP Set : lpi_status %d reg_status %d (count %d)\n", - lpi_status, reg_status, count); - usleep_range(50, 100); - count++; - } - if (count == max_count) { - dprintk(VIDC_ERR, - "DBLP Set: status %d\n", reg_status); - } - - /* HPG 6.1.2 Step 4, debug bridge to lpi release */ - __write_register(device, - VIDC_WRAPPER_DEBUG_BRIDGE_LPI_CONTROL, 0x0); - lpi_status = 0x1; - count = 0; - while (lpi_status && count < max_count) { - lpi_status = __read_register(device, - VIDC_WRAPPER_DEBUG_BRIDGE_LPI_STATUS); - dprintk(VIDC_DBG, - "DBLP Release: lpi_status %d(count %d)\n", - lpi_status, count); - usleep_range(50, 100); - count++; - } - if (count == max_count) { - dprintk(VIDC_ERR, - "DBLP Release: lpi_status %d\n", lpi_status); - } - - /* HPG 6.1.2 Step 6 */ - __disable_unprepare_clks(device); - - /* HPG 6.1.2 Step 7 & 8 */ - if (call_venus_op(device, reset_ahb2axi_bridge, device)) - dprintk(VIDC_ERR, "Failed to reset ahb2axi\n"); - - /* HPG 6.1.2 Step 5 */ - if (__disable_regulators(device)) - dprintk(VIDC_WARN, "Failed to disable regulators\n"); - - if (__unvote_buses(device)) - dprintk(VIDC_WARN, "Failed to unvote for buses\n"); - device->power_enabled = false; -} - static inline int __suspend(struct venus_hfi_device *device) { int rc = 0; @@ -4674,20 +4535,15 @@ static inline int __resume(struct venus_hfi_device *device) goto err_set_video_state; } - __setup_ucregion_memory_map(device); + call_venus_op(device, setup_ucregion_memmap, device); + /* Wait for boot completion */ - rc = __boot_firmware(device); + rc = call_venus_op(device, boot_firmware, device); if (rc) { dprintk(VIDC_ERR, "Failed to reset venus core\n"); goto err_reset_core; } - /* - * Work around for H/W bug, need to reprogram these registers once - * firmware is out reset - */ - __set_threshold_registers(device); - if (device->res->pm_qos_latency_us) { #ifdef CONFIG_SMP device->qos.type = PM_QOS_REQ_AFFINE_IRQ; @@ -4926,7 +4782,7 @@ static void __noc_error_info(struct venus_hfi_device *device, u32 core_num) dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG3_HIGH: %#x\n", core_num, val); } -static void noc_error_info_common(struct venus_hfi_device *device) +static void __noc_error_info_common(struct venus_hfi_device *device) { const u32 core0 = 0, core1 = 1; @@ -4939,38 +4795,6 @@ static void noc_error_info_common(struct venus_hfi_device *device) __noc_error_info(device, core1); } -static void noc_error_info_iris2(struct venus_hfi_device *device) -{ - u32 val = 0; - - val = __read_register(device, VCODEC_NOC_ERL_MAIN_SWID_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_SWID_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_SWID_HIGH); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_SWID_HIGH: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_MAINCTL_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_MAINCTL_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRVLD_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRVLD_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRCLR_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRCLR_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW: %#x\n", val); - val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH); - dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH: %#x\n", val); -} - static int venus_hfi_noc_error_info(void *dev) { struct venus_hfi_device *device; diff --git a/msm/vidc/venus_hfi.h b/msm/vidc/hfi_common.h similarity index 81% rename from msm/vidc/venus_hfi.h rename to msm/vidc/hfi_common.h index 2bc1890c8a34..c519f2f41f96 100644 --- a/msm/vidc/venus_hfi.h +++ b/msm/vidc/hfi_common.h @@ -3,8 +3,8 @@ * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ -#ifndef __H_VENUS_HFI_H__ -#define __H_VENUS_HFI_H__ +#ifndef __HFI_COMMON_H__ +#define __HFI_COMMON_H__ #include #include @@ -234,12 +234,17 @@ enum reset_state { struct venus_hfi_device; struct venus_hfi_vpu_ops { - void (*interrupt_init)(struct venus_hfi_device *ptr); - void (*setup_dsp_uc_memmap)(struct venus_hfi_device *device); + void (*interrupt_init)(struct venus_hfi_device *device); + void (*setup_ucregion_memmap)(struct venus_hfi_device *device); void (*clock_config_on_enable)(struct venus_hfi_device *device); int (*reset_ahb2axi_bridge)(struct venus_hfi_device *device); void (*power_off)(struct venus_hfi_device *device); + int (*prepare_pc)(struct venus_hfi_device *device); + void (*raise_interrupt)(struct venus_hfi_device *device); + bool (*watchdog)(u32 intr_status); void (*noc_error_info)(struct venus_hfi_device *device); + void (*core_clear_interrupt)(struct venus_hfi_device *device); + int (*boot_firmware)(struct venus_hfi_device *device); }; struct venus_hfi_device { @@ -286,4 +291,30 @@ int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id, struct msm_vidc_platform_resources *res, hfi_cmd_response_callback callback); +void __write_register(struct venus_hfi_device *device, u32 reg, u32 value); +int __read_register(struct venus_hfi_device *device, u32 reg); +void __disable_unprepare_clks(struct venus_hfi_device *device); +int __disable_regulators(struct venus_hfi_device *device); +int __unvote_buses(struct venus_hfi_device *device); +int __reset_ahb2axi_bridge_common(struct venus_hfi_device *device); +int __prepare_pc(struct venus_hfi_device *device); + +/* AR50 specific */ +void __interrupt_init_ar50(struct venus_hfi_device *device); +/* IRIS1 specific */ +void __interrupt_init_iris1(struct venus_hfi_device *device); +void __setup_dsp_uc_memmap_iris1(struct venus_hfi_device *device); +void __clock_config_on_enable_iris1(struct venus_hfi_device *device); +void __setup_ucregion_memory_map_iris1(struct venus_hfi_device *device); +/* IRIS2 specific */ +void __interrupt_init_iris2(struct venus_hfi_device *device); +void __setup_ucregion_memory_map_iris2(struct venus_hfi_device *device); +void __power_off_iris2(struct venus_hfi_device *device); +int __prepare_pc_iris2(struct venus_hfi_device *device); +void __raise_interrupt_iris2(struct venus_hfi_device *device); +bool __watchdog_iris2(u32 intr_status); +void __noc_error_info_iris2(struct venus_hfi_device *device); +void __core_clear_interrupt_iris2(struct venus_hfi_device *device); +int __boot_firmware_iris2(struct venus_hfi_device *device); + #endif diff --git a/msm/vidc/hfi_io_common.h b/msm/vidc/hfi_io_common.h new file mode 100644 index 000000000000..2d42fdaa381e --- /dev/null +++ b/msm/vidc/hfi_io_common.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __HFI_IO_COMMON_H__ +#define __HFI_IO_COMMON_H__ + +#include + +#define VBIF_BASE_OFFS 0x00080000 + +#define CPU_BASE_OFFS 0x000C0000 +#define CPU_CS_BASE_OFFS (CPU_BASE_OFFS + 0x00012000) +#define CPU_IC_BASE_OFFS (CPU_BASE_OFFS + 0x0001F000) + +#define CPU_CS_A2HSOFTINT (CPU_CS_BASE_OFFS + 0x18) +#define CPU_CS_A2HSOFTINTCLR (CPU_CS_BASE_OFFS + 0x1C) +#define CPU_CS_VMIMSG (CPU_CS_BASE_OFFS + 0x34) +#define CPU_CS_VMIMSGAG0 (CPU_CS_BASE_OFFS + 0x38) +#define CPU_CS_VMIMSGAG1 (CPU_CS_BASE_OFFS + 0x3C) +#define CPU_CS_SCIACMD (CPU_CS_BASE_OFFS + 0x48) + +/* HFI_CTRL_STATUS */ +#define CPU_CS_SCIACMDARG0 (CPU_CS_BASE_OFFS + 0x4C) +#define CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK 0xfe +#define CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY 0x100 +#define CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK 0x40000000 + +/* HFI_QTBL_INFO */ +#define CPU_CS_SCIACMDARG1 (CPU_CS_BASE_OFFS + 0x50) + +/* HFI_QTBL_ADDR */ +#define CPU_CS_SCIACMDARG2 (CPU_CS_BASE_OFFS + 0x54) + +/* HFI_VERSION_INFO */ +#define CPU_CS_SCIACMDARG3 (CPU_CS_BASE_OFFS + 0x58) + +/* SFR_ADDR */ +#define CPU_CS_SCIBCMD (CPU_CS_BASE_OFFS + 0x5C) + +/* MMAP_ADDR */ +#define CPU_CS_SCIBCMDARG0 (CPU_CS_BASE_OFFS + 0x60) + +/* UC_REGION_ADDR */ +#define CPU_CS_SCIBARG1 (CPU_CS_BASE_OFFS + 0x64) + +/* UC_REGION_ADDR */ +#define CPU_CS_SCIBARG2 (CPU_CS_BASE_OFFS + 0x68) + +#define CPU_IC_SOFTINT (CPU_IC_BASE_OFFS + 0x18) +#define CPU_IC_SOFTINT_H2A_SHFT 0xF + +/* + * -------------------------------------------------------------------------- + * MODULE: wrapper + * -------------------------------------------------------------------------- + */ +#define WRAPPER_BASE_OFFS 0x000E0000 +#define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C) +#define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10 +#define WRAPPER_INTR_STATUS_A2H_BMSK 0x4 + +#define WRAPPER_INTR_MASK (WRAPPER_BASE_OFFS + 0x10) +#define WRAPPER_INTR_MASK_A2HWD_BMSK 0x10 +#define WRAPPER_INTR_MASK_A2HVCODEC_BMSK 0x8 +#define WRAPPER_INTR_MASK_A2HCPU_BMSK 0x4 +#define WRAPPER_INTR_CLEAR (WRAPPER_BASE_OFFS + 0x14) + +#define WRAPPER_CPU_CLOCK_CONFIG (WRAPPER_BASE_OFFS + 0x2000) +#define WRAPPER_CPU_CGC_DIS (WRAPPER_BASE_OFFS + 0x2010) +#define WRAPPER_CPU_STATUS (WRAPPER_BASE_OFFS + 0x2014) + +#define CTRL_INIT CPU_CS_SCIACMD + +#define CTRL_STATUS CPU_CS_SCIACMDARG0 +#define CTRL_ERROR_STATUS__M \ + CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK +#define CTRL_INIT_IDLE_MSG_BMSK \ + CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK +#define CTRL_STATUS_PC_READY \ + CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY + + +#define QTBL_INFO CPU_CS_SCIACMDARG1 + +#define QTBL_ADDR CPU_CS_SCIACMDARG2 + +#define VERSION_INFO CPU_CS_SCIACMDARG3 + +#define SFR_ADDR CPU_CS_SCIBCMD +#define MMAP_ADDR CPU_CS_SCIBCMDARG0 +#define UC_REGION_ADDR CPU_CS_SCIBARG1 +#define UC_REGION_SIZE CPU_CS_SCIBARG2 + +/* HFI_DSP_QTBL_ADDR + * 31:3 - HFI_DSP_QTBL_ADDR + * 4-byte aligned Address + */ +#define HFI_DSP_QTBL_ADDR CPU_CS_VMIMSG + +/* HFI_DSP_UC_REGION_ADDR + * 31:20 - HFI_DSP_UC_REGION_ADDR + * 1MB aligned address. + * Uncached Region start Address. This region covers + * HFI DSP QTable, + * HFI DSP Queue Headers, + * HFI DSP Queues, + */ +#define HFI_DSP_UC_REGION_ADDR CPU_CS_VMIMSGAG0 + +/* HFI_DSP_UC_REGION_SIZE + * 31:20 - HFI_DSP_UC_REGION_SIZE + * Multiples of 1MB. + * Size of the DSP_UC_REGION Uncached Region + */ +#define HFI_DSP_UC_REGION_SIZE CPU_CS_VMIMSGAG1 + +/* + * -------------------------------------------------------------------------- + * MODULE: vcodec noc error log registers + * -------------------------------------------------------------------------- + */ +#define VCODEC_CORE0_VIDEO_NOC_BASE_OFFS 0x00004000 +#define VCODEC_CORE1_VIDEO_NOC_BASE_OFFS 0x0000C000 +#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_LOW_OFFS 0x0500 +#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_HIGH_OFFS 0x0504 +#define VCODEC_COREX_VIDEO_NOC_ERR_MAINCTL_LOW_OFFS 0x0508 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRVLD_LOW_OFFS 0x0510 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRCLR_LOW_OFFS 0x0518 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_LOW_OFFS 0x0520 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_HIGH_OFFS 0x0524 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_LOW_OFFS 0x0528 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_HIGH_OFFS 0x052C +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_LOW_OFFS 0x0530 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_HIGH_OFFS 0x0534 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_LOW_OFFS 0x0538 +#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_HIGH_OFFS 0x053C +#endif diff --git a/msm/vidc/hfi_iris1.c b/msm/vidc/hfi_iris1.c new file mode 100644 index 000000000000..faf1e075691b --- /dev/null +++ b/msm/vidc/hfi_iris1.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include "hfi_common.h" +#include "hfi_io_common.h" + +void __interrupt_init_iris1(struct venus_hfi_device *device) +{ + u32 mask_val = 0; + + /* All interrupts should be disabled initially 0x1F6 : Reset value */ + mask_val = __read_register(device, WRAPPER_INTR_MASK); + + /* Write 0 to unmask CPU and WD interrupts */ + mask_val &= ~(WRAPPER_INTR_MASK_A2HWD_BMSK | + WRAPPER_INTR_MASK_A2HCPU_BMSK); + __write_register(device, WRAPPER_INTR_MASK, mask_val); +} + +void __setup_ucregion_memory_map_iris1(struct venus_hfi_device *device) +{ + /* initialize CPU QTBL & UCREGION */ + __write_register(device, UC_REGION_ADDR, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, UC_REGION_SIZE, SHARED_QSIZE); + __write_register(device, QTBL_ADDR, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, QTBL_INFO, 0x01); + if (device->sfr.align_device_addr) + __write_register(device, SFR_ADDR, + (u32)device->sfr.align_device_addr); + if (device->qdss.align_device_addr) + __write_register(device, MMAP_ADDR, + (u32)device->qdss.align_device_addr); + + /* initialize DSP QTBL & UCREGION with CPU queues by default */ + __write_register(device, HFI_DSP_QTBL_ADDR, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, HFI_DSP_UC_REGION_ADDR, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, HFI_DSP_UC_REGION_SIZE, SHARED_QSIZE); + if (device->res->domain_cvp) { + /* initialize DSP QTBL & UCREGION with DSP queues */ + __write_register(device, HFI_DSP_QTBL_ADDR, + (u32)device->dsp_iface_q_table.align_device_addr); + __write_register(device, HFI_DSP_UC_REGION_ADDR, + (u32)device->dsp_iface_q_table.align_device_addr); + __write_register(device, HFI_DSP_UC_REGION_SIZE, + device->dsp_iface_q_table.mem_data.size); + } +} + +void __clock_config_on_enable_iris1(struct venus_hfi_device *device) +{ + __write_register(device, WRAPPER_CPU_CGC_DIS, 0); + __write_register(device, WRAPPER_CPU_CLOCK_CONFIG, 0); +} + diff --git a/msm/vidc/hfi_iris2.c b/msm/vidc/hfi_iris2.c new file mode 100644 index 000000000000..4fd4dc415289 --- /dev/null +++ b/msm/vidc/hfi_iris2.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include "msm_vidc_debug.h" +#include "hfi_common.h" + +#define VBIF_BASE_OFFS_IRIS2 0x00080000 + +#define CPU_BASE_OFFS_IRIS2 0x000A0000 +#define AON_BASE_OFFS 0x000E0000 +#define CPU_CS_BASE_OFFS_IRIS2 (CPU_BASE_OFFS_IRIS2) +#define CPU_IC_BASE_OFFS_IRIS2 (CPU_BASE_OFFS_IRIS2) + +#define CPU_CS_A2HSOFTINTCLR_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x1C) +#define CPU_CS_VMIMSG_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x34) +#define CPU_CS_VMIMSGAG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x38) +#define CPU_CS_VMIMSGAG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x3C) +#define CPU_CS_SCIACMD_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x48) +#define CPU_CS_H2XSOFTINTEN_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x148) + +/* HFI_CTRL_STATUS */ +#define CPU_CS_SCIACMDARG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x4C) +#define CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_IRIS2 0xfe +#define CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_IRIS2 0x100 +#define CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_IRIS2 0x40000000 + +/* HFI_QTBL_INFO */ +#define CPU_CS_SCIACMDARG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x50) + +/* HFI_QTBL_ADDR */ +#define CPU_CS_SCIACMDARG2_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x54) + +/* HFI_VERSION_INFO */ +#define CPU_CS_SCIACMDARG3_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x58) + +/* SFR_ADDR */ +#define CPU_CS_SCIBCMD_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x5C) + +/* MMAP_ADDR */ +#define CPU_CS_SCIBCMDARG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x60) + +/* UC_REGION_ADDR */ +#define CPU_CS_SCIBARG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x64) + +/* UC_REGION_ADDR */ +#define CPU_CS_SCIBARG2_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x68) + +/* FAL10 Feature Control */ +#define CPU_CS_X2RPMh_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x168) +#define CPU_CS_X2RPMh_MASK0_BMSK_IRIS2 0x1 +#define CPU_CS_X2RPMh_MASK0_SHFT_IRIS2 0x0 +#define CPU_CS_X2RPMh_MASK1_BMSK_IRIS2 0x2 +#define CPU_CS_X2RPMh_MASK1_SHFT_IRIS2 0x1 +#define CPU_CS_X2RPMh_SWOVERRIDE_BMSK_IRIS2 0x4 +#define CPU_CS_X2RPMh_SWOVERRIDE_SHFT_IRIS2 0x3 + +#define CPU_IC_SOFTINT_IRIS2 (CPU_IC_BASE_OFFS_IRIS2 + 0x150) +#define CPU_IC_SOFTINT_H2A_SHFT_IRIS2 0x0 + +/* + * -------------------------------------------------------------------------- + * MODULE: wrapper + * -------------------------------------------------------------------------- + */ +#define WRAPPER_BASE_OFFS_IRIS2 0x000B0000 +#define WRAPPER_INTR_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x0C) +#define WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2 0x8 +#define WRAPPER_INTR_STATUS_A2H_BMSK_IRIS2 0x4 + +#define WRAPPER_INTR_MASK_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x10) +#define WRAPPER_INTR_MASK_A2HWD_BMSK_IRIS2 0x8 +#define WRAPPER_INTR_MASK_A2HCPU_BMSK_IRIS2 0x4 + +#define WRAPPER_CPU_CLOCK_CONFIG_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2000) +#define WRAPPER_CPU_CGC_DIS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2010) +#define WRAPPER_CPU_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2014) + +#define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x54) +#define WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x58) +/* + * -------------------------------------------------------------------------- + * MODULE: tz_wrapper + * -------------------------------------------------------------------------- + */ +#define WRAPPER_TZ_BASE_OFFS 0x000C0000 +#define WRAPPER_TZ_CPU_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS) +#define WRAPPER_TZ_CPU_STATUS (WRAPPER_TZ_BASE_OFFS + 0x10) + +#define CTRL_INIT_IRIS2 CPU_CS_SCIACMD_IRIS2 + +#define CTRL_STATUS_IRIS2 CPU_CS_SCIACMDARG0_IRIS2 +#define CTRL_ERROR_STATUS__M_IRIS2 \ + CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_IRIS2 +#define CTRL_INIT_IDLE_MSG_BMSK_IRIS2 \ + CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_IRIS2 +#define CTRL_STATUS_PC_READY_IRIS2 \ + CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_IRIS2 + + +#define QTBL_INFO_IRIS2 CPU_CS_SCIACMDARG1_IRIS2 + +#define QTBL_ADDR_IRIS2 CPU_CS_SCIACMDARG2_IRIS2 + +#define VERSION_INFO_IRIS2 CPU_CS_SCIACMDARG3_IRIS2 + +#define SFR_ADDR_IRIS2 CPU_CS_SCIBCMD_IRIS2 +#define MMAP_ADDR_IRIS2 CPU_CS_SCIBCMDARG0_IRIS2 +#define UC_REGION_ADDR_IRIS2 CPU_CS_SCIBARG1_IRIS2 +#define UC_REGION_SIZE_IRIS2 CPU_CS_SCIBARG2_IRIS2 + +#define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS) +#define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4) + +/* + * -------------------------------------------------------------------------- + * MODULE: vcodec noc error log registers (iris2) + * -------------------------------------------------------------------------- + */ +#define VCODEC_NOC_VIDEO_A_NOC_BASE_OFFS 0x00010000 +#define VCODEC_NOC_ERL_MAIN_SWID_LOW 0x00011200 +#define VCODEC_NOC_ERL_MAIN_SWID_HIGH 0x00011204 +#define VCODEC_NOC_ERL_MAIN_MAINCTL_LOW 0x00011208 +#define VCODEC_NOC_ERL_MAIN_ERRVLD_LOW 0x00011210 +#define VCODEC_NOC_ERL_MAIN_ERRCLR_LOW 0x00011218 +#define VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW 0x00011220 +#define VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH 0x00011224 +#define VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW 0x00011228 +#define VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH 0x0001122C +#define VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW 0x00011230 +#define VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH 0x00011234 +#define VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW 0x00011238 +#define VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH 0x0001123C + +void __interrupt_init_iris2(struct venus_hfi_device *device) +{ + u32 mask_val = 0; + + /* All interrupts should be disabled initially 0x1F6 : Reset value */ + mask_val = __read_register(device, WRAPPER_INTR_MASK_IRIS2); + + /* Write 0 to unmask CPU and WD interrupts */ + mask_val &= ~(WRAPPER_INTR_MASK_A2HWD_BMSK_IRIS2| + WRAPPER_INTR_MASK_A2HCPU_BMSK_IRIS2); + __write_register(device, WRAPPER_INTR_MASK_IRIS2, mask_val); +} + +void __setup_ucregion_memory_map_iris2(struct venus_hfi_device *device) +{ + __write_register(device, UC_REGION_ADDR_IRIS2, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, UC_REGION_SIZE_IRIS2, SHARED_QSIZE); + __write_register(device, QTBL_ADDR_IRIS2, + (u32)device->iface_q_table.align_device_addr); + __write_register(device, QTBL_INFO_IRIS2, 0x01); + if (device->sfr.align_device_addr) + __write_register(device, SFR_ADDR_IRIS2, + (u32)device->sfr.align_device_addr); + if (device->qdss.align_device_addr) + __write_register(device, MMAP_ADDR_IRIS2, + (u32)device->qdss.align_device_addr); +} + +void __power_off_iris2(struct venus_hfi_device *device) +{ + u32 lpi_status, reg_status = 0, count = 0, max_count = 10; + + if (!device->power_enabled) + return; + + if (!(device->intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2)) + disable_irq_nosync(device->hal_data->irq); + device->intr_status = 0; + + /* HPG 6.1.2 Step 1 */ + __write_register(device, CPU_CS_X2RPMh_IRIS2, 0x3); + + /* HPG 6.1.2 Step 2, noc to low power */ + __write_register(device, AON_WRAPPER_MVP_NOC_LPI_CONTROL, 0x1); + while (!reg_status && count < max_count) { + lpi_status = + __read_register(device, + AON_WRAPPER_MVP_NOC_LPI_STATUS); + reg_status = lpi_status & BIT(0); + dprintk(VIDC_DBG, + "Noc: lpi_status %d noc_status %d (count %d)\n", + lpi_status, reg_status, count); + usleep_range(50, 100); + count++; + } + if (count == max_count) { + dprintk(VIDC_ERR, + "NOC not in qaccept status %d\n", reg_status); + } + + /* HPG 6.1.2 Step 3, debug bridge to low power */ + __write_register(device, + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2, 0x7); + reg_status = 0; + count = 0; + while ((reg_status != 0x7) && count < max_count) { + lpi_status = __read_register(device, + WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2); + reg_status = lpi_status & 0x7; + dprintk(VIDC_DBG, + "DBLP Set : lpi_status %d reg_status %d (count %d)\n", + lpi_status, reg_status, count); + usleep_range(50, 100); + count++; + } + if (count == max_count) { + dprintk(VIDC_ERR, + "DBLP Set: status %d\n", reg_status); + } + + /* HPG 6.1.2 Step 4, debug bridge to lpi release */ + __write_register(device, + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2, 0x0); + lpi_status = 0x1; + count = 0; + while (lpi_status && count < max_count) { + lpi_status = __read_register(device, + WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2); + dprintk(VIDC_DBG, + "DBLP Release: lpi_status %d(count %d)\n", + lpi_status, count); + usleep_range(50, 100); + count++; + } + if (count == max_count) { + dprintk(VIDC_ERR, + "DBLP Release: lpi_status %d\n", lpi_status); + } + + /* HPG 6.1.2 Step 6 */ + __disable_unprepare_clks(device); + + /* HPG 6.1.2 Step 7 & 8 */ + if (call_venus_op(device, reset_ahb2axi_bridge, device)) + dprintk(VIDC_ERR, "Failed to reset ahb2axi\n"); + + /* HPG 6.1.2 Step 5 */ + if (__disable_regulators(device)) + dprintk(VIDC_WARN, "Failed to disable regulators\n"); + + if (__unvote_buses(device)) + dprintk(VIDC_WARN, "Failed to unvote for buses\n"); + device->power_enabled = false; +} + +int __prepare_pc_iris2(struct venus_hfi_device *device) +{ + int rc = 0; + u32 wfi_status = 0, idle_status = 0, pc_ready = 0; + u32 ctrl_status = 0; + int count = 0; + const int max_tries = 10; + + ctrl_status = __read_register(device, CTRL_STATUS_IRIS2); + pc_ready = ctrl_status & CTRL_STATUS_PC_READY_IRIS2; + idle_status = ctrl_status & BIT(30); + + if (pc_ready) { + dprintk(VIDC_DBG, "Already in pc_ready state\n"); + return 0; + } + + wfi_status = BIT(0) & __read_register(device, + WRAPPER_TZ_CPU_STATUS); + if (!wfi_status || !idle_status) { + dprintk(VIDC_WARN, "Skipping PC, wfi status not set\n"); + goto skip_power_off; + } + + rc = __prepare_pc(device); + if (rc) { + dprintk(VIDC_WARN, "Failed __prepare_pc %d\n", rc); + goto skip_power_off; + } + + while (count < max_tries) { + wfi_status = BIT(0) & __read_register(device, + WRAPPER_TZ_CPU_STATUS); + ctrl_status = __read_register(device, CTRL_STATUS_IRIS2); + if (wfi_status && (ctrl_status & CTRL_STATUS_PC_READY_IRIS2)) + break; + usleep_range(150, 250); + count++; + } + + if (count == max_tries) { + dprintk(VIDC_ERR, "Skip PC. Core is not in right state\n"); + goto skip_power_off; + } + + return rc; + +skip_power_off: + dprintk(VIDC_WARN, "Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n", + wfi_status, idle_status, pc_ready, ctrl_status); + return -EAGAIN; +} + +void __raise_interrupt_iris2(struct venus_hfi_device *device) +{ + __write_register(device, CPU_IC_SOFTINT_IRIS2, + 1 << CPU_IC_SOFTINT_H2A_SHFT_IRIS2); +} + +bool __watchdog_iris2(u32 intr_status) +{ + bool rc = false; + + if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2) + rc = true; + + return rc; +} + +void __noc_error_info_iris2(struct venus_hfi_device *device) +{ + u32 val = 0; + + val = __read_register(device, VCODEC_NOC_ERL_MAIN_SWID_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_SWID_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_SWID_HIGH); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_SWID_HIGH: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_MAINCTL_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_MAINCTL_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRVLD_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRVLD_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRCLR_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRCLR_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW: %#x\n", val); + val = __read_register(device, VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH); + dprintk(VIDC_ERR, "VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH: %#x\n", val); +} + +void __core_clear_interrupt_iris2(struct venus_hfi_device *device) +{ + u32 intr_status = 0, mask = 0; + + if (!device) { + dprintk(VIDC_ERR, "%s: NULL device\n", __func__); + return; + } + + intr_status = __read_register(device, WRAPPER_INTR_STATUS_IRIS2); + mask = (WRAPPER_INTR_STATUS_A2H_BMSK_IRIS2| + WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2| + CTRL_INIT_IDLE_MSG_BMSK_IRIS2); + + if (intr_status & mask) { + device->intr_status |= intr_status; + device->reg_count++; + dprintk(VIDC_DBG, + "INTERRUPT for device: %pK: times: %d interrupt_status: %d\n", + device, device->reg_count, intr_status); + } else { + device->spur_count++; + } + + __write_register(device, CPU_CS_A2HSOFTINTCLR_IRIS2, 1); +} + +int __boot_firmware_iris2(struct venus_hfi_device *device) +{ + int rc = 0; + u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 10000; + + ctrl_init_val = BIT(0); + if (device->res->domain_cvp) + ctrl_init_val |= BIT(1); + + __write_register(device, CTRL_INIT_IRIS2, ctrl_init_val); + while (!ctrl_status && count < max_tries) { + ctrl_status = __read_register(device, CTRL_STATUS_IRIS2); + if ((ctrl_status & CTRL_ERROR_STATUS__M_IRIS2) == 0x4) { + dprintk(VIDC_ERR, "invalid setting for UC_REGION\n"); + break; + } + + usleep_range(50, 100); + count++; + } + + if (count >= max_tries) { + dprintk(VIDC_ERR, "Error booting up vidc firmware\n"); + rc = -ETIME; + } + + /* Enable interrupt before sending commands to venus */ + __write_register(device, CPU_CS_H2XSOFTINTEN_IRIS2, 0x1); + __write_register(device, CPU_CS_X2RPMh_IRIS2, 0x0); + + return rc; +} diff --git a/msm/vidc/hfi_response_handler.c b/msm/vidc/hfi_response_handler.c index ef55a3a3f28a..a97d95cb3627 100644 --- a/msm/vidc/hfi_response_handler.c +++ b/msm/vidc/hfi_response_handler.c @@ -11,7 +11,6 @@ #include #include #include "vidc_hfi_helper.h" -#include "vidc_hfi_io.h" #include "msm_vidc_debug.h" #include "vidc_hfi.h" diff --git a/msm/vidc/msm_venc.c b/msm/vidc/msm_venc.c index 8d1256cdf1ce..a42802d5267b 100644 --- a/msm/vidc/msm_venc.c +++ b/msm/vidc/msm_venc.c @@ -1391,16 +1391,13 @@ static int msm_venc_resolve_rc_enable(struct msm_vidc_inst *inst, static int msm_venc_resolve_rate_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { - struct v4l2_ctrl *rc_enable; - if (inst->rc_type == RATE_CONTROL_LOSSLESS) { dprintk(VIDC_DBG, "Skip RC mode when enabling lossless encoding\n"); return 0; } - rc_enable = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE); - if (!rc_enable->val) { + if (inst->rc_type == RATE_CONTROL_OFF) { dprintk(VIDC_ERR, "RC is not enabled.\n"); return -EINVAL; @@ -2617,7 +2614,6 @@ int msm_venc_set_frame_qp(struct msm_vidc_inst *inst) struct v4l2_ctrl *i_qp = NULL; struct v4l2_ctrl *p_qp = NULL; struct v4l2_ctrl *b_qp = NULL; - struct v4l2_ctrl *rc_enable = NULL; struct hfi_quantization qp; if (!inst || !inst->core) { @@ -2633,7 +2629,6 @@ int msm_venc_set_frame_qp(struct msm_vidc_inst *inst) i_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP); p_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP); b_qp = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP); - rc_enable = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE); /* * When RC is ON: @@ -2642,7 +2637,7 @@ int msm_venc_set_frame_qp(struct msm_vidc_inst *inst) * I_QP value must be set by client. * If other QP value is invalid, then, assign I_QP value to it. */ - if (rc_enable->val) { + if (inst->rc_type != RATE_CONTROL_OFF) { if (!(inst->client_set_ctrls & CLIENT_SET_I_QP)) qp.enable &= ~QP_ENABLE_I; if (!(inst->client_set_ctrls & CLIENT_SET_P_QP)) @@ -2829,7 +2824,6 @@ int msm_venc_set_slice_control_mode(struct msm_vidc_inst *inst) u32 mb_per_frame, fps, mbps, bitrate, max_slices; u32 slice_val, slice_mode, max_avg_slicesize; u32 rc_mode, output_width, output_height; - struct v4l2_ctrl *rc_enable; u32 codec; if (!inst || !inst->core) { @@ -2845,13 +2839,11 @@ int msm_venc_set_slice_control_mode(struct msm_vidc_inst *inst) slice_val = 0; bitrate = inst->clk_data.bitrate; - fps = inst->clk_data.frame_rate; + fps = inst->clk_data.frame_rate >> 16; rc_mode = inst->rc_type; - rc_enable = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE); - if (fps > 60 || - (rc_enable->val && - rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR && - rc_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)) { + if (fps > 60 || (!(rc_mode == RATE_CONTROL_OFF || + rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR || + rc_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))) { goto set_and_exit; } @@ -2896,8 +2888,11 @@ int msm_venc_set_slice_control_mode(struct msm_vidc_inst *inst) mbps <= NUM_MBS_PER_SEC(1088, 1920, 60)) { max_slices = inst->capability.cap[CAP_SLICE_BYTE].max ? inst->capability.cap[CAP_SLICE_BYTE].max : 1; - max_avg_slicesize = ((bitrate / fps) / 8) / max_slices; - slice_val = max(slice_val, max_avg_slicesize); + if (rc_mode != RATE_CONTROL_OFF) { + max_avg_slicesize = + ((bitrate / fps) / 8) / max_slices; + slice_val = max(slice_val, max_avg_slicesize); + } } } @@ -2928,7 +2923,6 @@ int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst) int rc = 0; struct hfi_device *hdev; struct v4l2_ctrl *ctrl = NULL; - struct v4l2_ctrl *rc_mode = NULL; struct hfi_intra_refresh intra_refresh; struct v4l2_format *f; @@ -2938,9 +2932,8 @@ int msm_venc_set_intra_refresh_mode(struct msm_vidc_inst *inst) } hdev = inst->core->device; - rc_mode = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE_MODE); - if (!(rc_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR || - rc_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)) + if (!(inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR || + inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)) return 0; /* Firmware supports only random mode */ @@ -3616,6 +3609,11 @@ int msm_venc_set_ltr_mode(struct msm_vidc_inst *inst) if (!(codec == V4L2_PIX_FMT_HEVC || codec == V4L2_PIX_FMT_H264)) return 0; + if (!(inst->rc_type == RATE_CONTROL_OFF || + inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR || + inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR_VFR)) + return 0; + ctrl = get_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT); if (!ctrl->val) return 0; @@ -3706,7 +3704,6 @@ int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) int rc = 0; struct hfi_device *hdev; struct hfi_quantization qp; - struct v4l2_ctrl *rc_enable; if (!inst || !inst->core) { dprintk(VIDC_ERR, "%s: invalid params\n", __func__); @@ -3714,8 +3711,7 @@ int msm_venc_set_dyn_qp(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) } hdev = inst->core->device; - rc_enable = get_ctrl(inst, V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE); - if (rc_enable->val) { + if (inst->rc_type != RATE_CONTROL_OFF) { dprintk(VIDC_ERR, "%s: Dyn qp is set only when RC is OFF\n", __func__); return -EINVAL; @@ -3958,6 +3954,9 @@ int msm_venc_set_properties(struct msm_vidc_inst *inst) if (rc) goto exit; rc = msm_venc_set_rate_control(inst); + if (rc) + goto exit; + rc = msm_venc_set_vbv_delay(inst); if (rc) goto exit; rc = msm_venc_set_bitrate_savings_mode(inst); diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index 72e4a0cb310f..5a633cd0f5df 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -1432,12 +1432,6 @@ static void msm_vidc_comm_update_ctrl_limits(struct msm_vidc_inst *inst) return; msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDEO_BITRATE, &inst->capability.cap[CAP_BITRATE]); - msm_vidc_comm_update_ctrl(inst, - V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, - &inst->capability.cap[CAP_SLICE_BYTE]); - msm_vidc_comm_update_ctrl(inst, - V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, - &inst->capability.cap[CAP_SLICE_MB]); msm_vidc_comm_update_ctrl(inst, V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT, &inst->capability.cap[CAP_LTR_COUNT]); diff --git a/msm/vidc/vidc_hfi.c b/msm/vidc/vidc_hfi.c index cedf0c1dea00..11ea53019f63 100644 --- a/msm/vidc/vidc_hfi.c +++ b/msm/vidc/vidc_hfi.c @@ -1,11 +1,11 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. */ #include #include "msm_vidc_debug.h" #include "vidc_hfi_api.h" -#include "venus_hfi.h" +#include "hfi_common.h" struct hfi_device *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id, struct msm_vidc_platform_resources *res, diff --git a/msm/vidc/vidc_hfi_io.h b/msm/vidc/vidc_hfi_io.h deleted file mode 100644 index 388d1ac1cc98..000000000000 --- a/msm/vidc/vidc_hfi_io.h +++ /dev/null @@ -1,220 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. - */ - -#ifndef __VIDC_HFI_IO_H__ -#define __VIDC_HFI_IO_H__ - -#include - -#define VIDC_VBIF_BASE_OFFS 0x00080000 - -#define VIDC_CPU_BASE_OFFS 0x000A0000 -#define VIDEO_CC_BASE_OFFS 0x000F0000 -#define VIDC_AON_BASE_OFFS 0x000E0000 -#define VIDC_CPU_CS_BASE_OFFS (VIDC_CPU_BASE_OFFS) -#define VIDC_CPU_IC_BASE_OFFS (VIDC_CPU_BASE_OFFS) - -#define VIDC_CPU_CS_A2HSOFTINTEN (VIDC_CPU_CS_BASE_OFFS + 0x10) -#define VIDC_CPU_CS_A2HSOFTINTENCLR (VIDC_CPU_CS_BASE_OFFS + 0x14) -#define VIDC_CPU_CS_A2HSOFTINT (VIDC_CPU_CS_BASE_OFFS + 0x18) -#define VIDC_CPU_CS_A2HSOFTINTCLR (VIDC_CPU_CS_BASE_OFFS + 0x1C) -#define VIDC_CPU_CS_VMIMSG (VIDC_CPU_CS_BASE_OFFS + 0x34) -#define VIDC_CPU_CS_VMIMSGAG0 (VIDC_CPU_CS_BASE_OFFS + 0x38) -#define VIDC_CPU_CS_VMIMSGAG1 (VIDC_CPU_CS_BASE_OFFS + 0x3C) -#define VIDC_CPU_CS_VMIMSGAG2 (VIDC_CPU_CS_BASE_OFFS + 0x40) -#define VIDC_CPU_CS_VMIMSGAG3 (VIDC_CPU_CS_BASE_OFFS + 0x44) -#define VIDC_CPU_CS_SCIACMD (VIDC_CPU_CS_BASE_OFFS + 0x48) -#define VIDC_CPU_CS_H2XSOFTINTEN (VIDC_CPU_CS_BASE_OFFS + 0x148) - -/* HFI_CTRL_STATUS */ -#define VIDC_CPU_CS_SCIACMDARG0 (VIDC_CPU_CS_BASE_OFFS + 0x4C) -#define VIDC_CPU_CS_SCIACMDARG0_BMSK 0xff -#define VIDC_CPU_CS_SCIACMDARG0_SHFT 0x0 -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK 0xfe -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT 0x1 -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK 0x1 -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT 0x0 -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY 0x100 -#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK 0x40000000 - -/* HFI_QTBL_INFO */ -#define VIDC_CPU_CS_SCIACMDARG1 (VIDC_CPU_CS_BASE_OFFS + 0x50) - -/* HFI_QTBL_ADDR */ -#define VIDC_CPU_CS_SCIACMDARG2 (VIDC_CPU_CS_BASE_OFFS + 0x54) - -/* HFI_VERSION_INFO */ -#define VIDC_CPU_CS_SCIACMDARG3 (VIDC_CPU_CS_BASE_OFFS + 0x58) - -/* VIDC_SFR_ADDR */ -#define VIDC_CPU_CS_SCIBCMD (VIDC_CPU_CS_BASE_OFFS + 0x5C) - -/* VIDC_MMAP_ADDR */ -#define VIDC_CPU_CS_SCIBCMDARG0 (VIDC_CPU_CS_BASE_OFFS + 0x60) - -/* VIDC_UC_REGION_ADDR */ -#define VIDC_CPU_CS_SCIBARG1 (VIDC_CPU_CS_BASE_OFFS + 0x64) - -/* VIDC_UC_REGION_ADDR */ -#define VIDC_CPU_CS_SCIBARG2 (VIDC_CPU_CS_BASE_OFFS + 0x68) - -#define VIDC_CPU_CS_SCIBARG3 (VIDC_CPU_CS_BASE_OFFS + 0x6C) - -/* FAL10 Feature Control */ -#define VIDC_CPU_CS_X2RPMh (VIDC_CPU_CS_BASE_OFFS + 0x168) -#define VIDC_CPU_CS_X2RPMh_MASK0_BMSK 0x1 -#define VIDC_CPU_CS_X2RPMh_MASK0_SHFT 0x0 -#define VIDC_CPU_CS_X2RPMh_MASK1_BMSK 0x2 -#define VIDC_CPU_CS_X2RPMh_MASK1_SHFT 0x1 -#define VIDC_CPU_CS_X2RPMh_SWOVERRIDE_BMSK 0x4 -#define VIDC_CPU_CS_X2RPMh_SWOVERRIDE_SHFT 0x3 - -#define VIDC_CPU_IC_SOFTINT (VIDC_CPU_IC_BASE_OFFS + 0x150) -#define VIDC_CPU_IC_SOFTINT_H2A_BMSK 0x1 -#define VIDC_CPU_IC_SOFTINT_H2A_SHFT 0x0 -#define VIDC_CPU_IC_SOFTINTCLEAR (VIDC_CPU_IC_BASE_OFFS + 0x154) - -/* - * -------------------------------------------------------------------------- - * MODULE: vidc_wrapper - * -------------------------------------------------------------------------- - */ -#define VIDC_WRAPPER_BASE_OFFS 0x000B0000 - -#define VIDC_WRAPPER_HW_VERSION (VIDC_WRAPPER_BASE_OFFS + 0x00) -#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_MASK 0x78000000 -#define VIDC_WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT 28 -#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_MASK 0xFFF0000 -#define VIDC_WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT 16 -#define VIDC_WRAPPER_HW_VERSION_STEP_VERSION_MASK 0xFFFF -#define VIDC_WRAPPER_CLOCK_CONFIG (VIDC_WRAPPER_BASE_OFFS + 0x04) - -#define VIDC_WRAPPER_INTR_STATUS (VIDC_WRAPPER_BASE_OFFS + 0x0C) -#define VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK 0x8 -#define VIDC_WRAPPER_INTR_STATUS_A2HWD_SHFT 0x3 -#define VIDC_WRAPPER_INTR_STATUS_A2H_BMSK 0x4 -#define VIDC_WRAPPER_INTR_STATUS_A2H_SHFT 0x2 - -#define VIDC_WRAPPER_INTR_MASK (VIDC_WRAPPER_BASE_OFFS + 0x10) -#define VIDC_WRAPPER_INTR_MASK_A2HWD_BMSK 0x8 -#define VIDC_WRAPPER_INTR_MASK_A2HWD_SHFT 0x3 -#define VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK 0x8 -#define VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK 0x4 -#define VIDC_WRAPPER_INTR_MASK_A2HCPU_SHFT 0x2 - -#define VIDC_WRAPPER_CPU_CLOCK_CONFIG (VIDC_WRAPPER_BASE_OFFS + 0x2000) -#define VIDC_WRAPPER_CPU_CGC_DIS (VIDC_WRAPPER_BASE_OFFS + 0x2010) -#define VIDC_WRAPPER_CPU_STATUS (VIDC_WRAPPER_BASE_OFFS + 0x2014) - -#define VIDC_WRAPPER_DEBUG_BRIDGE_LPI_CONTROL (VIDC_WRAPPER_BASE_OFFS + 0x54) -#define VIDC_WRAPPER_DEBUG_BRIDGE_LPI_STATUS (VIDC_WRAPPER_BASE_OFFS + 0x58) -/* - * -------------------------------------------------------------------------- - * MODULE: vidc_tz_wrapper - * -------------------------------------------------------------------------- - */ -#define VIDC_WRAPPER_TZ_BASE_OFFS 0x000C0000 -#define VIDC_WRAPPER_TZ_CPU_CLOCK_CONFIG (VIDC_WRAPPER_TZ_BASE_OFFS) -#define VIDC_WRAPPER_TZ_CPU_STATUS (VIDC_WRAPPER_TZ_BASE_OFFS + 0x10) - -#define VIDC_VENUS_VBIF_CLK_ON (VIDC_VBIF_BASE_OFFS + 0x4) -#define VENUS_VBIF_AXI_HALT_CTRL0 (VIDC_VBIF_BASE_OFFS + 0x208) -#define VENUS_VBIF_AXI_HALT_CTRL1 (VIDC_VBIF_BASE_OFFS + 0x20C) - -#define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ BIT(0) -#define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK BIT(0) -#define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US 500000 - - -#define VIDC_CTRL_INIT VIDC_CPU_CS_SCIACMD - -#define VIDC_CTRL_STATUS VIDC_CPU_CS_SCIACMDARG0 -#define VIDC_CTRL_ERROR_STATUS__M \ - VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK -#define VIDC_CTRL_INIT_IDLE_MSG_BMSK \ - VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK -#define VIDC_CTRL_STATUS_PC_READY \ - VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY - - -#define VIDC_QTBL_INFO VIDC_CPU_CS_SCIACMDARG1 - -#define VIDC_QTBL_ADDR VIDC_CPU_CS_SCIACMDARG2 - -#define VIDC_VERSION_INFO VIDC_CPU_CS_SCIACMDARG3 - -#define VIDC_SFR_ADDR VIDC_CPU_CS_SCIBCMD -#define VIDC_MMAP_ADDR VIDC_CPU_CS_SCIBCMDARG0 -#define VIDC_UC_REGION_ADDR VIDC_CPU_CS_SCIBARG1 -#define VIDC_UC_REGION_SIZE VIDC_CPU_CS_SCIBARG2 - -/* HFI_DSP_QTBL_ADDR - * 31:3 - HFI_DSP_QTBL_ADDR - * 4-byte aligned Address - */ -#define HFI_DSP_QTBL_ADDR VIDC_CPU_CS_VMIMSG - -/* HFI_DSP_UC_REGION_ADDR - * 31:20 - HFI_DSP_UC_REGION_ADDR - * 1MB aligned address. - * Uncached Region start Address. This region covers - * HFI DSP QTable, - * HFI DSP Queue Headers, - * HFI DSP Queues, - */ -#define HFI_DSP_UC_REGION_ADDR VIDC_CPU_CS_VMIMSGAG0 - -/* HFI_DSP_UC_REGION_SIZE - * 31:20 - HFI_DSP_UC_REGION_SIZE - * Multiples of 1MB. - * Size of the DSP_UC_REGION Uncached Region - */ -#define HFI_DSP_UC_REGION_SIZE VIDC_CPU_CS_VMIMSGAG1 - -/* - * -------------------------------------------------------------------------- - * MODULE: vcodec noc error log registers (iris1) - * -------------------------------------------------------------------------- - */ -#define VCODEC_CORE0_VIDEO_NOC_BASE_OFFS 0x00004000 -#define VCODEC_CORE1_VIDEO_NOC_BASE_OFFS 0x0000C000 -#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_LOW_OFFS 0x0500 -#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_HIGH_OFFS 0x0504 -#define VCODEC_COREX_VIDEO_NOC_ERR_MAINCTL_LOW_OFFS 0x0508 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRVLD_LOW_OFFS 0x0510 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRCLR_LOW_OFFS 0x0518 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_LOW_OFFS 0x0520 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_HIGH_OFFS 0x0524 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_LOW_OFFS 0x0528 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_HIGH_OFFS 0x052C -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_LOW_OFFS 0x0530 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_HIGH_OFFS 0x0534 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_LOW_OFFS 0x0538 -#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_HIGH_OFFS 0x053C - -#define VIDC_AON_WRAPPER_MVP_NOC_LPI_CONTROL (VIDC_AON_BASE_OFFS) -#define VIDC_AON_WRAPPER_MVP_NOC_LPI_STATUS (VIDC_AON_BASE_OFFS + 0x4) - -/* - * -------------------------------------------------------------------------- - * MODULE: vcodec noc error log registers (iris2) - * -------------------------------------------------------------------------- - */ -#define VCODEC_NOC_VIDEO_A_NOC_BASE_OFFS 0x00010000 -#define VCODEC_NOC_ERL_MAIN_SWID_LOW 0x00011200 -#define VCODEC_NOC_ERL_MAIN_SWID_HIGH 0x00011204 -#define VCODEC_NOC_ERL_MAIN_MAINCTL_LOW 0x00011208 -#define VCODEC_NOC_ERL_MAIN_ERRVLD_LOW 0x00011210 -#define VCODEC_NOC_ERL_MAIN_ERRCLR_LOW 0x00011218 -#define VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW 0x00011220 -#define VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH 0x00011224 -#define VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW 0x00011228 -#define VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH 0x0001122C -#define VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW 0x00011230 -#define VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH 0x00011234 -#define VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW 0x00011238 -#define VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH 0x0001123C -# -#endif