Lines Matching +full:tri +full:- +full:default
1 // SPDX-License-Identifier: GPL-2.0
12 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
26 #include <linux/v4l2-mediabus.h>
31 #include <media/v4l2-ctrls.h>
32 #include <media/v4l2-device.h>
33 #include <media/v4l2-event.h>
34 #include <media/v4l2-fwnode.h>
35 #include <media/v4l2-image-sizes.h>
36 #include <media/v4l2-subdev.h>
41 #define GAIN 0x00 /* AGC - Gain control gain setting */
42 #define BLUE 0x01 /* AWB - Blue channel gain setting */
43 #define RED 0x02 /* AWB - Red channel gain setting */
44 #define GREEN 0x03 /* AWB - Green channel gain setting */
49 #define AECH 0x08 /* Exposure Value - AEC MSBs */
65 #define HSIZE 0x18 /* Horizontal frame (HREF column) end high 8-bit */
66 #define VSTART 0x19 /* Vertical frame (row) start high 8-bit */
68 #define PSHFT 0x1B /* Data format - pixel delay select */
69 #define MIDH 0x1C /* Manufacturer ID byte - high */
70 #define MIDL 0x1D /* Manufacturer ID byte - low */
75 #define AEW 0x24 /* AGC/AEC - Stable operating region (upper limit) */
76 #define AEB 0x25 /* AGC/AEC - Stable operating region (lower limit) */
110 #define LCC1 0x47 /* Lens correction option 1 - X coordinate */
111 #define LCC2 0x48 /* Lens correction option 2 - Y coordinate */
113 #define LCC4 0x4A /* Lens correction option 4 - radius of the circular */
180 #define DNSTH 0x8E /* De-noise threshold */
183 #define DNSOFF 0x91 /* Auto De-noise threshold control */
237 /* Tri-state option for output clock */
238 #define NOTRI_CLOCK 0x04 /* 0: Tri-state at this period */
239 /* 1: No tri-state at this period */
240 /* Tri-state option for output data */
241 #define NOTRI_DATA 0x02 /* 0: Tri-state at this period */
242 /* 1: No tri-state at this period */
277 #define CLKRC_DIV(n) ((n) - 1)
282 /* 1 : Resets all registers to default */
316 /* Automatic gain ceiling - maximum AGC value */
367 #define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */
429 /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
501 /* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output,
502 * regardless of the COM7 value. We can thus only support 10-bit
565 ret = regmap_write(priv->regmap, COM7, SCCB_RESET); in ov772x_reset()
571 return regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, in ov772x_reset()
585 mutex_lock(&priv->lock); in ov772x_s_stream()
587 if (priv->streaming == enable) in ov772x_s_stream()
590 if (priv->bus_type == V4L2_MBUS_BT656) { in ov772x_s_stream()
591 ret = regmap_update_bits(priv->regmap, COM7, ITU656_ON_OFF, in ov772x_s_stream()
598 ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, in ov772x_s_stream()
604 dev_dbg(&client->dev, "format %d, win %s\n", in ov772x_s_stream()
605 priv->cfmt->code, priv->win->name); in ov772x_s_stream()
607 priv->streaming = enable; in ov772x_s_stream()
610 mutex_unlock(&priv->lock); in ov772x_s_stream()
618 unsigned int fps = tpf->numerator ? in ov772x_select_fps()
619 tpf->denominator / tpf->numerator : in ov772x_select_fps()
620 tpf->denominator; in ov772x_select_fps()
629 diff = abs(fps - ov772x_frame_intervals[i]); in ov772x_select_fps()
644 unsigned long fin = clk_get_rate(priv->clk); in ov772x_set_frame_rate()
655 switch (cfmt->com7 & OFMT_MASK) { in ov772x_set_frame_rate()
657 fsize = win->sizeimage; in ov772x_set_frame_rate()
661 default: in ov772x_set_frame_rate()
662 fsize = win->sizeimage * 2; in ov772x_set_frame_rate()
671 * Fin -> [ / CLKRC_div] -> [ * PLL_mult] -> pclk in ov772x_set_frame_rate()
679 * and re-calculate the pixel clock using it: in ov772x_set_frame_rate()
701 diff = abs(pclk - t_pclk); in ov772x_set_frame_rate()
709 ret = regmap_write(priv->regmap, COM4, com4 | COM4_RESERVED); in ov772x_set_frame_rate()
713 ret = regmap_write(priv->regmap, CLKRC, clkrc | CLKRC_RESERVED); in ov772x_set_frame_rate()
725 struct v4l2_fract *tpf = &ival->interval; in ov772x_get_frame_interval()
731 if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) in ov772x_get_frame_interval()
732 return -EINVAL; in ov772x_get_frame_interval()
734 tpf->numerator = 1; in ov772x_get_frame_interval()
735 tpf->denominator = priv->fps; in ov772x_get_frame_interval()
745 struct v4l2_fract *tpf = &ival->interval; in ov772x_set_frame_interval()
753 if (ival->which != V4L2_SUBDEV_FORMAT_ACTIVE) in ov772x_set_frame_interval()
754 return -EINVAL; in ov772x_set_frame_interval()
756 mutex_lock(&priv->lock); in ov772x_set_frame_interval()
758 if (priv->streaming) { in ov772x_set_frame_interval()
759 ret = -EBUSY; in ov772x_set_frame_interval()
768 * the frame rate will be restored right after power-up. in ov772x_set_frame_interval()
770 if (priv->power_count > 0) { in ov772x_set_frame_interval()
771 ret = ov772x_set_frame_rate(priv, fps, priv->cfmt, priv->win); in ov772x_set_frame_interval()
776 tpf->numerator = 1; in ov772x_set_frame_interval()
777 tpf->denominator = fps; in ov772x_set_frame_interval()
778 priv->fps = fps; in ov772x_set_frame_interval()
781 mutex_unlock(&priv->lock); in ov772x_set_frame_interval()
788 struct ov772x_priv *priv = container_of(ctrl->handler, in ov772x_s_ctrl()
790 struct regmap *regmap = priv->regmap; in ov772x_s_ctrl()
799 * the controls will be restored right after power-up. in ov772x_s_ctrl()
801 if (priv->power_count == 0) in ov772x_s_ctrl()
804 switch (ctrl->id) { in ov772x_s_ctrl()
806 val = ctrl->val ? VFLIP_IMG : 0x00; in ov772x_s_ctrl()
807 if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP)) in ov772x_s_ctrl()
811 val = ctrl->val ? HFLIP_IMG : 0x00; in ov772x_s_ctrl()
812 if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP)) in ov772x_s_ctrl()
816 if (!ctrl->val) { in ov772x_s_ctrl()
824 val = 256 - ctrl->val; in ov772x_s_ctrl()
834 priv->test_pattern = ctrl->val; in ov772x_s_ctrl()
838 return -EINVAL; in ov772x_s_ctrl()
849 reg->size = 1; in ov772x_g_register()
850 if (reg->reg > 0xff) in ov772x_g_register()
851 return -EINVAL; in ov772x_g_register()
853 ret = regmap_read(priv->regmap, reg->reg, &val); in ov772x_g_register()
857 reg->val = (__u64)val; in ov772x_g_register()
867 if (reg->reg > 0xff || in ov772x_s_register()
868 reg->val > 0xff) in ov772x_s_register()
869 return -EINVAL; in ov772x_s_register()
871 return regmap_write(priv->regmap, reg->reg, reg->val); in ov772x_s_register()
877 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); in ov772x_power_on()
880 if (priv->clk) { in ov772x_power_on()
881 ret = clk_prepare_enable(priv->clk); in ov772x_power_on()
886 if (priv->pwdn_gpio) { in ov772x_power_on()
887 gpiod_set_value(priv->pwdn_gpio, 1); in ov772x_power_on()
893 * platforms (namely the SuperH Migo-R). Until a framework becomes in ov772x_power_on()
897 priv->rstb_gpio = gpiod_get_optional(&client->dev, "reset", in ov772x_power_on()
899 if (IS_ERR(priv->rstb_gpio)) { in ov772x_power_on()
900 dev_info(&client->dev, "Unable to get GPIO \"reset\""); in ov772x_power_on()
901 clk_disable_unprepare(priv->clk); in ov772x_power_on()
902 return PTR_ERR(priv->rstb_gpio); in ov772x_power_on()
905 if (priv->rstb_gpio) { in ov772x_power_on()
906 gpiod_set_value(priv->rstb_gpio, 1); in ov772x_power_on()
908 gpiod_set_value(priv->rstb_gpio, 0); in ov772x_power_on()
911 gpiod_put(priv->rstb_gpio); in ov772x_power_on()
919 clk_disable_unprepare(priv->clk); in ov772x_power_off()
921 if (priv->pwdn_gpio) { in ov772x_power_off()
922 gpiod_set_value(priv->pwdn_gpio, 0); in ov772x_power_off()
938 mutex_lock(&priv->lock); in ov772x_s_power()
943 if (priv->power_count == !on) { in ov772x_s_power()
951 ret = ov772x_set_params(priv, priv->cfmt, in ov772x_s_power()
952 priv->win); in ov772x_s_power()
960 priv->power_count += on ? 1 : -1; in ov772x_s_power()
961 WARN(priv->power_count < 0, "Unbalanced power count\n"); in ov772x_s_power()
962 WARN(priv->power_count > 1, "Duplicated s_power call\n"); in ov772x_s_power()
965 mutex_unlock(&priv->lock); in ov772x_s_power()
977 u32 diff = abs(width - ov772x_win_sizes[i].rect.width) in ov772x_select_win()
978 + abs(height - ov772x_win_sizes[i].rect.height); in ov772x_select_win()
998 if (mf->code == ov772x_cfmts[i].code) { in ov772x_select_params()
1005 *win = ov772x_select_win(mf->width, mf->height); in ov772x_select_params()
1010 struct regmap *regmap = priv->regmap; in ov772x_edgectrl()
1013 if (!priv->info) in ov772x_edgectrl()
1016 if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) { in ov772x_edgectrl()
1020 * Edge auto strength bit is set by default. in ov772x_edgectrl()
1030 priv->info->edgectrl.threshold); in ov772x_edgectrl()
1036 priv->info->edgectrl.strength); in ov772x_edgectrl()
1040 } else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) { in ov772x_edgectrl()
1048 priv->info->edgectrl.upper); in ov772x_edgectrl()
1054 priv->info->edgectrl.lower); in ov772x_edgectrl()
1078 ret = regmap_write(priv->regmap, HSTART, win->rect.left >> 2); in ov772x_set_params()
1081 ret = regmap_write(priv->regmap, HSIZE, win->rect.width >> 2); in ov772x_set_params()
1084 ret = regmap_write(priv->regmap, VSTART, win->rect.top >> 1); in ov772x_set_params()
1087 ret = regmap_write(priv->regmap, VSIZE, win->rect.height >> 1); in ov772x_set_params()
1090 ret = regmap_write(priv->regmap, HOUTSIZE, win->rect.width >> 2); in ov772x_set_params()
1093 ret = regmap_write(priv->regmap, VOUTSIZE, win->rect.height >> 1); in ov772x_set_params()
1096 ret = regmap_write(priv->regmap, HREF, in ov772x_set_params()
1097 ((win->rect.top & 1) << HREF_VSTART_SHIFT) | in ov772x_set_params()
1098 ((win->rect.left & 3) << HREF_HSTART_SHIFT) | in ov772x_set_params()
1099 ((win->rect.height & 1) << HREF_VSIZE_SHIFT) | in ov772x_set_params()
1100 ((win->rect.width & 3) << HREF_HSIZE_SHIFT)); in ov772x_set_params()
1103 ret = regmap_write(priv->regmap, EXHCH, in ov772x_set_params()
1104 ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) | in ov772x_set_params()
1105 ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT)); in ov772x_set_params()
1110 val = cfmt->dsp3; in ov772x_set_params()
1112 ret = regmap_update_bits(priv->regmap, DSP_CTRL3, UV_MASK, val); in ov772x_set_params()
1118 if (cfmt->dsp4) { in ov772x_set_params()
1119 ret = regmap_write(priv->regmap, DSP_CTRL4, cfmt->dsp4); in ov772x_set_params()
1125 val = cfmt->com3; in ov772x_set_params()
1126 if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP)) in ov772x_set_params()
1128 if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP)) in ov772x_set_params()
1130 if (priv->vflip_ctrl->val) in ov772x_set_params()
1132 if (priv->hflip_ctrl->val) in ov772x_set_params()
1134 if (priv->test_pattern) in ov772x_set_params()
1137 ret = regmap_update_bits(priv->regmap, COM3, SWAP_MASK | IMG_MASK, val); in ov772x_set_params()
1142 ret = regmap_write(priv->regmap, COM7, win->com7_bit | cfmt->com7); in ov772x_set_params()
1147 ret = ov772x_set_frame_rate(priv, priv->fps, cfmt, win); in ov772x_set_params()
1152 if (priv->band_filter_ctrl->val) { in ov772x_set_params()
1153 unsigned short band_filter = priv->band_filter_ctrl->val; in ov772x_set_params()
1155 ret = regmap_update_bits(priv->regmap, COM8, in ov772x_set_params()
1158 ret = regmap_update_bits(priv->regmap, BDBASE, in ov772x_set_params()
1159 0xff, 256 - band_filter); in ov772x_set_params()
1179 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) in ov772x_get_selection()
1180 return -EINVAL; in ov772x_get_selection()
1182 sel->r.left = 0; in ov772x_get_selection()
1183 sel->r.top = 0; in ov772x_get_selection()
1184 switch (sel->target) { in ov772x_get_selection()
1187 sel->r.width = priv->win->rect.width; in ov772x_get_selection()
1188 sel->r.height = priv->win->rect.height; in ov772x_get_selection()
1190 default: in ov772x_get_selection()
1191 return -EINVAL; in ov772x_get_selection()
1199 struct v4l2_mbus_framefmt *mf = &format->format; in ov772x_get_fmt()
1202 if (format->pad) in ov772x_get_fmt()
1203 return -EINVAL; in ov772x_get_fmt()
1205 mf->width = priv->win->rect.width; in ov772x_get_fmt()
1206 mf->height = priv->win->rect.height; in ov772x_get_fmt()
1207 mf->code = priv->cfmt->code; in ov772x_get_fmt()
1208 mf->colorspace = priv->cfmt->colorspace; in ov772x_get_fmt()
1209 mf->field = V4L2_FIELD_NONE; in ov772x_get_fmt()
1219 struct v4l2_mbus_framefmt *mf = &format->format; in ov772x_set_fmt()
1224 if (format->pad) in ov772x_set_fmt()
1225 return -EINVAL; in ov772x_set_fmt()
1229 mf->code = cfmt->code; in ov772x_set_fmt()
1230 mf->width = win->rect.width; in ov772x_set_fmt()
1231 mf->height = win->rect.height; in ov772x_set_fmt()
1232 mf->field = V4L2_FIELD_NONE; in ov772x_set_fmt()
1233 mf->colorspace = cfmt->colorspace; in ov772x_set_fmt()
1234 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in ov772x_set_fmt()
1235 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in ov772x_set_fmt()
1236 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in ov772x_set_fmt()
1238 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in ov772x_set_fmt()
1243 mutex_lock(&priv->lock); in ov772x_set_fmt()
1245 if (priv->streaming) { in ov772x_set_fmt()
1246 ret = -EBUSY; in ov772x_set_fmt()
1253 * the format will be restored right after power-up. in ov772x_set_fmt()
1255 if (priv->power_count > 0) { in ov772x_set_fmt()
1260 priv->win = win; in ov772x_set_fmt()
1261 priv->cfmt = cfmt; in ov772x_set_fmt()
1264 mutex_unlock(&priv->lock); in ov772x_set_fmt()
1271 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); in ov772x_video_probe()
1281 ret = regmap_read(priv->regmap, PID, &pid); in ov772x_video_probe()
1284 ret = regmap_read(priv->regmap, VER, &ver); in ov772x_video_probe()
1295 default: in ov772x_video_probe()
1296 dev_err(&client->dev, in ov772x_video_probe()
1298 ret = -ENODEV; in ov772x_video_probe()
1302 ret = regmap_read(priv->regmap, MIDH, &midh); in ov772x_video_probe()
1305 ret = regmap_read(priv->regmap, MIDL, &midl); in ov772x_video_probe()
1309 dev_info(&client->dev, in ov772x_video_probe()
1313 ret = v4l2_ctrl_handler_setup(&priv->hdl); in ov772x_video_probe()
1340 if (fie->pad || fie->index >= ARRAY_SIZE(ov772x_frame_intervals)) in ov772x_enum_frame_interval()
1341 return -EINVAL; in ov772x_enum_frame_interval()
1343 if (fie->width != VGA_WIDTH && fie->width != QVGA_WIDTH) in ov772x_enum_frame_interval()
1344 return -EINVAL; in ov772x_enum_frame_interval()
1345 if (fie->height != VGA_HEIGHT && fie->height != QVGA_HEIGHT) in ov772x_enum_frame_interval()
1346 return -EINVAL; in ov772x_enum_frame_interval()
1348 fie->interval.numerator = 1; in ov772x_enum_frame_interval()
1349 fie->interval.denominator = ov772x_frame_intervals[fie->index]; in ov772x_enum_frame_interval()
1358 if (code->pad || code->index >= ARRAY_SIZE(ov772x_cfmts)) in ov772x_enum_mbus_code()
1359 return -EINVAL; in ov772x_enum_mbus_code()
1361 code->code = ov772x_cfmts[code->index].code; in ov772x_enum_mbus_code()
1395 ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); in ov772x_parse_dt()
1397 dev_err(&client->dev, "Endpoint node not found\n"); in ov772x_parse_dt()
1398 return -EINVAL; in ov772x_parse_dt()
1403 * bus-type property was not mandatory, assume in ov772x_parse_dt()
1406 * 'bus-type' is not specified. in ov772x_parse_dt()
1417 priv->bus_type = bus_cfg.bus_type; in ov772x_parse_dt()
1440 if (!client->dev.of_node && !client->dev.platform_data) { in ov772x_probe()
1441 dev_err(&client->dev, in ov772x_probe()
1442 "Missing ov772x platform data for non-DT device\n"); in ov772x_probe()
1443 return -EINVAL; in ov772x_probe()
1446 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); in ov772x_probe()
1448 return -ENOMEM; in ov772x_probe()
1450 priv->regmap = devm_regmap_init_sccb(client, &ov772x_regmap_config); in ov772x_probe()
1451 if (IS_ERR(priv->regmap)) { in ov772x_probe()
1452 dev_err(&client->dev, "Failed to allocate register map\n"); in ov772x_probe()
1453 return PTR_ERR(priv->regmap); in ov772x_probe()
1456 priv->info = client->dev.platform_data; in ov772x_probe()
1457 mutex_init(&priv->lock); in ov772x_probe()
1459 v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); in ov772x_probe()
1460 priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in ov772x_probe()
1462 v4l2_ctrl_handler_init(&priv->hdl, 3); in ov772x_probe()
1464 priv->hdl.lock = &priv->lock; in ov772x_probe()
1465 priv->vflip_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1467 priv->hflip_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1469 priv->band_filter_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1472 v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1474 ARRAY_SIZE(ov772x_test_pattern_menu) - 1, in ov772x_probe()
1476 priv->subdev.ctrl_handler = &priv->hdl; in ov772x_probe()
1477 if (priv->hdl.error) { in ov772x_probe()
1478 ret = priv->hdl.error; in ov772x_probe()
1482 priv->clk = clk_get(&client->dev, NULL); in ov772x_probe()
1483 if (IS_ERR(priv->clk)) { in ov772x_probe()
1484 dev_err(&client->dev, "Unable to get xclk clock\n"); in ov772x_probe()
1485 ret = PTR_ERR(priv->clk); in ov772x_probe()
1489 priv->pwdn_gpio = gpiod_get_optional(&client->dev, "powerdown", in ov772x_probe()
1491 if (IS_ERR(priv->pwdn_gpio)) { in ov772x_probe()
1492 dev_info(&client->dev, "Unable to get GPIO \"powerdown\""); in ov772x_probe()
1493 ret = PTR_ERR(priv->pwdn_gpio); in ov772x_probe()
1505 priv->pad.flags = MEDIA_PAD_FL_SOURCE; in ov772x_probe()
1506 priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in ov772x_probe()
1507 ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); in ov772x_probe()
1511 priv->cfmt = &ov772x_cfmts[0]; in ov772x_probe()
1512 priv->win = &ov772x_win_sizes[0]; in ov772x_probe()
1513 priv->fps = 15; in ov772x_probe()
1515 ret = v4l2_async_register_subdev(&priv->subdev); in ov772x_probe()
1522 media_entity_cleanup(&priv->subdev.entity); in ov772x_probe()
1524 if (priv->pwdn_gpio) in ov772x_probe()
1525 gpiod_put(priv->pwdn_gpio); in ov772x_probe()
1527 clk_put(priv->clk); in ov772x_probe()
1529 v4l2_ctrl_handler_free(&priv->hdl); in ov772x_probe()
1530 mutex_destroy(&priv->lock); in ov772x_probe()
1539 media_entity_cleanup(&priv->subdev.entity); in ov772x_remove()
1540 clk_put(priv->clk); in ov772x_remove()
1541 if (priv->pwdn_gpio) in ov772x_remove()
1542 gpiod_put(priv->pwdn_gpio); in ov772x_remove()
1543 v4l2_async_unregister_subdev(&priv->subdev); in ov772x_remove()
1544 v4l2_ctrl_handler_free(&priv->hdl); in ov772x_remove()
1545 mutex_destroy(&priv->lock); in ov772x_remove()