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