@@ -15,7 +15,7 @@
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/firmware.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
@@ -23,7 +23,6 @@
#include <asm/unaligned.h>
#include <media/media-entity.h>
-#include <media/i2c/s5k4ecgx.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-mediabus.h>
@@ -171,12 +170,6 @@ static const char * const s5k4ecgx_supply_names[] = {
#define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names)
-enum s5k4ecgx_gpio_id {
- STBY,
- RSET,
- GPIO_NUM,
-};
-
struct s5k4ecgx {
struct v4l2_subdev sd;
struct media_pad pad;
@@ -190,7 +183,8 @@ struct s5k4ecgx {
u8 set_params;
struct regulator_bulk_data supplies[S5K4ECGX_NUM_SUPPLIES];
- struct s5k4ecgx_gpio gpio[GPIO_NUM];
+ struct gpio_desc *stby;
+ struct gpio_desc *reset;
};
static inline struct s5k4ecgx *to_s5k4ecgx(struct v4l2_subdev *sd)
@@ -454,15 +448,6 @@ static int s5k4ecgx_init_sensor(struct v4l2_subdev *sd)
return ret;
}
-static int s5k4ecgx_gpio_set_value(struct s5k4ecgx *priv, int id, u32 val)
-{
- if (!gpio_is_valid(priv->gpio[id].gpio))
- return 0;
- gpio_set_value(priv->gpio[id].gpio, val);
-
- return 1;
-}
-
static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
{
int ret;
@@ -472,23 +457,22 @@ static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
return ret;
usleep_range(30, 50);
- /* The polarity of STBY is controlled by TSP */
- if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level))
- usleep_range(30, 50);
-
- if (s5k4ecgx_gpio_set_value(priv, RSET, priv->gpio[RSET].level))
- usleep_range(30, 50);
+ /* De-assert standby and reset */
+ gpiod_set_value(priv->stby, 0);
+ usleep_range(30, 50);
+ gpiod_set_value(priv->reset, 0);
+ usleep_range(30, 50);
return 0;
}
static int __s5k4ecgx_power_off(struct s5k4ecgx *priv)
{
- if (s5k4ecgx_gpio_set_value(priv, RSET, !priv->gpio[RSET].level))
- usleep_range(30, 50);
-
- if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level))
- usleep_range(30, 50);
+ /* Assert reset and standby */
+ gpiod_set_value(priv->reset, 1);
+ usleep_range(30, 50);
+ gpiod_set_value(priv->stby, 1);
+ usleep_range(30, 50);
priv->streaming = 0;
@@ -840,68 +824,6 @@ static const struct v4l2_subdev_ops s5k4ecgx_ops = {
.video = &s5k4ecgx_video_ops,
};
-/*
- * GPIO setup
- */
-static int s5k4ecgx_config_gpio(int nr, int val, const char *name)
-{
- unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
- int ret;
-
- if (!gpio_is_valid(nr))
- return 0;
- ret = gpio_request_one(nr, flags, name);
- if (!ret)
- gpio_export(nr, 0);
-
- return ret;
-}
-
-static void s5k4ecgx_free_gpios(struct s5k4ecgx *priv)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(priv->gpio); i++) {
- if (!gpio_is_valid(priv->gpio[i].gpio))
- continue;
- gpio_free(priv->gpio[i].gpio);
- priv->gpio[i].gpio = -EINVAL;
- }
-}
-
-static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv,
- const struct s5k4ecgx_platform_data *pdata)
-{
- const struct s5k4ecgx_gpio *gpio = &pdata->gpio_stby;
- int ret;
-
- priv->gpio[STBY].gpio = -EINVAL;
- priv->gpio[RSET].gpio = -EINVAL;
-
- ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY");
-
- if (ret) {
- s5k4ecgx_free_gpios(priv);
- return ret;
- }
- priv->gpio[STBY] = *gpio;
- if (gpio_is_valid(gpio->gpio))
- gpio_set_value(gpio->gpio, 0);
-
- gpio = &pdata->gpio_reset;
-
- ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_RST");
- if (ret) {
- s5k4ecgx_free_gpios(priv);
- return ret;
- }
- priv->gpio[RSET] = *gpio;
- if (gpio_is_valid(gpio->gpio))
- gpio_set_value(gpio->gpio, 0);
-
- return 0;
-}
-
static int s5k4ecgx_init_v4l2_ctrls(struct s5k4ecgx *priv)
{
const struct v4l2_ctrl_ops *ops = &s5k4ecgx_ctrl_ops;
@@ -965,11 +887,22 @@ static int s5k4ecgx_probe(struct i2c_client *client,
if (ret)
return ret;
- ret = s5k4ecgx_config_gpios(priv, pdata);
- if (ret) {
- dev_err(&client->dev, "Failed to set gpios\n");
- goto out_err1;
+ /* Request GPIO lines asserted */
+ priv->stby = devm_gpiod_get(&client->dev, "standby", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->stby)) {
+ v4l2_err(sd, "failed to request gpio S5K4ECGX_STBY");
+ ret = PTR_ERR(priv->stby);
+ goto out_err;
+ }
+ gpiod_set_consumer_name(priv->stby, "S5K4ECGX_STBY");
+ priv->reset = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset)) {
+ v4l2_err(sd, "failed to request gpio S5K4ECGX_RST");
+ ret = PTR_ERR(priv->reset);
+ goto out_err;
}
+ gpiod_set_consumer_name(priv->reset, "S5K4ECGX_RST");
+
for (i = 0; i < S5K4ECGX_NUM_SUPPLIES; i++)
priv->supplies[i].supply = s5k4ecgx_supply_names[i];
@@ -977,20 +910,18 @@ static int s5k4ecgx_probe(struct i2c_client *client,
priv->supplies);
if (ret) {
dev_err(&client->dev, "Failed to get regulators\n");
- goto out_err2;
+ goto out_err;
}
ret = s5k4ecgx_init_v4l2_ctrls(priv);
if (ret)
- goto out_err2;
+ goto out_err;
priv->curr_pixfmt = &s5k4ecgx_formats[0];
priv->curr_frmsize = &s5k4ecgx_prev_sizes[0];
return 0;
-out_err2:
- s5k4ecgx_free_gpios(priv);
-out_err1:
+out_err:
media_entity_cleanup(&priv->sd.entity);
return ret;
@@ -1002,7 +933,6 @@ static void s5k4ecgx_remove(struct i2c_client *client)
struct s5k4ecgx *priv = to_s5k4ecgx(sd);
mutex_destroy(&priv->lock);
- s5k4ecgx_free_gpios(priv);
v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&priv->handler);
media_entity_cleanup(&sd->entity);
deleted file mode 100644
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * S5K4ECGX image sensor header file
- *
- * Copyright (C) 2012, Linaro
- * Copyright (C) 2012, Samsung Electronics Co., Ltd.
- */
-
-#ifndef S5K4ECGX_H
-#define S5K4ECGX_H
-
-/**
- * struct s5k4ecgx_gpio - data structure describing a GPIO
- * @gpio: GPIO number
- * @level: indicates active state of the @gpio
- */
-struct s5k4ecgx_gpio {
- int gpio;
- int level;
-};
-
-/**
- * struct s5k4ecgx_platform_data - s5k4ecgx driver platform data
- * @gpio_reset: GPIO driving RESET pin
- * @gpio_stby: GPIO driving STBY pin
- */
-
-struct s5k4ecgx_platform_data {
- struct s5k4ecgx_gpio gpio_reset;
- struct s5k4ecgx_gpio gpio_stby;
-};
-
-#endif /* S5K4ECGX_H */