Loading drivers/media/platform/msm/cvp/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ msm-cvp-objs := cvp.o \ cvp_core_hfi.o \ msm_cvp_clocks.o \ msm_cvp_dsp.o \ msm_cvp_buf.o msm_cvp_buf.o \ msm_cvp_synx.o obj-$(CONFIG_MSM_CVP) := msm-cvp.o drivers/media/platform/msm/cvp/cvp_comm_def.h 0 → 100644 +24 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _MSM_COMM_DEF_H_ #define _MSM_COMM_DEF_H_ #include <linux/types.h> enum op_mode { OP_NORMAL, OP_DRAINING, OP_FLUSH, OP_INVALID, }; enum queue_state { QUEUE_INIT, QUEUE_ACTIVE = 1, QUEUE_STOP = 2, QUEUE_INVALID, }; #endif drivers/media/platform/msm/cvp/msm_cvp.c +50 −466 Original line number Diff line number Diff line Loading @@ -278,19 +278,16 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q, return true; } static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, static int cvp_fence_dme(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { int i; int rc = 0; unsigned long timeout; int h_synx; u64 ktid; unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; struct synx_session ssid; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; Loading @@ -298,29 +295,10 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; i = 0; while (i < HFI_DME_BUF_NUM - 1) { h_synx = synx[i]; if (h_synx) { rc = synx_wait(ssid, h_synx, timeout_ms); if (rc) { dprintk(CVP_ERR, "%s %s: synx_wait %d failed\n", current->comm, __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) goto exit; } /* * Increase loop count to skip fence * waiting on downscale image where i == 1. */ if (i == FENCE_DME_ICA_ENABLED_IDX) ++i; } ++i; } rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); Loading Loading @@ -357,40 +335,21 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, } exit: if (synx[FENCE_DME_ICA_ENABLED_IDX]) { h_synx = synx[FENCE_DME_DS_IDX]; rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", current->comm, __func__, FENCE_DME_DS_IDX); synx_state = SYNX_STATE_SIGNALED_ERROR; } } h_synx = synx[FENCE_DME_OUTPUT_IDX]; rc = synx_signal(ssid, h_synx, synx_state); if (rc) dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", current->comm, __func__, FENCE_DME_OUTPUT_IDX); rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, static int cvp_fence_proc(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { int i; int rc = 0; unsigned long timeout; int h_synx; u64 ktid; unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; struct synx_session ssid; u32 in, out; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; Loading @@ -398,34 +357,10 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; in = synx[0] >> 16; out = synx[0] & 0xFFFF; i = 1; while (i <= in) { h_synx = synx[i]; if (h_synx) { rc = synx_wait(ssid, h_synx, timeout_ms); if (rc) { synx_state = synx_get_status(ssid, h_synx); if (synx_state == SYNX_STATE_SIGNALED_CANCEL) { dprintk(CVP_DBG, "%s: synx_wait %d cancel %d state %d\n", current->comm, i, rc, synx_state); } else { dprintk(CVP_ERR, "%s: synx_wait %d failed %d state %d\n", current->comm, i, rc, synx_state); synx_state = SYNX_STATE_SIGNALED_ERROR; } if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) goto exit; } } ++i; } rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); Loading Loading @@ -458,19 +393,7 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, } exit: i = in + 1; while (i <= in + out) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", current->comm, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } ++i; } rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } Loading Loading @@ -501,119 +424,6 @@ static void cvp_free_fence_data(struct cvp_fence_command *f) f = NULL; } static int cvp_import_synx(struct msm_cvp_inst *inst, u32 type, u32 *fence, u32 *synx) { int rc = 0; int i; int start = 0, end = 0; struct cvp_fence_type *f; struct synx_import_params params; s32 h_synx; struct synx_session ssid; f = (struct cvp_fence_type *)fence; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 0; end = HFI_DME_BUF_NUM; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in = fence[0]; u32 out = fence[1]; if (in > MAX_HFI_FENCE_SIZE || out > MAX_HFI_FENCE_SIZE || in > MAX_HFI_FENCE_SIZE - out) { dprintk(CVP_ERR, "%s: failed!\n", __func__); rc = -EINVAL; return rc; } synx[0] = (in << 16) | out; start = 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = f[i].h_synx; if (h_synx) { params.h_synx = h_synx; params.secure_key = f[i].secure_key; params.new_h_synx = &synx[i]; rc = synx_import(ssid, ¶ms); if (rc) { dprintk(CVP_ERR, "%s: synx_import failed\n", __func__); return rc; } } } return rc; } static int cvp_release_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; s32 h_synx; struct synx_session ssid; int start = 0, end = 0; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 0; end = HFI_DME_BUF_NUM; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in = synx[0] >> 16; u32 out = synx[0] & 0xFFFF; start = 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_release(ssid, h_synx); if (rc) dprintk(CVP_ERR, "%s: synx_release %d failed\n", __func__, i); } } return rc; } static int cvp_fence_thread(void *data) { int rc = 0; Loading Loading @@ -656,10 +466,10 @@ static int cvp_fence_thread(void *data) switch (f->type) { case HFI_CMD_SESSION_CVP_DME_FRAME: rc = cvp_fence_dme(inst, synx, pkt); rc = cvp_fence_dme(inst, f, pkt); break; case HFI_CMD_SESSION_CVP_FD_FRAME: rc = cvp_fence_proc(inst, synx, pkt); rc = cvp_fence_proc(inst, f, pkt); break; default: dprintk(CVP_ERR, "%s: unknown hfi cmd type 0x%x\n", Loading @@ -670,7 +480,7 @@ static int cvp_fence_thread(void *data) } mutex_lock(&q->lock); cvp_release_synx(inst, f->type, synx); cvp_release_synx(inst, f); list_del_init(&f->list); mutex_unlock(&q->lock); Loading @@ -693,6 +503,8 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, int rc = 0; int idx; struct cvp_kmd_hfi_fence_packet *fence_pkt; struct cvp_kmd_hfi_synx_packet *synx_pkt; struct cvp_kmd_fence_ctrl *kfc; struct cvp_hfi_cmd_session_hdr *pkt; unsigned int offset, buf_num, in_offset, in_buf_num; struct msm_cvp_inst *s; Loading Loading @@ -727,7 +539,6 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, fence_pkt = &arg->data.hfi_fence_pkt; pkt = (struct cvp_hfi_cmd_session_hdr *)&fence_pkt->pkt_data; fence = (u32 *)&fence_pkt->fence_data; idx = get_pkt_index((struct cvp_hal_session_cmd_pkt *)pkt); if (idx < 0 || pkt->size > MAX_HFI_FENCE_OFFSET) { Loading Loading @@ -758,16 +569,29 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, goto exit; f->type = cvp_hfi_defs[idx].type; f->frame_id = arg->data.hfi_fence_pkt.frame_id; f->mode = OP_NORMAL; synx_pkt = &arg->data.hfi_synx_pkt; if (synx_pkt->fence_data[0] != 0xFEEDFACE) { fence = (u32 *)&fence_pkt->fence_data; f->frame_id = arg->data.hfi_fence_pkt.frame_id; } else { kfc = &synx_pkt->fc; fence = (u32 *)&kfc->fences; f->frame_id = kfc->frame_id; f->signature = 0xFEEDFACE; f->num_fences = kfc->num_fences; f->output_index = kfc->output_index; } dprintk(CVP_DBG, "%s: frameID %llu\n", __func__, f->frame_id); memcpy(f->pkt, pkt, pkt->size); f->pkt->client_data.kdata |= FENCE_BIT; rc = cvp_import_synx(inst, f->type, fence, f->synx); rc = cvp_import_synx(inst, f, fence); if (rc) { kfree(f); goto exit; Loading Loading @@ -897,77 +721,6 @@ static void aggregate_power_update(struct msm_cvp_core *core, rt_pwr->bw_sum += bw_sum[1]; } static void aggregate_power_request(struct msm_cvp_core *core, struct cvp_power_level *nrt_pwr, struct cvp_power_level *rt_pwr, unsigned int max_clk_rate) { struct msm_cvp_inst *inst; int i; unsigned long core_sum[2] = {0}, ctlr_sum[2] = {0}, fw_sum[2] = {0}; unsigned long op_core_max[2] = {0}, op_ctlr_max[2] = {0}; unsigned long op_fw_max[2] = {0}, bw_sum[2] = {0}, op_bw_max[2] = {0}; list_for_each_entry(inst, &core->instances, list) { if (inst->state == MSM_CVP_CORE_INVALID || inst->state == MSM_CVP_CORE_UNINIT || is_subblock_profile_existed(inst)) continue; if (inst->prop.priority <= CVP_RT_PRIO_THRESHOLD) { /* Non-realtime session use index 0 */ i = 0; } else { i = 1; } dprintk(CVP_PROF, "pwrReq sess %pK core %u ctl %u fw %u\n", inst, inst->power.clock_cycles_a, inst->power.clock_cycles_b, inst->power.reserved[0]); dprintk(CVP_PROF, "pwrReq op_core %u op_ctl %u op_fw %u\n", inst->power.reserved[1], inst->power.reserved[2], inst->power.reserved[3]); core_sum[i] += inst->power.clock_cycles_a; ctlr_sum[i] += inst->power.clock_cycles_b; fw_sum[i] += inst->power.reserved[0]; op_core_max[i] = (op_core_max[i] >= inst->power.reserved[1]) ? op_core_max[i] : inst->power.reserved[1]; op_ctlr_max[i] = (op_ctlr_max[i] >= inst->power.reserved[2]) ? op_ctlr_max[i] : inst->power.reserved[2]; op_fw_max[i] = (op_fw_max[i] >= inst->power.reserved[3]) ? op_fw_max[i] : inst->power.reserved[3]; bw_sum[i] += inst->power.ddr_bw; op_bw_max[i] = (op_bw_max[i] >= inst->power.reserved[4]) ? op_bw_max[i] : inst->power.reserved[4]; } for (i = 0; i < 2; i++) { core_sum[i] = max_3(core_sum[i], ctlr_sum[i], fw_sum[i]); op_core_max[i] = max_3(op_core_max[i], op_ctlr_max[i], op_fw_max[i]); op_core_max[i] = (op_core_max[i] > max_clk_rate) ? max_clk_rate : op_core_max[i]; bw_sum[i] = (bw_sum[i] >= op_bw_max[i]) ? bw_sum[i] : op_bw_max[i]; } nrt_pwr->core_sum += core_sum[0]; nrt_pwr->op_core_sum = (nrt_pwr->op_core_sum >= op_core_max[0]) ? nrt_pwr->op_core_sum : op_core_max[0]; nrt_pwr->bw_sum += bw_sum[0]; rt_pwr->core_sum += core_sum[1]; rt_pwr->op_core_sum = (rt_pwr->op_core_sum >= op_core_max[1]) ? rt_pwr->op_core_sum : op_core_max[1]; rt_pwr->bw_sum += bw_sum[1]; } /** * adjust_bw_freqs(): calculate CVP clock freq and bw required to sustain * required use case. Loading Loading @@ -1006,10 +759,6 @@ static int adjust_bw_freqs(void) max_bw = bus->range[1]; min_bw = max_bw/10; aggregate_power_request(core, &nrt_pwr, &rt_pwr, cvp_max_rate); dprintk(CVP_DBG, "PwrReq nrt %u %u rt %u %u\n", nrt_pwr.core_sum, nrt_pwr.op_core_sum, rt_pwr.core_sum, rt_pwr.op_core_sum); aggregate_power_update(core, &nrt_pwr, &rt_pwr, cvp_max_rate); dprintk(CVP_DBG, "PwrUpdate nrt %u %u rt %u %u\n", nrt_pwr.core_sum, nrt_pwr.op_core_sum, Loading Loading @@ -1069,64 +818,6 @@ static int adjust_bw_freqs(void) return rc; } /** * Use of cvp_kmd_request_power structure * clock_cycles_a: CVP core clock freq * clock_cycles_b: CVP controller clock freq * ddr_bw: b/w vote in Bps * reserved[0]: CVP firmware required clock freq * reserved[1]: CVP core operational clock freq * reserved[2]: CVP controller operational clock freq * reserved[3]: CVP firmware operational clock freq * reserved[4]: CVP operational b/w vote * * session's power record only saves normalized freq or b/w vote */ static int msm_cvp_request_power(struct msm_cvp_inst *inst, struct cvp_kmd_request_power *power) { int rc = 0; struct msm_cvp_core *core; struct msm_cvp_inst *s; if (!inst || !power) { dprintk(CVP_ERR, "%s: invalid params\n", __func__); return -EINVAL; } s = cvp_get_inst_validate(inst->core, inst); if (!s) return -ECONNRESET; inst->cur_cmd_type = CVP_KMD_REQUEST_POWER; core = inst->core; mutex_lock(&core->lock); memcpy(&inst->power, power, sizeof(*power)); /* Normalize CVP controller clock freqs */ inst->power.clock_cycles_b = div_by_1dot5(inst->power.clock_cycles_b); inst->power.reserved[0] = div_by_1dot5(inst->power.reserved[0]); inst->power.reserved[2] = div_by_1dot5(inst->power.reserved[2]); inst->power.reserved[3] = div_by_1dot5(inst->power.reserved[3]); /* Convert bps to KBps */ inst->power.ddr_bw = inst->power.ddr_bw >> 10; rc = adjust_bw_freqs(); if (rc) { memset(&inst->power, 0x0, sizeof(inst->power)); dprintk(CVP_ERR, "Instance %pK power request out of range\n"); } mutex_unlock(&core->lock); inst->cur_cmd_type = 0; cvp_put_inst(s); return rc; } static int msm_cvp_update_power(struct msm_cvp_inst *inst) { int rc = 0; Loading Loading @@ -1430,7 +1121,7 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, struct cvp_kmd_sys_properties *props = &arg->data.sys_properties; struct cvp_hfi_device *hdev; struct iris_hfi_device *hfi; int rc = 0; int i, rc = 0; if (!inst || !inst->core || !inst->core->device) { dprintk(CVP_ERR, "%s: invalid params\n", __func__); Loading @@ -1440,17 +1131,19 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, hdev = inst->core->device; hfi = hdev->hfi_device_data; switch (props->prop_data.prop_type) { for (i = 0; i < props->prop_num; i++) { switch (props->prop_data[i].prop_type) { case CVP_KMD_PROP_HFI_VERSION: { props->prop_data.data = hfi->version; props->prop_data[i].data = hfi->version; break; } default: dprintk(CVP_ERR, "unrecognized sys property %d\n", props->prop_data.prop_type); props->prop_data[i].prop_type); rc = -EFAULT; } } return rc; } Loading @@ -1473,7 +1166,7 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return -E2BIG; } prop_array = &arg->data.sys_properties.prop_data; prop_array = &arg->data.sys_properties.prop_data[0]; session_prop = &inst->prop; for (i = 0; i < props->prop_num; i++) { Loading Loading @@ -1549,107 +1242,6 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return rc; } static int cvp_cancel_input_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; int h_synx; struct synx_session ssid; int start = 0, end = 0; int synx_state = SYNX_STATE_SIGNALED_CANCEL; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 1; end = HFI_DME_BUF_NUM - 1; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in, out; in = synx[0] >> 16; out = synx[0] & 0xFFFF; start = 1; end = in + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc && rc != -EALREADY) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } } return rc; } static int cvp_cancel_output_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; int h_synx; struct synx_session ssid; int start = 0, end = 0; int synx_state = SYNX_STATE_SIGNALED_CANCEL; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = FENCE_DME_OUTPUT_IDX; end = FENCE_DME_OUTPUT_IDX + 1; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in, out; in = synx[0] >> 16; out = synx[0] & 0xFFFF; start = in + 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } } return rc; } static int cvp_drain_fence_cmd_queue_partial(struct msm_cvp_inst *inst) { unsigned long wait_time; Loading Loading @@ -1790,8 +1382,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); cvp_cancel_output_synx(inst, f->type, f->synx); cvp_release_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); cvp_release_synx(inst, f); cvp_free_fence_data(f); } Loading @@ -1802,7 +1394,7 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); cvp_cancel_input_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); Loading Loading @@ -1906,8 +1498,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); cvp_cancel_output_synx(inst, f->type, f->synx); cvp_release_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); cvp_release_synx(inst, f); cvp_free_fence_data(f); } Loading @@ -1921,7 +1513,7 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); cvp_cancel_input_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); Loading Loading @@ -1969,14 +1561,6 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg) rc = msm_cvp_get_session_info(inst, session); break; } case CVP_KMD_REQUEST_POWER: { struct cvp_kmd_request_power *power = (struct cvp_kmd_request_power *)&arg->data.req_power; rc = msm_cvp_request_power(inst, power); break; } case CVP_KMD_UPDATE_POWER: { rc = msm_cvp_update_power(inst); Loading drivers/media/platform/msm/cvp/msm_cvp_core.c +1 −138 Original line number Diff line number Diff line Loading @@ -29,144 +29,7 @@ int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc, struct cvp_kmd_request_power *cvp_voting) { unsigned int cvp_cycles = 0; unsigned int hcd_cycles = 0; unsigned int dme_cycles = 0; unsigned int ds_cycles = 0; unsigned int ncc_cycles = 0; unsigned int num_16x16_blocks = 0; unsigned int cvp_bw = 0; unsigned int ds_pixel_read = 0; unsigned int ds_pixel_write = 0; unsigned int hcd_pixel_read = 0; unsigned int hcd_stats_write = 0; unsigned int dme_pixel_read = 0; unsigned int ncc_pixel_read = 0; unsigned int process_width = 0; unsigned int process_height = 0; if (!cvp_desc || !cvp_voting) { dprintk(CVP_ERR, "%s: invalid args\n", __func__); return -EINVAL; } if (cvp_desc->is_downscale) { num_16x16_blocks = (cvp_desc->fullres_width>>4) * (cvp_desc->fullres_height>>4); ds_cycles = NUM_CYCLES16X16_DS_FRAME * num_16x16_blocks; process_width = cvp_desc->downscale_width; process_height = cvp_desc->downscale_height; num_16x16_blocks = (process_width>>4)*(process_height>>4); hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; /*Estimate downscale output (always UBWC) BW stats*/ if (cvp_desc->fullres_width <= 1920) { /*w*h/1.58=w*h*(81/128)*/ ds_pixel_write = ((process_width*process_height*81)>>7); } else { /*w*h/2.38=w*h*(54/128)*/ ds_pixel_write = ((process_width*process_height*54)>>7); } /*Estimate downscale input BW stats based on colorfmt*/ switch (cvp_desc->colorfmt) { case COLOR_FMT_NV12: { /*w*h*1.5*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 3)>>1); break; } case COLOR_FMT_P010: { /*w*h*2*1.5*/ ds_pixel_read = cvp_desc->fullres_width * cvp_desc->fullres_height * 3; break; } case COLOR_FMT_NV12_UBWC: { /*w*h*1.5/factor(factor=width>1920?2.38:1.58)*/ if (cvp_desc->fullres_width <= 1920) { /*w*h*1.5/1.58 = w*h*121/128*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 121)>>7); } else { /*w*h*1.5/1.61 = w*h*119/128*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 119)>>7); } break; } case COLOR_FMT_NV12_BPP10_UBWC: { /*w*h*1.33*1.5/factor(factor=width>1920?2.38:1.58)*/ if (cvp_desc->fullres_width <= 1920) { /*w*h*1.33*1.5/1.58 = w*h*5/4*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 5)>>2); } else { /*w*h*1.33*1.5/1.61 = w*h*79/64*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 79)>>6); } break; } default: dprintk(CVP_ERR, "Defaulting to linear P010\n"); /*w*h*1.5*2 COLOR_FMT_P010*/ ds_pixel_read = (cvp_desc->fullres_width * cvp_desc->fullres_height * 3); } } else { process_width = cvp_desc->fullres_width; process_height = cvp_desc->fullres_height; num_16x16_blocks = (process_width>>4)*(process_height>>4); hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; } dme_cycles = NUM_CYCLES16X16_DME_FRAME * NUM_DME_MAX_FEATURE_POINTS; ncc_cycles = NUM_CYCLES16X16_NCC_FRAME * NUM_DME_MAX_FEATURE_POINTS; cvp_cycles = dme_cycles + ds_cycles + hcd_cycles + ncc_cycles; cvp_cycles = cvp_cycles + (cvp_cycles>>CYCLES_MARGIN_IN_POWEROF2); cvp_voting->clock_cycles_a = cvp_cycles * cvp_desc->fps; cvp_voting->clock_cycles_b = 0; cvp_voting->reserved[0] = NUM_CYCLESFW_FRAME * cvp_desc->fps; cvp_voting->reserved[1] = cvp_cycles * cvp_desc->op_rate; cvp_voting->reserved[2] = 0; cvp_voting->reserved[3] = NUM_CYCLESFW_FRAME*cvp_desc->op_rate; if (process_width <= 1920) { /*w*h*1.5(for filter fetch overhead)/1.58=w*h*(3/2)*(5/8)*/ hcd_pixel_read = ((process_width * process_height * 15)>>4); /*num_16x16_blocks*8*4*/ hcd_stats_write = (num_16x16_blocks<<5); /*NUM_DME_MAX_FEATURE_POINTS*96*48/1.58*/ dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 2880; /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/1.58*/ ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1040; } else { /*w*h*1.5(for filter fetch overhead)/2.38=w*h*(3/2)*(54/128)*/ hcd_pixel_read = ((process_width * process_height * 81)>>7); /*num_16x16_blocks*8*4*/ hcd_stats_write = (num_16x16_blocks<<5); /*NUM_DME_MAX_FEATURE_POINTS*96*48/2.38*/ dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1944; /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/2.38*/ ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 702; } cvp_bw = ds_pixel_read + ds_pixel_write + hcd_pixel_read + hcd_stats_write + dme_pixel_read + ncc_pixel_read; cvp_voting->ddr_bw = cvp_bw * cvp_desc->fps; cvp_voting->reserved[4] = cvp_bw * cvp_desc->op_rate; dprintk(CVP_DBG, "%s Voting cycles_a, b, bw: %d %d %d\n", __func__, cvp_voting->clock_cycles_a, cvp_voting->clock_cycles_b, cvp_voting->ddr_bw); dprintk(CVP_ERR, "Deprecated cvp func %s\n", __func__); return 0; } EXPORT_SYMBOL(msm_cvp_est_cycles); Loading drivers/media/platform/msm/cvp/msm_cvp_core.h +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <media/msm_cvp_private.h> #include <media/msm_cvp_vidc.h> #include "msm_cvp_buf.h" #include "msm_cvp_synx.h" enum core_id { MSM_CORE_CVP = 0, Loading Loading
drivers/media/platform/msm/cvp/Makefile +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ msm-cvp-objs := cvp.o \ cvp_core_hfi.o \ msm_cvp_clocks.o \ msm_cvp_dsp.o \ msm_cvp_buf.o msm_cvp_buf.o \ msm_cvp_synx.o obj-$(CONFIG_MSM_CVP) := msm-cvp.o
drivers/media/platform/msm/cvp/cvp_comm_def.h 0 → 100644 +24 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #ifndef _MSM_COMM_DEF_H_ #define _MSM_COMM_DEF_H_ #include <linux/types.h> enum op_mode { OP_NORMAL, OP_DRAINING, OP_FLUSH, OP_INVALID, }; enum queue_state { QUEUE_INIT, QUEUE_ACTIVE = 1, QUEUE_STOP = 2, QUEUE_INVALID, }; #endif
drivers/media/platform/msm/cvp/msm_cvp.c +50 −466 Original line number Diff line number Diff line Loading @@ -278,19 +278,16 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q, return true; } static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, static int cvp_fence_dme(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { int i; int rc = 0; unsigned long timeout; int h_synx; u64 ktid; unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; struct synx_session ssid; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; Loading @@ -298,29 +295,10 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; i = 0; while (i < HFI_DME_BUF_NUM - 1) { h_synx = synx[i]; if (h_synx) { rc = synx_wait(ssid, h_synx, timeout_ms); if (rc) { dprintk(CVP_ERR, "%s %s: synx_wait %d failed\n", current->comm, __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) goto exit; } /* * Increase loop count to skip fence * waiting on downscale image where i == 1. */ if (i == FENCE_DME_ICA_ENABLED_IDX) ++i; } ++i; } rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); Loading Loading @@ -357,40 +335,21 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst, u32 *synx, } exit: if (synx[FENCE_DME_ICA_ENABLED_IDX]) { h_synx = synx[FENCE_DME_DS_IDX]; rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", current->comm, __func__, FENCE_DME_DS_IDX); synx_state = SYNX_STATE_SIGNALED_ERROR; } } h_synx = synx[FENCE_DME_OUTPUT_IDX]; rc = synx_signal(ssid, h_synx, synx_state); if (rc) dprintk(CVP_ERR, "%s %s: synx_signal %d failed\n", current->comm, __func__, FENCE_DME_OUTPUT_IDX); rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, static int cvp_fence_proc(struct msm_cvp_inst *inst, struct cvp_fence_command *fc, struct cvp_hfi_cmd_session_hdr *pkt) { int i; int rc = 0; unsigned long timeout; int h_synx; u64 ktid; unsigned long timeout_ms = 1000; int synx_state = SYNX_STATE_SIGNALED_SUCCESS; struct cvp_hfi_device *hdev; struct cvp_session_queue *sq; struct synx_session ssid; u32 in, out; u32 hfi_err = HFI_ERR_NONE; struct cvp_hfi_msg_session_hdr *hdr; Loading @@ -398,34 +357,10 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, hdev = inst->core->device; sq = &inst->session_queue_fence; ssid = inst->synx_session_id; ktid = pkt->client_data.kdata; in = synx[0] >> 16; out = synx[0] & 0xFFFF; i = 1; while (i <= in) { h_synx = synx[i]; if (h_synx) { rc = synx_wait(ssid, h_synx, timeout_ms); if (rc) { synx_state = synx_get_status(ssid, h_synx); if (synx_state == SYNX_STATE_SIGNALED_CANCEL) { dprintk(CVP_DBG, "%s: synx_wait %d cancel %d state %d\n", current->comm, i, rc, synx_state); } else { dprintk(CVP_ERR, "%s: synx_wait %d failed %d state %d\n", current->comm, i, rc, synx_state); synx_state = SYNX_STATE_SIGNALED_ERROR; } if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) goto exit; } } ++i; } rc = call_hfi_op(hdev, session_send, (void *)inst->session, (struct cvp_kmd_hfi_packet *)pkt); Loading Loading @@ -458,19 +393,7 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst, u32 *synx, } exit: i = in + 1; while (i <= in + out) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", current->comm, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } ++i; } rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state); return rc; } Loading Loading @@ -501,119 +424,6 @@ static void cvp_free_fence_data(struct cvp_fence_command *f) f = NULL; } static int cvp_import_synx(struct msm_cvp_inst *inst, u32 type, u32 *fence, u32 *synx) { int rc = 0; int i; int start = 0, end = 0; struct cvp_fence_type *f; struct synx_import_params params; s32 h_synx; struct synx_session ssid; f = (struct cvp_fence_type *)fence; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 0; end = HFI_DME_BUF_NUM; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in = fence[0]; u32 out = fence[1]; if (in > MAX_HFI_FENCE_SIZE || out > MAX_HFI_FENCE_SIZE || in > MAX_HFI_FENCE_SIZE - out) { dprintk(CVP_ERR, "%s: failed!\n", __func__); rc = -EINVAL; return rc; } synx[0] = (in << 16) | out; start = 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = f[i].h_synx; if (h_synx) { params.h_synx = h_synx; params.secure_key = f[i].secure_key; params.new_h_synx = &synx[i]; rc = synx_import(ssid, ¶ms); if (rc) { dprintk(CVP_ERR, "%s: synx_import failed\n", __func__); return rc; } } } return rc; } static int cvp_release_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; s32 h_synx; struct synx_session ssid; int start = 0, end = 0; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 0; end = HFI_DME_BUF_NUM; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in = synx[0] >> 16; u32 out = synx[0] & 0xFFFF; start = 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_release(ssid, h_synx); if (rc) dprintk(CVP_ERR, "%s: synx_release %d failed\n", __func__, i); } } return rc; } static int cvp_fence_thread(void *data) { int rc = 0; Loading Loading @@ -656,10 +466,10 @@ static int cvp_fence_thread(void *data) switch (f->type) { case HFI_CMD_SESSION_CVP_DME_FRAME: rc = cvp_fence_dme(inst, synx, pkt); rc = cvp_fence_dme(inst, f, pkt); break; case HFI_CMD_SESSION_CVP_FD_FRAME: rc = cvp_fence_proc(inst, synx, pkt); rc = cvp_fence_proc(inst, f, pkt); break; default: dprintk(CVP_ERR, "%s: unknown hfi cmd type 0x%x\n", Loading @@ -670,7 +480,7 @@ static int cvp_fence_thread(void *data) } mutex_lock(&q->lock); cvp_release_synx(inst, f->type, synx); cvp_release_synx(inst, f); list_del_init(&f->list); mutex_unlock(&q->lock); Loading @@ -693,6 +503,8 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, int rc = 0; int idx; struct cvp_kmd_hfi_fence_packet *fence_pkt; struct cvp_kmd_hfi_synx_packet *synx_pkt; struct cvp_kmd_fence_ctrl *kfc; struct cvp_hfi_cmd_session_hdr *pkt; unsigned int offset, buf_num, in_offset, in_buf_num; struct msm_cvp_inst *s; Loading Loading @@ -727,7 +539,6 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, fence_pkt = &arg->data.hfi_fence_pkt; pkt = (struct cvp_hfi_cmd_session_hdr *)&fence_pkt->pkt_data; fence = (u32 *)&fence_pkt->fence_data; idx = get_pkt_index((struct cvp_hal_session_cmd_pkt *)pkt); if (idx < 0 || pkt->size > MAX_HFI_FENCE_OFFSET) { Loading Loading @@ -758,16 +569,29 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, goto exit; f->type = cvp_hfi_defs[idx].type; f->frame_id = arg->data.hfi_fence_pkt.frame_id; f->mode = OP_NORMAL; synx_pkt = &arg->data.hfi_synx_pkt; if (synx_pkt->fence_data[0] != 0xFEEDFACE) { fence = (u32 *)&fence_pkt->fence_data; f->frame_id = arg->data.hfi_fence_pkt.frame_id; } else { kfc = &synx_pkt->fc; fence = (u32 *)&kfc->fences; f->frame_id = kfc->frame_id; f->signature = 0xFEEDFACE; f->num_fences = kfc->num_fences; f->output_index = kfc->output_index; } dprintk(CVP_DBG, "%s: frameID %llu\n", __func__, f->frame_id); memcpy(f->pkt, pkt, pkt->size); f->pkt->client_data.kdata |= FENCE_BIT; rc = cvp_import_synx(inst, f->type, fence, f->synx); rc = cvp_import_synx(inst, f, fence); if (rc) { kfree(f); goto exit; Loading Loading @@ -897,77 +721,6 @@ static void aggregate_power_update(struct msm_cvp_core *core, rt_pwr->bw_sum += bw_sum[1]; } static void aggregate_power_request(struct msm_cvp_core *core, struct cvp_power_level *nrt_pwr, struct cvp_power_level *rt_pwr, unsigned int max_clk_rate) { struct msm_cvp_inst *inst; int i; unsigned long core_sum[2] = {0}, ctlr_sum[2] = {0}, fw_sum[2] = {0}; unsigned long op_core_max[2] = {0}, op_ctlr_max[2] = {0}; unsigned long op_fw_max[2] = {0}, bw_sum[2] = {0}, op_bw_max[2] = {0}; list_for_each_entry(inst, &core->instances, list) { if (inst->state == MSM_CVP_CORE_INVALID || inst->state == MSM_CVP_CORE_UNINIT || is_subblock_profile_existed(inst)) continue; if (inst->prop.priority <= CVP_RT_PRIO_THRESHOLD) { /* Non-realtime session use index 0 */ i = 0; } else { i = 1; } dprintk(CVP_PROF, "pwrReq sess %pK core %u ctl %u fw %u\n", inst, inst->power.clock_cycles_a, inst->power.clock_cycles_b, inst->power.reserved[0]); dprintk(CVP_PROF, "pwrReq op_core %u op_ctl %u op_fw %u\n", inst->power.reserved[1], inst->power.reserved[2], inst->power.reserved[3]); core_sum[i] += inst->power.clock_cycles_a; ctlr_sum[i] += inst->power.clock_cycles_b; fw_sum[i] += inst->power.reserved[0]; op_core_max[i] = (op_core_max[i] >= inst->power.reserved[1]) ? op_core_max[i] : inst->power.reserved[1]; op_ctlr_max[i] = (op_ctlr_max[i] >= inst->power.reserved[2]) ? op_ctlr_max[i] : inst->power.reserved[2]; op_fw_max[i] = (op_fw_max[i] >= inst->power.reserved[3]) ? op_fw_max[i] : inst->power.reserved[3]; bw_sum[i] += inst->power.ddr_bw; op_bw_max[i] = (op_bw_max[i] >= inst->power.reserved[4]) ? op_bw_max[i] : inst->power.reserved[4]; } for (i = 0; i < 2; i++) { core_sum[i] = max_3(core_sum[i], ctlr_sum[i], fw_sum[i]); op_core_max[i] = max_3(op_core_max[i], op_ctlr_max[i], op_fw_max[i]); op_core_max[i] = (op_core_max[i] > max_clk_rate) ? max_clk_rate : op_core_max[i]; bw_sum[i] = (bw_sum[i] >= op_bw_max[i]) ? bw_sum[i] : op_bw_max[i]; } nrt_pwr->core_sum += core_sum[0]; nrt_pwr->op_core_sum = (nrt_pwr->op_core_sum >= op_core_max[0]) ? nrt_pwr->op_core_sum : op_core_max[0]; nrt_pwr->bw_sum += bw_sum[0]; rt_pwr->core_sum += core_sum[1]; rt_pwr->op_core_sum = (rt_pwr->op_core_sum >= op_core_max[1]) ? rt_pwr->op_core_sum : op_core_max[1]; rt_pwr->bw_sum += bw_sum[1]; } /** * adjust_bw_freqs(): calculate CVP clock freq and bw required to sustain * required use case. Loading Loading @@ -1006,10 +759,6 @@ static int adjust_bw_freqs(void) max_bw = bus->range[1]; min_bw = max_bw/10; aggregate_power_request(core, &nrt_pwr, &rt_pwr, cvp_max_rate); dprintk(CVP_DBG, "PwrReq nrt %u %u rt %u %u\n", nrt_pwr.core_sum, nrt_pwr.op_core_sum, rt_pwr.core_sum, rt_pwr.op_core_sum); aggregate_power_update(core, &nrt_pwr, &rt_pwr, cvp_max_rate); dprintk(CVP_DBG, "PwrUpdate nrt %u %u rt %u %u\n", nrt_pwr.core_sum, nrt_pwr.op_core_sum, Loading Loading @@ -1069,64 +818,6 @@ static int adjust_bw_freqs(void) return rc; } /** * Use of cvp_kmd_request_power structure * clock_cycles_a: CVP core clock freq * clock_cycles_b: CVP controller clock freq * ddr_bw: b/w vote in Bps * reserved[0]: CVP firmware required clock freq * reserved[1]: CVP core operational clock freq * reserved[2]: CVP controller operational clock freq * reserved[3]: CVP firmware operational clock freq * reserved[4]: CVP operational b/w vote * * session's power record only saves normalized freq or b/w vote */ static int msm_cvp_request_power(struct msm_cvp_inst *inst, struct cvp_kmd_request_power *power) { int rc = 0; struct msm_cvp_core *core; struct msm_cvp_inst *s; if (!inst || !power) { dprintk(CVP_ERR, "%s: invalid params\n", __func__); return -EINVAL; } s = cvp_get_inst_validate(inst->core, inst); if (!s) return -ECONNRESET; inst->cur_cmd_type = CVP_KMD_REQUEST_POWER; core = inst->core; mutex_lock(&core->lock); memcpy(&inst->power, power, sizeof(*power)); /* Normalize CVP controller clock freqs */ inst->power.clock_cycles_b = div_by_1dot5(inst->power.clock_cycles_b); inst->power.reserved[0] = div_by_1dot5(inst->power.reserved[0]); inst->power.reserved[2] = div_by_1dot5(inst->power.reserved[2]); inst->power.reserved[3] = div_by_1dot5(inst->power.reserved[3]); /* Convert bps to KBps */ inst->power.ddr_bw = inst->power.ddr_bw >> 10; rc = adjust_bw_freqs(); if (rc) { memset(&inst->power, 0x0, sizeof(inst->power)); dprintk(CVP_ERR, "Instance %pK power request out of range\n"); } mutex_unlock(&core->lock); inst->cur_cmd_type = 0; cvp_put_inst(s); return rc; } static int msm_cvp_update_power(struct msm_cvp_inst *inst) { int rc = 0; Loading Loading @@ -1430,7 +1121,7 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, struct cvp_kmd_sys_properties *props = &arg->data.sys_properties; struct cvp_hfi_device *hdev; struct iris_hfi_device *hfi; int rc = 0; int i, rc = 0; if (!inst || !inst->core || !inst->core->device) { dprintk(CVP_ERR, "%s: invalid params\n", __func__); Loading @@ -1440,17 +1131,19 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst, hdev = inst->core->device; hfi = hdev->hfi_device_data; switch (props->prop_data.prop_type) { for (i = 0; i < props->prop_num; i++) { switch (props->prop_data[i].prop_type) { case CVP_KMD_PROP_HFI_VERSION: { props->prop_data.data = hfi->version; props->prop_data[i].data = hfi->version; break; } default: dprintk(CVP_ERR, "unrecognized sys property %d\n", props->prop_data.prop_type); props->prop_data[i].prop_type); rc = -EFAULT; } } return rc; } Loading @@ -1473,7 +1166,7 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return -E2BIG; } prop_array = &arg->data.sys_properties.prop_data; prop_array = &arg->data.sys_properties.prop_data[0]; session_prop = &inst->prop; for (i = 0; i < props->prop_num; i++) { Loading Loading @@ -1549,107 +1242,6 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst, return rc; } static int cvp_cancel_input_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; int h_synx; struct synx_session ssid; int start = 0, end = 0; int synx_state = SYNX_STATE_SIGNALED_CANCEL; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = 1; end = HFI_DME_BUF_NUM - 1; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in, out; in = synx[0] >> 16; out = synx[0] & 0xFFFF; start = 1; end = in + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc && rc != -EALREADY) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } } return rc; } static int cvp_cancel_output_synx(struct msm_cvp_inst *inst, u32 type, u32 *synx) { int rc = 0; int i; int h_synx; struct synx_session ssid; int start = 0, end = 0; int synx_state = SYNX_STATE_SIGNALED_CANCEL; ssid = inst->synx_session_id; switch (type) { case HFI_CMD_SESSION_CVP_DME_FRAME: { start = FENCE_DME_OUTPUT_IDX; end = FENCE_DME_OUTPUT_IDX + 1; break; } case HFI_CMD_SESSION_CVP_FD_FRAME: { u32 in, out; in = synx[0] >> 16; out = synx[0] & 0xFFFF; start = in + 1; end = in + out + 1; break; } default: dprintk(CVP_ERR, "%s: unknown fence type\n", __func__); rc = -EINVAL; return rc; } for (i = start; i < end; ++i) { h_synx = synx[i]; if (h_synx) { rc = synx_signal(ssid, h_synx, synx_state); if (rc) { dprintk(CVP_ERR, "%s: synx_signal %d failed\n", __func__, i); synx_state = SYNX_STATE_SIGNALED_ERROR; } } } return rc; } static int cvp_drain_fence_cmd_queue_partial(struct msm_cvp_inst *inst) { unsigned long wait_time; Loading Loading @@ -1790,8 +1382,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); cvp_cancel_output_synx(inst, f->type, f->synx); cvp_release_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); cvp_release_synx(inst, f); cvp_free_fence_data(f); } Loading @@ -1802,7 +1394,7 @@ static int cvp_flush_all(struct msm_cvp_inst *inst) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); cvp_cancel_input_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); Loading Loading @@ -1906,8 +1498,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) list_del_init(&f->list); msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata); cvp_cancel_output_synx(inst, f->type, f->synx); cvp_release_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f); cvp_release_synx(inst, f); cvp_free_fence_data(f); } Loading @@ -1921,7 +1513,7 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id) __func__, ktid); dprintk(CVP_DBG, "%s: flush frameID %llu from sched_list\n", __func__, f->frame_id); cvp_cancel_input_synx(inst, f->type, f->synx); cvp_cancel_synx(inst, CVP_INPUT_SYNX, f); } mutex_unlock(&q->lock); Loading Loading @@ -1969,14 +1561,6 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg) rc = msm_cvp_get_session_info(inst, session); break; } case CVP_KMD_REQUEST_POWER: { struct cvp_kmd_request_power *power = (struct cvp_kmd_request_power *)&arg->data.req_power; rc = msm_cvp_request_power(inst, power); break; } case CVP_KMD_UPDATE_POWER: { rc = msm_cvp_update_power(inst); Loading
drivers/media/platform/msm/cvp/msm_cvp_core.c +1 −138 Original line number Diff line number Diff line Loading @@ -29,144 +29,7 @@ int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc, struct cvp_kmd_request_power *cvp_voting) { unsigned int cvp_cycles = 0; unsigned int hcd_cycles = 0; unsigned int dme_cycles = 0; unsigned int ds_cycles = 0; unsigned int ncc_cycles = 0; unsigned int num_16x16_blocks = 0; unsigned int cvp_bw = 0; unsigned int ds_pixel_read = 0; unsigned int ds_pixel_write = 0; unsigned int hcd_pixel_read = 0; unsigned int hcd_stats_write = 0; unsigned int dme_pixel_read = 0; unsigned int ncc_pixel_read = 0; unsigned int process_width = 0; unsigned int process_height = 0; if (!cvp_desc || !cvp_voting) { dprintk(CVP_ERR, "%s: invalid args\n", __func__); return -EINVAL; } if (cvp_desc->is_downscale) { num_16x16_blocks = (cvp_desc->fullres_width>>4) * (cvp_desc->fullres_height>>4); ds_cycles = NUM_CYCLES16X16_DS_FRAME * num_16x16_blocks; process_width = cvp_desc->downscale_width; process_height = cvp_desc->downscale_height; num_16x16_blocks = (process_width>>4)*(process_height>>4); hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; /*Estimate downscale output (always UBWC) BW stats*/ if (cvp_desc->fullres_width <= 1920) { /*w*h/1.58=w*h*(81/128)*/ ds_pixel_write = ((process_width*process_height*81)>>7); } else { /*w*h/2.38=w*h*(54/128)*/ ds_pixel_write = ((process_width*process_height*54)>>7); } /*Estimate downscale input BW stats based on colorfmt*/ switch (cvp_desc->colorfmt) { case COLOR_FMT_NV12: { /*w*h*1.5*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 3)>>1); break; } case COLOR_FMT_P010: { /*w*h*2*1.5*/ ds_pixel_read = cvp_desc->fullres_width * cvp_desc->fullres_height * 3; break; } case COLOR_FMT_NV12_UBWC: { /*w*h*1.5/factor(factor=width>1920?2.38:1.58)*/ if (cvp_desc->fullres_width <= 1920) { /*w*h*1.5/1.58 = w*h*121/128*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 121)>>7); } else { /*w*h*1.5/1.61 = w*h*119/128*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 119)>>7); } break; } case COLOR_FMT_NV12_BPP10_UBWC: { /*w*h*1.33*1.5/factor(factor=width>1920?2.38:1.58)*/ if (cvp_desc->fullres_width <= 1920) { /*w*h*1.33*1.5/1.58 = w*h*5/4*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 5)>>2); } else { /*w*h*1.33*1.5/1.61 = w*h*79/64*/ ds_pixel_read = ((cvp_desc->fullres_width * cvp_desc->fullres_height * 79)>>6); } break; } default: dprintk(CVP_ERR, "Defaulting to linear P010\n"); /*w*h*1.5*2 COLOR_FMT_P010*/ ds_pixel_read = (cvp_desc->fullres_width * cvp_desc->fullres_height * 3); } } else { process_width = cvp_desc->fullres_width; process_height = cvp_desc->fullres_height; num_16x16_blocks = (process_width>>4)*(process_height>>4); hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks; } dme_cycles = NUM_CYCLES16X16_DME_FRAME * NUM_DME_MAX_FEATURE_POINTS; ncc_cycles = NUM_CYCLES16X16_NCC_FRAME * NUM_DME_MAX_FEATURE_POINTS; cvp_cycles = dme_cycles + ds_cycles + hcd_cycles + ncc_cycles; cvp_cycles = cvp_cycles + (cvp_cycles>>CYCLES_MARGIN_IN_POWEROF2); cvp_voting->clock_cycles_a = cvp_cycles * cvp_desc->fps; cvp_voting->clock_cycles_b = 0; cvp_voting->reserved[0] = NUM_CYCLESFW_FRAME * cvp_desc->fps; cvp_voting->reserved[1] = cvp_cycles * cvp_desc->op_rate; cvp_voting->reserved[2] = 0; cvp_voting->reserved[3] = NUM_CYCLESFW_FRAME*cvp_desc->op_rate; if (process_width <= 1920) { /*w*h*1.5(for filter fetch overhead)/1.58=w*h*(3/2)*(5/8)*/ hcd_pixel_read = ((process_width * process_height * 15)>>4); /*num_16x16_blocks*8*4*/ hcd_stats_write = (num_16x16_blocks<<5); /*NUM_DME_MAX_FEATURE_POINTS*96*48/1.58*/ dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 2880; /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/1.58*/ ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1040; } else { /*w*h*1.5(for filter fetch overhead)/2.38=w*h*(3/2)*(54/128)*/ hcd_pixel_read = ((process_width * process_height * 81)>>7); /*num_16x16_blocks*8*4*/ hcd_stats_write = (num_16x16_blocks<<5); /*NUM_DME_MAX_FEATURE_POINTS*96*48/2.38*/ dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1944; /*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/2.38*/ ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 702; } cvp_bw = ds_pixel_read + ds_pixel_write + hcd_pixel_read + hcd_stats_write + dme_pixel_read + ncc_pixel_read; cvp_voting->ddr_bw = cvp_bw * cvp_desc->fps; cvp_voting->reserved[4] = cvp_bw * cvp_desc->op_rate; dprintk(CVP_DBG, "%s Voting cycles_a, b, bw: %d %d %d\n", __func__, cvp_voting->clock_cycles_a, cvp_voting->clock_cycles_b, cvp_voting->ddr_bw); dprintk(CVP_ERR, "Deprecated cvp func %s\n", __func__); return 0; } EXPORT_SYMBOL(msm_cvp_est_cycles); Loading
drivers/media/platform/msm/cvp/msm_cvp_core.h +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <media/msm_cvp_private.h> #include <media/msm_cvp_vidc.h> #include "msm_cvp_buf.h" #include "msm_cvp_synx.h" enum core_id { MSM_CORE_CVP = 0, Loading