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; } } 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)); } } pr_err("%s intf_cmd 0x%x cmd_bits 0x%x\n", __func__, ispif->applied_intf_cmd[vfe_intf].intf_cmd, cmd_bits); /* 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_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 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 int msm_ispif_validate_intf_status(struct ispif_device *ispif, uint8_t intftype, uint8_t vfe_intf) { int rc = 0; uint32_t data = 0; BUG_ON(!ispif); if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); return -EINVAL; } switch (intftype) { case PIX0: data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 0)); break; case RDI0: data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 0)); break; case PIX1: data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1)); break; case RDI1: data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 1)); break; case RDI2: data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 2)); break; } if ((data & 0xf) != 0xf) rc = -EBUSY; return rc; }
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 int msm_ispif_stop_frame_boundary(struct ispif_device *ispif, struct msm_ispif_param_data *params) { int i, rc = 0; uint16_t cid_mask = 0; uint32_t intf_addr; enum msm_ispif_vfe_intf vfe_intf; uint32_t stop_flag = 0; 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++) { if (!msm_ispif_is_intf_valid(ispif->csid_version, params->entries[i].vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); rc = -EINVAL; goto end; } } msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY, params); for (i = 0; i < params->num; i++) { cid_mask = msm_ispif_get_cids_mask_from_cfg(¶ms->entries[i]); vfe_intf = params->entries[i].vfe_intf; switch (params->entries[i].intftype) { case PIX0: intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 0); break; case RDI0: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 0); break; case PIX1: intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1); break; case RDI1: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 1); break; case RDI2: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 2); break; default: pr_err("%s: invalid intftype=%d\n", __func__, params->entries[i].intftype); rc = -EPERM; goto end; } rc = readl_poll_timeout(ispif->base + intf_addr, stop_flag, (stop_flag & 0xF) == 0xF, ISPIF_TIMEOUT_SLEEP_US, ISPIF_TIMEOUT_ALL_US); if (rc < 0) goto end; /* disable CIDs in CID_MASK register */ msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype, cid_mask, vfe_intf, 0); } end: return rc; }
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_stop_frame_boundary(struct ispif_device *ispif, struct msm_ispif_param_data *params) { int i, rc = 0; uint16_t cid_mask = 0; uint32_t intf_addr; 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; } for (i = 0; i < params->num; i++) { if (!msm_ispif_is_intf_valid(ispif->csid_version, params->entries[i].vfe_intf)) { pr_err("%s: invalid interface type\n", __func__); rc = -EINVAL; goto end; } } msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_FRAME_BOUNDARY, params); for (i = 0; i < params->num; i++) { cid_mask = msm_ispif_get_cids_mask_from_cfg(¶ms->entries[i]); vfe_intf = params->entries[i].vfe_intf; switch (params->entries[i].intftype) { case PIX0: intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 0); break; case RDI0: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 0); break; case PIX1: intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1); break; case RDI1: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 1); break; case RDI2: intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 2); break; default: pr_err("%s: invalid intftype=%d\n", __func__, params->entries[i].intftype); rc = -EPERM; goto end; } /* todo_bug_fix? very bad. use readl_poll_timeout */ while ((msm_camera_io_r(ispif->base + intf_addr) & 0xF) != 0xF) CDBG("%s: Wait for %d Idle\n", __func__, params->entries[i].intftype); /* disable CIDs in CID_MASK register */ msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype, cid_mask, vfe_intf, 0); } end: return rc; }