static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) { struct fimc_isp *isp = v4l2_get_subdevdata(sd); struct fimc_is *is = fimc_isp_to_is(isp); int ret; isp_dbg(1, sd, "%s: on: %d\n", __func__, on); if (!test_bit(IS_ST_INIT_DONE, &is->state)) return -EBUSY; fimc_is_mem_barrier(); if (on) { if (__get_pending_param_count(is)) { ret = fimc_is_itf_s_param(is, true); if (ret < 0) return ret; } isp_dbg(1, sd, "changing mode to %d\n", is->config_index); ret = fimc_is_itf_mode_change(is); if (ret) return -EINVAL; clear_bit(IS_ST_STREAM_ON, &is->state); fimc_is_hw_stream_on(is); ret = fimc_is_wait_event(is, IS_ST_STREAM_ON, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { v4l2_err(sd, "stream on timeout\n"); return ret; } } else { clear_bit(IS_ST_STREAM_OFF, &is->state); fimc_is_hw_stream_off(is); ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { v4l2_err(sd, "stream off timeout\n"); return ret; } is->setfile.sub_index = 0; } return 0; }
static int fimc_is_hw_open_sensor(struct fimc_is *is, struct fimc_is_sensor *sensor) { struct sensor_open_extended *soe = (void *)&is->is_p_region->shared; fimc_is_hw_wait_intmsr0_intmsd0(is); soe->self_calibration_mode = 1; soe->actuator_type = 0; soe->mipi_lane_num = 0; soe->mclk = 0; soe->mipi_speed = 0; soe->fast_open_sensor = 0; soe->i2c_sclk = 88000000; fimc_is_mem_barrier(); mcuctl_write(HIC_OPEN_SENSOR, is, MCUCTL_REG_ISSR(0)); mcuctl_write(is->sensor_index, is, MCUCTL_REG_ISSR(1)); mcuctl_write(sensor->drvdata->id, is, MCUCTL_REG_ISSR(2)); mcuctl_write(sensor->i2c_bus, is, MCUCTL_REG_ISSR(3)); mcuctl_write(is->is_dma_p_region, is, MCUCTL_REG_ISSR(4)); fimc_is_hw_set_intgr0_gd0(is); return fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 1, FIMC_IS_SENSOR_OPEN_TIMEOUT); }
int fimc_is_itf_mode_change(struct fimc_is *is) { int ret; clear_bit(IS_ST_CHANGE_MODE, &is->state); fimc_is_hw_change_mode(is); ret = fimc_is_wait_event(is, IS_ST_CHANGE_MODE, 1, FIMC_IS_CONFIG_TIMEOUT); if (!ret < 0) dev_err(&is->pdev->dev, "%s(): mode change (%d) timeout\n", __func__, is->config_index); return ret; }
int fimc_is_itf_s_param(struct fimc_is *is, bool update) { int ret; if (update) __is_hw_update_params(is); fimc_is_mem_barrier(); clear_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); fimc_is_hw_set_param(is); ret = fimc_is_wait_event(is, IS_ST_BLOCK_CMD_CLEARED, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) dev_err(&is->pdev->dev, "%s() timeout\n", __func__); return ret; }
int fimc_is_start_firmware(struct fimc_is *is) { struct device *dev = &is->pdev->dev; int ret; memcpy(is->memory.vaddr, is->fw.f_w->data, is->fw.f_w->size); wmb(); ret = fimc_is_cpu_set_power(is, 1); if (ret < 0) return ret; ret = fimc_is_wait_event(is, IS_ST_A5_PWR_ON, 1, msecs_to_jiffies(FIMC_IS_FW_LOAD_TIMEOUT)); if (ret < 0) dev_err(dev, "FIMC-IS CPU power on failed\n"); return ret; }
static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on) { struct fimc_isp *isp = v4l2_get_subdevdata(sd); struct fimc_is *is = fimc_isp_to_is(isp); int ret = 0; pr_debug("on: %d\n", on); if (on) { ret = pm_runtime_get_sync(&is->pdev->dev); if (ret < 0) return ret; set_bit(IS_ST_PWR_ON, &is->state); ret = fimc_is_start_firmware(is); if (ret < 0) { v4l2_err(sd, "firmware booting failed\n"); pm_runtime_put(&is->pdev->dev); return ret; } set_bit(IS_ST_PWR_SUBIP_ON, &is->state); ret = fimc_is_hw_initialize(is); } else { /* Close sensor */ if (!test_bit(IS_ST_PWR_ON, &is->state)) { fimc_is_hw_close_sensor(is, 0); ret = fimc_is_wait_event(is, IS_ST_OPEN_SENSOR, 0, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { v4l2_err(sd, "sensor close timeout\n"); return ret; } } /* SUB IP power off */ if (test_bit(IS_ST_PWR_SUBIP_ON, &is->state)) { fimc_is_hw_subip_power_off(is); ret = fimc_is_wait_event(is, IS_ST_PWR_SUBIP_ON, 0, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { v4l2_err(sd, "sub-IP power off timeout\n"); return ret; } } fimc_is_cpu_set_power(is, 0); pm_runtime_put_sync(&is->pdev->dev); clear_bit(IS_ST_PWR_ON, &is->state); clear_bit(IS_ST_INIT_DONE, &is->state); is->state = 0; is->config[is->config_index].p_region_index[0] = 0; is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_IDLE, &is->state); wmb(); } return ret; }
int fimc_is_hw_initialize(struct fimc_is *is) { const int config_ids[] = { IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO, IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO }; struct device *dev = &is->pdev->dev; u32 prev_id; int i, ret; /* Sensor initialization. */ ret = fimc_is_hw_open_sensor(is, is->sensor); if (ret < 0) return ret; /* Get the setfile address. */ fimc_is_hw_get_setfile_addr(is); ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { dev_err(dev, "get setfile address timed out\n"); return ret; } pr_debug("setfile.base: %#x\n", is->setfile.base); /* Load the setfile. */ fimc_is_load_setfile(is, FIMC_IS_SETFILE_6A3); clear_bit(IS_ST_SETFILE_LOADED, &is->state); fimc_is_hw_load_setfile(is); ret = fimc_is_wait_event(is, IS_ST_SETFILE_LOADED, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { dev_err(dev, "loading setfile timed out\n"); return ret; } pr_debug("setfile: base: %#x, size: %d\n", is->setfile.base, is->setfile.size); pr_info("FIMC-IS Setfile info: %s\n", is->fw.setfile_info); /* Check magic number. */ if (is->is_p_region->shared[MAX_SHARED_COUNT - 1] != FIMC_IS_MAGIC_NUMBER) { dev_err(dev, "magic number error!\n"); return -EIO; } pr_debug("shared region: %#x, parameter region: %#x\n", is->memory.paddr + FIMC_IS_SHARED_REGION_OFFSET, is->is_dma_p_region); is->setfile.sub_index = 0; /* Stream off. */ fimc_is_hw_stream_off(is); ret = fimc_is_wait_event(is, IS_ST_STREAM_OFF, 1, FIMC_IS_CONFIG_TIMEOUT); if (ret < 0) { dev_err(dev, "stream off timeout\n"); return ret; } /* Preserve previous mode. */ prev_id = is->config_index; /* Set initial parameter values. */ for (i = 0; i < ARRAY_SIZE(config_ids); i++) { is->config_index = config_ids[i]; fimc_is_set_initial_params(is); ret = fimc_is_itf_s_param(is, true); if (ret < 0) { is->config_index = prev_id; return ret; } } is->config_index = prev_id; set_bit(IS_ST_INIT_DONE, &is->state); dev_info(dev, "initialization sequence completed (%d)\n", is->config_index); return 0; }