u32 ddl_open(u32 **ddl_handle, u32 decoding) { struct ddl_context *ddl_context; struct ddl_client_context *ddl; void *ptr; u32 status; DDL_MSG_HIGH("ddl_open"); if (!ddl_handle) { DDL_MSG_ERROR("ddl_open:Bad_handle"); return VCD_ERR_BAD_HANDLE; } ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_open:Not_inited"); return VCD_ERR_ILLEGAL_OP; } status = ddl_client_transact(DDL_GET_CLIENT, &ddl); if (status) { DDL_MSG_ERROR("ddl_open:Client_trasac_failed"); return status; } ptr = ddl_pmem_alloc(&ddl->shared_mem[0], DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32)); if (!ptr) status = VCD_ERR_ALLOC_FAIL; if (!status && ddl_context->frame_channel_depth == VCD_DUAL_FRAME_COMMAND_CHANNEL) { ptr = ddl_pmem_alloc(&ddl->shared_mem[1], DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32)); if (!ptr) { ddl_pmem_free(&ddl->shared_mem[0]); status = VCD_ERR_ALLOC_FAIL; } } if (!status) { memset(ddl->shared_mem[0].align_virtual_addr, 0, DDL_FW_AUX_HOST_CMD_SPACE_SIZE); if (ddl_context->frame_channel_depth == VCD_DUAL_FRAME_COMMAND_CHANNEL) { memset(ddl->shared_mem[1].align_virtual_addr, 0, DDL_FW_AUX_HOST_CMD_SPACE_SIZE); } DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_OPEN", ddl_get_state_string(ddl->client_state)); ddl->client_state = DDL_CLIENT_OPEN; ddl->codec_data.hdr.decoding = decoding; ddl->decoding = decoding; ddl_set_default_meta_data_hdr(ddl); ddl_set_initial_default_values(ddl); *ddl_handle = (u32 *) ddl; } else { ddl_pmem_free(&ddl->shared_mem[0]); if (ddl_context->frame_channel_depth == VCD_DUAL_FRAME_COMMAND_CHANNEL) ddl_pmem_free(&ddl->shared_mem[1]); ddl_client_transact(DDL_FREE_CLIENT, &ddl); } return status; }
u32 ddl_encode_end(u32 *ddl_handle, void *client_data) { struct ddl_client_context *ddl = (struct ddl_client_context *) ddl_handle; struct ddl_context *ddl_context; DDL_MSG_HIGH("ddl_encode_end"); ddl_reset_core_time_variables(ENC_OP_TIME); ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_enc_end:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (DDL_IS_BUSY(ddl_context)) { DDL_MSG_ERROR("ddl_enc_end:Ddl_busy"); return VCD_ERR_BUSY; } if (!ddl || ddl->decoding) { DDL_MSG_ERROR("ddl_enc_end:Bad_handle"); return VCD_ERR_BAD_HANDLE; } if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME) && !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODEC) && !DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_FAVIDC_ERROR)) { DDL_MSG_ERROR("ddl_enc_end:Wrong_state"); return VCD_ERR_ILLEGAL_OP; } if (!ddl_take_command_channel(ddl_context, ddl, client_data)) return VCD_ERR_BUSY; ddl_vidc_channel_end(ddl); return VCD_S_SUCCESS; }
static int res_trk_pmem_alloc (struct ddl_buf_addr *addr, size_t sz, u32 alignment) { u32 alloc_size; struct ddl_context *ddl_context; int rc = 0; DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz); if (!addr) { DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__); rc = -EINVAL; goto bail_out; } ddl_context = ddl_get_context(); res_trk_set_mem_type(addr->mem_type); alloc_size = (sz + alignment); if (res_trk_get_enable_ion()) { if (!res_trk_is_cp_enabled() || !res_trk_check_for_sec_session()) { if (!ddl_context->video_ion_client) ddl_context->video_ion_client = res_trk_get_ion_client(); if (!ddl_context->video_ion_client) { DDL_MSG_ERROR( "%s() :DDL ION Client Invalid handle\n", __func__); rc = -ENOMEM; goto bail_out; } alloc_size = (alloc_size+4095) & ~4095; addr->alloc_handle = ion_alloc( ddl_context->video_ion_client, alloc_size, SZ_4K, res_trk_get_mem_type()); if (IS_ERR_OR_NULL(addr->alloc_handle)) { DDL_MSG_ERROR("%s() :DDL ION alloc failed\n", __func__); rc = -ENOMEM; goto bail_out; } } else { addr->alloc_handle = NULL; addr->alloced_phys_addr = PIL_FW_BASE_ADDR; addr->buffer_size = sz; } } else { addr->alloced_phys_addr = (phys_addr_t) allocate_contiguous_memory_nomap(alloc_size, res_trk_get_mem_type(), SZ_4K); if (!addr->alloced_phys_addr) { DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n", __func__, alloc_size); rc = -ENOMEM; goto bail_out; } addr->buffer_size = sz; return rc; } bail_out: return rc; }
static void ddl_sys_init_done_callback(struct ddl_context *ddl_context, u32 fw_size) { u32 vcd_status = VCD_S_SUCCESS; u8 *fw_ver; DDL_MSG_MED("ddl_sys_init_done_callback"); if (!DDLCOMMAND_STATE_IS(ddl_context, DDL_CMD_DMA_INIT)) { DDL_MSG_ERROR("UNKNOWN_SYS_INIT_DONE"); } else { ddl_context->cmd_state = DDL_CMD_INVALID; DDL_MSG_LOW("SYS_INIT_DONE"); vidc_1080p_get_fw_version(&ddl_context->fw_version); fw_ver = (u8 *)&ddl_context->fw_version; DDL_MSG_ERROR("fw_version %x:%x:20%x", fw_ver[1]&0xFF, fw_ver[0]&0xFF, fw_ver[2]&0xFF); if (ddl_context->fw_memory_size >= fw_size) { ddl_context->device_state = DDL_DEVICE_INITED; vcd_status = VCD_S_SUCCESS; } else vcd_status = VCD_ERR_FAIL; ddl_context->ddl_callback(VCD_EVT_RESP_DEVICE_INIT, vcd_status, NULL, 0, NULL, ddl_context->client_data); DDL_IDLE(ddl_context); } }
u32 ddl_device_release(void *client_data) { struct ddl_context *ddl_context; DDL_MSG_HIGH("ddl_device_release"); ddl_context = ddl_get_context(); if (!DDL_IS_IDLE(ddl_context)) { DDL_MSG_ERROR("ddl_dev_rel:Ddl_busy"); return VCD_ERR_BUSY; } if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_dev_rel:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (!ddl_client_transact(DDL_ACTIVE_CLIENT, NULL)) { DDL_MSG_ERROR("ddl_dev_rel:Client_present_err"); return VCD_ERR_CLIENT_PRESENT; } DDL_BUSY(ddl_context); ddl_context->device_state = DDL_DEVICE_NOTINIT; ddl_context->client_data = client_data; ddl_context->cmd_state = DDL_CMD_INVALID; ddl_vidc_core_term(ddl_context); DDL_MSG_LOW("FW_ENDDONE"); ddl_context->core_virtual_base_addr = NULL; ddl_release_context_buffers(ddl_context); ddl_context->video_ion_client = NULL; DDL_IDLE(ddl_context); return VCD_S_SUCCESS; }
u32 ddl_close(u32 **ddl_handle) { struct ddl_context *ddl_context; struct ddl_client_context **pp_ddl = (struct ddl_client_context **)ddl_handle; DDL_MSG_HIGH("ddl_close"); if (!pp_ddl || !*pp_ddl) { DDL_MSG_ERROR("ddl_close:Bad_handle"); return VCD_ERR_BAD_HANDLE; } ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_close:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (!DDLCLIENT_STATE_IS(*pp_ddl, DDL_CLIENT_OPEN)) { DDL_MSG_ERROR("ddl_close:Not_in_open_state"); return VCD_ERR_ILLEGAL_OP; } ddl_pmem_free(&(*pp_ddl)->shared_mem[0]); if (ddl_context->frame_channel_depth == VCD_DUAL_FRAME_COMMAND_CHANNEL) ddl_pmem_free(&(*pp_ddl)->shared_mem[1]); DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_INVALID", ddl_get_state_string((*pp_ddl)->client_state)); (*pp_ddl)->client_state = DDL_CLIENT_INVALID; ddl_codec_type_transact(*pp_ddl, true, (enum vcd_codec)0); ddl_client_transact(DDL_FREE_CLIENT, pp_ddl); return VCD_S_SUCCESS; }
static u32 ddl_eos_frame_done_callback( struct ddl_client_context *ddl) { struct ddl_context *ddl_context = ddl->ddl_context; struct ddl_decoder_data *decoder = &ddl->codec_data.decoder; struct ddl_mask *dpb_mask = &decoder->dpb_mask; u32 ret_status = true, rsl_chg; enum vidc_1080p_display_status disp_status; if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) { DDL_MSG_ERROR("STATE-CRITICAL-EOSFRMRUN"); ddl_client_fatal_cb(ddl); } else { DDL_MSG_LOW("EOS_FRM_RUN_DONE"); ddl->cmd_state = DDL_CMD_INVALID; get_dec_status(&ddl->codec_data.decoder.dec_disp_info, ddl->codec_data.decoder.output_order, &disp_status, &rsl_chg); ddl_vidc_decode_dynamic_property(ddl, false); if (disp_status == VIDC_1080P_DISPLAY_STATUS_DPB_EMPTY) { ddl_decoder_eos_done_callback(ddl); } else { struct vidc_1080p_dec_frame_start_param dec_param; ret_status = false; if (disp_status == VIDC_1080P_DISPLAY_STATUS_DISPLAY_ONLY) { if (ddl_decoder_output_done_callback( ddl, false)) ret_status = true; } else if (disp_status != VIDC_1080P_DISPLAY_STATUS_NOOP) DDL_MSG_ERROR("EOS-STATE-CRITICAL-" "WRONG-DISP-STATUS"); if (!ret_status) { ddl_decoder_dpb_transact(decoder, NULL, DDL_DPB_OP_SET_MASK); ddl->cmd_state = DDL_CMD_EOS; memset(&dec_param, 0, sizeof(dec_param)); dec_param.cmd_seq_num = ++ddl_context->cmd_seq_num; dec_param.inst_id = ddl->instance_id; dec_param.shared_mem_addr_offset = DDL_ADDR_OFFSET( ddl_context->dram_base_a, ddl->shared_mem[ddl->command_channel]); dec_param.release_dpb_bit_mask = dpb_mask->hw_mask; dec_param.decode = VIDC_1080P_DEC_TYPE_LAST_FRAME_DATA; ddl_context->vidc_decode_frame_start[ddl->\ command_channel](&dec_param); } } } return ret_status; }
void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment) { u32 alloc_size, offset = 0, flags = 0; u32 index = 0; struct ddl_context *ddl_context; struct msm_mapped_buffer *mapped_buffer = NULL; DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz); if (!addr) { DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__); goto bail_out; } ddl_context = ddl_get_context(); alloc_size = (sz + alignment); addr->alloced_phys_addr = (phys_addr_t) allocate_contiguous_memory_nomap(alloc_size, res_trk_get_mem_type(), SZ_4K); if (!addr->alloced_phys_addr) { DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n", __func__, alloc_size); goto bail_out; } flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR; if (alignment == DDL_KILO_BYTE(128)) index = 1; else if (alignment > SZ_4K) flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K; addr->mapped_buffer = msm_subsystem_map_buffer((unsigned long)addr->alloced_phys_addr, alloc_size, flags, &vidc_mmu_subsystem[index], sizeof(vidc_mmu_subsystem[index])/sizeof(unsigned int)); if (IS_ERR(addr->mapped_buffer)) { pr_err(" %s() buffer map failed", __func__); goto free_acm_alloc; } mapped_buffer = addr->mapped_buffer; if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) { pr_err("%s() map buffers failed\n", __func__); goto free_map_buffers; } addr->physical_base_addr = (u8 *)mapped_buffer->iova[0]; addr->virtual_base_addr = mapped_buffer->vaddr; addr->align_physical_addr = (u8 *) DDL_ALIGN((u32) addr->physical_base_addr, alignment); offset = (u32)(addr->align_physical_addr - addr->physical_base_addr); addr->align_virtual_addr = addr->virtual_base_addr + offset; addr->buffer_size = sz; return addr->virtual_base_addr; free_map_buffers: msm_subsystem_unmap_buffer(addr->mapped_buffer); addr->mapped_buffer = NULL; free_acm_alloc: free_contiguous_memory_by_paddr( (unsigned long)addr->alloced_phys_addr); addr->alloced_phys_addr = (phys_addr_t)NULL; bail_out: return NULL; }
u32 ddl_set_property(u32 *ddl_handle, struct vcd_property_hdr *property_hdr, void *property_value) { struct ddl_context *ddl_context; struct ddl_client_context *ddl = (struct ddl_client_context *) ddl_handle; u32 vcd_status; DDL_MSG_HIGH("ddl_set_property"); if (!property_hdr || !property_value) { DDL_MSG_ERROR("ddl_set_prop:Bad_argument"); return VCD_ERR_ILLEGAL_PARM; } ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_set_prop:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (!ddl) { DDL_MSG_ERROR("ddl_set_prop:Bad_handle"); return VCD_ERR_BAD_HANDLE; } if (ddl->decoding) vcd_status = ddl_set_dec_property(ddl, property_hdr, property_value); else vcd_status = ddl_set_enc_property(ddl, property_hdr, property_value); if (vcd_status) DDL_MSG_ERROR("ddl_set_prop:FAILED"); return vcd_status; }
static u32 ddl_handle_client_fatal_errors( struct ddl_client_context_type *p_ddl) { struct ddl_context_type *p_ddl_context = p_ddl->p_ddl_context; u32 b_status = FALSE; switch (p_ddl_context->n_cmd_err_status) { case VIDC_1080P_ERROR_UNSUPPORTED_FEATURE_IN_PROFILE: case VIDC_1080P_ERROR_RESOLUTION_NOT_SUPPORTED: case VIDC_1080P_ERROR_FRAME_RATE_NOT_SUPPORTED: case VIDC_1080P_ERROR_INVALID_QP_VALUE: case VIDC_1080P_ERROR_INVALID_RC_REACTION_COEFFICIENT: case VIDC_1080P_ERROR_INVALID_CPB_SIZE_AT_GIVEN_LEVEL: case VIDC_1080P_ERROR_ALLOC_DPB_SIZE_NOT_SUFFICIENT: case VIDC_1080P_ERROR_NUM_DPB_OUT_OF_RANGE: case VIDC_1080P_ERROR_NULL_METADATA_INPUT_POINTER: case VIDC_1080P_ERROR_NULL_DPB_POINTER: case VIDC_1080P_ERROR_NULL_OTH_EXT_BUFADDR: case VIDC_1080P_ERROR_NULL_MV_POINTER: b_status = TRUE; DDL_MSG_ERROR("VIDC_CLIENT_FATAL!!"); break; default: break; } if (!b_status) DDL_MSG_ERROR("VIDC_UNKNOWN_OP_FAILED"); ddl_client_fatal_cb(p_ddl); return TRUE; }
static void *res_trk_pmem_alloc (struct ddl_buf_addr *addr, size_t sz, u32 alignment) { u32 alloc_size; struct ddl_context *ddl_context; DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz); if (!addr) { DDL_MSG_ERROR("\n%s() Invalid Parameters", __func__); goto bail_out; } ddl_context = ddl_get_context(); res_trk_set_mem_type(addr->mem_type); alloc_size = (sz + alignment); if (res_trk_get_enable_ion()) { if (!ddl_context->video_ion_client) ddl_context->video_ion_client = res_trk_get_ion_client(); if (!ddl_context->video_ion_client) { DDL_MSG_ERROR("%s() :DDL ION Client Invalid handle\n", __func__); goto bail_out; } alloc_size = (alloc_size+4095) & ~4095; addr->alloc_handle = ion_alloc( ddl_context->video_ion_client, alloc_size, SZ_4K, res_trk_get_mem_type()); if (IS_ERR_OR_NULL(addr->alloc_handle)) { DDL_MSG_ERROR("%s() :DDL ION alloc failed\n", __func__); goto free_acm_ion_alloc; } return (void *) addr->alloc_handle; } else { addr->alloced_phys_addr = (phys_addr_t) allocate_contiguous_memory_nomap(alloc_size, res_trk_get_mem_type(), SZ_4K); if (!addr->alloced_phys_addr) { DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n", __func__, alloc_size); goto bail_out; } addr->buffer_size = sz; return (void *)addr->alloced_phys_addr; } free_acm_ion_alloc: if (ddl_context->video_ion_client) { if (addr->alloc_handle) { ion_free(ddl_context->video_ion_client, addr->alloc_handle); addr->alloc_handle = NULL; } } bail_out: return NULL; }
static void res_trk_pmem_free(struct ddl_buf_addr *addr) { struct ddl_context *ddl_context; if (!addr) { DDL_MSG_ERROR("\n%s() NULL address", __func__); return; } ddl_context = ddl_get_context(); if (ddl_context->video_ion_client) { if (addr->alloc_handle) { ion_free(ddl_context->video_ion_client, addr->alloc_handle); addr->alloc_handle = NULL; } } else { if (addr->mapped_buffer) msm_subsystem_unmap_buffer(addr->mapped_buffer); if (addr->alloced_phys_addr) free_contiguous_memory_by_paddr( (unsigned long)addr->alloced_phys_addr); } memset(addr, 0 , sizeof(struct ddl_buf_addr)); }
static u32 ddl_frame_run_callback(struct ddl_context *ddl_context) { struct ddl_client_context *ddl; u32 channel_inst_id; u32 return_status = true; vidc_1080p_get_returned_channel_inst_id(&channel_inst_id); vidc_1080p_clear_returned_channel_inst_id(); ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context, ddl_context->response_cmd_ch_id); if (ddl) { if (ddl->cmd_state == DDL_CMD_DECODE_FRAME) return_status = ddl_decoder_frame_run_callback(ddl); else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME) ddl_encoder_frame_run_callback(ddl); else if (ddl->cmd_state == DDL_CMD_EOS) return_status = ddl_eos_frame_done_callback(ddl); else { DDL_MSG_ERROR("UNKWN_FRAME_DONE"); return_status = false; } } else return_status = false; return return_status; }
static void ddl_handle_npf_decoding_error(struct ddl_client_context_type *p_ddl) { struct vidc_1080p_dec_disp_info_type *p_dec_disp_info = &(p_ddl->codec_data.decoder.dec_disp_info); if (!p_ddl->b_decoding) { DDL_MSG_ERROR("VIDC_FW_ISSUE_ENC_NPF"); ddl_client_fatal_cb(p_ddl); } else { vidc_sm_get_frame_tags( &p_ddl->shared_mem[p_ddl->n_command_channel], &p_dec_disp_info->n_tag_top, &p_dec_disp_info->n_tag_bottom); ddl_vidc_decode_dynamic_property(p_ddl, FALSE); p_ddl->output_frame.vcd_frm.n_ip_frm_tag = p_dec_disp_info->n_tag_top; p_ddl->output_frame.vcd_frm.p_physical = NULL; p_ddl->output_frame.vcd_frm.p_virtual = NULL; p_ddl->output_frame.b_frm_trans_end = FALSE; p_ddl->p_ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE, VCD_ERR_INTRLCD_FIELD_DROP, &(p_ddl->output_frame), sizeof(struct ddl_frame_data_type_tag), (u32 *) p_ddl, p_ddl->p_client_data); ddl_vidc_decode_frame_run(p_ddl); } }
static u32 ddl_encoder_seq_done_callback(struct ddl_context_type *p_ddl_context, struct ddl_client_context_type *p_ddl) { struct ddl_encoder_data_type *p_encoder; DDL_MSG_MED("ddl_encoder_seq_done_callback"); if (!DDLCLIENT_STATE_IS(p_ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) { DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC"); ddl_client_fatal_cb(p_ddl); return TRUE; } p_ddl->e_cmd_state = DDL_CMD_INVALID; DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_FRAME", ddl_get_state_string(p_ddl->e_client_state)); p_ddl->e_client_state = DDL_CLIENT_WAIT_FOR_FRAME; DDL_MSG_LOW("INIT_CODEC_DONE"); p_encoder = &p_ddl->codec_data.encoder; vidc_1080p_get_encoder_sequence_header_size( &p_encoder->n_seq_header_length); p_ddl_context->ddl_callback(VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL, 0, (u32 *) p_ddl, p_ddl->p_client_data); ddl_release_command_channel(p_ddl_context, p_ddl->n_command_channel); return TRUE; }
static u32 ddl_dpb_buffers_set_done_callback( struct ddl_context *ddl_context) { struct ddl_client_context *ddl; u32 channel_inst_id, ret_status = true; DDL_MSG_MED("ddl_dpb_buffers_set_done_callback"); vidc_1080p_get_returned_channel_inst_id(&channel_inst_id); vidc_1080p_clear_returned_channel_inst_id(); ddl = ddl_get_current_ddl_client_for_command(ddl_context, DDL_CMD_DECODE_SET_DPB); if (ddl) { ddl->cmd_state = DDL_CMD_INVALID; if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_DPBDONE)) { DDL_MSG_ERROR("STATE-CRITICAL-DPBDONE"); ddl_client_fatal_cb(ddl); } else { DDL_MSG_LOW("INTR_DPBDONE"); DDL_MSG_LOW("ddl_state_transition: %s ~~>" "DDL_CLIENT_WAIT_FOR_FRAME", ddl_get_state_string(ddl->client_state)); if (vidc_msg_timing) { ddl_calc_core_proc_time(__func__, DEC_OP_TIME); ddl_reset_core_time_variables(DEC_OP_TIME); } ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME; ddl_vidc_decode_frame_run(ddl); ret_status = false; } } return ret_status; }
static void ddl_encoder_eos_done(struct ddl_context *ddl_context) { struct ddl_client_context *ddl; u32 channel_inst_id; vidc_1080p_get_returned_channel_inst_id(&channel_inst_id); vidc_1080p_clear_returned_channel_inst_id(); ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context, ddl_context->response_cmd_ch_id); if (!ddl || (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE))) { DDL_MSG_ERROR("STATE-CRITICAL-EOSFRMDONE"); ddl_client_fatal_cb(ddl); } else { struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder); vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info); ddl_handle_enc_frame_done(ddl); DDL_MSG_LOW("encoder_eos_done"); ddl->cmd_state = DDL_CMD_INVALID; DDL_MSG_LOW("ddl_state_transition: %s ~~>" "DDL_CLIENT_WAIT_FOR_FRAME", ddl_get_state_string(ddl->client_state)); ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME; DDL_MSG_LOW("eos_done"); ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE, VCD_S_SUCCESS, NULL, 0, (u32 *)ddl, ddl->client_data); ddl_release_command_channel(ddl_context, ddl->command_channel); } }
static u32 ddl_encoder_seq_done_callback(struct ddl_context *ddl_context, struct ddl_client_context *ddl) { struct ddl_encoder_data *encoder; DDL_MSG_MED("ddl_encoder_seq_done_callback"); if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) { DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC"); ddl_client_fatal_cb(ddl); return true; } if (vidc_msg_timing) ddl_calc_core_proc_time(__func__, ENC_OP_TIME); ddl->cmd_state = DDL_CMD_INVALID; DDL_MSG_LOW("ddl_state_transition: %s ~~> DDL_CLIENT_WAIT_FOR_FRAME", ddl_get_state_string(ddl->client_state)); ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME; DDL_MSG_LOW("INIT_CODEC_DONE"); encoder = &ddl->codec_data.encoder; vidc_1080p_get_encoder_sequence_header_size( &encoder->seq_header_length); if ((encoder->codec.codec == VCD_CODEC_H264) && (encoder->profile.profile == VCD_PROFILE_H264_BASELINE)) if ((encoder->seq_header.align_virtual_addr) && (encoder->seq_header_length > 6)) encoder->seq_header.align_virtual_addr[6] = 0xC0; ddl_context->ddl_callback(VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL, 0, (u32 *) ddl, ddl->client_data); ddl_release_command_channel(ddl_context, ddl->command_channel); return true; }
static u32 ddl_get_decoded_frame(struct vcd_frame_data *frame, enum vidc_1080p_decode_frame frame_type) { u32 status = true; switch (frame_type) { case VIDC_1080P_DECODE_FRAMETYPE_I: frame->flags |= VCD_FRAME_FLAG_SYNCFRAME; frame->frame = VCD_FRAME_I; break; case VIDC_1080P_DECODE_FRAMETYPE_P: frame->frame = VCD_FRAME_P; break; case VIDC_1080P_DECODE_FRAMETYPE_B: frame->frame = VCD_FRAME_B; break; case VIDC_1080P_DECODE_FRAMETYPE_NOT_CODED: frame->frame = VCD_FRAME_NOTCODED; frame->data_len = 0; DDL_MSG_HIGH("DDL_INFO:Decoder:NotCodedFrame>"); break; case VIDC_1080P_DECODE_FRAMETYPE_OTHERS: frame->frame = VCD_FRAME_YUV; break; case VIDC_1080P_DECODE_FRAMETYPE_32BIT: default: DDL_MSG_ERROR("UNKNOWN-FRAMETYPE"); status = false; break; } return status; }
u32 ddl_get_property(u32 *ddl_handle, struct vcd_property_hdr *property_hdr, void *property_value) { struct ddl_context *ddl_context; struct ddl_client_context *ddl = (struct ddl_client_context *) ddl_handle; u32 vcd_status = VCD_ERR_ILLEGAL_PARM; DDL_MSG_HIGH("ddl_get_property"); if (!property_hdr || !property_value) return VCD_ERR_ILLEGAL_PARM; if (property_hdr->prop_id == DDL_I_CAPABILITY) { if (sizeof(struct ddl_property_capability) == property_hdr->sz) { struct ddl_property_capability *ddl_capability = (struct ddl_property_capability *) property_value; ddl_capability->max_num_client = VCD_MAX_NO_CLIENT; ddl_capability->exclusive = VCD_COMMAND_EXCLUSIVE; ddl_capability->frame_command_depth = VCD_FRAME_COMMAND_DEPTH; ddl_capability->general_command_depth = VCD_GENEVIDC_COMMAND_DEPTH; ddl_capability->ddl_time_out_in_ms = DDL_HW_TIMEOUT_IN_MS; vcd_status = VCD_S_SUCCESS; } return vcd_status; } ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) return VCD_ERR_ILLEGAL_OP; if (!ddl) return VCD_ERR_BAD_HANDLE; if (ddl->decoding) vcd_status = ddl_get_dec_property(ddl, property_hdr, property_value); else vcd_status = ddl_get_enc_property(ddl, property_hdr, property_value); if (vcd_status) DDL_MSG_ERROR("ddl_get_prop:FAILED"); else DDL_MSG_ERROR("ddl_get_prop:SUCCESS"); return vcd_status; }
u32 ddl_handle_core_errors(struct ddl_context_type *p_ddl_context) { struct ddl_client_context_type *p_ddl; u32 n_channel_inst_id, b_status = FALSE; if (!p_ddl_context->n_cmd_err_status && !p_ddl_context->n_disp_pic_err_status) { DDL_MSG_ERROR("VIDC_NO_ERROR"); } else { vidc_1080p_get_returned_channel_inst_id(&n_channel_inst_id); vidc_1080p_clear_returned_channel_inst_id(); p_ddl = ddl_get_current_ddl_client_for_channel_id(p_ddl_context, p_ddl_context->n_response_cmd_ch_id); if (!p_ddl) { DDL_MSG_ERROR("VIDC_SPURIOUS_INTERRUPT_ERROR"); b_status = TRUE; } else { u32 b_disp_status; if (p_ddl_context->n_cmd_err_status) print_core_errors( p_ddl_context->n_cmd_err_status); if (p_ddl_context->n_disp_pic_err_status) print_core_errors( p_ddl_context->n_disp_pic_err_status); b_status = ddl_handle_core_warnings( p_ddl_context->n_cmd_err_status); b_disp_status = ddl_handle_core_warnings( p_ddl_context->n_disp_pic_err_status); if (!b_status && !b_disp_status) { DDL_MSG_ERROR("ddl_warning:Unknown"); b_status = ddl_handle_hw_fatal_errors(p_ddl); if (!b_status) b_status = ddl_handle_core_recoverable_errors( p_ddl); if (!b_status) b_status = ddl_handle_client_fatal_errors(p_ddl); } } } return b_status; }
static void ddl_fw_status_done_callback(struct ddl_context_type *p_ddl_context) { DDL_MSG_MED("ddl_fw_status_done_callback"); if (!DDLCOMMAND_STATE_IS(p_ddl_context, DDL_CMD_DMA_INIT)) { DDL_MSG_ERROR("UNKWN_DMADONE"); } else { DDL_MSG_LOW("FW_STATUS_DONE"); vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_SYS_INIT, p_ddl_context->n_fw_ctxt_memory_size, 0, 0, 0); } }
u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header, void *client_data) { struct ddl_client_context *ddl = (struct ddl_client_context *) ddl_handle; struct ddl_context *ddl_context; struct ddl_decoder_data *decoder; u32 status = VCD_S_SUCCESS; DDL_MSG_HIGH("ddl_decode_start"); if (vidc_msg_timing) { ddl_reset_core_time_variables(DEC_OP_TIME); ddl_reset_core_time_variables(DEC_IP_TIME); } ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_dec_start:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (DDL_IS_BUSY(ddl_context)) { DDL_MSG_ERROR("ddl_dec_start:Ddl_busy"); return VCD_ERR_BUSY; } if (!ddl || !ddl->decoding) { DDL_MSG_ERROR("ddl_dec_start:Bad_handle"); return VCD_ERR_BAD_HANDLE; } if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) { DDL_MSG_ERROR("ddl_dec_start:Not_in_opened_state"); return VCD_ERR_ILLEGAL_OP; } if ((header) && ((!header->sequence_header_len) || (!header->sequence_header))) { DDL_MSG_ERROR("ddl_dec_start:Bad_param_seq_header"); return VCD_ERR_ILLEGAL_PARM; } if (!ddl_decoder_ready_to_start(ddl, header)) { DDL_MSG_ERROR("ddl_dec_start:Err_param_settings"); return VCD_ERR_ILLEGAL_OP; } decoder = &ddl->codec_data.decoder; status = ddl_allocate_dec_hw_buffers(ddl); if (status) return status; #ifdef DDL_BUF_LOG ddl_list_buffers(ddl); #endif if (!ddl_take_command_channel(ddl_context, ddl, client_data)) return VCD_ERR_BUSY; if (header) { decoder->header_in_start = true; decoder->decode_config = *header; } else { decoder->header_in_start = false; decoder->decode_config.sequence_header_len = 0; } ddl_vidc_channel_set(ddl); return status; }
u32 ddl_encode_start(u32 *ddl_handle, void *client_data) { struct ddl_client_context *ddl = (struct ddl_client_context *) ddl_handle; struct ddl_context *ddl_context; struct ddl_encoder_data *encoder; void *ptr; u32 status = VCD_S_SUCCESS; DDL_MSG_HIGH("ddl_encode_start"); #ifdef DDL_PROFILE if (first_time < 2) { ddl_reset_time_variables(1); first_time++; } ddl_get_core_start_time(1); #endif ddl_context = ddl_get_context(); if (!DDL_IS_INITIALIZED(ddl_context)) { DDL_MSG_ERROR("ddl_enc_start:Not_inited"); return VCD_ERR_ILLEGAL_OP; } if (DDL_IS_BUSY(ddl_context)) { DDL_MSG_ERROR("ddl_enc_start:Ddl_busy"); return VCD_ERR_BUSY; } if (!ddl || ddl->decoding) { DDL_MSG_ERROR("ddl_enc_start:Bad_handle"); return VCD_ERR_BAD_HANDLE; } if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) { DDL_MSG_ERROR("ddl_enc_start:Not_opened"); return VCD_ERR_ILLEGAL_OP; } if (!ddl_encoder_ready_to_start(ddl)) { DDL_MSG_ERROR("ddl_enc_start:Err_param_settings"); return VCD_ERR_ILLEGAL_OP; } encoder = &ddl->codec_data.encoder; status = ddl_allocate_enc_hw_buffers(ddl); if (status) return status; #ifdef DDL_BUF_LOG ddl_list_buffers(ddl); #endif ptr = ddl_pmem_alloc(&encoder->seq_header, DDL_ENC_SEQHEADER_SIZE, DDL_LINEAR_BUFFER_ALIGN_BYTES); if (!ptr) { ddl_free_enc_hw_buffers(ddl); DDL_MSG_ERROR("ddl_enc_start:Seq_hdr_alloc_failed"); return VCD_ERR_ALLOC_FAIL; } if (!ddl_take_command_channel(ddl_context, ddl, client_data)) return VCD_ERR_BUSY; ddl_vidc_channel_set(ddl); return status; }
void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment) { u32 alloc_size, offset = 0; DBG_PMEM("\n%s() IN: Requested alloc size(%u)", __func__, (u32)sz); alloc_size = (sz + alignment); addr->physical_base_addr = (u8 *) pmem_kalloc(alloc_size, PMEM_MEMTYPE_SMI | PMEM_ALIGNMENT_4K); if (!addr->physical_base_addr) { DDL_MSG_ERROR("%s() : pmem alloc failed (%d)\n", __func__, alloc_size); return NULL; } DDL_MSG_LOW("%s() : pmem alloc physical base addr/sz 0x%x / %d\n",\ __func__, (u32)addr->physical_base_addr, alloc_size); addr->virtual_base_addr = (u8 *)ioremap((unsigned long) addr->physical_base_addr, alloc_size); if (!addr->virtual_base_addr) { DDL_MSG_ERROR("%s() : ioremap failed, virtual(%x)\n", __func__, (u32)addr->virtual_base_addr); return NULL; } DDL_MSG_LOW("%s() : pmem alloc virtual base addr/sz 0x%x / %d\n",\ __func__, (u32)addr->virtual_base_addr, alloc_size); addr->align_physical_addr = (u8 *) DDL_ALIGN((u32) addr->physical_base_addr, alignment); offset = (u32)(addr->align_physical_addr - addr->physical_base_addr); addr->align_virtual_addr = addr->virtual_base_addr + offset; addr->buffer_size = sz; DDL_MSG_LOW("\n%s() : alig_phy_addr(%p) alig_vir_addr(%p)", __func__, addr->align_physical_addr, addr->align_virtual_addr); DBG_PMEM("\n%s() OUT: phy_addr(%p) vir_addr(%p) size(%u)", __func__, addr->physical_base_addr, addr->virtual_base_addr, addr->buffer_size); return addr->virtual_base_addr; }
u32 ddl_decoder_ready_to_start(struct ddl_client_context *ddl, struct vcd_sequence_hdr *header) { struct ddl_decoder_data *decoder = &(ddl->codec_data.decoder); if (!decoder->codec.codec) { DDL_MSG_ERROR("ddl_dec_start_check:Codec_not_set"); return false; } if ((!header) && (!decoder->client_frame_size.height || !decoder->client_frame_size.width)) { DDL_MSG_ERROR("ddl_dec_start_check:\ Client_height_width_default"); return false; }
static u32 ddl_channel_set_callback(struct ddl_context *ddl_context, u32 instance_id) { struct ddl_client_context *ddl; u32 ret = false; DDL_MSG_MED("ddl_channel_open_callback"); ddl = ddl_get_current_ddl_client_for_command(ddl_context, DDL_CMD_CHANNEL_SET); if (ddl) { ddl->cmd_state = DDL_CMD_INVALID; if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_CHDONE)) { DDL_MSG_ERROR("STATE-CRITICAL-CHSET"); ddl_release_command_channel(ddl_context, ddl->command_channel); } else { DDL_MSG_LOW("CH_SET_DONE"); DDL_MSG_LOW("ddl_state_transition: %s ~~>" "DDL_CLIENT_WAIT_FOR_INITCODEC", ddl_get_state_string(ddl->client_state)); ddl->client_state = DDL_CLIENT_WAIT_FOR_INITCODEC; ddl->instance_id = instance_id; if (ddl->decoding) { if (vidc_msg_timing) ddl_calc_core_proc_time(__func__, DEC_OP_TIME); if (ddl->codec_data.decoder.header_in_start) ddl_vidc_decode_init_codec(ddl); else { ddl_context->ddl_callback( VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL, 0, (u32 *)ddl, ddl->client_data); ddl_release_command_channel( ddl_context, ddl->command_channel); ret = true; } } else ddl_vidc_encode_init_codec(ddl); } } return ret; }
static u32 ddl_process_intr_status(struct ddl_context *ddl_context, u32 intr_status) { u32 return_status = true; switch (intr_status) { case VIDC_1080P_RISC2HOST_CMD_OPEN_CH_RET: return_status = ddl_channel_set_callback(ddl_context, ddl_context->response_cmd_ch_id); break; case VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET: ddl_channel_end_callback(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET: return_status = ddl_sequence_done_callback(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET: return_status = ddl_frame_run_callback(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET: ddl_sys_init_done_callback(ddl_context, ddl_context->response_cmd_ch_id); break; case VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET: ddl_fw_status_done_callback(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET: ddl_edfu_callback(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET: ddl_encoder_eos_done(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_ERROR_RET: DDL_MSG_ERROR("CMD_ERROR_INTR"); return_status = ddl_handle_core_errors(ddl_context); break; case VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET: return_status = ddl_dpb_buffers_set_done_callback(ddl_context); break; default: DDL_MSG_LOW("UNKWN_INTR"); break; } return return_status; }
static void ddl_decoder_eos_done_callback( struct ddl_client_context_type *p_ddl) { struct ddl_context_type *p_ddl_context = p_ddl->p_ddl_context; if (!p_ddl->b_decoding) { DDL_MSG_ERROR("STATE-CRITICAL-EOSDONE"); ddl_client_fatal_cb(p_ddl); } else { p_ddl->e_client_state = DDL_CLIENT_WAIT_FOR_FRAME; DDL_MSG_LOW("EOS_DONE"); p_ddl_context->ddl_callback(VCD_EVT_RESP_EOS_DONE, VCD_S_SUCCESS, NULL, 0, (u32 *)p_ddl, p_ddl->p_client_data); ddl_release_command_channel(p_ddl_context, p_ddl->n_command_channel); } }
static u32 ddl_channel_set_callback(struct ddl_context_type *p_ddl_context, u32 n_instance_id) { struct ddl_client_context_type *p_ddl; u32 b_ret = FALSE; DDL_MSG_MED("ddl_channel_open_callback"); p_ddl = ddl_get_current_ddl_client_for_command(p_ddl_context, DDL_CMD_CHANNEL_SET); if (p_ddl) { p_ddl->e_cmd_state = DDL_CMD_INVALID; if (!DDLCLIENT_STATE_IS(p_ddl, DDL_CLIENT_WAIT_FOR_CHDONE)) { DDL_MSG_ERROR("STATE-CRITICAL-CHSET"); ddl_release_command_channel(p_ddl_context, p_ddl->n_command_channel); } else { DDL_MSG_LOW("CH_SET_DONE"); DDL_MSG_LOW("ddl_state_transition: %s ~~>\ DDL_CLIENT_WAIT_FOR_INITCODEC", ddl_get_state_string(p_ddl->e_client_state)); p_ddl->e_client_state = DDL_CLIENT_WAIT_FOR_INITCODEC; p_ddl->n_channel_id = n_instance_id; if (p_ddl->b_decoding) { if (p_ddl->codec_data.decoder.b_header_in_start) ddl_vidc_decode_init_codec(p_ddl); else { p_ddl_context->ddl_callback( VCD_EVT_RESP_START, VCD_S_SUCCESS, NULL, 0, (u32 *)p_ddl, p_ddl->p_client_data); ddl_release_command_channel( p_ddl_context, p_ddl->n_command_channel); b_ret = TRUE; } } else ddl_vidc_encode_init_codec(p_ddl); } } return b_ret; }