root/drivers/media/i2c/s5k6a3.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sd_to_s5k6a3
  2. find_sensor_format
  3. s5k6a3_enum_mbus_code
  4. s5k6a3_try_format
  5. __s5k6a3_get_format
  6. s5k6a3_set_fmt
  7. s5k6a3_get_fmt
  8. s5k6a3_open
  9. __s5k6a3_power_on
  10. __s5k6a3_power_off
  11. s5k6a3_s_power
  12. s5k6a3_probe
  13. s5k6a3_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Samsung S5K6A3 image sensor driver
   4  *
   5  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   6  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
   7  */
   8 
   9 #include <linux/clk.h>
  10 #include <linux/delay.h>
  11 #include <linux/device.h>
  12 #include <linux/errno.h>
  13 #include <linux/gpio.h>
  14 #include <linux/i2c.h>
  15 #include <linux/kernel.h>
  16 #include <linux/module.h>
  17 #include <linux/of_gpio.h>
  18 #include <linux/pm_runtime.h>
  19 #include <linux/regulator/consumer.h>
  20 #include <linux/slab.h>
  21 #include <linux/videodev2.h>
  22 #include <media/v4l2-async.h>
  23 #include <media/v4l2-subdev.h>
  24 
  25 #define S5K6A3_SENSOR_MAX_WIDTH         1412
  26 #define S5K6A3_SENSOR_MAX_HEIGHT        1412
  27 #define S5K6A3_SENSOR_MIN_WIDTH         32
  28 #define S5K6A3_SENSOR_MIN_HEIGHT        32
  29 
  30 #define S5K6A3_DEFAULT_WIDTH            1296
  31 #define S5K6A3_DEFAULT_HEIGHT           732
  32 
  33 #define S5K6A3_DRV_NAME                 "S5K6A3"
  34 #define S5K6A3_CLK_NAME                 "extclk"
  35 #define S5K6A3_DEFAULT_CLK_FREQ         24000000U
  36 
  37 enum {
  38         S5K6A3_SUPP_VDDA,
  39         S5K6A3_SUPP_VDDIO,
  40         S5K6A3_SUPP_AFVDD,
  41         S5K6A3_NUM_SUPPLIES,
  42 };
  43 
  44 /**
  45  * struct s5k6a3 - fimc-is sensor data structure
  46  * @dev: pointer to this I2C client device structure
  47  * @subdev: the image sensor's v4l2 subdev
  48  * @pad: subdev media source pad
  49  * @supplies: image sensor's voltage regulator supplies
  50  * @gpio_reset: GPIO connected to the sensor's reset pin
  51  * @lock: mutex protecting the structure's members below
  52  * @format: media bus format at the sensor's source pad
  53  * @clock: pointer to &struct clk.
  54  * @clock_frequency: clock frequency
  55  * @power_count: stores state if device is powered
  56  */
  57 struct s5k6a3 {
  58         struct device *dev;
  59         struct v4l2_subdev subdev;
  60         struct media_pad pad;
  61         struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
  62         int gpio_reset;
  63         struct mutex lock;
  64         struct v4l2_mbus_framefmt format;
  65         struct clk *clock;
  66         u32 clock_frequency;
  67         int power_count;
  68 };
  69 
  70 static const char * const s5k6a3_supply_names[] = {
  71         [S5K6A3_SUPP_VDDA]      = "svdda",
  72         [S5K6A3_SUPP_VDDIO]     = "svddio",
  73         [S5K6A3_SUPP_AFVDD]     = "afvdd",
  74 };
  75 
  76 static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
  77 {
  78         return container_of(sd, struct s5k6a3, subdev);
  79 }
  80 
  81 static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
  82         {
  83                 .code = MEDIA_BUS_FMT_SGRBG10_1X10,
  84                 .colorspace = V4L2_COLORSPACE_SRGB,
  85                 .field = V4L2_FIELD_NONE,
  86         }
  87 };
  88 
  89 static const struct v4l2_mbus_framefmt *find_sensor_format(
  90         struct v4l2_mbus_framefmt *mf)
  91 {
  92         int i;
  93 
  94         for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
  95                 if (mf->code == s5k6a3_formats[i].code)
  96                         return &s5k6a3_formats[i];
  97 
  98         return &s5k6a3_formats[0];
  99 }
 100 
 101 static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
 102                                   struct v4l2_subdev_pad_config *cfg,
 103                                   struct v4l2_subdev_mbus_code_enum *code)
 104 {
 105         if (code->index >= ARRAY_SIZE(s5k6a3_formats))
 106                 return -EINVAL;
 107 
 108         code->code = s5k6a3_formats[code->index].code;
 109         return 0;
 110 }
 111 
 112 static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
 113 {
 114         const struct v4l2_mbus_framefmt *fmt;
 115 
 116         fmt = find_sensor_format(mf);
 117         mf->code = fmt->code;
 118         mf->field = V4L2_FIELD_NONE;
 119         v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
 120                               S5K6A3_SENSOR_MAX_WIDTH, 0,
 121                               &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
 122                               S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
 123 }
 124 
 125 static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
 126                 struct s5k6a3 *sensor, struct v4l2_subdev_pad_config *cfg,
 127                 u32 pad, enum v4l2_subdev_format_whence which)
 128 {
 129         if (which == V4L2_SUBDEV_FORMAT_TRY)
 130                 return cfg ? v4l2_subdev_get_try_format(&sensor->subdev, cfg, pad) : NULL;
 131 
 132         return &sensor->format;
 133 }
 134 
 135 static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
 136                                   struct v4l2_subdev_pad_config *cfg,
 137                                   struct v4l2_subdev_format *fmt)
 138 {
 139         struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
 140         struct v4l2_mbus_framefmt *mf;
 141 
 142         s5k6a3_try_format(&fmt->format);
 143 
 144         mf = __s5k6a3_get_format(sensor, cfg, fmt->pad, fmt->which);
 145         if (mf) {
 146                 mutex_lock(&sensor->lock);
 147                 *mf = fmt->format;
 148                 mutex_unlock(&sensor->lock);
 149         }
 150         return 0;
 151 }
 152 
 153 static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
 154                           struct v4l2_subdev_pad_config *cfg,
 155                           struct v4l2_subdev_format *fmt)
 156 {
 157         struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
 158         struct v4l2_mbus_framefmt *mf;
 159 
 160         mf = __s5k6a3_get_format(sensor, cfg, fmt->pad, fmt->which);
 161 
 162         mutex_lock(&sensor->lock);
 163         fmt->format = *mf;
 164         mutex_unlock(&sensor->lock);
 165         return 0;
 166 }
 167 
 168 static const struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
 169         .enum_mbus_code = s5k6a3_enum_mbus_code,
 170         .get_fmt        = s5k6a3_get_fmt,
 171         .set_fmt        = s5k6a3_set_fmt,
 172 };
 173 
 174 static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 175 {
 176         struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
 177 
 178         *format         = s5k6a3_formats[0];
 179         format->width   = S5K6A3_DEFAULT_WIDTH;
 180         format->height  = S5K6A3_DEFAULT_HEIGHT;
 181 
 182         return 0;
 183 }
 184 
 185 static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops = {
 186         .open = s5k6a3_open,
 187 };
 188 
 189 static int __s5k6a3_power_on(struct s5k6a3 *sensor)
 190 {
 191         int i = S5K6A3_SUPP_VDDA;
 192         int ret;
 193 
 194         ret = clk_set_rate(sensor->clock, sensor->clock_frequency);
 195         if (ret < 0)
 196                 return ret;
 197 
 198         ret = pm_runtime_get(sensor->dev);
 199         if (ret < 0)
 200                 return ret;
 201 
 202         ret = regulator_enable(sensor->supplies[i].consumer);
 203         if (ret < 0)
 204                 goto error_rpm_put;
 205 
 206         ret = clk_prepare_enable(sensor->clock);
 207         if (ret < 0)
 208                 goto error_reg_dis;
 209 
 210         for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
 211                 ret = regulator_enable(sensor->supplies[i].consumer);
 212                 if (ret < 0)
 213                         goto error_reg_dis;
 214         }
 215 
 216         gpio_set_value(sensor->gpio_reset, 1);
 217         usleep_range(600, 800);
 218         gpio_set_value(sensor->gpio_reset, 0);
 219         usleep_range(600, 800);
 220         gpio_set_value(sensor->gpio_reset, 1);
 221 
 222         /* Delay needed for the sensor initialization */
 223         msleep(20);
 224         return 0;
 225 
 226 error_reg_dis:
 227         for (--i; i >= 0; --i)
 228                 regulator_disable(sensor->supplies[i].consumer);
 229 error_rpm_put:
 230         pm_runtime_put(sensor->dev);
 231         return ret;
 232 }
 233 
 234 static int __s5k6a3_power_off(struct s5k6a3 *sensor)
 235 {
 236         int i;
 237 
 238         gpio_set_value(sensor->gpio_reset, 0);
 239 
 240         for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--)
 241                 regulator_disable(sensor->supplies[i].consumer);
 242 
 243         clk_disable_unprepare(sensor->clock);
 244         pm_runtime_put(sensor->dev);
 245         return 0;
 246 }
 247 
 248 static int s5k6a3_s_power(struct v4l2_subdev *sd, int on)
 249 {
 250         struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
 251         int ret = 0;
 252 
 253         mutex_lock(&sensor->lock);
 254 
 255         if (sensor->power_count == !on) {
 256                 if (on)
 257                         ret = __s5k6a3_power_on(sensor);
 258                 else
 259                         ret = __s5k6a3_power_off(sensor);
 260 
 261                 if (ret == 0)
 262                         sensor->power_count += on ? 1 : -1;
 263         }
 264 
 265         mutex_unlock(&sensor->lock);
 266         return ret;
 267 }
 268 
 269 static const struct v4l2_subdev_core_ops s5k6a3_core_ops = {
 270         .s_power = s5k6a3_s_power,
 271 };
 272 
 273 static const struct v4l2_subdev_ops s5k6a3_subdev_ops = {
 274         .core = &s5k6a3_core_ops,
 275         .pad = &s5k6a3_pad_ops,
 276 };
 277 
 278 static int s5k6a3_probe(struct i2c_client *client)
 279 {
 280         struct device *dev = &client->dev;
 281         struct s5k6a3 *sensor;
 282         struct v4l2_subdev *sd;
 283         int gpio, i, ret;
 284 
 285         sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
 286         if (!sensor)
 287                 return -ENOMEM;
 288 
 289         mutex_init(&sensor->lock);
 290         sensor->gpio_reset = -EINVAL;
 291         sensor->clock = ERR_PTR(-EINVAL);
 292         sensor->dev = dev;
 293 
 294         sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME);
 295         if (IS_ERR(sensor->clock))
 296                 return PTR_ERR(sensor->clock);
 297 
 298         gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
 299         if (!gpio_is_valid(gpio))
 300                 return gpio;
 301 
 302         ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
 303                                                 S5K6A3_DRV_NAME);
 304         if (ret < 0)
 305                 return ret;
 306 
 307         sensor->gpio_reset = gpio;
 308 
 309         if (of_property_read_u32(dev->of_node, "clock-frequency",
 310                                  &sensor->clock_frequency)) {
 311                 sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ;
 312                 dev_info(dev, "using default %u Hz clock frequency\n",
 313                                         sensor->clock_frequency);
 314         }
 315 
 316         for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++)
 317                 sensor->supplies[i].supply = s5k6a3_supply_names[i];
 318 
 319         ret = devm_regulator_bulk_get(&client->dev, S5K6A3_NUM_SUPPLIES,
 320                                       sensor->supplies);
 321         if (ret < 0)
 322                 return ret;
 323 
 324         sd = &sensor->subdev;
 325         v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops);
 326         sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 327         sd->internal_ops = &s5k6a3_sd_internal_ops;
 328 
 329         sensor->format.code = s5k6a3_formats[0].code;
 330         sensor->format.width = S5K6A3_DEFAULT_WIDTH;
 331         sensor->format.height = S5K6A3_DEFAULT_HEIGHT;
 332 
 333         sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
 334         sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
 335         ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad);
 336         if (ret < 0)
 337                 return ret;
 338 
 339         pm_runtime_no_callbacks(dev);
 340         pm_runtime_enable(dev);
 341 
 342         ret = v4l2_async_register_subdev(sd);
 343 
 344         if (ret < 0) {
 345                 pm_runtime_disable(&client->dev);
 346                 media_entity_cleanup(&sd->entity);
 347         }
 348 
 349         return ret;
 350 }
 351 
 352 static int s5k6a3_remove(struct i2c_client *client)
 353 {
 354         struct v4l2_subdev *sd = i2c_get_clientdata(client);
 355 
 356         pm_runtime_disable(&client->dev);
 357         v4l2_async_unregister_subdev(sd);
 358         media_entity_cleanup(&sd->entity);
 359         return 0;
 360 }
 361 
 362 static const struct i2c_device_id s5k6a3_ids[] = {
 363         { }
 364 };
 365 MODULE_DEVICE_TABLE(i2c, s5k6a3_ids);
 366 
 367 #ifdef CONFIG_OF
 368 static const struct of_device_id s5k6a3_of_match[] = {
 369         { .compatible = "samsung,s5k6a3" },
 370         { /* sentinel */ }
 371 };
 372 MODULE_DEVICE_TABLE(of, s5k6a3_of_match);
 373 #endif
 374 
 375 static struct i2c_driver s5k6a3_driver = {
 376         .driver = {
 377                 .of_match_table = of_match_ptr(s5k6a3_of_match),
 378                 .name           = S5K6A3_DRV_NAME,
 379         },
 380         .probe_new      = s5k6a3_probe,
 381         .remove         = s5k6a3_remove,
 382         .id_table       = s5k6a3_ids,
 383 };
 384 
 385 module_i2c_driver(s5k6a3_driver);
 386 
 387 MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
 388 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
 389 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */