From 77077ade56f3fc0a00fa2a9332f305d06c1d0f1f Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 22 May 2022 14:31:08 +0200 Subject: [PATCH 333/391] media: i2c: ov8858: Port BSP driver to 5.18 and improve DT bindings - drop power-gpios - use optional gpio instead of error checks everywhere - assume positive meaning for gpios with inversion handled in DT - don't touch default pinctrl setup - simplify powerup Signed-off-by: Ondrej Jirman --- drivers/media/i2c/ov8858.c | 132 ++++++++++++++----------------------- 1 file changed, 50 insertions(+), 82 deletions(-) diff --git a/drivers/media/i2c/ov8858.c b/drivers/media/i2c/ov8858.c index 11f01e30b..69ec1efef 100644 --- a/drivers/media/i2c/ov8858.c +++ b/drivers/media/i2c/ov8858.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include "rk-camera-module.h" #include #include @@ -34,8 +34,6 @@ #include #include -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) - #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN #endif @@ -158,7 +156,6 @@ struct ov8858_mode { struct ov8858 { struct i2c_client *client; struct clk *xvclk; - struct gpio_desc *power_gpio; struct gpio_desc *reset_gpio; struct gpio_desc *pwdn_gpio; struct regulator_bulk_data supplies[OV8858_NUM_SUPPLIES]; @@ -1488,7 +1485,7 @@ ov8858_find_best_fit(struct ov8858 *ov8858, } static int ov8858_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *fmt) { struct ov8858 *ov8858 = to_ov8858(sd); @@ -1504,7 +1501,7 @@ static int ov8858_set_fmt(struct v4l2_subdev *sd, fmt->format.field = V4L2_FIELD_NONE; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API - *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; + *v4l2_subdev_get_try_format(sd, state, fmt->pad) = fmt->format; #else mutex_unlock(&ov8858->mutex); return -ENOTTY; @@ -1526,7 +1523,7 @@ static int ov8858_set_fmt(struct v4l2_subdev *sd, } static int ov8858_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_format *fmt) { struct ov8858 *ov8858 = to_ov8858(sd); @@ -1535,7 +1532,7 @@ static int ov8858_get_fmt(struct v4l2_subdev *sd, mutex_lock(&ov8858->mutex); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API - fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + fmt->format = *v4l2_subdev_get_try_format(sd, state, fmt->pad); #else mutex_unlock(&ov8858->mutex); return -ENOTTY; @@ -1552,7 +1549,7 @@ static int ov8858_get_fmt(struct v4l2_subdev *sd, } static int ov8858_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { if (code->index != 0) @@ -1563,7 +1560,7 @@ static int ov8858_enum_mbus_code(struct v4l2_subdev *sd, } static int ov8858_enum_frame_sizes(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse) { struct ov8858 *ov8858 = to_ov8858(sd); @@ -2137,11 +2134,6 @@ static int __ov8858_power_on(struct ov8858 *ov8858) u32 delay_us; struct device *dev = &ov8858->client->dev; - if (!IS_ERR(ov8858->power_gpio)) - gpiod_set_value_cansleep(ov8858->power_gpio, 1); - - usleep_range(1000, 2000); - if (!IS_ERR_OR_NULL(ov8858->pins_default)) { ret = pinctrl_select_state(ov8858->pinctrl, ov8858->pins_default); @@ -2154,31 +2146,28 @@ static int __ov8858_power_on(struct ov8858 *ov8858) dev_warn(dev, "Failed to set xvclk rate (24MHz)\n"); if (clk_get_rate(ov8858->xvclk) != OV8858_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n"); + ret = clk_prepare_enable(ov8858->xvclk); if (ret < 0) { dev_err(dev, "Failed to enable xvclk\n"); return ret; } - if (!IS_ERR(ov8858->reset_gpio)) - gpiod_set_value_cansleep(ov8858->reset_gpio, 0); - ret = regulator_bulk_enable(OV8858_NUM_SUPPLIES, ov8858->supplies); if (ret < 0) { dev_err(dev, "Failed to enable regulators\n"); goto disable_clk; } - if (!IS_ERR(ov8858->reset_gpio)) - gpiod_set_value_cansleep(ov8858->reset_gpio, 1); + mdelay(20); - usleep_range(1000, 2000); - if (!IS_ERR(ov8858->pwdn_gpio)) - gpiod_set_value_cansleep(ov8858->pwdn_gpio, 1); + gpiod_set_value_cansleep(ov8858->reset_gpio, 0); + gpiod_set_value_cansleep(ov8858->pwdn_gpio, 0); /* 8192 cycles prior to first SCCB transaction */ - delay_us = ov8858_cal_delay(8192); - usleep_range(delay_us, delay_us * 2); + //delay_us = ov8858_cal_delay(8192); + //usleep_range(delay_us, delay_us * 2); + mdelay(10); return 0; @@ -2193,11 +2182,10 @@ static void __ov8858_power_off(struct ov8858 *ov8858) int ret; struct device *dev = &ov8858->client->dev; - if (!IS_ERR(ov8858->pwdn_gpio)) - gpiod_set_value_cansleep(ov8858->pwdn_gpio, 0); + gpiod_set_value_cansleep(ov8858->pwdn_gpio, 1); clk_disable_unprepare(ov8858->xvclk); - if (!IS_ERR(ov8858->reset_gpio)) - gpiod_set_value_cansleep(ov8858->reset_gpio, 0); + gpiod_set_value_cansleep(ov8858->reset_gpio, 1); + if (!IS_ERR_OR_NULL(ov8858->pins_sleep)) { ret = pinctrl_select_state(ov8858->pinctrl, ov8858->pins_sleep); @@ -2205,9 +2193,6 @@ static void __ov8858_power_off(struct ov8858 *ov8858) dev_dbg(dev, "could not set pins\n"); } - //if (!IS_ERR(ov8858->power_gpio)) - //gpiod_set_value_cansleep(ov8858->power_gpio, 0); - regulator_bulk_disable(OV8858_NUM_SUPPLIES, ov8858->supplies); } @@ -2236,7 +2221,7 @@ static int ov8858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) { struct ov8858 *ov8858 = to_ov8858(sd); struct v4l2_mbus_framefmt *try_fmt = - v4l2_subdev_get_try_format(sd, fh->pad, 0); + v4l2_subdev_get_try_format(sd, fh->state, 0); const struct ov8858_mode *def_mode = &supported_modes[0]; mutex_lock(&ov8858->mutex); @@ -2254,7 +2239,7 @@ static int ov8858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) #endif static int ov8858_enum_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_state *state, struct v4l2_subdev_frame_interval_enum *fie) { struct ov8858 *ov8858 = to_ov8858(sd); @@ -2726,18 +2711,19 @@ static int ov8858_check_sensor_id(struct ov8858 *ov8858, int ret; ret = ov8858_read_reg(client, OV8858_REG_CHIP_ID, - OV8858_REG_VALUE_24BIT, &id); + OV8858_REG_VALUE_24BIT, &id); if (id != CHIP_ID) { dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret); return ret; } ret = ov8858_read_reg(client, OV8858_CHIP_REVISION_REG, - OV8858_REG_VALUE_08BIT, &id); + OV8858_REG_VALUE_08BIT, &id); if (ret) { dev_err(dev, "Read chip revision register error\n"); return ret; } + dev_info(dev, "Detected OV%06x sensor, REVISION 0x%x\n", CHIP_ID, id); if (id == OV8858_R2A) { @@ -2781,6 +2767,7 @@ static int ov8858_parse_of(struct ov8858 *ov8858) dev_err(dev, "Failed to get endpoint\n"); return -EINVAL; } + fwnode = of_fwnode_handle(endpoint); rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); if (rval <= 0) { @@ -2821,16 +2808,12 @@ static int ov8858_probe(struct i2c_client *client, char facing[2]; int ret; - dev_info(dev, "driver version: %02x.%02x.%02x", - DRIVER_VERSION >> 16, - (DRIVER_VERSION & 0xff00) >> 8, - DRIVER_VERSION & 0x00ff); - ov8858 = devm_kzalloc(dev, sizeof(*ov8858), GFP_KERNEL); if (!ov8858) return -ENOMEM; ov8858->client = client; + ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX, &ov8858->module_index); ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING, @@ -2839,40 +2822,37 @@ static int ov8858_probe(struct i2c_client *client, &ov8858->module_name); ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME, &ov8858->len_name); - if (ret) { - dev_err(dev, + if (ret) + return dev_err_probe(dev, -EINVAL, "could not get module information!\n"); - return -EINVAL; - } ov8858->xvclk = devm_clk_get(dev, "xvclk"); - if (IS_ERR(ov8858->xvclk)) { - dev_err(dev, "Failed to get xvclk\n"); - return -EINVAL; - } + if (IS_ERR(ov8858->xvclk)) + return dev_err_probe(dev, PTR_ERR(ov8858->xvclk), + "Failed to get xvclk\n"); - ov8858->power_gpio = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); - if (IS_ERR(ov8858->power_gpio)) - dev_warn(dev, "Failed to get power-gpios, maybe no use\n"); - - ov8858->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); + ov8858->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); if (IS_ERR(ov8858->reset_gpio)) - dev_warn(dev, "Failed to get reset-gpios, maybe no use\n"); + return dev_err_probe(dev, PTR_ERR(ov8858->reset_gpio), + "Failed to get reset gpio\n"); - ov8858->pwdn_gpio = devm_gpiod_get(dev, "pwdn", GPIOD_OUT_LOW); + ov8858->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown", + GPIOD_OUT_HIGH); if (IS_ERR(ov8858->pwdn_gpio)) - dev_warn(dev, "Failed to get pwdn-gpios, maybe no use\n"); + return dev_err_probe(dev, PTR_ERR(ov8858->pwdn_gpio), + "Failed to get powerdown gpio\n"); ret = ov8858_configure_regulators(ov8858); - if (ret) { - dev_err(dev, "Failed to get power regulators\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to get power regulators\n"); ret = ov8858_parse_of(ov8858); if (ret != 0) return -EINVAL; + /* ov8858->pinctrl = devm_pinctrl_get(dev); if (!IS_ERR(ov8858->pinctrl)) { ov8858->pins_default = @@ -2887,6 +2867,7 @@ static int ov8858_probe(struct i2c_client *client, if (IS_ERR(ov8858->pins_sleep)) dev_err(dev, "could not get sleep pinstate\n"); } + */ mutex_init(&ov8858->mutex); @@ -2910,10 +2891,10 @@ static int ov8858_probe(struct i2c_client *client, sd->internal_ops = &ov8858_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #endif -#if defined(CONFIG_MEDIA_CONTROLLER) +#ifdef CONFIG_MEDIA_CONTROLLER ov8858->pad.flags = MEDIA_PAD_FL_SOURCE; - sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; - ret = media_entity_init(&sd->entity, 1, &ov8858->pad, 0); + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + ret = media_entity_pads_init(&sd->entity, 1, &ov8858->pad); if (ret < 0) goto err_power_off; #endif @@ -2927,7 +2908,7 @@ static int ov8858_probe(struct i2c_client *client, snprintf(sd->name, sizeof(sd->name), "m%02d_%s_%s %s", ov8858->module_index, facing, OV8858_NAME, dev_name(sd->dev)); - ret = v4l2_async_register_subdev_sensor_common(sd); + ret = v4l2_async_register_subdev_sensor(sd); if (ret) { dev_err(dev, "v4l2 async register subdev failed\n"); goto err_clean_entity; @@ -2940,7 +2921,7 @@ static int ov8858_probe(struct i2c_client *client, return 0; err_clean_entity: -#if defined(CONFIG_MEDIA_CONTROLLER) +#ifdef CONFIG_MEDIA_CONTROLLER media_entity_cleanup(&sd->entity); #endif err_power_off: @@ -2953,13 +2934,13 @@ static int ov8858_probe(struct i2c_client *client, return ret; } -static int ov8858_remove(struct i2c_client *client) +static void ov8858_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov8858 *ov8858 = to_ov8858(sd); v4l2_async_unregister_subdev(sd); -#if defined(CONFIG_MEDIA_CONTROLLER) +#ifdef CONFIG_MEDIA_CONTROLLER media_entity_cleanup(&sd->entity); #endif v4l2_ctrl_handler_free(&ov8858->ctrl_handler); @@ -2973,8 +2954,6 @@ static int ov8858_remove(struct i2c_client *client) if (!pm_runtime_status_suspended(&client->dev)) __ov8858_power_off(ov8858); pm_runtime_set_suspended(&client->dev); - - return 0; } #if IS_ENABLED(CONFIG_OF) @@ -3001,18 +2980,7 @@ static struct i2c_driver ov8858_i2c_driver = { .id_table = ov8858_match_id, }; -static int __init sensor_mod_init(void) -{ - return i2c_add_driver(&ov8858_i2c_driver); -} - -static void __exit sensor_mod_exit(void) -{ - i2c_del_driver(&ov8858_i2c_driver); -} - -device_initcall_sync(sensor_mod_init); -module_exit(sensor_mod_exit); +module_i2c_driver(ov8858_i2c_driver); MODULE_DESCRIPTION("OmniVision ov8858 sensor driver"); MODULE_LICENSE("GPL v2"); -- 2.35.3