11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************************
2f327ebbd004fb2f08291ca4c6637f5f27319683cLuca Risolia * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Controllers                                                             *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                                                         *
5f327ebbd004fb2f08291ca4c6637f5f27319683cLuca Risolia * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                                                         *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify    *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by    *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or       *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version.                                     *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                                                         *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful,         *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details.                            *
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                                                                         *
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License       *
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software             *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ***************************************************************************/
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sn9c102_sensor.h"
23d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil#include "sn9c102_devtable.h"
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mi0343_init(struct sn9c102_device* cam)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31c680dd603857d7218b84751e9f6f0654bbfbefa2Trent Piepho	err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
32c680dd603857d7218b84751e9f6f0654bbfbefa2Trent Piepho				       {0x0a, 0x14}, {0x40, 0x01},
33c680dd603857d7218b84751e9f6f0654bbfbefa2Trent Piepho				       {0x20, 0x17}, {0x07, 0x18},
34c680dd603857d7218b84751e9f6f0654bbfbefa2Trent Piepho				       {0xa0, 0x19});
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
37f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x00, 0x01, 0, 0);
38f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
39f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x00, 0x00, 0, 0);
40f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
41f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x01, 0xe1, 0, 0);
42f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
43f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x02, 0x81, 0, 0);
44f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
45f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x00, 0x17, 0, 0);
46f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
47f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x00, 0x11, 0, 0);
48f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
49f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia					 0x04, 0x9a, 0, 0);
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehabstatic int mi0343_get_ctrl(struct sn9c102_device* cam,
56d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab			   struct v4l2_control* ctrl)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
58f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
59480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia	u8 data[2];
60f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ctrl->id) {
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_EXPOSURE:
63480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
64480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
66480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		ctrl->value = data[0];
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_GAIN:
69480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
70480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_HFLIP:
74480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
75480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
77480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		ctrl->value = data[1] & 0x20 ? 1 : 0;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_VFLIP:
80480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
81480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
83480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		ctrl->value = data[1] & 0x80 ? 1 : 0;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_RED_BALANCE:
86480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
87480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_BLUE_BALANCE:
91480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
92480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SN9C102_V4L2_CID_GREEN_BALANCE:
96480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
97480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia					     data) < 0)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EIO;
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ctrl->id) {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_GAIN:
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_RED_BALANCE:
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_BLUE_BALANCE:
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SN9C102_V4L2_CID_GREEN_BALANCE:
109480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia		ctrl->value = data[1] | (data[0] << 8);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ctrl->value -= 0x10;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ctrl->value -= 0x60;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ctrl->value -= 0xe0;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehabstatic int mi0343_set_ctrl(struct sn9c102_device* cam,
123d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab			   const struct v4l2_control* ctrl)
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
125f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 reg = 0;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ctrl->id) {
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_GAIN:
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_RED_BALANCE:
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_BLUE_BALANCE:
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SN9C102_V4L2_CID_GREEN_BALANCE:
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ctrl->value <= (0x3f-0x10))
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reg = 0x10 + ctrl->value;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reg = 0x60 + (ctrl->value - (0x3f-0x10));
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ctrl->id) {
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_EXPOSURE:
145f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
146d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x09, ctrl->value, 0x00,
147d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_GAIN:
150f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
151d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x35, reg >> 8, reg & 0xff,
152d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_HFLIP:
155f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
156d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x20, ctrl->value ? 0x40:0x00,
157d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 ctrl->value ? 0x20:0x00,
158d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_VFLIP:
161f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
162d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x20, ctrl->value ? 0x80:0x00,
163d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 ctrl->value ? 0x80:0x00,
164d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_RED_BALANCE:
167f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
168d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x2d, reg >> 8, reg & 0xff,
169d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case V4L2_CID_BLUE_BALANCE:
172f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
173d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x2c, reg >> 8, reg & 0xff,
174d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SN9C102_V4L2_CID_GREEN_BALANCE:
177f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
178d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x2b, reg >> 8, reg & 0xff,
179d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
180f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
181d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x2e, reg >> 8, reg & 0xff,
182d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0, 0);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err ? -EIO : 0;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
192d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehabstatic int mi0343_set_crop(struct sn9c102_device* cam,
193d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab			    const struct v4l2_rect* rect)
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
195f327ebbd004fb2f08291ca4c6637f5f27319683cLuca Risolia	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err += sn9c102_write_reg(cam, h_start, 0x12);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err += sn9c102_write_reg(cam, v_start, 0x13);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
207d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehabstatic int mi0343_set_pix_format(struct sn9c102_device* cam,
208d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab				 const struct v4l2_pix_format* pix)
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
210f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
214f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
215d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x0a, 0x00, 0x03, 0, 0);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err += sn9c102_write_reg(cam, 0x20, 0x19);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
218f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
219d56410e0a594150c5ca06319da7bc8901c4d455eMauro Carvalho Chehab						 0x0a, 0x00, 0x05, 0, 0);
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err += sn9c102_write_reg(cam, 0xa0, 0x19);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
227480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risoliastatic const struct sn9c102_sensor mi0343 = {
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "MI-0343",
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
230f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.frequency = SN9C102_I2C_100KHZ,
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.interface = SN9C102_I2C_2WIRES,
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.i2c_slave_id = 0x5d,
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init = &mi0343_init,
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.qctrl = {
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_EXPOSURE,
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_INTEGER,
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "exposure",
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0x00,
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = 0x0f,
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 0x01,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0x06,
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_GAIN,
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_INTEGER,
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "global gain",
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0x00,
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 0x01,
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0x00,
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_HFLIP,
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_BOOLEAN,
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "horizontal mirror",
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0,
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = 1,
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 1,
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0,
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_VFLIP,
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_BOOLEAN,
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "vertical mirror",
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0,
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = 1,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 1,
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0,
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_RED_BALANCE,
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_INTEGER,
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "red balance",
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0x00,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 0x01,
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0x00,
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = V4L2_CID_BLUE_BALANCE,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_INTEGER,
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "blue balance",
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0x00,
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 0x01,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0x00,
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.id = SN9C102_V4L2_CID_GREEN_BALANCE,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.type = V4L2_CTRL_TYPE_INTEGER,
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.name = "green balance",
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.minimum = 0x00,
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.step = 0x01,
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.default_value = 0x00,
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.flags = 0,
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_ctrl = &mi0343_get_ctrl,
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_ctrl = &mi0343_set_ctrl,
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.cropcap = {
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.bounds = {
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.left = 0,
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.top = 0,
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.width = 640,
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.height = 480,
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.defrect = {
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.left = 0,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.top = 0,
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.width = 640,
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			.height = 480,
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		},
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_crop = &mi0343_set_crop,
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.pix_format = {
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.width = 640,
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.height = 480,
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.pixelformat = V4L2_PIX_FMT_SBGGR8,
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.priv = 8,
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_pix_format = &mi0343_set_pix_format
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sn9c102_probe_mi0343(struct sn9c102_device* cam)
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
336480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia	u8 data[2];
337c680dd603857d7218b84751e9f6f0654bbfbefa2Trent Piepho
338480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia	if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
339480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia				     {0x28, 0x17}))
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
343f423b9a86a6dd3d2bc08d78f4d21525a14c40a6bLuca Risolia				     2, data) < 0)
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
346480b55c26e2f6408e86f22a69fcecc29e019e819Luca Risolia	if (data[1] != 0x42 || data[0] != 0xe3)
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sn9c102_attach_sensor(cam, &mi0343);
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
353