/* * This function executes in interrupt context. */ static int msm_isp_notify_vfe(struct v4l2_subdev *sd, unsigned int notification, void *arg) { int rc = 0; struct v4l2_event v4l2_evt; struct msm_isp_event_ctrl *isp_event; struct msm_cam_media_controller *pmctl = (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd); struct msm_free_buf buf; if (!pmctl) { pr_err("%s: no context in dsp callback.\n", __func__); rc = -EINVAL; return rc; } if (notification == NOTIFY_VFE_BUF_EVT) return msm_isp_notify_VFE_BUF_EVT(sd, arg); if (notification == NOTIFY_VFE_BUF_FREE_EVT) return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg); isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC); if (!isp_event) { pr_err("%s Insufficient memory. return", __func__); return -ENOMEM; } v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_STAT_EVT_MSG; v4l2_evt.id = 0; *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event; isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG; isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG; isp_event->isp_data.isp_msg.len = 0; switch (notification) { case NOTIFY_ISP_MSG_EVT: { struct isp_msg_event *isp_msg = (struct isp_msg_event *)arg; isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id; isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count; getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp)); break; } case NOTIFY_VFE_MSG_OUT: { uint8_t msgid; struct msm_cam_buf_handle buf_handle; struct isp_msg_output *isp_output = (struct isp_msg_output *)arg; if (!isp_output->buf.inst_handle) { switch (isp_output->output_id) { case MSG_ID_OUTPUT_P: msgid = VFE_MSG_OUTPUT_P; break; case MSG_ID_OUTPUT_V: msgid = VFE_MSG_OUTPUT_V; break; case MSG_ID_OUTPUT_T: msgid = VFE_MSG_OUTPUT_T; break; case MSG_ID_OUTPUT_S: msgid = VFE_MSG_OUTPUT_S; break; case MSG_ID_OUTPUT_PRIMARY: msgid = VFE_MSG_OUTPUT_PRIMARY; break; case MSG_ID_OUTPUT_SECONDARY: msgid = VFE_MSG_OUTPUT_SECONDARY; break; case MSG_ID_OUTPUT_TERTIARY1: msgid = VFE_MSG_OUTPUT_TERTIARY1; break; case MSG_ID_OUTPUT_TERTIARY2: msgid = VFE_MSG_OUTPUT_TERTIARY2; break; default: pr_err("%s: Invalid VFE output id: %d\n", __func__, isp_output->output_id); rc = -EINVAL; break; } if (!rc) { buf_handle.buf_lookup_type = BUF_LOOKUP_BY_IMG_MODE; buf_handle.image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, msgid); } } else { buf_handle.buf_lookup_type = BUF_LOOKUP_BY_INST_HANDLE; buf_handle.inst_handle = isp_output->buf.inst_handle; } isp_event->isp_data.isp_msg.msg_id = isp_output->output_id; isp_event->isp_data.isp_msg.frame_id = isp_output->frameCounter; buf = isp_output->buf; msm_mctl_buf_done(pmctl, &buf_handle, &buf, isp_output->frameCounter); } break; case NOTIFY_VFE_MSG_COMP_STATS: { struct msm_stats_buf *stats = (struct msm_stats_buf *)arg; struct msm_stats_buf *stats_buf = NULL; isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE; stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->aec.buff, &(stats->aec.fd)); stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->awb.buff, &(stats->awb.fd)); stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->af.buff, &(stats->af.fd)); stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->ihist.buff, &(stats->ihist.fd)); stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->rs.buff, &(stats->rs.fd)); stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->cs.buff, &(stats->cs.fd)); stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = *stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } break; case NOTIFY_VFE_MSG_STATS: { struct msm_stats_buf stats; struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg; memset(&stats, 0, sizeof(stats)); isp_event->isp_data.isp_msg.msg_id = isp_stats->id; isp_event->isp_data.isp_msg.frame_id = isp_stats->frameCounter; stats.buffer = isp_stats->buffer; stats.fd = isp_stats->fd; /* buf_idx used for O(0) lookup */ stats.buf_idx = isp_stats->buf_idx; switch (isp_stats->id) { case MSG_ID_STATS_AEC: case MSG_ID_STATS_BG: stats.aec.buff = stats.buffer; stats.aec.fd = stats.fd; break; case MSG_ID_STATS_AF: case MSG_ID_STATS_BF: stats.af.buff = stats.buffer; stats.af.fd = stats.fd; break; case MSG_ID_STATS_AWB: stats.awb.buff = stats.buffer; stats.awb.fd = stats.fd; break; case MSG_ID_STATS_IHIST: stats.ihist.buff = stats.buffer; stats.ihist.fd = stats.fd; break; case MSG_ID_STATS_RS: stats.rs.buff = stats.buffer; stats.rs.fd = stats.fd; break; case MSG_ID_STATS_CS: stats.cs.buff = stats.buffer; stats.cs.fd = stats.fd; break; case MSG_ID_STATS_BHIST: stats.skin.buff = stats.buffer; stats.skin.fd = stats.fd; break; case MSG_ID_STATS_AWB_AEC: break; default: pr_err("%s: Invalid msg type", __func__); break; } if (!stats.buffer) { pr_err("%s: msm_pmem_stats_ptov_lookup error\n", __func__); isp_event->isp_data.isp_msg.len = 0; rc = -EFAULT; } else { struct msm_stats_buf *stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory. stats_id = %d\n", __func__, isp_stats->id); rc = -ENOMEM; } else { *stats_buf = stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } } break; default: pr_err("%s: Unsupport isp notification %d\n", __func__, notification); rc = -EINVAL; break; } v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev, &v4l2_evt); return rc; }
static int msm_isp_notify_vfe(struct v4l2_subdev *sd, unsigned int notification, void *arg) { int rc = 0; struct v4l2_event v4l2_evt; struct msm_isp_event_ctrl *isp_event; struct msm_cam_media_controller *pmctl = (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd); struct msm_free_buf buf; unsigned long pphy; int newWidth; int newHeight; if (!pmctl) { pr_err("%s: no context in dsp callback.\n", __func__); rc = -EINVAL; return rc; } if (notification == NOTIFY_VFE_BUF_EVT) return msm_isp_notify_VFE_BUF_EVT(sd, arg); if (notification == NOTIFY_VFE_BUF_FREE_EVT) return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg); isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC); if (!isp_event) { pr_err("%s Insufficient memory. return", __func__); return -ENOMEM; } v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_STAT_EVT_MSG; *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event; isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG; isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG; isp_event->isp_data.isp_msg.len = 0; switch (notification) { case NOTIFY_ISP_MSG_EVT: { struct isp_msg_event *isp_msg = (struct isp_msg_event *)arg; if (!isp_msg) { pr_err("%s: null pointer check, line(%d)", __func__, __LINE__); rc = -EINVAL; return rc; } isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id; isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count; getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp)); if(atomic_read(&pmctl->dropframe_enabled) && atomic_read(&pmctl->snap_dropframe_num) == 0 && isp_msg->msg_id == MSG_ID_SOF_ACK) { isp_event->isp_data.isp_msg.msg_id = MSG_ID_HDR_SOF_ACK; pr_info("%s MSG_ID_HDR_SOF_ACK", __func__); } break; } case NOTIFY_VFE_MSG_OUT: { int8_t msgid; int image_mode; struct isp_msg_output *isp_output = (struct isp_msg_output *)arg; if (!isp_output) { pr_err("%s: null pointer check, line(%d)", __func__, __LINE__); rc = -EINVAL; return rc; } switch (isp_output->output_id) { case MSG_ID_OUTPUT_P: msgid = VFE_MSG_OUTPUT_P; break; case MSG_ID_OUTPUT_V: msgid = VFE_MSG_OUTPUT_V; break; case MSG_ID_OUTPUT_T: msgid = VFE_MSG_OUTPUT_T; break; case MSG_ID_OUTPUT_S: msgid = VFE_MSG_OUTPUT_S; break; case MSG_ID_OUTPUT_PRIMARY: msgid = VFE_MSG_OUTPUT_PRIMARY; break; case MSG_ID_OUTPUT_SECONDARY: msgid = VFE_MSG_OUTPUT_SECONDARY; break; default: pr_err("%s: Invalid VFE output id: %d\n", __func__, isp_output->output_id); rc = -EINVAL; break; } if (!rc) { if (msm_isp_should_drop_frame(pmctl, msgid)) { msgid = msm_isp_vfe_msg_to_img_mode(pmctl, msgid); msm_mctl_return_free_buf(pmctl, msgid, &(isp_output->buf)); kfree(isp_event); return rc; } else { isp_event->isp_data.isp_msg.msg_id = isp_output->output_id; isp_event->isp_data.isp_msg.frame_id = isp_output->frameCounter; buf = isp_output->buf; image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, msgid); BUG_ON(image_mode < 0); msm_mctl_buf_done(pmctl, image_mode , &buf, isp_output->frameCounter); } } } break; case NOTIFY_VFE_MSG_COMP_STATS: { struct msm_stats_buf *stats = (struct msm_stats_buf *)arg; struct msm_stats_buf *stats_buf = NULL; if (!stats) { pr_err("%s: null pointer check, line(%d)", __func__, __LINE__); rc = -EINVAL; return rc; } isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE; stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->aec.buff, &(stats->aec.fd)); stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->awb.buff, &(stats->awb.fd)); stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->af.buff, &(stats->af.fd)); stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->ihist.buff, &(stats->ihist.fd)); stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->rs.buff, &(stats->rs.fd)); stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->cs.buff, &(stats->cs.fd)); stats->skin.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->skin.buff, &(stats->skin.fd)); stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = *stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } break; case NOTIFY_VFE_MSG_STATS: { struct msm_stats_buf stats; struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg; if (!isp_stats) { pr_err("%s: null pointer check, line(%d)", __func__, __LINE__); rc = -EINVAL; return rc; } isp_event->isp_data.isp_msg.msg_id = isp_stats->id; isp_event->isp_data.isp_msg.frame_id = isp_stats->frameCounter; #ifdef CONFIG_ARCH_MSM8X60 stats.frame_id = isp_stats->frameCounter; #endif stats.buffer = msm_pmem_stats_ptov_lookup(pmctl, isp_stats->buffer, &(stats.fd)); switch (isp_stats->id) { case MSG_ID_STATS_AEC: case MSG_ID_STATS_BG: stats.aec.buff = stats.buffer; stats.aec.fd = stats.fd; break; case MSG_ID_STATS_AF: stats.af.buff = stats.buffer; stats.af.fd = stats.fd; break; case MSG_ID_STATS_BF: newWidth = 0; newHeight = 0; stats.htc_af_info.af_input.af_use_sw_sharpness = false; if (pmctl->htc_af_info.af_input.af_use_sw_sharpness) { pphy = msm_pmem_stats_ptov_lookup_2(pmctl, isp_stats->buffer, &(stats.fd)); memset((uint8_t *)(pphy+BAYER_FOCUS_BUF_SIZE), 0x00, SW_FOCUS_BUF_SIZE); rc = swfa_Transform2((uint8_t *)(pphy+BAYER_FOCUS_BUF_SIZE), &newWidth, &newHeight); if(!rc) stats.htc_af_info.af_input.af_use_sw_sharpness = false; else stats.htc_af_info.af_input.af_use_sw_sharpness = pmctl->htc_af_info.af_input.af_use_sw_sharpness; } stats.htc_af_info.af_input.preview_width = pmctl->htc_af_info.af_input.preview_width; stats.htc_af_info.af_input.preview_height = pmctl->htc_af_info.af_input.preview_height; stats.htc_af_info.af_input.roi_x = pmctl->htc_af_info.af_input.roi_x; stats.htc_af_info.af_input.roi_y = pmctl->htc_af_info.af_input.roi_y; stats.htc_af_info.af_input.roi_width = newWidth; stats.htc_af_info.af_input.roi_height = newHeight; stats.af.buff = stats.buffer; stats.af.fd = stats.fd; break; case MSG_ID_STATS_AWB: stats.awb.buff = stats.buffer; stats.awb.fd = stats.fd; break; case MSG_ID_STATS_IHIST: stats.ihist.buff = stats.buffer; stats.ihist.fd = stats.fd; break; case MSG_ID_STATS_RS: stats.rs.buff = stats.buffer; stats.rs.fd = stats.fd; break; case MSG_ID_STATS_CS: stats.cs.buff = stats.buffer; stats.cs.fd = stats.fd; break; case MSG_ID_STATS_BHIST: stats.skin.buff = stats.buffer; stats.skin.fd = stats.fd; break; case MSG_ID_STATS_AWB_AEC: break; default: pr_err("%s: Invalid msg type", __func__); break; } if (!stats.buffer) { pr_err("%s: msm_pmem_stats_ptov_lookup error\n", __func__); isp_event->isp_data.isp_msg.len = 0; rc = -EFAULT; } else { struct msm_stats_buf *stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } } break; default: pr_err("%s: Unsupport isp notification %d\n", __func__, notification); rc = -EINVAL; break; } if (!pmctl->config_device) { pr_err("%s: null pointer check, line(%d)", __func__, __LINE__); rc = -EINVAL; return rc; } v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev, &v4l2_evt); return rc; }
/* * This function executes in interrupt context. */ static int msm_isp_notify_vfe(struct v4l2_subdev *sd, unsigned int notification, void *arg) { int rc = 0; struct v4l2_event v4l2_evt; struct msm_isp_event_ctrl *isp_event; struct msm_sync *sync = (struct msm_sync *)v4l2_get_subdev_hostdata(sd); struct msm_cam_media_controller *pmctl = NULL; struct msm_free_buf buf; if (!sync) { pr_err("%s: no context in dsp callback.\n", __func__); rc = -EINVAL; return rc; } pmctl = &sync->pcam_sync->mctl; if (notification == NOTIFY_VFE_BUF_EVT) return msm_isp_notify_VFE_BUF_EVT(sd, arg); isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC); if (!isp_event) { pr_err("%s Insufficient memory. return", __func__); return -ENOMEM; } v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_STAT_EVT_MSG; *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event; isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG; isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG; isp_event->isp_data.isp_msg.len = 0; switch (notification) { case NOTIFY_ISP_MSG_EVT: { struct isp_msg_event *isp_msg = (struct isp_msg_event *)arg; isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id; isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count; break; } case NOTIFY_VFE_MSG_OUT: { uint8_t msgid; struct isp_msg_output *isp_output = (struct isp_msg_output *)arg; switch (isp_output->output_id) { case MSG_ID_OUTPUT_P: msgid = VFE_MSG_OUTPUT_P; break; case MSG_ID_OUTPUT_V: msgid = VFE_MSG_OUTPUT_V; break; case MSG_ID_OUTPUT_T: msgid = VFE_MSG_OUTPUT_T; break; case MSG_ID_OUTPUT_S: msgid = VFE_MSG_OUTPUT_S; break; default: pr_err("%s: Invalid VFE output id: %d\n", __func__, isp_output->output_id); rc = -EINVAL; break; } if (!rc) { isp_event->isp_data.isp_msg.msg_id = isp_output->output_id; isp_event->isp_data.isp_msg.frame_id = isp_output->frameCounter; buf = isp_output->buf; msm_mctl_buf_done(pmctl, msgid, &buf, isp_output->frameCounter); } } break; case NOTIFY_VFE_MSG_STATS: { struct msm_stats_buf stats; struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg; isp_event->isp_data.isp_msg.msg_id = isp_stats->id; isp_event->isp_data.isp_msg.frame_id = isp_stats->frameCounter; stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync, isp_stats->buffer, &(stats.fd)); if (!stats.buffer) { pr_err("%s: msm_pmem_stats_ptov_lookup error\n", __func__); isp_event->isp_data.isp_msg.len = 0; rc = -EFAULT; } else { struct msm_stats_buf *stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } } break; default: pr_err("%s: Unsupport isp notification %d\n", __func__, notification); rc = -EINVAL; break; } v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev, &v4l2_evt); return rc; }
/* This will enqueue ISP events or signal buffer completion */ static int msm_isp_enqueue(struct msm_cam_media_controller *pmctl, struct msm_vfe_resp *data, enum msm_queue qtype) { struct v4l2_event v4l2_evt; struct msm_stats_buf stats; struct msm_isp_stats_event_ctrl *isp_event; isp_event = (struct msm_isp_stats_event_ctrl *)v4l2_evt.u.data; if (!data) { D("%s !!!!data = 0x%p\n", __func__, data); return -EINVAL; } D("%s data->type = %d\n", __func__, data->type); switch (qtype) { case MSM_CAM_Q_VFE_EVT: case MSM_CAM_Q_VFE_MSG: /* adsp event and message */ v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_STAT_EVT_MSG; isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG; /* 0 - msg from aDSP, 1 - event from mARM */ isp_event->isp_data.isp_msg.type = data->evt_msg.type; isp_event->isp_data.isp_msg.msg_id = data->evt_msg.msg_id; isp_event->isp_data.isp_msg.len = data->evt_msg.len; D("%s: qtype %d length %d msd_id %d\n", __func__, qtype, isp_event->isp_data.isp_msg.len, isp_event->isp_data.isp_msg.msg_id); if ((data->type >= VFE_MSG_STATS_AEC) && (data->type <= VFE_MSG_STATS_WE)) { D("%s data->phy.sbuf_phy = 0x%x\n", __func__, data->phy.sbuf_phy); stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync, data->phy.sbuf_phy, &(stats.fd)); if (!stats.buffer) { pr_err("%s: msm_pmem_stats_ptov_lookup error\n", __func__); isp_event->isp_data.isp_msg.len = 0; } else { memcpy((void *)isp_event->isp_data.isp_msg.data, &stats, sizeof(struct msm_stats_buf)); isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); } } else if ((data->evt_msg.len > 0) && (data->evt_msg.len <= 48) && /* only 48 bytes */ (data->type == VFE_MSG_GENERAL)) { memcpy((void *)isp_event->isp_data.isp_msg.data, data->evt_msg.data, data->evt_msg.len); } else if (data->type == VFE_MSG_OUTPUT_P || data->type == VFE_MSG_OUTPUT_V || data->type == VFE_MSG_OUTPUT_S || data->type == VFE_MSG_OUTPUT_T) { msm_mctl_buf_done(pmctl, data->type, (u32)data->phy.y_phy); } break; default: break; } /* now queue the event */ v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev, &v4l2_evt); return 0; }
/* * This function executes in interrupt context. */ static int msm_isp_notify_vfe(struct v4l2_subdev *sd, unsigned int notification, void *arg) { int rc = 0; struct v4l2_event v4l2_evt; struct msm_isp_event_ctrl *isp_event; struct msm_cam_media_controller *pmctl = (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd); struct msm_free_buf buf; if (!pmctl) { pr_err("%s: no context in dsp callback.\n", __func__); rc = -EINVAL; return rc; } if (notification == NOTIFY_VFE_BUF_EVT) return msm_isp_notify_VFE_BUF_EVT(sd, arg); if (notification == NOTIFY_VFE_BUF_FREE_EVT) return msm_isp_notify_VFE_BUF_FREE_EVT(sd, arg); isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC); if (!isp_event) { pr_err("%s Insufficient memory. return", __func__); return -ENOMEM; } v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_STAT_EVT_MSG; *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event; isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG; isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG; isp_event->isp_data.isp_msg.len = 0; switch (notification) { case NOTIFY_ISP_MSG_EVT: { struct isp_msg_event *isp_msg = (struct isp_msg_event *)arg; isp_event->isp_data.isp_msg.msg_id = isp_msg->msg_id; isp_event->isp_data.isp_msg.frame_id = isp_msg->sof_count; getnstimeofday(&(isp_event->isp_data.isp_msg.timestamp)); /* HTC_START */ if(atomic_read(&pmctl->dropframe_enabled) && atomic_read(&pmctl->snap_dropframe_num) == 0 && isp_msg->msg_id == MSG_ID_SOF_ACK) { isp_event->isp_data.isp_msg.msg_id = MSG_ID_HDR_SOF_ACK; pr_info("%s MSG_ID_HDR_SOF_ACK", __func__); } /* HTC_END */ break; } case NOTIFY_VFE_MSG_OUT: { /* HTC_START (klockwork issue)*/ int8_t msgid; /* HTC_END */ struct isp_msg_output *isp_output = (struct isp_msg_output *)arg; switch (isp_output->output_id) { case MSG_ID_OUTPUT_P: msgid = VFE_MSG_OUTPUT_P; break; case MSG_ID_OUTPUT_V: msgid = VFE_MSG_OUTPUT_V; break; case MSG_ID_OUTPUT_T: msgid = VFE_MSG_OUTPUT_T; break; case MSG_ID_OUTPUT_S: msgid = VFE_MSG_OUTPUT_S; break; case MSG_ID_OUTPUT_PRIMARY: msgid = VFE_MSG_OUTPUT_PRIMARY; break; case MSG_ID_OUTPUT_SECONDARY: msgid = VFE_MSG_OUTPUT_SECONDARY; break; default: pr_err("%s: Invalid VFE output id: %d\n", __func__, isp_output->output_id); rc = -EINVAL; break; } if (!rc) { /* HTC_START */ if (msm_isp_should_drop_frame(pmctl, msgid)) { msgid = msm_isp_vfe_msg_to_img_mode(pmctl, msgid); /* return dropped frame buffer to free_vq directly */ msm_mctl_return_free_buf(pmctl, msgid, &(isp_output->buf)); return rc; } else { /* HTC_END */ isp_event->isp_data.isp_msg.msg_id = isp_output->output_id; isp_event->isp_data.isp_msg.frame_id = isp_output->frameCounter; buf = isp_output->buf; msgid = msm_isp_vfe_msg_to_img_mode(pmctl, msgid); /* HTC_START (klockwork issue)*/ if(msgid<0) { BUG_ON(msgid < 0); return -EINVAL; } /* HTC_END */ msm_mctl_buf_done(pmctl, msgid, &buf, isp_output->frameCounter); /* HTC_START */ } /* HTC_END */ } } break; case NOTIFY_VFE_MSG_COMP_STATS: { struct msm_stats_buf *stats = (struct msm_stats_buf *)arg; struct msm_stats_buf *stats_buf = NULL; isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE; stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->aec.buff, &(stats->aec.fd)); stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->awb.buff, &(stats->awb.fd)); stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->af.buff, &(stats->af.fd)); stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->ihist.buff, &(stats->ihist.fd)); stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->rs.buff, &(stats->rs.fd)); stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl, stats->cs.buff, &(stats->cs.fd)); stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = *stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } break; case NOTIFY_VFE_MSG_STATS: { struct msm_stats_buf stats; struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg; isp_event->isp_data.isp_msg.msg_id = isp_stats->id; isp_event->isp_data.isp_msg.frame_id = isp_stats->frameCounter; stats.buffer = msm_pmem_stats_ptov_lookup(pmctl, isp_stats->buffer, &(stats.fd)); switch (isp_stats->id) { case MSG_ID_STATS_AEC: stats.aec.buff = stats.buffer; stats.aec.fd = stats.fd; break; case MSG_ID_STATS_AF: stats.af.buff = stats.buffer; stats.af.fd = stats.fd; break; case MSG_ID_STATS_AWB: stats.awb.buff = stats.buffer; stats.awb.fd = stats.fd; break; case MSG_ID_STATS_IHIST: stats.ihist.buff = stats.buffer; stats.ihist.fd = stats.fd; break; case MSG_ID_STATS_RS: stats.rs.buff = stats.buffer; stats.rs.fd = stats.fd; break; case MSG_ID_STATS_CS: stats.cs.buff = stats.buffer; stats.cs.fd = stats.fd; break; case MSG_ID_STATS_AWB_AEC: break; default: pr_err("%s: Invalid msg type", __func__); break; } if (!stats.buffer) { pr_err("%s: msm_pmem_stats_ptov_lookup error\n", __func__); isp_event->isp_data.isp_msg.len = 0; rc = -EFAULT; } else { struct msm_stats_buf *stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC); if (!stats_buf) { pr_err("%s: out of memory.\n", __func__); rc = -ENOMEM; } else { *stats_buf = stats; isp_event->isp_data.isp_msg.len = sizeof(struct msm_stats_buf); isp_event->isp_data.isp_msg.data = stats_buf; } } } break; default: pr_err("%s: Unsupport isp notification %d\n", __func__, notification); rc = -EINVAL; break; } v4l2_event_queue(pmctl->config_device->config_stat_event_queue.pvdev, &v4l2_evt); return rc; }