Lines Matching +full:hb +full:- +full:pll +full:- +full:clock
1 // SPDX-License-Identifier: GPL-2.0-only
9 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-fwnode.h>
24 #include <media/v4l2-mediabus.h>
25 #include <media/v4l2-image-sizes.h>
29 MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
34 MODULE_PARM_DESC(debug, "Debug level (0-1)");
67 #define CLK_EXT 0x40 /* Use external clock directly */
68 #define CLK_SCALE 0x3f /* Mask for internal clock scale */
76 #define COM7_RGB 0x04 /* bits 0 and 2 - RGB format */
87 #define REG_COM9 0x14 /* Control 9 - gain ceiling */
92 #define COM10_VS_LEAD 0x04 /* VSYNC on clock leading edge */
113 #define TSLB_YLAST 0x04 /* UYVY or VYUY - see com13 */
125 #define COM13_UVSWAP 0x01 /* V before U - w/TSLB */
127 #define COM14_DCWEN 0x10 /* DCW/PCLK-scale enable */
138 #define COM17_AECWIN 0xc0 /* AEC window - must match COM4 */
145 * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
147 * They are nine-bit signed quantities, with the sign bit
148 * stored in 0x58. Sign for v-red is bit 0, and up from there.
160 #define REG_DBLV 0x6b /* PLL control an debugging */
161 #define DBLV_BYPASS 0x0a /* Bypass PLL */
162 #define DBLV_X4 0x4a /* clock x4 */
163 #define DBLV_X6 0x8a /* clock x6 */
164 #define DBLV_X8 0xca /* clock x8 */
250 int clock_speed; /* External clock speed (MHz) */
251 u8 clkrc; /* Clock divider value */
265 return &container_of(ctrl->handler, struct ov7670_info, hdl)->sd; in to_sd()
272 * is really no making sense of most of these - lots of "reserved" values
286 * Clock scale: 3 = 15fps
290 { REG_CLKRC, 0x1 }, /* OV: clock scale (30 fps) */
295 * make sense - hstop is less than hstart. But they work...
384 /* Extra-weird stuff. Some sort of multiplexor register */
471 * Low-level register I/O.
518 msg.addr = client->addr; in ov7670_read_i2c()
522 ret = i2c_transfer(client->adapter, &msg, 1); in ov7670_read_i2c()
531 ret = i2c_transfer(client->adapter, &msg, 1); in ov7670_read_i2c()
548 msg.addr = client->addr; in ov7670_write_i2c()
552 ret = i2c_transfer(client->adapter, &msg, 1); in ov7670_write_i2c()
565 if (info->use_smbus) in ov7670_read()
576 if (info->use_smbus) in ov7670_write()
600 while (vals->reg_num != 0xff || vals->value != 0xff) { in ov7670_write_array()
601 int ret = ov7670_write(sd, vals->reg_num, vals->value); in ov7670_write_array()
639 return -ENODEV; in ov7670_detect()
644 return -ENODEV; in ov7670_detect()
652 return -ENODEV; in ov7670_detect()
657 return -ENODEV; in ov7670_detect()
677 .cmatrix = { 128, -128, 0, -34, -94, 128 },
683 .cmatrix = { 179, -179, 0, -61, -176, 228 },
689 .cmatrix = { 179, -179, 0, -61, -176, 228 },
706 * QCIF mode is done (by OV) in a very strange way - it actually looks like
707 * VGA with weird scaling options - they do *not* use the canned QCIF mode
799 u32 clkrc = info->clkrc; in ov7675_get_framerate()
802 if (info->pll_bypass) in ov7675_get_framerate()
808 if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8) in ov7675_get_framerate()
811 tpf->numerator = 1; in ov7675_get_framerate()
812 tpf->denominator = (5 * pll_factor * info->clock_speed) / in ov7675_get_framerate()
821 ret = ov7670_write(sd, REG_CLKRC, info->clkrc); in ov7675_apply_framerate()
826 info->pll_bypass ? DBLV_BYPASS : DBLV_X4); in ov7675_apply_framerate()
843 if (tpf->numerator == 0 || tpf->denominator == 0) { in ov7675_set_framerate()
846 pll_factor = info->pll_bypass ? 1 : PLL_FACTOR; in ov7675_set_framerate()
847 clkrc = (5 * pll_factor * info->clock_speed * tpf->numerator) / in ov7675_set_framerate()
848 (4 * tpf->denominator); in ov7675_set_framerate()
849 if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8) in ov7675_set_framerate()
851 clkrc--; in ov7675_set_framerate()
855 * The datasheet claims that clkrc = 0 will divide the input clock by 1 in ov7675_set_framerate()
863 info->clkrc = clkrc; in ov7675_set_framerate()
871 * the framerate will be restored right after power-up. in ov7675_set_framerate()
873 if (info->on) in ov7675_set_framerate()
884 tpf->numerator = 1; in ov7670_get_framerate_legacy()
885 tpf->denominator = info->clock_speed; in ov7670_get_framerate_legacy()
886 if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1) in ov7670_get_framerate_legacy()
887 tpf->denominator /= (info->clkrc & CLK_SCALE); in ov7670_get_framerate_legacy()
896 if (tpf->numerator == 0 || tpf->denominator == 0) in ov7670_set_framerate_legacy()
899 div = (tpf->numerator * info->clock_speed) / tpf->denominator; in ov7670_set_framerate_legacy()
904 info->clkrc = (info->clkrc & 0x80) | div; in ov7670_set_framerate_legacy()
905 tpf->numerator = 1; in ov7670_set_framerate_legacy()
906 tpf->denominator = info->clock_speed / div; in ov7670_set_framerate_legacy()
911 * the framerate will be restored right after power-up. in ov7670_set_framerate_legacy()
913 if (info->on) in ov7670_set_framerate_legacy()
914 return ov7670_write(sd, REG_CLKRC, info->clkrc); in ov7670_set_framerate_legacy()
966 if (code->pad || code->index >= N_OV7670_FMTS) in ov7670_enum_mbus_code()
967 return -EINVAL; in ov7670_enum_mbus_code()
969 code->code = ov7670_formats[code->index].mbus_code; in ov7670_enum_mbus_code()
981 unsigned int n_win_sizes = info->devtype->n_win_sizes; in ov7670_try_fmt_internal()
985 if (ov7670_formats[index].mbus_code == fmt->code) in ov7670_try_fmt_internal()
990 fmt->code = ov7670_formats[0].mbus_code; in ov7670_try_fmt_internal()
997 fmt->field = V4L2_FIELD_NONE; in ov7670_try_fmt_internal()
1003 if (info->min_width || info->min_height) in ov7670_try_fmt_internal()
1005 wsize = info->devtype->win_sizes + i; in ov7670_try_fmt_internal()
1007 if (wsize->width < info->min_width || in ov7670_try_fmt_internal()
1008 wsize->height < info->min_height) { in ov7670_try_fmt_internal()
1017 for (wsize = info->devtype->win_sizes; in ov7670_try_fmt_internal()
1018 wsize < info->devtype->win_sizes + win_sizes_limit; wsize++) in ov7670_try_fmt_internal()
1019 if (fmt->width >= wsize->width && fmt->height >= wsize->height) in ov7670_try_fmt_internal()
1021 if (wsize >= info->devtype->win_sizes + win_sizes_limit) in ov7670_try_fmt_internal()
1022 wsize--; /* Take the smallest one */ in ov7670_try_fmt_internal()
1028 fmt->width = wsize->width; in ov7670_try_fmt_internal()
1029 fmt->height = wsize->height; in ov7670_try_fmt_internal()
1030 fmt->colorspace = ov7670_formats[index].colorspace; in ov7670_try_fmt_internal()
1032 info->format = *fmt; in ov7670_try_fmt_internal()
1040 struct ov7670_win_size *wsize = info->wsize; in ov7670_apply_fmt()
1047 * to set it absolutely here, as long as the format-specific in ov7670_apply_fmt()
1050 com7 = info->fmt->regs[0].value; in ov7670_apply_fmt()
1051 com7 |= wsize->com7_bit; in ov7670_apply_fmt()
1059 if (info->mbus_config & V4L2_MBUS_VSYNC_ACTIVE_LOW) in ov7670_apply_fmt()
1061 if (info->mbus_config & V4L2_MBUS_HSYNC_ACTIVE_LOW) in ov7670_apply_fmt()
1063 if (info->pclk_hb_disable) in ov7670_apply_fmt()
1072 ret = ov7670_write_array(sd, info->fmt->regs + 1); in ov7670_apply_fmt()
1076 ret = ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart, in ov7670_apply_fmt()
1077 wsize->vstop); in ov7670_apply_fmt()
1081 if (wsize->regs) { in ov7670_apply_fmt()
1082 ret = ov7670_write_array(sd, wsize->regs); in ov7670_apply_fmt()
1097 ret = ov7670_write(sd, REG_CLKRC, info->clkrc); in ov7670_apply_fmt()
1117 if (format->pad) in ov7670_set_fmt()
1118 return -EINVAL; in ov7670_set_fmt()
1120 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in ov7670_set_fmt()
1121 ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL); in ov7670_set_fmt()
1126 format->pad); in ov7670_set_fmt()
1127 *mbus_fmt = format->format; in ov7670_set_fmt()
1132 ret = ov7670_try_fmt_internal(sd, &format->format, &info->fmt, &info->wsize); in ov7670_set_fmt()
1139 * the frame format will be restored right after power-up. in ov7670_set_fmt()
1141 if (info->on) in ov7670_set_fmt()
1156 if (format->which == V4L2_SUBDEV_FORMAT_TRY) { in ov7670_get_fmt()
1159 format->format = *mbus_fmt; in ov7670_get_fmt()
1162 return -EINVAL; in ov7670_get_fmt()
1165 format->format = info->format; in ov7670_get_fmt()
1181 info->devtype->get_framerate(sd, &ival->interval); in ov7670_g_frame_interval()
1189 struct v4l2_fract *tpf = &ival->interval; in ov7670_s_frame_interval()
1193 return info->devtype->set_framerate(sd, tpf); in ov7670_s_frame_interval()
1198 * Frame intervals. Since frame rates are controlled with the clock
1210 unsigned int n_win_sizes = info->devtype->n_win_sizes; in ov7670_enum_frame_interval()
1213 if (fie->pad) in ov7670_enum_frame_interval()
1214 return -EINVAL; in ov7670_enum_frame_interval()
1215 if (fie->index >= ARRAY_SIZE(ov7670_frame_rates)) in ov7670_enum_frame_interval()
1216 return -EINVAL; in ov7670_enum_frame_interval()
1225 struct ov7670_win_size *win = &info->devtype->win_sizes[i]; in ov7670_enum_frame_interval()
1227 if (info->min_width && win->width < info->min_width) in ov7670_enum_frame_interval()
1229 if (info->min_height && win->height < info->min_height) in ov7670_enum_frame_interval()
1231 if (fie->width == win->width && fie->height == win->height) in ov7670_enum_frame_interval()
1235 return -EINVAL; in ov7670_enum_frame_interval()
1236 fie->interval.numerator = 1; in ov7670_enum_frame_interval()
1237 fie->interval.denominator = ov7670_frame_rates[fie->index]; in ov7670_enum_frame_interval()
1250 int num_valid = -1; in ov7670_enum_frame_size()
1251 __u32 index = fse->index; in ov7670_enum_frame_size()
1252 unsigned int n_win_sizes = info->devtype->n_win_sizes; in ov7670_enum_frame_size()
1254 if (fse->pad) in ov7670_enum_frame_size()
1255 return -EINVAL; in ov7670_enum_frame_size()
1262 struct ov7670_win_size *win = &info->devtype->win_sizes[i]; in ov7670_enum_frame_size()
1264 if (info->min_width && win->width < info->min_width) in ov7670_enum_frame_size()
1266 if (info->min_height && win->height < info->min_height) in ov7670_enum_frame_size()
1269 fse->min_width = fse->max_width = win->width; in ov7670_enum_frame_size()
1270 fse->min_height = fse->max_height = win->height; in ov7670_enum_frame_size()
1275 return -EINVAL; in ov7670_enum_frame_size()
1300 if (matrix[i] < -255) in ov7670_store_cmatrix()
1303 raw = (-1 * matrix[i]) & 0xff; in ov7670_store_cmatrix()
1321 * So here is a simple table of sine values, 0-90 degrees, in steps
1325 * carefully limited to -180 <= theta <= 180.
1341 theta = -theta; in ov7670_sine()
1342 chs = -1; in ov7670_sine()
1347 theta -= 90; in ov7670_sine()
1348 sine = 1000 - ov7670_sin_table[theta/SIN_STEP]; in ov7670_sine()
1355 theta = 90 - theta; in ov7670_cosine()
1357 theta -= 360; in ov7670_cosine()
1358 else if (theta < -180) in ov7670_cosine()
1374 matrix[i] = (info->fmt->cmatrix[i] * sat) >> 7; in ov7670_calc_cmatrix()
1388 matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000; in ov7670_calc_cmatrix()
1389 matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000; in ov7670_calc_cmatrix()
1390 matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000; in ov7670_calc_cmatrix()
1414 return (128 - v) | 0x80; in ov7670_abs_to_sm()
1563 "8-bar color bar",
1585 switch (ctrl->id) { in ov7670_g_volatile_ctrl()
1587 return ov7670_g_gain(sd, &info->gain->val); in ov7670_g_volatile_ctrl()
1589 return -EINVAL; in ov7670_g_volatile_ctrl()
1597 switch (ctrl->id) { in ov7670_s_ctrl()
1599 return ov7670_s_brightness(sd, ctrl->val); in ov7670_s_ctrl()
1601 return ov7670_s_contrast(sd, ctrl->val); in ov7670_s_ctrl()
1604 info->saturation->val, info->hue->val); in ov7670_s_ctrl()
1606 return ov7670_s_vflip(sd, ctrl->val); in ov7670_s_ctrl()
1608 return ov7670_s_hflip(sd, ctrl->val); in ov7670_s_ctrl()
1612 if (!ctrl->val) { in ov7670_s_ctrl()
1614 return ov7670_s_gain(sd, info->gain->val); in ov7670_s_ctrl()
1616 return ov7670_s_autogain(sd, ctrl->val); in ov7670_s_ctrl()
1620 if (ctrl->val == V4L2_EXPOSURE_MANUAL) { in ov7670_s_ctrl()
1622 return ov7670_s_exp(sd, info->exposure->val); in ov7670_s_ctrl()
1624 return ov7670_s_autoexp(sd, ctrl->val); in ov7670_s_ctrl()
1626 return ov7670_s_test_pattern(sd, ctrl->val); in ov7670_s_ctrl()
1628 return -EINVAL; in ov7670_s_ctrl()
1642 ret = ov7670_read(sd, reg->reg & 0xff, &val); in ov7670_g_register()
1643 reg->val = val; in ov7670_g_register()
1644 reg->size = 1; in ov7670_g_register()
1650 ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); in ov7670_s_register()
1659 if (info->on) in ov7670_power_on()
1662 clk_prepare_enable(info->clk); in ov7670_power_on()
1664 if (info->pwdn_gpio) in ov7670_power_on()
1665 gpiod_set_value(info->pwdn_gpio, 0); in ov7670_power_on()
1666 if (info->resetb_gpio) { in ov7670_power_on()
1667 gpiod_set_value(info->resetb_gpio, 1); in ov7670_power_on()
1669 gpiod_set_value(info->resetb_gpio, 0); in ov7670_power_on()
1671 if (info->pwdn_gpio || info->resetb_gpio || info->clk) in ov7670_power_on()
1674 info->on = true; in ov7670_power_on()
1681 if (!info->on) in ov7670_power_off()
1684 clk_disable_unprepare(info->clk); in ov7670_power_off()
1686 if (info->pwdn_gpio) in ov7670_power_off()
1687 gpiod_set_value(info->pwdn_gpio, 1); in ov7670_power_off()
1689 info->on = false; in ov7670_power_off()
1696 if (info->on == on) in ov7670_s_power()
1704 v4l2_ctrl_handler_setup(&info->hdl); in ov7670_s_power()
1717 format->width = info->devtype->win_sizes[0].width; in ov7670_get_default_format()
1718 format->height = info->devtype->win_sizes[0].height; in ov7670_get_default_format()
1719 format->colorspace = info->fmt->colorspace; in ov7670_get_default_format()
1720 format->code = info->fmt->mbus_code; in ov7670_get_default_format()
1721 format->field = V4L2_FIELD_NONE; in ov7670_get_default_format()
1728 v4l2_subdev_get_try_format(sd, fh->state, 0); in ov7670_open()
1736 /* ----------------------------------------------------------------------- */
1776 /* ----------------------------------------------------------------------- */
1795 info->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown", in ov7670_init_gpio()
1797 if (IS_ERR(info->pwdn_gpio)) { in ov7670_init_gpio()
1798 dev_info(&client->dev, "can't get %s GPIO\n", "powerdown"); in ov7670_init_gpio()
1799 return PTR_ERR(info->pwdn_gpio); in ov7670_init_gpio()
1802 info->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset", in ov7670_init_gpio()
1804 if (IS_ERR(info->resetb_gpio)) { in ov7670_init_gpio()
1805 dev_info(&client->dev, "can't get %s GPIO\n", "reset"); in ov7670_init_gpio()
1806 return PTR_ERR(info->resetb_gpio); in ov7670_init_gpio()
1815 * ov7670_parse_dt() - Parse device tree to collect mbus configuration
1827 return -EINVAL; in ov7670_parse_dt()
1829 info->pclk_hb_disable = false; in ov7670_parse_dt()
1830 if (fwnode_property_present(fwnode, "ov7670,pclk-hb-disable")) in ov7670_parse_dt()
1831 info->pclk_hb_disable = true; in ov7670_parse_dt()
1835 return -EINVAL; in ov7670_parse_dt()
1846 info->mbus_config = bus_cfg.bus.parallel.flags; in ov7670_parse_dt()
1859 info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); in ov7670_probe()
1861 return -ENOMEM; in ov7670_probe()
1862 sd = &info->sd; in ov7670_probe()
1866 sd->internal_ops = &ov7670_subdev_internal_ops; in ov7670_probe()
1867 sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; in ov7670_probe()
1870 info->clock_speed = 30; /* default: a guess */ in ov7670_probe()
1872 if (dev_fwnode(&client->dev)) { in ov7670_probe()
1873 ret = ov7670_parse_dt(&client->dev, info); in ov7670_probe()
1877 } else if (client->dev.platform_data) { in ov7670_probe()
1878 struct ov7670_config *config = client->dev.platform_data; in ov7670_probe()
1884 info->min_width = config->min_width; in ov7670_probe()
1885 info->min_height = config->min_height; in ov7670_probe()
1886 info->use_smbus = config->use_smbus; in ov7670_probe()
1888 if (config->clock_speed) in ov7670_probe()
1889 info->clock_speed = config->clock_speed; in ov7670_probe()
1891 if (config->pll_bypass) in ov7670_probe()
1892 info->pll_bypass = true; in ov7670_probe()
1894 if (config->pclk_hb_disable) in ov7670_probe()
1895 info->pclk_hb_disable = true; in ov7670_probe()
1898 info->clk = devm_clk_get(&client->dev, "xclk"); /* optional */ in ov7670_probe()
1899 if (IS_ERR(info->clk)) { in ov7670_probe()
1900 ret = PTR_ERR(info->clk); in ov7670_probe()
1901 if (ret == -ENOENT) in ov7670_probe()
1902 info->clk = NULL; in ov7670_probe()
1913 if (info->clk) { in ov7670_probe()
1914 info->clock_speed = clk_get_rate(info->clk) / 1000000; in ov7670_probe()
1915 if (info->clock_speed < 10 || info->clock_speed > 48) { in ov7670_probe()
1916 ret = -EINVAL; in ov7670_probe()
1926 client->addr << 1, client->adapter->name); in ov7670_probe()
1930 client->addr << 1, client->adapter->name); in ov7670_probe()
1932 info->devtype = &ov7670_devdata[id->driver_data]; in ov7670_probe()
1933 info->fmt = &ov7670_formats[0]; in ov7670_probe()
1934 info->wsize = &info->devtype->win_sizes[0]; in ov7670_probe()
1936 ov7670_get_default_format(sd, &info->format); in ov7670_probe()
1938 info->clkrc = 0; in ov7670_probe()
1943 info->devtype->set_framerate(sd, &tpf); in ov7670_probe()
1945 v4l2_ctrl_handler_init(&info->hdl, 10); in ov7670_probe()
1946 v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1948 v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1950 v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1952 v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1954 info->saturation = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1956 info->hue = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1957 V4L2_CID_HUE, -180, 180, 5, 0); in ov7670_probe()
1958 info->gain = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1960 info->auto_gain = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1962 info->exposure = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1964 info->auto_exposure = v4l2_ctrl_new_std_menu(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1967 v4l2_ctrl_new_std_menu_items(&info->hdl, &ov7670_ctrl_ops, in ov7670_probe()
1969 ARRAY_SIZE(ov7670_test_pattern_menu) - 1, 0, 0, in ov7670_probe()
1971 sd->ctrl_handler = &info->hdl; in ov7670_probe()
1972 if (info->hdl.error) { in ov7670_probe()
1973 ret = info->hdl.error; in ov7670_probe()
1981 v4l2_ctrl_auto_cluster(2, &info->auto_gain, 0, true); in ov7670_probe()
1982 v4l2_ctrl_auto_cluster(2, &info->auto_exposure, in ov7670_probe()
1984 v4l2_ctrl_cluster(2, &info->saturation); in ov7670_probe()
1987 info->pad.flags = MEDIA_PAD_FL_SOURCE; in ov7670_probe()
1988 info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; in ov7670_probe()
1989 ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad); in ov7670_probe()
1994 v4l2_ctrl_handler_setup(&info->hdl); in ov7670_probe()
1996 ret = v4l2_async_register_subdev(&info->sd); in ov7670_probe()
2004 media_entity_cleanup(&info->sd.entity); in ov7670_probe()
2006 v4l2_ctrl_handler_free(&info->hdl); in ov7670_probe()
2018 v4l2_ctrl_handler_free(&info->hdl); in ov7670_remove()
2019 media_entity_cleanup(&info->sd.entity); in ov7670_remove()