Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Samsung S5K6A3 image sensor driver
0004  *
0005  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
0006  * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
0007  */
0008 
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/device.h>
0012 #include <linux/errno.h>
0013 #include <linux/gpio.h>
0014 #include <linux/i2c.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of_gpio.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/regulator/consumer.h>
0020 #include <linux/slab.h>
0021 #include <linux/videodev2.h>
0022 #include <media/v4l2-async.h>
0023 #include <media/v4l2-subdev.h>
0024 
0025 #define S5K6A3_SENSOR_MAX_WIDTH     1412
0026 #define S5K6A3_SENSOR_MAX_HEIGHT    1412
0027 #define S5K6A3_SENSOR_MIN_WIDTH     32
0028 #define S5K6A3_SENSOR_MIN_HEIGHT    32
0029 
0030 #define S5K6A3_DEFAULT_WIDTH        1296
0031 #define S5K6A3_DEFAULT_HEIGHT       732
0032 
0033 #define S5K6A3_DRV_NAME         "S5K6A3"
0034 #define S5K6A3_CLK_NAME         "extclk"
0035 #define S5K6A3_DEFAULT_CLK_FREQ     24000000U
0036 
0037 enum {
0038     S5K6A3_SUPP_VDDA,
0039     S5K6A3_SUPP_VDDIO,
0040     S5K6A3_SUPP_AFVDD,
0041     S5K6A3_NUM_SUPPLIES,
0042 };
0043 
0044 /**
0045  * struct s5k6a3 - fimc-is sensor data structure
0046  * @dev: pointer to this I2C client device structure
0047  * @subdev: the image sensor's v4l2 subdev
0048  * @pad: subdev media source pad
0049  * @supplies: image sensor's voltage regulator supplies
0050  * @gpio_reset: GPIO connected to the sensor's reset pin
0051  * @lock: mutex protecting the structure's members below
0052  * @format: media bus format at the sensor's source pad
0053  * @clock: pointer to &struct clk.
0054  * @clock_frequency: clock frequency
0055  * @power_count: stores state if device is powered
0056  */
0057 struct s5k6a3 {
0058     struct device *dev;
0059     struct v4l2_subdev subdev;
0060     struct media_pad pad;
0061     struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
0062     int gpio_reset;
0063     struct mutex lock;
0064     struct v4l2_mbus_framefmt format;
0065     struct clk *clock;
0066     u32 clock_frequency;
0067     int power_count;
0068 };
0069 
0070 static const char * const s5k6a3_supply_names[] = {
0071     [S5K6A3_SUPP_VDDA]  = "svdda",
0072     [S5K6A3_SUPP_VDDIO] = "svddio",
0073     [S5K6A3_SUPP_AFVDD] = "afvdd",
0074 };
0075 
0076 static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
0077 {
0078     return container_of(sd, struct s5k6a3, subdev);
0079 }
0080 
0081 static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
0082     {
0083         .code = MEDIA_BUS_FMT_SGRBG10_1X10,
0084         .colorspace = V4L2_COLORSPACE_SRGB,
0085         .field = V4L2_FIELD_NONE,
0086     }
0087 };
0088 
0089 static const struct v4l2_mbus_framefmt *find_sensor_format(
0090     struct v4l2_mbus_framefmt *mf)
0091 {
0092     int i;
0093 
0094     for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
0095         if (mf->code == s5k6a3_formats[i].code)
0096             return &s5k6a3_formats[i];
0097 
0098     return &s5k6a3_formats[0];
0099 }
0100 
0101 static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
0102                   struct v4l2_subdev_state *sd_state,
0103                   struct v4l2_subdev_mbus_code_enum *code)
0104 {
0105     if (code->index >= ARRAY_SIZE(s5k6a3_formats))
0106         return -EINVAL;
0107 
0108     code->code = s5k6a3_formats[code->index].code;
0109     return 0;
0110 }
0111 
0112 static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
0113 {
0114     const struct v4l2_mbus_framefmt *fmt;
0115 
0116     fmt = find_sensor_format(mf);
0117     mf->code = fmt->code;
0118     mf->field = V4L2_FIELD_NONE;
0119     v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
0120                   S5K6A3_SENSOR_MAX_WIDTH, 0,
0121                   &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
0122                   S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
0123 }
0124 
0125 static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
0126         struct s5k6a3 *sensor, struct v4l2_subdev_state *sd_state,
0127         u32 pad, enum v4l2_subdev_format_whence which)
0128 {
0129     if (which == V4L2_SUBDEV_FORMAT_TRY)
0130         return sd_state ? v4l2_subdev_get_try_format(&sensor->subdev,
0131                                  sd_state, pad) : NULL;
0132 
0133     return &sensor->format;
0134 }
0135 
0136 static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
0137                   struct v4l2_subdev_state *sd_state,
0138                   struct v4l2_subdev_format *fmt)
0139 {
0140     struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
0141     struct v4l2_mbus_framefmt *mf;
0142 
0143     s5k6a3_try_format(&fmt->format);
0144 
0145     mf = __s5k6a3_get_format(sensor, sd_state, fmt->pad, fmt->which);
0146     if (mf) {
0147         mutex_lock(&sensor->lock);
0148         *mf = fmt->format;
0149         mutex_unlock(&sensor->lock);
0150     }
0151     return 0;
0152 }
0153 
0154 static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
0155               struct v4l2_subdev_state *sd_state,
0156               struct v4l2_subdev_format *fmt)
0157 {
0158     struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
0159     struct v4l2_mbus_framefmt *mf;
0160 
0161     mf = __s5k6a3_get_format(sensor, sd_state, fmt->pad, fmt->which);
0162 
0163     mutex_lock(&sensor->lock);
0164     fmt->format = *mf;
0165     mutex_unlock(&sensor->lock);
0166     return 0;
0167 }
0168 
0169 static const struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
0170     .enum_mbus_code = s5k6a3_enum_mbus_code,
0171     .get_fmt    = s5k6a3_get_fmt,
0172     .set_fmt    = s5k6a3_set_fmt,
0173 };
0174 
0175 static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
0176 {
0177     struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(sd,
0178                                        fh->state,
0179                                        0);
0180 
0181     *format     = s5k6a3_formats[0];
0182     format->width   = S5K6A3_DEFAULT_WIDTH;
0183     format->height  = S5K6A3_DEFAULT_HEIGHT;
0184 
0185     return 0;
0186 }
0187 
0188 static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops = {
0189     .open = s5k6a3_open,
0190 };
0191 
0192 static int __s5k6a3_power_on(struct s5k6a3 *sensor)
0193 {
0194     int i = S5K6A3_SUPP_VDDA;
0195     int ret;
0196 
0197     ret = clk_set_rate(sensor->clock, sensor->clock_frequency);
0198     if (ret < 0)
0199         return ret;
0200 
0201     ret = pm_runtime_get(sensor->dev);
0202     if (ret < 0)
0203         goto error_rpm_put;
0204 
0205     ret = regulator_enable(sensor->supplies[i].consumer);
0206     if (ret < 0)
0207         goto error_rpm_put;
0208 
0209     ret = clk_prepare_enable(sensor->clock);
0210     if (ret < 0)
0211         goto error_reg_dis;
0212 
0213     for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
0214         ret = regulator_enable(sensor->supplies[i].consumer);
0215         if (ret < 0)
0216             goto error_clk;
0217     }
0218 
0219     gpio_set_value(sensor->gpio_reset, 1);
0220     usleep_range(600, 800);
0221     gpio_set_value(sensor->gpio_reset, 0);
0222     usleep_range(600, 800);
0223     gpio_set_value(sensor->gpio_reset, 1);
0224 
0225     /* Delay needed for the sensor initialization */
0226     msleep(20);
0227     return 0;
0228 
0229 error_clk:
0230     clk_disable_unprepare(sensor->clock);
0231 error_reg_dis:
0232     for (--i; i >= 0; --i)
0233         regulator_disable(sensor->supplies[i].consumer);
0234 error_rpm_put:
0235     pm_runtime_put(sensor->dev);
0236     return ret;
0237 }
0238 
0239 static int __s5k6a3_power_off(struct s5k6a3 *sensor)
0240 {
0241     int i;
0242 
0243     gpio_set_value(sensor->gpio_reset, 0);
0244 
0245     for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--)
0246         regulator_disable(sensor->supplies[i].consumer);
0247 
0248     clk_disable_unprepare(sensor->clock);
0249     pm_runtime_put(sensor->dev);
0250     return 0;
0251 }
0252 
0253 static int s5k6a3_s_power(struct v4l2_subdev *sd, int on)
0254 {
0255     struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
0256     int ret = 0;
0257 
0258     mutex_lock(&sensor->lock);
0259 
0260     if (sensor->power_count == !on) {
0261         if (on)
0262             ret = __s5k6a3_power_on(sensor);
0263         else
0264             ret = __s5k6a3_power_off(sensor);
0265 
0266         if (ret == 0)
0267             sensor->power_count += on ? 1 : -1;
0268     }
0269 
0270     mutex_unlock(&sensor->lock);
0271     return ret;
0272 }
0273 
0274 static const struct v4l2_subdev_core_ops s5k6a3_core_ops = {
0275     .s_power = s5k6a3_s_power,
0276 };
0277 
0278 static const struct v4l2_subdev_ops s5k6a3_subdev_ops = {
0279     .core = &s5k6a3_core_ops,
0280     .pad = &s5k6a3_pad_ops,
0281 };
0282 
0283 static int s5k6a3_probe(struct i2c_client *client)
0284 {
0285     struct device *dev = &client->dev;
0286     struct s5k6a3 *sensor;
0287     struct v4l2_subdev *sd;
0288     int gpio, i, ret;
0289 
0290     sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
0291     if (!sensor)
0292         return -ENOMEM;
0293 
0294     mutex_init(&sensor->lock);
0295     sensor->gpio_reset = -EINVAL;
0296     sensor->clock = ERR_PTR(-EINVAL);
0297     sensor->dev = dev;
0298 
0299     sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME);
0300     if (IS_ERR(sensor->clock))
0301         return PTR_ERR(sensor->clock);
0302 
0303     gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
0304     if (!gpio_is_valid(gpio))
0305         return gpio;
0306 
0307     ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
0308                         S5K6A3_DRV_NAME);
0309     if (ret < 0)
0310         return ret;
0311 
0312     sensor->gpio_reset = gpio;
0313 
0314     if (of_property_read_u32(dev->of_node, "clock-frequency",
0315                  &sensor->clock_frequency)) {
0316         sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ;
0317         dev_info(dev, "using default %u Hz clock frequency\n",
0318                     sensor->clock_frequency);
0319     }
0320 
0321     for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++)
0322         sensor->supplies[i].supply = s5k6a3_supply_names[i];
0323 
0324     ret = devm_regulator_bulk_get(&client->dev, S5K6A3_NUM_SUPPLIES,
0325                       sensor->supplies);
0326     if (ret < 0)
0327         return ret;
0328 
0329     sd = &sensor->subdev;
0330     v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops);
0331     sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
0332     sd->internal_ops = &s5k6a3_sd_internal_ops;
0333 
0334     sensor->format.code = s5k6a3_formats[0].code;
0335     sensor->format.width = S5K6A3_DEFAULT_WIDTH;
0336     sensor->format.height = S5K6A3_DEFAULT_HEIGHT;
0337 
0338     sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
0339     sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
0340     ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad);
0341     if (ret < 0)
0342         return ret;
0343 
0344     pm_runtime_no_callbacks(dev);
0345     pm_runtime_enable(dev);
0346 
0347     ret = v4l2_async_register_subdev(sd);
0348 
0349     if (ret < 0) {
0350         pm_runtime_disable(&client->dev);
0351         media_entity_cleanup(&sd->entity);
0352     }
0353 
0354     return ret;
0355 }
0356 
0357 static int s5k6a3_remove(struct i2c_client *client)
0358 {
0359     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0360 
0361     pm_runtime_disable(&client->dev);
0362     v4l2_async_unregister_subdev(sd);
0363     media_entity_cleanup(&sd->entity);
0364     return 0;
0365 }
0366 
0367 static const struct i2c_device_id s5k6a3_ids[] = {
0368     { }
0369 };
0370 MODULE_DEVICE_TABLE(i2c, s5k6a3_ids);
0371 
0372 #ifdef CONFIG_OF
0373 static const struct of_device_id s5k6a3_of_match[] = {
0374     { .compatible = "samsung,s5k6a3" },
0375     { /* sentinel */ }
0376 };
0377 MODULE_DEVICE_TABLE(of, s5k6a3_of_match);
0378 #endif
0379 
0380 static struct i2c_driver s5k6a3_driver = {
0381     .driver = {
0382         .of_match_table = of_match_ptr(s5k6a3_of_match),
0383         .name       = S5K6A3_DRV_NAME,
0384     },
0385     .probe_new  = s5k6a3_probe,
0386     .remove     = s5k6a3_remove,
0387     .id_table   = s5k6a3_ids,
0388 };
0389 
0390 module_i2c_driver(s5k6a3_driver);
0391 
0392 MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
0393 MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
0394 MODULE_LICENSE("GPL v2");