1 /* linux/drivers/media/video/s5k4ea.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * Driver for S5K4EA (SXGA camera) from Samsung Electronics
7 * 1/6" 1.3Mp CMOS Image Sensor SoC with an Embedded Image Processor
8 * supporting MIPI CSI-2
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/slab.h>
16 #include <linux/i2c.h>
17 #include <linux/delay.h>
18 #include <linux/version.h>
19 #include <media/v4l2-device.h>
20 #include <media/v4l2-subdev.h>
21 #include <media/v4l2-i2c-drv.h>
22 #include <media/s5k4ea_platform.h>
24 #ifdef CONFIG_VIDEO_SAMSUNG_V4L2
25 #include <linux/videodev2_exynos_media.h>
26 #include <linux/videodev2_exynos_camera.h>
31 #define S5K4EA_DRIVER_NAME "S5K4EA"
33 /* Default resolution & pixelformat. plz ref s5k4ea_platform.h */
34 #define DEFAULT_RES WVGA /* Index of resoultion */
35 #define DEFAUT_FPS_INDEX S5K4EA_15FPS
36 #define DEFAULT_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
40 * Parallel : ITU-R. 656/601 YUV422, RGB565, RGB888 (Up to VGA), RAW10
41 * Serial : MIPI CSI2 (single lane) YUV422, RGB565, RGB888 (Up to VGA), RAW10
42 * Resolution : 1280 (H) x 1024 (V)
43 * Image control : Brightness, Contrast, Saturation, Sharpness, Glamour
44 * Effect : Mono, Negative, Sepia, Aqua, Sketch
45 * FPS : 15fps @full resolution, 30fps @VGA, 24fps @720p
46 * Max. pixel clock frequency : 48MHz(upto)
47 * Internal PLL (6MHz to 27MHz input frequency)
50 /* Camera functional setting values configured by user concept */
51 struct s5k4ea_userset {
52 signed int exposure_bias; /* V4L2_CID_EXPOSURE */
54 unsigned int awb_lock;
55 unsigned int auto_wb; /* V4L2_CID_AUTO_WHITE_BALANCE */
56 unsigned int manual_wb; /* V4L2_CID_WHITE_BALANCE_PRESET */
57 unsigned int wb_temp; /* V4L2_CID_WHITE_BALANCE_TEMPERATURE */
58 unsigned int effect; /* Color FX (AKA Color tone) */
59 unsigned int contrast; /* V4L2_CID_CONTRAST */
60 unsigned int saturation; /* V4L2_CID_SATURATION */
61 unsigned int sharpness; /* V4L2_CID_SHARPNESS */
66 struct s5k4ea_platform_data *pdata;
67 struct v4l2_subdev sd;
68 struct v4l2_pix_format pix;
69 struct v4l2_fract timeperframe;
70 struct s5k4ea_userset userset;
71 int freq; /* MCLK in KHz */
78 static inline struct s5k4ea_state *to_state(struct v4l2_subdev *sd)
80 return container_of(sd, struct s5k4ea_state, sd);
84 * S5K4EA register structure : 2bytes address, 2bytes value
85 * retry on write failure up-to 5 times
87 static inline int s5k4ea_write(struct v4l2_subdev *sd, u16 addr, u16 val)
89 struct i2c_client *client = v4l2_get_subdevdata(sd);
90 struct i2c_msg msg[1];
100 msg->addr = client->addr;
106 reg[1] = addr & 0xff;
110 err = i2c_transfer(client->adapter, msg, 1);
112 return err; /* Returns here on success */
114 /* abnormal case: retry 5 times */
116 dev_err(&client->dev, "%s: address: 0x%02x%02x, " \
117 "value: 0x%02x%02x\n", __func__, \
118 reg[0], reg[1], reg[2], reg[3]);
126 static int s5k4ea_i2c_write(struct v4l2_subdev *sd, unsigned char i2c_data[],
127 unsigned char length)
129 struct i2c_client *client = v4l2_get_subdevdata(sd);
130 unsigned char buf[length], i;
131 struct i2c_msg msg = {client->addr, 0, length, buf};
133 for (i = 0; i < length; i++)
134 buf[i] = i2c_data[i];
136 return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
139 static const char *s5k4ea_querymenu_wb_preset[] = {
140 "WB Tungsten", "WB Fluorescent", "WB sunny", "WB cloudy", NULL
143 static const char *s5k4ea_querymenu_effect_mode[] = {
144 "Effect Sepia", "Effect Aqua", "Effect Monochrome",
145 "Effect Negative", "Effect Sketch", NULL
148 static const char *s5k4ea_querymenu_ev_bias_mode[] = {
149 "-3EV", "-2,1/2EV", "-2EV", "-1,1/2EV",
150 "-1EV", "-1/2EV", "0", "1/2EV",
151 "1EV", "1,1/2EV", "2EV", "2,1/2EV",
155 static struct v4l2_queryctrl s5k4ea_controls[] = {
158 * For now, we just support in preset type
159 * to be close to generic WB system,
160 * we define color temp range for each preset
162 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
163 .type = V4L2_CTRL_TYPE_INTEGER,
164 .name = "White balance in kelvin",
168 .default_value = 0, /* FIXME */
171 .id = V4L2_CID_WHITE_BALANCE_PRESET,
172 .type = V4L2_CTRL_TYPE_MENU,
173 .name = "White balance preset",
175 .maximum = ARRAY_SIZE(s5k4ea_querymenu_wb_preset) - 2,
180 .id = V4L2_CID_AUTO_WHITE_BALANCE,
181 .type = V4L2_CTRL_TYPE_BOOLEAN,
182 .name = "Auto white balance",
189 .id = V4L2_CID_EXPOSURE,
190 .type = V4L2_CTRL_TYPE_MENU,
191 .name = "Exposure bias",
193 .maximum = ARRAY_SIZE(s5k4ea_querymenu_ev_bias_mode) - 2,
195 .default_value = (ARRAY_SIZE(s5k4ea_querymenu_ev_bias_mode) \
199 .id = V4L2_CID_COLORFX,
200 .type = V4L2_CTRL_TYPE_MENU,
201 .name = "Image Effect",
203 .maximum = ARRAY_SIZE(s5k4ea_querymenu_effect_mode) - 2,
208 .id = V4L2_CID_CONTRAST,
209 .type = V4L2_CTRL_TYPE_INTEGER,
217 .id = V4L2_CID_SATURATION,
218 .type = V4L2_CTRL_TYPE_INTEGER,
219 .name = "Saturation",
226 .id = V4L2_CID_SHARPNESS,
227 .type = V4L2_CTRL_TYPE_INTEGER,
236 const char **s5k4ea_ctrl_get_menu(u32 id)
239 case V4L2_CID_WHITE_BALANCE_PRESET:
240 return s5k4ea_querymenu_wb_preset;
242 case V4L2_CID_COLORFX:
243 return s5k4ea_querymenu_effect_mode;
245 case V4L2_CID_EXPOSURE:
246 return s5k4ea_querymenu_ev_bias_mode;
249 return v4l2_ctrl_get_menu(id);
253 static inline struct v4l2_queryctrl const *s5k4ea_find_qctrl(int id)
257 for (i = 0; i < ARRAY_SIZE(s5k4ea_controls); i++)
258 if (s5k4ea_controls[i].id == id)
259 return &s5k4ea_controls[i];
264 static int s5k4ea_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
268 for (i = 0; i < ARRAY_SIZE(s5k4ea_controls); i++) {
269 if (s5k4ea_controls[i].id == qc->id) {
270 memcpy(qc, &s5k4ea_controls[i], \
271 sizeof(struct v4l2_queryctrl));
279 static int s5k4ea_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
281 struct v4l2_queryctrl qctrl;
284 s5k4ea_queryctrl(sd, &qctrl);
286 return v4l2_ctrl_query_menu(qm, &qctrl, s5k4ea_ctrl_get_menu(qm->id));
290 * Clock configuration
291 * Configure expected MCLK from host and return EINVAL if not supported clock
292 * frequency is expected
294 * flag : not supported for now
296 static int s5k4ea_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
303 static int s5k4ea_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
310 static int s5k4ea_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
316 static int s5k4ea_enum_framesizes(struct v4l2_subdev *sd,
317 struct v4l2_frmsizeenum *fsize)
324 static int s5k4ea_enum_frameintervals(struct v4l2_subdev *sd,
325 struct v4l2_frmivalenum *fival)
332 static int s5k4ea_enum_fmt(struct v4l2_subdev *sd,
333 struct v4l2_fmtdesc *fmtdesc)
340 static int s5k4ea_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
347 static int s5k4ea_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
354 static int s5k4ea_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
361 static int s5k4ea_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
363 struct i2c_client *client = v4l2_get_subdevdata(sd);
364 struct s5k4ea_state *state = to_state(sd);
365 struct s5k4ea_userset userset = state->userset;
369 case V4L2_CID_EXPOSURE:
370 ctrl->value = userset.exposure_bias;
373 case V4L2_CID_AUTO_WHITE_BALANCE:
374 ctrl->value = userset.auto_wb;
377 case V4L2_CID_WHITE_BALANCE_PRESET:
378 ctrl->value = userset.manual_wb;
381 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
382 ctrl->value = userset.wb_temp;
385 case V4L2_CID_COLORFX:
386 ctrl->value = userset.effect;
389 case V4L2_CID_CONTRAST:
390 ctrl->value = userset.contrast;
393 case V4L2_CID_SATURATION:
394 ctrl->value = userset.saturation;
397 case V4L2_CID_SHARPNESS:
398 ctrl->value = userset.saturation;
402 dev_err(&client->dev, "%s: no such ctrl\n", __func__);
409 static int s5k4ea_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
411 #ifdef S5K4EA_COMPLETE
412 struct i2c_client *client = v4l2_get_subdevdata(sd);
413 struct s5k4ea_state *state = to_state(sd);
414 struct s5k4ea_userset userset = state->userset;
418 case V4L2_CID_EXPOSURE:
419 dev_dbg(&client->dev, "%s: V4L2_CID_EXPOSURE\n", \
421 err = s5k4ea_write_regs(sd, s5k4ea_regs_ev_bias[ctrl->value]);
423 case V4L2_CID_AUTO_WHITE_BALANCE:
424 dev_dbg(&client->dev, "%s: V4L2_CID_AUTO_WHITE_BALANCE\n", \
426 err = s5k4ea_write_regs(sd, \
427 s5k4ea_regs_awb_enable[ctrl->value]);
429 case V4L2_CID_WHITE_BALANCE_PRESET:
430 dev_dbg(&client->dev, "%s: V4L2_CID_WHITE_BALANCE_PRESET\n", \
432 err = s5k4ea_write_regs(sd, \
433 s5k4ea_regs_wb_preset[ctrl->value]);
435 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
436 dev_dbg(&client->dev, \
437 "%s: V4L2_CID_WHITE_BALANCE_TEMPERATURE\n", __func__);
438 err = s5k4ea_write_regs(sd, \
439 s5k4ea_regs_wb_temperature[ctrl->value]);
441 case V4L2_CID_COLORFX:
442 dev_dbg(&client->dev, "%s: V4L2_CID_COLORFX\n", __func__);
443 err = s5k4ea_write_regs(sd, \
444 s5k4ea_regs_color_effect[ctrl->value]);
446 case V4L2_CID_CONTRAST:
447 dev_dbg(&client->dev, "%s: V4L2_CID_CONTRAST\n", __func__);
448 err = s5k4ea_write_regs(sd, \
449 s5k4ea_regs_contrast_bias[ctrl->value]);
451 case V4L2_CID_SATURATION:
452 dev_dbg(&client->dev, "%s: V4L2_CID_SATURATION\n", __func__);
453 err = s5k4ea_write_regs(sd, \
454 s5k4ea_regs_saturation_bias[ctrl->value]);
456 case V4L2_CID_SHARPNESS:
457 dev_dbg(&client->dev, "%s: V4L2_CID_SHARPNESS\n", __func__);
458 err = s5k4ea_write_regs(sd, \
459 s5k4ea_regs_sharpness_bias[ctrl->value]);
462 dev_err(&client->dev, "%s: no such control\n", __func__);
472 dev_dbg(&client->dev, "%s: vidioc_s_ctrl failed\n", __func__);
480 __s5k4ea_init_4bytes(struct v4l2_subdev *sd, unsigned char *reg[], int total)
482 struct i2c_client *client = v4l2_get_subdevdata(sd);
483 int err = -EINVAL, i;
486 for (i = 0; i < total; i++) {
487 item = (unsigned char *) ®[i];
488 if (item[0] == REG_DELAY) {
492 err = s5k4ea_i2c_write(sd, item, 4);
496 v4l_info(client, "%s: register set failed\n", \
504 __s5k4ea_init_2bytes(struct v4l2_subdev *sd, unsigned short *reg[], int total)
506 struct i2c_client *client = v4l2_get_subdevdata(sd);
507 int err = -EINVAL, i;
508 unsigned short *item;
510 for (i = 0; i < total; i++) {
511 item = (unsigned short *) ®[i];
512 if (item[0] == REG_DELAY) {
516 err = s5k4ea_write(sd, item[0], item[1]);
520 v4l_info(client, "%s: register set failed\n", \
527 static int s5k4ea_init(struct v4l2_subdev *sd, u32 val)
529 struct i2c_client *client = v4l2_get_subdevdata(sd);
532 v4l_info(client, "%s: camera initialization start\n", __func__);
534 err = __s5k4ea_init_4bytes(sd, \
535 (unsigned char **) s5k4ea_init_reg1, S5K4EA_INIT_REGS1);
537 err = __s5k4ea_init_2bytes(sd, \
538 (unsigned short **) s5k4ea_init_reg2, S5K4EA_INIT_REGS2);
540 err = __s5k4ea_init_4bytes(sd, \
541 (unsigned char **) s5k4ea_init_reg3, S5K4EA_INIT_REGS3);
543 err = __s5k4ea_init_2bytes(sd, \
544 (unsigned short **) s5k4ea_init_reg4, S5K4EA_INIT_REGS4);
547 err = __s5k4ea_init_4bytes(sd, \
548 (unsigned char **) s5k4ea_init_jpeg, S5K4EA_INIT_JPEG);
550 err = __s5k4ea_init_4bytes(sd, \
551 (unsigned char **) s5k4ea_init_reg5, S5K4EA_INIT_REGS5);
553 err = __s5k4ea_init_2bytes(sd, \
554 (unsigned short **) s5k4ea_init_reg6, S5K4EA_INIT_REGS6);
556 err = __s5k4ea_init_4bytes(sd, \
557 (unsigned char **) s5k4ea_init_reg7, S5K4EA_INIT_REGS7);
559 err = __s5k4ea_init_2bytes(sd, \
560 (unsigned short **) s5k4ea_init_reg8, S5K4EA_INIT_REGS8);
562 err = __s5k4ea_init_4bytes(sd, \
563 (unsigned char **) s5k4ea_init_reg9, S5K4EA_INIT_REGS9);
565 err = __s5k4ea_init_2bytes(sd, \
566 (unsigned short **) s5k4ea_init_reg10, S5K4EA_INIT_REGS10);
568 err = __s5k4ea_init_4bytes(sd, \
569 (unsigned char **) s5k4ea_init_reg11, S5K4EA_INIT_REGS11);
572 v4l_err(client, "%s: camera initialization failed\n", \
574 return -EIO; /* FIXME */
581 * s_config subdev ops
582 * With camera device, we need to re-initialize every single opening time
583 * therefor,it is not necessary to be initialized on probe time.
584 * except for version checking
585 * NOTE: version checking is optional
587 static int s5k4ea_s_config(struct v4l2_subdev *sd, int irq, void *platform_data)
589 struct i2c_client *client = v4l2_get_subdevdata(sd);
590 struct s5k4ea_state *state = to_state(sd);
591 struct s5k4ea_platform_data *pdata;
593 dev_info(&client->dev, "fetching platform data\n");
595 pdata = client->dev.platform_data;
598 dev_err(&client->dev, "%s: no platform data\n", __func__);
603 * Assign default format and resolution
604 * Use configured default information in platform data
605 * or without them, use default information in driver
607 if (!(pdata->default_width && pdata->default_height)) {
608 /* TODO: assign driver default resolution */
610 state->pix.width = pdata->default_width;
611 state->pix.height = pdata->default_height;
614 if (!pdata->pixelformat)
615 state->pix.pixelformat = DEFAULT_FMT;
617 state->pix.pixelformat = pdata->pixelformat;
620 state->freq = 48000000; /* 48MHz default */
622 state->freq = pdata->freq;
624 if (!pdata->is_mipi) {
626 dev_info(&client->dev, "parallel mode\n");
628 state->is_mipi = pdata->is_mipi;
633 static int s5k4ea_sleep(struct v4l2_subdev *sd)
635 struct i2c_client *client = v4l2_get_subdevdata(sd);
636 int err = -EINVAL, i;
638 v4l_info(client, "%s: sleep mode\n", __func__);
640 for (i = 0; i < S5K4EA_SLEEP_REGS; i++) {
641 if (s5k4ea_sleep_reg[i][0] == REG_DELAY) {
642 mdelay(s5k4ea_sleep_reg[i][1]);
645 err = s5k4ea_write(sd, s5k4ea_sleep_reg[i][0], \
646 s5k4ea_sleep_reg[i][1]);
650 v4l_info(client, "%s: register set failed\n", __func__);
654 v4l_err(client, "%s: sleep failed\n", __func__);
661 static int s5k4ea_wakeup(struct v4l2_subdev *sd)
663 struct i2c_client *client = v4l2_get_subdevdata(sd);
664 int err = -EINVAL, i;
666 v4l_info(client, "%s: wakeup mode\n", __func__);
668 for (i = 0; i < S5K4EA_WAKEUP_REGS; i++) {
669 if (s5k4ea_wakeup_reg[i][0] == REG_DELAY) {
670 mdelay(s5k4ea_wakeup_reg[i][1]);
673 err = s5k4ea_write(sd, s5k4ea_wakeup_reg[i][0], \
674 s5k4ea_wakeup_reg[i][1]);
678 v4l_info(client, "%s: register set failed\n", __func__);
682 v4l_err(client, "%s: wake up failed\n", __func__);
689 static int s5k4ea_s_stream(struct v4l2_subdev *sd, int enable)
691 return enable ? s5k4ea_wakeup(sd) : s5k4ea_sleep(sd);
694 static const struct v4l2_subdev_core_ops s5k4ea_core_ops = {
695 .init = s5k4ea_init, /* initializing API */
696 .s_config = s5k4ea_s_config, /* Fetch platform data */
697 .queryctrl = s5k4ea_queryctrl,
698 .querymenu = s5k4ea_querymenu,
699 .g_ctrl = s5k4ea_g_ctrl,
700 .s_ctrl = s5k4ea_s_ctrl,
703 static const struct v4l2_subdev_video_ops s5k4ea_video_ops = {
704 .s_crystal_freq = s5k4ea_s_crystal_freq,
705 .g_fmt = s5k4ea_g_fmt,
706 .s_fmt = s5k4ea_s_fmt,
707 .enum_framesizes = s5k4ea_enum_framesizes,
708 .enum_frameintervals = s5k4ea_enum_frameintervals,
709 .enum_fmt = s5k4ea_enum_fmt,
710 .try_fmt = s5k4ea_try_fmt,
711 .g_parm = s5k4ea_g_parm,
712 .s_parm = s5k4ea_s_parm,
713 .s_stream = s5k4ea_s_stream,
716 static const struct v4l2_subdev_ops s5k4ea_ops = {
717 .core = &s5k4ea_core_ops,
718 .video = &s5k4ea_video_ops,
723 * Fetching platform data is being done with s_config subdev call.
724 * In probe routine, we just register subdev device
726 static int s5k4ea_probe(struct i2c_client *client,
727 const struct i2c_device_id *id)
729 struct s5k4ea_state *state;
730 struct v4l2_subdev *sd;
732 state = kzalloc(sizeof(struct s5k4ea_state), GFP_KERNEL);
737 strcpy(sd->name, S5K4EA_DRIVER_NAME);
739 /* Registering subdev */
740 v4l2_i2c_subdev_init(sd, client, &s5k4ea_ops);
742 dev_info(&client->dev, "s5k4ea has been probed\n");
747 static int s5k4ea_remove(struct i2c_client *client)
749 struct v4l2_subdev *sd = i2c_get_clientdata(client);
751 v4l2_device_unregister_subdev(sd);
756 static const struct i2c_device_id s5k4ea_id[] = {
757 { S5K4EA_DRIVER_NAME, 0 },
760 MODULE_DEVICE_TABLE(i2c, s5k4ea_id);
762 static struct v4l2_i2c_driver_data v4l2_i2c_data = {
763 .name = S5K4EA_DRIVER_NAME,
764 .probe = s5k4ea_probe,
765 .remove = s5k4ea_remove,
766 .id_table = s5k4ea_id,
769 MODULE_DESCRIPTION("Samsung Electronics S5K4EA SXGA camera driver");
770 MODULE_AUTHOR("Dongsoo Nathaniel Kim<dongsoo45.kim@samsung.com>");
771 MODULE_LICENSE("GPL");