static void vfe_7x_ops(void *driver_data, unsigned id, size_t len, void (*getevent)(void *ptr, size_t len)) { uint32_t evt_buf[3]; void *data; struct buf_info *outch = NULL; uint32_t y_phy, cbcr_phy; struct table_cmd *table_pending = NULL; unsigned long flags; void *cmd_data = NULL; unsigned char buf[256]; struct msm_free_buf *free_buf = NULL; struct vfe_outputack fack; CDBG("%s:id=%d\n", __func__, id); if (id != VFE_ADSP_EVENT) { data = kzalloc(len, GFP_KERNEL); if (!data) { pr_err("%s: rp: cannot allocate buffer\n", __func__); return; } } if (id == VFE_ADSP_EVENT) { /* event */ getevent(evt_buf, sizeof(evt_buf)); CDBG("%s:event:msg_id=%d\n", __func__, id); } else { /* messages */ getevent(data, len); CDBG("%s:messages:msg_id=%d\n", __func__, id); switch (id) { case MSG_SNAPSHOT: msm_camio_set_perf_lvl(S_PREVIEW); vfe_7x_ops(driver_data, MSG_OUTPUT_S, len, getevent); if (!raw_mode) vfe_7x_ops(driver_data, MSG_OUTPUT_T, len, getevent); vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SNAPSHOT_DONE); return; case MSG_OUTPUT_S: outch = &vfe2x_ctrl->snap; y_phy = outch->ping.ch_paddr[0]; cbcr_phy = outch->ping.ch_paddr[1]; CDBG("MSG_OUTPUT_S: %x %x\n", (unsigned int)y_phy, (unsigned int)cbcr_phy); vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_S, y_phy, cbcr_phy); break; case MSG_OUTPUT_T: outch = &vfe2x_ctrl->thumb; y_phy = outch->ping.ch_paddr[0]; cbcr_phy = outch->ping.ch_paddr[1]; CDBG("MSG_OUTPUT_T: %x %x\n", (unsigned int)y_phy, (unsigned int)cbcr_phy); vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_T, y_phy, cbcr_phy); break; case MSG_OUTPUT1: case MSG_OUTPUT2: if (op_mode & SNAPSHOT_MASK_MODE) { kfree(data); return; } else { free_buf = vfe2x_check_free_buffer( VFE_MSG_OUTPUT_IRQ, VFE_MSG_OUTPUT_P); CDBG("free_buf = %x\n", (unsigned int) free_buf); if (free_buf) { fack.header = VFE_OUTPUT2_ACK; fack.output2newybufferaddress = (void *)(free_buf->ch_paddr[0]); fack.output2newcbcrbufferaddress = (void *)(free_buf->ch_paddr[1]); cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } else { fack.header = VFE_OUTPUT2_ACK; fack.output2newybufferaddress = (void *) ((struct vfe_endframe *)data)->y_address; fack.output2newcbcrbufferaddress = (void *) ((struct vfe_endframe *)data)->cbcr_address; cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } } y_phy = ((struct vfe_endframe *)data)->y_address; cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address; CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n", y_phy, cbcr_phy); memcpy(((struct vfe_frame_extra *)extdata), &((struct vfe_endframe *)data)->extra, sizeof(struct vfe_frame_extra)); vfe2x_ctrl->vfeFrameId = ((struct vfe_frame_extra *)extdata)->frame_id; vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_P, y_phy, cbcr_phy); break; case MSG_RESET_ACK: case MSG_START_ACK: case MSG_UPDATE_ACK: case MSG_VFE_ERROR: case MSG_SYNC_TIMER1_DONE: case MSG_SYNC_TIMER2_DONE: vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id); if (id == MSG_START_ACK) vfe2x_ctrl->vfe_started = 1; break; case MSG_SOF: vfe2x_ctrl->vfeFrameId++; if (vfe2x_ctrl->vfeFrameId == 0) vfe2x_ctrl->vfeFrameId = 1; /* wrapped back */ vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK); if (raw_mode) vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_START_ACK); break; case MSG_STOP_ACK: stopevent.state = 1; vfe2x_ctrl->vfe_started = 0; wake_up(&stopevent.wait); vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_STOP_ACK); break; case MSG_STATS_AF: case MSG_STATS_WE: vfe_send_stats_msg(*(uint32_t *)data, msgs_map[id].isp_id); break; default: vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id); break; } } if (MSG_TABLE_CMD_ACK == id) { spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags); if (list_empty(&vfe2x_ctrl->table_q)) { if (vfe2x_ctrl->start_pending) { CDBG("Send START\n"); cmd_data = buf; *(uint32_t *)cmd_data = VFE_START; memcpy(((char *)cmd_data) + 4, &vfe2x_ctrl->start_cmd, sizeof(vfe2x_ctrl->start_cmd)); /* Send Start cmd here */ len = sizeof(vfe2x_ctrl->start_cmd) + 4; msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); vfe2x_ctrl->start_pending = 0; } vfe2x_ctrl->tableack_pending = 0; spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); return; } table_pending = list_first_entry(&vfe2x_ctrl->table_q, struct table_cmd, list); if (!table_pending) { vfe2x_ctrl->tableack_pending = 0; spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); return; } msm_adsp_write(vfe_mod, table_pending->queue, table_pending->cmd, table_pending->size); list_del(&table_pending->list); kfree(table_pending->cmd); vfe2x_ctrl->tableack_pending = 1; spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); } else if (!vfe2x_ctrl->tableack_pending) {
static void vfe_7x_ops(void *driver_data, unsigned id, size_t len, void (*getevent)(void *ptr, size_t len)) { uint32_t evt_buf[3]; void *data; struct buf_info *outch = NULL; uint32_t y_phy, cbcr_phy; struct table_cmd *table_pending = NULL; unsigned long flags; void *cmd_data = NULL; unsigned char buf[256]; struct msm_free_buf *free_buf = NULL; struct vfe_outputack fack; int i; CDBG("%s:id=%d\n", __func__, id); if (id != VFE_ADSP_EVENT) { data = kzalloc(len, GFP_KERNEL); if (!data) { pr_err("%s: rp: cannot allocate buffer\n", __func__); return; } } if (id == VFE_ADSP_EVENT) { getevent(evt_buf, sizeof(evt_buf)); CDBG("%s:event:msg_id=%d\n", __func__, id); } else { getevent(data, len); CDBG("%s:messages:msg_id=%d\n", __func__, id); switch (id) { case MSG_SNAPSHOT: msm_camio_set_perf_lvl(S_PREVIEW); vfe_7x_ops(driver_data, MSG_OUTPUT_S, len, getevent); if (!raw_mode) vfe_7x_ops(driver_data, MSG_OUTPUT_T, len, getevent); vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SNAPSHOT_DONE); return; case MSG_OUTPUT_S: outch = &vfe2x_ctrl->snap; y_phy = outch->ping.ch_paddr[0]; cbcr_phy = outch->ping.ch_paddr[1]; CDBG("MSG_OUTPUT_S: %x %x\n", (unsigned int)y_phy, (unsigned int)cbcr_phy); vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_PRIMARY, y_phy, cbcr_phy); break; case MSG_OUTPUT_T: outch = &vfe2x_ctrl->thumb; y_phy = outch->ping.ch_paddr[0]; cbcr_phy = outch->ping.ch_paddr[1]; CDBG("MSG_OUTPUT_T: %x %x\n", (unsigned int)y_phy, (unsigned int)cbcr_phy); vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_SECONDARY, y_phy, cbcr_phy); break; case MSG_OUTPUT1: if (op_mode & SNAPSHOT_MASK_MODE) { kfree(data); return; } else { free_buf = vfe2x_check_free_buffer( VFE_MSG_OUTPUT_IRQ, VFE_MSG_OUTPUT_SECONDARY ); CDBG("free_buf = %x\n", (unsigned int) free_buf); if (free_buf) { fack.header = VFE_OUTPUT1_ACK; fack.output2newybufferaddress = (void *)(free_buf->ch_paddr[0]); fack.output2newcbcrbufferaddress = (void *)(free_buf->ch_paddr[1]); cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } else { fack.header = VFE_OUTPUT1_ACK; fack.output2newybufferaddress = (void *) ((struct vfe_endframe *)data)->y_address; fack.output2newcbcrbufferaddress = (void *) ((struct vfe_endframe *)data)->cbcr_address; cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } } y_phy = ((struct vfe_endframe *)data)->y_address; cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address; CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n", y_phy, cbcr_phy); if (free_buf) { for (i = 0; i < 3; i++) { if (vfe2x_ctrl->free_buf.buf[i]. ch_paddr[0] == y_phy) { vfe2x_ctrl->free_buf. buf[i].ch_paddr[0] = free_buf->ch_paddr[0]; vfe2x_ctrl->free_buf. buf[i].ch_paddr[1] = free_buf->ch_paddr[1]; break; } } if (i == 3) CDBG("Address doesnt match\n"); } memcpy(((struct vfe_frame_extra *)extdata), &((struct vfe_endframe *)data)->extra, sizeof(struct vfe_frame_extra)); vfe2x_ctrl->vfeFrameId = ((struct vfe_frame_extra *)extdata)->frame_id; vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_SECONDARY, y_phy, cbcr_phy); break; case MSG_OUTPUT2: if (op_mode & SNAPSHOT_MASK_MODE) { kfree(data); return; } else { free_buf = vfe2x_check_free_buffer( VFE_MSG_OUTPUT_IRQ, VFE_MSG_OUTPUT_PRIMARY); CDBG("free_buf = %x\n", (unsigned int) free_buf); if (free_buf) { fack.header = VFE_OUTPUT2_ACK; fack.output2newybufferaddress = (void *)(free_buf->ch_paddr[0]); fack.output2newcbcrbufferaddress = (void *)(free_buf->ch_paddr[1]); cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } else { fack.header = VFE_OUTPUT2_ACK; fack.output2newybufferaddress = (void *) ((struct vfe_endframe *)data)->y_address; fack.output2newcbcrbufferaddress = (void *) ((struct vfe_endframe *)data)->cbcr_address; cmd_data = &fack; len = sizeof(fack); msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); } } y_phy = ((struct vfe_endframe *)data)->y_address; cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address; CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n", y_phy, cbcr_phy); if (free_buf) { for (i = 0; i < 3; i++) { if (vfe2x_ctrl->free_buf.buf[i]. ch_paddr[0] == y_phy) { vfe2x_ctrl->free_buf. buf[i].ch_paddr[0] = free_buf->ch_paddr[0]; vfe2x_ctrl->free_buf. buf[i].ch_paddr[1] = free_buf->ch_paddr[1]; break; } } if (i == 3) CDBG("Address doesnt match\n"); } memcpy(((struct vfe_frame_extra *)extdata), &((struct vfe_endframe *)data)->extra, sizeof(struct vfe_frame_extra)); vfe2x_ctrl->vfeFrameId = ((struct vfe_frame_extra *)extdata)->frame_id; vfe_send_outmsg(&vfe2x_ctrl->subdev, MSG_ID_OUTPUT_PRIMARY, y_phy, cbcr_phy); break; case MSG_RESET_ACK: case MSG_START_ACK: case MSG_UPDATE_ACK: case MSG_VFE_ERROR: case MSG_SYNC_TIMER1_DONE: case MSG_SYNC_TIMER2_DONE: vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id); if (id == MSG_START_ACK) vfe2x_ctrl->vfe_started = 1; if (id == MSG_VFE_ERROR) { uint16_t *ptr; struct vfe_error_msg *VFE_ErrorMessageBuffer = data; ptr = data; CDBG("Error: %x %x\n", ptr[0], ptr[1]); CDBG("CAMIF_Error = %d\n", VFE_ErrorMessageBuffer->camif_error); CDBG("output1YBusOverflow = %d\n", VFE_ErrorMessageBuffer-> output1ybusoverflow); CDBG("output1CbCrBusOverflow = %d\n", VFE_ErrorMessageBuffer-> output1cbcrbusoverflow); CDBG("output2YBusOverflow = %d\n", VFE_ErrorMessageBuffer-> output2ybusoverflow); CDBG("output2CbCrBusOverflow = %d\n", VFE_ErrorMessageBuffer-> output2cbcrbusoverflow); CDBG("autofocusStatBusOverflow = %d\n", VFE_ErrorMessageBuffer-> autofocusstatbusoverflow); CDBG("WB_EXPStatBusOverflow = %d\n", VFE_ErrorMessageBuffer-> wb_expstatbusoverflow); CDBG("AXIError = %d\n", VFE_ErrorMessageBuffer-> axierror); CDBG("CAMIF_Staus = %d\n", VFE_ErrorMessageBuffer-> camif_staus); CDBG("pixel_count = %d\n", VFE_ErrorMessageBuffer-> pixel_count); CDBG("line_count = %d\n", VFE_ErrorMessageBuffer-> line_count); } break; case MSG_SOF: vfe2x_ctrl->vfeFrameId++; if (vfe2x_ctrl->vfeFrameId == 0) vfe2x_ctrl->vfeFrameId = 1; if ((op_mode & SNAPSHOT_MASK_MODE) && !raw_mode) { pr_err("Ignore SOF for snapshot\n"); kfree(data); return; } vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_SOF_ACK); if (raw_mode) vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_START_ACK); break; case MSG_STOP_ACK: stopevent.state = 1; vfe2x_ctrl->vfe_started = 0; wake_up(&stopevent.wait); vfe2x_send_isp_msg(vfe2x_ctrl, MSG_ID_STOP_ACK); break; case MSG_STATS_AF: case MSG_STATS_WE: vfe_send_stats_msg(*(uint32_t *)data, msgs_map[id].isp_id); break; default: vfe2x_send_isp_msg(vfe2x_ctrl, msgs_map[id].isp_id); break; } } if (MSG_TABLE_CMD_ACK == id) { spin_lock_irqsave(&vfe2x_ctrl->table_lock, flags); vfe2x_ctrl->tableack_pending = 0; if (list_empty(&vfe2x_ctrl->table_q)) { if (vfe2x_ctrl->start_pending) { CDBG("Send START\n"); cmd_data = buf; *(uint32_t *)cmd_data = VFE_START; memcpy(((char *)cmd_data) + 4, &vfe2x_ctrl->start_cmd, sizeof(vfe2x_ctrl->start_cmd)); len = sizeof(vfe2x_ctrl->start_cmd) + 4; msm_adsp_write(vfe_mod, QDSP_CMDQUEUE, cmd_data, len); vfe2x_ctrl->start_pending = 0; } spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); return; } table_pending = list_first_entry(&vfe2x_ctrl->table_q, struct table_cmd, list); if (!table_pending) { spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); return; } msm_adsp_write(vfe_mod, table_pending->queue, table_pending->cmd, table_pending->size); list_del(&table_pending->list); kfree(table_pending->cmd); vfe2x_ctrl->tableack_pending = 1; spin_unlock_irqrestore(&vfe2x_ctrl->table_lock, flags); } else if (!vfe2x_ctrl->tableack_pending) {