diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 3bfb51760c2f..f26ac00c9a6e 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1735,7 +1735,7 @@ static void msm_cpp_set_micro_irq_mask(struct cpp_device *cpp_dev, static void msm_cpp_do_timeout_work(struct work_struct *work) { uint32_t j = 0, i = 0, i1 = 0, i2 = 0; - int32_t queue_len = 0, rc = 0; + int32_t queue_len = 0, rc = 0, fifo_counter = 0; struct msm_device_queue *queue = NULL; struct msm_cpp_frame_info_t *processed_frame[MAX_CPP_PROCESSING_FRAME]; struct cpp_device *cpp_dev = cpp_timer.data.cpp_dev; @@ -1775,12 +1775,7 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) cpp_timer.data.cpp_dev->fw_name_bin); if (rc) { pr_warn("Firmware loading failed\n"); - cpp_dev->state = CPP_STATE_OFF; - /* clean buf queue here */ - msm_cpp_flush_queue_and_release_buffer(cpp_dev, queue_len); - msm_cpp_set_micro_irq_mask(cpp_dev, 1, 0x0); - cpp_dev->timeout_trial_cnt = 0; - goto end; + goto error; } else { pr_debug("Firmware loading done\n"); } @@ -1817,34 +1812,33 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) processed_frame[i]->identity, processed_frame[i]->frame_id); + rc = msm_cpp_poll_rx_empty(cpp_dev->base); + if (rc) { + pr_err("%s:%d: Reschedule payload failed %d\n", + __func__, __LINE__, rc); + goto error; + } msm_cpp_write(0x6, cpp_dev->base); + fifo_counter++; /* send top level and plane level */ - for (j = 0; j < cpp_dev->payload_params.stripe_base; j++) { - if (j % MSM_CPP_RX_FIFO_LEVEL == 0) { + for (j = 0; j < cpp_dev->payload_params.stripe_base; j++, + fifo_counter++) { + if (fifo_counter % MSM_CPP_RX_FIFO_LEVEL == 0) { rc = msm_cpp_poll_rx_empty(cpp_dev->base); if (rc) { pr_err("%s:%d] poll failed %d rc %d", __func__, __LINE__, j, rc); - cpp_dev->state = CPP_STATE_OFF; - msm_cpp_set_micro_irq_mask(cpp_dev, - 0, 0x0); - cpp_dev->timeout_trial_cnt = 0; - goto end; + goto error; } + fifo_counter = 0; } msm_cpp_write(processed_frame[i]->cpp_cmd_msg[j], cpp_dev->base); } if (rc) { - pr_err("%s: Rescheduling plane info failed %d\n", - __func__, rc); - /* flush the queue */ - cpp_dev->state = CPP_STATE_OFF; - msm_cpp_flush_queue_and_release_buffer(cpp_dev, - queue_len); - msm_cpp_set_micro_irq_mask(cpp_dev, 0, 0x0); - cpp_dev->timeout_trial_cnt = 0; - goto end; + pr_err("%s:%d: Rescheduling plane info failed %d\n", + __func__, __LINE__, rc); + goto error; } /* send stripes */ i1 = cpp_dev->payload_params.stripe_base + @@ -1853,14 +1847,15 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) i2 = cpp_dev->payload_params.stripe_size * (processed_frame[i]->last_stripe_index - processed_frame[i]->first_stripe_index + 1); - for (j = 0; j < i2; j++) { - if (j % MSM_CPP_RX_FIFO_LEVEL == 0) { + for (j = 0; j < i2; j++, fifo_counter++) { + if (fifo_counter % MSM_CPP_RX_FIFO_LEVEL == 0) { rc = msm_cpp_poll_rx_empty(cpp_dev->base); if (rc) { pr_err("%s:%d] poll failed %d rc %d", __func__, __LINE__, j, rc); break; } + fifo_counter = 0; } msm_cpp_write(processed_frame[i]->cpp_cmd_msg[j+i1], cpp_dev->base); @@ -1868,15 +1863,19 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) if (rc) { pr_err("%s:%d] Rescheduling stripe info failed %d\n", __func__, __LINE__, rc); - /* flush the queue */ - cpp_dev->state = CPP_STATE_OFF; - msm_cpp_flush_queue_and_release_buffer(cpp_dev, - queue_len); - msm_cpp_set_micro_irq_mask(cpp_dev, 0, 0x0); - cpp_dev->timeout_trial_cnt = 0; - goto end; + goto error; } /* send trailer */ + + if (fifo_counter % MSM_CPP_RX_FIFO_LEVEL == 0) { + rc = msm_cpp_poll_rx_empty(cpp_dev->base); + if (rc) { + pr_err("%s:%d] Reschedule trailer failed %d\n", + __func__, __LINE__, rc); + goto error; + } + fifo_counter = 0; + } msm_cpp_write(0xabcdefaa, cpp_dev->base); pr_debug("After frame:%d write\n", i+1); } @@ -1887,6 +1886,16 @@ end: mutex_unlock(&cpp_dev->mutex); pr_debug("%s:%d] exit\n", __func__, __LINE__); return; +error: + cpp_dev->state = CPP_STATE_OFF; + /* flush the queue */ + msm_cpp_flush_queue_and_release_buffer(cpp_dev, + queue_len); + msm_cpp_set_micro_irq_mask(cpp_dev, 0, 0x0); + cpp_dev->timeout_trial_cnt = 0; + mutex_unlock(&cpp_dev->mutex); + pr_debug("%s:%d] exit\n", __func__, __LINE__); + return; } void cpp_timer_callback(unsigned long data) @@ -1903,10 +1912,9 @@ static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev, unsigned long flags; uint32_t i, i1, i2; int32_t rc = -EAGAIN; - int ret; struct msm_cpp_frame_info_t *process_frame; struct msm_queue_cmd *qcmd = NULL; - uint32_t queue_len = 0; + uint32_t queue_len = 0, fifo_counter = 0; if (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) { process_frame = frame_qcmd->command; @@ -1923,25 +1931,33 @@ static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev, CPP_DBG("Starting timer to fire in %d ms. (jiffies=%lu)\n", CPP_CMD_TIMEOUT_MS, jiffies); - ret = mod_timer(&cpp_timer.cpp_timer, - jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS)); - if (ret) + if (mod_timer(&cpp_timer.cpp_timer, + (jiffies + msecs_to_jiffies(CPP_CMD_TIMEOUT_MS))) != 0) CPP_DBG("Timer has not expired yet\n"); + rc = msm_cpp_poll_rx_empty(cpp_dev->base); + if (rc) { + pr_err("%s:%d: Scheduling payload failed %d", + __func__, __LINE__, rc); + goto dequeue_frame; + } msm_cpp_write(0x6, cpp_dev->base); + fifo_counter++; /* send top level and plane level */ - for (i = 0; i < cpp_dev->payload_params.stripe_base; i++) { - if (i % MSM_CPP_RX_FIFO_LEVEL == 0) { + for (i = 0; i < cpp_dev->payload_params.stripe_base; i++, + fifo_counter++) { + if ((fifo_counter % MSM_CPP_RX_FIFO_LEVEL) == 0) { rc = msm_cpp_poll_rx_empty(cpp_dev->base); if (rc) break; + fifo_counter = 0; } msm_cpp_write(process_frame->cpp_cmd_msg[i], cpp_dev->base); } if (rc) { - pr_err("%s: Rescheduling plane info failed %d\n", - __func__, rc); + pr_err("%s:%d: Scheduling plane info failed %d\n", + __func__, __LINE__, rc); goto dequeue_frame; } /* send stripes */ @@ -1951,21 +1967,31 @@ static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev, i2 = cpp_dev->payload_params.stripe_size * (process_frame->last_stripe_index - process_frame->first_stripe_index + 1); - for (i = 0; i < i2; i++) { - if (i % MSM_CPP_RX_FIFO_LEVEL == 0) { + for (i = 0; i < i2; i++, fifo_counter++) { + if ((fifo_counter % MSM_CPP_RX_FIFO_LEVEL) == 0) { rc = msm_cpp_poll_rx_empty(cpp_dev->base); if (rc) break; + fifo_counter = 0; } msm_cpp_write(process_frame->cpp_cmd_msg[i+i1], cpp_dev->base); } if (rc) { - pr_err("%s: Rescheduling stripe info failed %d\n", - __func__, rc); + pr_err("%s:%d: Scheduling stripe info failed %d\n", + __func__, __LINE__, rc); goto dequeue_frame; } /* send trailer */ + if ((fifo_counter % MSM_CPP_RX_FIFO_LEVEL) == 0) { + rc = msm_cpp_poll_rx_empty(cpp_dev->base); + if (rc) { + pr_err("%s: Scheduling trailer failed %d\n", + __func__, rc); + goto dequeue_frame; + } + fifo_counter = 0; + } msm_cpp_write(MSM_CPP_MSG_ID_TRAILER, cpp_dev->base); do_gettimeofday(&(process_frame->in_time));