Lines Matching +full:fimc +full:- +full:isp
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Samsung EXYNOS4x12 FIMC-IS (Imaging Subsystem) driver
22 #include <media/v4l2-device.h>
24 #include "media-dev.h"
25 #include "fimc-isp-video.h"
26 #include "fimc-is-command.h"
27 #include "fimc-is-param.h"
28 #include "fimc-is-regs.h"
29 #include "fimc-is.h"
57 * fimc_isp_find_format - lookup color format by fourcc or media bus code
74 if (pixelformat && fmt->fourcc == *pixelformat) in fimc_isp_find_format()
76 if (mbus_code && fmt->mbus_code == *mbus_code) in fimc_isp_find_format()
87 is->i2h_cmd.args[0] = mcuctl_read(is, MCUCTL_REG_ISSR(20)); in fimc_isp_irq_handler()
88 is->i2h_cmd.args[1] = mcuctl_read(is, MCUCTL_REG_ISSR(21)); in fimc_isp_irq_handler()
93 wake_up(&is->irq_queue); in fimc_isp_irq_handler()
114 fmt = fimc_isp_find_format(NULL, NULL, code->index); in fimc_is_subdev_enum_mbus_code()
116 return -EINVAL; in fimc_is_subdev_enum_mbus_code()
117 code->code = fmt->mbus_code; in fimc_is_subdev_enum_mbus_code()
125 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_get_fmt() local
126 struct v4l2_mbus_framefmt *mf = &fmt->format; in fimc_isp_subdev_get_fmt()
128 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in fimc_isp_subdev_get_fmt()
129 *mf = *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); in fimc_isp_subdev_get_fmt()
133 mf->colorspace = V4L2_COLORSPACE_SRGB; in fimc_isp_subdev_get_fmt()
135 mutex_lock(&isp->subdev_lock); in fimc_isp_subdev_get_fmt()
137 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in fimc_isp_subdev_get_fmt()
138 /* ISP OTF input image format */ in fimc_isp_subdev_get_fmt()
139 *mf = isp->sink_fmt; in fimc_isp_subdev_get_fmt()
141 /* ISP OTF output image format */ in fimc_isp_subdev_get_fmt()
142 *mf = isp->src_fmt; in fimc_isp_subdev_get_fmt()
144 if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { in fimc_isp_subdev_get_fmt()
145 mf->colorspace = V4L2_COLORSPACE_JPEG; in fimc_isp_subdev_get_fmt()
146 mf->code = MEDIA_BUS_FMT_YUV10_1X30; in fimc_isp_subdev_get_fmt()
150 mutex_unlock(&isp->subdev_lock); in fimc_isp_subdev_get_fmt()
153 fmt->pad, mf->code, mf->width, mf->height); in fimc_isp_subdev_get_fmt()
158 static void __isp_subdev_try_format(struct fimc_isp *isp, in __isp_subdev_try_format() argument
162 struct v4l2_mbus_framefmt *mf = &fmt->format; in __isp_subdev_try_format()
165 mf->colorspace = V4L2_COLORSPACE_SRGB; in __isp_subdev_try_format()
167 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in __isp_subdev_try_format()
168 v4l_bound_align_image(&mf->width, FIMC_ISP_SINK_WIDTH_MIN, in __isp_subdev_try_format()
170 &mf->height, FIMC_ISP_SINK_HEIGHT_MIN, in __isp_subdev_try_format()
172 mf->code = MEDIA_BUS_FMT_SGRBG10_1X10; in __isp_subdev_try_format()
174 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) in __isp_subdev_try_format()
175 format = v4l2_subdev_get_try_format(&isp->subdev, in __isp_subdev_try_format()
179 format = &isp->sink_fmt; in __isp_subdev_try_format()
182 mf->width = format->width - FIMC_ISP_CAC_MARGIN_WIDTH; in __isp_subdev_try_format()
183 mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT; in __isp_subdev_try_format()
185 if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { in __isp_subdev_try_format()
186 mf->code = MEDIA_BUS_FMT_YUV10_1X30; in __isp_subdev_try_format()
187 mf->colorspace = V4L2_COLORSPACE_JPEG; in __isp_subdev_try_format()
189 mf->code = format->code; in __isp_subdev_try_format()
198 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_set_fmt() local
199 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_set_fmt()
200 struct v4l2_mbus_framefmt *mf = &fmt->format; in fimc_isp_subdev_set_fmt()
204 __func__, fmt->pad, mf->code, mf->width, mf->height); in fimc_isp_subdev_set_fmt()
206 mutex_lock(&isp->subdev_lock); in fimc_isp_subdev_set_fmt()
207 __isp_subdev_try_format(isp, sd_state, fmt); in fimc_isp_subdev_set_fmt()
209 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in fimc_isp_subdev_set_fmt()
210 mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); in fimc_isp_subdev_set_fmt()
211 *mf = fmt->format; in fimc_isp_subdev_set_fmt()
214 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in fimc_isp_subdev_set_fmt()
221 __isp_subdev_try_format(isp, sd_state, in fimc_isp_subdev_set_fmt()
229 if (!media_entity_is_streaming(&sd->entity)) { in fimc_isp_subdev_set_fmt()
230 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in fimc_isp_subdev_set_fmt()
233 isp->sink_fmt = *mf; in fimc_isp_subdev_set_fmt()
236 __isp_subdev_try_format(isp, sd_state, in fimc_isp_subdev_set_fmt()
239 isp->src_fmt = format.format; in fimc_isp_subdev_set_fmt()
240 __is_set_frame_size(is, &isp->src_fmt); in fimc_isp_subdev_set_fmt()
242 isp->src_fmt = *mf; in fimc_isp_subdev_set_fmt()
245 ret = -EBUSY; in fimc_isp_subdev_set_fmt()
249 mutex_unlock(&isp->subdev_lock); in fimc_isp_subdev_set_fmt()
255 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_s_stream() local
256 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_s_stream()
261 if (!test_bit(IS_ST_INIT_DONE, &is->state)) in fimc_isp_subdev_s_stream()
262 return -EBUSY; in fimc_isp_subdev_s_stream()
273 isp_dbg(1, sd, "changing mode to %d\n", is->config_index); in fimc_isp_subdev_s_stream()
277 return -EINVAL; in fimc_isp_subdev_s_stream()
279 clear_bit(IS_ST_STREAM_ON, &is->state); in fimc_isp_subdev_s_stream()
288 clear_bit(IS_ST_STREAM_OFF, &is->state); in fimc_isp_subdev_s_stream()
296 is->setfile.sub_index = 0; in fimc_isp_subdev_s_stream()
304 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_s_power() local
305 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_s_power()
311 ret = pm_runtime_resume_and_get(&is->pdev->dev); in fimc_isp_subdev_s_power()
315 set_bit(IS_ST_PWR_ON, &is->state); in fimc_isp_subdev_s_power()
320 pm_runtime_put(&is->pdev->dev); in fimc_isp_subdev_s_power()
323 set_bit(IS_ST_PWR_SUBIP_ON, &is->state); in fimc_isp_subdev_s_power()
328 if (!test_bit(IS_ST_PWR_ON, &is->state)) { in fimc_isp_subdev_s_power()
340 if (test_bit(IS_ST_PWR_SUBIP_ON, &is->state)) { in fimc_isp_subdev_s_power()
345 v4l2_err(sd, "sub-IP power off timeout\n"); in fimc_isp_subdev_s_power()
351 pm_runtime_put_sync(&is->pdev->dev); in fimc_isp_subdev_s_power()
353 clear_bit(IS_ST_PWR_ON, &is->state); in fimc_isp_subdev_s_power()
354 clear_bit(IS_ST_INIT_DONE, &is->state); in fimc_isp_subdev_s_power()
355 is->state = 0; in fimc_isp_subdev_s_power()
356 is->config[is->config_index].p_region_index[0] = 0; in fimc_isp_subdev_s_power()
357 is->config[is->config_index].p_region_index[1] = 0; in fimc_isp_subdev_s_power()
358 set_bit(IS_ST_IDLE, &is->state); in fimc_isp_subdev_s_power()
377 format = v4l2_subdev_get_try_format(sd, fh->state, in fimc_isp_subdev_open()
381 format = v4l2_subdev_get_try_format(sd, fh->state, in fimc_isp_subdev_open()
387 format = v4l2_subdev_get_try_format(sd, fh->state, in fimc_isp_subdev_open()
396 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_registered() local
400 isp->video_capture.ve.pipe = v4l2_get_subdev_hostdata(sd); in fimc_isp_subdev_registered()
402 ret = fimc_isp_video_device_register(isp, sd->v4l2_dev, in fimc_isp_subdev_registered()
405 isp->video_capture.ve.pipe = NULL; in fimc_isp_subdev_registered()
412 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_unregistered() local
414 fimc_isp_video_device_unregister(isp, in fimc_isp_subdev_unregistered()
467 return -EINVAL; in __ctrl_set_white_balance()
476 bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; in __ctrl_set_aewb_lock()
477 bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; in __ctrl_set_aewb_lock()
478 struct isp_param *isp = &is->is_p_region->parameter.isp; in __ctrl_set_aewb_lock() local
482 isp->aa.cmd = cmd; in __ctrl_set_aewb_lock()
483 isp->aa.target = ISP_AA_TARGET_AE; in __ctrl_set_aewb_lock()
485 is->af.ae_lock_state = ae_lock; in __ctrl_set_aewb_lock()
493 isp->aa.cmd = cmd; in __ctrl_set_aewb_lock()
494 isp->aa.target = ISP_AA_TARGET_AE; in __ctrl_set_aewb_lock()
496 is->af.awb_lock_state = awb_lock; in __ctrl_set_aewb_lock()
515 idx = is->isp.ctrls.iso->val; in __ctrl_set_iso()
517 return -EINVAL; in __ctrl_set_iso()
542 return -EINVAL; in __ctrl_set_metering()
565 return -EINVAL; in __ctrl_set_afc()
590 return -EINVAL; in __ctrl_set_image_effect()
595 struct fimc_isp *isp = ctrl_to_fimc_isp(ctrl); in fimc_is_s_ctrl() local
596 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_is_s_ctrl()
600 switch (ctrl->id) { in fimc_is_s_ctrl()
603 ctrl->val); in fimc_is_s_ctrl()
608 ctrl->val); in fimc_is_s_ctrl()
613 ctrl->val); in fimc_is_s_ctrl()
618 ctrl->val); in fimc_is_s_ctrl()
623 ctrl->val); in fimc_is_s_ctrl()
628 ctrl->val); in fimc_is_s_ctrl()
632 ret = __ctrl_set_metering(is, ctrl->val); in fimc_is_s_ctrl()
636 ret = __ctrl_set_white_balance(is, ctrl->val); in fimc_is_s_ctrl()
645 ret = __ctrl_set_iso(is, ctrl->val); in fimc_is_s_ctrl()
649 ret = __ctrl_set_afc(is, ctrl->val); in fimc_is_s_ctrl()
653 __ctrl_set_image_effect(is, ctrl->val); in fimc_is_s_ctrl()
657 ret = -EINVAL; in fimc_is_s_ctrl()
662 v4l2_err(&isp->subdev, "Failed to set control: %s (%d)\n", in fimc_is_s_ctrl()
663 ctrl->name, ctrl->val); in fimc_is_s_ctrl()
667 if (set_param && test_bit(IS_ST_STREAM_ON, &is->state)) in fimc_is_s_ctrl()
677 static void __isp_subdev_set_default_format(struct fimc_isp *isp) in __isp_subdev_set_default_format() argument
679 struct fimc_is *is = fimc_isp_to_is(isp); in __isp_subdev_set_default_format()
681 isp->sink_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + in __isp_subdev_set_default_format()
683 isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + in __isp_subdev_set_default_format()
685 isp->sink_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; in __isp_subdev_set_default_format()
687 isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; in __isp_subdev_set_default_format()
688 isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; in __isp_subdev_set_default_format()
689 isp->src_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; in __isp_subdev_set_default_format()
690 __is_set_frame_size(is, &isp->src_fmt); in __isp_subdev_set_default_format()
693 int fimc_isp_subdev_create(struct fimc_isp *isp) in fimc_isp_subdev_create() argument
696 struct v4l2_ctrl_handler *handler = &isp->ctrls.handler; in fimc_isp_subdev_create()
697 struct v4l2_subdev *sd = &isp->subdev; in fimc_isp_subdev_create()
698 struct fimc_isp_ctrls *ctrls = &isp->ctrls; in fimc_isp_subdev_create()
701 mutex_init(&isp->subdev_lock); in fimc_isp_subdev_create()
705 sd->owner = THIS_MODULE; in fimc_isp_subdev_create()
706 sd->grp_id = GRP_ID_FIMC_IS; in fimc_isp_subdev_create()
707 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in fimc_isp_subdev_create()
708 snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); in fimc_isp_subdev_create()
710 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; in fimc_isp_subdev_create()
711 isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; in fimc_isp_subdev_create()
712 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE; in fimc_isp_subdev_create()
713 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE; in fimc_isp_subdev_create()
714 ret = media_entity_pads_init(&sd->entity, FIMC_ISP_SD_PADS_NUM, in fimc_isp_subdev_create()
715 isp->subdev_pads); in fimc_isp_subdev_create()
721 ctrls->saturation = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SATURATION, in fimc_isp_subdev_create()
722 -2, 2, 1, 0); in fimc_isp_subdev_create()
723 ctrls->brightness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_BRIGHTNESS, in fimc_isp_subdev_create()
724 -4, 4, 1, 0); in fimc_isp_subdev_create()
725 ctrls->contrast = v4l2_ctrl_new_std(handler, ops, V4L2_CID_CONTRAST, in fimc_isp_subdev_create()
726 -2, 2, 1, 0); in fimc_isp_subdev_create()
727 ctrls->sharpness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SHARPNESS, in fimc_isp_subdev_create()
728 -2, 2, 1, 0); in fimc_isp_subdev_create()
729 ctrls->hue = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HUE, in fimc_isp_subdev_create()
730 -2, 2, 1, 0); in fimc_isp_subdev_create()
732 ctrls->auto_wb = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
736 ctrls->exposure = v4l2_ctrl_new_std(handler, ops, in fimc_isp_subdev_create()
738 -4, 4, 1, 0); in fimc_isp_subdev_create()
740 ctrls->exp_metering = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
748 ctrls->auto_iso = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
752 ctrls->iso = v4l2_ctrl_new_int_menu(handler, ops, in fimc_isp_subdev_create()
753 V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1, in fimc_isp_subdev_create()
754 ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu); in fimc_isp_subdev_create()
756 ctrls->aewb_lock = v4l2_ctrl_new_std(handler, ops, in fimc_isp_subdev_create()
760 ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_COLORFX, in fimc_isp_subdev_create()
763 if (handler->error) { in fimc_isp_subdev_create()
764 media_entity_cleanup(&sd->entity); in fimc_isp_subdev_create()
765 return handler->error; in fimc_isp_subdev_create()
768 v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso, in fimc_isp_subdev_create()
771 sd->ctrl_handler = handler; in fimc_isp_subdev_create()
772 sd->internal_ops = &fimc_is_subdev_internal_ops; in fimc_isp_subdev_create()
773 sd->entity.ops = &fimc_is_subdev_media_ops; in fimc_isp_subdev_create()
774 v4l2_set_subdevdata(sd, isp); in fimc_isp_subdev_create()
776 __isp_subdev_set_default_format(isp); in fimc_isp_subdev_create()
781 void fimc_isp_subdev_destroy(struct fimc_isp *isp) in fimc_isp_subdev_destroy() argument
783 struct v4l2_subdev *sd = &isp->subdev; in fimc_isp_subdev_destroy()
786 media_entity_cleanup(&sd->entity); in fimc_isp_subdev_destroy()
787 v4l2_ctrl_handler_free(&isp->ctrls.handler); in fimc_isp_subdev_destroy()