Lines Matching +full:ctrl +full:- +full:gpios
1 // SPDX-License-Identifier: GPL-2.0-only
25 #include <media/media-entity.h>
26 #include <media/v4l2-ctrls.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-subdev.h>
29 #include <media/v4l2-mediabus.h>
30 #include <media/v4l2-fwnode.h>
39 #define S5K5BAF_FW_FILENAME "s5k5baf-cfg.bin"
51 /* Default number of MIPI CSI-2 data lanes used */
200 /* Auto-algorithms enable mask */
287 struct s5k5baf_gpio gpios[NUM_GPIOS]; member
331 /* range 16-240 */
360 return -EINVAL; in s5k5baf_fw_parse()
366 return -EINVAL; in s5k5baf_fw_parse()
370 count -= S5K5BAG_FW_TAG_LEN; in s5k5baf_fw_parse()
374 return -ENOMEM; in s5k5baf_fw_parse()
380 if (count < 1 + 2 * f->count) { in s5k5baf_fw_parse()
382 f->count, 2 * (count + S5K5BAG_FW_TAG_LEN)); in s5k5baf_fw_parse()
383 return -EINVAL; in s5k5baf_fw_parse()
386 d += 1 + 2 * f->count; in s5k5baf_fw_parse()
388 for (i = 0; i < f->count; ++i) { in s5k5baf_fw_parse()
389 if (f->seq[i].offset + d <= end) in s5k5baf_fw_parse()
392 return -EINVAL; in s5k5baf_fw_parse()
400 static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) in ctrl_to_sd() argument
402 return &container_of(ctrl->handler, struct s5k5baf, ctrls.handler)->sd; in ctrl_to_sd()
407 return sd->entity.function == MEDIA_ENT_F_CAM_SENSOR; in s5k5baf_is_cis_subdev()
420 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_i2c_read()
424 { .addr = c->addr, .flags = 0, in s5k5baf_i2c_read()
426 { .addr = c->addr, .flags = I2C_M_RD, in s5k5baf_i2c_read()
431 if (state->error) in s5k5baf_i2c_read()
435 ret = i2c_transfer(c->adapter, msg, 2); in s5k5baf_i2c_read()
442 state->error = ret; in s5k5baf_i2c_read()
450 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_i2c_write()
453 if (state->error) in s5k5baf_i2c_write()
461 state->error = ret; in s5k5baf_i2c_write()
480 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_write_arr_seq()
484 if (state->error) in s5k5baf_write_arr_seq()
493 int n = min_t(int, count, ARRAY_SIZE(buf) - 1); in s5k5baf_write_arr_seq()
503 state->error = ret; in s5k5baf_write_arr_seq()
507 count -= n; in s5k5baf_write_arr_seq()
519 * s5k5baf_write_nseq() - Writes sequences of values to sensor memory via i2c
521 * (N, address, value[1]...value[N-1])*,0
532 --count; in s5k5baf_write_nseq()
547 if (state->error || !reg) in s5k5baf_synchronize()
552 v4l2_err(&state->sd, "timeout on register synchronize (%#x)\n", addr); in s5k5baf_synchronize()
553 state->error = -ETIMEDOUT; in s5k5baf_synchronize()
558 struct s5k5baf_fw *fw = state->fw; in s5k5baf_fw_get_seq()
565 data = &fw->seq[0].id + 2 * fw->count; in s5k5baf_fw_get_seq()
567 for (i = 0; i < fw->count; ++i) { in s5k5baf_fw_get_seq()
568 if (fw->seq[i].id == seq_id) in s5k5baf_fw_get_seq()
569 return data + fw->seq[i].offset; in s5k5baf_fw_get_seq()
585 unsigned long mclk = state->mclk_frequency / 1000; in s5k5baf_hw_set_clocks()
601 if (!state->error && status) { in s5k5baf_hw_set_clocks()
602 v4l2_err(&state->sd, "error configuring PLL (%d)\n", status); in s5k5baf_hw_set_clocks()
603 state->error = -EINVAL; in s5k5baf_hw_set_clocks()
632 if (state->apply_crop) { in s5k5baf_hw_sync_cfg()
641 u16 flip = state->ctrls.vflip->val | (state->ctrls.vflip->val << 1); in s5k5baf_hw_set_mirror()
644 if (state->streaming) in s5k5baf_hw_set_mirror()
652 if (!state->valid_auto_alg) in s5k5baf_hw_set_alg()
655 cur_alg = state->auto_alg; in s5k5baf_hw_set_alg()
662 if (state->error) in s5k5baf_hw_set_alg()
665 state->valid_auto_alg = 1; in s5k5baf_hw_set_alg()
666 state->auto_alg = new_alg; in s5k5baf_hw_set_alg()
672 struct s5k5baf_ctrls *ctrls = &state->ctrls; in s5k5baf_hw_set_awb()
676 ctrls->gain_red->val, 1, in s5k5baf_hw_set_awb()
678 ctrls->gain_blue->val, 1, in s5k5baf_hw_set_awb()
704 unsigned int exp_time = state->ctrls.exposure->val; in s5k5baf_hw_set_auto_exposure()
707 s5k5baf_hw_set_user_gain(state, state->ctrls.gain->val); in s5k5baf_hw_set_auto_exposure()
740 int i, c = -1; in s5k5baf_find_pixfmt()
743 if (mf->colorspace != s5k5baf_formats[i].colorspace) in s5k5baf_find_pixfmt()
745 if (mf->code == s5k5baf_formats[i].code) in s5k5baf_find_pixfmt()
755 int ret = state->error; in s5k5baf_clear_error()
757 state->error = 0; in s5k5baf_clear_error()
765 if (state->bus_type == V4L2_MBUS_CSI2_DPHY) in s5k5baf_hw_set_video_bus()
771 state->nlanes, en_pkts, 1); in s5k5baf_hw_set_video_bus()
796 if (state->error) in s5k5baf_hw_find_min_fiv()
799 for (n = 5; n > 0; --n) { in s5k5baf_hw_find_min_fiv()
802 if (state->error) in s5k5baf_hw_find_min_fiv()
809 state->fiv = fiv; in s5k5baf_hw_find_min_fiv()
810 v4l2_info(&state->sd, in s5k5baf_hw_find_min_fiv()
814 v4l2_err(&state->sd, in s5k5baf_hw_find_min_fiv()
816 state->error = -EINVAL; in s5k5baf_hw_find_min_fiv()
819 v4l2_err(&state->sd, "cannot find correct frame interval\n"); in s5k5baf_hw_find_min_fiv()
820 state->error = -ERANGE; in s5k5baf_hw_find_min_fiv()
828 if (state->error) in s5k5baf_hw_validate_cfg()
833 state->apply_cfg = 1; in s5k5baf_hw_validate_cfg()
837 if (!state->error) in s5k5baf_hw_validate_cfg()
838 state->apply_cfg = 1; in s5k5baf_hw_validate_cfg()
841 v4l2_err(&state->sd, in s5k5baf_hw_validate_cfg()
843 state->error = -EINVAL; in s5k5baf_hw_validate_cfg()
851 r->left = v->left * n->width / d->width; in s5k5baf_rescale()
852 r->top = v->top * n->height / d->height; in s5k5baf_rescale()
853 r->width = v->width * n->width / d->width; in s5k5baf_rescale()
854 r->height = v->height * n->height / d->height; in s5k5baf_rescale()
863 p = &state->crop_sink; in s5k5baf_hw_set_crop_rects()
864 s5k5baf_write_seq(state, REG_G_PREVREQ_IN_WIDTH, p->width, p->height, in s5k5baf_hw_set_crop_rects()
865 p->left, p->top); in s5k5baf_hw_set_crop_rects()
867 s5k5baf_rescale(&r, &state->crop_source, &state->crop_sink, in s5k5baf_hw_set_crop_rects()
868 &state->compose); in s5k5baf_hw_set_crop_rects()
890 v4l2_err(&state->sd, in s5k5baf_hw_set_crop_rects()
892 state->error = -EINVAL; in s5k5baf_hw_set_crop_rects()
894 s5k5baf_hw_set_fiv(state, state->req_fiv); in s5k5baf_hw_set_crop_rects()
898 v4l2_err(&state->sd, "crop error: %d\n", err); in s5k5baf_hw_set_crop_rects()
899 return -EINVAL; in s5k5baf_hw_set_crop_rects()
902 if (!state->apply_cfg) in s5k5baf_hw_set_crop_rects()
905 p = &state->crop_source; in s5k5baf_hw_set_crop_rects()
906 s5k5baf_write_seq(state, REG_P_OUT_WIDTH(0), p->width, p->height); in s5k5baf_hw_set_crop_rects()
907 s5k5baf_hw_set_fiv(state, state->req_fiv); in s5k5baf_hw_set_crop_rects()
915 u16 reg_fmt = s5k5baf_formats[state->pixfmt].reg_p_fmt; in s5k5baf_hw_set_config()
916 struct v4l2_rect *r = &state->crop_source; in s5k5baf_hw_set_config()
919 r->width, r->height, reg_fmt, in s5k5baf_hw_set_config()
923 state->req_fiv, S5K5BAF_MIN_FR_TIME); in s5k5baf_hw_set_config()
939 struct s5k5baf_gpio *gpio = &state->gpios[id]; in s5k5baf_gpio_assert()
941 gpio_set_value(gpio->gpio, gpio->level); in s5k5baf_gpio_assert()
946 struct s5k5baf_gpio *gpio = &state->gpios[id]; in s5k5baf_gpio_deassert()
948 gpio_set_value(gpio->gpio, !gpio->level); in s5k5baf_gpio_deassert()
955 ret = regulator_bulk_enable(S5K5BAF_NUM_SUPPLIES, state->supplies); in s5k5baf_power_on()
959 ret = clk_set_rate(state->clock, state->mclk_frequency); in s5k5baf_power_on()
963 ret = clk_prepare_enable(state->clock); in s5k5baf_power_on()
967 v4l2_dbg(1, debug, &state->sd, "clock frequency: %ld\n", in s5k5baf_power_on()
968 clk_get_rate(state->clock)); in s5k5baf_power_on()
976 regulator_bulk_disable(S5K5BAF_NUM_SUPPLIES, state->supplies); in s5k5baf_power_on()
978 v4l2_err(&state->sd, "%s() failed (%d)\n", __func__, ret); in s5k5baf_power_on()
986 state->streaming = 0; in s5k5baf_power_off()
987 state->apply_cfg = 0; in s5k5baf_power_off()
988 state->apply_crop = 0; in s5k5baf_power_off()
993 if (!IS_ERR(state->clock)) in s5k5baf_power_off()
994 clk_disable_unprepare(state->clock); in s5k5baf_power_off()
997 state->supplies); in s5k5baf_power_off()
999 v4l2_err(&state->sd, "failed to disable regulators\n"); in s5k5baf_power_off()
1019 state->pixfmt = 0; in s5k5baf_initialize_data()
1020 state->req_fiv = 10000 / 15; in s5k5baf_initialize_data()
1021 state->fiv = state->req_fiv; in s5k5baf_initialize_data()
1022 state->valid_auto_alg = 0; in s5k5baf_initialize_data()
1027 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_load_setfile()
1031 ret = request_firmware(&fw, S5K5BAF_FW_FILENAME, &c->dev); in s5k5baf_load_setfile()
1033 dev_warn(&c->dev, "firmware file (%s) not loaded\n", in s5k5baf_load_setfile()
1038 ret = s5k5baf_fw_parse(&c->dev, &state->fw, fw->size / 2, in s5k5baf_load_setfile()
1039 (__le16 *)fw->data); in s5k5baf_load_setfile()
1051 mutex_lock(&state->lock); in s5k5baf_set_power()
1053 if (state->power != !on) in s5k5baf_set_power()
1057 if (state->fw == NULL) in s5k5baf_set_power()
1079 state->power++; in s5k5baf_set_power()
1082 state->power--; in s5k5baf_set_power()
1086 mutex_unlock(&state->lock); in s5k5baf_set_power()
1089 ret = v4l2_ctrl_handler_setup(&state->ctrls.handler); in s5k5baf_set_power()
1104 mutex_lock(&state->lock); in s5k5baf_s_stream()
1106 if (state->streaming == !!on) { in s5k5baf_s_stream()
1123 state->streaming = !state->streaming; in s5k5baf_s_stream()
1126 mutex_unlock(&state->lock); in s5k5baf_s_stream()
1136 mutex_lock(&state->lock); in s5k5baf_g_frame_interval()
1137 fi->interval.numerator = state->fiv; in s5k5baf_g_frame_interval()
1138 fi->interval.denominator = 10000; in s5k5baf_g_frame_interval()
1139 mutex_unlock(&state->lock); in s5k5baf_g_frame_interval()
1147 struct v4l2_fract *i = &fi->interval; in s5k5baf_set_frame_interval()
1149 if (fi->interval.denominator == 0) in s5k5baf_set_frame_interval()
1150 state->req_fiv = S5K5BAF_MAX_FR_TIME; in s5k5baf_set_frame_interval()
1152 state->req_fiv = clamp_t(u32, in s5k5baf_set_frame_interval()
1153 i->numerator * 10000 / i->denominator, in s5k5baf_set_frame_interval()
1157 state->fiv = state->req_fiv; in s5k5baf_set_frame_interval()
1158 if (state->apply_cfg) { in s5k5baf_set_frame_interval()
1159 s5k5baf_hw_set_fiv(state, state->req_fiv); in s5k5baf_set_frame_interval()
1162 *i = (struct v4l2_fract){ state->fiv, 10000 }; in s5k5baf_set_frame_interval()
1163 if (state->fiv == state->req_fiv) in s5k5baf_set_frame_interval()
1164 v4l2_info(&state->sd, "frame interval changed to %d00us\n", in s5k5baf_set_frame_interval()
1165 state->fiv); in s5k5baf_set_frame_interval()
1173 mutex_lock(&state->lock); in s5k5baf_s_frame_interval()
1175 mutex_unlock(&state->lock); in s5k5baf_s_frame_interval()
1186 if (fie->index > S5K5BAF_MAX_FR_TIME - S5K5BAF_MIN_FR_TIME || in s5k5baf_enum_frame_interval()
1187 fie->pad != PAD_CIS) in s5k5baf_enum_frame_interval()
1188 return -EINVAL; in s5k5baf_enum_frame_interval()
1190 v4l_bound_align_image(&fie->width, S5K5BAF_WIN_WIDTH_MIN, in s5k5baf_enum_frame_interval()
1192 &fie->height, S5K5BAF_WIN_HEIGHT_MIN, in s5k5baf_enum_frame_interval()
1195 fie->interval.numerator = S5K5BAF_MIN_FR_TIME + fie->index; in s5k5baf_enum_frame_interval()
1196 fie->interval.denominator = 10000; in s5k5baf_enum_frame_interval()
1205 if (code->pad == PAD_CIS) { in s5k5baf_enum_mbus_code()
1206 if (code->index > 0) in s5k5baf_enum_mbus_code()
1207 return -EINVAL; in s5k5baf_enum_mbus_code()
1208 code->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_enum_mbus_code()
1212 if (code->index >= ARRAY_SIZE(s5k5baf_formats)) in s5k5baf_enum_mbus_code()
1213 return -EINVAL; in s5k5baf_enum_mbus_code()
1215 code->code = s5k5baf_formats[code->index].code; in s5k5baf_enum_mbus_code()
1225 if (fse->index > 0) in s5k5baf_enum_frame_size()
1226 return -EINVAL; in s5k5baf_enum_frame_size()
1228 if (fse->pad == PAD_CIS) { in s5k5baf_enum_frame_size()
1229 fse->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_enum_frame_size()
1230 fse->min_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1231 fse->max_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1232 fse->min_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1233 fse->max_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1238 while (--i) in s5k5baf_enum_frame_size()
1239 if (fse->code == s5k5baf_formats[i].code) in s5k5baf_enum_frame_size()
1241 fse->code = s5k5baf_formats[i].code; in s5k5baf_enum_frame_size()
1242 fse->min_width = S5K5BAF_WIN_WIDTH_MIN; in s5k5baf_enum_frame_size()
1243 fse->max_width = S5K5BAF_CIS_WIDTH; in s5k5baf_enum_frame_size()
1244 fse->max_height = S5K5BAF_WIN_HEIGHT_MIN; in s5k5baf_enum_frame_size()
1245 fse->min_height = S5K5BAF_CIS_HEIGHT; in s5k5baf_enum_frame_size()
1252 mf->width = S5K5BAF_CIS_WIDTH; in s5k5baf_try_cis_format()
1253 mf->height = S5K5BAF_CIS_HEIGHT; in s5k5baf_try_cis_format()
1254 mf->code = MEDIA_BUS_FMT_FIXED; in s5k5baf_try_cis_format()
1255 mf->colorspace = V4L2_COLORSPACE_JPEG; in s5k5baf_try_cis_format()
1256 mf->field = V4L2_FIELD_NONE; in s5k5baf_try_cis_format()
1263 v4l_bound_align_image(&mf->width, S5K5BAF_WIN_WIDTH_MIN, in s5k5baf_try_isp_format()
1265 &mf->height, S5K5BAF_WIN_HEIGHT_MIN, in s5k5baf_try_isp_format()
1270 mf->colorspace = s5k5baf_formats[pixfmt].colorspace; in s5k5baf_try_isp_format()
1271 mf->code = s5k5baf_formats[pixfmt].code; in s5k5baf_try_isp_format()
1272 mf->field = V4L2_FIELD_NONE; in s5k5baf_try_isp_format()
1285 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_get_fmt()
1286 mf = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad); in s5k5baf_get_fmt()
1287 fmt->format = *mf; in s5k5baf_get_fmt()
1291 mf = &fmt->format; in s5k5baf_get_fmt()
1292 if (fmt->pad == PAD_CIS) { in s5k5baf_get_fmt()
1296 mf->field = V4L2_FIELD_NONE; in s5k5baf_get_fmt()
1297 mutex_lock(&state->lock); in s5k5baf_get_fmt()
1298 pixfmt = &s5k5baf_formats[state->pixfmt]; in s5k5baf_get_fmt()
1299 mf->width = state->crop_source.width; in s5k5baf_get_fmt()
1300 mf->height = state->crop_source.height; in s5k5baf_get_fmt()
1301 mf->code = pixfmt->code; in s5k5baf_get_fmt()
1302 mf->colorspace = pixfmt->colorspace; in s5k5baf_get_fmt()
1303 mutex_unlock(&state->lock); in s5k5baf_get_fmt()
1312 struct v4l2_mbus_framefmt *mf = &fmt->format; in s5k5baf_set_fmt()
1317 mf->field = V4L2_FIELD_NONE; in s5k5baf_set_fmt()
1319 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_set_fmt()
1320 *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = *mf; in s5k5baf_set_fmt()
1324 if (fmt->pad == PAD_CIS) { in s5k5baf_set_fmt()
1329 mutex_lock(&state->lock); in s5k5baf_set_fmt()
1331 if (state->streaming) { in s5k5baf_set_fmt()
1332 mutex_unlock(&state->lock); in s5k5baf_set_fmt()
1333 return -EBUSY; in s5k5baf_set_fmt()
1336 state->pixfmt = s5k5baf_try_isp_format(mf); in s5k5baf_set_fmt()
1337 pixfmt = &s5k5baf_formats[state->pixfmt]; in s5k5baf_set_fmt()
1338 mf->code = pixfmt->code; in s5k5baf_set_fmt()
1339 mf->colorspace = pixfmt->colorspace; in s5k5baf_set_fmt()
1340 mf->width = state->crop_source.width; in s5k5baf_set_fmt()
1341 mf->height = state->crop_source.height; in s5k5baf_set_fmt()
1343 mutex_unlock(&state->lock); in s5k5baf_set_fmt()
1378 rtype = s5k5baf_get_sel_rect(sel->pad, sel->target); in s5k5baf_get_selection()
1382 return -EINVAL; in s5k5baf_get_selection()
1384 sel->r = s5k5baf_cis_rect; in s5k5baf_get_selection()
1390 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_get_selection()
1392 sel->r = *v4l2_subdev_get_try_compose(sd, sd_state, in s5k5baf_get_selection()
1393 sel->pad); in s5k5baf_get_selection()
1395 sel->r = *v4l2_subdev_get_try_crop(sd, sd_state, in s5k5baf_get_selection()
1396 sel->pad); in s5k5baf_get_selection()
1400 mutex_lock(&state->lock); in s5k5baf_get_selection()
1403 sel->r = state->crop_sink; in s5k5baf_get_selection()
1406 sel->r = state->compose; in s5k5baf_get_selection()
1409 sel->r = state->crop_source; in s5k5baf_get_selection()
1414 if (s5k5baf_is_bound_target(sel->target)) { in s5k5baf_get_selection()
1415 sel->r.left = 0; in s5k5baf_get_selection()
1416 sel->r.top = 0; in s5k5baf_get_selection()
1418 mutex_unlock(&state->lock); in s5k5baf_get_selection()
1429 *start = max - *len; in s5k5baf_bound_range()
1438 s5k5baf_bound_range(&r->left, &r->width, width); in s5k5baf_bound_rect()
1439 s5k5baf_bound_range(&r->top, &r->height, height); in s5k5baf_bound_rect()
1452 br = rects[i - 1]; in s5k5baf_set_rect_and_adjust()
1453 s5k5baf_bound_rect(r, br->width, br->height); in s5k5baf_set_rect_and_adjust()
1473 rtype = s5k5baf_get_sel_rect(sel->pad, sel->target); in s5k5baf_set_selection()
1474 if (rtype == R_INVALID || s5k5baf_is_bound_target(sel->target)) in s5k5baf_set_selection()
1475 return -EINVAL; in s5k5baf_set_selection()
1479 sel->r.left = 0; in s5k5baf_set_selection()
1480 sel->r.top = 0; in s5k5baf_set_selection()
1483 if (sel->which == V4L2_SUBDEV_FORMAT_TRY) { in s5k5baf_set_selection()
1493 s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r); in s5k5baf_set_selection()
1499 &state->crop_sink, in s5k5baf_set_selection()
1500 &state->compose, in s5k5baf_set_selection()
1501 &state->crop_source in s5k5baf_set_selection()
1503 mutex_lock(&state->lock); in s5k5baf_set_selection()
1504 if (state->streaming) { in s5k5baf_set_selection()
1505 /* adjust sel->r to avoid output resolution change */ in s5k5baf_set_selection()
1507 if (sel->r.width < state->crop_source.width) in s5k5baf_set_selection()
1508 sel->r.width = state->crop_source.width; in s5k5baf_set_selection()
1509 if (sel->r.height < state->crop_source.height) in s5k5baf_set_selection()
1510 sel->r.height = state->crop_source.height; in s5k5baf_set_selection()
1512 sel->r.width = state->crop_source.width; in s5k5baf_set_selection()
1513 sel->r.height = state->crop_source.height; in s5k5baf_set_selection()
1516 s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r); in s5k5baf_set_selection()
1517 if (!s5k5baf_cmp_rect(&state->crop_sink, &s5k5baf_cis_rect) || in s5k5baf_set_selection()
1518 !s5k5baf_cmp_rect(&state->compose, &s5k5baf_cis_rect)) in s5k5baf_set_selection()
1519 state->apply_crop = 1; in s5k5baf_set_selection()
1520 if (state->streaming) in s5k5baf_set_selection()
1522 mutex_unlock(&state->lock); in s5k5baf_set_selection()
1554 static int s5k5baf_s_ctrl(struct v4l2_ctrl *ctrl) in s5k5baf_s_ctrl() argument
1556 struct v4l2_subdev *sd = ctrl_to_sd(ctrl); in s5k5baf_s_ctrl()
1560 v4l2_dbg(1, debug, sd, "ctrl: %s, value: %d\n", ctrl->name, ctrl->val); in s5k5baf_s_ctrl()
1562 mutex_lock(&state->lock); in s5k5baf_s_ctrl()
1564 if (state->power == 0) in s5k5baf_s_ctrl()
1567 switch (ctrl->id) { in s5k5baf_s_ctrl()
1569 s5k5baf_hw_set_awb(state, ctrl->val); in s5k5baf_s_ctrl()
1573 s5k5baf_write(state, REG_USER_BRIGHTNESS, ctrl->val); in s5k5baf_s_ctrl()
1577 s5k5baf_hw_set_colorfx(state, ctrl->val); in s5k5baf_s_ctrl()
1581 s5k5baf_write(state, REG_USER_CONTRAST, ctrl->val); in s5k5baf_s_ctrl()
1585 s5k5baf_hw_set_auto_exposure(state, ctrl->val); in s5k5baf_s_ctrl()
1593 s5k5baf_hw_set_anti_flicker(state, ctrl->val); in s5k5baf_s_ctrl()
1597 s5k5baf_write(state, REG_USER_SATURATION, ctrl->val); in s5k5baf_s_ctrl()
1601 s5k5baf_write(state, REG_USER_SHARPBLUR, ctrl->val); in s5k5baf_s_ctrl()
1605 s5k5baf_write(state, REG_P_COLORTEMP(0), ctrl->val); in s5k5baf_s_ctrl()
1606 if (state->apply_cfg) in s5k5baf_s_ctrl()
1611 s5k5baf_hw_set_test_pattern(state, ctrl->val); in s5k5baf_s_ctrl()
1616 mutex_unlock(&state->lock); in s5k5baf_s_ctrl()
1637 struct s5k5baf_ctrls *ctrls = &state->ctrls; in s5k5baf_initialize_ctrls()
1638 struct v4l2_ctrl_handler *hdl = &ctrls->handler; in s5k5baf_initialize_ctrls()
1643 v4l2_err(&state->sd, "cannot init ctrl handler (%d)\n", ret); in s5k5baf_initialize_ctrls()
1648 ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE, in s5k5baf_initialize_ctrls()
1650 ctrls->gain_red = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE, in s5k5baf_initialize_ctrls()
1652 ctrls->gain_blue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE, in s5k5baf_initialize_ctrls()
1654 v4l2_ctrl_auto_cluster(3, &ctrls->awb, 0, false); in s5k5baf_initialize_ctrls()
1656 ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0); in s5k5baf_initialize_ctrls()
1657 ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0); in s5k5baf_initialize_ctrls()
1658 v4l2_ctrl_cluster(2, &ctrls->hflip); in s5k5baf_initialize_ctrls()
1660 ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops, in s5k5baf_initialize_ctrls()
1664 ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE, in s5k5baf_initialize_ctrls()
1667 ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, in s5k5baf_initialize_ctrls()
1669 v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false); in s5k5baf_initialize_ctrls()
1681 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1682 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1683 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1684 v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0); in s5k5baf_initialize_ctrls()
1687 ARRAY_SIZE(s5k5baf_test_pattern_menu) - 1, in s5k5baf_initialize_ctrls()
1690 if (hdl->error) { in s5k5baf_initialize_ctrls()
1691 v4l2_err(&state->sd, "error creating controls (%d)\n", in s5k5baf_initialize_ctrls()
1692 hdl->error); in s5k5baf_initialize_ctrls()
1693 ret = hdl->error; in s5k5baf_initialize_ctrls()
1698 state->sd.ctrl_handler = hdl; in s5k5baf_initialize_ctrls()
1709 mf = v4l2_subdev_get_try_format(sd, fh->state, PAD_CIS); in s5k5baf_open()
1715 mf = v4l2_subdev_get_try_format(sd, fh->state, PAD_OUT); in s5k5baf_open()
1716 mf->colorspace = s5k5baf_formats[0].colorspace; in s5k5baf_open()
1717 mf->code = s5k5baf_formats[0].code; in s5k5baf_open()
1718 mf->width = s5k5baf_cis_rect.width; in s5k5baf_open()
1719 mf->height = s5k5baf_cis_rect.height; in s5k5baf_open()
1720 mf->field = V4L2_FIELD_NONE; in s5k5baf_open()
1722 *v4l2_subdev_get_try_crop(sd, fh->state, PAD_CIS) = s5k5baf_cis_rect; in s5k5baf_open()
1723 *v4l2_subdev_get_try_compose(sd, fh->state, PAD_CIS) = s5k5baf_cis_rect; in s5k5baf_open()
1724 *v4l2_subdev_get_try_crop(sd, fh->state, PAD_OUT) = s5k5baf_cis_rect; in s5k5baf_open()
1741 v4l2_info(&state->sd, "FW API=%#x, revision=%#x sensor_id=%#x\n", in s5k5baf_check_fw_revision()
1745 v4l2_err(&state->sd, "FW API version not supported\n"); in s5k5baf_check_fw_revision()
1746 return -ENODEV; in s5k5baf_check_fw_revision()
1757 ret = v4l2_device_register_subdev(sd->v4l2_dev, &state->cis_sd); in s5k5baf_registered()
1760 state->cis_sd.name); in s5k5baf_registered()
1762 ret = media_create_pad_link(&state->cis_sd.entity, PAD_CIS, in s5k5baf_registered()
1763 &state->sd.entity, PAD_CIS, in s5k5baf_registered()
1772 v4l2_device_unregister_subdev(&state->cis_sd); in s5k5baf_unregistered()
1803 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_configure_gpios()
1804 struct s5k5baf_gpio *g = state->gpios; in s5k5baf_configure_gpios()
1811 ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags, name[i]); in s5k5baf_configure_gpios()
1820 static int s5k5baf_parse_gpios(struct s5k5baf_gpio *gpios, struct device *dev) in s5k5baf_parse_gpios() argument
1823 "stbyn-gpios", in s5k5baf_parse_gpios()
1824 "rstn-gpios", in s5k5baf_parse_gpios()
1826 struct device_node *node = dev->of_node; in s5k5baf_parse_gpios()
1836 gpios[i].gpio = ret; in s5k5baf_parse_gpios()
1837 gpios[i].level = !(flags & OF_GPIO_ACTIVE_LOW); in s5k5baf_parse_gpios()
1845 struct device_node *node = dev->of_node; in s5k5baf_parse_device_node()
1851 dev_err(dev, "no device-tree node provided\n"); in s5k5baf_parse_device_node()
1852 return -EINVAL; in s5k5baf_parse_device_node()
1855 ret = of_property_read_u32(node, "clock-frequency", in s5k5baf_parse_device_node()
1856 &state->mclk_frequency); in s5k5baf_parse_device_node()
1858 state->mclk_frequency = S5K5BAF_DEFAULT_MCLK_FREQ; in s5k5baf_parse_device_node()
1860 state->mclk_frequency); in s5k5baf_parse_device_node()
1863 ret = s5k5baf_parse_gpios(state->gpios, dev); in s5k5baf_parse_device_node()
1870 return -EINVAL; in s5k5baf_parse_device_node()
1878 state->bus_type = ep.bus_type; in s5k5baf_parse_device_node()
1880 switch (state->bus_type) { in s5k5baf_parse_device_node()
1882 state->nlanes = ep.bus.mipi_csi2.num_data_lanes; in s5k5baf_parse_device_node()
1889 return -EINVAL; in s5k5baf_parse_device_node()
1901 sd = &state->cis_sd; in s5k5baf_configure_subdevs()
1903 sd->owner = THIS_MODULE; in s5k5baf_configure_subdevs()
1905 snprintf(sd->name, sizeof(sd->name), "S5K5BAF-CIS %d-%04x", in s5k5baf_configure_subdevs()
1906 i2c_adapter_id(c->adapter), c->addr); in s5k5baf_configure_subdevs()
1908 sd->internal_ops = &s5k5baf_cis_subdev_internal_ops; in s5k5baf_configure_subdevs()
1909 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in s5k5baf_configure_subdevs()
1911 state->cis_pad.flags = MEDIA_PAD_FL_SOURCE; in s5k5baf_configure_subdevs()
1912 sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; in s5k5baf_configure_subdevs()
1913 ret = media_entity_pads_init(&sd->entity, NUM_CIS_PADS, &state->cis_pad); in s5k5baf_configure_subdevs()
1917 sd = &state->sd; in s5k5baf_configure_subdevs()
1919 snprintf(sd->name, sizeof(sd->name), "S5K5BAF-ISP %d-%04x", in s5k5baf_configure_subdevs()
1920 i2c_adapter_id(c->adapter), c->addr); in s5k5baf_configure_subdevs()
1922 sd->internal_ops = &s5k5baf_subdev_internal_ops; in s5k5baf_configure_subdevs()
1923 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; in s5k5baf_configure_subdevs()
1925 state->pads[PAD_CIS].flags = MEDIA_PAD_FL_SINK; in s5k5baf_configure_subdevs()
1926 state->pads[PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; in s5k5baf_configure_subdevs()
1927 sd->entity.function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN; in s5k5baf_configure_subdevs()
1928 ret = media_entity_pads_init(&sd->entity, NUM_ISP_PADS, state->pads); in s5k5baf_configure_subdevs()
1933 media_entity_cleanup(&state->cis_sd.entity); in s5k5baf_configure_subdevs()
1935 dev_err(&c->dev, "cannot init media entity %s\n", sd->name); in s5k5baf_configure_subdevs()
1941 struct i2c_client *c = v4l2_get_subdevdata(&state->sd); in s5k5baf_configure_regulators()
1946 state->supplies[i].supply = s5k5baf_supply_names[i]; in s5k5baf_configure_regulators()
1948 ret = devm_regulator_bulk_get(&c->dev, S5K5BAF_NUM_SUPPLIES, in s5k5baf_configure_regulators()
1949 state->supplies); in s5k5baf_configure_regulators()
1960 state = devm_kzalloc(&c->dev, sizeof(*state), GFP_KERNEL); in s5k5baf_probe()
1962 return -ENOMEM; in s5k5baf_probe()
1964 mutex_init(&state->lock); in s5k5baf_probe()
1965 state->crop_sink = s5k5baf_cis_rect; in s5k5baf_probe()
1966 state->compose = s5k5baf_cis_rect; in s5k5baf_probe()
1967 state->crop_source = s5k5baf_cis_rect; in s5k5baf_probe()
1969 ret = s5k5baf_parse_device_node(state, &c->dev); in s5k5baf_probe()
1985 state->clock = devm_clk_get(state->sd.dev, S5K5BAF_CLK_NAME); in s5k5baf_probe()
1986 if (IS_ERR(state->clock)) { in s5k5baf_probe()
1987 ret = -EPROBE_DEFER; in s5k5baf_probe()
1993 ret = -EPROBE_DEFER; in s5k5baf_probe()
2007 ret = v4l2_async_register_subdev(&state->sd); in s5k5baf_probe()
2014 v4l2_ctrl_handler_free(state->sd.ctrl_handler); in s5k5baf_probe()
2016 media_entity_cleanup(&state->sd.entity); in s5k5baf_probe()
2017 media_entity_cleanup(&state->cis_sd.entity); in s5k5baf_probe()
2027 v4l2_ctrl_handler_free(sd->ctrl_handler); in s5k5baf_remove()
2028 media_entity_cleanup(&sd->entity); in s5k5baf_remove()
2030 sd = &state->cis_sd; in s5k5baf_remove()
2032 media_entity_cleanup(&sd->entity); in s5k5baf_remove()