staticint imx296_power_on(struct imx296 *sensor)
{ int ret;
ret = regulator_bulk_enable(ARRAY_SIZE(sensor->supplies),
sensor->supplies); if (ret < 0) return ret;
udelay(1);
ret = gpiod_direction_output(sensor->reset, 0); if (ret < 0) goto err_supply;
udelay(1);
ret = clk_prepare_enable(sensor->clk); if (ret < 0) goto err_reset;
/* * The documentation doesn't explicitly say how much time is required * after providing a clock and before starting I2C communication. It * mentions a delay of 20µs in 4-wire mode, but tests showed that a * delay of 100µs resulted in I2C communication failures, while 500µs * seems to be enough. Be conservative.
*/
usleep_range(1000, 2000);
/* * Horizontal blanking is controlled through the HMAX register, which * contains a line length in INCK clock units. The INCK frequency is * fixed to 74.25 MHz. The HMAX value is currently fixed to 1100, * convert it to a number of pixels based on the nominal pixel rate.
*/
hblank = 1100 * 1188000000ULL / 10 / 74250000
- IMX296_PIXEL_ARRAY_WIDTH;
sensor->hblank = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
V4L2_CID_HBLANK, hblank, hblank, 1,
hblank); if (sensor->hblank)
sensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
sensor->vblank = v4l2_ctrl_new_std(&sensor->ctrls, &imx296_ctrl_ops,
V4L2_CID_VBLANK, 30,
1048575 - IMX296_PIXEL_ARRAY_HEIGHT,
1, 30); /* * The sensor calculates the MIPI timings internally to achieve a bit * rate between 1122 and 1198 Mbps. The exact value is unfortunately not * reported, at least according to the documentation. Report a nominal * rate of 1188 Mbps as that is used by the datasheet in multiple * examples.
*/
v4l2_ctrl_new_std(&sensor->ctrls, NULL, V4L2_CID_PIXEL_RATE,
1122000000 / 10, 1198000000 / 10, 1, 1188000000 / 10);
v4l2_ctrl_new_std_menu_items(&sensor->ctrls, &imx296_ctrl_ops,
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(imx296_test_pattern_menu) - 1,
0, 0, imx296_test_pattern_menu);
/* * HMAX and VMAX configure horizontal and vertical blanking by * specifying the total line time and frame time respectively. The line * time is specified in operational clock units (which appears to be the * output of an internal PLL, fixed at 74.25 MHz regardless of the * exernal clock frequency), while the frame time is specified as a * number of lines. * * In the vertical direction the sensor outputs the following: * * - one line for the FS packet * - two lines of embedded data (DT 0x12) * - six null lines (DT 0x10) * - four lines of vertical effective optical black (DT 0x37) * - 8 to 1088 lines of active image data (RAW10, DT 0x2b) * - one line for the FE packet * - 16 or more lines of vertical blanking
*/
imx296_write(sensor, IMX296_HMAX, 1100, &ret);
imx296_write(sensor, IMX296_VMAX,
format->height + sensor->vblank->cur.val, &ret);
for (i = 0; i < ARRAY_SIZE(sensor->clk_params->incksel); ++i)
imx296_write(sensor, IMX296_INCKSEL(i),
sensor->clk_params->incksel[i], &ret);
imx296_write(sensor, IMX296_GTTABLENUM, 0xc5, &ret);
imx296_write(sensor, IMX296_CTRL418C, sensor->clk_params->ctrl418c,
&ret);
staticint imx296_s_stream(struct v4l2_subdev *sd, int enable)
{ struct imx296 *sensor = to_imx296(sd); struct v4l2_subdev_state *state; int ret;
state = v4l2_subdev_lock_and_get_active_state(sd);
if (!enable) {
ret = imx296_stream_off(sensor);
pm_runtime_put_autosuspend(sensor->dev);
goto unlock;
}
ret = pm_runtime_resume_and_get(sensor->dev); if (ret < 0) goto unlock;
ret = imx296_setup(sensor, state); if (ret < 0) goto err_pm;
ret = __v4l2_ctrl_handler_setup(&sensor->ctrls); if (ret < 0) goto err_pm;
ret = imx296_stream_on(sensor); if (ret) goto err_pm;
unlock:
v4l2_subdev_unlock_state(state);
return ret;
err_pm: /* * In case of error, turn the power off synchronously as the device * likely has no other chance to recover.
*/
pm_runtime_put_sync(sensor->dev);
crop = v4l2_subdev_state_get_crop(state, fmt->pad);
format = v4l2_subdev_state_get_format(state, fmt->pad);
/* * Binning is only allowed when cropping is disabled according to the * documentation. This should be double-checked.
*/ if (crop->width == IMX296_PIXEL_ARRAY_WIDTH &&
crop->height == IMX296_PIXEL_ARRAY_HEIGHT) { unsignedint width; unsignedint height; unsignedint hratio; unsignedint vratio;
/* Clamp the width and height to avoid dividing by zero. */
width = clamp_t(unsignedint, fmt->format.width,
crop->width / 2, crop->width);
height = clamp_t(unsignedint, fmt->format.height,
crop->height / 2, crop->height);
hratio = DIV_ROUND_CLOSEST(crop->width, width);
vratio = DIV_ROUND_CLOSEST(crop->height, height);
staticint imx296_identify_model(struct imx296 *sensor)
{ unsignedint model; int temp = 0; int ret;
model = (uintptr_t)of_device_get_match_data(sensor->dev); if (model) {
dev_dbg(sensor->dev, "sensor model auto-detection disabled, forcing 0x%04x\n",
model);
sensor->mono = model & IMX296_SENSOR_INFO_MONO; return 0;
}
/* * While most registers can be read when the sensor is in standby, this * is not the case of the sensor info register :-(
*/
ret = imx296_write(sensor, IMX296_CTRL00, 0, NULL); if (ret < 0) {
dev_err(sensor->dev, "failed to get sensor out of standby (%d)\n", ret); return ret;
}
usleep_range(2000, 5000);
ret = imx296_read(sensor, IMX296_SENSOR_INFO); if (ret < 0) {
dev_err(sensor->dev, "failed to read sensor information (%d)\n",
ret); goto done;
}
model = (ret >> 6) & 0x1ff;
switch (model) { case 296:
sensor->mono = ret & IMX296_SENSOR_INFO_MONO; break; /* * The IMX297 seems to share features with the IMX296, it may be * possible to support it in the same driver.
*/ case 297: default:
dev_err(sensor->dev, "invalid device model 0x%04x\n", ret);
ret = -ENODEV; goto done;
}
ret = imx296_read_temperature(sensor, &temp); if (ret < 0) goto done;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_warn(&adapter->dev, "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); return -EIO;
}
sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (!sensor) return -ENOMEM;
sensor->dev = &client->dev;
/* Acquire resources. */ for (i = 0; i < ARRAY_SIZE(sensor->supplies); ++i)
sensor->supplies[i].supply = imx296_supply_names[i];
ret = devm_regulator_bulk_get(sensor->dev, ARRAY_SIZE(sensor->supplies),
sensor->supplies); if (ret) {
dev_err_probe(sensor->dev, ret, "failed to get supplies\n"); return ret;
}
sensor->reset = devm_gpiod_get_optional(sensor->dev, "reset",
GPIOD_OUT_HIGH); if (IS_ERR(sensor->reset)) return dev_err_probe(sensor->dev, PTR_ERR(sensor->reset), "failed to get reset GPIO\n");
sensor->clk = devm_clk_get(sensor->dev, "inck"); if (IS_ERR(sensor->clk)) return dev_err_probe(sensor->dev, PTR_ERR(sensor->clk), "failed to get clock\n");
clk_rate = clk_get_rate(sensor->clk); for (i = 0; i < ARRAY_SIZE(imx296_clk_params); ++i) { if (clk_rate == imx296_clk_params[i].freq) {
sensor->clk_params = &imx296_clk_params[i]; break;
}
}
sensor->regmap = devm_regmap_init_i2c(client, &imx296_regmap_config); if (IS_ERR(sensor->regmap)) return PTR_ERR(sensor->regmap);
/* * Enable power management. The driver supports runtime PM, but needs to * work when runtime PM is disabled in the kernel. To that end, power * the sensor on manually here, identify it, and fully initialize it.
*/
ret = imx296_power_on(sensor); if (ret < 0) return ret;
ret = imx296_identify_model(sensor); if (ret < 0) goto err_power;
/* Initialize the V4L2 subdev. */
ret = imx296_subdev_init(sensor); if (ret < 0) goto err_power;
/* * Enable runtime PM. As the device has been powered manually, mark it * as active, and increase the usage count without resuming the device.
*/
pm_runtime_set_active(sensor->dev);
pm_runtime_get_noresume(sensor->dev);
pm_runtime_enable(sensor->dev);
/* Register the V4L2 subdev. */
ret = v4l2_async_register_subdev(&sensor->subdev); if (ret < 0) goto err_pm;
/* * Finally, enable autosuspend and decrease the usage count. The device * will get suspended after the autosuspend delay, turning the power * off.
*/
pm_runtime_set_autosuspend_delay(sensor->dev, 1000);
pm_runtime_use_autosuspend(sensor->dev);
pm_runtime_put_autosuspend(sensor->dev);
/* * Disable runtime PM. In case runtime PM is disabled in the kernel, * make sure to turn power off manually.
*/
pm_runtime_disable(sensor->dev); if (!pm_runtime_status_suspended(sensor->dev))
imx296_power_off(sensor);
pm_runtime_set_suspended(sensor->dev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.