Lines Matching +full:gain +full:- +full:scaling +full:- +full:p

1 // SPDX-License-Identifier: GPL-2.0-only
24 #include <media/media-entity.h>
25 #include <media/v4l2-ctrls.h>
26 #include <media/v4l2-device.h>
27 #include <media/v4l2-subdev.h>
28 #include <media/v4l2-mediabus.h>
29 #include <media/v4l2-fwnode.h>
38 #define S5K5BAF_FW_FILENAME "s5k5baf-cfg.bin"
50 /* Default number of MIPI CSI-2 data lanes used */
199 /* Auto-algorithms enable mask */
259 struct { /* Auto exposure / manual exposure and gain cluster */
262 struct v4l2_ctrl *gain; member
325 /* range 16-240 */
354 return -EINVAL; in s5k5baf_fw_parse()
360 return -EINVAL; in s5k5baf_fw_parse()
364 count -= S5K5BAG_FW_TAG_LEN; in s5k5baf_fw_parse()
368 return -ENOMEM; in s5k5baf_fw_parse()
374 if (count < 1 + 2 * f->count) { in s5k5baf_fw_parse()
376 f->count, 2 * (count + S5K5BAG_FW_TAG_LEN)); in s5k5baf_fw_parse()
377 return -EINVAL; in s5k5baf_fw_parse()
380 d += 1 + 2 * f->count; in s5k5baf_fw_parse()
382 for (i = 0; i < f->count; ++i) { in s5k5baf_fw_parse()
383 if (f->seq[i].offset + d <= end) in s5k5baf_fw_parse()
386 return -EINVAL; in s5k5baf_fw_parse()
396 return &container_of(ctrl->handler, struct s5k5baf, ctrls.handler)->sd; in ctrl_to_sd()
401 return sd->entity.function == MEDIA_ENT_F_CAM_SENSOR; in s5k5baf_is_cis_subdev()
414 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_i2c_read()
418 { .addr = c->addr, .flags = 0, in s5k5baf_i2c_read()
420 { .addr = c->addr, .flags = I2C_M_RD, in s5k5baf_i2c_read()
425 if (state->error) in s5k5baf_i2c_read()
429 ret = i2c_transfer(c->adapter, msg, 2); in s5k5baf_i2c_read()
436 state->error = ret; in s5k5baf_i2c_read()
444 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_i2c_write()
447 if (state->error) in s5k5baf_i2c_write()
455 state->error = ret; in s5k5baf_i2c_write()
474 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_write_arr_seq()
478 if (state->error) in s5k5baf_write_arr_seq()
487 int n = min_t(int, count, ARRAY_SIZE(buf) - 1); in s5k5baf_write_arr_seq()
497 state->error = ret; in s5k5baf_write_arr_seq()
501 count -= n; in s5k5baf_write_arr_seq()
513 * s5k5baf_write_nseq() - Writes sequences of values to sensor memory via i2c
515 * (N, address, value[1]...value[N-1])*,0
526 --count; in s5k5baf_write_nseq()
541 if (state->error || !reg) in s5k5baf_synchronize()
546 v4l2_err(&state->sd, "timeout on register synchronize (%#x)\n", addr); in s5k5baf_synchronize()
547 state->error = -ETIMEDOUT; in s5k5baf_synchronize()
552 struct s5k5baf_fw *fw = state->fw; in s5k5baf_fw_get_seq()
559 data = &fw->seq[0].id + 2 * fw->count; in s5k5baf_fw_get_seq()
561 for (i = 0; i < fw->count; ++i) { in s5k5baf_fw_get_seq()
562 if (fw->seq[i].id == seq_id) in s5k5baf_fw_get_seq()
563 return data + fw->seq[i].offset; in s5k5baf_fw_get_seq()
579 unsigned long mclk = state->mclk_frequency / 1000; in s5k5baf_hw_set_clocks()
595 if (!state->error && status) { in s5k5baf_hw_set_clocks()
596 v4l2_err(&state->sd, "error configuring PLL (%d)\n", status); in s5k5baf_hw_set_clocks()
597 state->error = -EINVAL; in s5k5baf_hw_set_clocks()
626 if (state->apply_crop) { in s5k5baf_hw_sync_cfg()
635 u16 flip = state->ctrls.vflip->val | (state->ctrls.vflip->val << 1); in s5k5baf_hw_set_mirror()
638 if (state->streaming) in s5k5baf_hw_set_mirror()
646 if (!state->valid_auto_alg) in s5k5baf_hw_set_alg()
649 cur_alg = state->auto_alg; in s5k5baf_hw_set_alg()
656 if (state->error) in s5k5baf_hw_set_alg()
659 state->valid_auto_alg = 1; in s5k5baf_hw_set_alg()
660 state->auto_alg = new_alg; in s5k5baf_hw_set_alg()
666 struct s5k5baf_ctrls *ctrls = &state->ctrls; in s5k5baf_hw_set_awb()
670 ctrls->gain_red->val, 1, in s5k5baf_hw_set_awb()
672 ctrls->gain_blue->val, 1, in s5k5baf_hw_set_awb()
687 static void s5k5baf_hw_set_user_gain(struct s5k5baf *state, int gain) in s5k5baf_hw_set_user_gain() argument
689 s5k5baf_write_seq(state, REG_SF_USR_TOT_GAIN, gain, 1); in s5k5baf_hw_set_user_gain()
692 /* Set auto/manual exposure and total gain */
698 unsigned int exp_time = state->ctrls.exposure->val; in s5k5baf_hw_set_auto_exposure()
701 s5k5baf_hw_set_user_gain(state, state->ctrls.gain->val); in s5k5baf_hw_set_auto_exposure()
734 int i, c = -1; in s5k5baf_find_pixfmt()
737 if (mf->colorspace != s5k5baf_formats[i].colorspace) in s5k5baf_find_pixfmt()
739 if (mf->code == s5k5baf_formats[i].code) in s5k5baf_find_pixfmt()
749 int ret = state->error; in s5k5baf_clear_error()
751 state->error = 0; in s5k5baf_clear_error()
759 if (state->bus_type == V4L2_MBUS_CSI2_DPHY) in s5k5baf_hw_set_video_bus()
765 state->nlanes, en_pkts, 1); in s5k5baf_hw_set_video_bus()
790 if (state->error) in s5k5baf_hw_find_min_fiv()
793 for (n = 5; n > 0; --n) { in s5k5baf_hw_find_min_fiv()
796 if (state->error) in s5k5baf_hw_find_min_fiv()
803 state->fiv = fiv; in s5k5baf_hw_find_min_fiv()
804 v4l2_info(&state->sd, in s5k5baf_hw_find_min_fiv()
808 v4l2_err(&state->sd, in s5k5baf_hw_find_min_fiv()
810 state->error = -EINVAL; in s5k5baf_hw_find_min_fiv()
813 v4l2_err(&state->sd, "cannot find correct frame interval\n"); in s5k5baf_hw_find_min_fiv()
814 state->error = -ERANGE; in s5k5baf_hw_find_min_fiv()
822 if (state->error) in s5k5baf_hw_validate_cfg()
827 state->apply_cfg = 1; in s5k5baf_hw_validate_cfg()
831 if (!state->error) in s5k5baf_hw_validate_cfg()
832 state->apply_cfg = 1; in s5k5baf_hw_validate_cfg()
835 v4l2_err(&state->sd, in s5k5baf_hw_validate_cfg()
837 state->error = -EINVAL; in s5k5baf_hw_validate_cfg()
845 r->left = v->left * n->width / d->width; in s5k5baf_rescale()
846 r->top = v->top * n->height / d->height; in s5k5baf_rescale()
847 r->width = v->width * n->width / d->width; in s5k5baf_rescale()
848 r->height = v->height * n->height / d->height; in s5k5baf_rescale()
853 struct v4l2_rect *p, r; in s5k5baf_hw_set_crop_rects() local
857 p = &state->crop_sink; in s5k5baf_hw_set_crop_rects()
858 s5k5baf_write_seq(state, REG_G_PREVREQ_IN_WIDTH, p->width, p->height, in s5k5baf_hw_set_crop_rects()
859 p->left, p->top); in s5k5baf_hw_set_crop_rects()
861 s5k5baf_rescale(&r, &state->crop_source, &state->crop_sink, in s5k5baf_hw_set_crop_rects()
862 &state->compose); in s5k5baf_hw_set_crop_rects()
884 v4l2_err(&state->sd, in s5k5baf_hw_set_crop_rects()
886 state->error = -EINVAL; in s5k5baf_hw_set_crop_rects()
888 s5k5baf_hw_set_fiv(state, state->req_fiv); in s5k5baf_hw_set_crop_rects()
892 v4l2_err(&state->sd, "crop error: %d\n", err); in s5k5baf_hw_set_crop_rects()
893 return -EINVAL; in s5k5baf_hw_set_crop_rects()
896 if (!state->apply_cfg) in s5k5baf_hw_set_crop_rects()
899 p = &state->crop_source; in s5k5baf_hw_set_crop_rects()
900 s5k5baf_write_seq(state, REG_P_OUT_WIDTH(0), p->width, p->height); in s5k5baf_hw_set_crop_rects()
901 s5k5baf_hw_set_fiv(state, state->req_fiv); in s5k5baf_hw_set_crop_rects()
909 u16 reg_fmt = s5k5baf_formats[state->pixfmt].reg_p_fmt; in s5k5baf_hw_set_config()
910 struct v4l2_rect *r = &state->crop_source; in s5k5baf_hw_set_config()
913 r->width, r->height, reg_fmt, in s5k5baf_hw_set_config()
917 state->req_fiv, S5K5BAF_MIN_FR_TIME); in s5k5baf_hw_set_config()
933 gpiod_set_value_cansleep(state->gpios[id], 1); in s5k5baf_gpio_assert()
938 gpiod_set_value_cansleep(state->gpios[id], 0); in s5k5baf_gpio_deassert()
945 ret = regulator_bulk_enable(S5K5BAF_NUM_SUPPLIES, state->supplies); in s5k5baf_power_on()
949 ret = clk_set_rate(state->clock, state->mclk_frequency); in s5k5baf_power_on()
953 ret = clk_prepare_enable(state->clock); in s5k5baf_power_on()
957 v4l2_dbg(1, debug, &state->sd, "clock frequency: %ld\n", in s5k5baf_power_on()
958 clk_get_rate(state->clock)); in s5k5baf_power_on()
966 regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES, state->supplies); in s5k5baf_power_on()
968 v4l2_err(&state->sd, "%s() failed (%d)\n", __func__, ret); in s5k5baf_power_on()
976 state->streaming = 0; in s5k5baf_power_off()
977 state->apply_cfg = 0; in s5k5baf_power_off()
978 state->apply_crop = 0; in s5k5baf_power_off()
983 if (!IS_ERR(state->clock)) in s5k5baf_power_off()
984 clk_disable_unprepare(state->clock); in s5k5baf_power_off()
987 state->supplies); in s5k5baf_power_off()
989 v4l2_err(&state->sd, "failed to disable regulators\n"); in s5k5baf_power_off()
1009 state->pixfmt = 0; in s5k5baf_initialize_data()
1010 state->req_fiv = 10000 / 15; in s5k5baf_initialize_data()
1011 state->fiv = state->req_fiv; in s5k5baf_initialize_data()
1012 state->valid_auto_alg = 0; in s5k5baf_initialize_data()
1017 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_load_setfile()
1021 ret = request_firmware(&fw, S5K5BAF_FW_FILENAME, &c->dev); in s5k5baf_load_setfile()
1023 dev_warn(&c->dev, "firmware file (%s) not loaded\n", in s5k5baf_load_setfile()
1028 ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2, in s5k5baf_load_setfile()
1029 (__le16 *)fw->data); in s5k5baf_load_setfile()
1041 mutex_lock(&state->lock); in s5k5baf_set_power()
1043 if (state->power != !on) in s5k5baf_set_power()
1047 if (state->fw == NULL) in s5k5baf_set_power()
1069 state->power++; in s5k5baf_set_power()
1072 state->power--; in s5k5baf_set_power()
1076 mutex_unlock(&state->lock); in s5k5baf_set_power()
1079 ret = v4l2_ctrl_handler_setup(&state->ctrls.handler); in s5k5baf_set_power()
1094 mutex_lock(&state->lock); in s5k5baf_s_stream()
1096 if (state->streaming == !!on) { in s5k5baf_s_stream()
1113 state->streaming = !state->streaming; in s5k5baf_s_stream()
1116 mutex_unlock(&state->lock); in s5k5baf_s_stream()
1131 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) in s5k5baf_get_frame_interval()
1132 return -EINVAL; in s5k5baf_get_frame_interval()
1134 mutex_lock(&state->lock); in s5k5baf_get_frame_interval()
1135 fi->interval.numerator = state->fiv; in s5k5baf_get_frame_interval()
1136 fi->interval.denominator = 10000; in s5k5baf_get_frame_interval()
1137 mutex_unlock(&state->lock); in s5k5baf_get_frame_interval()
1145 struct v4l2_fract *i = &fi->interval; in __s5k5baf_set_frame_interval()
1147 if (fi->interval.denominator == 0) in __s5k5baf_set_frame_interval()
1148 state->req_fiv = S5K5BAF_MAX_FR_TIME; in __s5k5baf_set_frame_interval()
1150 state->req_fiv = clamp_t(u32, in __s5k5baf_set_frame_interval()
1151 i->numerator * 10000 / i->denominator, in __s5k5baf_set_frame_interval()
1155 state->fiv = state->req_fiv; in __s5k5baf_set_frame_interval()
1156 if (state->apply_cfg) { in __s5k5baf_set_frame_interval()
1157 s5k5baf_hw_set_fiv(state, state->req_fiv); in __s5k5baf_set_frame_interval()
1160 *i = (struct v4l2_fract){ state->fiv, 10000 }; in __s5k5baf_set_frame_interval()
1161 if (state->fiv == state->req_fiv) in __s5k5baf_set_frame_interval()
1162 v4l2_info(&state->sd, "frame interval changed to %d00us\n", in __s5k5baf_set_frame_interval()
1163 state->fiv); in __s5k5baf_set_frame_interval()
1176 if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) in s5k5baf_set_frame_interval()
1177 return -EINVAL; in s5k5baf_set_frame_interval()
1179 mutex_lock(&state->lock); in s5k5baf_set_frame_interval()
1181 mutex_unlock(&state->lock); in s5k5baf_set_frame_interval()
1192 if (fie->index > S5K5BAF_MAX_FR_TIME - S5K5BAF_MIN_FR_TIME || in s5k5baf_enum_frame_interval()
1193 fie->pad != PAD_CIS) in s5k5baf_enum_frame_interval()
1194 return -EINVAL; in s5k5baf_enum_frame_interval()
1196 v4l_bound_align_image(&fie->width, S5K5BAF_WIN_WIDTH_MIN, in s5k5baf_enum_frame_interval()
1198 &fie->height, S5K5BAF_WIN_HEIGHT_MIN, in s5k5baf_enum_frame_interval()
1201 fie->interval.numerator = S5K5BAF_MIN_FR_TIME + fie->index; in s5k5baf_enum_frame_interval()
1202 fie->interval.denominator = 10000; in s5k5baf_enum_frame_interval()
1211 if (code->pad == PAD_CIS) { in s5k5baf_enum_mbus_code()
1212 if (code->index > 0) in s5k5baf_enum_mbus_code()
1213 return -EINVAL; in s5k5baf_enum_mbus_code()
1214 code->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_enum_mbus_code()
1218 if (code->index >= ARRAY_SIZE(s5k5baf_formats)) in s5k5baf_enum_mbus_code()
1219 return -EINVAL; in s5k5baf_enum_mbus_code()
1221 code->code = s5k5baf_formats[code->index].code; in s5k5baf_enum_mbus_code()
1231 if (fse->index > 0) in s5k5baf_enum_frame_size()
1232 return -EINVAL; in s5k5baf_enum_frame_size()
1234 if (fse->pad == PAD_CIS) { in s5k5baf_enum_frame_size()
1235 fse->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_enum_frame_size()
1236 fse->min_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1237 fse->max_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1238 fse->min_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1239 fse->max_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1244 while (--i) in s5k5baf_enum_frame_size()
1245 if (fse->code == s5k5baf_formats[i].code) in s5k5baf_enum_frame_size()
1247 fse->code = s5k5baf_formats[i].code; in s5k5baf_enum_frame_size()
1248 fse->min_width = S5K5BAF_WIN_WIDTH_MIN; in s5k5baf_enum_frame_size()
1249 fse->max_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1250 fse->max_height = S5K5BAF_WIN_HEIGHT_MIN; in s5k5baf_enum_frame_size()
1251 fse->min_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1258 mf->width = S5K5BAF_CIS_WIDTH; in s5k5baf_try_cis_format()
1259 mf->height = S5K5BAF_CIS_HEIGHT; in s5k5baf_try_cis_format()
1260 mf->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_try_cis_format()
1261 mf->colorspace = V4L2_COLORSPACE_JPEG; in s5k5baf_try_cis_format()
1262 mf->field = V4L2_FIELD_NONE; in s5k5baf_try_cis_format()
1269 v4l_bound_align_image(&mf->width, S5K5BAF_WIN_WIDTH_MIN, in s5k5baf_try_isp_format()
1271 &mf->height, S5K5BAF_WIN_HEIGHT_MIN, in s5k5baf_try_isp_format()
1276 mf->colorspace = s5k5baf_formats[pixfmt].colorspace; in s5k5baf_try_isp_format()
1277 mf->code = s5k5baf_formats[pixfmt].code; in s5k5baf_try_isp_format()
1278 mf->field = V4L2_FIELD_NONE; in s5k5baf_try_isp_format()
1291 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_get_fmt()
1292 mf = v4l2_subdev_state_get_format(sd_state, fmt->pad); in s5k5baf_get_fmt()
1293 fmt->format = *mf; in s5k5baf_get_fmt()
1297 mf = &fmt->format; in s5k5baf_get_fmt()
1298 if (fmt->pad == PAD_CIS) { in s5k5baf_get_fmt()
1302 mf->field = V4L2_FIELD_NONE; in s5k5baf_get_fmt()
1303 mutex_lock(&state->lock); in s5k5baf_get_fmt()
1304 pixfmt = &s5k5baf_formats[state->pixfmt]; in s5k5baf_get_fmt()
1305 mf->width = state->crop_source.width; in s5k5baf_get_fmt()
1306 mf->height = state->crop_source.height; in s5k5baf_get_fmt()
1307 mf->code = pixfmt->code; in s5k5baf_get_fmt()
1308 mf->colorspace = pixfmt->colorspace; in s5k5baf_get_fmt()
1309 mutex_unlock(&state->lock); in s5k5baf_get_fmt()
1318 struct v4l2_mbus_framefmt *mf = &fmt->format; in s5k5baf_set_fmt()
1323 mf->field = V4L2_FIELD_NONE; in s5k5baf_set_fmt()
1325 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_set_fmt()
1326 *v4l2_subdev_state_get_format(sd_state, fmt->pad) = *mf; in s5k5baf_set_fmt()
1330 if (fmt->pad == PAD_CIS) { in s5k5baf_set_fmt()
1335 mutex_lock(&state->lock); in s5k5baf_set_fmt()
1337 if (state->streaming) { in s5k5baf_set_fmt()
1338 mutex_unlock(&state->lock); in s5k5baf_set_fmt()
1339 return -EBUSY; in s5k5baf_set_fmt()
1342 state->pixfmt = s5k5baf_try_isp_format(mf); in s5k5baf_set_fmt()
1343 pixfmt = &s5k5baf_formats[state->pixfmt]; in s5k5baf_set_fmt()
1344 mf->code = pixfmt->code; in s5k5baf_set_fmt()
1345 mf->colorspace = pixfmt->colorspace; in s5k5baf_set_fmt()
1346 mf->width = state->crop_source.width; in s5k5baf_set_fmt()
1347 mf->height = state->crop_source.height; in s5k5baf_set_fmt()
1349 mutex_unlock(&state->lock); in s5k5baf_set_fmt()
1384 rtype = s5k5baf_get_sel_rect(sel->pad, sel->target); in s5k5baf_get_selection()
1388 return -EINVAL; in s5k5baf_get_selection()
1390 sel->r = s5k5baf_cis_rect; in s5k5baf_get_selection()
1396 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_get_selection()
1398 sel->r = *v4l2_subdev_state_get_compose(sd_state, in s5k5baf_get_selection()
1399 sel->pad); in s5k5baf_get_selection()
1401 sel->r = *v4l2_subdev_state_get_crop(sd_state, in s5k5baf_get_selection()
1402 sel->pad); in s5k5baf_get_selection()
1406 mutex_lock(&state->lock); in s5k5baf_get_selection()
1409 sel->r = state->crop_sink; in s5k5baf_get_selection()
1412 sel->r = state->compose; in s5k5baf_get_selection()
1415 sel->r = state->crop_source; in s5k5baf_get_selection()
1420 if (s5k5baf_is_bound_target(sel->target)) { in s5k5baf_get_selection()
1421 sel->r.left = 0; in s5k5baf_get_selection()
1422 sel->r.top = 0; in s5k5baf_get_selection()
1424 mutex_unlock(&state->lock); in s5k5baf_get_selection()
1435 *start = max - *len; in s5k5baf_bound_range()
1444 s5k5baf_bound_range(&r->left, &r->width, width); in s5k5baf_bound_rect()
1445 s5k5baf_bound_range(&r->top, &r->height, height); in s5k5baf_bound_rect()
1458 br = rects[i - 1]; in s5k5baf_set_rect_and_adjust()
1459 s5k5baf_bound_rect(r, br->width, br->height); in s5k5baf_set_rect_and_adjust()
1479 rtype = s5k5baf_get_sel_rect(sel->pad, sel->target); in s5k5baf_set_selection()
1480 if (rtype == R_INVALID || s5k5baf_is_bound_target(sel->target)) in s5k5baf_set_selection()
1481 return -EINVAL; in s5k5baf_set_selection()
1483 /* allow only scaling on compose */ in s5k5baf_set_selection()
1485 sel->r.left = 0; in s5k5baf_set_selection()
1486 sel->r.top = 0; in s5k5baf_set_selection()
1489 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_set_selection()
1496 s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r); in s5k5baf_set_selection()
1502 &state->crop_sink, in s5k5baf_set_selection()
1503 &state->compose, in s5k5baf_set_selection()
1504 &state->crop_source in s5k5baf_set_selection()
1506 mutex_lock(&state->lock); in s5k5baf_set_selection()
1507 if (state->streaming) { in s5k5baf_set_selection()
1508 /* adjust sel->r to avoid output resolution change */ in s5k5baf_set_selection()
1510 if (sel->r.width < state->crop_source.width) in s5k5baf_set_selection()
1511 sel->r.width = state->crop_source.width; in s5k5baf_set_selection()
1512 if (sel->r.height < state->crop_source.height) in s5k5baf_set_selection()
1513 sel->r.height = state->crop_source.height; in s5k5baf_set_selection()
1515 sel->r.width = state->crop_source.width; in s5k5baf_set_selection()
1516 sel->r.height = state->crop_source.height; in s5k5baf_set_selection()
1519 s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r); in s5k5baf_set_selection()
1520 if (!s5k5baf_cmp_rect(&state->crop_sink, &s5k5baf_cis_rect) || in s5k5baf_set_selection()
1521 !s5k5baf_cmp_rect(&state->compose, &s5k5baf_cis_rect)) in s5k5baf_set_selection()
1522 state->apply_crop = 1; in s5k5baf_set_selection()
1523 if (state->streaming) in s5k5baf_set_selection()
1525 mutex_unlock(&state->lock); in s5k5baf_set_selection()
1563 v4l2_dbg(1, debug, sd, "ctrl: %s, value: %d\n", ctrl->name, ctrl->val); in s5k5baf_s_ctrl()
1565 mutex_lock(&state->lock); in s5k5baf_s_ctrl()
1567 if (state->power == 0) in s5k5baf_s_ctrl()
1570 switch (ctrl->id) { in s5k5baf_s_ctrl()
1572 s5k5baf_hw_set_awb(state, ctrl->val); in s5k5baf_s_ctrl()
1576 s5k5baf_write(state, REG_USER_BRIGHTNESS, ctrl->val); in s5k5baf_s_ctrl()
1580 s5k5baf_hw_set_colorfx(state, ctrl->val); in s5k5baf_s_ctrl()
1584 s5k5baf_write(state, REG_USER_CONTRAST, ctrl->val); in s5k5baf_s_ctrl()
1588 s5k5baf_hw_set_auto_exposure(state, ctrl->val); in s5k5baf_s_ctrl()
1596 s5k5baf_hw_set_anti_flicker(state, ctrl->val); in s5k5baf_s_ctrl()
1600 s5k5baf_write(state, REG_USER_SATURATION, ctrl->val); in s5k5baf_s_ctrl()
1604 s5k5baf_write(state, REG_USER_SHARPBLUR, ctrl->val); in s5k5baf_s_ctrl()
1608 s5k5baf_write(state, REG_P_COLORTEMP(0), ctrl->val); in s5k5baf_s_ctrl()
1609 if (state->apply_cfg) in s5k5baf_s_ctrl()
1614 s5k5baf_hw_set_test_pattern(state, ctrl->val); in s5k5baf_s_ctrl()
1619 mutex_unlock(&state->lock); in s5k5baf_s_ctrl()
1640 struct s5k5baf_ctrls *ctrls = &state->ctrls; in s5k5baf_initialize_ctrls()
1641 struct v4l2_ctrl_handler *hdl = &ctrls->handler; in s5k5baf_initialize_ctrls()
1646 v4l2_err(&state->sd, "cannot init ctrl handler (%d)\n", ret); in s5k5baf_initialize_ctrls()
1651 ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, in s5k5baf_initialize_ctrls()
1653 ctrls->gain_red = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE, in s5k5baf_initialize_ctrls()
1655 ctrls->gain_blue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE, in s5k5baf_initialize_ctrls()
1657 v4l2_ctrl_auto_cluster(3, &ctrls->awb, 0, false); in s5k5baf_initialize_ctrls()
1659 ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); in s5k5baf_initialize_ctrls()
1660 ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); in s5k5baf_initialize_ctrls()
1661 v4l2_ctrl_cluster(2, &ctrls->hflip); in s5k5baf_initialize_ctrls()
1663 ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops, in s5k5baf_initialize_ctrls()
1667 ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, in s5k5baf_initialize_ctrls()
1669 /* Total gain: 256 <=> 1x */ in s5k5baf_initialize_ctrls()
1670 ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, in s5k5baf_initialize_ctrls()
1672 v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false); in s5k5baf_initialize_ctrls()
1684 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1685 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1686 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1687 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1690 ARRAY_SIZE(s5k5baf_test_pattern_menu) - 1, in s5k5baf_initialize_ctrls()
1693 if (hdl->error) { in s5k5baf_initialize_ctrls()
1694 v4l2_err(&state->sd, "error creating controls (%d)\n", in s5k5baf_initialize_ctrls()
1695 hdl->error); in s5k5baf_initialize_ctrls()
1696 ret = hdl->error; in s5k5baf_initialize_ctrls()
1701 state->sd.ctrl_handler = hdl; in s5k5baf_initialize_ctrls()
1712 mf = v4l2_subdev_state_get_format(fh->state, PAD_CIS); in s5k5baf_open()
1718 mf = v4l2_subdev_state_get_format(fh->state, PAD_OUT); in s5k5baf_open()
1719 mf->colorspace = s5k5baf_formats[0].colorspace; in s5k5baf_open()
1720 mf->code = s5k5baf_formats[0].code; in s5k5baf_open()
1721 mf->width = s5k5baf_cis_rect.width; in s5k5baf_open()
1722 mf->height = s5k5baf_cis_rect.height; in s5k5baf_open()
1723 mf->field = V4L2_FIELD_NONE; in s5k5baf_open()
1725 *v4l2_subdev_state_get_crop(fh->state, PAD_CIS) = s5k5baf_cis_rect; in s5k5baf_open()
1726 *v4l2_subdev_state_get_compose(fh->state, PAD_CIS) = s5k5baf_cis_rect; in s5k5baf_open()
1727 *v4l2_subdev_state_get_crop(fh->state, PAD_OUT) = s5k5baf_cis_rect; in s5k5baf_open()
1744 v4l2_info(&state->sd, "FW API=%#x, revision=%#x sensor_id=%#x\n", in s5k5baf_check_fw_revision()
1748 v4l2_err(&state->sd, "FW API version not supported\n"); in s5k5baf_check_fw_revision()
1749 return -ENODEV; in s5k5baf_check_fw_revision()
1760 ret = v4l2_device_register_subdev(sd->v4l2_dev, &state->cis_sd); in s5k5baf_registered()
1763 state->cis_sd.name); in s5k5baf_registered()
1765 ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS, in s5k5baf_registered()
1766 &state->sd.entity, PAD_CIS, in s5k5baf_registered()
1775 v4l2_device_unregister_subdev(&state->cis_sd); in s5k5baf_unregistered()
1807 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_configure_gpios()
1812 gpio = devm_gpiod_get(&c->dev, name[i], GPIOD_OUT_HIGH); in s5k5baf_configure_gpios()
1827 state->gpios[i] = gpio; in s5k5baf_configure_gpios()
1834 struct device_node *node = dev->of_node; in s5k5baf_parse_device_node()
1840 dev_err(dev, "no device-tree node provided\n"); in s5k5baf_parse_device_node()
1841 return -EINVAL; in s5k5baf_parse_device_node()
1844 ret = of_property_read_u32(node, "clock-frequency", in s5k5baf_parse_device_node()
1845 &state->mclk_frequency); in s5k5baf_parse_device_node()
1847 state->mclk_frequency = S5K5BAF_DEFAULT_MCLK_FREQ; in s5k5baf_parse_device_node()
1849 state->mclk_frequency); in s5k5baf_parse_device_node()
1852 node_ep = of_graph_get_endpoint_by_regs(node, 0, -1); in s5k5baf_parse_device_node()
1855 return -EINVAL; in s5k5baf_parse_device_node()
1863 state->bus_type = ep.bus_type; in s5k5baf_parse_device_node()
1865 switch (state->bus_type) { in s5k5baf_parse_device_node()
1867 state->nlanes = ep.bus.mipi_csi2.num_data_lanes; in s5k5baf_parse_device_node()
1874 return -EINVAL; in s5k5baf_parse_device_node()
1886 sd = &state->cis_sd; in s5k5baf_configure_subdevs()
1888 sd->owner = THIS_MODULE; in s5k5baf_configure_subdevs()
1890 snprintf(sd->name, sizeof(sd->name), "S5K5BAF-CIS %d-%04x", in s5k5baf_configure_subdevs()
1891 i2c_adapter_id(c->adapter), c->addr); in s5k5baf_configure_subdevs()
1893 sd->internal_ops = &s5k5baf_cis_subdev_internal_ops; in s5k5baf_configure_subdevs()
1894 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in s5k5baf_configure_subdevs()
1896 state->cis_pad.flags = MEDIA_PAD_FL_SOURCE; in s5k5baf_configure_subdevs()
1897 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; in s5k5baf_configure_subdevs()
1898 ret = media_entity_pads_init(&sd->entity, NUM_CIS_PADS, &state->cis_pad); in s5k5baf_configure_subdevs()
1902 sd = &state->sd; in s5k5baf_configure_subdevs()
1904 snprintf(sd->name, sizeof(sd->name), "S5K5BAF-ISP %d-%04x", in s5k5baf_configure_subdevs()
1905 i2c_adapter_id(c->adapter), c->addr); in s5k5baf_configure_subdevs()
1907 sd->internal_ops = &s5k5baf_subdev_internal_ops; in s5k5baf_configure_subdevs()
1908 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in s5k5baf_configure_subdevs()
1910 state->pads[PAD_CIS].flags = MEDIA_PAD_FL_SINK; in s5k5baf_configure_subdevs()
1911 state->pads[PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; in s5k5baf_configure_subdevs()
1912 sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; in s5k5baf_configure_subdevs()
1913 ret = media_entity_pads_init(&sd->entity, NUM_ISP_PADS, state->pads); in s5k5baf_configure_subdevs()
1918 media_entity_cleanup(&state->cis_sd.entity); in s5k5baf_configure_subdevs()
1920 dev_err(&c->dev, "cannot init media entity %s\n", sd->name); in s5k5baf_configure_subdevs()
1926 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_configure_regulators()
1931 state->supplies[i].supply = s5k5baf_supply_names[i]; in s5k5baf_configure_regulators()
1933 ret = devm_regulator_bulk_get(&c->dev, S5K5BAF_NUM_SUPPLIES, in s5k5baf_configure_regulators()
1934 state->supplies); in s5k5baf_configure_regulators()
1945 state = devm_kzalloc(&c->dev, sizeof(*state), GFP_KERNEL); in s5k5baf_probe()
1947 return -ENOMEM; in s5k5baf_probe()
1949 mutex_init(&state->lock); in s5k5baf_probe()
1950 state->crop_sink = s5k5baf_cis_rect; in s5k5baf_probe()
1951 state->compose = s5k5baf_cis_rect; in s5k5baf_probe()
1952 state->crop_source = s5k5baf_cis_rect; in s5k5baf_probe()
1954 ret = s5k5baf_parse_device_node(state, &c->dev); in s5k5baf_probe()
1970 state->clock = devm_clk_get(state->sd.dev, S5K5BAF_CLK_NAME); in s5k5baf_probe()
1971 if (IS_ERR(state->clock)) { in s5k5baf_probe()
1972 ret = -EPROBE_DEFER; in s5k5baf_probe()
1978 ret = -EPROBE_DEFER; in s5k5baf_probe()
1992 ret = v4l2_async_register_subdev(&state->sd); in s5k5baf_probe()
1999 v4l2_ctrl_handler_free(state->sd.ctrl_handler); in s5k5baf_probe()
2001 media_entity_cleanup(&state->sd.entity); in s5k5baf_probe()
2002 media_entity_cleanup(&state->cis_sd.entity); in s5k5baf_probe()
2012 v4l2_ctrl_handler_free(sd->ctrl_handler); in s5k5baf_remove()
2013 media_entity_cleanup(&sd->entity); in s5k5baf_remove()
2015 sd = &state->cis_sd; in s5k5baf_remove()
2017 media_entity_cleanup(&sd->entity); in s5k5baf_remove()