Lines Matching +full:error +full:- +full:correction

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) */
109 #define LCC0 0x46 /* Lens correction control 0 */
110 #define LCC1 0x47 /* Lens correction option 1 - X coordinate */
111 #define LCC2 0x48 /* Lens correction option 2 - Y coordinate */
112 #define LCC3 0x49 /* Lens correction option 3 */
113 #define LCC4 0x4A /* Lens correction option 4 - radius of the circular */
114 #define LCC5 0x4B /* Lens correction option 5 */
115 #define LCC6 0x4C /* Lens correction option 6 */
117 #define LC_CTR 0x46 /* Lens correction control */
118 #define LC_XC 0x47 /* X coordinate of lens correction center relative */
119 #define LC_YC 0x48 /* Y coordinate of lens correction center relative */
120 #define LC_COEF 0x49 /* Lens correction coefficient */
121 #define LC_RADI 0x4A /* Lens correction radius */
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)
316 /* Automatic gain ceiling - maximum AGC value */
348 #define AUTO_BLK_ON_OFF 0x02 /* Black defect auto correction ON/OFF */
349 #define AUTO_WHT_ON_OFF 0x01 /* White define auto correction ON/OFF */
367 #define DENOISE_ACTRL 0x40 /* De-noise auto threshold control */
429 /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
503 /* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output,
504 * regardless of the COM7 value. We can thus only support 10-bit
567 ret = regmap_write(priv->regmap, COM7, SCCB_RESET); in ov772x_reset()
573 return regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, in ov772x_reset()
587 mutex_lock(&priv->lock); in ov772x_s_stream()
589 if (priv->streaming == enable) in ov772x_s_stream()
592 if (priv->bus_type == V4L2_MBUS_BT656) { in ov772x_s_stream()
593 ret = regmap_update_bits(priv->regmap, COM7, ITU656_ON_OFF, in ov772x_s_stream()
600 ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, in ov772x_s_stream()
606 dev_dbg(&client->dev, "format %d, win %s\n", in ov772x_s_stream()
607 priv->cfmt->code, priv->win->name); in ov772x_s_stream()
609 priv->streaming = enable; in ov772x_s_stream()
612 mutex_unlock(&priv->lock); in ov772x_s_stream()
620 unsigned int fps = tpf->numerator ? in ov772x_select_fps()
621 tpf->denominator / tpf->numerator : in ov772x_select_fps()
622 tpf->denominator; in ov772x_select_fps()
631 diff = abs(fps - ov772x_frame_intervals[i]); in ov772x_select_fps()
646 unsigned long fin = clk_get_rate(priv->clk); in ov772x_set_frame_rate()
657 switch (cfmt->com7 & OFMT_MASK) { in ov772x_set_frame_rate()
659 fsize = win->sizeimage; in ov772x_set_frame_rate()
664 fsize = win->sizeimage * 2; in ov772x_set_frame_rate()
673 * Fin -> [ / CLKRC_div] -> [ * PLL_mult] -> pclk in ov772x_set_frame_rate()
681 * and re-calculate the pixel clock using it: in ov772x_set_frame_rate()
703 diff = abs(pclk - t_pclk); in ov772x_set_frame_rate()
711 ret = regmap_write(priv->regmap, COM4, com4 | COM4_RESERVED); in ov772x_set_frame_rate()
715 ret = regmap_write(priv->regmap, CLKRC, clkrc | CLKRC_RESERVED); in ov772x_set_frame_rate()
726 struct v4l2_fract *tpf = &ival->interval; in ov772x_g_frame_interval()
728 tpf->numerator = 1; in ov772x_g_frame_interval()
729 tpf->denominator = priv->fps; in ov772x_g_frame_interval()
738 struct v4l2_fract *tpf = &ival->interval; in ov772x_s_frame_interval()
742 mutex_lock(&priv->lock); in ov772x_s_frame_interval()
744 if (priv->streaming) { in ov772x_s_frame_interval()
745 ret = -EBUSY; in ov772x_s_frame_interval()
746 goto error; in ov772x_s_frame_interval()
754 * the frame rate will be restored right after power-up. in ov772x_s_frame_interval()
756 if (priv->power_count > 0) { in ov772x_s_frame_interval()
757 ret = ov772x_set_frame_rate(priv, fps, priv->cfmt, priv->win); in ov772x_s_frame_interval()
759 goto error; in ov772x_s_frame_interval()
762 tpf->numerator = 1; in ov772x_s_frame_interval()
763 tpf->denominator = fps; in ov772x_s_frame_interval()
764 priv->fps = fps; in ov772x_s_frame_interval()
766 error: in ov772x_s_frame_interval()
767 mutex_unlock(&priv->lock); in ov772x_s_frame_interval()
774 struct ov772x_priv *priv = container_of(ctrl->handler, in ov772x_s_ctrl()
776 struct regmap *regmap = priv->regmap; in ov772x_s_ctrl()
785 * the controls will be restored right after power-up. in ov772x_s_ctrl()
787 if (priv->power_count == 0) in ov772x_s_ctrl()
790 switch (ctrl->id) { in ov772x_s_ctrl()
792 val = ctrl->val ? VFLIP_IMG : 0x00; in ov772x_s_ctrl()
793 if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP)) in ov772x_s_ctrl()
797 val = ctrl->val ? HFLIP_IMG : 0x00; in ov772x_s_ctrl()
798 if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP)) in ov772x_s_ctrl()
802 if (!ctrl->val) { in ov772x_s_ctrl()
810 val = 256 - ctrl->val; in ov772x_s_ctrl()
820 priv->test_pattern = ctrl->val; in ov772x_s_ctrl()
824 return -EINVAL; in ov772x_s_ctrl()
835 reg->size = 1; in ov772x_g_register()
836 if (reg->reg > 0xff) in ov772x_g_register()
837 return -EINVAL; in ov772x_g_register()
839 ret = regmap_read(priv->regmap, reg->reg, &val); in ov772x_g_register()
843 reg->val = (__u64)val; in ov772x_g_register()
853 if (reg->reg > 0xff || in ov772x_s_register()
854 reg->val > 0xff) in ov772x_s_register()
855 return -EINVAL; in ov772x_s_register()
857 return regmap_write(priv->regmap, reg->reg, reg->val); in ov772x_s_register()
863 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); in ov772x_power_on()
866 if (priv->clk) { in ov772x_power_on()
867 ret = clk_prepare_enable(priv->clk); in ov772x_power_on()
872 if (priv->pwdn_gpio) { in ov772x_power_on()
873 gpiod_set_value(priv->pwdn_gpio, 1); in ov772x_power_on()
879 * platforms (namely the SuperH Migo-R). Until a framework becomes in ov772x_power_on()
883 priv->rstb_gpio = gpiod_get_optional(&client->dev, "reset", in ov772x_power_on()
885 if (IS_ERR(priv->rstb_gpio)) { in ov772x_power_on()
886 dev_info(&client->dev, "Unable to get GPIO \"reset\""); in ov772x_power_on()
887 clk_disable_unprepare(priv->clk); in ov772x_power_on()
888 return PTR_ERR(priv->rstb_gpio); in ov772x_power_on()
891 if (priv->rstb_gpio) { in ov772x_power_on()
892 gpiod_set_value(priv->rstb_gpio, 1); in ov772x_power_on()
894 gpiod_set_value(priv->rstb_gpio, 0); in ov772x_power_on()
897 gpiod_put(priv->rstb_gpio); in ov772x_power_on()
905 clk_disable_unprepare(priv->clk); in ov772x_power_off()
907 if (priv->pwdn_gpio) { in ov772x_power_off()
908 gpiod_set_value(priv->pwdn_gpio, 0); in ov772x_power_off()
924 mutex_lock(&priv->lock); in ov772x_s_power()
929 if (priv->power_count == !on) { in ov772x_s_power()
937 ret = ov772x_set_params(priv, priv->cfmt, in ov772x_s_power()
938 priv->win); in ov772x_s_power()
946 priv->power_count += on ? 1 : -1; in ov772x_s_power()
947 WARN(priv->power_count < 0, "Unbalanced power count\n"); in ov772x_s_power()
948 WARN(priv->power_count > 1, "Duplicated s_power call\n"); in ov772x_s_power()
951 mutex_unlock(&priv->lock); in ov772x_s_power()
963 u32 diff = abs(width - ov772x_win_sizes[i].rect.width) in ov772x_select_win()
964 + abs(height - ov772x_win_sizes[i].rect.height); in ov772x_select_win()
984 if (mf->code == ov772x_cfmts[i].code) { in ov772x_select_params()
991 *win = ov772x_select_win(mf->width, mf->height); in ov772x_select_params()
996 struct regmap *regmap = priv->regmap; in ov772x_edgectrl()
999 if (!priv->info) in ov772x_edgectrl()
1002 if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) { in ov772x_edgectrl()
1016 priv->info->edgectrl.threshold); in ov772x_edgectrl()
1022 priv->info->edgectrl.strength); in ov772x_edgectrl()
1026 } else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) { in ov772x_edgectrl()
1034 priv->info->edgectrl.upper); in ov772x_edgectrl()
1040 priv->info->edgectrl.lower); in ov772x_edgectrl()
1064 ret = regmap_write(priv->regmap, HSTART, win->rect.left >> 2); in ov772x_set_params()
1067 ret = regmap_write(priv->regmap, HSIZE, win->rect.width >> 2); in ov772x_set_params()
1070 ret = regmap_write(priv->regmap, VSTART, win->rect.top >> 1); in ov772x_set_params()
1073 ret = regmap_write(priv->regmap, VSIZE, win->rect.height >> 1); in ov772x_set_params()
1076 ret = regmap_write(priv->regmap, HOUTSIZE, win->rect.width >> 2); in ov772x_set_params()
1079 ret = regmap_write(priv->regmap, VOUTSIZE, win->rect.height >> 1); in ov772x_set_params()
1082 ret = regmap_write(priv->regmap, HREF, in ov772x_set_params()
1083 ((win->rect.top & 1) << HREF_VSTART_SHIFT) | in ov772x_set_params()
1084 ((win->rect.left & 3) << HREF_HSTART_SHIFT) | in ov772x_set_params()
1085 ((win->rect.height & 1) << HREF_VSIZE_SHIFT) | in ov772x_set_params()
1086 ((win->rect.width & 3) << HREF_HSIZE_SHIFT)); in ov772x_set_params()
1089 ret = regmap_write(priv->regmap, EXHCH, in ov772x_set_params()
1090 ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) | in ov772x_set_params()
1091 ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT)); in ov772x_set_params()
1096 val = cfmt->dsp3; in ov772x_set_params()
1098 ret = regmap_update_bits(priv->regmap, DSP_CTRL3, UV_MASK, val); in ov772x_set_params()
1104 if (cfmt->dsp4) { in ov772x_set_params()
1105 ret = regmap_write(priv->regmap, DSP_CTRL4, cfmt->dsp4); in ov772x_set_params()
1111 val = cfmt->com3; in ov772x_set_params()
1112 if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP)) in ov772x_set_params()
1114 if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP)) in ov772x_set_params()
1116 if (priv->vflip_ctrl->val) in ov772x_set_params()
1118 if (priv->hflip_ctrl->val) in ov772x_set_params()
1120 if (priv->test_pattern) in ov772x_set_params()
1123 ret = regmap_update_bits(priv->regmap, COM3, SWAP_MASK | IMG_MASK, val); in ov772x_set_params()
1128 ret = regmap_write(priv->regmap, COM7, win->com7_bit | cfmt->com7); in ov772x_set_params()
1133 ret = ov772x_set_frame_rate(priv, priv->fps, cfmt, win); in ov772x_set_params()
1138 if (priv->band_filter_ctrl->val) { in ov772x_set_params()
1139 unsigned short band_filter = priv->band_filter_ctrl->val; in ov772x_set_params()
1141 ret = regmap_update_bits(priv->regmap, COM8, in ov772x_set_params()
1144 ret = regmap_update_bits(priv->regmap, BDBASE, in ov772x_set_params()
1145 0xff, 256 - band_filter); in ov772x_set_params()
1165 if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) in ov772x_get_selection()
1166 return -EINVAL; in ov772x_get_selection()
1168 sel->r.left = 0; in ov772x_get_selection()
1169 sel->r.top = 0; in ov772x_get_selection()
1170 switch (sel->target) { in ov772x_get_selection()
1173 sel->r.width = priv->win->rect.width; in ov772x_get_selection()
1174 sel->r.height = priv->win->rect.height; in ov772x_get_selection()
1177 return -EINVAL; in ov772x_get_selection()
1185 struct v4l2_mbus_framefmt *mf = &format->format; in ov772x_get_fmt()
1188 if (format->pad) in ov772x_get_fmt()
1189 return -EINVAL; in ov772x_get_fmt()
1191 mf->width = priv->win->rect.width; in ov772x_get_fmt()
1192 mf->height = priv->win->rect.height; in ov772x_get_fmt()
1193 mf->code = priv->cfmt->code; in ov772x_get_fmt()
1194 mf->colorspace = priv->cfmt->colorspace; in ov772x_get_fmt()
1195 mf->field = V4L2_FIELD_NONE; in ov772x_get_fmt()
1205 struct v4l2_mbus_framefmt *mf = &format->format; in ov772x_set_fmt()
1210 if (format->pad) in ov772x_set_fmt()
1211 return -EINVAL; in ov772x_set_fmt()
1215 mf->code = cfmt->code; in ov772x_set_fmt()
1216 mf->width = win->rect.width; in ov772x_set_fmt()
1217 mf->height = win->rect.height; in ov772x_set_fmt()
1218 mf->field = V4L2_FIELD_NONE; in ov772x_set_fmt()
1219 mf->colorspace = cfmt->colorspace; in ov772x_set_fmt()
1220 mf->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; in ov772x_set_fmt()
1221 mf->quantization = V4L2_QUANTIZATION_DEFAULT; in ov772x_set_fmt()
1222 mf->xfer_func = V4L2_XFER_FUNC_DEFAULT; in ov772x_set_fmt()
1224 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in ov772x_set_fmt()
1225 sd_state->pads->try_fmt = *mf; in ov772x_set_fmt()
1229 mutex_lock(&priv->lock); in ov772x_set_fmt()
1231 if (priv->streaming) { in ov772x_set_fmt()
1232 ret = -EBUSY; in ov772x_set_fmt()
1233 goto error; in ov772x_set_fmt()
1239 * the format will be restored right after power-up. in ov772x_set_fmt()
1241 if (priv->power_count > 0) { in ov772x_set_fmt()
1244 goto error; in ov772x_set_fmt()
1246 priv->win = win; in ov772x_set_fmt()
1247 priv->cfmt = cfmt; in ov772x_set_fmt()
1249 error: in ov772x_set_fmt()
1250 mutex_unlock(&priv->lock); in ov772x_set_fmt()
1257 struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); in ov772x_video_probe()
1267 ret = regmap_read(priv->regmap, PID, &pid); in ov772x_video_probe()
1270 ret = regmap_read(priv->regmap, VER, &ver); in ov772x_video_probe()
1282 dev_err(&client->dev, in ov772x_video_probe()
1283 "Product ID error %x:%x\n", pid, ver); in ov772x_video_probe()
1284 ret = -ENODEV; in ov772x_video_probe()
1288 ret = regmap_read(priv->regmap, MIDH, &midh); in ov772x_video_probe()
1291 ret = regmap_read(priv->regmap, MIDL, &midl); in ov772x_video_probe()
1295 dev_info(&client->dev, in ov772x_video_probe()
1299 ret = v4l2_ctrl_handler_setup(&priv->hdl); in ov772x_video_probe()
1326 if (fie->pad || fie->index >= ARRAY_SIZE(ov772x_frame_intervals)) in ov772x_enum_frame_interval()
1327 return -EINVAL; in ov772x_enum_frame_interval()
1329 if (fie->width != VGA_WIDTH && fie->width != QVGA_WIDTH) in ov772x_enum_frame_interval()
1330 return -EINVAL; in ov772x_enum_frame_interval()
1331 if (fie->height != VGA_HEIGHT && fie->height != QVGA_HEIGHT) in ov772x_enum_frame_interval()
1332 return -EINVAL; in ov772x_enum_frame_interval()
1334 fie->interval.numerator = 1; in ov772x_enum_frame_interval()
1335 fie->interval.denominator = ov772x_frame_intervals[fie->index]; in ov772x_enum_frame_interval()
1344 if (code->pad || code->index >= ARRAY_SIZE(ov772x_cfmts)) in ov772x_enum_mbus_code()
1345 return -EINVAL; in ov772x_enum_mbus_code()
1347 code->code = ov772x_cfmts[code->index].code; in ov772x_enum_mbus_code()
1381 ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL); in ov772x_parse_dt()
1383 dev_err(&client->dev, "Endpoint node not found\n"); in ov772x_parse_dt()
1384 return -EINVAL; in ov772x_parse_dt()
1389 * bus-type property was not mandatory, assume in ov772x_parse_dt()
1392 * 'bus-type' is not specified. in ov772x_parse_dt()
1403 priv->bus_type = bus_cfg.bus_type; in ov772x_parse_dt()
1426 if (!client->dev.of_node && !client->dev.platform_data) { in ov772x_probe()
1427 dev_err(&client->dev, in ov772x_probe()
1428 "Missing ov772x platform data for non-DT device\n"); in ov772x_probe()
1429 return -EINVAL; in ov772x_probe()
1432 priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); in ov772x_probe()
1434 return -ENOMEM; in ov772x_probe()
1436 priv->regmap = devm_regmap_init_sccb(client, &ov772x_regmap_config); in ov772x_probe()
1437 if (IS_ERR(priv->regmap)) { in ov772x_probe()
1438 dev_err(&client->dev, "Failed to allocate register map\n"); in ov772x_probe()
1439 return PTR_ERR(priv->regmap); in ov772x_probe()
1442 priv->info = client->dev.platform_data; in ov772x_probe()
1443 mutex_init(&priv->lock); in ov772x_probe()
1445 v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops); in ov772x_probe()
1446 priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | in ov772x_probe()
1448 v4l2_ctrl_handler_init(&priv->hdl, 3); in ov772x_probe()
1450 priv->hdl.lock = &priv->lock; in ov772x_probe()
1451 priv->vflip_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1453 priv->hflip_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1455 priv->band_filter_ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1458 v4l2_ctrl_new_std_menu_items(&priv->hdl, &ov772x_ctrl_ops, in ov772x_probe()
1460 ARRAY_SIZE(ov772x_test_pattern_menu) - 1, in ov772x_probe()
1462 priv->subdev.ctrl_handler = &priv->hdl; in ov772x_probe()
1463 if (priv->hdl.error) { in ov772x_probe()
1464 ret = priv->hdl.error; in ov772x_probe()
1468 priv->clk = clk_get(&client->dev, NULL); in ov772x_probe()
1469 if (IS_ERR(priv->clk)) { in ov772x_probe()
1470 dev_err(&client->dev, "Unable to get xclk clock\n"); in ov772x_probe()
1471 ret = PTR_ERR(priv->clk); in ov772x_probe()
1475 priv->pwdn_gpio = gpiod_get_optional(&client->dev, "powerdown", in ov772x_probe()
1477 if (IS_ERR(priv->pwdn_gpio)) { in ov772x_probe()
1478 dev_info(&client->dev, "Unable to get GPIO \"powerdown\""); in ov772x_probe()
1479 ret = PTR_ERR(priv->pwdn_gpio); in ov772x_probe()
1492 priv->pad.flags = MEDIA_PAD_FL_SOURCE; in ov772x_probe()
1493 priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR; in ov772x_probe()
1494 ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad); in ov772x_probe()
1499 priv->cfmt = &ov772x_cfmts[0]; in ov772x_probe()
1500 priv->win = &ov772x_win_sizes[0]; in ov772x_probe()
1501 priv->fps = 15; in ov772x_probe()
1503 ret = v4l2_async_register_subdev(&priv->subdev); in ov772x_probe()
1510 media_entity_cleanup(&priv->subdev.entity); in ov772x_probe()
1512 if (priv->pwdn_gpio) in ov772x_probe()
1513 gpiod_put(priv->pwdn_gpio); in ov772x_probe()
1515 clk_put(priv->clk); in ov772x_probe()
1517 v4l2_ctrl_handler_free(&priv->hdl); in ov772x_probe()
1518 mutex_destroy(&priv->lock); in ov772x_probe()
1527 media_entity_cleanup(&priv->subdev.entity); in ov772x_remove()
1528 clk_put(priv->clk); in ov772x_remove()
1529 if (priv->pwdn_gpio) in ov772x_remove()
1530 gpiod_put(priv->pwdn_gpio); in ov772x_remove()
1531 v4l2_async_unregister_subdev(&priv->subdev); in ov772x_remove()
1532 v4l2_ctrl_handler_free(&priv->hdl); in ov772x_remove()
1533 mutex_destroy(&priv->lock); in ov772x_remove()