static int __ctrl_set_aewb_lock(struct fimc_is *is, struct v4l2_ctrl *ctrl) { bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; struct isp_param *isp = &is->is_p_region->parameter.isp; int cmd, ret; cmd = ae_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START; isp->aa.cmd = cmd; isp->aa.target = ISP_AA_TARGET_AE; fimc_is_set_param_bit(is, PARAM_ISP_AA); is->af.ae_lock_state = ae_lock; wmb(); ret = fimc_is_itf_s_param(is, false); if (ret < 0) return ret; cmd = awb_lock ? ISP_AA_COMMAND_STOP : ISP_AA_COMMAND_START; isp->aa.cmd = cmd; isp->aa.target = ISP_AA_TARGET_AE; fimc_is_set_param_bit(is, PARAM_ISP_AA); is->af.awb_lock_state = awb_lock; wmb(); return fimc_is_itf_s_param(is, false); }
static void isp_video_capture_stop_streaming(struct vb2_queue *q) { struct fimc_isp *isp = vb2_get_drv_priv(q); struct fimc_is *is = fimc_isp_to_is(isp); struct param_dma_output *dma = __get_isp_dma2(is); int ret; ret = fimc_pipeline_call(&isp->video_capture.ve, set_stream, 0); if (ret < 0) return; dma->cmd = DMA_OUTPUT_COMMAND_DISABLE; dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_DISABLE; dma->buffer_number = 0; dma->buffer_address = 0; dma->dma_out_mask = 0; fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT); __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT); ret = fimc_is_itf_s_param(is, false); if (ret < 0) dev_warn(&is->pdev->dev, "%s: DMA stop failed\n", __func__); fimc_is_hw_set_isp_buf_mask(is, 0); clear_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); clear_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); isp->video_capture.buf_count = 0; }
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 isp_video_capture_start_streaming(struct vb2_queue *q, unsigned int count) { struct fimc_isp *isp = vb2_get_drv_priv(q); struct fimc_is *is = fimc_isp_to_is(isp); struct param_dma_output *dma = __get_isp_dma2(is); struct fimc_is_video *video = &isp->video_capture; int ret; if (!test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state) || test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) return 0; dma->cmd = DMA_OUTPUT_COMMAND_ENABLE; dma->notify_dma_done = DMA_OUTPUT_NOTIFY_DMA_DONE_ENABLE; dma->buffer_address = is->is_dma_p_region + DMA2_OUTPUT_ADDR_ARRAY_OFFS; dma->buffer_number = video->reqbufs_count; dma->dma_out_mask = video->buf_mask; isp_dbg(2, &video->ve.vdev, "buf_count: %d, planes: %d, dma addr table: %#x\n", video->buf_count, video->format->memplanes, dma->buffer_address); fimc_is_mem_barrier(); fimc_is_set_param_bit(is, PARAM_ISP_DMA2_OUTPUT); __fimc_is_hw_update_param(is, PARAM_ISP_DMA2_OUTPUT); ret = fimc_is_itf_s_param(is, false); if (ret < 0) return ret; ret = fimc_pipeline_call(&video->ve, set_stream, 1); if (ret < 0) return ret; set_bit(ST_ISP_VID_CAP_STREAMING, &isp->state); return ret; }
static int fimc_is_s_ctrl(struct v4l2_ctrl *ctrl) { struct fimc_isp *isp = ctrl_to_fimc_isp(ctrl); struct fimc_is *is = fimc_isp_to_is(isp); bool set_param = true; int ret = 0; switch (ctrl->id) { case V4L2_CID_CONTRAST: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, ctrl->val); break; case V4L2_CID_SATURATION: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SATURATION, ctrl->val); break; case V4L2_CID_SHARPNESS: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SHARPNESS, ctrl->val); break; case V4L2_CID_EXPOSURE_ABSOLUTE: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_EXPOSURE, ctrl->val); break; case V4L2_CID_BRIGHTNESS: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_BRIGHTNESS, ctrl->val); break; case V4L2_CID_HUE: __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, ctrl->val); break; case V4L2_CID_EXPOSURE_METERING: ret = __ctrl_set_metering(is, ctrl->val); break; case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE: ret = __ctrl_set_white_balance(is, ctrl->val); break; case V4L2_CID_3A_LOCK: ret = __ctrl_set_aewb_lock(is, ctrl); set_param = false; break; case V4L2_CID_ISO_SENSITIVITY_AUTO: ret = __ctrl_set_iso(is, ctrl->val); break; case V4L2_CID_POWER_LINE_FREQUENCY: ret = __ctrl_set_afc(is, ctrl->val); break; case V4L2_CID_COLORFX: __ctrl_set_image_effect(is, ctrl->val); break; default: ret = -EINVAL; break; } if (ret < 0) { v4l2_err(&isp->subdev, "Failed to set control: %s (%d)\n", ctrl->name, ctrl->val); return ret; } if (set_param && test_bit(IS_ST_STREAM_ON, &is->state)) return fimc_is_itf_s_param(is, true); return 0; }
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; }
static int fimc_is_ischain_dis_tag(struct fimc_is_subdev *subdev, void *device_data, struct fimc_is_frame *frame, struct camera2_node *node) { int ret = 0; struct fimc_is_group *group; struct tpu_param *tpu_param; struct fimc_is_crop inparm; struct fimc_is_crop *incrop, *otcrop; struct fimc_is_subdev *leader; struct fimc_is_device_ischain *device; u32 lindex, hindex, indexes; device = (struct fimc_is_device_ischain *)device_data; BUG_ON(!subdev); BUG_ON(!device); BUG_ON(!device->is_region); BUG_ON(!frame); #ifdef DBG_STREAMING mdbgd_ischain("DIS TAG\n", device); #endif incrop = (struct fimc_is_crop *)node->input.cropRegion; otcrop = (struct fimc_is_crop *)node->output.cropRegion; group = &device->group_dis; leader = subdev->leader; lindex = hindex = indexes = 0; tpu_param = &device->is_region->parameter.tpu; if (test_bit(FIMC_IS_GROUP_OTF_INPUT, &group->state)) { inparm.x = 0; inparm.y = 0; inparm.w = tpu_param->otf_input.width; inparm.h = tpu_param->otf_input.height; } else { inparm.x = 0; inparm.y = 0; inparm.w = tpu_param->dma_input.width; inparm.h = tpu_param->dma_input.height; } if (IS_NULL_CROP(incrop)) *incrop = inparm; if (!COMPARE_CROP(incrop, &inparm)|| test_bit(FIMC_IS_SUBDEV_FORCE_SET, &leader->state)) { ret = fimc_is_ischain_dis_cfg(subdev, device, frame, incrop, otcrop, &lindex, &hindex, &indexes); if (ret) { merr("fimc_is_ischain_dis_cfg is fail(%d)", device, ret); goto p_err; } msrinfo("in_crop[%d, %d, %d, %d]\n", device, subdev, frame, incrop->x, incrop->y, incrop->w, incrop->h); } ret = fimc_is_itf_s_param(device, frame, lindex, hindex, indexes); if (ret) { mrerr("fimc_is_itf_s_param is fail(%d)", device, frame, ret); goto p_err; } p_err: return ret; }
static int fimc_is_ischain_3ac_tag(struct fimc_is_subdev *subdev, void *device_data, struct fimc_is_frame *ldr_frame, struct camera2_node *node) { int ret = 0; struct fimc_is_subdev *leader; struct fimc_is_queue *queue; struct camera2_scaler_uctl *scalerUd; struct taa_param *taa_param; struct fimc_is_crop *otcrop, otparm; struct fimc_is_device_ischain *device; u32 lindex, hindex, indexes; u32 pixelformat = 0; device = (struct fimc_is_device_ischain *)device_data; BUG_ON(!device); BUG_ON(!device->is_region); BUG_ON(!subdev); BUG_ON(!GET_SUBDEV_QUEUE(subdev)); BUG_ON(!ldr_frame); BUG_ON(!ldr_frame->shot); #ifdef DBG_STREAMING mdbgd_ischain("3AAC TAG(request %d)\n", device, node->request); #endif lindex = hindex = indexes = 0; leader = subdev->leader; taa_param = &device->is_region->parameter.taa; scalerUd = &ldr_frame->shot->uctl.scalerUd; queue = GET_SUBDEV_QUEUE(subdev); if (!queue) { merr("queue is NULL", device); ret = -EINVAL; goto p_err; } if (!queue->framecfg.format) { merr("format is NULL", device); ret = -EINVAL; goto p_err; } pixelformat = queue->framecfg.format->pixelformat; if (node->request) { otcrop = (struct fimc_is_crop *)node->output.cropRegion; otparm.x = 0; otparm.y = 0; otparm.w = taa_param->otf_input.bayer_crop_width; otparm.h = taa_param->otf_input.bayer_crop_height; if (IS_NULL_CROP(otcrop)) *otcrop = otparm; if (!COMPARE_CROP(otcrop, &otparm) || !test_bit(FIMC_IS_SUBDEV_RUN, &subdev->state) || test_bit(FIMC_IS_SUBDEV_FORCE_SET, &leader->state)) { ret = fimc_is_ischain_3ac_start(device, subdev, ldr_frame, queue, taa_param, otcrop, &lindex, &hindex, &indexes); if (ret) { merr("fimc_is_ischain_3ac_start is fail(%d)", device, ret); goto p_err; } mdbg_pframe("ot_crop[%d, %d, %d, %d]\n", device, subdev, ldr_frame, otcrop->x, otcrop->y, otcrop->w, otcrop->h); } ret = fimc_is_ischain_buf_tag(device, subdev, ldr_frame, pixelformat, otcrop->w, otcrop->h, scalerUd->txcTargetAddress); if (ret) { mswarn("%d frame is drop", device, subdev, ldr_frame->fcount); node->request = 0; } } else { if (test_bit(FIMC_IS_SUBDEV_RUN, &subdev->state)) { ret = fimc_is_ischain_3ac_stop(device, subdev, ldr_frame, &lindex, &hindex, &indexes); if (ret) { merr("fimc_is_ischain_3ac_stop is fail(%d)", device, ret); goto p_err; } msrinfo(" off\n", device, subdev, ldr_frame); } scalerUd->txcTargetAddress[0] = 0; scalerUd->txcTargetAddress[1] = 0; scalerUd->txcTargetAddress[2] = 0; node->request = 0; } ret = fimc_is_itf_s_param(device, ldr_frame, lindex, hindex, indexes); if (ret) { mrerr("fimc_is_itf_s_param is fail(%d)", device, ldr_frame, ret); goto p_err; } p_err: return ret; }