upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / s5k4ea.c
1 /* linux/drivers/media/video/s5k4ea.c
2  *
3  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com/
5  *
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
9  *
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.
13 */
14
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>
23
24 #ifdef CONFIG_VIDEO_SAMSUNG_V4L2
25 #include <linux/videodev2_exynos_media.h>
26 #include <linux/videodev2_exynos_camera.h>
27 #endif
28
29 #include "s5k4ea.h"
30
31 #define S5K4EA_DRIVER_NAME      "S5K4EA"
32
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 */
37
38 /*
39  * Specification
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)
48  */
49
50 /* Camera functional setting values configured by user concept */
51 struct s5k4ea_userset {
52         signed int exposure_bias;       /* V4L2_CID_EXPOSURE */
53         unsigned int ae_lock;
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 */
62         unsigned int glamour;
63 };
64
65 struct s5k4ea_state {
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 */
72         int is_mipi;
73         int isize;
74         int ver;
75         int fps;
76 };
77
78 static inline struct s5k4ea_state *to_state(struct v4l2_subdev *sd)
79 {
80         return container_of(sd, struct s5k4ea_state, sd);
81 }
82
83 /*
84  * S5K4EA register structure : 2bytes address, 2bytes value
85  * retry on write failure up-to 5 times
86  */
87 static inline int s5k4ea_write(struct v4l2_subdev *sd, u16 addr, u16 val)
88 {
89         struct i2c_client *client = v4l2_get_subdevdata(sd);
90         struct i2c_msg msg[1];
91         unsigned char reg[4];
92         int err = 0;
93         int retry = 0;
94
95
96         if (!client->adapter)
97                 return -ENODEV;
98
99 again:
100         msg->addr = client->addr;
101         msg->flags = 0;
102         msg->len = 4;
103         msg->buf = reg;
104
105         reg[0] = addr >> 8;
106         reg[1] = addr & 0xff;
107         reg[2] = val >> 8;
108         reg[3] = val & 0xff;
109
110         err = i2c_transfer(client->adapter, msg, 1);
111         if (err >= 0)
112                 return err;     /* Returns here on success */
113
114         /* abnormal case: retry 5 times */
115         if (retry < 5) {
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]);
119                 retry++;
120                 goto again;
121         }
122
123         return err;
124 }
125
126 static int s5k4ea_i2c_write(struct v4l2_subdev *sd, unsigned char i2c_data[],
127                                 unsigned char length)
128 {
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};
132
133         for (i = 0; i < length; i++)
134                 buf[i] = i2c_data[i];
135
136         return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
137 }
138
139 static const char *s5k4ea_querymenu_wb_preset[] = {
140         "WB Tungsten", "WB Fluorescent", "WB sunny", "WB cloudy", NULL
141 };
142
143 static const char *s5k4ea_querymenu_effect_mode[] = {
144         "Effect Sepia", "Effect Aqua", "Effect Monochrome",
145         "Effect Negative", "Effect Sketch", NULL
146 };
147
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",
152         "3EV", NULL
153 };
154
155 static struct v4l2_queryctrl s5k4ea_controls[] = {
156         {
157                 /*
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
161                  */
162                 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
163                 .type = V4L2_CTRL_TYPE_INTEGER,
164                 .name = "White balance in kelvin",
165                 .minimum = 0,
166                 .maximum = 10000,
167                 .step = 1,
168                 .default_value = 0,     /* FIXME */
169         },
170         {
171                 .id = V4L2_CID_WHITE_BALANCE_PRESET,
172                 .type = V4L2_CTRL_TYPE_MENU,
173                 .name = "White balance preset",
174                 .minimum = 0,
175                 .maximum = ARRAY_SIZE(s5k4ea_querymenu_wb_preset) - 2,
176                 .step = 1,
177                 .default_value = 0,
178         },
179         {
180                 .id = V4L2_CID_AUTO_WHITE_BALANCE,
181                 .type = V4L2_CTRL_TYPE_BOOLEAN,
182                 .name = "Auto white balance",
183                 .minimum = 0,
184                 .maximum = 1,
185                 .step = 1,
186                 .default_value = 0,
187         },
188         {
189                 .id = V4L2_CID_EXPOSURE,
190                 .type = V4L2_CTRL_TYPE_MENU,
191                 .name = "Exposure bias",
192                 .minimum = 0,
193                 .maximum = ARRAY_SIZE(s5k4ea_querymenu_ev_bias_mode) - 2,
194                 .step = 1,
195                 .default_value = (ARRAY_SIZE(s5k4ea_querymenu_ev_bias_mode) \
196                                 - 2) / 2,       /* 0 EV */
197         },
198         {
199                 .id = V4L2_CID_COLORFX,
200                 .type = V4L2_CTRL_TYPE_MENU,
201                 .name = "Image Effect",
202                 .minimum = 0,
203                 .maximum = ARRAY_SIZE(s5k4ea_querymenu_effect_mode) - 2,
204                 .step = 1,
205                 .default_value = 0,
206         },
207         {
208                 .id = V4L2_CID_CONTRAST,
209                 .type = V4L2_CTRL_TYPE_INTEGER,
210                 .name = "Contrast",
211                 .minimum = 0,
212                 .maximum = 4,
213                 .step = 1,
214                 .default_value = 2,
215         },
216         {
217                 .id = V4L2_CID_SATURATION,
218                 .type = V4L2_CTRL_TYPE_INTEGER,
219                 .name = "Saturation",
220                 .minimum = 0,
221                 .maximum = 4,
222                 .step = 1,
223                 .default_value = 2,
224         },
225         {
226                 .id = V4L2_CID_SHARPNESS,
227                 .type = V4L2_CTRL_TYPE_INTEGER,
228                 .name = "Sharpness",
229                 .minimum = 0,
230                 .maximum = 4,
231                 .step = 1,
232                 .default_value = 2,
233         },
234 };
235
236 const char **s5k4ea_ctrl_get_menu(u32 id)
237 {
238         switch (id) {
239         case V4L2_CID_WHITE_BALANCE_PRESET:
240                 return s5k4ea_querymenu_wb_preset;
241
242         case V4L2_CID_COLORFX:
243                 return s5k4ea_querymenu_effect_mode;
244
245         case V4L2_CID_EXPOSURE:
246                 return s5k4ea_querymenu_ev_bias_mode;
247
248         default:
249                 return v4l2_ctrl_get_menu(id);
250         }
251 }
252
253 static inline struct v4l2_queryctrl const *s5k4ea_find_qctrl(int id)
254 {
255         int i;
256
257         for (i = 0; i < ARRAY_SIZE(s5k4ea_controls); i++)
258                 if (s5k4ea_controls[i].id == id)
259                         return &s5k4ea_controls[i];
260
261         return NULL;
262 }
263
264 static int s5k4ea_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
265 {
266         int i;
267
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));
272                         return 0;
273                 }
274         }
275
276         return -EINVAL;
277 }
278
279 static int s5k4ea_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
280 {
281         struct v4l2_queryctrl qctrl;
282
283         qctrl.id = qm->id;
284         s5k4ea_queryctrl(sd, &qctrl);
285
286         return v4l2_ctrl_query_menu(qm, &qctrl, s5k4ea_ctrl_get_menu(qm->id));
287 }
288
289 /*
290  * Clock configuration
291  * Configure expected MCLK from host and return EINVAL if not supported clock
292  * frequency is expected
293  *      freq : in Hz
294  *      flag : not supported for now
295  */
296 static int s5k4ea_s_crystal_freq(struct v4l2_subdev *sd, u32  freq, u32 flags)
297 {
298         int err = -EINVAL;
299
300         return err;
301 }
302
303 static int s5k4ea_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
304 {
305         int err = 0;
306
307         return err;
308 }
309
310 static int s5k4ea_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
311 {
312         int err = 0;
313
314         return err;
315 }
316 static int s5k4ea_enum_framesizes(struct v4l2_subdev *sd,
317                                         struct v4l2_frmsizeenum *fsize)
318 {
319         int err = 0;
320
321         return err;
322 }
323
324 static int s5k4ea_enum_frameintervals(struct v4l2_subdev *sd,
325                                         struct v4l2_frmivalenum *fival)
326 {
327         int err = 0;
328
329         return err;
330 }
331
332 static int s5k4ea_enum_fmt(struct v4l2_subdev *sd,
333                                 struct v4l2_fmtdesc *fmtdesc)
334 {
335         int err = 0;
336
337         return err;
338 }
339
340 static int s5k4ea_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
341 {
342         int err = 0;
343
344         return err;
345 }
346
347 static int s5k4ea_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
348 {
349         int err = 0;
350
351         return err;
352 }
353
354 static int s5k4ea_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
355 {
356         int err = 0;
357
358         return err;
359 }
360
361 static int s5k4ea_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
362 {
363         struct i2c_client *client = v4l2_get_subdevdata(sd);
364         struct s5k4ea_state *state = to_state(sd);
365         struct s5k4ea_userset userset = state->userset;
366         int err = -EINVAL;
367
368         switch (ctrl->id) {
369         case V4L2_CID_EXPOSURE:
370                 ctrl->value = userset.exposure_bias;
371                 err = 0;
372                 break;
373         case V4L2_CID_AUTO_WHITE_BALANCE:
374                 ctrl->value = userset.auto_wb;
375                 err = 0;
376                 break;
377         case V4L2_CID_WHITE_BALANCE_PRESET:
378                 ctrl->value = userset.manual_wb;
379                 err = 0;
380                 break;
381         case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
382                 ctrl->value = userset.wb_temp;
383                 err = 0;
384                 break;
385         case V4L2_CID_COLORFX:
386                 ctrl->value = userset.effect;
387                 err = 0;
388                 break;
389         case V4L2_CID_CONTRAST:
390                 ctrl->value = userset.contrast;
391                 err = 0;
392                 break;
393         case V4L2_CID_SATURATION:
394                 ctrl->value = userset.saturation;
395                 err = 0;
396                 break;
397         case V4L2_CID_SHARPNESS:
398                 ctrl->value = userset.saturation;
399                 err = 0;
400                 break;
401         default:
402                 dev_err(&client->dev, "%s: no such ctrl\n", __func__);
403                 break;
404         }
405
406         return err;
407 }
408
409 static int s5k4ea_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
410 {
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;
415         int err = -EINVAL;
416
417         switch (ctrl->id) {
418         case V4L2_CID_EXPOSURE:
419                 dev_dbg(&client->dev, "%s: V4L2_CID_EXPOSURE\n", \
420                         __func__);
421                 err = s5k4ea_write_regs(sd, s5k4ea_regs_ev_bias[ctrl->value]);
422                 break;
423         case V4L2_CID_AUTO_WHITE_BALANCE:
424                 dev_dbg(&client->dev, "%s: V4L2_CID_AUTO_WHITE_BALANCE\n", \
425                         __func__);
426                 err = s5k4ea_write_regs(sd, \
427                         s5k4ea_regs_awb_enable[ctrl->value]);
428                 break;
429         case V4L2_CID_WHITE_BALANCE_PRESET:
430                 dev_dbg(&client->dev, "%s: V4L2_CID_WHITE_BALANCE_PRESET\n", \
431                         __func__);
432                 err = s5k4ea_write_regs(sd, \
433                         s5k4ea_regs_wb_preset[ctrl->value]);
434                 break;
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]);
440                 break;
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]);
445                 break;
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]);
450                 break;
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]);
455                 break;
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]);
460                 break;
461         default:
462                 dev_err(&client->dev, "%s: no such control\n", __func__);
463                 break;
464         }
465
466         if (err < 0)
467                 goto out;
468         else
469                 return 0;
470
471 out:
472         dev_dbg(&client->dev, "%s: vidioc_s_ctrl failed\n", __func__);
473         return err;
474 #else
475         return 0;
476 #endif
477 }
478
479 int
480 __s5k4ea_init_4bytes(struct v4l2_subdev *sd, unsigned char *reg[], int total)
481 {
482         struct i2c_client *client = v4l2_get_subdevdata(sd);
483         int err = -EINVAL, i;
484         unsigned char *item;
485
486         for (i = 0; i < total; i++) {
487                 item = (unsigned char *) &reg[i];
488                 if (item[0] == REG_DELAY) {
489                         mdelay(item[1]);
490                         err = 0;
491                 } else {
492                         err = s5k4ea_i2c_write(sd, item, 4);
493                 }
494
495                 if (err < 0)
496                         v4l_info(client, "%s: register set failed\n", \
497                         __func__);
498         }
499
500         return err;
501 }
502
503 static int
504 __s5k4ea_init_2bytes(struct v4l2_subdev *sd, unsigned short *reg[], int total)
505 {
506         struct i2c_client *client = v4l2_get_subdevdata(sd);
507         int err = -EINVAL, i;
508         unsigned short *item;
509
510         for (i = 0; i < total; i++) {
511                 item = (unsigned short *) &reg[i];
512                 if (item[0] == REG_DELAY) {
513                         mdelay(item[1]);
514                         err = 0;
515                 } else {
516                         err = s5k4ea_write(sd, item[0], item[1]);
517                 }
518
519                 if (err < 0)
520                         v4l_info(client, "%s: register set failed\n", \
521                         __func__);
522         }
523
524         return err;
525 }
526
527 static int s5k4ea_init(struct v4l2_subdev *sd, u32 val)
528 {
529         struct i2c_client *client = v4l2_get_subdevdata(sd);
530         int err = -EINVAL;
531
532         v4l_info(client, "%s: camera initialization start\n", __func__);
533
534         err = __s5k4ea_init_4bytes(sd, \
535                 (unsigned char **) s5k4ea_init_reg1, S5K4EA_INIT_REGS1);
536
537         err = __s5k4ea_init_2bytes(sd, \
538                 (unsigned short **) s5k4ea_init_reg2, S5K4EA_INIT_REGS2);
539
540         err = __s5k4ea_init_4bytes(sd, \
541                 (unsigned char **) s5k4ea_init_reg3, S5K4EA_INIT_REGS3);
542
543         err = __s5k4ea_init_2bytes(sd, \
544                 (unsigned short **) s5k4ea_init_reg4, S5K4EA_INIT_REGS4);
545
546         if (val == 1)
547                 err = __s5k4ea_init_4bytes(sd, \
548                         (unsigned char **) s5k4ea_init_jpeg, S5K4EA_INIT_JPEG);
549         else
550                 err = __s5k4ea_init_4bytes(sd, \
551                         (unsigned char **) s5k4ea_init_reg5, S5K4EA_INIT_REGS5);
552
553         err = __s5k4ea_init_2bytes(sd, \
554                 (unsigned short **) s5k4ea_init_reg6, S5K4EA_INIT_REGS6);
555
556         err = __s5k4ea_init_4bytes(sd, \
557                 (unsigned char **) s5k4ea_init_reg7, S5K4EA_INIT_REGS7);
558
559         err = __s5k4ea_init_2bytes(sd, \
560                 (unsigned short **) s5k4ea_init_reg8, S5K4EA_INIT_REGS8);
561
562         err = __s5k4ea_init_4bytes(sd, \
563                 (unsigned char **) s5k4ea_init_reg9, S5K4EA_INIT_REGS9);
564
565         err = __s5k4ea_init_2bytes(sd, \
566                 (unsigned short **) s5k4ea_init_reg10, S5K4EA_INIT_REGS10);
567
568         err = __s5k4ea_init_4bytes(sd, \
569                 (unsigned char **) s5k4ea_init_reg11, S5K4EA_INIT_REGS11);
570
571         if (err < 0) {
572                 v4l_err(client, "%s: camera initialization failed\n", \
573                         __func__);
574                 return -EIO;    /* FIXME */
575         }
576
577         return 0;
578 }
579
580 /*
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
586  */
587 static int s5k4ea_s_config(struct v4l2_subdev *sd, int irq, void *platform_data)
588 {
589         struct i2c_client *client = v4l2_get_subdevdata(sd);
590         struct s5k4ea_state *state = to_state(sd);
591         struct s5k4ea_platform_data *pdata;
592
593         dev_info(&client->dev, "fetching platform data\n");
594
595         pdata = client->dev.platform_data;
596
597         if (!pdata) {
598                 dev_err(&client->dev, "%s: no platform data\n", __func__);
599                 return -ENODEV;
600         }
601
602         /*
603          * Assign default format and resolution
604          * Use configured default information in platform data
605          * or without them, use default information in driver
606          */
607         if (!(pdata->default_width && pdata->default_height)) {
608                 /* TODO: assign driver default resolution */
609         } else {
610                 state->pix.width = pdata->default_width;
611                 state->pix.height = pdata->default_height;
612         }
613
614         if (!pdata->pixelformat)
615                 state->pix.pixelformat = DEFAULT_FMT;
616         else
617                 state->pix.pixelformat = pdata->pixelformat;
618
619         if (!pdata->freq)
620                 state->freq = 48000000; /* 48MHz default */
621         else
622                 state->freq = pdata->freq;
623
624         if (!pdata->is_mipi) {
625                 state->is_mipi = 0;
626                 dev_info(&client->dev, "parallel mode\n");
627         } else
628                 state->is_mipi = pdata->is_mipi;
629
630         return 0;
631 }
632
633 static int s5k4ea_sleep(struct v4l2_subdev *sd)
634 {
635         struct i2c_client *client = v4l2_get_subdevdata(sd);
636         int err = -EINVAL, i;
637
638         v4l_info(client, "%s: sleep mode\n", __func__);
639
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]);
643                         err = 0;
644                 } else {
645                         err = s5k4ea_write(sd, s5k4ea_sleep_reg[i][0], \
646                                 s5k4ea_sleep_reg[i][1]);
647                 }
648
649                 if (err < 0)
650                         v4l_info(client, "%s: register set failed\n", __func__);
651         }
652
653         if (err < 0) {
654                 v4l_err(client, "%s: sleep failed\n", __func__);
655                 return -EIO;
656         }
657
658         return 0;
659 }
660
661 static int s5k4ea_wakeup(struct v4l2_subdev *sd)
662 {
663         struct i2c_client *client = v4l2_get_subdevdata(sd);
664         int err = -EINVAL, i;
665
666         v4l_info(client, "%s: wakeup mode\n", __func__);
667
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]);
671                         err = 0;
672                 } else {
673                         err = s5k4ea_write(sd, s5k4ea_wakeup_reg[i][0], \
674                                 s5k4ea_wakeup_reg[i][1]);
675                 }
676
677                 if (err < 0)
678                         v4l_info(client, "%s: register set failed\n", __func__);
679         }
680
681         if (err < 0) {
682                 v4l_err(client, "%s: wake up failed\n", __func__);
683                 return -EIO;
684         }
685
686         return 0;
687 }
688
689 static int s5k4ea_s_stream(struct v4l2_subdev *sd, int enable)
690 {
691         return enable ? s5k4ea_wakeup(sd) : s5k4ea_sleep(sd);
692 }
693
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,
701 };
702
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,
714 };
715
716 static const struct v4l2_subdev_ops s5k4ea_ops = {
717         .core = &s5k4ea_core_ops,
718         .video = &s5k4ea_video_ops,
719 };
720
721 /*
722  * s5k4ea_probe
723  * Fetching platform data is being done with s_config subdev call.
724  * In probe routine, we just register subdev device
725  */
726 static int s5k4ea_probe(struct i2c_client *client,
727                          const struct i2c_device_id *id)
728 {
729         struct s5k4ea_state *state;
730         struct v4l2_subdev *sd;
731
732         state = kzalloc(sizeof(struct s5k4ea_state), GFP_KERNEL);
733         if (state == NULL)
734                 return -ENOMEM;
735
736         sd = &state->sd;
737         strcpy(sd->name, S5K4EA_DRIVER_NAME);
738
739         /* Registering subdev */
740         v4l2_i2c_subdev_init(sd, client, &s5k4ea_ops);
741
742         dev_info(&client->dev, "s5k4ea has been probed\n");
743         return 0;
744 }
745
746
747 static int s5k4ea_remove(struct i2c_client *client)
748 {
749         struct v4l2_subdev *sd = i2c_get_clientdata(client);
750
751         v4l2_device_unregister_subdev(sd);
752         kfree(to_state(sd));
753         return 0;
754 }
755
756 static const struct i2c_device_id s5k4ea_id[] = {
757         { S5K4EA_DRIVER_NAME, 0 },
758         { },
759 };
760 MODULE_DEVICE_TABLE(i2c, s5k4ea_id);
761
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,
767 };
768
769 MODULE_DESCRIPTION("Samsung Electronics S5K4EA SXGA camera driver");
770 MODULE_AUTHOR("Dongsoo Nathaniel Kim<dongsoo45.kim@samsung.com>");
771 MODULE_LICENSE("GPL");
772