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_state_get_format(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()
178 format = &isp->sink_fmt; in __isp_subdev_try_format()
181 mf->width = format->width - FIMC_ISP_CAC_MARGIN_WIDTH; in __isp_subdev_try_format()
182 mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT; in __isp_subdev_try_format()
184 if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { in __isp_subdev_try_format()
185 mf->code = MEDIA_BUS_FMT_YUV10_1X30; in __isp_subdev_try_format()
186 mf->colorspace = V4L2_COLORSPACE_JPEG; in __isp_subdev_try_format()
188 mf->code = format->code; in __isp_subdev_try_format()
197 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_set_fmt() local
198 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_set_fmt()
199 struct v4l2_mbus_framefmt *mf = &fmt->format; in fimc_isp_subdev_set_fmt()
203 __func__, fmt->pad, mf->code, mf->width, mf->height); in fimc_isp_subdev_set_fmt()
205 mutex_lock(&isp->subdev_lock); in fimc_isp_subdev_set_fmt()
206 __isp_subdev_try_format(isp, sd_state, fmt); in fimc_isp_subdev_set_fmt()
208 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in fimc_isp_subdev_set_fmt()
209 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad); in fimc_isp_subdev_set_fmt()
210 *mf = fmt->format; in fimc_isp_subdev_set_fmt()
213 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in fimc_isp_subdev_set_fmt()
220 __isp_subdev_try_format(isp, sd_state, in fimc_isp_subdev_set_fmt()
228 if (!media_entity_is_streaming(&sd->entity)) { in fimc_isp_subdev_set_fmt()
229 if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { in fimc_isp_subdev_set_fmt()
232 isp->sink_fmt = *mf; in fimc_isp_subdev_set_fmt()
235 __isp_subdev_try_format(isp, sd_state, in fimc_isp_subdev_set_fmt()
238 isp->src_fmt = format.format; in fimc_isp_subdev_set_fmt()
239 __is_set_frame_size(is, &isp->src_fmt); in fimc_isp_subdev_set_fmt()
241 isp->src_fmt = *mf; in fimc_isp_subdev_set_fmt()
244 ret = -EBUSY; in fimc_isp_subdev_set_fmt()
248 mutex_unlock(&isp->subdev_lock); in fimc_isp_subdev_set_fmt()
254 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_s_stream() local
255 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_s_stream()
260 if (!test_bit(IS_ST_INIT_DONE, &is->state)) in fimc_isp_subdev_s_stream()
261 return -EBUSY; in fimc_isp_subdev_s_stream()
272 isp_dbg(1, sd, "changing mode to %d\n", is->config_index); in fimc_isp_subdev_s_stream()
276 return -EINVAL; in fimc_isp_subdev_s_stream()
278 clear_bit(IS_ST_STREAM_ON, &is->state); in fimc_isp_subdev_s_stream()
287 clear_bit(IS_ST_STREAM_OFF, &is->state); in fimc_isp_subdev_s_stream()
295 is->setfile.sub_index = 0; in fimc_isp_subdev_s_stream()
303 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_s_power() local
304 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_isp_subdev_s_power()
310 ret = pm_runtime_resume_and_get(&is->pdev->dev); in fimc_isp_subdev_s_power()
314 set_bit(IS_ST_PWR_ON, &is->state); in fimc_isp_subdev_s_power()
319 pm_runtime_put(&is->pdev->dev); in fimc_isp_subdev_s_power()
322 set_bit(IS_ST_PWR_SUBIP_ON, &is->state); in fimc_isp_subdev_s_power()
327 if (!test_bit(IS_ST_PWR_ON, &is->state)) { in fimc_isp_subdev_s_power()
339 if (test_bit(IS_ST_PWR_SUBIP_ON, &is->state)) { in fimc_isp_subdev_s_power()
344 v4l2_err(sd, "sub-IP power off timeout\n"); in fimc_isp_subdev_s_power()
350 pm_runtime_put_sync(&is->pdev->dev); in fimc_isp_subdev_s_power()
352 clear_bit(IS_ST_PWR_ON, &is->state); in fimc_isp_subdev_s_power()
353 clear_bit(IS_ST_INIT_DONE, &is->state); in fimc_isp_subdev_s_power()
354 is->state = 0; in fimc_isp_subdev_s_power()
355 is->config[is->config_index].p_region_index[0] = 0; in fimc_isp_subdev_s_power()
356 is->config[is->config_index].p_region_index[1] = 0; in fimc_isp_subdev_s_power()
357 set_bit(IS_ST_IDLE, &is->state); in fimc_isp_subdev_s_power()
376 format = v4l2_subdev_state_get_format(fh->state, FIMC_ISP_SD_PAD_SINK); in fimc_isp_subdev_open()
379 format = v4l2_subdev_state_get_format(fh->state, in fimc_isp_subdev_open()
385 format = v4l2_subdev_state_get_format(fh->state, in fimc_isp_subdev_open()
394 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_registered() local
398 isp->video_capture.ve.pipe = v4l2_get_subdev_hostdata(sd); in fimc_isp_subdev_registered()
400 ret = fimc_isp_video_device_register(isp, sd->v4l2_dev, in fimc_isp_subdev_registered()
403 isp->video_capture.ve.pipe = NULL; in fimc_isp_subdev_registered()
410 struct fimc_isp *isp = v4l2_get_subdevdata(sd); in fimc_isp_subdev_unregistered() local
412 fimc_isp_video_device_unregister(isp, in fimc_isp_subdev_unregistered()
465 return -EINVAL; in __ctrl_set_white_balance()
474 bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; in __ctrl_set_aewb_lock()
475 bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; in __ctrl_set_aewb_lock()
476 struct isp_param *isp = &is->is_p_region->parameter.isp; in __ctrl_set_aewb_lock() local
480 isp->aa.cmd = cmd; in __ctrl_set_aewb_lock()
481 isp->aa.target = ISP_AA_TARGET_AE; in __ctrl_set_aewb_lock()
483 is->af.ae_lock_state = ae_lock; in __ctrl_set_aewb_lock()
491 isp->aa.cmd = cmd; in __ctrl_set_aewb_lock()
492 isp->aa.target = ISP_AA_TARGET_AE; in __ctrl_set_aewb_lock()
494 is->af.awb_lock_state = awb_lock; in __ctrl_set_aewb_lock()
513 idx = is->isp.ctrls.iso->val; in __ctrl_set_iso()
515 return -EINVAL; in __ctrl_set_iso()
540 return -EINVAL; in __ctrl_set_metering()
563 return -EINVAL; in __ctrl_set_afc()
588 return -EINVAL; in __ctrl_set_image_effect()
593 struct fimc_isp *isp = ctrl_to_fimc_isp(ctrl); in fimc_is_s_ctrl() local
594 struct fimc_is *is = fimc_isp_to_is(isp); in fimc_is_s_ctrl()
598 switch (ctrl->id) { in fimc_is_s_ctrl()
601 ctrl->val); in fimc_is_s_ctrl()
606 ctrl->val); in fimc_is_s_ctrl()
611 ctrl->val); in fimc_is_s_ctrl()
616 ctrl->val); in fimc_is_s_ctrl()
621 ctrl->val); in fimc_is_s_ctrl()
626 ctrl->val); in fimc_is_s_ctrl()
630 ret = __ctrl_set_metering(is, ctrl->val); in fimc_is_s_ctrl()
634 ret = __ctrl_set_white_balance(is, ctrl->val); in fimc_is_s_ctrl()
643 ret = __ctrl_set_iso(is, ctrl->val); in fimc_is_s_ctrl()
647 ret = __ctrl_set_afc(is, ctrl->val); in fimc_is_s_ctrl()
651 __ctrl_set_image_effect(is, ctrl->val); in fimc_is_s_ctrl()
655 ret = -EINVAL; in fimc_is_s_ctrl()
660 v4l2_err(&isp->subdev, "Failed to set control: %s (%d)\n", in fimc_is_s_ctrl()
661 ctrl->name, ctrl->val); in fimc_is_s_ctrl()
665 if (set_param && test_bit(IS_ST_STREAM_ON, &is->state)) in fimc_is_s_ctrl()
675 static void __isp_subdev_set_default_format(struct fimc_isp *isp) in __isp_subdev_set_default_format() argument
677 struct fimc_is *is = fimc_isp_to_is(isp); in __isp_subdev_set_default_format()
679 isp->sink_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + in __isp_subdev_set_default_format()
681 isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + in __isp_subdev_set_default_format()
683 isp->sink_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; in __isp_subdev_set_default_format()
685 isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; in __isp_subdev_set_default_format()
686 isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; in __isp_subdev_set_default_format()
687 isp->src_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10; in __isp_subdev_set_default_format()
688 __is_set_frame_size(is, &isp->src_fmt); in __isp_subdev_set_default_format()
691 int fimc_isp_subdev_create(struct fimc_isp *isp) in fimc_isp_subdev_create() argument
694 struct v4l2_ctrl_handler *handler = &isp->ctrls.handler; in fimc_isp_subdev_create()
695 struct v4l2_subdev *sd = &isp->subdev; in fimc_isp_subdev_create()
696 struct fimc_isp_ctrls *ctrls = &isp->ctrls; in fimc_isp_subdev_create()
699 mutex_init(&isp->subdev_lock); in fimc_isp_subdev_create()
703 sd->owner = THIS_MODULE; in fimc_isp_subdev_create()
704 sd->grp_id = GRP_ID_FIMC_IS; in fimc_isp_subdev_create()
705 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in fimc_isp_subdev_create()
706 snprintf(sd->name, sizeof(sd->name), "FIMC-IS-ISP"); in fimc_isp_subdev_create()
708 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; in fimc_isp_subdev_create()
709 isp->subdev_pads[FIMC_ISP_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; in fimc_isp_subdev_create()
710 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_FIFO].flags = MEDIA_PAD_FL_SOURCE; in fimc_isp_subdev_create()
711 isp->subdev_pads[FIMC_ISP_SD_PAD_SRC_DMA].flags = MEDIA_PAD_FL_SOURCE; in fimc_isp_subdev_create()
712 ret = media_entity_pads_init(&sd->entity, FIMC_ISP_SD_PADS_NUM, in fimc_isp_subdev_create()
713 isp->subdev_pads); in fimc_isp_subdev_create()
719 ctrls->saturation = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SATURATION, in fimc_isp_subdev_create()
720 -2, 2, 1, 0); in fimc_isp_subdev_create()
721 ctrls->brightness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_BRIGHTNESS, in fimc_isp_subdev_create()
722 -4, 4, 1, 0); in fimc_isp_subdev_create()
723 ctrls->contrast = v4l2_ctrl_new_std(handler, ops, V4L2_CID_CONTRAST, in fimc_isp_subdev_create()
724 -2, 2, 1, 0); in fimc_isp_subdev_create()
725 ctrls->sharpness = v4l2_ctrl_new_std(handler, ops, V4L2_CID_SHARPNESS, in fimc_isp_subdev_create()
726 -2, 2, 1, 0); in fimc_isp_subdev_create()
727 ctrls->hue = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HUE, in fimc_isp_subdev_create()
728 -2, 2, 1, 0); in fimc_isp_subdev_create()
730 ctrls->auto_wb = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
734 ctrls->exposure = v4l2_ctrl_new_std(handler, ops, in fimc_isp_subdev_create()
736 -4, 4, 1, 0); in fimc_isp_subdev_create()
738 ctrls->exp_metering = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
746 ctrls->auto_iso = v4l2_ctrl_new_std_menu(handler, ops, in fimc_isp_subdev_create()
750 ctrls->iso = v4l2_ctrl_new_int_menu(handler, ops, in fimc_isp_subdev_create()
751 V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1, in fimc_isp_subdev_create()
752 ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu); in fimc_isp_subdev_create()
754 ctrls->aewb_lock = v4l2_ctrl_new_std(handler, ops, in fimc_isp_subdev_create()
758 ctrls->colorfx = v4l2_ctrl_new_std_menu(handler, ops, V4L2_CID_COLORFX, in fimc_isp_subdev_create()
761 if (handler->error) { in fimc_isp_subdev_create()
762 media_entity_cleanup(&sd->entity); in fimc_isp_subdev_create()
763 return handler->error; in fimc_isp_subdev_create()
766 v4l2_ctrl_auto_cluster(2, &ctrls->auto_iso, in fimc_isp_subdev_create()
769 sd->ctrl_handler = handler; in fimc_isp_subdev_create()
770 sd->internal_ops = &fimc_is_subdev_internal_ops; in fimc_isp_subdev_create()
771 sd->entity.ops = &fimc_is_subdev_media_ops; in fimc_isp_subdev_create()
772 v4l2_set_subdevdata(sd, isp); in fimc_isp_subdev_create()
774 __isp_subdev_set_default_format(isp); in fimc_isp_subdev_create()
779 void fimc_isp_subdev_destroy(struct fimc_isp *isp) in fimc_isp_subdev_destroy() argument
781 struct v4l2_subdev *sd = &isp->subdev; in fimc_isp_subdev_destroy()
784 media_entity_cleanup(&sd->entity); in fimc_isp_subdev_destroy()
785 v4l2_ctrl_handler_free(&isp->ctrls.handler); in fimc_isp_subdev_destroy()