void axi_stop(struct axi_ctrl_t *axi_ctrl) { uint8_t axiBusyFlag = true; /* axi halt command. */ msm_camera_io_w(AXI_HALT, axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD); wmb(); while (axiBusyFlag) { if (msm_camera_io_r( axi_ctrl->share_ctrl->vfebase + VFE_AXI_STATUS) & 0x1) axiBusyFlag = false; } /* Ensure the write order while writing to the command register using the barrier */ msm_camera_io_w_mb(AXI_HALT_CLEAR, axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD); /* after axi halt, then ok to apply global reset. */ /* enable reset_ack and async timer interrupt only while stopping the pipeline.*/ msm_camera_io_w(0xf0000000, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0); msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1); /* Ensure the write order while writing to the command register using the barrier */ msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD, axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET); }
static void msm_cci_flush_queue(struct cci_device *cci_dev, enum cci_i2c_master_t master) { int32_t rc = 0; msm_camera_io_w_mb(1 << master, cci_dev->base + CCI_HALT_REQ_ADDR); rc = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); if (rc < 0) { pr_err("%s:%d wait failed\n", __func__, __LINE__); } else if (rc == 0) { pr_err("%s:%d wait timeout\n", __func__, __LINE__); /* Set reset pending flag to TRUE */ cci_dev->cci_master_info[master].reset_pending = TRUE; /* Set proper mask to RESET CMD address based on MASTER */ if (master == MASTER_0) msm_camera_io_w_mb(CCI_M0_RESET_RMSK, cci_dev->base + CCI_RESET_CMD_ADDR); else msm_camera_io_w_mb(CCI_M1_RESET_RMSK, cci_dev->base + CCI_RESET_CMD_ADDR); /* wait for reset done irq */ rc = wait_for_completion_timeout( &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT); if (rc <= 0) pr_err("%s:%d wait failed %d\n", __func__, __LINE__, rc); } return; }
static void msm_ispif_enable_crop(struct ispif_device *ispif, uint8_t intftype, uint8_t vfe_intf, uint16_t start_pixel, uint16_t end_pixel) { uint32_t data; BUG_ON(!ispif); if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return; } data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf)); data |= (1 << (intftype + 7)); if (intftype == PIX0) data |= 1 << PIX0_LINE_BUF_EN_BIT; msm_camera_io_w(data, ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf)); if (intftype == PIX0) msm_camera_io_w_mb(start_pixel | (end_pixel << 16), ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 0)); else if (intftype == PIX1) msm_camera_io_w_mb(start_pixel | (end_pixel << 16), ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 1)); else { pr_err("%s: invalid intftype=%d\n", __func__, intftype); BUG_ON(1); return; } }
static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits, struct msm_ispif_param_data *params) { uint8_t vc; int i, k; enum msm_ispif_intftype intf_type; enum msm_ispif_cid cid; enum msm_ispif_vfe_intf vfe_intf; BUG_ON(!ispif); BUG_ON(!params); for (i = 0; i < params->num; i++) { vfe_intf = params->entries[i].vfe_intf; if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return; } if (params->entries[i].num_cids > MAX_CID_CH) { pr_err("%s: out of range of cid_num %d\n", __func__, params->entries[i].num_cids); return; } } for (i = 0; i < params->num; i++) { intf_type = params->entries[i].intftype; vfe_intf = params->entries[i].vfe_intf; for (k = 0; k < params->entries[i].num_cids; k++) { cid = params->entries[i].cids[k]; vc = cid / 4; if (intf_type == RDI2) { /* zero out two bits */ ispif->applied_intf_cmd[vfe_intf].intf_cmd1 &= ~(0x3 << (vc * 2 + 8)); /* set cmd bits */ ispif->applied_intf_cmd[vfe_intf].intf_cmd1 |= (cmd_bits << (vc * 2 + 8)); } else { /* zero 2 bits */ ispif->applied_intf_cmd[vfe_intf].intf_cmd &= ~(0x3 << (vc * 2 + intf_type * 8)); /* set cmd bits */ ispif->applied_intf_cmd[vfe_intf].intf_cmd |= (cmd_bits << (vc * 2 + intf_type * 8)); } } /* cmd for PIX0, PIX1, RDI0, RDI1 */ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF) msm_camera_io_w_mb( ispif->applied_intf_cmd[vfe_intf].intf_cmd, ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf)); /* cmd for RDI2 */ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF) msm_camera_io_w_mb( ispif->applied_intf_cmd[vfe_intf].intf_cmd1, ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf)); } }
static void msm_cci_set_clk_param(struct cci_device *cci_dev, struct msm_camera_cci_ctrl *c_ctrl) { struct msm_cci_clk_params_t *clk_params = NULL; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; //LGE_CHANGE_S, i2c speed up for camera entrance time issue, 2014-07-02, [email protected] i2c_freq_mode = I2C_FAST_MODE; //LGE_CHANGE_E, i2c speed up for camera entrance time issue, 2014-07-02, [email protected] if (cci_dev->master_clk_init[master]) return; clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; if (MASTER_0 == master) { msm_camera_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR); msm_camera_io_w_mb(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta, cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR); msm_camera_io_w_mb(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta, cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR); msm_camera_io_w_mb(clk_params->hw_tbuf, cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR); msm_camera_io_w_mb(clk_params->hw_scl_stretch_en << 8 | clk_params->hw_trdhld << 4 | clk_params->hw_tsp, cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR); } else if (MASTER_1 == master) { msm_camera_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR); msm_camera_io_w_mb(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta, cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR); msm_camera_io_w_mb(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta, cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR); msm_camera_io_w_mb(clk_params->hw_tbuf, cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR); msm_camera_io_w_mb(clk_params->hw_scl_stretch_en << 8 | clk_params->hw_trdhld << 4 | clk_params->hw_tsp, cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR); } cci_dev->master_clk_init[master] = 1; return; }
static int vpe_start(void) { /* enable the frame irq, bit 0 = Display list 0 ROI done */ msm_camera_io_w_mb(1, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET); msm_camera_io_dump(vpe_ctrl->vpebase, 0x120); msm_camera_io_dump(vpe_ctrl->vpebase + 0x00400, 0x18); msm_camera_io_dump(vpe_ctrl->vpebase + 0x10000, 0x250); msm_camera_io_dump(vpe_ctrl->vpebase + 0x30000, 0x20); msm_camera_io_dump(vpe_ctrl->vpebase + 0x50000, 0x30); msm_camera_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10); /* this triggers the operation. */ msm_camera_io_w_mb(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET); return 0; }
static int32_t msm_cci_validate_queue(struct cci_device *cci_dev, uint32_t len, enum cci_i2c_master_t master, enum cci_i2c_queue_t queue) { int32_t rc = 0; uint32_t read_val = 0; uint32_t reg_offset = master * 0x200 + queue * 0x100; read_val = msm_camera_io_r_mb(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset); CDBG("%s line %d CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d\n", __func__, __LINE__, read_val, len, cci_dev->cci_i2c_queue_info[master][queue].max_queue_size); if ((read_val + len + 1) > cci_dev-> cci_i2c_queue_info[master][queue].max_queue_size) { uint32_t reg_val = 0; uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8); CDBG("%s:%d CCI_I2C_REPORT_CMD\n", __func__, __LINE__); msm_camera_io_w_mb(report_val, cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR + reg_offset); read_val++; CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d\n", __func__, __LINE__, read_val); msm_camera_io_w_mb(read_val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset); reg_val = 1 << ((master * 2) + queue); CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__); msm_camera_io_w_mb(reg_val, cci_dev->base + CCI_QUEUE_START_ADDR); CDBG("%s line %d wait_for_completion_timeout\n", __func__, __LINE__); rc = wait_for_completion_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); if (rc <= 0) { pr_err("%s: wait_for_completion_timeout %d\n", __func__, __LINE__); if (rc == 0) rc = -ETIMEDOUT; msm_cci_flush_queue(cci_dev, master); return rc; } rc = cci_dev->cci_master_info[master].status; if (rc < 0) pr_err("%s failed rc %d\n", __func__, rc); } return rc; }
static void msm_cci_set_clk_param(struct cci_device *cci_dev, struct msm_camera_cci_ctrl *c_ctrl) { struct msm_cci_clk_params_t *clk_params = NULL; enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master; enum i2c_freq_mode_t i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode; if (cci_dev->master_clk_init[master]) return; clk_params = &cci_dev->cci_clk_params[i2c_freq_mode]; if (MASTER_0 == master) { msm_camera_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR); msm_camera_io_w_mb(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta, cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR); msm_camera_io_w_mb(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta, cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR); msm_camera_io_w_mb(clk_params->hw_tbuf, cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR); msm_camera_io_w_mb(clk_params->hw_scl_stretch_en << 8 | clk_params->hw_trdhld << 4 | clk_params->hw_tsp, cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR); } else if (MASTER_1 == master) { msm_camera_io_w_mb(clk_params->hw_thigh << 16 | clk_params->hw_tlow, cci_dev->base + CCI_I2C_M1_SCL_CTL_ADDR); msm_camera_io_w_mb(clk_params->hw_tsu_sto << 16 | clk_params->hw_tsu_sta, cci_dev->base + CCI_I2C_M1_SDA_CTL_0_ADDR); msm_camera_io_w_mb(clk_params->hw_thd_dat << 16 | clk_params->hw_thd_sta, cci_dev->base + CCI_I2C_M1_SDA_CTL_1_ADDR); msm_camera_io_w_mb(clk_params->hw_tbuf, cci_dev->base + CCI_I2C_M1_SDA_CTL_2_ADDR); msm_camera_io_w_mb(clk_params->hw_scl_stretch_en << 8 | clk_params->hw_trdhld << 4 | clk_params->hw_tsp, cci_dev->base + CCI_I2C_M1_MISC_CTL_ADDR); } cci_dev->master_clk_init[master] = 1; return; }
void msm_camera_io_memcpy_mb(void __iomem *dest_addr, void __iomem *src_addr, u32 len) { int i; u32 *d = (u32 *) dest_addr; u32 *s = (u32 *) src_addr; for (i = 0; i < (len / 4); i++) msm_camera_io_w_mb(*s++, d++); }
static irqreturn_t vpe_parse_irq(int irq_num, void *data) { vpe_ctrl->irq_status = msm_camera_io_r_mb(vpe_ctrl->vpebase + VPE_INTR_STATUS_OFFSET); msm_camera_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase + VPE_INTR_CLEAR_OFFSET); msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET); D("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status); tasklet_schedule(&vpe_tasklet); return IRQ_HANDLED; }
static void msm_ispif_sel_csid_core(struct ispif_device *ispif, uint8_t intftype, uint8_t csid, uint8_t vfe_intf) { int rc = 0; uint32_t data; BUG_ON(!ispif); if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return; } if (ispif->csid_version <= CSID_VERSION_V2) { if (ispif->ispif_clk[vfe_intf][intftype] == NULL) { CDBG("%s: ispif NULL clk\n", __func__); return; } rc = clk_set_rate(ispif->ispif_clk[vfe_intf][intftype], csid); if (rc) { pr_err("%s: clk_set_rate failed %d\n", __func__, rc); return; } } data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf)); switch (intftype) { case PIX0: data &= ~(BIT(1) | BIT(0)); data |= csid; break; case RDI0: data &= ~(BIT(5) | BIT(4)); data |= (csid << 4); break; case PIX1: data &= ~(BIT(9) | BIT(8)); data |= (csid << 8); break; case RDI1: data &= ~(BIT(13) | BIT(12)); data |= (csid << 12); break; case RDI2: data &= ~(BIT(21) | BIT(20)); data |= (csid << 20); break; } if (data) msm_camera_io_w_mb(data, ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf)); }
static int msm_ispif_reset(struct ispif_device *ispif) { int rc = 0; int i; BUG_ON(!ispif); memset(ispif->sof_count, 0, sizeof(ispif->sof_count)); frame_event_manager_reset(&ispif->fem); for (i = 0; i < ispif->vfe_info.num_vfe; i++) { msm_camera_io_w(1 << PIX0_LINE_BUF_EN_BIT, ispif->base + ISPIF_VFE_m_CTRL_0(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INPUT_SEL(i)); msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_0(i)); msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_1(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 2)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(i, 1)); } msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR); return rc; }
static void msm_axi_process_irq(struct v4l2_subdev *sd, void *arg) { struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd); uint32_t irqstatus = (uint32_t) arg; if (!axi_ctrl->share_ctrl->vfebase) { pr_err("%s: base address unmapped\n", __func__); return; } /* next, check output path related interrupts. */ if (irqstatus & VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) { CDBG("Image composite done 0 irq occured.\n"); vfe40_process_output_path_irq_0(axi_ctrl); } if (irqstatus & VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) { CDBG("Image composite done 1 irq occured.\n"); vfe40_process_output_path_irq_1(axi_ctrl); } /* in snapshot mode if done then send snapshot done message */ if (axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN || axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB || axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG || axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB || axi_ctrl->share_ctrl->operation_mode == VFE_OUTPUTS_RAW) { if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0) && (axi_ctrl->share_ctrl->outpath.out1. capture_cnt == 0)) { msm_camera_io_w_mb( CAMIF_COMMAND_STOP_IMMEDIATELY, axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND); vfe40_send_isp_msg(&axi_ctrl->subdev, axi_ctrl->share_ctrl->vfeFrameId, MSG_ID_SNAPSHOT_DONE); } } }
static void msm_ispif_enable_intf_cids(struct ispif_device *ispif, uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable) { uint32_t intf_addr, data; BUG_ON(!ispif); if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return; } switch (intftype) { case PIX0: intf_addr = ISPIF_VFE_m_PIX_INTF_n_CID_MASK(vfe_intf, 0); break; case RDI0: intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 0); break; case PIX1: intf_addr = ISPIF_VFE_m_PIX_INTF_n_CID_MASK(vfe_intf, 1); break; case RDI1: intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 1); break; case RDI2: intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 2); break; default: pr_err("%s: invalid intftype=%d\n", __func__, intftype); BUG_ON(1); return; } data = msm_camera_io_r(ispif->base + intf_addr); if (enable) data |= cid_mask; else data &= ~cid_mask; pr_err("%s: <DBG01> vfe_intf %u intftype %u intf_addr %x data %x\n", __func__, vfe_intf, intftype, intf_addr, data); msm_camera_io_w_mb(data, ispif->base + intf_addr); }
static void msm_ispif_sel_csid_core(struct ispif_device *ispif, uint8_t intftype, uint8_t csid, uint8_t vfe_intf) { uint32_t data; BUG_ON(!ispif); if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return; } data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf)); switch (intftype) { case PIX0: data &= ~(BIT(1) | BIT(0)); data |= csid; break; case RDI0: data &= ~(BIT(5) | BIT(4)); data |= (csid << 4); break; case PIX1: data &= ~(BIT(9) | BIT(8)); data |= (csid << 8); break; case RDI1: data &= ~(BIT(13) | BIT(12)); data |= (csid << 12); break; case RDI2: data &= ~(BIT(21) | BIT(20)); data |= (csid << 20); break; } msm_camera_io_w_mb(data, ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf)); }
static irqreturn_t vpe_parse_irq(int irq_num, void *data) { unsigned long flags; uint32_t irq_status = 0; struct vpe_isr_queue_cmd_type *qcmd; CDBG("vpe_parse_irq.\n"); /* read and clear back-to-back. */ irq_status = msm_camera_io_r_mb(vpe_device->vpebase + VPE_INTR_STATUS_OFFSET); msm_camera_io_w_mb(irq_status, vpe_device->vpebase + VPE_INTR_CLEAR_OFFSET); msm_camera_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET); if (irq_status == 0) { pr_err("%s: irq_status = 0,Something is wrong!\n", __func__); return IRQ_HANDLED; } irq_status &= 0x1; /* apply mask. only interested in bit 0. */ if (irq_status) { qcmd = kzalloc(sizeof(struct vpe_isr_queue_cmd_type), GFP_ATOMIC); if (!qcmd) { pr_err("%s: qcmd malloc failed!\n", __func__); return IRQ_HANDLED; } /* must be 0x1 now. so in bottom half we don't really need to check. */ qcmd->irq_status = irq_status & 0x1; spin_lock_irqsave(&vpe_ctrl->tasklet_lock, flags); list_add_tail(&qcmd->list, &vpe_ctrl->tasklet_q); spin_unlock_irqrestore(&vpe_ctrl->tasklet_lock, flags); tasklet_schedule(&vpe_tasklet); } return IRQ_HANDLED; }
static int msm_ispif_reset_hw(struct ispif_device *ispif, int release) { int rc = 0, i; long timeout = 0; struct clk *reset_clk1[ARRAY_SIZE(ispif_8626_reset_clk_info)]; ispif->clk_idx = 0; rc = msm_ispif_get_clk_info(ispif, ispif->pdev, ispif_ahb_clk_info, ispif_clk_info); if (rc < 0) { pr_err("%s: msm_isp_get_clk_info() failed", __func__); return -EFAULT; } /* Turn ON regulators before enabling the clocks*/ rc = msm_ispif_set_regulator(ispif, 1); if (rc < 0) { pr_err("%s: ispif enable regulator failed", __func__); return -EFAULT; } rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info, ispif->clk, ispif->num_clk, 1); if (rc < 0) { pr_err("%s: cannot enable clock, error = %d\n", __func__, rc); rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8626_reset_clk_info, reset_clk1, ARRAY_SIZE(ispif_8626_reset_clk_info), 1); if (rc < 0) { pr_err("%s: cannot enable clock, error = %d", __func__, rc); } else { /* This is set when device is 8x26 */ ispif->clk_idx = 2; } } else { /* This is set when device is 8974 */ ispif->clk_idx = 1; } if (release) { for (i = 0; i < ispif->vfe_info.num_vfe; i++) { msm_camera_io_w_mb(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_0(i)); msm_camera_io_w_mb(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_1(i)); } msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR); } init_completion(&ispif->reset_complete[VFE0]); if (ispif->hw_num_isps > 1) init_completion(&ispif->reset_complete[VFE1]); /* initiate reset of ISPIF */ msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR); timeout = wait_for_completion_timeout( &ispif->reset_complete[VFE0], msecs_to_jiffies(500)); CDBG("%s: VFE0 done\n", __func__); if (timeout <= 0) { pr_err("%s: VFE0 reset wait timeout\n", __func__); rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info, ispif->clk, ispif->num_clk, 0); if (rc < 0) { rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8626_reset_clk_info, reset_clk1, ARRAY_SIZE(ispif_8626_reset_clk_info), 0); if (rc < 0) pr_err("%s: VFE0 reset wait timeout\n", __func__); } /* Turn OFF regulators */ rc = msm_ispif_set_regulator(ispif, 0); return -ETIMEDOUT; } if (ispif->hw_num_isps > 1) { msm_camera_io_w(ISPIF_RST_CMD_1_MASK, ispif->base + ISPIF_RST_CMD_1_ADDR); timeout = wait_for_completion_timeout( &ispif->reset_complete[VFE1], msecs_to_jiffies(500)); CDBG("%s: VFE1 done\n", __func__); if (timeout <= 0) { pr_err("%s: VFE1 reset wait timeout\n", __func__); rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info, ispif->clk, ispif->num_clk, 0); /* Turn OFF regulators */ rc = msm_ispif_set_regulator(ispif, 0); return -ETIMEDOUT; } } if (ispif->clk_idx == 1) { rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info, ispif->clk, ispif->num_clk, 0); if (rc < 0) { pr_err("%s: cannot disable clock, error = %d", __func__, rc); } } if (ispif->clk_idx == 2) { rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8626_reset_clk_info, reset_clk1, ARRAY_SIZE(ispif_8626_reset_clk_info), 0); if (rc < 0) { pr_err("%s: cannot disable clock, error = %d", __func__, rc); } } /* Turn OFF regulators after enabling the clocks*/ rc = msm_ispif_set_regulator(ispif, 0); if (rc < 0) { pr_err("%s: ispif disable regulator failed", __func__); return -EFAULT; } return rc; }
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out, void *data) { struct ispif_device *ispif = (struct ispif_device *)data; BUG_ON(!ispif); BUG_ON(!out); out[VFE0].ispifIrqStatus0 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_0(VFE0)); msm_camera_io_w(out[VFE0].ispifIrqStatus0, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE0)); out[VFE0].ispifIrqStatus1 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_1(VFE0)); msm_camera_io_w(out[VFE0].ispifIrqStatus1, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE0)); out[VFE0].ispifIrqStatus2 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_2(VFE0)); msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE0)); if (ispif->vfe_info.num_vfe > 1) { out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_0(VFE1)); msm_camera_io_w(out[VFE1].ispifIrqStatus0, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1)); out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_1(VFE1)); msm_camera_io_w(out[VFE1].ispifIrqStatus1, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1)); out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base + ISPIF_VFE_m_IRQ_STATUS_2(VFE1)); msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1)); } msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR); if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) { if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ) complete(&ispif->reset_complete[VFE0]); if (out[VFE0].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ) pr_err("%s: VFE0 pix0 overflow.\n", __func__); if (out[VFE0].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ) pr_err("%s: VFE0 rdi0 overflow.\n", __func__); if (out[VFE0].ispifIrqStatus1 & RAW_INTF_1_OVERFLOW_IRQ) pr_err("%s: VFE0 rdi1 overflow.\n", __func__); if (out[VFE0].ispifIrqStatus2 & RAW_INTF_2_OVERFLOW_IRQ) pr_err("%s: VFE0 rdi2 overflow.\n", __func__); ispif_process_irq(ispif, out, VFE0); } if (ispif->hw_num_isps > 1) { if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ) complete(&ispif->reset_complete[VFE1]); if (out[VFE1].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ) pr_err("%s: VFE1 pix0 overflow.\n", __func__); if (out[VFE1].ispifIrqStatus0 & RAW_INTF_0_OVERFLOW_IRQ) pr_err("%s: VFE1 rdi0 overflow.\n", __func__); if (out[VFE1].ispifIrqStatus1 & RAW_INTF_1_OVERFLOW_IRQ) pr_err("%s: VFE1 rdi1 overflow.\n", __func__); if (out[VFE1].ispifIrqStatus2 & RAW_INTF_2_OVERFLOW_IRQ) pr_err("%s: VFE1 rdi2 overflow.\n", __func__); ispif_process_irq(ispif, out, VFE1); } }
static int msm_ispif_config(struct ispif_device *ispif, struct msm_ispif_param_data *params) { int rc = 0, i = 0; uint16_t cid_mask; enum msm_ispif_intftype intftype; enum msm_ispif_vfe_intf vfe_intf; BUG_ON(!ispif); BUG_ON(!params); if (ispif->ispif_state != ISPIF_POWER_UP) { pr_err("%s: ispif invalid state %d\n", __func__, ispif->ispif_state); rc = -EPERM; return rc; } if (params->num > MAX_PARAM_ENTRIES) { pr_err("%s: invalid param entries %d\n", __func__, params->num); rc = -EINVAL; return rc; } for (i = 0; i < params->num; i++) { vfe_intf = params->entries[i].vfe_intf; if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return -EINVAL; } msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(vfe_intf)); msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(vfe_intf)); msm_camera_io_w_mb(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(vfe_intf)); } for (i = 0; i < params->num; i++) { intftype = params->entries[i].intftype; vfe_intf = params->entries[i].vfe_intf; CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__, intftype, vfe_intf, params->entries[i].csid); if ((intftype >= INTF_MAX) || (vfe_intf >= ispif->vfe_info.num_vfe) || (ispif->csid_version <= CSID_VERSION_V22 && (vfe_intf > VFE0))) { pr_err("%s: VFEID %d and CSID version %d mismatch\n", __func__, vfe_intf, ispif->csid_version); return -EINVAL; } if (ispif->csid_version >= CSID_VERSION_V30) msm_ispif_select_clk_mux(ispif, intftype, params->entries[i].csid, vfe_intf); rc = msm_ispif_validate_intf_status(ispif, intftype, vfe_intf); if (rc) { pr_err("%s:validate_intf_status failed, rc = %d\n", __func__, rc); return rc; } msm_ispif_sel_csid_core(ispif, intftype, params->entries[i].csid, vfe_intf); cid_mask = msm_ispif_get_cids_mask_from_cfg( ¶ms->entries[i]); msm_ispif_enable_intf_cids(ispif, intftype, cid_mask, vfe_intf, 1); if (params->entries[i].crop_enable) msm_ispif_enable_crop(ispif, intftype, vfe_intf, params->entries[i].crop_start_pixel, params->entries[i].crop_end_pixel); } for (vfe_intf = 0; vfe_intf < 2; vfe_intf++) { msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(vfe_intf)); msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf)); msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(vfe_intf)); msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf)); msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(vfe_intf)); msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf)); } msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR); return rc; }
static int msm_ispif_reset(struct ispif_device *ispif) { int rc = 0; long lrc = 0; unsigned long jiffes = msecs_to_jiffies(500); unsigned long flags; spin_lock_irqsave(&ispif->auto_complete_lock, flags); ispif->wait_timeout[VFE0] = 0; init_completion(&ispif->reset_complete[VFE0]); if (ispif->csid_version >= CSID_VERSION_V3 && ispif->vfe_info.num_vfe > 1) { ispif->wait_timeout[VFE1] = 0; init_completion(&ispif->reset_complete[VFE1]); } spin_unlock_irqrestore(&ispif->auto_complete_lock, flags); BUG_ON(!ispif); memset(ispif->sof_count, 0, sizeof(ispif->sof_count)); msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_0(0)); msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR); lrc = wait_for_completion_interruptible_timeout( &ispif->reset_complete[VFE0], jiffes); if (lrc < 0 || !lrc) { pr_err("%s: wait timeout ret = %ld, vfeid = %d\n", __func__, lrc, VFE0); rc = -EIO; spin_lock_irqsave(&ispif->auto_complete_lock, flags); ispif->wait_timeout[VFE0] = 1; spin_unlock_irqrestore(&ispif->auto_complete_lock, flags); goto end; } if (ispif->csid_version >= CSID_VERSION_V3 && ispif->vfe_info.num_vfe > 1) { msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base + ISPIF_RST_CMD_1_ADDR); lrc = wait_for_completion_interruptible_timeout( &ispif->reset_complete[VFE1], jiffes); if (lrc < 0 || !lrc) { pr_err("%s: wait timeout ret = %ld, vfeid = %d\n", __func__, lrc, VFE1); rc = -EIO; spin_lock_irqsave(&ispif->auto_complete_lock, flags); ispif->wait_timeout[VFE1] = 1; spin_unlock_irqrestore(&ispif->auto_complete_lock, flags); } } end: return rc; }
static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd, uint32_t *cfg_data, uint32_t cmd_len) { switch (reg_cfg_cmd->cmd_type) { case VFE_WRITE: { if (resource_size(vfe_dev->vfe_mem) < (reg_cfg_cmd->u.rw_info.reg_offset + reg_cfg_cmd->u.rw_info.len)) { pr_err("%s: VFE_WRITE: Invalid length\n", __func__); return -EINVAL; } msm_camera_io_memcpy(vfe_dev->vfe_base + reg_cfg_cmd->u.rw_info.reg_offset, cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4, reg_cfg_cmd->u.rw_info.len); break; } case VFE_WRITE_MB: { uint32_t *data_ptr = cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4; if ((UINT_MAX - sizeof(*data_ptr) < reg_cfg_cmd->u.rw_info.reg_offset) || (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.rw_info.reg_offset + sizeof(*data_ptr))) { pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__); return -EINVAL; } msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + reg_cfg_cmd->u.rw_info.reg_offset); break; } case VFE_CFG_MASK: { uint32_t temp; if (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.mask_info.reg_offset) return -EINVAL; temp = msm_camera_io_r(vfe_dev->vfe_base + reg_cfg_cmd->u.mask_info.reg_offset); temp &= ~reg_cfg_cmd->u.mask_info.mask; temp |= reg_cfg_cmd->u.mask_info.val; if ((UINT_MAX - sizeof(temp) < reg_cfg_cmd->u.mask_info.reg_offset) || (resource_size(vfe_dev->vfe_mem) < reg_cfg_cmd->u.mask_info.reg_offset + sizeof(temp))) { pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__); return -EINVAL; } msm_camera_io_w(temp, vfe_dev->vfe_base + reg_cfg_cmd->u.mask_info.reg_offset); break; } case VFE_WRITE_DMI_16BIT: case VFE_WRITE_DMI_32BIT: case VFE_WRITE_DMI_64BIT: { int i; uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; uint32_t hi_val, lo_val, lo_val1; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset < reg_cfg_cmd->u.dmi_info.len) || (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + reg_cfg_cmd->u.dmi_info.len > cmd_len)) { pr_err("Invalid Hi Table out of bounds\n"); return -EINVAL; } hi_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; } if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + reg_cfg_cmd->u.dmi_info.len > cmd_len) { pr_err("Invalid Lo Table out of bounds\n"); return -EINVAL; } lo_tbl_ptr = cfg_data + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) reg_cfg_cmd->u.dmi_info.len = reg_cfg_cmd->u.dmi_info.len / 2; for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) { lo_val = *lo_tbl_ptr++; if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_16BIT) { lo_val1 = lo_val & 0x0000FFFF; lo_val = (lo_val & 0xFFFF0000)>>16; msm_camera_io_w(lo_val1, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } else if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { lo_tbl_ptr++; hi_val = *hi_tbl_ptr; hi_tbl_ptr = hi_tbl_ptr + 2; msm_camera_io_w(hi_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset); } msm_camera_io_w(lo_val, vfe_dev->vfe_base + vfe_dev->hw_info->dmi_reg_offset + 0x4); } break; }
static int msm_ispif_reset(struct ispif_device *ispif) { int rc = 0; int i; // memset(ispif->sof_count, 0, sizeof(ispif->sof_count)); for (i = 0; i < ispif->vfe_info.num_vfe; i++) { msm_camera_io_w(1 << PIX0_LINE_BUF_EN_BIT, ispif->base + ISPIF_VFE_m_CTRL_0(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(i)); msm_camera_io_w(0xFFFFFFFF, ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(i)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INPUT_SEL(i)); msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_0(i)); msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY, ispif->base + ISPIF_VFE_m_INTF_CMD_1(i)); pr_debug("%s: base %x", __func__, (unsigned int)ispif->base); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1)); /* */ #if 0 msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 1)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 2)); #else msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 1)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_RDI_INTF_n_CID_MASK(i, 2)); #endif /* */ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(i, 0)); msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(i, 1)); } msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR); return rc; }