• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/
1/*
2 * OmniVision OV96xx Camera Driver
3 *
4 * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
5 *
6 * Based on ov772x camera driver:
7 *
8 * Copyright (C) 2008 Renesas Solutions Corp.
9 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
10 *
11 * Based on ov7670 and soc_camera_platform driver,
12 *
13 * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
14 * Copyright (C) 2008 Magnus Damm
15 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License version 2 as
19 * published by the Free Software Foundation.
20 */
21
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/i2c.h>
25#include <linux/slab.h>
26#include <linux/delay.h>
27#include <linux/videodev2.h>
28#include <media/v4l2-chip-ident.h>
29#include <media/v4l2-common.h>
30#include <media/soc_camera.h>
31
32#include "ov9640.h"
33
34/* default register setup */
35static const struct ov9640_reg ov9640_regs_dflt[] = {
36	{ OV9640_COM5,	OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP },
37	{ OV9640_COM6,	OV9640_COM6_OPT_BLC | OV9640_COM6_ADBLC_BIAS |
38			OV9640_COM6_FMT_RST | OV9640_COM6_ADBLC_OPTEN },
39	{ OV9640_PSHFT,	OV9640_PSHFT_VAL(0x01) },
40	{ OV9640_ACOM,	OV9640_ACOM_2X_ANALOG | OV9640_ACOM_RSVD },
41	{ OV9640_TSLB,	OV9640_TSLB_YUYV_UYVY },
42	{ OV9640_COM16,	OV9640_COM16_RB_AVG },
43
44	/* Gamma curve P */
45	{ 0x6c, 0x40 },	{ 0x6d, 0x30 },	{ 0x6e, 0x4b },	{ 0x6f, 0x60 },
46	{ 0x70, 0x70 },	{ 0x71, 0x70 },	{ 0x72, 0x70 },	{ 0x73, 0x70 },
47	{ 0x74, 0x60 },	{ 0x75, 0x60 },	{ 0x76, 0x50 },	{ 0x77, 0x48 },
48	{ 0x78, 0x3a },	{ 0x79, 0x2e },	{ 0x7a, 0x28 },	{ 0x7b, 0x22 },
49
50	/* Gamma curve T */
51	{ 0x7c, 0x04 },	{ 0x7d, 0x07 },	{ 0x7e, 0x10 },	{ 0x7f, 0x28 },
52	{ 0x80, 0x36 },	{ 0x81, 0x44 },	{ 0x82, 0x52 },	{ 0x83, 0x60 },
53	{ 0x84, 0x6c },	{ 0x85, 0x78 },	{ 0x86, 0x8c },	{ 0x87, 0x9e },
54	{ 0x88, 0xbb },	{ 0x89, 0xd2 },	{ 0x8a, 0xe6 },
55};
56
57/* Configurations
58 * NOTE: for YUV, alter the following registers:
59 * 		COM12 |= OV9640_COM12_YUV_AVG
60 *
61 *	 for RGB, alter the following registers:
62 *		COM7  |= OV9640_COM7_RGB
63 *		COM13 |= OV9640_COM13_RGB_AVG
64 *		COM15 |= proper RGB color encoding mode
65 */
66static const struct ov9640_reg ov9640_regs_qqcif[] = {
67	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) },
68	{ OV9640_COM1,	OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP },
69	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
70	{ OV9640_COM7,	OV9640_COM7_QCIF },
71	{ OV9640_COM12,	OV9640_COM12_RSVD },
72	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
73	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
74};
75
76static const struct ov9640_reg ov9640_regs_qqvga[] = {
77	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) },
78	{ OV9640_COM1,	OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP },
79	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
80	{ OV9640_COM7,	OV9640_COM7_QVGA },
81	{ OV9640_COM12,	OV9640_COM12_RSVD },
82	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
83	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
84};
85
86static const struct ov9640_reg ov9640_regs_qcif[] = {
87	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) },
88	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
89	{ OV9640_COM7,	OV9640_COM7_QCIF },
90	{ OV9640_COM12,	OV9640_COM12_RSVD },
91	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
92	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
93};
94
95static const struct ov9640_reg ov9640_regs_qvga[] = {
96	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) },
97	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
98	{ OV9640_COM7,	OV9640_COM7_QVGA },
99	{ OV9640_COM12,	OV9640_COM12_RSVD },
100	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
101	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
102};
103
104static const struct ov9640_reg ov9640_regs_cif[] = {
105	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) },
106	{ OV9640_COM3,	OV9640_COM3_VP },
107	{ OV9640_COM7,	OV9640_COM7_CIF },
108	{ OV9640_COM12,	OV9640_COM12_RSVD },
109	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
110	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
111};
112
113static const struct ov9640_reg ov9640_regs_vga[] = {
114	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) },
115	{ OV9640_COM3,	OV9640_COM3_VP },
116	{ OV9640_COM7,	OV9640_COM7_VGA },
117	{ OV9640_COM12,	OV9640_COM12_RSVD },
118	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
119	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
120};
121
122static const struct ov9640_reg ov9640_regs_sxga[] = {
123	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) },
124	{ OV9640_COM3,	OV9640_COM3_VP },
125	{ OV9640_COM7,	0 },
126	{ OV9640_COM12,	OV9640_COM12_RSVD },
127	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
128	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
129};
130
131static const struct ov9640_reg ov9640_regs_yuv[] = {
132	{ OV9640_MTX1,	0x58 },
133	{ OV9640_MTX2,	0x48 },
134	{ OV9640_MTX3,	0x10 },
135	{ OV9640_MTX4,	0x28 },
136	{ OV9640_MTX5,	0x48 },
137	{ OV9640_MTX6,	0x70 },
138	{ OV9640_MTX7,	0x40 },
139	{ OV9640_MTX8,	0x40 },
140	{ OV9640_MTX9,	0x40 },
141	{ OV9640_MTXS,	0x0f },
142};
143
144static const struct ov9640_reg ov9640_regs_rgb[] = {
145	{ OV9640_MTX1,	0x71 },
146	{ OV9640_MTX2,	0x3e },
147	{ OV9640_MTX3,	0x0c },
148	{ OV9640_MTX4,	0x33 },
149	{ OV9640_MTX5,	0x72 },
150	{ OV9640_MTX6,	0x00 },
151	{ OV9640_MTX7,	0x2b },
152	{ OV9640_MTX8,	0x66 },
153	{ OV9640_MTX9,	0xd2 },
154	{ OV9640_MTXS,	0x65 },
155};
156
157static enum v4l2_mbus_pixelcode ov9640_codes[] = {
158	V4L2_MBUS_FMT_UYVY8_2X8,
159	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
160	V4L2_MBUS_FMT_RGB565_2X8_LE,
161};
162
163static const struct v4l2_queryctrl ov9640_controls[] = {
164	{
165		.id		= V4L2_CID_VFLIP,
166		.type		= V4L2_CTRL_TYPE_BOOLEAN,
167		.name		= "Flip Vertically",
168		.minimum	= 0,
169		.maximum	= 1,
170		.step		= 1,
171		.default_value	= 0,
172	},
173	{
174		.id		= V4L2_CID_HFLIP,
175		.type		= V4L2_CTRL_TYPE_BOOLEAN,
176		.name		= "Flip Horizontally",
177		.minimum	= 0,
178		.maximum	= 1,
179		.step		= 1,
180		.default_value	= 0,
181	},
182};
183
184/* read a register */
185static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val)
186{
187	int ret;
188	u8 data = reg;
189	struct i2c_msg msg = {
190		.addr	= client->addr,
191		.flags	= 0,
192		.len	= 1,
193		.buf	= &data,
194	};
195
196	ret = i2c_transfer(client->adapter, &msg, 1);
197	if (ret < 0)
198		goto err;
199
200	msg.flags = I2C_M_RD;
201	ret = i2c_transfer(client->adapter, &msg, 1);
202	if (ret < 0)
203		goto err;
204
205	*val = data;
206	return 0;
207
208err:
209	dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg);
210	return ret;
211}
212
213/* write a register */
214static int ov9640_reg_write(struct i2c_client *client, u8 reg, u8 val)
215{
216	int ret;
217	u8 _val;
218	unsigned char data[2] = { reg, val };
219	struct i2c_msg msg = {
220		.addr	= client->addr,
221		.flags	= 0,
222		.len	= 2,
223		.buf	= data,
224	};
225
226	ret = i2c_transfer(client->adapter, &msg, 1);
227	if (ret < 0) {
228		dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg);
229		return ret;
230	}
231
232	/* we have to read the register back ... no idea why, maybe HW bug */
233	ret = ov9640_reg_read(client, reg, &_val);
234	if (ret)
235		dev_err(&client->dev,
236			"Failed reading back register 0x%02x!\n", reg);
237
238	return 0;
239}
240
241
242/* Read a register, alter its bits, write it back */
243static int ov9640_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 unset)
244{
245	u8 val;
246	int ret;
247
248	ret = ov9640_reg_read(client, reg, &val);
249	if (ret) {
250		dev_err(&client->dev,
251			"[Read]-Modify-Write of register %02x failed!\n", reg);
252		return val;
253	}
254
255	val |= set;
256	val &= ~unset;
257
258	ret = ov9640_reg_write(client, reg, val);
259	if (ret)
260		dev_err(&client->dev,
261			"Read-Modify-[Write] of register %02x failed!\n", reg);
262
263	return ret;
264}
265
266/* Soft reset the camera. This has nothing to do with the RESET pin! */
267static int ov9640_reset(struct i2c_client *client)
268{
269	int ret;
270
271	ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET);
272	if (ret)
273		dev_err(&client->dev,
274			"An error occured while entering soft reset!\n");
275
276	return ret;
277}
278
279/* Start/Stop streaming from the device */
280static int ov9640_s_stream(struct v4l2_subdev *sd, int enable)
281{
282	return 0;
283}
284
285/* Alter bus settings on camera side */
286static int ov9640_set_bus_param(struct soc_camera_device *icd,
287				unsigned long flags)
288{
289	return 0;
290}
291
292/* Request bus settings on camera side */
293static unsigned long ov9640_query_bus_param(struct soc_camera_device *icd)
294{
295	struct soc_camera_link *icl = to_soc_camera_link(icd);
296
297	/*
298	 * REVISIT: the camera probably can do 10 bit transfers, but I don't
299	 *          have those pins connected on my hardware.
300	 */
301	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
302		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
303		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
304
305	return soc_camera_apply_sensor_flags(icl, flags);
306}
307
308/* Get status of additional camera capabilities */
309static int ov9640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
310{
311	struct i2c_client *client = sd->priv;
312	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
313					struct ov9640_priv, subdev);
314
315	switch (ctrl->id) {
316	case V4L2_CID_VFLIP:
317		ctrl->value = priv->flag_vflip;
318		break;
319	case V4L2_CID_HFLIP:
320		ctrl->value = priv->flag_hflip;
321		break;
322	}
323	return 0;
324}
325
326/* Set status of additional camera capabilities */
327static int ov9640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
328{
329	struct i2c_client *client = sd->priv;
330	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
331					struct ov9640_priv, subdev);
332
333	int ret = 0;
334
335	switch (ctrl->id) {
336	case V4L2_CID_VFLIP:
337		priv->flag_vflip = ctrl->value;
338		if (ctrl->value)
339			ret = ov9640_reg_rmw(client, OV9640_MVFP,
340							OV9640_MVFP_V, 0);
341		else
342			ret = ov9640_reg_rmw(client, OV9640_MVFP,
343							0, OV9640_MVFP_V);
344		break;
345	case V4L2_CID_HFLIP:
346		priv->flag_hflip = ctrl->value;
347		if (ctrl->value)
348			ret = ov9640_reg_rmw(client, OV9640_MVFP,
349							OV9640_MVFP_H, 0);
350		else
351			ret = ov9640_reg_rmw(client, OV9640_MVFP,
352							0, OV9640_MVFP_H);
353		break;
354	}
355
356	return ret;
357}
358
359/* Get chip identification */
360static int ov9640_g_chip_ident(struct v4l2_subdev *sd,
361				struct v4l2_dbg_chip_ident *id)
362{
363	struct i2c_client *client = sd->priv;
364	struct ov9640_priv *priv = container_of(i2c_get_clientdata(client),
365					struct ov9640_priv, subdev);
366
367	id->ident	= priv->model;
368	id->revision	= priv->revision;
369
370	return 0;
371}
372
373#ifdef CONFIG_VIDEO_ADV_DEBUG
374static int ov9640_get_register(struct v4l2_subdev *sd,
375				struct v4l2_dbg_register *reg)
376{
377	struct i2c_client *client = sd->priv;
378	int ret;
379	u8 val;
380
381	if (reg->reg & ~0xff)
382		return -EINVAL;
383
384	reg->size = 1;
385
386	ret = ov9640_reg_read(client, reg->reg, &val);
387	if (ret)
388		return ret;
389
390	reg->val = (__u64)val;
391
392	return 0;
393}
394
395static int ov9640_set_register(struct v4l2_subdev *sd,
396				struct v4l2_dbg_register *reg)
397{
398	struct i2c_client *client = sd->priv;
399
400	if (reg->reg & ~0xff || reg->val & ~0xff)
401		return -EINVAL;
402
403	return ov9640_reg_write(client, reg->reg, reg->val);
404}
405#endif
406
407/* select nearest higher resolution for capture */
408static void ov9640_res_roundup(u32 *width, u32 *height)
409{
410	int i;
411	enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA };
412	int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 };
413	int res_y[] = { 72, 120, 144, 240, 288, 480, 960 };
414
415	for (i = 0; i < ARRAY_SIZE(res_x); i++) {
416		if (res_x[i] >= *width && res_y[i] >= *height) {
417			*width = res_x[i];
418			*height = res_y[i];
419			return;
420		}
421	}
422
423	*width = res_x[SXGA];
424	*height = res_y[SXGA];
425}
426
427/* Prepare necessary register changes depending on color encoding */
428static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
429			      struct ov9640_reg_alt *alt)
430{
431	switch (code) {
432	default:
433	case V4L2_MBUS_FMT_UYVY8_2X8:
434		alt->com12	= OV9640_COM12_YUV_AVG;
435		alt->com13	= OV9640_COM13_Y_DELAY_EN |
436					OV9640_COM13_YUV_DLY(0x01);
437		break;
438	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
439		alt->com7	= OV9640_COM7_RGB;
440		alt->com13	= OV9640_COM13_RGB_AVG;
441		alt->com15	= OV9640_COM15_RGB_555;
442		break;
443	case V4L2_MBUS_FMT_RGB565_2X8_LE:
444		alt->com7	= OV9640_COM7_RGB;
445		alt->com13	= OV9640_COM13_RGB_AVG;
446		alt->com15	= OV9640_COM15_RGB_565;
447		break;
448	};
449}
450
451/* Setup registers according to resolution and color encoding */
452static int ov9640_write_regs(struct i2c_client *client, u32 width,
453		enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts)
454{
455	const struct ov9640_reg	*ov9640_regs, *matrix_regs;
456	int			ov9640_regs_len, matrix_regs_len;
457	int			i, ret;
458	u8			val;
459
460	/* select register configuration for given resolution */
461	switch (width) {
462	case W_QQCIF:
463		ov9640_regs	= ov9640_regs_qqcif;
464		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qqcif);
465		break;
466	case W_QQVGA:
467		ov9640_regs	= ov9640_regs_qqvga;
468		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qqvga);
469		break;
470	case W_QCIF:
471		ov9640_regs	= ov9640_regs_qcif;
472		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qcif);
473		break;
474	case W_QVGA:
475		ov9640_regs	= ov9640_regs_qvga;
476		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qvga);
477		break;
478	case W_CIF:
479		ov9640_regs	= ov9640_regs_cif;
480		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_cif);
481		break;
482	case W_VGA:
483		ov9640_regs	= ov9640_regs_vga;
484		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_vga);
485		break;
486	case W_SXGA:
487		ov9640_regs	= ov9640_regs_sxga;
488		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_sxga);
489		break;
490	default:
491		dev_err(&client->dev, "Failed to select resolution!\n");
492		return -EINVAL;
493	}
494
495	/* select color matrix configuration for given color encoding */
496	if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
497		matrix_regs	= ov9640_regs_yuv;
498		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_yuv);
499	} else {
500		matrix_regs	= ov9640_regs_rgb;
501		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_rgb);
502	}
503
504	/* write register settings into the module */
505	for (i = 0; i < ov9640_regs_len; i++) {
506		val = ov9640_regs[i].val;
507
508		switch (ov9640_regs[i].reg) {
509		case OV9640_COM7:
510			val |= alts->com7;
511			break;
512		case OV9640_COM12:
513			val |= alts->com12;
514			break;
515		case OV9640_COM13:
516			val |= alts->com13;
517			break;
518		case OV9640_COM15:
519			val |= alts->com15;
520			break;
521		}
522
523		ret = ov9640_reg_write(client, ov9640_regs[i].reg, val);
524		if (ret)
525			return ret;
526	}
527
528	/* write color matrix configuration into the module */
529	for (i = 0; i < matrix_regs_len; i++) {
530		ret = ov9640_reg_write(client, matrix_regs[i].reg,
531						matrix_regs[i].val);
532		if (ret)
533			return ret;
534	}
535
536	return 0;
537}
538
539/* program default register values */
540static int ov9640_prog_dflt(struct i2c_client *client)
541{
542	int i, ret;
543
544	for (i = 0; i < ARRAY_SIZE(ov9640_regs_dflt); i++) {
545		ret = ov9640_reg_write(client, ov9640_regs_dflt[i].reg,
546						ov9640_regs_dflt[i].val);
547		if (ret)
548			return ret;
549	}
550
551	/* wait for the changes to actually happen, 140ms are not enough yet */
552	mdelay(150);
553
554	return 0;
555}
556
557/* set the format we will capture in */
558static int ov9640_s_fmt(struct v4l2_subdev *sd,
559			struct v4l2_mbus_framefmt *mf)
560{
561	struct i2c_client *client = sd->priv;
562	struct ov9640_reg_alt alts = {0};
563	enum v4l2_colorspace cspace;
564	enum v4l2_mbus_pixelcode code = mf->code;
565	int ret;
566
567	ov9640_res_roundup(&mf->width, &mf->height);
568	ov9640_alter_regs(mf->code, &alts);
569
570	ov9640_reset(client);
571
572	ret = ov9640_prog_dflt(client);
573	if (ret)
574		return ret;
575
576	switch (code) {
577	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
578	case V4L2_MBUS_FMT_RGB565_2X8_LE:
579		cspace = V4L2_COLORSPACE_SRGB;
580		break;
581	default:
582		code = V4L2_MBUS_FMT_UYVY8_2X8;
583	case V4L2_MBUS_FMT_UYVY8_2X8:
584		cspace = V4L2_COLORSPACE_JPEG;
585	}
586
587	ret = ov9640_write_regs(client, mf->width, code, &alts);
588	if (!ret) {
589		mf->code	= code;
590		mf->colorspace	= cspace;
591	}
592
593	return ret;
594}
595
596static int ov9640_try_fmt(struct v4l2_subdev *sd,
597			  struct v4l2_mbus_framefmt *mf)
598{
599	ov9640_res_roundup(&mf->width, &mf->height);
600
601	mf->field = V4L2_FIELD_NONE;
602
603	switch (mf->code) {
604	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
605	case V4L2_MBUS_FMT_RGB565_2X8_LE:
606		mf->colorspace = V4L2_COLORSPACE_SRGB;
607		break;
608	default:
609		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
610	case V4L2_MBUS_FMT_UYVY8_2X8:
611		mf->colorspace = V4L2_COLORSPACE_JPEG;
612	}
613
614	return 0;
615}
616
617static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
618			   enum v4l2_mbus_pixelcode *code)
619{
620	if (index >= ARRAY_SIZE(ov9640_codes))
621		return -EINVAL;
622
623	*code = ov9640_codes[index];
624	return 0;
625}
626
627static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
628{
629	a->c.left	= 0;
630	a->c.top	= 0;
631	a->c.width	= W_SXGA;
632	a->c.height	= H_SXGA;
633	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
634
635	return 0;
636}
637
638static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
639{
640	a->bounds.left			= 0;
641	a->bounds.top			= 0;
642	a->bounds.width			= W_SXGA;
643	a->bounds.height		= H_SXGA;
644	a->defrect			= a->bounds;
645	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
646	a->pixelaspect.numerator	= 1;
647	a->pixelaspect.denominator	= 1;
648
649	return 0;
650}
651
652
653
654static int ov9640_video_probe(struct soc_camera_device *icd,
655				struct i2c_client *client)
656{
657	struct ov9640_priv *priv = i2c_get_clientdata(client);
658	u8		pid, ver, midh, midl;
659	const char	*devname;
660	int		ret = 0;
661
662	/*
663	 * We must have a parent by now. And it cannot be a wrong one.
664	 * So this entire test is completely redundant.
665	 */
666	if (!icd->dev.parent ||
667	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
668		dev_err(&client->dev, "Parent missing or invalid!\n");
669		ret = -ENODEV;
670		goto err;
671	}
672
673	/*
674	 * check and show product ID and manufacturer ID
675	 */
676
677	ret = ov9640_reg_read(client, OV9640_PID, &pid);
678	if (ret)
679		goto err;
680
681	ret = ov9640_reg_read(client, OV9640_VER, &ver);
682	if (ret)
683		goto err;
684
685	ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
686	if (ret)
687		goto err;
688
689	ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
690	if (ret)
691		goto err;
692
693	switch (VERSION(pid, ver)) {
694	case OV9640_V2:
695		devname		= "ov9640";
696		priv->model	= V4L2_IDENT_OV9640;
697		priv->revision	= 2;
698	case OV9640_V3:
699		devname		= "ov9640";
700		priv->model	= V4L2_IDENT_OV9640;
701		priv->revision	= 3;
702		break;
703	default:
704		dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
705		ret = -ENODEV;
706		goto err;
707	}
708
709	dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
710		 devname, pid, ver, midh, midl);
711
712err:
713	return ret;
714}
715
716static struct soc_camera_ops ov9640_ops = {
717	.set_bus_param		= ov9640_set_bus_param,
718	.query_bus_param	= ov9640_query_bus_param,
719	.controls		= ov9640_controls,
720	.num_controls		= ARRAY_SIZE(ov9640_controls),
721};
722
723static struct v4l2_subdev_core_ops ov9640_core_ops = {
724	.g_ctrl			= ov9640_g_ctrl,
725	.s_ctrl			= ov9640_s_ctrl,
726	.g_chip_ident		= ov9640_g_chip_ident,
727#ifdef CONFIG_VIDEO_ADV_DEBUG
728	.g_register		= ov9640_get_register,
729	.s_register		= ov9640_set_register,
730#endif
731
732};
733
734static struct v4l2_subdev_video_ops ov9640_video_ops = {
735	.s_stream	= ov9640_s_stream,
736	.s_mbus_fmt	= ov9640_s_fmt,
737	.try_mbus_fmt	= ov9640_try_fmt,
738	.enum_mbus_fmt	= ov9640_enum_fmt,
739	.cropcap	= ov9640_cropcap,
740	.g_crop		= ov9640_g_crop,
741
742};
743
744static struct v4l2_subdev_ops ov9640_subdev_ops = {
745	.core	= &ov9640_core_ops,
746	.video	= &ov9640_video_ops,
747};
748
749/*
750 * i2c_driver function
751 */
752static int ov9640_probe(struct i2c_client *client,
753			const struct i2c_device_id *did)
754{
755	struct ov9640_priv *priv;
756	struct soc_camera_device *icd	= client->dev.platform_data;
757	struct soc_camera_link *icl;
758	int ret;
759
760	if (!icd) {
761		dev_err(&client->dev, "Missing soc-camera data!\n");
762		return -EINVAL;
763	}
764
765	icl = to_soc_camera_link(icd);
766	if (!icl) {
767		dev_err(&client->dev, "Missing platform_data for driver\n");
768		return -EINVAL;
769	}
770
771	priv = kzalloc(sizeof(struct ov9640_priv), GFP_KERNEL);
772	if (!priv) {
773		dev_err(&client->dev,
774			"Failed to allocate memory for private data!\n");
775		return -ENOMEM;
776	}
777
778	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
779
780	icd->ops	= &ov9640_ops;
781
782	ret = ov9640_video_probe(icd, client);
783
784	if (ret) {
785		icd->ops = NULL;
786		kfree(priv);
787	}
788
789	return ret;
790}
791
792static int ov9640_remove(struct i2c_client *client)
793{
794	struct ov9640_priv *priv = i2c_get_clientdata(client);
795
796	kfree(priv);
797	return 0;
798}
799
800static const struct i2c_device_id ov9640_id[] = {
801	{ "ov9640", 0 },
802	{ }
803};
804MODULE_DEVICE_TABLE(i2c, ov9640_id);
805
806static struct i2c_driver ov9640_i2c_driver = {
807	.driver = {
808		.name = "ov9640",
809	},
810	.probe    = ov9640_probe,
811	.remove   = ov9640_remove,
812	.id_table = ov9640_id,
813};
814
815static int __init ov9640_module_init(void)
816{
817	return i2c_add_driver(&ov9640_i2c_driver);
818}
819
820static void __exit ov9640_module_exit(void)
821{
822	i2c_del_driver(&ov9640_i2c_driver);
823}
824
825module_init(ov9640_module_init);
826module_exit(ov9640_module_exit);
827
828MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx");
829MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
830MODULE_LICENSE("GPL v2");
831