build/patch/kernel/archive/sunxi-6.1/patches.megous/media-i2c-ov8858-Port-BSP-driver-to-5.18-and-improve-DT-binding.patch

390 lines
12 KiB
Diff
Raw Permalink Normal View History

From b3f40bb2fbcb4cca9cf1ca3adc09f4ae87524e1d Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Sun, 22 May 2022 14:31:08 +0200
Subject: [PATCH 357/389] 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 <megi@xff.cz>
---
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 11f01e30bc1d..69ec1efef2f8 100644
--- a/drivers/media/i2c/ov8858.c
+++ b/drivers/media/i2c/ov8858.c
@@ -21,7 +21,7 @@
#include <linux/slab.h>
#include <linux/pinctrl/consumer.h>
#include <linux/version.h>
-#include <linux/rk-camera-module.h>
+#include "rk-camera-module.h"
#include <media/v4l2-async.h>
#include <media/media-entity.h>
@@ -34,8 +34,6 @@
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
-#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