xref: /openbmc/linux/drivers/media/i2c/ov7740.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1  // SPDX-License-Identifier: GPL-2.0
2  // Copyright (c) 2017 Microchip Corporation.
3  
4  #include <linux/clk.h>
5  #include <linux/delay.h>
6  #include <linux/gpio/consumer.h>
7  #include <linux/i2c.h>
8  #include <linux/module.h>
9  #include <linux/pm_runtime.h>
10  #include <linux/regmap.h>
11  #include <media/v4l2-ctrls.h>
12  #include <media/v4l2-event.h>
13  #include <media/v4l2-image-sizes.h>
14  #include <media/v4l2-subdev.h>
15  
16  #define REG_OUTSIZE_LSB 0x34
17  
18  /* OV7740 register tables */
19  #define REG_GAIN	0x00	/* Gain lower 8 bits (rest in vref) */
20  #define REG_BGAIN	0x01	/* blue gain */
21  #define REG_RGAIN	0x02	/* red gain */
22  #define REG_GGAIN	0x03	/* green gain */
23  #define REG_REG04	0x04	/* analog setting, don't change*/
24  #define REG_BAVG	0x05	/* b channel average */
25  #define REG_GAVG	0x06	/* g channel average */
26  #define REG_RAVG	0x07	/* r channel average */
27  
28  #define REG_REG0C	0x0C	/* filp enable */
29  #define REG0C_IMG_FLIP		0x80
30  #define REG0C_IMG_MIRROR	0x40
31  
32  #define REG_REG0E	0x0E	/* blc line */
33  #define REG_HAEC	0x0F	/* auto exposure cntrl */
34  #define REG_AEC		0x10	/* auto exposure cntrl */
35  
36  #define REG_CLK		0x11	/* Clock control */
37  #define REG_REG55	0x55	/* Clock PLL DIV/PreDiv */
38  
39  #define REG_REG12	0x12
40  
41  #define REG_REG13	0x13	/* auto/manual AGC, AEC, Write Balance*/
42  #define REG13_AEC_EN	0x01
43  #define REG13_AGC_EN	0x04
44  
45  #define REG_REG14	0x14
46  #define REG_CTRL15	0x15
47  #define REG15_GAIN_MSB	0x03
48  
49  #define REG_REG16	0x16
50  
51  #define REG_MIDH	0x1C	/* manufacture id byte */
52  #define REG_MIDL	0x1D	/* manufacture id byre */
53  #define REG_PIDH	0x0A	/* Product ID MSB */
54  #define REG_PIDL	0x0B	/* Product ID LSB */
55  
56  #define REG_84		0x84	/* lots of stuff */
57  #define REG_REG38	0x38	/* sub-addr */
58  
59  #define REG_AHSTART	0x17	/* Horiz start high bits */
60  #define REG_AHSIZE	0x18
61  #define REG_AVSTART	0x19	/* Vert start high bits */
62  #define REG_AVSIZE	0x1A
63  #define REG_PSHFT	0x1b	/* Pixel delay after HREF */
64  
65  #define REG_HOUTSIZE	0x31
66  #define REG_VOUTSIZE	0x32
67  #define REG_HVSIZEOFF	0x33
68  #define REG_REG34	0x34	/* DSP output size H/V LSB*/
69  
70  #define REG_ISP_CTRL00	0x80
71  #define ISPCTRL00_AWB_EN	0x10
72  #define ISPCTRL00_AWB_GAIN_EN	0x04
73  
74  #define	REG_YGAIN	0xE2	/* ygain for contrast control */
75  
76  #define	REG_YBRIGHT	  0xE3
77  #define	REG_SGNSET	  0xE4
78  #define	SGNSET_YBRIGHT_MASK	  0x08
79  
80  #define REG_USAT	0xDD
81  #define REG_VSAT	0xDE
82  
83  
84  struct ov7740 {
85  	struct v4l2_subdev subdev;
86  #if defined(CONFIG_MEDIA_CONTROLLER)
87  	struct media_pad pad;
88  #endif
89  	struct v4l2_mbus_framefmt format;
90  	const struct ov7740_pixfmt *fmt;  /* Current format */
91  	const struct ov7740_framesize *frmsize;
92  	struct regmap *regmap;
93  	struct clk *xvclk;
94  	struct v4l2_ctrl_handler ctrl_handler;
95  	struct {
96  		/* gain cluster */
97  		struct v4l2_ctrl *auto_gain;
98  		struct v4l2_ctrl *gain;
99  	};
100  	struct {
101  		struct v4l2_ctrl *auto_wb;
102  		struct v4l2_ctrl *blue_balance;
103  		struct v4l2_ctrl *red_balance;
104  	};
105  	struct {
106  		struct v4l2_ctrl *hflip;
107  		struct v4l2_ctrl *vflip;
108  	};
109  	struct {
110  		/* exposure cluster */
111  		struct v4l2_ctrl *auto_exposure;
112  		struct v4l2_ctrl *exposure;
113  	};
114  	struct {
115  		/* saturation/hue cluster */
116  		struct v4l2_ctrl *saturation;
117  		struct v4l2_ctrl *hue;
118  	};
119  	struct v4l2_ctrl *brightness;
120  	struct v4l2_ctrl *contrast;
121  
122  	struct mutex mutex;	/* To serialize asynchronus callbacks */
123  	bool streaming;		/* Streaming on/off */
124  
125  	struct gpio_desc *resetb_gpio;
126  	struct gpio_desc *pwdn_gpio;
127  };
128  
129  struct ov7740_pixfmt {
130  	u32 mbus_code;
131  	enum v4l2_colorspace colorspace;
132  	const struct reg_sequence *regs;
133  	u32 reg_num;
134  };
135  
136  struct ov7740_framesize {
137  	u16 width;
138  	u16 height;
139  	const struct reg_sequence *regs;
140  	u32 reg_num;
141  };
142  
143  static const struct reg_sequence ov7740_vga[] = {
144  	{0x55, 0x40},
145  	{0x11, 0x02},
146  
147  	{0xd5, 0x10},
148  	{0x0c, 0x12},
149  	{0x0d, 0x34},
150  	{0x17, 0x25},
151  	{0x18, 0xa0},
152  	{0x19, 0x03},
153  	{0x1a, 0xf0},
154  	{0x1b, 0x89},
155  	{0x22, 0x03},
156  	{0x29, 0x18},
157  	{0x2b, 0xf8},
158  	{0x2c, 0x01},
159  	{REG_HOUTSIZE, 0xa0},
160  	{REG_VOUTSIZE, 0xf0},
161  	{0x33, 0xc4},
162  	{REG_OUTSIZE_LSB, 0x0},
163  	{0x35, 0x05},
164  	{0x04, 0x60},
165  	{0x27, 0x80},
166  	{0x3d, 0x0f},
167  	{0x3e, 0x80},
168  	{0x3f, 0x40},
169  	{0x40, 0x7f},
170  	{0x41, 0x6a},
171  	{0x42, 0x29},
172  	{0x44, 0x22},
173  	{0x45, 0x41},
174  	{0x47, 0x02},
175  	{0x49, 0x64},
176  	{0x4a, 0xa1},
177  	{0x4b, 0x40},
178  	{0x4c, 0x1a},
179  	{0x4d, 0x50},
180  	{0x4e, 0x13},
181  	{0x64, 0x00},
182  	{0x67, 0x88},
183  	{0x68, 0x1a},
184  
185  	{0x14, 0x28},
186  	{0x24, 0x3c},
187  	{0x25, 0x30},
188  	{0x26, 0x72},
189  	{0x50, 0x97},
190  	{0x51, 0x1f},
191  	{0x52, 0x00},
192  	{0x53, 0x00},
193  	{0x20, 0x00},
194  	{0x21, 0xcf},
195  	{0x50, 0x4b},
196  	{0x38, 0x14},
197  	{0xe9, 0x00},
198  	{0x56, 0x55},
199  	{0x57, 0xff},
200  	{0x58, 0xff},
201  	{0x59, 0xff},
202  	{0x5f, 0x04},
203  	{0xec, 0x00},
204  	{0x13, 0xff},
205  
206  	{0x81, 0x3f},
207  	{0x82, 0x32},
208  	{0x38, 0x11},
209  	{0x84, 0x70},
210  	{0x85, 0x00},
211  	{0x86, 0x03},
212  	{0x87, 0x01},
213  	{0x88, 0x05},
214  	{0x89, 0x30},
215  	{0x8d, 0x30},
216  	{0x8f, 0x85},
217  	{0x93, 0x30},
218  	{0x95, 0x85},
219  	{0x99, 0x30},
220  	{0x9b, 0x85},
221  
222  	{0x9c, 0x08},
223  	{0x9d, 0x12},
224  	{0x9e, 0x23},
225  	{0x9f, 0x45},
226  	{0xa0, 0x55},
227  	{0xa1, 0x64},
228  	{0xa2, 0x72},
229  	{0xa3, 0x7f},
230  	{0xa4, 0x8b},
231  	{0xa5, 0x95},
232  	{0xa6, 0xa7},
233  	{0xa7, 0xb5},
234  	{0xa8, 0xcb},
235  	{0xa9, 0xdd},
236  	{0xaa, 0xec},
237  	{0xab, 0x1a},
238  
239  	{0xce, 0x78},
240  	{0xcf, 0x6e},
241  	{0xd0, 0x0a},
242  	{0xd1, 0x0c},
243  	{0xd2, 0x84},
244  	{0xd3, 0x90},
245  	{0xd4, 0x1e},
246  
247  	{0x5a, 0x24},
248  	{0x5b, 0x1f},
249  	{0x5c, 0x88},
250  	{0x5d, 0x60},
251  
252  	{0xac, 0x6e},
253  	{0xbe, 0xff},
254  	{0xbf, 0x00},
255  
256  	{0x0f, 0x1d},
257  	{0x0f, 0x1f},
258  };
259  
260  static const struct ov7740_framesize ov7740_framesizes[] = {
261  	{
262  		.width		= VGA_WIDTH,
263  		.height		= VGA_HEIGHT,
264  		.regs		= ov7740_vga,
265  		.reg_num	= ARRAY_SIZE(ov7740_vga),
266  	},
267  };
268  
269  #ifdef CONFIG_VIDEO_ADV_DEBUG
ov7740_get_register(struct v4l2_subdev * sd,struct v4l2_dbg_register * reg)270  static int ov7740_get_register(struct v4l2_subdev *sd,
271  			       struct v4l2_dbg_register *reg)
272  {
273  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
274  	struct regmap *regmap = ov7740->regmap;
275  	unsigned int val = 0;
276  	int ret;
277  
278  	ret = regmap_read(regmap, reg->reg & 0xff, &val);
279  	reg->val = val;
280  	reg->size = 1;
281  
282  	return ret;
283  }
284  
ov7740_set_register(struct v4l2_subdev * sd,const struct v4l2_dbg_register * reg)285  static int ov7740_set_register(struct v4l2_subdev *sd,
286  			       const struct v4l2_dbg_register *reg)
287  {
288  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
289  	struct regmap *regmap = ov7740->regmap;
290  
291  	regmap_write(regmap, reg->reg & 0xff, reg->val & 0xff);
292  
293  	return 0;
294  }
295  #endif
296  
ov7740_set_power(struct ov7740 * ov7740,int on)297  static int ov7740_set_power(struct ov7740 *ov7740, int on)
298  {
299  	int ret;
300  
301  	if (on) {
302  		ret = clk_prepare_enable(ov7740->xvclk);
303  		if (ret)
304  			return ret;
305  
306  		if (ov7740->pwdn_gpio)
307  			gpiod_direction_output(ov7740->pwdn_gpio, 0);
308  
309  		if (ov7740->resetb_gpio) {
310  			gpiod_set_value(ov7740->resetb_gpio, 1);
311  			usleep_range(500, 1000);
312  			gpiod_set_value(ov7740->resetb_gpio, 0);
313  			usleep_range(3000, 5000);
314  		}
315  	} else {
316  		clk_disable_unprepare(ov7740->xvclk);
317  
318  		if (ov7740->pwdn_gpio)
319  			gpiod_direction_output(ov7740->pwdn_gpio, 0);
320  	}
321  
322  	return 0;
323  }
324  
325  static const struct v4l2_subdev_core_ops ov7740_subdev_core_ops = {
326  	.log_status = v4l2_ctrl_subdev_log_status,
327  #ifdef CONFIG_VIDEO_ADV_DEBUG
328  	.g_register = ov7740_get_register,
329  	.s_register = ov7740_set_register,
330  #endif
331  	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
332  	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
333  };
334  
ov7740_set_white_balance(struct ov7740 * ov7740,int awb)335  static int ov7740_set_white_balance(struct ov7740 *ov7740, int awb)
336  {
337  	struct regmap *regmap = ov7740->regmap;
338  	unsigned int value;
339  	int ret;
340  
341  	ret = regmap_read(regmap, REG_ISP_CTRL00, &value);
342  	if (!ret) {
343  		if (awb)
344  			value |= (ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
345  		else
346  			value &= ~(ISPCTRL00_AWB_EN | ISPCTRL00_AWB_GAIN_EN);
347  		ret = regmap_write(regmap, REG_ISP_CTRL00, value);
348  		if (ret)
349  			return ret;
350  	}
351  
352  	if (!awb) {
353  		ret = regmap_write(regmap, REG_BGAIN,
354  				   ov7740->blue_balance->val);
355  		if (ret)
356  			return ret;
357  
358  		ret = regmap_write(regmap, REG_RGAIN, ov7740->red_balance->val);
359  		if (ret)
360  			return ret;
361  	}
362  
363  	return 0;
364  }
365  
ov7740_set_saturation(struct regmap * regmap,int value)366  static int ov7740_set_saturation(struct regmap *regmap, int value)
367  {
368  	int ret;
369  
370  	ret = regmap_write(regmap, REG_USAT, (unsigned char)value);
371  	if (ret)
372  		return ret;
373  
374  	return regmap_write(regmap, REG_VSAT, (unsigned char)value);
375  }
376  
ov7740_set_gain(struct regmap * regmap,int value)377  static int ov7740_set_gain(struct regmap *regmap, int value)
378  {
379  	int ret;
380  
381  	ret = regmap_write(regmap, REG_GAIN, value & 0xff);
382  	if (ret)
383  		return ret;
384  
385  	ret = regmap_update_bits(regmap, REG_CTRL15,
386  				 REG15_GAIN_MSB, (value >> 8) & 0x3);
387  	if (!ret)
388  		ret = regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
389  
390  	return ret;
391  }
392  
ov7740_set_autogain(struct regmap * regmap,int value)393  static int ov7740_set_autogain(struct regmap *regmap, int value)
394  {
395  	unsigned int reg;
396  	int ret;
397  
398  	ret = regmap_read(regmap, REG_REG13, &reg);
399  	if (ret)
400  		return ret;
401  	if (value)
402  		reg |= REG13_AGC_EN;
403  	else
404  		reg &= ~REG13_AGC_EN;
405  	return regmap_write(regmap, REG_REG13, reg);
406  }
407  
ov7740_set_brightness(struct regmap * regmap,int value)408  static int ov7740_set_brightness(struct regmap *regmap, int value)
409  {
410  	/* Turn off AEC/AGC */
411  	regmap_update_bits(regmap, REG_REG13, REG13_AEC_EN, 0);
412  	regmap_update_bits(regmap, REG_REG13, REG13_AGC_EN, 0);
413  
414  	if (value >= 0) {
415  		regmap_write(regmap, REG_YBRIGHT, (unsigned char)value);
416  		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 0);
417  	} else{
418  		regmap_write(regmap, REG_YBRIGHT, (unsigned char)(-value));
419  		regmap_update_bits(regmap, REG_SGNSET, SGNSET_YBRIGHT_MASK, 1);
420  	}
421  
422  	return 0;
423  }
424  
ov7740_set_contrast(struct regmap * regmap,int value)425  static int ov7740_set_contrast(struct regmap *regmap, int value)
426  {
427  	return regmap_write(regmap, REG_YGAIN, (unsigned char)value);
428  }
429  
ov7740_get_gain(struct ov7740 * ov7740,struct v4l2_ctrl * ctrl)430  static int ov7740_get_gain(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
431  {
432  	struct regmap *regmap = ov7740->regmap;
433  	unsigned int value0, value1;
434  	int ret;
435  
436  	if (!ctrl->val)
437  		return 0;
438  
439  	ret = regmap_read(regmap, REG_GAIN, &value0);
440  	if (ret)
441  		return ret;
442  	ret = regmap_read(regmap, REG_CTRL15, &value1);
443  	if (ret)
444  		return ret;
445  
446  	ov7740->gain->val = (value1 << 8) | (value0 & 0xff);
447  
448  	return 0;
449  }
450  
ov7740_get_exp(struct ov7740 * ov7740,struct v4l2_ctrl * ctrl)451  static int ov7740_get_exp(struct ov7740 *ov7740, struct v4l2_ctrl *ctrl)
452  {
453  	struct regmap *regmap = ov7740->regmap;
454  	unsigned int value0, value1;
455  	int ret;
456  
457  	if (ctrl->val == V4L2_EXPOSURE_MANUAL)
458  		return 0;
459  
460  	ret = regmap_read(regmap, REG_AEC, &value0);
461  	if (ret)
462  		return ret;
463  	ret = regmap_read(regmap, REG_HAEC, &value1);
464  	if (ret)
465  		return ret;
466  
467  	ov7740->exposure->val = (value1 << 8) | (value0 & 0xff);
468  
469  	return 0;
470  }
471  
ov7740_set_exp(struct regmap * regmap,int value)472  static int ov7740_set_exp(struct regmap *regmap, int value)
473  {
474  	int ret;
475  
476  	/* Turn off AEC/AGC */
477  	ret = regmap_update_bits(regmap, REG_REG13,
478  				 REG13_AEC_EN | REG13_AGC_EN, 0);
479  	if (ret)
480  		return ret;
481  
482  	ret = regmap_write(regmap, REG_AEC, (unsigned char)value);
483  	if (ret)
484  		return ret;
485  
486  	return regmap_write(regmap, REG_HAEC, (unsigned char)(value >> 8));
487  }
488  
ov7740_set_autoexp(struct regmap * regmap,enum v4l2_exposure_auto_type value)489  static int ov7740_set_autoexp(struct regmap *regmap,
490  			      enum v4l2_exposure_auto_type value)
491  {
492  	unsigned int reg;
493  	int ret;
494  
495  	ret = regmap_read(regmap, REG_REG13, &reg);
496  	if (!ret) {
497  		if (value == V4L2_EXPOSURE_AUTO)
498  			reg |= (REG13_AEC_EN | REG13_AGC_EN);
499  		else
500  			reg &= ~(REG13_AEC_EN | REG13_AGC_EN);
501  		ret = regmap_write(regmap, REG_REG13, reg);
502  	}
503  
504  	return ret;
505  }
506  
507  
ov7740_get_volatile_ctrl(struct v4l2_ctrl * ctrl)508  static int ov7740_get_volatile_ctrl(struct v4l2_ctrl *ctrl)
509  {
510  	struct ov7740 *ov7740 = container_of(ctrl->handler,
511  					     struct ov7740, ctrl_handler);
512  	int ret;
513  
514  	switch (ctrl->id) {
515  	case V4L2_CID_AUTOGAIN:
516  		ret = ov7740_get_gain(ov7740, ctrl);
517  		break;
518  	case V4L2_CID_EXPOSURE_AUTO:
519  		ret = ov7740_get_exp(ov7740, ctrl);
520  		break;
521  	default:
522  		ret = -EINVAL;
523  		break;
524  	}
525  	return ret;
526  }
527  
ov7740_set_ctrl(struct v4l2_ctrl * ctrl)528  static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
529  {
530  	struct ov7740 *ov7740 = container_of(ctrl->handler,
531  					     struct ov7740, ctrl_handler);
532  	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
533  	struct regmap *regmap = ov7740->regmap;
534  	int ret;
535  	u8 val;
536  
537  	if (!pm_runtime_get_if_in_use(&client->dev))
538  		return 0;
539  
540  	switch (ctrl->id) {
541  	case V4L2_CID_AUTO_WHITE_BALANCE:
542  		ret = ov7740_set_white_balance(ov7740, ctrl->val);
543  		break;
544  	case V4L2_CID_SATURATION:
545  		ret = ov7740_set_saturation(regmap, ctrl->val);
546  		break;
547  	case V4L2_CID_BRIGHTNESS:
548  		ret = ov7740_set_brightness(regmap, ctrl->val);
549  		break;
550  	case V4L2_CID_CONTRAST:
551  		ret = ov7740_set_contrast(regmap, ctrl->val);
552  		break;
553  	case V4L2_CID_VFLIP:
554  		val = ctrl->val ? REG0C_IMG_FLIP : 0x00;
555  		ret = regmap_update_bits(regmap, REG_REG0C,
556  					 REG0C_IMG_FLIP, val);
557  		break;
558  	case V4L2_CID_HFLIP:
559  		val = ctrl->val ? REG0C_IMG_MIRROR : 0x00;
560  		ret = regmap_update_bits(regmap, REG_REG0C,
561  					 REG0C_IMG_MIRROR, val);
562  		break;
563  	case V4L2_CID_AUTOGAIN:
564  		if (!ctrl->val)
565  			ret = ov7740_set_gain(regmap, ov7740->gain->val);
566  		else
567  			ret = ov7740_set_autogain(regmap, ctrl->val);
568  		break;
569  
570  	case V4L2_CID_EXPOSURE_AUTO:
571  		if (ctrl->val == V4L2_EXPOSURE_MANUAL)
572  			ret = ov7740_set_exp(regmap, ov7740->exposure->val);
573  		else
574  			ret = ov7740_set_autoexp(regmap, ctrl->val);
575  		break;
576  	default:
577  		ret = -EINVAL;
578  		break;
579  	}
580  
581  	pm_runtime_put(&client->dev);
582  
583  	return ret;
584  }
585  
586  static const struct v4l2_ctrl_ops ov7740_ctrl_ops = {
587  	.g_volatile_ctrl = ov7740_get_volatile_ctrl,
588  	.s_ctrl = ov7740_set_ctrl,
589  };
590  
ov7740_start_streaming(struct ov7740 * ov7740)591  static int ov7740_start_streaming(struct ov7740 *ov7740)
592  {
593  	int ret;
594  
595  	if (ov7740->fmt) {
596  		ret = regmap_multi_reg_write(ov7740->regmap,
597  					     ov7740->fmt->regs,
598  					     ov7740->fmt->reg_num);
599  		if (ret)
600  			return ret;
601  	}
602  
603  	if (ov7740->frmsize) {
604  		ret = regmap_multi_reg_write(ov7740->regmap,
605  					     ov7740->frmsize->regs,
606  					     ov7740->frmsize->reg_num);
607  		if (ret)
608  			return ret;
609  	}
610  
611  	return __v4l2_ctrl_handler_setup(ov7740->subdev.ctrl_handler);
612  }
613  
ov7740_set_stream(struct v4l2_subdev * sd,int enable)614  static int ov7740_set_stream(struct v4l2_subdev *sd, int enable)
615  {
616  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
617  	struct i2c_client *client = v4l2_get_subdevdata(sd);
618  	int ret = 0;
619  
620  	mutex_lock(&ov7740->mutex);
621  	if (ov7740->streaming == enable) {
622  		mutex_unlock(&ov7740->mutex);
623  		return 0;
624  	}
625  
626  	if (enable) {
627  		ret = pm_runtime_resume_and_get(&client->dev);
628  		if (ret < 0)
629  			goto err_unlock;
630  
631  		ret = ov7740_start_streaming(ov7740);
632  		if (ret)
633  			goto err_rpm_put;
634  	} else {
635  		pm_runtime_put(&client->dev);
636  	}
637  
638  	ov7740->streaming = enable;
639  
640  	mutex_unlock(&ov7740->mutex);
641  	return ret;
642  
643  err_rpm_put:
644  	pm_runtime_put(&client->dev);
645  err_unlock:
646  	mutex_unlock(&ov7740->mutex);
647  	return ret;
648  }
649  
ov7740_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * ival)650  static int ov7740_g_frame_interval(struct v4l2_subdev *sd,
651  				   struct v4l2_subdev_frame_interval *ival)
652  {
653  	struct v4l2_fract *tpf = &ival->interval;
654  
655  
656  	tpf->numerator = 1;
657  	tpf->denominator = 60;
658  
659  	return 0;
660  }
661  
ov7740_s_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * ival)662  static int ov7740_s_frame_interval(struct v4l2_subdev *sd,
663  				   struct v4l2_subdev_frame_interval *ival)
664  {
665  	struct v4l2_fract *tpf = &ival->interval;
666  
667  
668  	tpf->numerator = 1;
669  	tpf->denominator = 60;
670  
671  	return 0;
672  }
673  
674  static const struct v4l2_subdev_video_ops ov7740_subdev_video_ops = {
675  	.s_stream = ov7740_set_stream,
676  	.s_frame_interval = ov7740_s_frame_interval,
677  	.g_frame_interval = ov7740_g_frame_interval,
678  };
679  
680  static const struct reg_sequence ov7740_format_yuyv[] = {
681  	{0x12, 0x00},
682  	{0x36, 0x3f},
683  	{0x80, 0x7f},
684  	{0x83, 0x01},
685  };
686  
687  static const struct reg_sequence ov7740_format_bggr8[] = {
688  	{0x36, 0x2f},
689  	{0x80, 0x01},
690  	{0x83, 0x04},
691  };
692  
693  static const struct ov7740_pixfmt ov7740_formats[] = {
694  	{
695  		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
696  		.colorspace = V4L2_COLORSPACE_SRGB,
697  		.regs = ov7740_format_yuyv,
698  		.reg_num = ARRAY_SIZE(ov7740_format_yuyv),
699  	},
700  	{
701  		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
702  		.colorspace = V4L2_COLORSPACE_SRGB,
703  		.regs = ov7740_format_bggr8,
704  		.reg_num = ARRAY_SIZE(ov7740_format_bggr8),
705  	}
706  };
707  #define N_OV7740_FMTS ARRAY_SIZE(ov7740_formats)
708  
ov7740_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)709  static int ov7740_enum_mbus_code(struct v4l2_subdev *sd,
710  				 struct v4l2_subdev_state *sd_state,
711  				 struct v4l2_subdev_mbus_code_enum *code)
712  {
713  	if (code->pad || code->index >= N_OV7740_FMTS)
714  		return -EINVAL;
715  
716  	code->code = ov7740_formats[code->index].mbus_code;
717  
718  	return 0;
719  }
720  
ov7740_enum_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_interval_enum * fie)721  static int ov7740_enum_frame_interval(struct v4l2_subdev *sd,
722  				struct v4l2_subdev_state *sd_state,
723  				struct v4l2_subdev_frame_interval_enum *fie)
724  {
725  	if (fie->pad)
726  		return -EINVAL;
727  
728  	if (fie->index >= 1)
729  		return -EINVAL;
730  
731  	if ((fie->width != VGA_WIDTH) || (fie->height != VGA_HEIGHT))
732  		return -EINVAL;
733  
734  	fie->interval.numerator = 1;
735  	fie->interval.denominator = 60;
736  
737  	return 0;
738  }
739  
ov7740_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)740  static int ov7740_enum_frame_size(struct v4l2_subdev *sd,
741  				  struct v4l2_subdev_state *sd_state,
742  				  struct v4l2_subdev_frame_size_enum *fse)
743  {
744  	if (fse->pad)
745  		return -EINVAL;
746  
747  	if (fse->index > 0)
748  		return -EINVAL;
749  
750  	fse->min_width = fse->max_width = VGA_WIDTH;
751  	fse->min_height = fse->max_height = VGA_HEIGHT;
752  
753  	return 0;
754  }
755  
ov7740_try_fmt_internal(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * fmt,const struct ov7740_pixfmt ** ret_fmt,const struct ov7740_framesize ** ret_frmsize)756  static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
757  				   struct v4l2_mbus_framefmt *fmt,
758  				   const struct ov7740_pixfmt **ret_fmt,
759  				   const struct ov7740_framesize **ret_frmsize)
760  {
761  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
762  	const struct ov7740_framesize *fsize = &ov7740_framesizes[0];
763  	int index, i;
764  
765  	for (index = 0; index < N_OV7740_FMTS; index++) {
766  		if (ov7740_formats[index].mbus_code == fmt->code)
767  			break;
768  	}
769  	if (index >= N_OV7740_FMTS) {
770  		/* default to first format */
771  		index = 0;
772  		fmt->code = ov7740_formats[0].mbus_code;
773  	}
774  	if (ret_fmt != NULL)
775  		*ret_fmt = ov7740_formats + index;
776  
777  	for (i = 0; i < ARRAY_SIZE(ov7740_framesizes); i++) {
778  		if ((fsize->width >= fmt->width) &&
779  		    (fsize->height >= fmt->height)) {
780  			fmt->width = fsize->width;
781  			fmt->height = fsize->height;
782  			break;
783  		}
784  
785  		fsize++;
786  	}
787  	if (i >= ARRAY_SIZE(ov7740_framesizes)) {
788  		fsize = &ov7740_framesizes[0];
789  		fmt->width = fsize->width;
790  		fmt->height = fsize->height;
791  	}
792  	if (ret_frmsize != NULL)
793  		*ret_frmsize = fsize;
794  
795  	fmt->field = V4L2_FIELD_NONE;
796  	fmt->colorspace = ov7740_formats[index].colorspace;
797  
798  	ov7740->format = *fmt;
799  
800  	return 0;
801  }
802  
ov7740_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)803  static int ov7740_set_fmt(struct v4l2_subdev *sd,
804  			  struct v4l2_subdev_state *sd_state,
805  			  struct v4l2_subdev_format *format)
806  {
807  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
808  	const struct ov7740_pixfmt *ovfmt;
809  	const struct ov7740_framesize *fsize;
810  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
811  	struct v4l2_mbus_framefmt *mbus_fmt;
812  #endif
813  	int ret;
814  
815  	mutex_lock(&ov7740->mutex);
816  	if (format->pad) {
817  		ret = -EINVAL;
818  		goto error;
819  	}
820  
821  	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
822  		ret = ov7740_try_fmt_internal(sd, &format->format, NULL, NULL);
823  		if (ret)
824  			goto error;
825  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
826  		mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state,
827  						      format->pad);
828  		*mbus_fmt = format->format;
829  #endif
830  		mutex_unlock(&ov7740->mutex);
831  		return 0;
832  	}
833  
834  	ret = ov7740_try_fmt_internal(sd, &format->format, &ovfmt, &fsize);
835  	if (ret)
836  		goto error;
837  
838  	ov7740->fmt = ovfmt;
839  	ov7740->frmsize = fsize;
840  
841  	mutex_unlock(&ov7740->mutex);
842  	return 0;
843  
844  error:
845  	mutex_unlock(&ov7740->mutex);
846  	return ret;
847  }
848  
ov7740_get_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * format)849  static int ov7740_get_fmt(struct v4l2_subdev *sd,
850  			  struct v4l2_subdev_state *sd_state,
851  			  struct v4l2_subdev_format *format)
852  {
853  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
854  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
855  	struct v4l2_mbus_framefmt *mbus_fmt;
856  #endif
857  	int ret = 0;
858  
859  	mutex_lock(&ov7740->mutex);
860  	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
861  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
862  		mbus_fmt = v4l2_subdev_get_try_format(sd, sd_state, 0);
863  		format->format = *mbus_fmt;
864  		ret = 0;
865  #else
866  		ret = -EINVAL;
867  #endif
868  	} else {
869  		format->format = ov7740->format;
870  	}
871  	mutex_unlock(&ov7740->mutex);
872  
873  	return ret;
874  }
875  
876  static const struct v4l2_subdev_pad_ops ov7740_subdev_pad_ops = {
877  	.enum_frame_interval = ov7740_enum_frame_interval,
878  	.enum_frame_size = ov7740_enum_frame_size,
879  	.enum_mbus_code = ov7740_enum_mbus_code,
880  	.get_fmt = ov7740_get_fmt,
881  	.set_fmt = ov7740_set_fmt,
882  };
883  
884  static const struct v4l2_subdev_ops ov7740_subdev_ops = {
885  	.core	= &ov7740_subdev_core_ops,
886  	.video	= &ov7740_subdev_video_ops,
887  	.pad	= &ov7740_subdev_pad_ops,
888  };
889  
ov7740_get_default_format(struct v4l2_subdev * sd,struct v4l2_mbus_framefmt * format)890  static void ov7740_get_default_format(struct v4l2_subdev *sd,
891  				      struct v4l2_mbus_framefmt *format)
892  {
893  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
894  
895  	format->width = ov7740->frmsize->width;
896  	format->height = ov7740->frmsize->height;
897  	format->colorspace = ov7740->fmt->colorspace;
898  	format->code = ov7740->fmt->mbus_code;
899  	format->field = V4L2_FIELD_NONE;
900  }
901  
902  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
ov7740_open(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)903  static int ov7740_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
904  {
905  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
906  	struct v4l2_mbus_framefmt *format =
907  				v4l2_subdev_get_try_format(sd, fh->state, 0);
908  
909  	mutex_lock(&ov7740->mutex);
910  	ov7740_get_default_format(sd, format);
911  	mutex_unlock(&ov7740->mutex);
912  
913  	return 0;
914  }
915  
916  static const struct v4l2_subdev_internal_ops ov7740_subdev_internal_ops = {
917  	.open = ov7740_open,
918  };
919  #endif
920  
ov7740_probe_dt(struct i2c_client * client,struct ov7740 * ov7740)921  static int ov7740_probe_dt(struct i2c_client *client,
922  			   struct ov7740 *ov7740)
923  {
924  	ov7740->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
925  			GPIOD_OUT_HIGH);
926  	if (IS_ERR(ov7740->resetb_gpio)) {
927  		dev_info(&client->dev, "can't get %s GPIO\n", "reset");
928  		return PTR_ERR(ov7740->resetb_gpio);
929  	}
930  
931  	ov7740->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
932  			GPIOD_OUT_LOW);
933  	if (IS_ERR(ov7740->pwdn_gpio)) {
934  		dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
935  		return PTR_ERR(ov7740->pwdn_gpio);
936  	}
937  
938  	return 0;
939  }
940  
ov7740_detect(struct ov7740 * ov7740)941  static int ov7740_detect(struct ov7740 *ov7740)
942  {
943  	struct regmap *regmap = ov7740->regmap;
944  	unsigned int midh, midl, pidh, pidl;
945  	int ret;
946  
947  	ret = regmap_read(regmap, REG_MIDH, &midh);
948  	if (ret)
949  		return ret;
950  	if (midh != 0x7f)
951  		return -ENODEV;
952  
953  	ret = regmap_read(regmap, REG_MIDL, &midl);
954  	if (ret)
955  		return ret;
956  	if (midl != 0xa2)
957  		return -ENODEV;
958  
959  	ret = regmap_read(regmap, REG_PIDH, &pidh);
960  	if (ret)
961  		return ret;
962  	if (pidh != 0x77)
963  		return -ENODEV;
964  
965  	ret = regmap_read(regmap, REG_PIDL, &pidl);
966  	if (ret)
967  		return ret;
968  	if ((pidl != 0x40) && (pidl != 0x41) && (pidl != 0x42))
969  		return -ENODEV;
970  
971  	return 0;
972  }
973  
ov7740_init_controls(struct ov7740 * ov7740)974  static int ov7740_init_controls(struct ov7740 *ov7740)
975  {
976  	struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
977  	struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
978  	int ret;
979  
980  	ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
981  	if (ret < 0)
982  		return ret;
983  
984  	ctrl_hdlr->lock = &ov7740->mutex;
985  	ov7740->auto_wb = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
986  					  V4L2_CID_AUTO_WHITE_BALANCE,
987  					  0, 1, 1, 1);
988  	ov7740->blue_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
989  					       V4L2_CID_BLUE_BALANCE,
990  					       0, 0xff, 1, 0x80);
991  	ov7740->red_balance = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
992  					      V4L2_CID_RED_BALANCE,
993  					      0, 0xff, 1, 0x80);
994  
995  	ov7740->brightness = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
996  					     V4L2_CID_BRIGHTNESS,
997  					     -255, 255, 1, 0);
998  	ov7740->contrast = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
999  					   V4L2_CID_CONTRAST,
1000  					   0, 127, 1, 0x20);
1001  	ov7740->saturation = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1002  			  V4L2_CID_SATURATION, 0, 256, 1, 0x80);
1003  	ov7740->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1004  					V4L2_CID_HFLIP, 0, 1, 1, 0);
1005  	ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1006  					V4L2_CID_VFLIP, 0, 1, 1, 0);
1007  
1008  	ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1009  				       V4L2_CID_GAIN, 0, 1023, 1, 500);
1010  
1011  	ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1012  					    V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1013  
1014  	ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
1015  					   V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
1016  
1017  	ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
1018  					&ov7740_ctrl_ops,
1019  					V4L2_CID_EXPOSURE_AUTO,
1020  					V4L2_EXPOSURE_MANUAL, 0,
1021  					V4L2_EXPOSURE_AUTO);
1022  
1023  	v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
1024  	v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
1025  	v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
1026  			       V4L2_EXPOSURE_MANUAL, true);
1027  
1028  	if (ctrl_hdlr->error) {
1029  		ret = ctrl_hdlr->error;
1030  		dev_err(&client->dev, "controls initialisation failed (%d)\n",
1031  			ret);
1032  		goto error;
1033  	}
1034  
1035  	ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
1036  	if (ret) {
1037  		dev_err(&client->dev, "%s control init failed (%d)\n",
1038  			__func__, ret);
1039  		goto error;
1040  	}
1041  
1042  	ov7740->subdev.ctrl_handler = ctrl_hdlr;
1043  	return 0;
1044  
1045  error:
1046  	v4l2_ctrl_handler_free(ctrl_hdlr);
1047  	mutex_destroy(&ov7740->mutex);
1048  	return ret;
1049  }
1050  
ov7740_free_controls(struct ov7740 * ov7740)1051  static void ov7740_free_controls(struct ov7740 *ov7740)
1052  {
1053  	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1054  	mutex_destroy(&ov7740->mutex);
1055  }
1056  
1057  #define OV7740_MAX_REGISTER     0xff
1058  static const struct regmap_config ov7740_regmap_config = {
1059  	.reg_bits	= 8,
1060  	.val_bits	= 8,
1061  	.max_register	= OV7740_MAX_REGISTER,
1062  };
1063  
ov7740_probe(struct i2c_client * client)1064  static int ov7740_probe(struct i2c_client *client)
1065  {
1066  	struct ov7740 *ov7740;
1067  	struct v4l2_subdev *sd;
1068  	int ret;
1069  
1070  	ov7740 = devm_kzalloc(&client->dev, sizeof(*ov7740), GFP_KERNEL);
1071  	if (!ov7740)
1072  		return -ENOMEM;
1073  
1074  	ov7740->xvclk = devm_clk_get(&client->dev, "xvclk");
1075  	if (IS_ERR(ov7740->xvclk)) {
1076  		ret = PTR_ERR(ov7740->xvclk);
1077  		dev_err(&client->dev,
1078  			"OV7740: fail to get xvclk: %d\n", ret);
1079  		return ret;
1080  	}
1081  
1082  	ret = ov7740_probe_dt(client, ov7740);
1083  	if (ret)
1084  		return ret;
1085  
1086  	ov7740->regmap = devm_regmap_init_sccb(client, &ov7740_regmap_config);
1087  	if (IS_ERR(ov7740->regmap)) {
1088  		ret = PTR_ERR(ov7740->regmap);
1089  		dev_err(&client->dev, "Failed to allocate register map: %d\n",
1090  			ret);
1091  		return ret;
1092  	}
1093  
1094  	sd = &ov7740->subdev;
1095  	v4l2_i2c_subdev_init(sd, client, &ov7740_subdev_ops);
1096  
1097  #ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
1098  	sd->internal_ops = &ov7740_subdev_internal_ops;
1099  	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
1100  #endif
1101  
1102  #if defined(CONFIG_MEDIA_CONTROLLER)
1103  	ov7740->pad.flags = MEDIA_PAD_FL_SOURCE;
1104  	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
1105  	ret = media_entity_pads_init(&sd->entity, 1, &ov7740->pad);
1106  	if (ret)
1107  		return ret;
1108  #endif
1109  
1110  	ret = ov7740_set_power(ov7740, 1);
1111  	if (ret)
1112  		return ret;
1113  
1114  	pm_runtime_set_active(&client->dev);
1115  	pm_runtime_enable(&client->dev);
1116  
1117  	ret = ov7740_detect(ov7740);
1118  	if (ret)
1119  		goto error_detect;
1120  
1121  	mutex_init(&ov7740->mutex);
1122  
1123  	ret = ov7740_init_controls(ov7740);
1124  	if (ret)
1125  		goto error_init_controls;
1126  
1127  	v4l_info(client, "chip found @ 0x%02x (%s)\n",
1128  			client->addr << 1, client->adapter->name);
1129  
1130  	ov7740->fmt = &ov7740_formats[0];
1131  	ov7740->frmsize = &ov7740_framesizes[0];
1132  
1133  	ov7740_get_default_format(sd, &ov7740->format);
1134  
1135  	ret = v4l2_async_register_subdev(sd);
1136  	if (ret)
1137  		goto error_async_register;
1138  
1139  	pm_runtime_idle(&client->dev);
1140  
1141  	return 0;
1142  
1143  error_async_register:
1144  	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1145  error_init_controls:
1146  	ov7740_free_controls(ov7740);
1147  error_detect:
1148  	pm_runtime_disable(&client->dev);
1149  	pm_runtime_set_suspended(&client->dev);
1150  	ov7740_set_power(ov7740, 0);
1151  	media_entity_cleanup(&ov7740->subdev.entity);
1152  
1153  	return ret;
1154  }
1155  
ov7740_remove(struct i2c_client * client)1156  static void ov7740_remove(struct i2c_client *client)
1157  {
1158  	struct v4l2_subdev *sd = i2c_get_clientdata(client);
1159  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1160  
1161  	mutex_destroy(&ov7740->mutex);
1162  	v4l2_ctrl_handler_free(ov7740->subdev.ctrl_handler);
1163  	media_entity_cleanup(&ov7740->subdev.entity);
1164  	v4l2_async_unregister_subdev(sd);
1165  	ov7740_free_controls(ov7740);
1166  
1167  	pm_runtime_get_sync(&client->dev);
1168  	pm_runtime_disable(&client->dev);
1169  	pm_runtime_set_suspended(&client->dev);
1170  	pm_runtime_put_noidle(&client->dev);
1171  
1172  	ov7740_set_power(ov7740, 0);
1173  }
1174  
ov7740_runtime_suspend(struct device * dev)1175  static int __maybe_unused ov7740_runtime_suspend(struct device *dev)
1176  {
1177  	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1178  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1179  
1180  	ov7740_set_power(ov7740, 0);
1181  
1182  	return 0;
1183  }
1184  
ov7740_runtime_resume(struct device * dev)1185  static int __maybe_unused ov7740_runtime_resume(struct device *dev)
1186  {
1187  	struct v4l2_subdev *sd = dev_get_drvdata(dev);
1188  	struct ov7740 *ov7740 = container_of(sd, struct ov7740, subdev);
1189  
1190  	return ov7740_set_power(ov7740, 1);
1191  }
1192  
1193  static const struct i2c_device_id ov7740_id[] = {
1194  	{ "ov7740", 0 },
1195  	{ /* sentinel */ }
1196  };
1197  MODULE_DEVICE_TABLE(i2c, ov7740_id);
1198  
1199  static const struct dev_pm_ops ov7740_pm_ops = {
1200  	SET_RUNTIME_PM_OPS(ov7740_runtime_suspend, ov7740_runtime_resume, NULL)
1201  };
1202  
1203  static const struct of_device_id ov7740_of_match[] = {
1204  	{.compatible = "ovti,ov7740", },
1205  	{ /* sentinel */ },
1206  };
1207  MODULE_DEVICE_TABLE(of, ov7740_of_match);
1208  
1209  static struct i2c_driver ov7740_i2c_driver = {
1210  	.driver = {
1211  		.name = "ov7740",
1212  		.pm = &ov7740_pm_ops,
1213  		.of_match_table = ov7740_of_match,
1214  	},
1215  	.probe    = ov7740_probe,
1216  	.remove   = ov7740_remove,
1217  	.id_table = ov7740_id,
1218  };
1219  module_i2c_driver(ov7740_i2c_driver);
1220  
1221  MODULE_DESCRIPTION("The V4L2 driver for Omnivision 7740 sensor");
1222  MODULE_AUTHOR("Songjun Wu <songjun.wu@atmel.com>");
1223  MODULE_LICENSE("GPL v2");
1224