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, "isp_match_format_get_index = %d\n", i);
625 if (i >= formats->nfmts &&
626 (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y)) {
629 sensor_idx = isp_match_sensor_format_get_index(isp_dev);
634 if (pad != STF_ISP_PAD_SINK)
635 *fmt = *__isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
637 if (i >= formats->nfmts) {
638 fmt->code = formats->fmts[0].code;
639 bpp = formats->fmts[0].bpp;
640 st_info(ST_ISP, "Use default index 0 format = 0x%x\n", fmt->code);
642 // sink format and raw format must one by one
643 if (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y) {
644 fmt->code = formats->fmts[i].code;
645 bpp = formats->fmts[i].bpp;
646 st_info(ST_ISP, "Use mapping format from sink index %d = 0x%x\n",
650 bpp = formats->fmts[i].bpp;
651 st_info(ST_ISP, "Use input format = 0x%x\n", fmt->code);
656 case STF_ISP_PAD_SINK:
658 case STF_ISP_PAD_SRC:
659 isp_dev->rect[ISP_COMPOSE].bpp = bpp;
661 case STF_ISP_PAD_SRC_SS0:
662 isp_dev->rect[ISP_SCALE_SS0].bpp = bpp;
664 case STF_ISP_PAD_SRC_SS1:
665 isp_dev->rect[ISP_SCALE_SS1].bpp = bpp;
667 case STF_ISP_PAD_SRC_ITIW:
668 case STF_ISP_PAD_SRC_ITIR:
669 isp_dev->rect[ISP_ITIWS].bpp = bpp;
671 case STF_ISP_PAD_SRC_RAW:
672 isp_dev->rect[ISP_CROP].bpp = bpp;
674 case STF_ISP_PAD_SRC_SCD_Y:
679 static int isp_enum_mbus_code(struct v4l2_subdev *sd,
680 struct v4l2_subdev_state *state,
681 struct v4l2_subdev_mbus_code_enum *code)
683 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
684 const struct isp_format_table *formats;
686 if (code->index >= isp_dev->nformats)
688 if (code->pad == STF_ISP_PAD_SINK) {
689 formats = &isp_dev->formats[SINK_FORMATS_INDEX];
690 code->code = formats->fmts[code->index].code;
692 struct v4l2_mbus_framefmt *sink_fmt;
694 sink_fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK,
697 code->code = sink_fmt->code;
706 static int isp_enum_frame_size(struct v4l2_subdev *sd,
707 struct v4l2_subdev_state *state,
708 struct v4l2_subdev_frame_size_enum *fse)
710 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
711 struct v4l2_mbus_framefmt format;
716 format.code = fse->code;
719 isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
720 fse->min_width = format.width;
721 fse->min_height = format.height;
723 if (format.code != fse->code)
726 format.code = fse->code;
729 isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
730 fse->max_width = format.width;
731 fse->max_height = format.height;
736 static int isp_get_format(struct v4l2_subdev *sd,
737 struct v4l2_subdev_state *state,
738 struct v4l2_subdev_format *fmt)
740 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
741 struct v4l2_mbus_framefmt *format;
743 format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
747 fmt->format = *format;
752 static int isp_set_format(struct v4l2_subdev *sd,
753 struct v4l2_subdev_state *state,
754 struct v4l2_subdev_format *fmt)
756 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
757 struct v4l2_mbus_framefmt *format;
758 struct v4l2_subdev_selection sel = { 0 };
759 struct v4l2_rect *rect = NULL;
762 format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
766 mutex_lock(&isp_dev->stream_lock);
767 if (isp_dev->stream_count) {
768 fmt->format = *format;
769 if (fmt->reserved[0] != 0) {
770 sel.which = fmt->which;
771 sel.pad = fmt->reserved[0];
773 switch (fmt->reserved[0]) {
774 case STF_ISP_PAD_SRC:
775 rect = __isp_get_compose(isp_dev, state, fmt->which);
777 case STF_ISP_PAD_SRC_SS0:
778 case STF_ISP_PAD_SRC_SS1:
779 rect = __isp_get_scale(isp_dev, state, &sel);
781 case STF_ISP_PAD_SRC_ITIW:
782 case STF_ISP_PAD_SRC_ITIR:
783 rect = __isp_get_itiws(isp_dev, state, fmt->which);
785 case STF_ISP_PAD_SRC_RAW:
786 case STF_ISP_PAD_SRC_SCD_Y:
787 rect = __isp_get_crop(isp_dev, state, fmt->which);
793 fmt->format.width = rect->width;
794 fmt->format.height = rect->height;
797 mutex_unlock(&isp_dev->stream_lock);
800 isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which);
801 *format = fmt->format;
803 mutex_unlock(&isp_dev->stream_lock);
805 /* Propagate the format from sink to source */
806 if (fmt->pad == STF_ISP_PAD_SINK) {
807 /* Reset sink pad compose selection */
808 sel.which = fmt->which;
809 sel.pad = STF_ISP_PAD_SINK;
810 sel.target = V4L2_SEL_TGT_CROP;
811 sel.r.width = fmt->format.width;
812 sel.r.height = fmt->format.height;
813 ret = isp_set_selection(sd, state, &sel);
822 static struct v4l2_rect *
823 __isp_get_compose(struct stf_isp_dev *isp_dev,
824 struct v4l2_subdev_state *state,
825 enum v4l2_subdev_format_whence which)
827 if (which == V4L2_SUBDEV_FORMAT_TRY)
828 return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
832 return &isp_dev->rect[ISP_COMPOSE].rect;
835 static struct v4l2_rect *
836 __isp_get_crop(struct stf_isp_dev *isp_dev,
837 struct v4l2_subdev_state *state,
838 enum v4l2_subdev_format_whence which)
840 if (which == V4L2_SUBDEV_FORMAT_TRY)
841 return v4l2_subdev_get_try_crop(&isp_dev->subdev, state,
844 return &isp_dev->rect[ISP_CROP].rect;
847 static struct v4l2_rect *
848 __isp_get_scale(struct stf_isp_dev *isp_dev,
849 struct v4l2_subdev_state *state,
850 struct v4l2_subdev_selection *sel)
854 if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
855 return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
857 if (sel->pad != STF_ISP_PAD_SRC_SS0 && sel->pad != STF_ISP_PAD_SRC_SS1)
860 pad = sel->pad == STF_ISP_PAD_SRC_SS0 ? ISP_SCALE_SS0 : ISP_SCALE_SS1;
861 return &isp_dev->rect[pad].rect;
864 static struct v4l2_rect *
865 __isp_get_itiws(struct stf_isp_dev *isp_dev,
866 struct v4l2_subdev_state *state,
867 enum v4l2_subdev_format_whence which)
869 if (which == V4L2_SUBDEV_FORMAT_TRY)
870 return v4l2_subdev_get_try_crop(&isp_dev->subdev, state, STF_ISP_PAD_SINK);
872 return &isp_dev->rect[ISP_ITIWS].rect;
875 static void isp_try_crop(struct stf_isp_dev *isp_dev,
876 struct v4l2_subdev_state *state,
877 struct v4l2_rect *rect,
878 enum v4l2_subdev_format_whence which)
880 struct v4l2_mbus_framefmt *fmt;
882 fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
884 if (rect->width > fmt->width)
885 rect->width = fmt->width;
887 if (rect->width + rect->left > fmt->width)
888 rect->left = fmt->width - rect->width;
890 if (rect->height > fmt->height)
891 rect->height = fmt->height;
893 if (rect->height + rect->top > fmt->height)
894 rect->top = fmt->height - rect->height;
896 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
898 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
901 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
903 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
905 rect->height &= ~0x1;
908 static void isp_try_compose(struct stf_isp_dev *isp_dev,
909 struct v4l2_subdev_state *state,
910 struct v4l2_rect *rect,
911 enum v4l2_subdev_format_whence which)
913 struct v4l2_rect *crop;
915 crop = __isp_get_crop(isp_dev, state, which);
917 if (rect->width > crop->width)
918 rect->width = crop->width;
920 if (rect->height > crop->height)
921 rect->height = crop->height;
923 if (crop->width > rect->width * SCALER_RATIO_MAX)
924 rect->width = (crop->width + SCALER_RATIO_MAX - 1) /
927 if (crop->height > rect->height * SCALER_RATIO_MAX)
928 rect->height = (crop->height + SCALER_RATIO_MAX - 1) /
931 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH)
932 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
934 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT)
935 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
936 rect->height &= ~0x1;
939 static void isp_try_scale(struct stf_isp_dev *isp_dev,
940 struct v4l2_subdev_state *state,
941 struct v4l2_rect *rect,
942 enum v4l2_subdev_format_whence which)
944 struct v4l2_rect *compose;
946 compose = __isp_get_compose(isp_dev, state, which);
948 if (rect->width > compose->width)
949 rect->width = compose->width;
951 if (rect->width + rect->left > compose->width)
952 rect->left = compose->width - rect->width;
954 if (rect->height > compose->height)
955 rect->height = compose->height;
957 if (rect->height + rect->top > compose->height)
958 rect->top = compose->height - rect->height;
960 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
962 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
965 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
967 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
969 rect->height &= ~0x1;
972 static void isp_try_itiws(struct stf_isp_dev *isp_dev,
973 struct v4l2_subdev_state *state,
974 struct v4l2_rect *rect,
975 enum v4l2_subdev_format_whence which)
977 struct v4l2_rect *crop;
979 crop = __isp_get_crop(isp_dev, state, which);
981 if (rect->width > crop->width)
982 rect->width = crop->width;
984 if (rect->width + rect->left > crop->width)
985 rect->left = crop->width - rect->width;
987 if (rect->height > crop->height)
988 rect->height = crop->height;
990 if (rect->height + rect->top > crop->height)
991 rect->top = crop->height - rect->height;
993 if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
995 rect->width = STFCAMSS_FRAME_MIN_WIDTH;
998 if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
1000 rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
1002 rect->height &= ~0x1;
1005 static int isp_get_selection(struct v4l2_subdev *sd,
1006 struct v4l2_subdev_state *state,
1007 struct v4l2_subdev_selection *sel)
1009 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1010 struct v4l2_subdev_format fmt = { 0 };
1011 struct v4l2_rect *rect;
1014 switch (sel->target) {
1015 case V4L2_SEL_TGT_CROP_BOUNDS:
1016 case V4L2_SEL_TGT_CROP_DEFAULT:
1018 fmt.which = sel->which;
1019 ret = isp_get_format(sd, state, &fmt);
1025 sel->r.width = fmt.format.width;
1026 sel->r.height = fmt.format.height;
1028 case V4L2_SEL_TGT_CROP:
1029 rect = __isp_get_crop(isp_dev, state, sel->which);
1035 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1036 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1037 if (sel->pad > STF_ISP_PAD_SRC_ITIR)
1039 rect = __isp_get_crop(isp_dev, state, sel->which);
1043 sel->r.left = rect->left;
1044 sel->r.top = rect->top;
1045 sel->r.width = rect->width;
1046 sel->r.height = rect->height;
1048 case V4L2_SEL_TGT_COMPOSE:
1049 if (sel->pad > STF_ISP_PAD_SRC_ITIR)
1051 if (sel->pad == STF_ISP_PAD_SRC_SS0
1052 || sel->pad == STF_ISP_PAD_SRC_SS1) {
1053 rect = __isp_get_scale(isp_dev, state, sel);
1056 } else if (sel->pad == STF_ISP_PAD_SRC_ITIW
1057 || sel->pad == STF_ISP_PAD_SRC_ITIR) {
1058 rect = __isp_get_itiws(isp_dev, state, sel->which);
1062 rect = __isp_get_compose(isp_dev, state, sel->which);
1072 st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
1073 __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
1077 static int isp_set_selection(struct v4l2_subdev *sd,
1078 struct v4l2_subdev_state *state,
1079 struct v4l2_subdev_selection *sel)
1081 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1082 struct v4l2_rect *rect;
1085 if (sel->target == V4L2_SEL_TGT_COMPOSE &&
1086 ((sel->pad == STF_ISP_PAD_SINK)
1087 || (sel->pad == STF_ISP_PAD_SRC))) {
1088 struct v4l2_subdev_format fmt = { 0 };
1091 rect = __isp_get_compose(isp_dev, state, sel->which);
1095 mutex_lock(&isp_dev->stream_lock);
1096 if (isp_dev->stream_count) {
1098 mutex_unlock(&isp_dev->stream_lock);
1102 isp_try_compose(isp_dev, state, &sel->r, sel->which);
1105 mutex_unlock(&isp_dev->stream_lock);
1107 /* Reset source pad format width and height */
1108 fmt.which = sel->which;
1109 fmt.pad = STF_ISP_PAD_SRC;
1110 ret = isp_get_format(sd, state, &fmt);
1114 fmt.format.width = rect->width;
1115 fmt.format.height = rect->height;
1116 ret = isp_set_format(sd, state, &fmt);
1119 for (i = STF_ISP_PAD_SRC_SS0; i <= STF_ISP_PAD_SRC_ITIR; i++) {
1120 struct v4l2_subdev_selection scale = { 0 };
1122 scale.which = sel->which;
1123 scale.target = V4L2_SEL_TGT_COMPOSE;
1126 ret = isp_set_selection(sd, state, &scale);
1128 } else if (sel->target == V4L2_SEL_TGT_COMPOSE
1129 && ((sel->pad == STF_ISP_PAD_SRC_SS0)
1130 || (sel->pad == STF_ISP_PAD_SRC_SS1))) {
1131 struct v4l2_subdev_format fmt = { 0 };
1133 rect = __isp_get_scale(isp_dev, state, sel);
1137 mutex_lock(&isp_dev->stream_lock);
1138 if (isp_dev->stream_count) {
1140 mutex_unlock(&isp_dev->stream_lock);
1144 isp_try_scale(isp_dev, state, &sel->r, sel->which);
1147 mutex_unlock(&isp_dev->stream_lock);
1149 /* Reset source pad format width and height */
1150 fmt.which = sel->which;
1152 ret = isp_get_format(sd, state, &fmt);
1156 fmt.format.width = rect->width;
1157 fmt.format.height = rect->height;
1158 ret = isp_set_format(sd, state, &fmt);
1159 } else if (sel->target == V4L2_SEL_TGT_COMPOSE
1160 && ((sel->pad == STF_ISP_PAD_SRC_ITIW)
1161 || (sel->pad == STF_ISP_PAD_SRC_ITIR))) {
1162 struct v4l2_subdev_format fmt = { 0 };
1164 rect = __isp_get_itiws(isp_dev, state, sel->which);
1168 mutex_lock(&isp_dev->stream_lock);
1169 if (isp_dev->stream_count) {
1171 mutex_unlock(&isp_dev->stream_lock);
1175 isp_try_itiws(isp_dev, state, &sel->r, sel->which);
1178 mutex_unlock(&isp_dev->stream_lock);
1180 /* Reset source pad format width and height */
1181 fmt.which = sel->which;
1183 ret = isp_get_format(sd, state, &fmt);
1187 fmt.format.width = rect->width;
1188 fmt.format.height = rect->height;
1189 ret = isp_set_format(sd, state, &fmt);
1190 } else if (sel->target == V4L2_SEL_TGT_CROP) {
1191 struct v4l2_subdev_selection compose = { 0 };
1194 rect = __isp_get_crop(isp_dev, state, sel->which);
1198 mutex_lock(&isp_dev->stream_lock);
1199 if (isp_dev->stream_count) {
1201 mutex_unlock(&isp_dev->stream_lock);
1205 isp_try_crop(isp_dev, state, &sel->r, sel->which);
1208 mutex_unlock(&isp_dev->stream_lock);
1210 /* Reset source compose selection */
1211 compose.which = sel->which;
1212 compose.target = V4L2_SEL_TGT_COMPOSE;
1213 compose.r.width = rect->width;
1214 compose.r.height = rect->height;
1215 compose.pad = STF_ISP_PAD_SINK;
1216 ret = isp_set_selection(sd, state, &compose);
1218 /* Reset source pad format width and height */
1219 for (i = STF_ISP_PAD_SRC_RAW; i < STF_ISP_PAD_MAX; i++) {
1220 struct v4l2_subdev_format fmt = { 0 };
1222 fmt.which = sel->which;
1224 ret = isp_get_format(sd, state, &fmt);
1228 fmt.format.width = rect->width;
1229 fmt.format.height = rect->height;
1230 ret = isp_set_format(sd, state, &fmt);
1236 st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
1237 __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
1242 static int isp_init_formats(struct v4l2_subdev *sd,
1243 struct v4l2_subdev_fh *fh)
1245 struct v4l2_subdev_format format = {
1246 .pad = STF_ISP_PAD_SINK,
1247 .which = fh ? V4L2_SUBDEV_FORMAT_TRY :
1248 V4L2_SUBDEV_FORMAT_ACTIVE,
1250 .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
1256 return isp_set_format(sd, fh ? fh->state : NULL, &format);
1259 static int isp_link_setup(struct media_entity *entity,
1260 const struct media_pad *local,
1261 const struct media_pad *remote, u32 flags)
1263 if (flags & MEDIA_LNK_FL_ENABLED)
1264 if (media_entity_remote_pad(local))
1269 static int stf_isp_load_setfile(struct stf_isp_dev *isp_dev, char *file_name)
1271 struct device *dev = isp_dev->stfcamss->dev;
1272 const struct firmware *fw;
1277 st_debug(ST_ISP, "%s, file_name %s\n", __func__, file_name);
1278 ret = request_firmware(&fw, file_name, dev);
1280 st_err(ST_ISP, "firmware request failed (%d)\n", ret);
1283 buf = devm_kzalloc(dev, fw->size, GFP_KERNEL);
1286 memcpy(buf, fw->data, fw->size);
1288 mutex_lock(&isp_dev->setfile_lock);
1289 if (isp_dev->setfile.state == 1)
1290 devm_kfree(dev, isp_dev->setfile.data);
1291 isp_dev->setfile.data = buf;
1292 isp_dev->setfile.size = fw->size;
1293 isp_dev->setfile.state = 1;
1294 regval_num = (int *)&buf[fw->size - sizeof(unsigned int)];
1295 isp_dev->setfile.settings.regval_num = *regval_num;
1296 isp_dev->setfile.settings.regval = (struct regval_t *)buf;
1297 mutex_unlock(&isp_dev->setfile_lock);
1299 st_debug(ST_ISP, "stf_isp setfile loaded size: %zu B, reg_nul: %d\n",
1300 fw->size, isp_dev->setfile.settings.regval_num);
1302 release_firmware(fw);
1306 static long stf_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
1308 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1309 struct device *dev = isp_dev->stfcamss->dev;
1310 int ret = -ENOIOCTLCMD;
1313 case VIDIOC_STFISP_LOAD_FW: {
1314 struct stfisp_fw_info *fw_info = arg;
1316 if (IS_ERR(fw_info)) {
1317 st_err(ST_ISP, "fw_info failed, params invaild\n");
1321 ret = stf_isp_load_setfile(isp_dev, fw_info->filename);
1324 case VIDIOC_STF_DMABUF_ALLOC:
1325 case VIDIOC_STF_DMABUF_FREE:
1326 ret = stf_dmabuf_ioctl(dev, cmd, arg);
1328 case VIDIOC_STFISP_GET_REG:
1329 ret = isp_dev->hw_ops->isp_reg_read(isp_dev, arg);
1331 case VIDIOC_STFISP_SET_REG:
1332 ret = isp_dev->hw_ops->isp_reg_write(isp_dev, arg);
1334 case VIDIOC_STFISP_SHADOW_LOCK:
1335 if (atomic_add_unless(&isp_dev->shadow_count, 1, 1))
1339 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1341 case VIDIOC_STFISP_SHADOW_UNLOCK:
1342 if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
1346 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1348 case VIDIOC_STFISP_SHADOW_UNLOCK_N_TRIGGER:
1350 isp_dev->hw_ops->isp_shadow_trigger(isp_dev);
1351 if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
1355 st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
1358 case VIDIOC_STFISP_SET_USER_CONFIG_ISP:
1359 st_debug(ST_ISP, "%s, %d set user_config_isp\n", __func__, __LINE__);
1360 user_config_isp = 1;
1368 int isp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1370 struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
1372 st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__);
1373 while (atomic_dec_if_positive(&isp_dev->shadow_count) > 0)
1374 st_warn(ST_ISP, "user not unlocked the shadow lock, driver unlock it!\n");
1379 static int stf_isp_subscribe_event(struct v4l2_subdev *sd,
1381 struct v4l2_event_subscription *sub)
1383 switch (sub->type) {
1384 case V4L2_EVENT_SOURCE_CHANGE:
1385 return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
1386 case V4L2_EVENT_CTRL:
1387 return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
1389 st_debug(ST_ISP, "unspport subscribe_event\n");
1394 static const struct v4l2_subdev_core_ops isp_core_ops = {
1395 .s_power = isp_set_power,
1396 .ioctl = stf_isp_ioctl,
1397 .log_status = v4l2_ctrl_subdev_log_status,
1398 // .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
1399 .subscribe_event = stf_isp_subscribe_event,
1400 .unsubscribe_event = v4l2_event_subdev_unsubscribe,
1403 static const struct v4l2_subdev_video_ops isp_video_ops = {
1404 .s_stream = isp_set_stream,
1407 static const struct v4l2_subdev_pad_ops isp_pad_ops = {
1408 .enum_mbus_code = isp_enum_mbus_code,
1409 .enum_frame_size = isp_enum_frame_size,
1410 .get_fmt = isp_get_format,
1411 .set_fmt = isp_set_format,
1412 .get_selection = isp_get_selection,
1413 .set_selection = isp_set_selection,
1416 static const struct v4l2_subdev_ops isp_v4l2_ops = {
1417 .core = &isp_core_ops,
1418 .video = &isp_video_ops,
1419 .pad = &isp_pad_ops,
1422 static const struct v4l2_subdev_internal_ops isp_v4l2_internal_ops = {
1423 .open = isp_init_formats,
1427 static const struct media_entity_operations isp_media_ops = {
1428 .link_setup = isp_link_setup,
1429 .link_validate = v4l2_subdev_link_validate,
1432 int stf_isp_register(struct stf_isp_dev *isp_dev,
1433 struct v4l2_device *v4l2_dev)
1435 struct v4l2_subdev *sd = &isp_dev->subdev;
1436 struct media_pad *pads = isp_dev->pads;
1439 v4l2_subdev_init(sd, &isp_v4l2_ops);
1440 sd->internal_ops = &isp_v4l2_internal_ops;
1441 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1442 snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
1444 v4l2_set_subdevdata(sd, isp_dev);
1446 ret = isp_init_formats(sd, NULL);
1448 st_err(ST_ISP, "Failed to init format: %d\n", ret);
1452 pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
1453 pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
1454 pads[STF_ISP_PAD_SRC_SS0].flags = MEDIA_PAD_FL_SOURCE;
1455 pads[STF_ISP_PAD_SRC_SS1].flags = MEDIA_PAD_FL_SOURCE;
1456 pads[STF_ISP_PAD_SRC_ITIW].flags = MEDIA_PAD_FL_SOURCE;
1457 pads[STF_ISP_PAD_SRC_ITIR].flags = MEDIA_PAD_FL_SOURCE;
1458 pads[STF_ISP_PAD_SRC_RAW].flags = MEDIA_PAD_FL_SOURCE;
1459 pads[STF_ISP_PAD_SRC_SCD_Y].flags = MEDIA_PAD_FL_SOURCE;
1461 sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
1462 sd->entity.ops = &isp_media_ops;
1463 ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
1465 st_err(ST_ISP, "Failed to init media entity: %d\n", ret);
1469 ret = isp_init_controls(isp_dev);
1473 ret = v4l2_device_register_subdev(v4l2_dev, sd);
1475 st_err(ST_ISP, "Failed to register subdev: %d\n", ret);
1482 v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
1484 media_entity_cleanup(&sd->entity);
1488 int stf_isp_unregister(struct stf_isp_dev *isp_dev)
1490 v4l2_device_unregister_subdev(&isp_dev->subdev);
1491 media_entity_cleanup(&isp_dev->subdev.entity);
1492 v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
1493 mutex_destroy(&isp_dev->stream_lock);
1494 mutex_destroy(&isp_dev->power_lock);
1495 mutex_destroy(&isp_dev->setfile_lock);