Exemplo n.º 1
0
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_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;
}