1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 StarFive Technology Co., Ltd.
6 #include <media/v4l2-async.h>
7 #include <media/v4l2-ctrls.h>
8 #include <media/v4l2-device.h>
9 #include <media/v4l2-event.h>
10 #include <media/v4l2-fwnode.h>
11 #include <media/v4l2-subdev.h>
12 #include <linux/firmware.h>
13 #include "stf_isp_ioctl.h"
14 #include "stf_dmabuf.h"
16 static int user_config_isp;
17 static int isp_set_selection(struct v4l2_subdev *sd,
18 struct v4l2_subdev_state *state,
19 struct v4l2_subdev_selection *sel);
21 static struct v4l2_rect *
22 __isp_get_compose(struct stf_isp_dev *isp_dev,
23 struct v4l2_subdev_state *state,
24 enum v4l2_subdev_format_whence which);
26 static struct v4l2_rect *
27 __isp_get_crop(struct stf_isp_dev *isp_dev,
28 struct v4l2_subdev_state *state,
29 enum v4l2_subdev_format_whence which);
31 static struct v4l2_rect *
32 __isp_get_scale(struct stf_isp_dev *isp_dev,
33 struct v4l2_subdev_state *state,
34 struct v4l2_subdev_selection *sel);
36 static struct v4l2_rect *
37 __isp_get_itiws(struct stf_isp_dev *isp_dev,
38 struct v4l2_subdev_state *state,
39 enum v4l2_subdev_format_whence which);
41 // sink format and raw format must one by one
42 static const struct isp_format isp_formats_st7110_sink[] = {
43 { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
44 { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
45 { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
46 { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
49 static const struct isp_format isp_formats_st7110_raw[] = {
50 { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
51 { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
52 { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
53 { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
56 static const struct isp_format isp_formats_st7110_compat_10bit_raw[] = {
57 { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
58 { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
59 { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
60 { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
63 static const struct isp_format isp_formats_st7110_compat_8bit_raw[] = {
64 { MEDIA_BUS_FMT_SRGGB8_1X8, 8},
65 { MEDIA_BUS_FMT_SGRBG8_1X8, 8},
66 { MEDIA_BUS_FMT_SGBRG8_1X8, 8},
67 { MEDIA_BUS_FMT_SBGGR8_1X8, 8},
70 static const struct isp_format isp_formats_st7110_uo[] = {
71 { MEDIA_BUS_FMT_Y12_1X12, 8},
74 static const struct isp_format isp_formats_st7110_iti[] = {
75 { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
76 { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
77 { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
78 { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
79 { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
80 { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
81 { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
82 { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
83 { MEDIA_BUS_FMT_Y12_1X12, 8},
84 { MEDIA_BUS_FMT_YUV8_1X24, 8},
87 #define SINK_FORMATS_INDEX 0
88 #define UO_FORMATS_INDEX 1
89 #define ITI_FORMATS_INDEX 2
90 #define RAW_FORMATS_INDEX 3
92 static const struct isp_format_table isp_formats_st7110[] = {
93 { isp_formats_st7110_sink, ARRAY_SIZE(isp_formats_st7110_sink) }, // 0
94 { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) }, // 1
95 { isp_formats_st7110_iti, ARRAY_SIZE(isp_formats_st7110_iti) }, // 2
96 { isp_formats_st7110_raw, ARRAY_SIZE(isp_formats_st7110_raw) }, // 3
99 int stf_isp_subdev_init(struct stfcamss *stfcamss)
101 struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
103 isp_dev->sdev_type = ISP_DEV_TYPE;
104 isp_dev->hw_ops = &isp_ops;
105 isp_dev->stfcamss = stfcamss;
106 isp_dev->formats = isp_formats_st7110;
107 isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110);
108 mutex_init(&isp_dev->stream_lock);
109 mutex_init(&isp_dev->power_lock);
110 mutex_init(&isp_dev->setfile_lock);
111 atomic_set(&isp_dev->shadow_count, 0);
119 static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
121 return &container_of(ctrl->handler, struct stf_isp_dev,
122 ctrls.handler)->subdev;
125 static u64 isp_calc_pixel_rate(struct stf_isp_dev *isp_dev)
132 static int isp_set_ctrl_hue(struct stf_isp_dev *isp_dev, int value)
139 static int isp_set_ctrl_contrast(struct stf_isp_dev *isp_dev, int value)
146 static int isp_set_ctrl_saturation(struct stf_isp_dev *isp_dev, int value)
153 static int isp_set_ctrl_white_balance(struct stf_isp_dev *isp_dev, int awb)
155 struct isp_ctrls *ctrls = &isp_dev->ctrls;
158 if (!awb && (ctrls->red_balance->is_new
159 || ctrls->blue_balance->is_new)) {
160 u16 red = (u16)ctrls->red_balance->val;
161 u16 blue = (u16)ctrls->blue_balance->val;
163 st_debug(ST_ISP, "red = 0x%x, blue = 0x%x\n", red, blue);
164 //isp_dev->hw_ops->isp_set_awb_r_gain(isp_dev, red);
167 //isp_dev->hw_ops->isp_set_awb_b_gain(isp_dev, blue);
173 static int isp_set_ctrl_exposure(struct stf_isp_dev *isp_dev,
174 enum v4l2_exposure_auto_type auto_exposure)
181 static int isp_set_ctrl_gain(struct stf_isp_dev *isp_dev, bool auto_gain)
188 static const char * const test_pattern_menu[] = {
191 "Color bars w/ rolling bar",
193 "Color squares w/ rolling bar",
196 #define ISP_TEST_ENABLE BIT(7)
197 #define ISP_TEST_ROLLING BIT(6) /* rolling horizontal bar */
198 #define ISP_TEST_TRANSPARENT BIT(5)
199 #define ISP_TEST_SQUARE_BW BIT(4) /* black & white squares */
200 #define ISP_TEST_BAR_STANDARD (0 << 2)
201 #define ISP_TEST_BAR_VERT_CHANGE_1 (1 << 2)
202 #define ISP_TEST_BAR_HOR_CHANGE (2 << 2)
203 #define ISP_TEST_BAR_VERT_CHANGE_2 (3 << 2)
204 #define ISP_TEST_BAR (0 << 0)
205 #define ISP_TEST_RANDOM (1 << 0)
206 #define ISP_TEST_SQUARE (2 << 0)
207 #define ISP_TEST_BLACK (3 << 0)
209 static const u8 test_pattern_val[] = {
211 ISP_TEST_ENABLE | ISP_TEST_BAR_VERT_CHANGE_1 |
213 ISP_TEST_ENABLE | ISP_TEST_ROLLING |
214 ISP_TEST_BAR_VERT_CHANGE_1 | ISP_TEST_BAR,
215 ISP_TEST_ENABLE | ISP_TEST_SQUARE,
216 ISP_TEST_ENABLE | ISP_TEST_ROLLING | ISP_TEST_SQUARE,
219 static int isp_set_ctrl_test_pattern(struct stf_isp_dev *isp_dev, int value)
223 // return isp_write_reg(isp_dev, ISP_REG_PRE_ISP_TEST_SET1,
224 // test_pattern_val[value]);
228 static int isp_set_ctrl_light_freq(struct stf_isp_dev *isp_dev, int value)
235 static int isp_set_ctrl_hflip(struct stf_isp_dev *isp_dev, int value)
242 static int isp_set_ctrl_vflip(struct stf_isp_dev *isp_dev, int value)
249 static int isp_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
252 case V4L2_CID_AUTOGAIN:
254 case V4L2_CID_EXPOSURE_AUTO:
261 static int isp_s_ctrl(struct v4l2_ctrl *ctrl)
263 struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
264 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
268 * If the device is not powered up by the host driver do
269 * not apply any controls to H/W at this time. Instead
270 * the controls will be restored right after power-up.
272 mutex_lock(&isp_dev->power_lock);
273 if (isp_dev->power_count == 0) {
274 mutex_unlock(&isp_dev->power_lock);
277 mutex_unlock(&isp_dev->power_lock);
280 case V4L2_CID_AUTOGAIN:
281 ret = isp_set_ctrl_gain(isp_dev, ctrl->val);
283 case V4L2_CID_EXPOSURE_AUTO:
284 ret = isp_set_ctrl_exposure(isp_dev, ctrl->val);
286 case V4L2_CID_AUTO_WHITE_BALANCE:
287 ret = isp_set_ctrl_white_balance(isp_dev, ctrl->val);
290 ret = isp_set_ctrl_hue(isp_dev, ctrl->val);
292 case V4L2_CID_CONTRAST:
293 ret = isp_set_ctrl_contrast(isp_dev, ctrl->val);
295 case V4L2_CID_SATURATION:
296 ret = isp_set_ctrl_saturation(isp_dev, ctrl->val);
298 case V4L2_CID_TEST_PATTERN:
299 ret = isp_set_ctrl_test_pattern(isp_dev, ctrl->val);
301 case V4L2_CID_POWER_LINE_FREQUENCY:
302 ret = isp_set_ctrl_light_freq(isp_dev, ctrl->val);
305 ret = isp_set_ctrl_hflip(isp_dev, ctrl->val);
308 ret = isp_set_ctrl_vflip(isp_dev, ctrl->val);
318 static const struct v4l2_ctrl_ops isp_ctrl_ops = {
319 .g_volatile_ctrl = isp_g_volatile_ctrl,
320 .s_ctrl = isp_s_ctrl,
323 static int isp_init_controls(struct stf_isp_dev *isp_dev)
325 const struct v4l2_ctrl_ops *ops = &isp_ctrl_ops;
326 struct isp_ctrls *ctrls = &isp_dev->ctrls;
327 struct v4l2_ctrl_handler *hdl = &ctrls->handler;
330 v4l2_ctrl_handler_init(hdl, 32);
332 /* Clock related controls */
333 ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
335 isp_calc_pixel_rate(isp_dev));
337 /* Auto/manual white balance */
338 ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
339 V4L2_CID_AUTO_WHITE_BALANCE,
341 ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
343 ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
345 /* Auto/manual exposure */
346 ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
347 V4L2_CID_EXPOSURE_AUTO,
348 V4L2_EXPOSURE_MANUAL, 0,
350 ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
352 /* Auto/manual gain */
353 ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
355 ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
358 ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
360 ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
362 ctrls->contrast = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
364 ctrls->test_pattern =
365 v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
366 ARRAY_SIZE(test_pattern_menu) - 1,
367 0, 0, test_pattern_menu);
368 ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
370 ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
374 v4l2_ctrl_new_std_menu(hdl, ops,
375 V4L2_CID_POWER_LINE_FREQUENCY,
376 V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
377 V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
384 ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
385 ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
386 ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
388 v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
389 v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
390 v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
392 isp_dev->subdev.ctrl_handler = hdl;
396 v4l2_ctrl_handler_free(hdl);
400 static int isp_set_power(struct v4l2_subdev *sd, int on)
402 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
403 struct stf_vin2_dev *vin_dev = isp_dev->stfcamss->vin_dev;
405 st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__);
406 mutex_lock(&isp_dev->power_lock);
408 if (isp_dev->power_count == 0) {
409 /* Needs to enable vin clock before access ISP. */
410 vin_dev->hw_ops->vin_top_clk_init(vin_dev);
411 vin_dev->hw_ops->vin_clk_enable(vin_dev);
412 isp_dev->hw_ops->isp_clk_enable(isp_dev);
413 if (!user_config_isp)
414 isp_dev->hw_ops->isp_config_set(isp_dev);
416 isp_dev->power_count++;
418 if (isp_dev->power_count == 0)
420 if (isp_dev->power_count == 1)
421 isp_dev->hw_ops->isp_clk_disable(isp_dev);
422 isp_dev->power_count--;
425 mutex_unlock(&isp_dev->power_lock);
430 static struct v4l2_mbus_framefmt *
431 __isp_get_format(struct stf_isp_dev *isp_dev,
432 struct v4l2_subdev_state *state,
434 enum v4l2_subdev_format_whence which)
437 if (which == V4L2_SUBDEV_FORMAT_TRY)
438 return v4l2_subdev_get_try_format(&isp_dev->subdev, state, pad);
440 return &isp_dev->fmt[pad];
443 static int isp_get_interface_type(struct media_entity *entity)
445 struct v4l2_subdev *subdev;
446 struct media_pad *pad = &entity->pads[0];
448 if (!(pad->flags & MEDIA_PAD_FL_SINK))
451 pad = media_entity_remote_pad(pad);
452 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
455 subdev = media_entity_to_v4l2_subdev(pad->entity);
457 st_debug(ST_ISP, "interface subdev name %s\n", subdev->name);
458 if (!strncmp(subdev->name, STF_CSI_NAME, strlen(STF_CSI_NAME)))
460 if (!strncmp(subdev->name, STF_DVP_NAME, strlen(STF_DVP_NAME)))
465 static int isp_set_stream(struct v4l2_subdev *sd, int enable)
467 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
468 int ret = 0, interface_type;
469 struct v4l2_mbus_framefmt *fmt;
470 struct v4l2_event src_ch = { 0 };
472 fmt = __isp_get_format(isp_dev, NULL, STF_ISP_PAD_SINK, V4L2_SUBDEV_FORMAT_ACTIVE);
473 mutex_lock(&isp_dev->stream_lock);
475 if (isp_dev->stream_count == 0) {
476 interface_type = isp_get_interface_type(&sd->entity);
477 if (interface_type < 0) {
478 st_err(ST_ISP, "%s, pipeline not config\n", __func__);
481 isp_dev->hw_ops->isp_set_format(isp_dev,
482 isp_dev->rect, fmt->code, interface_type);
483 isp_dev->hw_ops->isp_reset(isp_dev);
484 isp_dev->hw_ops->isp_stream_set(isp_dev, enable);
487 isp_dev->stream_count++;
489 if (isp_dev->stream_count == 0)
491 if (isp_dev->stream_count == 1)
492 isp_dev->hw_ops->isp_stream_set(isp_dev, enable);
493 isp_dev->stream_count--;
495 src_ch.type = V4L2_EVENT_SOURCE_CHANGE,
496 src_ch.u.src_change.changes = isp_dev->stream_count,
498 v4l2_subdev_notify_event(sd, &src_ch);
500 mutex_unlock(&isp_dev->stream_lock);
502 mutex_lock(&isp_dev->power_lock);
503 /* restore controls */
504 if (enable && isp_dev->power_count == 1) {
505 mutex_unlock(&isp_dev->power_lock);
506 ret = v4l2_ctrl_handler_setup(&isp_dev->ctrls.handler);
508 mutex_unlock(&isp_dev->power_lock);
513 /*Try to match sensor format with sink, and then get the index as default.*/
514 static int isp_match_sensor_format_get_index(struct stf_isp_dev *isp_dev)
517 struct media_entity *sensor;
518 struct v4l2_subdev *subdev;
519 struct v4l2_subdev_format fmt;
520 const struct isp_format_table *formats;
525 sensor = stfcamss_find_sensor(&isp_dev->subdev.entity);
529 subdev = media_entity_to_v4l2_subdev(sensor);
530 st_debug(ST_ISP, "Found sensor = %s\n", sensor->name);
533 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
534 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
536 st_warn(ST_ISP, "Sonser get format failed !!\n");
540 st_debug(ST_ISP, "Got sensor format 0x%x !!\n", fmt.format.code);
542 formats = &isp_dev->formats[SINK_FORMATS_INDEX];
543 for (idx = 0; idx < formats->nfmts; idx++) {
544 if (formats->fmts[idx].code == fmt.format.code) {
546 "Match sensor format to isp_formats_st7110_sink index %d !!\n",
554 static int isp_match_format_get_index(const struct isp_format_table *f_table,
560 for (i = 0; i < f_table->nfmts; i++) {
561 if (mbus_code == f_table->fmts[i].code) {
564 if (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y) {
565 if (mbus_code == (isp_formats_st7110_compat_10bit_raw[i].code ||
566 isp_formats_st7110_compat_8bit_raw[i].code))
575 static void isp_try_format(struct stf_isp_dev *isp_dev,
576 struct v4l2_subdev_state *state,
578 struct v4l2_mbus_framefmt *fmt,
579 enum v4l2_subdev_format_whence which)
581 const struct isp_format_table *formats;
583 u32 code = fmt->code;
587 case STF_ISP_PAD_SINK:
588 /* Set format on sink pad */
590 formats = &isp_dev->formats[SINK_FORMATS_INDEX];
591 fmt->width = clamp_t(u32,
592 fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
593 STFCAMSS_FRAME_MAX_WIDTH);
594 fmt->height = clamp_t(u32,
595 fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
596 STFCAMSS_FRAME_MAX_HEIGHT);
599 fmt->field = V4L2_FIELD_NONE;
600 fmt->colorspace = V4L2_COLORSPACE_SRGB;
605 case STF_ISP_PAD_SRC:
606 case STF_ISP_PAD_SRC_SS0:
607 case STF_ISP_PAD_SRC_SS1:
608 formats = &isp_dev->formats[UO_FORMATS_INDEX];
611 case STF_ISP_PAD_SRC_ITIW:
612 case STF_ISP_PAD_SRC_ITIR:
613 formats = &isp_dev->formats[ITI_FORMATS_INDEX];
616 case STF_ISP_PAD_SRC_RAW:
617 case STF_ISP_PAD_SRC_SCD_Y:
618 formats = &isp_dev->formats[RAW_FORMATS_INDEX];
622 i = isp_match_format_get_index(formats, fmt->code, pad);
623 st_debug(ST_ISP, "%s pad=%d, code=%x isp_match_format_get_index = %d\n",
624 __func__, pad, code, i);
626 if (i >= formats->nfmts &&
627 (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y)) {
630 sensor_idx = isp_match_sensor_format_get_index(isp_dev);
635 if (pad != STF_ISP_PAD_SINK)
636 *fmt = *__isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
638 if (i >= formats->nfmts) {
639 fmt->code = formats->fmts[0].code;
640 bpp = formats->fmts[0].bpp;
641 st_info(ST_ISP, "Use default index 0 format = 0x%x\n", fmt->code);
643 // sink format and raw format must one by one
644 if (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y) {
645 fmt->code = formats->fmts[i].code;
646 bpp = formats->fmts[i].bpp;
647 st_info(ST_ISP, "Use mapping format from sink index %d = 0x%x\n",
651 bpp = formats->fmts[i].bpp;
652 st_info(ST_ISP, "Use input format = 0x%x\n", fmt->code);
657 case STF_ISP_PAD_SINK:
659 case STF_ISP_PAD_SRC:
660 isp_dev->rect[ISP_COMPOSE].bpp = bpp;
662 case STF_ISP_PAD_SRC_SS0:
663 isp_dev->rect[ISP_SCALE_SS0].bpp = bpp;
665 case STF_ISP_PAD_SRC_SS1:
666 isp_dev->rect[ISP_SCALE_SS1].bpp = bpp;
668 case STF_ISP_PAD_SRC_ITIW:
669 case STF_ISP_PAD_SRC_ITIR:
670 isp_dev->rect[ISP_ITIWS].bpp = bpp;
672 case STF_ISP_PAD_SRC_RAW:
673 isp_dev->rect[ISP_CROP].bpp = bpp;
675 case STF_ISP_PAD_SRC_SCD_Y:
680 static int isp_enum_mbus_code(struct v4l2_subdev *sd,
681 struct v4l2_subdev_state *state,
682 struct v4l2_subdev_mbus_code_enum *code)
684 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
685 const struct isp_format_table *formats;
687 if (code->index >= isp_dev->nformats)
689 if (code->pad == STF_ISP_PAD_SINK) {
690 formats = &isp_dev->formats[SINK_FORMATS_INDEX];
691 code->code = formats->fmts[code->index].code;
693 struct v4l2_mbus_framefmt *sink_fmt;
695 sink_fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK,
698 code->code = sink_fmt->code;
707 static int isp_enum_frame_size(struct v4l2_subdev *sd,
708 struct v4l2_subdev_state *state,
709 struct v4l2_subdev_frame_size_enum *fse)
711 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
712 struct v4l2_mbus_framefmt format;
717 format.code = fse->code;
720 isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
721 fse->min_width = format.width;
722 fse->min_height = format.height;
724 if (format.code != fse->code)
727 format.code = fse->code;
730 isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
731 fse->max_width = format.width;
732 fse->max_height = format.height;
737 static int isp_get_format(struct v4l2_subdev *sd,
738 struct v4l2_subdev_state *state,
739 struct v4l2_subdev_format *fmt)
741 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
742 struct v4l2_mbus_framefmt *format;
744 format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
748 fmt->format = *format;
753 static int isp_set_format(struct v4l2_subdev *sd,
754 struct v4l2_subdev_state *state,
755 struct v4l2_subdev_format *fmt)
757 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
758 struct v4l2_mbus_framefmt *format;
759 struct v4l2_subdev_selection sel = { 0 };
760 struct v4l2_rect *rect = NULL;
763 st_debug(ST_ISP, "%s pad=%d, code=%x, which=%d\n",
764 __func__, fmt->reserved[0], fmt->format.code, fmt->which);
765 format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
769 mutex_lock(&isp_dev->stream_lock);
770 if (isp_dev->stream_count) {
771 fmt->format = *format;
772 if (fmt->reserved[0] != 0) {
773 sel.which = fmt->which;
774 sel.pad = fmt->reserved[0];
776 switch (fmt->reserved[0]) {
777 case STF_ISP_PAD_SRC:
778 rect = __isp_get_compose(isp_dev, state, fmt->which);
780 case STF_ISP_PAD_SRC_SS0:
781 case STF_ISP_PAD_SRC_SS1:
782 rect = __isp_get_scale(isp_dev, state, &sel);
784 case STF_ISP_PAD_SRC_ITIW:
785 case STF_ISP_PAD_SRC_ITIR:
786 rect = __isp_get_itiws(isp_dev, state, fmt->which);
788 case STF_ISP_PAD_SRC_RAW:
789 case STF_ISP_PAD_SRC_SCD_Y:
790 rect = __isp_get_crop(isp_dev, state, fmt->which);
796 fmt->format.width = rect->width;
797 fmt->format.height = rect->height;
800 mutex_unlock(&isp_dev->stream_lock);
803 isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which);
804 *format = fmt->format;
806 mutex_unlock(&isp_dev->stream_lock);
808 /* Propagate the format from sink to source */
809 if (fmt->pad == STF_ISP_PAD_SINK) {
810 /* Reset sink pad compose selection */
811 sel.which = fmt->which;
812 sel.pad = STF_ISP_PAD_SINK;
813 sel.target = V4L2_SEL_TGT_CROP;
814 sel.r.width = fmt->format.width;
815 sel.r.height = fmt->format.height;
816 ret = isp_set_selection(sd, state, &sel);
825 static struct v4l2_rect *
826 __isp_get_compose(struct stf_isp_dev *isp_dev,
827 struct v4l2_subdev_state *state,
828 enum v4l2_subdev_format_whence which)
830 if (which == V4L2_SUBDEV_FORMAT_TRY)
831 return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
835 return &isp_dev->rect[ISP_COMPOSE].rect;
838 static struct v4l2_rect *
839 __isp_get_crop(struct stf_isp_dev *isp_dev,
840 struct v4l2_subdev_state *state,
841 enum v4l2_subdev_format_whence which)
843 if (which == V4L2_SUBDEV_FORMAT_TRY)
844 return v4l2_subdev_get_try_crop(&isp_dev->subdev, state,
847 return &isp_dev->rect[ISP_CROP].rect;
850 static struct v4l2_rect *
851 __isp_get_scale(struct stf_isp_dev *isp_dev,
852 struct v4l2_subdev_state *state,
853 struct v4l2_subdev_selection *sel)
857 if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
858 return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
860 if (sel->pad != STF_ISP_PAD_SRC_SS0 && sel->pad != STF_ISP_PAD_SRC_SS1)
863 pad = sel->pad == STF_ISP_PAD_SRC_SS0 ? ISP_SCALE_SS0 : ISP_SCALE_SS1;
864 return &isp_dev->rect[pad].rect;
867 static struct v4l2_rect *
868 __isp_get_itiws(struct stf_isp_dev *isp_dev,
869 struct v4l2_subdev_state *state,
870 enum v4l2_subdev_format_whence which)
872 if (which == V4L2_SUBDEV_FORMAT_TRY)
873 return v4l2_subdev_get_try_crop(&isp_dev->subdev, state, STF_ISP_PAD_SINK);
875 return &isp_dev->rect[ISP_ITIWS].rect;
878 static void isp_try_crop(struct stf_isp_dev *isp_dev,
879 struct v4l2_subdev_state *state,
880 struct v4l2_rect *rect,
881 enum v4l2_subdev_format_whence which)
883 struct v4l2_mbus_framefmt *fmt;
885 fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
887 if (rect->width > fmt->width)
888 rect->width = fmt->width;
890 if (rect->width + rect->left > fmt->width)
891 rect->left = fmt->width - rect->width;
893 if (rect->height > fmt->height)
894 rect->height = fmt->height;
896 if (rect->height + rect->top > fmt->height)
897 rect->top = fmt->height - rect->height;
899 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
901 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
904 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
906 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
908 rect->height &= ~0x1;
911 static void isp_try_compose(struct stf_isp_dev *isp_dev,
912 struct v4l2_subdev_state *state,
913 struct v4l2_rect *rect,
914 enum v4l2_subdev_format_whence which)
916 struct v4l2_rect *crop;
918 crop = __isp_get_crop(isp_dev, state, which);
920 if (rect->width > crop->width)
921 rect->width = crop->width;
923 if (rect->height > crop->height)
924 rect->height = crop->height;
926 if (crop->width > rect->width * SCALER_RATIO_MAX)
927 rect->width = (crop->width + SCALER_RATIO_MAX - 1) /
930 if (crop->height > rect->height * SCALER_RATIO_MAX)
931 rect->height = (crop->height + SCALER_RATIO_MAX - 1) /
934 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH)
935 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
937 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT)
938 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
939 rect->height &= ~0x1;
942 static void isp_try_scale(struct stf_isp_dev *isp_dev,
943 struct v4l2_subdev_state *state,
944 struct v4l2_rect *rect,
945 enum v4l2_subdev_format_whence which)
947 struct v4l2_rect *compose;
949 compose = __isp_get_compose(isp_dev, state, which);
951 if (rect->width > compose->width)
952 rect->width = compose->width;
954 if (rect->width + rect->left > compose->width)
955 rect->left = compose->width - rect->width;
957 if (rect->height > compose->height)
958 rect->height = compose->height;
960 if (rect->height + rect->top > compose->height)
961 rect->top = compose->height - rect->height;
963 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
965 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
968 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
970 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
972 rect->height &= ~0x1;
975 static void isp_try_itiws(struct stf_isp_dev *isp_dev,
976 struct v4l2_subdev_state *state,
977 struct v4l2_rect *rect,
978 enum v4l2_subdev_format_whence which)
980 struct v4l2_rect *crop;
982 crop = __isp_get_crop(isp_dev, state, which);
984 if (rect->width > crop->width)
985 rect->width = crop->width;
987 if (rect->width + rect->left > crop->width)
988 rect->left = crop->width - rect->width;
990 if (rect->height > crop->height)
991 rect->height = crop->height;
993 if (rect->height + rect->top > crop->height)
994 rect->top = crop->height - rect->height;
996 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
998 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
1001 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
1003 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
1005 rect->height &= ~0x1;
1008 static int isp_get_selection(struct v4l2_subdev *sd,
1009 struct v4l2_subdev_state *state,
1010 struct v4l2_subdev_selection *sel)
1012 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1013 struct v4l2_subdev_format fmt = { 0 };
1014 struct v4l2_rect *rect;
1017 switch (sel->target) {
1018 case V4L2_SEL_TGT_CROP_BOUNDS:
1019 case V4L2_SEL_TGT_CROP_DEFAULT:
1021 fmt.which = sel->which;
1022 ret = isp_get_format(sd, state, &fmt);
1028 sel->r.width = fmt.format.width;
1029 sel->r.height = fmt.format.height;
1031 case V4L2_SEL_TGT_CROP:
1032 rect = __isp_get_crop(isp_dev, state, sel->which);
1038 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1039 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1040 if (sel->pad > STF_ISP_PAD_SRC_ITIR)
1042 rect = __isp_get_crop(isp_dev, state, sel->which);
1046 sel->r.left = rect->left;
1047 sel->r.top = rect->top;
1048 sel->r.width = rect->width;
1049 sel->r.height = rect->height;
1051 case V4L2_SEL_TGT_COMPOSE:
1052 if (sel->pad > STF_ISP_PAD_SRC_ITIR)
1054 if (sel->pad == STF_ISP_PAD_SRC_SS0
1055 || sel->pad == STF_ISP_PAD_SRC_SS1) {
1056 rect = __isp_get_scale(isp_dev, state, sel);
1059 } else if (sel->pad == STF_ISP_PAD_SRC_ITIW
1060 || sel->pad == STF_ISP_PAD_SRC_ITIR) {
1061 rect = __isp_get_itiws(isp_dev, state, sel->which);
1065 rect = __isp_get_compose(isp_dev, state, sel->which);
1075 st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
1076 __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
1080 static int isp_set_selection(struct v4l2_subdev *sd,
1081 struct v4l2_subdev_state *state,
1082 struct v4l2_subdev_selection *sel)
1084 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1085 struct v4l2_rect *rect;
1088 if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1089 ((sel->pad == STF_ISP_PAD_SINK)
1090 || (sel->pad == STF_ISP_PAD_SRC))) {
1091 struct v4l2_subdev_format fmt = { 0 };
1094 rect = __isp_get_compose(isp_dev, state, sel->which);
1098 mutex_lock(&isp_dev->stream_lock);
1099 if (isp_dev->stream_count) {
1101 mutex_unlock(&isp_dev->stream_lock);
1105 isp_try_compose(isp_dev, state, &sel->r, sel->which);
1108 mutex_unlock(&isp_dev->stream_lock);
1110 /* Reset source pad format width and height */
1111 fmt.which = sel->which;
1112 fmt.pad = STF_ISP_PAD_SRC;
1113 ret = isp_get_format(sd, state, &fmt);
1117 fmt.format.width = rect->width;
1118 fmt.format.height = rect->height;
1119 ret = isp_set_format(sd, state, &fmt);
1122 for (i = STF_ISP_PAD_SRC_SS0; i <= STF_ISP_PAD_SRC_ITIR; i++) {
1123 struct v4l2_subdev_selection scale = { 0 };
1125 scale.which = sel->which;
1126 scale.target = V4L2_SEL_TGT_COMPOSE;
1129 ret = isp_set_selection(sd, state, &scale);
1131 } else if (sel->target == V4L2_SEL_TGT_COMPOSE
1132 && ((sel->pad == STF_ISP_PAD_SRC_SS0)
1133 || (sel->pad == STF_ISP_PAD_SRC_SS1))) {
1134 struct v4l2_subdev_format fmt = { 0 };
1136 rect = __isp_get_scale(isp_dev, state, sel);
1140 mutex_lock(&isp_dev->stream_lock);
1141 if (isp_dev->stream_count) {
1143 mutex_unlock(&isp_dev->stream_lock);
1147 isp_try_scale(isp_dev, state, &sel->r, sel->which);
1150 mutex_unlock(&isp_dev->stream_lock);
1152 /* Reset source pad format width and height */
1153 fmt.which = sel->which;
1155 ret = isp_get_format(sd, state, &fmt);
1159 fmt.format.width = rect->width;
1160 fmt.format.height = rect->height;
1161 ret = isp_set_format(sd, state, &fmt);
1162 } else if (sel->target == V4L2_SEL_TGT_COMPOSE
1163 && ((sel->pad == STF_ISP_PAD_SRC_ITIW)
1164 || (sel->pad == STF_ISP_PAD_SRC_ITIR))) {
1165 struct v4l2_subdev_format fmt = { 0 };
1167 rect = __isp_get_itiws(isp_dev, state, sel->which);
1171 mutex_lock(&isp_dev->stream_lock);
1172 if (isp_dev->stream_count) {
1174 mutex_unlock(&isp_dev->stream_lock);
1178 isp_try_itiws(isp_dev, state, &sel->r, sel->which);
1181 mutex_unlock(&isp_dev->stream_lock);
1183 /* Reset source pad format width and height */
1184 fmt.which = sel->which;
1186 ret = isp_get_format(sd, state, &fmt);
1190 fmt.format.width = rect->width;
1191 fmt.format.height = rect->height;
1192 ret = isp_set_format(sd, state, &fmt);
1193 } else if (sel->target == V4L2_SEL_TGT_CROP) {
1194 struct v4l2_subdev_selection compose = { 0 };
1197 rect = __isp_get_crop(isp_dev, state, sel->which);
1201 mutex_lock(&isp_dev->stream_lock);
1202 if (isp_dev->stream_count) {
1204 mutex_unlock(&isp_dev->stream_lock);
1208 isp_try_crop(isp_dev, state, &sel->r, sel->which);
1211 mutex_unlock(&isp_dev->stream_lock);
1213 /* Reset source compose selection */
1214 compose.which = sel->which;
1215 compose.target = V4L2_SEL_TGT_COMPOSE;
1216 compose.r.width = rect->width;
1217 compose.r.height = rect->height;
1218 compose.pad = STF_ISP_PAD_SINK;
1219 ret = isp_set_selection(sd, state, &compose);
1221 /* Reset source pad format width and height */
1222 for (i = STF_ISP_PAD_SRC_RAW; i < STF_ISP_PAD_MAX; i++) {
1223 struct v4l2_subdev_format fmt = { 0 };
1225 fmt.which = sel->which;
1227 ret = isp_get_format(sd, state, &fmt);
1231 fmt.format.width = rect->width;
1232 fmt.format.height = rect->height;
1233 ret = isp_set_format(sd, state, &fmt);
1239 st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
1240 __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
1245 static int isp_init_formats(struct v4l2_subdev *sd,
1246 struct v4l2_subdev_fh *fh)
1248 struct v4l2_subdev_format format = {
1249 .pad = STF_ISP_PAD_SINK,
1250 .which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1251 V4L2_SUBDEV_FORMAT_ACTIVE,
1253 .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
1259 return isp_set_format(sd, fh ? fh->state : NULL, &format);
1262 static int isp_link_setup(struct media_entity *entity,
1263 const struct media_pad *local,
1264 const struct media_pad *remote, u32 flags)
1266 if (flags & MEDIA_LNK_FL_ENABLED)
1267 if (media_entity_remote_pad(local))
1272 static int stf_isp_load_setfile(struct stf_isp_dev *isp_dev, char *file_name)
1274 struct device *dev = isp_dev->stfcamss->dev;
1275 const struct firmware *fw;
1280 st_debug(ST_ISP, "%s, file_name %s\n", __func__, file_name);
1281 ret = request_firmware(&fw, file_name, dev);
1283 st_err(ST_ISP, "firmware request failed (%d)\n", ret);
1286 buf = devm_kzalloc(dev, fw->size, GFP_KERNEL);
1289 memcpy(buf, fw->data, fw->size);
1291 mutex_lock(&isp_dev->setfile_lock);
1292 if (isp_dev->setfile.state == 1)
1293 devm_kfree(dev, isp_dev->setfile.data);
1294 isp_dev->setfile.data = buf;
1295 isp_dev->setfile.size = fw->size;
1296 isp_dev->setfile.state = 1;
1297 regval_num = (int *)&buf[fw->size - sizeof(unsigned int)];
1298 isp_dev->setfile.settings.regval_num = *regval_num;
1299 isp_dev->setfile.settings.regval = (struct regval_t *)buf;
1300 mutex_unlock(&isp_dev->setfile_lock);
1302 st_debug(ST_ISP, "stf_isp setfile loaded size: %zu B, reg_nul: %d\n",
1303 fw->size, isp_dev->setfile.settings.regval_num);
1305 release_firmware(fw);
1309 static long stf_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1311 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1312 struct device *dev = isp_dev->stfcamss->dev;
1313 int ret = -ENOIOCTLCMD;
1316 case VIDIOC_STFISP_LOAD_FW: {
1317 struct stfisp_fw_info *fw_info = arg;
1319 if (IS_ERR(fw_info)) {
1320 st_err(ST_ISP, "fw_info failed, params invaild\n");
1324 ret = stf_isp_load_setfile(isp_dev, fw_info->filename);
1327 case VIDIOC_STF_DMABUF_ALLOC:
1328 case VIDIOC_STF_DMABUF_FREE:
1329 ret = stf_dmabuf_ioctl(dev, cmd, arg);
1331 case VIDIOC_STFISP_GET_REG:
1332 ret = isp_dev->hw_ops->isp_reg_read(isp_dev, arg);
1334 case VIDIOC_STFISP_SET_REG:
1335 ret = isp_dev->hw_ops->isp_reg_write(isp_dev, arg);
1337 case VIDIOC_STFISP_SHADOW_LOCK:
1338 if (atomic_add_unless(&isp_dev->shadow_count, 1, 1))
1342 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1344 case VIDIOC_STFISP_SHADOW_UNLOCK:
1345 if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
1349 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1351 case VIDIOC_STFISP_SHADOW_UNLOCK_N_TRIGGER:
1353 isp_dev->hw_ops->isp_shadow_trigger(isp_dev);
1354 if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
1358 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1361 case VIDIOC_STFISP_SET_USER_CONFIG_ISP:
1362 st_debug(ST_ISP, "%s, %d set user_config_isp\n", __func__, __LINE__);
1363 user_config_isp = 1;
1371 int isp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1373 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1375 st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__);
1376 while (atomic_dec_if_positive(&isp_dev->shadow_count) > 0)
1377 st_warn(ST_ISP, "user not unlocked the shadow lock, driver unlock it!\n");
1382 static int stf_isp_subscribe_event(struct v4l2_subdev *sd,
1384 struct v4l2_event_subscription *sub)
1386 switch (sub->type) {
1387 case V4L2_EVENT_SOURCE_CHANGE:
1388 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
1389 case V4L2_EVENT_CTRL:
1390 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
1392 st_debug(ST_ISP, "unspport subscribe_event\n");
1397 static const struct v4l2_subdev_core_ops isp_core_ops = {
1398 .s_power = isp_set_power,
1399 .ioctl = stf_isp_ioctl,
1400 .log_status = v4l2_ctrl_subdev_log_status,
1401 // .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1402 .subscribe_event = stf_isp_subscribe_event,
1403 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1406 static const struct v4l2_subdev_video_ops isp_video_ops = {
1407 .s_stream = isp_set_stream,
1410 static const struct v4l2_subdev_pad_ops isp_pad_ops = {
1411 .enum_mbus_code = isp_enum_mbus_code,
1412 .enum_frame_size = isp_enum_frame_size,
1413 .get_fmt = isp_get_format,
1414 .set_fmt = isp_set_format,
1415 .get_selection = isp_get_selection,
1416 .set_selection = isp_set_selection,
1419 static const struct v4l2_subdev_ops isp_v4l2_ops = {
1420 .core = &isp_core_ops,
1421 .video = &isp_video_ops,
1422 .pad = &isp_pad_ops,
1425 static const struct v4l2_subdev_internal_ops isp_v4l2_internal_ops = {
1426 .open = isp_init_formats,
1430 static const struct media_entity_operations isp_media_ops = {
1431 .link_setup = isp_link_setup,
1432 .link_validate = v4l2_subdev_link_validate,
1435 int stf_isp_register(struct stf_isp_dev *isp_dev,
1436 struct v4l2_device *v4l2_dev)
1438 struct v4l2_subdev *sd = &isp_dev->subdev;
1439 struct media_pad *pads = isp_dev->pads;
1442 v4l2_subdev_init(sd, &isp_v4l2_ops);
1443 sd->internal_ops = &isp_v4l2_internal_ops;
1444 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1445 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
1447 v4l2_set_subdevdata(sd, isp_dev);
1449 ret = isp_init_formats(sd, NULL);
1451 st_err(ST_ISP, "Failed to init format: %d\n", ret);
1455 pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1456 pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
1457 pads[STF_ISP_PAD_SRC_SS0].flags = MEDIA_PAD_FL_SOURCE;
1458 pads[STF_ISP_PAD_SRC_SS1].flags = MEDIA_PAD_FL_SOURCE;
1459 pads[STF_ISP_PAD_SRC_ITIW].flags = MEDIA_PAD_FL_SOURCE;
1460 pads[STF_ISP_PAD_SRC_ITIR].flags = MEDIA_PAD_FL_SOURCE;
1461 pads[STF_ISP_PAD_SRC_RAW].flags = MEDIA_PAD_FL_SOURCE;
1462 pads[STF_ISP_PAD_SRC_SCD_Y].flags = MEDIA_PAD_FL_SOURCE;
1464 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1465 sd->entity.ops = &isp_media_ops;
1466 ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
1468 st_err(ST_ISP, "Failed to init media entity: %d\n", ret);
1472 ret = isp_init_controls(isp_dev);
1476 ret = v4l2_device_register_subdev(v4l2_dev, sd);
1478 st_err(ST_ISP, "Failed to register subdev: %d\n", ret);
1485 v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
1487 media_entity_cleanup(&sd->entity);
1491 int stf_isp_unregister(struct stf_isp_dev *isp_dev)
1493 v4l2_device_unregister_subdev(&isp_dev->subdev);
1494 media_entity_cleanup(&isp_dev->subdev.entity);
1495 v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
1496 mutex_destroy(&isp_dev->stream_lock);
1497 mutex_destroy(&isp_dev->power_lock);
1498 mutex_destroy(&isp_dev->setfile_lock);