• 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.36/drivers/staging/dream/camera/
1/*
2 * Copyright (C) 2008-2009 QUALCOMM Incorporated.
3 */
4
5#include <linux/delay.h>
6#include <linux/slab.h>
7#include <linux/types.h>
8#include <linux/i2c.h>
9#include <linux/uaccess.h>
10#include <linux/miscdevice.h>
11#include <media/msm_camera.h>
12#include <mach/gpio.h>
13#include "mt9d112.h"
14
15/* Micron MT9D112 Registers and their values */
16/* Sensor Core Registers */
17#define  REG_MT9D112_MODEL_ID 0x3000
18#define  MT9D112_MODEL_ID     0x1580
19
20/*  SOC Registers Page 1  */
21#define  REG_MT9D112_SENSOR_RESET     0x301A
22#define  REG_MT9D112_STANDBY_CONTROL  0x3202
23#define  REG_MT9D112_MCU_BOOT         0x3386
24
25struct mt9d112_work {
26	struct work_struct work;
27};
28
29static struct  mt9d112_work *mt9d112_sensorw;
30static struct  i2c_client *mt9d112_client;
31
32struct mt9d112_ctrl {
33	const struct msm_camera_sensor_info *sensordata;
34};
35
36
37static struct mt9d112_ctrl *mt9d112_ctrl;
38
39static DECLARE_WAIT_QUEUE_HEAD(mt9d112_wait_queue);
40DECLARE_MUTEX(mt9d112_sem);
41
42
43/*=============================================================
44	EXTERNAL DECLARATIONS
45==============================================================*/
46extern struct mt9d112_reg mt9d112_regs;
47
48
49/*=============================================================*/
50
51static int mt9d112_reset(const struct msm_camera_sensor_info *dev)
52{
53	int rc = 0;
54
55	rc = gpio_request(dev->sensor_reset, "mt9d112");
56
57	if (!rc) {
58		rc = gpio_direction_output(dev->sensor_reset, 0);
59		mdelay(20);
60		rc = gpio_direction_output(dev->sensor_reset, 1);
61	}
62
63	gpio_free(dev->sensor_reset);
64	return rc;
65}
66
67static int32_t mt9d112_i2c_txdata(unsigned short saddr,
68	unsigned char *txdata, int length)
69{
70	struct i2c_msg msg[] = {
71		{
72			.addr = saddr,
73			.flags = 0,
74			.len = length,
75			.buf = txdata,
76		},
77	};
78
79	if (i2c_transfer(mt9d112_client->adapter, msg, 1) < 0) {
80		CDBG("mt9d112_i2c_txdata failed\n");
81		return -EIO;
82	}
83
84	return 0;
85}
86
87static int32_t mt9d112_i2c_write(unsigned short saddr,
88	unsigned short waddr, unsigned short wdata, enum mt9d112_width width)
89{
90	int32_t rc = -EIO;
91	unsigned char buf[4];
92
93	memset(buf, 0, sizeof(buf));
94	switch (width) {
95	case WORD_LEN: {
96		buf[0] = (waddr & 0xFF00)>>8;
97		buf[1] = (waddr & 0x00FF);
98		buf[2] = (wdata & 0xFF00)>>8;
99		buf[3] = (wdata & 0x00FF);
100
101		rc = mt9d112_i2c_txdata(saddr, buf, 4);
102	}
103		break;
104
105	case BYTE_LEN: {
106		buf[0] = waddr;
107		buf[1] = wdata;
108		rc = mt9d112_i2c_txdata(saddr, buf, 2);
109	}
110		break;
111
112	default:
113		break;
114	}
115
116	if (rc < 0)
117		CDBG(
118		"i2c_write failed, addr = 0x%x, val = 0x%x!\n",
119		waddr, wdata);
120
121	return rc;
122}
123
124static int32_t mt9d112_i2c_write_table(
125	struct mt9d112_i2c_reg_conf const *reg_conf_tbl,
126	int num_of_items_in_table)
127{
128	int i;
129	int32_t rc = -EIO;
130
131	for (i = 0; i < num_of_items_in_table; i++) {
132		rc = mt9d112_i2c_write(mt9d112_client->addr,
133			reg_conf_tbl->waddr, reg_conf_tbl->wdata,
134			reg_conf_tbl->width);
135		if (rc < 0)
136			break;
137		if (reg_conf_tbl->mdelay_time != 0)
138			mdelay(reg_conf_tbl->mdelay_time);
139		reg_conf_tbl++;
140	}
141
142	return rc;
143}
144
145static int mt9d112_i2c_rxdata(unsigned short saddr,
146	unsigned char *rxdata, int length)
147{
148	struct i2c_msg msgs[] = {
149	{
150		.addr   = saddr,
151		.flags = 0,
152		.len   = 2,
153		.buf   = rxdata,
154	},
155	{
156		.addr   = saddr,
157		.flags = I2C_M_RD,
158		.len   = length,
159		.buf   = rxdata,
160	},
161	};
162
163	if (i2c_transfer(mt9d112_client->adapter, msgs, 2) < 0) {
164		CDBG("mt9d112_i2c_rxdata failed!\n");
165		return -EIO;
166	}
167
168	return 0;
169}
170
171static int32_t mt9d112_i2c_read(unsigned short   saddr,
172	unsigned short raddr, unsigned short *rdata, enum mt9d112_width width)
173{
174	int32_t rc = 0;
175	unsigned char buf[4];
176
177	if (!rdata)
178		return -EIO;
179
180	memset(buf, 0, sizeof(buf));
181
182	switch (width) {
183	case WORD_LEN: {
184		buf[0] = (raddr & 0xFF00)>>8;
185		buf[1] = (raddr & 0x00FF);
186
187		rc = mt9d112_i2c_rxdata(saddr, buf, 2);
188		if (rc < 0)
189			return rc;
190
191		*rdata = buf[0] << 8 | buf[1];
192	}
193		break;
194
195	default:
196		break;
197	}
198
199	if (rc < 0)
200		CDBG("mt9d112_i2c_read failed!\n");
201
202	return rc;
203}
204
205static int32_t mt9d112_set_lens_roll_off(void)
206{
207	int32_t rc = 0;
208	rc = mt9d112_i2c_write_table(&mt9d112_regs.rftbl[0],
209								 mt9d112_regs.rftbl_size);
210	return rc;
211}
212
213static long mt9d112_reg_init(void)
214{
215	int32_t array_length;
216	int32_t i;
217	long rc;
218
219	/* PLL Setup Start */
220	rc = mt9d112_i2c_write_table(&mt9d112_regs.plltbl[0],
221					mt9d112_regs.plltbl_size);
222
223	if (rc < 0)
224		return rc;
225	/* PLL Setup End   */
226
227	array_length = mt9d112_regs.prev_snap_reg_settings_size;
228
229	/* Configure sensor for Preview mode and Snapshot mode */
230	for (i = 0; i < array_length; i++) {
231		rc = mt9d112_i2c_write(mt9d112_client->addr,
232		  mt9d112_regs.prev_snap_reg_settings[i].register_address,
233		  mt9d112_regs.prev_snap_reg_settings[i].register_value,
234		  WORD_LEN);
235
236		if (rc < 0)
237			return rc;
238	}
239
240	/* Configure for Noise Reduction, Saturation and Aperture Correction */
241	array_length = mt9d112_regs.noise_reduction_reg_settings_size;
242
243	for (i = 0; i < array_length; i++) {
244		rc = mt9d112_i2c_write(mt9d112_client->addr,
245			mt9d112_regs.noise_reduction_reg_settings[i].register_address,
246			mt9d112_regs.noise_reduction_reg_settings[i].register_value,
247			WORD_LEN);
248
249		if (rc < 0)
250			return rc;
251	}
252
253	/* Set Color Kill Saturation point to optimum value */
254	rc =
255	mt9d112_i2c_write(mt9d112_client->addr,
256	0x35A4,
257	0x0593,
258	WORD_LEN);
259	if (rc < 0)
260		return rc;
261
262	rc = mt9d112_i2c_write_table(&mt9d112_regs.stbl[0],
263					mt9d112_regs.stbl_size);
264	if (rc < 0)
265		return rc;
266
267	rc = mt9d112_set_lens_roll_off();
268	if (rc < 0)
269		return rc;
270
271	return 0;
272}
273
274static long mt9d112_set_sensor_mode(int mode)
275{
276	uint16_t clock;
277	long rc = 0;
278
279	switch (mode) {
280	case SENSOR_PREVIEW_MODE:
281		rc =
282			mt9d112_i2c_write(mt9d112_client->addr,
283				0x338C, 0xA20C, WORD_LEN);
284		if (rc < 0)
285			return rc;
286
287		rc =
288			mt9d112_i2c_write(mt9d112_client->addr,
289				0x3390, 0x0004, WORD_LEN);
290		if (rc < 0)
291			return rc;
292
293		rc =
294			mt9d112_i2c_write(mt9d112_client->addr,
295				0x338C, 0xA215, WORD_LEN);
296		if (rc < 0)
297			return rc;
298
299		rc =
300			mt9d112_i2c_write(mt9d112_client->addr,
301				0x3390, 0x0004, WORD_LEN);
302		if (rc < 0)
303			return rc;
304
305		rc =
306			mt9d112_i2c_write(mt9d112_client->addr,
307				0x338C, 0xA20B, WORD_LEN);
308		if (rc < 0)
309			return rc;
310
311		rc =
312			mt9d112_i2c_write(mt9d112_client->addr,
313				0x3390, 0x0000, WORD_LEN);
314		if (rc < 0)
315			return rc;
316
317		clock = 0x0250;
318
319		rc =
320			mt9d112_i2c_write(mt9d112_client->addr,
321				0x341C, clock, WORD_LEN);
322		if (rc < 0)
323			return rc;
324
325		rc =
326			mt9d112_i2c_write(mt9d112_client->addr,
327				0x338C, 0xA103, WORD_LEN);
328		if (rc < 0)
329			return rc;
330
331		rc =
332			mt9d112_i2c_write(mt9d112_client->addr,
333				0x3390, 0x0001, WORD_LEN);
334		if (rc < 0)
335			return rc;
336
337		mdelay(5);
338		break;
339
340	case SENSOR_SNAPSHOT_MODE:
341		/* Switch to lower fps for Snapshot */
342		rc =
343			mt9d112_i2c_write(mt9d112_client->addr,
344				0x341C, 0x0120, WORD_LEN);
345		if (rc < 0)
346			return rc;
347
348		rc =
349			mt9d112_i2c_write(mt9d112_client->addr,
350				0x338C, 0xA120, WORD_LEN);
351		if (rc < 0)
352			return rc;
353
354		rc =
355			mt9d112_i2c_write(mt9d112_client->addr,
356				0x3390, 0x0002, WORD_LEN);
357		if (rc < 0)
358			return rc;
359
360		mdelay(5);
361
362		rc =
363			mt9d112_i2c_write(mt9d112_client->addr,
364				0x338C, 0xA103, WORD_LEN);
365		if (rc < 0)
366			return rc;
367
368		rc =
369			mt9d112_i2c_write(mt9d112_client->addr,
370				0x3390, 0x0002, WORD_LEN);
371		if (rc < 0)
372			return rc;
373		break;
374
375	default:
376		return -EINVAL;
377	}
378
379	return 0;
380}
381
382static long mt9d112_set_effect(int mode, int effect)
383{
384	uint16_t reg_addr;
385	uint16_t reg_val;
386	long rc = 0;
387
388	switch (mode) {
389	case SENSOR_PREVIEW_MODE:
390		/* Context A Special Effects */
391		reg_addr = 0x2799;
392		break;
393
394	case SENSOR_SNAPSHOT_MODE:
395		/* Context B Special Effects */
396		reg_addr = 0x279B;
397		break;
398
399	default:
400		reg_addr = 0x2799;
401		break;
402	}
403
404	switch (effect) {
405	case CAMERA_EFFECT_OFF: {
406		reg_val = 0x6440;
407
408		rc = mt9d112_i2c_write(mt9d112_client->addr,
409			0x338C, reg_addr, WORD_LEN);
410		if (rc < 0)
411			return rc;
412
413		rc = mt9d112_i2c_write(mt9d112_client->addr,
414			0x3390, reg_val, WORD_LEN);
415		if (rc < 0)
416			return rc;
417	}
418			break;
419
420	case CAMERA_EFFECT_MONO: {
421		reg_val = 0x6441;
422		rc = mt9d112_i2c_write(mt9d112_client->addr,
423			0x338C, reg_addr, WORD_LEN);
424		if (rc < 0)
425			return rc;
426
427		rc = mt9d112_i2c_write(mt9d112_client->addr,
428			0x3390, reg_val, WORD_LEN);
429		if (rc < 0)
430			return rc;
431	}
432		break;
433
434	case CAMERA_EFFECT_NEGATIVE: {
435		reg_val = 0x6443;
436		rc = mt9d112_i2c_write(mt9d112_client->addr,
437			0x338C, reg_addr, WORD_LEN);
438		if (rc < 0)
439			return rc;
440
441		rc = mt9d112_i2c_write(mt9d112_client->addr,
442			0x3390, reg_val, WORD_LEN);
443		if (rc < 0)
444			return rc;
445	}
446		break;
447
448	case CAMERA_EFFECT_SOLARIZE: {
449		reg_val = 0x6445;
450		rc = mt9d112_i2c_write(mt9d112_client->addr,
451			0x338C, reg_addr, WORD_LEN);
452		if (rc < 0)
453			return rc;
454
455		rc = mt9d112_i2c_write(mt9d112_client->addr,
456			0x3390, reg_val, WORD_LEN);
457		if (rc < 0)
458			return rc;
459	}
460		break;
461
462	case CAMERA_EFFECT_SEPIA: {
463		reg_val = 0x6442;
464		rc = mt9d112_i2c_write(mt9d112_client->addr,
465			0x338C, reg_addr, WORD_LEN);
466		if (rc < 0)
467			return rc;
468
469		rc = mt9d112_i2c_write(mt9d112_client->addr,
470			0x3390, reg_val, WORD_LEN);
471		if (rc < 0)
472			return rc;
473	}
474		break;
475
476	case CAMERA_EFFECT_PASTEL:
477	case CAMERA_EFFECT_MOSAIC:
478	case CAMERA_EFFECT_RESIZE:
479		return -EINVAL;
480
481	default: {
482		reg_val = 0x6440;
483		rc = mt9d112_i2c_write(mt9d112_client->addr,
484			0x338C, reg_addr, WORD_LEN);
485		if (rc < 0)
486			return rc;
487
488		rc = mt9d112_i2c_write(mt9d112_client->addr,
489			0x3390, reg_val, WORD_LEN);
490		if (rc < 0)
491			return rc;
492
493		return -EINVAL;
494	}
495	}
496
497	/* Refresh Sequencer */
498	rc = mt9d112_i2c_write(mt9d112_client->addr,
499		0x338C, 0xA103, WORD_LEN);
500	if (rc < 0)
501		return rc;
502
503	rc = mt9d112_i2c_write(mt9d112_client->addr,
504		0x3390, 0x0005, WORD_LEN);
505
506	return rc;
507}
508
509static int mt9d112_sensor_init_probe(const struct msm_camera_sensor_info *data)
510{
511	uint16_t model_id = 0;
512	int rc = 0;
513
514	CDBG("init entry \n");
515	rc = mt9d112_reset(data);
516	if (rc < 0) {
517		CDBG("reset failed!\n");
518		goto init_probe_fail;
519	}
520
521	mdelay(5);
522
523	/* Micron suggested Power up block Start:
524	* Put MCU into Reset - Stop MCU */
525	rc = mt9d112_i2c_write(mt9d112_client->addr,
526		REG_MT9D112_MCU_BOOT, 0x0501, WORD_LEN);
527	if (rc < 0)
528		goto init_probe_fail;
529
530	/* Pull MCU from Reset - Start MCU */
531	rc = mt9d112_i2c_write(mt9d112_client->addr,
532		REG_MT9D112_MCU_BOOT, 0x0500, WORD_LEN);
533	if (rc < 0)
534		goto init_probe_fail;
535
536	mdelay(5);
537
538	/* Micron Suggested - Power up block */
539	rc = mt9d112_i2c_write(mt9d112_client->addr,
540		REG_MT9D112_SENSOR_RESET, 0x0ACC, WORD_LEN);
541	if (rc < 0)
542		goto init_probe_fail;
543
544	rc = mt9d112_i2c_write(mt9d112_client->addr,
545		REG_MT9D112_STANDBY_CONTROL, 0x0008, WORD_LEN);
546	if (rc < 0)
547		goto init_probe_fail;
548
549	/* FUSED_DEFECT_CORRECTION */
550	rc = mt9d112_i2c_write(mt9d112_client->addr,
551		0x33F4, 0x031D, WORD_LEN);
552	if (rc < 0)
553		goto init_probe_fail;
554
555	mdelay(5);
556
557	/* Micron suggested Power up block End */
558	/* Read the Model ID of the sensor */
559	rc = mt9d112_i2c_read(mt9d112_client->addr,
560		REG_MT9D112_MODEL_ID, &model_id, WORD_LEN);
561	if (rc < 0)
562		goto init_probe_fail;
563
564	CDBG("mt9d112 model_id = 0x%x\n", model_id);
565
566	/* Check if it matches it with the value in Datasheet */
567	if (model_id != MT9D112_MODEL_ID) {
568		rc = -EINVAL;
569		goto init_probe_fail;
570	}
571
572	rc = mt9d112_reg_init();
573	if (rc < 0)
574		goto init_probe_fail;
575
576	return rc;
577
578init_probe_fail:
579	return rc;
580}
581
582int mt9d112_sensor_init(const struct msm_camera_sensor_info *data)
583{
584	int rc = 0;
585
586	mt9d112_ctrl = kzalloc(sizeof(struct mt9d112_ctrl), GFP_KERNEL);
587	if (!mt9d112_ctrl) {
588		CDBG("mt9d112_init failed!\n");
589		rc = -ENOMEM;
590		goto init_done;
591	}
592
593	if (data)
594		mt9d112_ctrl->sensordata = data;
595
596	/* Input MCLK = 24MHz */
597	msm_camio_clk_rate_set(24000000);
598	mdelay(5);
599
600	msm_camio_camif_pad_reg_reset();
601
602	rc = mt9d112_sensor_init_probe(data);
603	if (rc < 0) {
604		CDBG("mt9d112_sensor_init failed!\n");
605		goto init_fail;
606	}
607
608init_done:
609	return rc;
610
611init_fail:
612	kfree(mt9d112_ctrl);
613	return rc;
614}
615
616static int mt9d112_init_client(struct i2c_client *client)
617{
618	/* Initialize the MSM_CAMI2C Chip */
619	init_waitqueue_head(&mt9d112_wait_queue);
620	return 0;
621}
622
623int mt9d112_sensor_config(void __user *argp)
624{
625	struct sensor_cfg_data cfg_data;
626	long   rc = 0;
627
628	if (copy_from_user(&cfg_data,
629			(void *)argp,
630			sizeof(struct sensor_cfg_data)))
631		return -EFAULT;
632
633	/* down(&mt9d112_sem); */
634
635	CDBG("mt9d112_ioctl, cfgtype = %d, mode = %d\n",
636		cfg_data.cfgtype, cfg_data.mode);
637
638		switch (cfg_data.cfgtype) {
639		case CFG_SET_MODE:
640			rc = mt9d112_set_sensor_mode(
641						cfg_data.mode);
642			break;
643
644		case CFG_SET_EFFECT:
645			rc = mt9d112_set_effect(cfg_data.mode,
646						cfg_data.cfg.effect);
647			break;
648
649		case CFG_GET_AF_MAX_STEPS:
650		default:
651			rc = -EINVAL;
652			break;
653		}
654
655	/* up(&mt9d112_sem); */
656
657	return rc;
658}
659
660int mt9d112_sensor_release(void)
661{
662	int rc = 0;
663
664	/* down(&mt9d112_sem); */
665
666	kfree(mt9d112_ctrl);
667	/* up(&mt9d112_sem); */
668
669	return rc;
670}
671
672static int mt9d112_i2c_probe(struct i2c_client *client,
673	const struct i2c_device_id *id)
674{
675	int rc = 0;
676	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
677		rc = -ENOTSUPP;
678		goto probe_failure;
679	}
680
681	mt9d112_sensorw =
682		kzalloc(sizeof(struct mt9d112_work), GFP_KERNEL);
683
684	if (!mt9d112_sensorw) {
685		rc = -ENOMEM;
686		goto probe_failure;
687	}
688
689	i2c_set_clientdata(client, mt9d112_sensorw);
690	mt9d112_init_client(client);
691	mt9d112_client = client;
692
693	CDBG("mt9d112_probe succeeded!\n");
694
695	return 0;
696
697probe_failure:
698	kfree(mt9d112_sensorw);
699	mt9d112_sensorw = NULL;
700	CDBG("mt9d112_probe failed!\n");
701	return rc;
702}
703
704static const struct i2c_device_id mt9d112_i2c_id[] = {
705	{ "mt9d112", 0},
706	{ },
707};
708
709static struct i2c_driver mt9d112_i2c_driver = {
710	.id_table = mt9d112_i2c_id,
711	.probe  = mt9d112_i2c_probe,
712	.remove = __exit_p(mt9d112_i2c_remove),
713	.driver = {
714		.name = "mt9d112",
715	},
716};
717
718static int mt9d112_sensor_probe(const struct msm_camera_sensor_info *info,
719				struct msm_sensor_ctrl *s)
720{
721	int rc = i2c_add_driver(&mt9d112_i2c_driver);
722	if (rc < 0 || mt9d112_client == NULL) {
723		rc = -ENOTSUPP;
724		goto probe_done;
725	}
726
727	/* Input MCLK = 24MHz */
728	msm_camio_clk_rate_set(24000000);
729	mdelay(5);
730
731	rc = mt9d112_sensor_init_probe(info);
732	if (rc < 0)
733		goto probe_done;
734
735	s->s_init = mt9d112_sensor_init;
736	s->s_release = mt9d112_sensor_release;
737	s->s_config  = mt9d112_sensor_config;
738
739probe_done:
740	CDBG("%s %s:%d\n", __FILE__, __func__, __LINE__);
741	return rc;
742}
743
744static int __mt9d112_probe(struct platform_device *pdev)
745{
746	return msm_camera_drv_start(pdev, mt9d112_sensor_probe);
747}
748
749static struct platform_driver msm_camera_driver = {
750	.probe = __mt9d112_probe,
751	.driver = {
752		.name = "msm_camera_mt9d112",
753		.owner = THIS_MODULE,
754	},
755};
756
757static int __init mt9d112_init(void)
758{
759	return platform_driver_register(&msm_camera_driver);
760}
761
762module_init(mt9d112_init);
763