0001
0002
0003
0004
0005
0006
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
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
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
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 { }
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");