1/*
2 * Driver for IMX074 CMOS Image Sensor from Sony
3 *
4 * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5 *
6 * Partially inspired by the IMX074 driver from the Android / MSM tree
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/i2c.h>
15#include <linux/v4l2-mediabus.h>
16#include <linux/slab.h>
17#include <linux/videodev2.h>
18#include <linux/module.h>
19
20#include <media/soc_camera.h>
21#include <media/v4l2-async.h>
22#include <media/v4l2-clk.h>
23#include <media/v4l2-subdev.h>
24
25/* IMX074 registers */
26
27#define MODE_SELECT			0x0100
28#define IMAGE_ORIENTATION		0x0101
29#define GROUPED_PARAMETER_HOLD		0x0104
30
31/* Integration Time */
32#define COARSE_INTEGRATION_TIME_HI	0x0202
33#define COARSE_INTEGRATION_TIME_LO	0x0203
34/* Gain */
35#define ANALOGUE_GAIN_CODE_GLOBAL_HI	0x0204
36#define ANALOGUE_GAIN_CODE_GLOBAL_LO	0x0205
37
38/* PLL registers */
39#define PRE_PLL_CLK_DIV			0x0305
40#define PLL_MULTIPLIER			0x0307
41#define PLSTATIM			0x302b
42#define VNDMY_ABLMGSHLMT		0x300a
43#define Y_OPBADDR_START_DI		0x3014
44/* mode setting */
45#define FRAME_LENGTH_LINES_HI		0x0340
46#define FRAME_LENGTH_LINES_LO		0x0341
47#define LINE_LENGTH_PCK_HI		0x0342
48#define LINE_LENGTH_PCK_LO		0x0343
49#define YADDR_START			0x0347
50#define YADDR_END			0x034b
51#define X_OUTPUT_SIZE_MSB		0x034c
52#define X_OUTPUT_SIZE_LSB		0x034d
53#define Y_OUTPUT_SIZE_MSB		0x034e
54#define Y_OUTPUT_SIZE_LSB		0x034f
55#define X_EVEN_INC			0x0381
56#define X_ODD_INC			0x0383
57#define Y_EVEN_INC			0x0385
58#define Y_ODD_INC			0x0387
59
60#define HMODEADD			0x3001
61#define VMODEADD			0x3016
62#define VAPPLINE_START			0x3069
63#define VAPPLINE_END			0x306b
64#define SHUTTER				0x3086
65#define HADDAVE				0x30e8
66#define LANESEL				0x3301
67
68/* IMX074 supported geometry */
69#define IMX074_WIDTH			1052
70#define IMX074_HEIGHT			780
71
72/* IMX074 has only one fixed colorspace per pixelcode */
73struct imx074_datafmt {
74	u32	code;
75	enum v4l2_colorspace		colorspace;
76};
77
78struct imx074 {
79	struct v4l2_subdev		subdev;
80	const struct imx074_datafmt	*fmt;
81	struct v4l2_clk			*clk;
82};
83
84static const struct imx074_datafmt imx074_colour_fmts[] = {
85	{MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
86};
87
88static struct imx074 *to_imx074(const struct i2c_client *client)
89{
90	return container_of(i2c_get_clientdata(client), struct imx074, subdev);
91}
92
93/* Find a data format by a pixel code in an array */
94static const struct imx074_datafmt *imx074_find_datafmt(u32 code)
95{
96	int i;
97
98	for (i = 0; i < ARRAY_SIZE(imx074_colour_fmts); i++)
99		if (imx074_colour_fmts[i].code == code)
100			return imx074_colour_fmts + i;
101
102	return NULL;
103}
104
105static int reg_write(struct i2c_client *client, const u16 addr, const u8 data)
106{
107	struct i2c_adapter *adap = client->adapter;
108	struct i2c_msg msg;
109	unsigned char tx[3];
110	int ret;
111
112	msg.addr = client->addr;
113	msg.buf = tx;
114	msg.len = 3;
115	msg.flags = 0;
116
117	tx[0] = addr >> 8;
118	tx[1] = addr & 0xff;
119	tx[2] = data;
120
121	ret = i2c_transfer(adap, &msg, 1);
122
123	mdelay(2);
124
125	return ret == 1 ? 0 : -EIO;
126}
127
128static int reg_read(struct i2c_client *client, const u16 addr)
129{
130	u8 buf[2] = {addr >> 8, addr & 0xff};
131	int ret;
132	struct i2c_msg msgs[] = {
133		{
134			.addr  = client->addr,
135			.flags = 0,
136			.len   = 2,
137			.buf   = buf,
138		}, {
139			.addr  = client->addr,
140			.flags = I2C_M_RD,
141			.len   = 2,
142			.buf   = buf,
143		},
144	};
145
146	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
147	if (ret < 0) {
148		dev_warn(&client->dev, "Reading register %x from %x failed\n",
149			 addr, client->addr);
150		return ret;
151	}
152
153	return buf[0] & 0xff; /* no sign-extension */
154}
155
156static int imx074_try_fmt(struct v4l2_subdev *sd,
157			  struct v4l2_mbus_framefmt *mf)
158{
159	const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
160
161	dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
162
163	if (!fmt) {
164		mf->code	= imx074_colour_fmts[0].code;
165		mf->colorspace	= imx074_colour_fmts[0].colorspace;
166	}
167
168	mf->width	= IMX074_WIDTH;
169	mf->height	= IMX074_HEIGHT;
170	mf->field	= V4L2_FIELD_NONE;
171
172	return 0;
173}
174
175static int imx074_s_fmt(struct v4l2_subdev *sd,
176			struct v4l2_mbus_framefmt *mf)
177{
178	struct i2c_client *client = v4l2_get_subdevdata(sd);
179	struct imx074 *priv = to_imx074(client);
180
181	dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
182
183	/* MIPI CSI could have changed the format, double-check */
184	if (!imx074_find_datafmt(mf->code))
185		return -EINVAL;
186
187	imx074_try_fmt(sd, mf);
188
189	priv->fmt = imx074_find_datafmt(mf->code);
190
191	return 0;
192}
193
194static int imx074_g_fmt(struct v4l2_subdev *sd,
195			struct v4l2_mbus_framefmt *mf)
196{
197	struct i2c_client *client = v4l2_get_subdevdata(sd);
198	struct imx074 *priv = to_imx074(client);
199
200	const struct imx074_datafmt *fmt = priv->fmt;
201
202	mf->code	= fmt->code;
203	mf->colorspace	= fmt->colorspace;
204	mf->width	= IMX074_WIDTH;
205	mf->height	= IMX074_HEIGHT;
206	mf->field	= V4L2_FIELD_NONE;
207
208	return 0;
209}
210
211static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
212{
213	struct v4l2_rect *rect = &a->c;
214
215	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
216	rect->top	= 0;
217	rect->left	= 0;
218	rect->width	= IMX074_WIDTH;
219	rect->height	= IMX074_HEIGHT;
220
221	return 0;
222}
223
224static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
225{
226	a->bounds.left			= 0;
227	a->bounds.top			= 0;
228	a->bounds.width			= IMX074_WIDTH;
229	a->bounds.height		= IMX074_HEIGHT;
230	a->defrect			= a->bounds;
231	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
232	a->pixelaspect.numerator	= 1;
233	a->pixelaspect.denominator	= 1;
234
235	return 0;
236}
237
238static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
239			   u32 *code)
240{
241	if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
242		return -EINVAL;
243
244	*code = imx074_colour_fmts[index].code;
245	return 0;
246}
247
248static int imx074_s_stream(struct v4l2_subdev *sd, int enable)
249{
250	struct i2c_client *client = v4l2_get_subdevdata(sd);
251
252	/* MODE_SELECT: stream or standby */
253	return reg_write(client, MODE_SELECT, !!enable);
254}
255
256static int imx074_s_power(struct v4l2_subdev *sd, int on)
257{
258	struct i2c_client *client = v4l2_get_subdevdata(sd);
259	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
260	struct imx074 *priv = to_imx074(client);
261
262	return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
263}
264
265static int imx074_g_mbus_config(struct v4l2_subdev *sd,
266				struct v4l2_mbus_config *cfg)
267{
268	cfg->type = V4L2_MBUS_CSI2;
269	cfg->flags = V4L2_MBUS_CSI2_2_LANE |
270		V4L2_MBUS_CSI2_CHANNEL_0 |
271		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
272
273	return 0;
274}
275
276static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
277	.s_stream	= imx074_s_stream,
278	.s_mbus_fmt	= imx074_s_fmt,
279	.g_mbus_fmt	= imx074_g_fmt,
280	.try_mbus_fmt	= imx074_try_fmt,
281	.enum_mbus_fmt	= imx074_enum_fmt,
282	.g_crop		= imx074_g_crop,
283	.cropcap	= imx074_cropcap,
284	.g_mbus_config	= imx074_g_mbus_config,
285};
286
287static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
288	.s_power	= imx074_s_power,
289};
290
291static struct v4l2_subdev_ops imx074_subdev_ops = {
292	.core	= &imx074_subdev_core_ops,
293	.video	= &imx074_subdev_video_ops,
294};
295
296static int imx074_video_probe(struct i2c_client *client)
297{
298	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
299	int ret;
300	u16 id;
301
302	ret = imx074_s_power(subdev, 1);
303	if (ret < 0)
304		return ret;
305
306	/* Read sensor Model ID */
307	ret = reg_read(client, 0);
308	if (ret < 0)
309		goto done;
310
311	id = ret << 8;
312
313	ret = reg_read(client, 1);
314	if (ret < 0)
315		goto done;
316
317	id |= ret;
318
319	dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
320
321	if (id != 0x74) {
322		ret = -ENODEV;
323		goto done;
324	}
325
326	/* PLL Setting EXTCLK=24MHz, 22.5times */
327	reg_write(client, PLL_MULTIPLIER, 0x2D);
328	reg_write(client, PRE_PLL_CLK_DIV, 0x02);
329	reg_write(client, PLSTATIM, 0x4B);
330
331	/* 2-lane mode */
332	reg_write(client, 0x3024, 0x00);
333
334	reg_write(client, IMAGE_ORIENTATION, 0x00);
335
336	/* select RAW mode:
337	 * 0x08+0x08 = top 8 bits
338	 * 0x0a+0x08 = compressed 8-bits
339	 * 0x0a+0x0a = 10 bits
340	 */
341	reg_write(client, 0x0112, 0x08);
342	reg_write(client, 0x0113, 0x08);
343
344	/* Base setting for High frame mode */
345	reg_write(client, VNDMY_ABLMGSHLMT, 0x80);
346	reg_write(client, Y_OPBADDR_START_DI, 0x08);
347	reg_write(client, 0x3015, 0x37);
348	reg_write(client, 0x301C, 0x01);
349	reg_write(client, 0x302C, 0x05);
350	reg_write(client, 0x3031, 0x26);
351	reg_write(client, 0x3041, 0x60);
352	reg_write(client, 0x3051, 0x24);
353	reg_write(client, 0x3053, 0x34);
354	reg_write(client, 0x3057, 0xC0);
355	reg_write(client, 0x305C, 0x09);
356	reg_write(client, 0x305D, 0x07);
357	reg_write(client, 0x3060, 0x30);
358	reg_write(client, 0x3065, 0x00);
359	reg_write(client, 0x30AA, 0x08);
360	reg_write(client, 0x30AB, 0x1C);
361	reg_write(client, 0x30B0, 0x32);
362	reg_write(client, 0x30B2, 0x83);
363	reg_write(client, 0x30D3, 0x04);
364	reg_write(client, 0x3106, 0x78);
365	reg_write(client, 0x310C, 0x82);
366	reg_write(client, 0x3304, 0x05);
367	reg_write(client, 0x3305, 0x04);
368	reg_write(client, 0x3306, 0x11);
369	reg_write(client, 0x3307, 0x02);
370	reg_write(client, 0x3308, 0x0C);
371	reg_write(client, 0x3309, 0x06);
372	reg_write(client, 0x330A, 0x08);
373	reg_write(client, 0x330B, 0x04);
374	reg_write(client, 0x330C, 0x08);
375	reg_write(client, 0x330D, 0x06);
376	reg_write(client, 0x330E, 0x01);
377	reg_write(client, 0x3381, 0x00);
378
379	/* V : 1/2V-addition (1,3), H : 1/2H-averaging (1,3) -> Full HD */
380	/* 1608 = 1560 + 48 (black lines) */
381	reg_write(client, FRAME_LENGTH_LINES_HI, 0x06);
382	reg_write(client, FRAME_LENGTH_LINES_LO, 0x48);
383	reg_write(client, YADDR_START, 0x00);
384	reg_write(client, YADDR_END, 0x2F);
385	/* 0x838 == 2104 */
386	reg_write(client, X_OUTPUT_SIZE_MSB, 0x08);
387	reg_write(client, X_OUTPUT_SIZE_LSB, 0x38);
388	/* 0x618 == 1560 */
389	reg_write(client, Y_OUTPUT_SIZE_MSB, 0x06);
390	reg_write(client, Y_OUTPUT_SIZE_LSB, 0x18);
391	reg_write(client, X_EVEN_INC, 0x01);
392	reg_write(client, X_ODD_INC, 0x03);
393	reg_write(client, Y_EVEN_INC, 0x01);
394	reg_write(client, Y_ODD_INC, 0x03);
395	reg_write(client, HMODEADD, 0x00);
396	reg_write(client, VMODEADD, 0x16);
397	reg_write(client, VAPPLINE_START, 0x24);
398	reg_write(client, VAPPLINE_END, 0x53);
399	reg_write(client, SHUTTER, 0x00);
400	reg_write(client, HADDAVE, 0x80);
401
402	reg_write(client, LANESEL, 0x00);
403
404	reg_write(client, GROUPED_PARAMETER_HOLD, 0x00);	/* off */
405
406	ret = 0;
407
408done:
409	imx074_s_power(subdev, 0);
410	return ret;
411}
412
413static int imx074_probe(struct i2c_client *client,
414			const struct i2c_device_id *did)
415{
416	struct imx074 *priv;
417	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
418	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
419	int ret;
420
421	if (!ssdd) {
422		dev_err(&client->dev, "IMX074: missing platform data!\n");
423		return -EINVAL;
424	}
425
426	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
427		dev_warn(&adapter->dev,
428			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
429		return -EIO;
430	}
431
432	priv = devm_kzalloc(&client->dev, sizeof(struct imx074), GFP_KERNEL);
433	if (!priv)
434		return -ENOMEM;
435
436	v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
437
438	priv->fmt	= &imx074_colour_fmts[0];
439
440	priv->clk = v4l2_clk_get(&client->dev, "mclk");
441	if (IS_ERR(priv->clk)) {
442		dev_info(&client->dev, "Error %ld getting clock\n", PTR_ERR(priv->clk));
443		return -EPROBE_DEFER;
444	}
445
446	ret = soc_camera_power_init(&client->dev, ssdd);
447	if (ret < 0)
448		goto epwrinit;
449
450	ret = imx074_video_probe(client);
451	if (ret < 0)
452		goto eprobe;
453
454	ret = v4l2_async_register_subdev(&priv->subdev);
455	if (!ret)
456		return 0;
457
458epwrinit:
459eprobe:
460	v4l2_clk_put(priv->clk);
461	return ret;
462}
463
464static int imx074_remove(struct i2c_client *client)
465{
466	struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
467	struct imx074 *priv = to_imx074(client);
468
469	v4l2_async_unregister_subdev(&priv->subdev);
470	v4l2_clk_put(priv->clk);
471
472	if (ssdd->free_bus)
473		ssdd->free_bus(ssdd);
474
475	return 0;
476}
477
478static const struct i2c_device_id imx074_id[] = {
479	{ "imx074", 0 },
480	{ }
481};
482MODULE_DEVICE_TABLE(i2c, imx074_id);
483
484static struct i2c_driver imx074_i2c_driver = {
485	.driver = {
486		.name = "imx074",
487	},
488	.probe		= imx074_probe,
489	.remove		= imx074_remove,
490	.id_table	= imx074_id,
491};
492
493module_i2c_driver(imx074_i2c_driver);
494
495MODULE_DESCRIPTION("Sony IMX074 Camera driver");
496MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
497MODULE_LICENSE("GPL v2");
498