// SPDX-License-Identifier: GPL-2.0+
/*
* IMI RDACM20 GMSL Camera Driver
*
* Copyright (C) 2017-2020 Jacopo Mondi
* Copyright (C) 2017-2020 Kieran Bingham
* Copyright (C) 2017-2019 Laurent Pinchart
* Copyright (C) 2017-2019 Niklas Söderlund
* Copyright (C) 2016 Renesas Electronics Corporation
* Copyright (C) 2015 Cogent Embedded, Inc.
*/
/*
* The camera is made of an Omnivision OV10635 sensor connected to a Maxim
* MAX9271 GMSL serializer.
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include "max9271.h"
#define OV10635_I2C_ADDRESS 0 x30
#define OV10635_SOFTWARE_RESET 0 x0103
#define OV10635_PID 0 x300a
#define OV10635_VER 0 x300b
#define OV10635_SC_CMMN_SCCB_ID 0 x300c
#define OV10635_SC_CMMN_SCCB_ID_SELECT BIT(0 )
#define OV10635_VERSION 0 xa635
#define OV10635_WIDTH 1280
#define OV10635_HEIGHT 800
/* VTS = PCLK / FPS / HTS / 2 (= 88MHz / 1572 / 30 / 2) */
#define OV10635_HTS 1572
/* FPS = 29,9998 */
#define OV10635_VTS 933
/*
* As the drivers supports a single MEDIA_BUS_FMT_UYVY8_1X16 format we
* can harcode the pixel rate.
*
* PCLK is fed through the system clock, programmed @88MHz.
* MEDIA_BUS_FMT_UYVY8_1X16 format = 2 samples per pixel.
*
* Pixelrate = PCLK / 2
* FPS = (OV10635_VTS * OV10635_HTS) / PixelRate
* = 29,9998
*/
#define OV10635_PIXEL_RATE (44000000 )
static const struct ov10635_reg {
u16 reg;
u8 val;
} ov10635_regs_wizard[] = {
{ 0 x301b, 0 xff }, { 0 x301c, 0 xff }, { 0 x301a, 0 xff }, { 0 x3011, 0 x42 },
{ 0 x6900, 0 x0c }, { 0 x6901, 0 x19 }, { 0 x3503, 0 x10 }, { 0 x3025, 0 x03 },
{ 0 x3003, 0 x16 }, { 0 x3004, 0 x30 }, { 0 x3005, 0 x40 }, { 0 x3006, 0 x91 },
{ 0 x3600, 0 x74 }, { 0 x3601, 0 x2b }, { 0 x3612, 0 x00 }, { 0 x3611, 0 x67 },
{ 0 x3633, 0 xca }, { 0 x3602, 0 xaf }, { 0 x3603, 0 x04 }, { 0 x3630, 0 x28 },
{ 0 x3631, 0 x16 }, { 0 x3714, 0 x10 }, { 0 x371d, 0 x01 }, { 0 x4300, 0 x3a },
{ 0 x3007, 0 x01 }, { 0 x3024, 0 x03 }, { 0 x3020, 0 x0a }, { 0 x3702, 0 x0d },
{ 0 x3703, 0 x20 }, { 0 x3704, 0 x15 }, { 0 x3709, 0 xa8 }, { 0 x370c, 0 xc7 },
{ 0 x370d, 0 x80 }, { 0 x3712, 0 x00 }, { 0 x3713, 0 x20 }, { 0 x3715, 0 x04 },
{ 0 x381d, 0 x40 }, { 0 x381c, 0 x00 }, { 0 x3822, 0 x50 }, { 0 x3824, 0 x10 },
{ 0 x3815, 0 x8c }, { 0 x3804, 0 x05 }, { 0 x3805, 0 x1f }, { 0 x3800, 0 x00 },
{ 0 x3801, 0 x00 }, { 0 x3806, 0 x03 }, { 0 x3807, 0 x28 }, { 0 x3802, 0 x00 },
{ 0 x3803, 0 x07 }, { 0 x3808, 0 x05 }, { 0 x3809, 0 x00 }, { 0 x380a, 0 x03 },
{ 0 x380b, 0 x20 }, { 0 x380c, OV10635_HTS >> 8 },
{ 0 x380d, OV10635_HTS & 0 xff }, { 0 x380e, OV10635_VTS >> 8 },
{ 0 x380f, OV10635_VTS & 0 xff }, { 0 x3813, 0 x02 }, { 0 x3811, 0 x08 },
{ 0 x381f, 0 x0c }, { 0 x3819, 0 x04 }, { 0 x3804, 0 x01 }, { 0 x3805, 0 x00 },
{ 0 x3828, 0 x03 }, { 0 x3829, 0 x10 }, { 0 x382a, 0 x10 }, { 0 x3621, 0 x63 },
{ 0 x5005, 0 x08 }, { 0 x56d5, 0 x00 }, { 0 x56d6, 0 x80 }, { 0 x56d7, 0 x00 },
{ 0 x56d8, 0 x00 }, { 0 x56d9, 0 x00 }, { 0 x56da, 0 x80 }, { 0 x56db, 0 x00 },
{ 0 x56dc, 0 x00 }, { 0 x56e8, 0 x00 }, { 0 x56e9, 0 x7f }, { 0 x56ea, 0 x00 },
{ 0 x56eb, 0 x7f }, { 0 x5100, 0 x00 }, { 0 x5101, 0 x80 }, { 0 x5102, 0 x00 },
{ 0 x5103, 0 x80 }, { 0 x5104, 0 x00 }, { 0 x5105, 0 x80 }, { 0 x5106, 0 x00 },
{ 0 x5107, 0 x80 }, { 0 x5108, 0 x00 }, { 0 x5109, 0 x00 }, { 0 x510a, 0 x00 },
{ 0 x510b, 0 x00 }, { 0 x510c, 0 x00 }, { 0 x510d, 0 x00 }, { 0 x510e, 0 x00 },
{ 0 x510f, 0 x00 }, { 0 x5110, 0 x00 }, { 0 x5111, 0 x80 }, { 0 x5112, 0 x00 },
{ 0 x5113, 0 x80 }, { 0 x5114, 0 x00 }, { 0 x5115, 0 x80 }, { 0 x5116, 0 x00 },
{ 0 x5117, 0 x80 }, { 0 x5118, 0 x00 }, { 0 x5119, 0 x00 }, { 0 x511a, 0 x00 },
{ 0 x511b, 0 x00 }, { 0 x511c, 0 x00 }, { 0 x511d, 0 x00 }, { 0 x511e, 0 x00 },
{ 0 x511f, 0 x00 }, { 0 x56d0, 0 x00 }, { 0 x5006, 0 x04 }, { 0 x5608, 0 x05 },
{ 0 x52d7, 0 x06 }, { 0 x528d, 0 x08 }, { 0 x5293, 0 x12 }, { 0 x52d3, 0 x12 },
{ 0 x5288, 0 x06 }, { 0 x5289, 0 x20 }, { 0 x52c8, 0 x06 }, { 0 x52c9, 0 x20 },
{ 0 x52cd, 0 x04 }, { 0 x5381, 0 x00 }, { 0 x5382, 0 xff }, { 0 x5589, 0 x76 },
{ 0 x558a, 0 x47 }, { 0 x558b, 0 xef }, { 0 x558c, 0 xc9 }, { 0 x558d, 0 x49 },
{ 0 x558e, 0 x30 }, { 0 x558f, 0 x67 }, { 0 x5590, 0 x3f }, { 0 x5591, 0 xf0 },
{ 0 x5592, 0 x10 }, { 0 x55a2, 0 x6d }, { 0 x55a3, 0 x55 }, { 0 x55a4, 0 xc3 },
{ 0 x55a5, 0 xb5 }, { 0 x55a6, 0 x43 }, { 0 x55a7, 0 x38 }, { 0 x55a8, 0 x5f },
{ 0 x55a9, 0 x4b }, { 0 x55aa, 0 xf0 }, { 0 x55ab, 0 x10 }, { 0 x5581, 0 x52 },
{ 0 x5300, 0 x01 }, { 0 x5301, 0 x00 }, { 0 x5302, 0 x00 }, { 0 x5303, 0 x0e },
{ 0 x5304, 0 x00 }, { 0 x5305, 0 x0e }, { 0 x5306, 0 x00 }, { 0 x5307, 0 x36 },
{ 0 x5308, 0 x00 }, { 0 x5309, 0 xd9 }, { 0 x530a, 0 x00 }, { 0 x530b, 0 x0f },
{ 0 x530c, 0 x00 }, { 0 x530d, 0 x2c }, { 0 x530e, 0 x00 }, { 0 x530f, 0 x59 },
{ 0 x5310, 0 x00 }, { 0 x5311, 0 x7b }, { 0 x5312, 0 x00 }, { 0 x5313, 0 x22 },
{ 0 x5314, 0 x00 }, { 0 x5315, 0 xd5 }, { 0 x5316, 0 x00 }, { 0 x5317, 0 x13 },
{ 0 x5318, 0 x00 }, { 0 x5319, 0 x18 }, { 0 x531a, 0 x00 }, { 0 x531b, 0 x26 },
{ 0 x531c, 0 x00 }, { 0 x531d, 0 xdc }, { 0 x531e, 0 x00 }, { 0 x531f, 0 x02 },
{ 0 x5320, 0 x00 }, { 0 x5321, 0 x24 }, { 0 x5322, 0 x00 }, { 0 x5323, 0 x56 },
{ 0 x5324, 0 x00 }, { 0 x5325, 0 x85 }, { 0 x5326, 0 x00 }, { 0 x5327, 0 x20 },
{ 0 x5609, 0 x01 }, { 0 x560a, 0 x40 }, { 0 x560b, 0 x01 }, { 0 x560c, 0 x40 },
{ 0 x560d, 0 x00 }, { 0 x560e, 0 xfa }, { 0 x560f, 0 x00 }, { 0 x5610, 0 xfa },
{ 0 x5611, 0 x02 }, { 0 x5612, 0 x80 }, { 0 x5613, 0 x02 }, { 0 x5614, 0 x80 },
{ 0 x5615, 0 x01 }, { 0 x5616, 0 x2c }, { 0 x5617, 0 x01 }, { 0 x5618, 0 x2c },
{ 0 x563b, 0 x01 }, { 0 x563c, 0 x01 }, { 0 x563d, 0 x01 }, { 0 x563e, 0 x01 },
{ 0 x563f, 0 x03 }, { 0 x5640, 0 x03 }, { 0 x5641, 0 x03 }, { 0 x5642, 0 x05 },
{ 0 x5643, 0 x09 }, { 0 x5644, 0 x05 }, { 0 x5645, 0 x05 }, { 0 x5646, 0 x05 },
{ 0 x5647, 0 x05 }, { 0 x5651, 0 x00 }, { 0 x5652, 0 x80 }, { 0 x521a, 0 x01 },
{ 0 x521b, 0 x03 }, { 0 x521c, 0 x06 }, { 0 x521d, 0 x0a }, { 0 x521e, 0 x0e },
{ 0 x521f, 0 x12 }, { 0 x5220, 0 x16 }, { 0 x5223, 0 x02 }, { 0 x5225, 0 x04 },
{ 0 x5227, 0 x08 }, { 0 x5229, 0 x0c }, { 0 x522b, 0 x12 }, { 0 x522d, 0 x18 },
{ 0 x522f, 0 x1e }, { 0 x5241, 0 x04 }, { 0 x5242, 0 x01 }, { 0 x5243, 0 x03 },
{ 0 x5244, 0 x06 }, { 0 x5245, 0 x0a }, { 0 x5246, 0 x0e }, { 0 x5247, 0 x12 },
{ 0 x5248, 0 x16 }, { 0 x524a, 0 x03 }, { 0 x524c, 0 x04 }, { 0 x524e, 0 x08 },
{ 0 x5250, 0 x0c }, { 0 x5252, 0 x12 }, { 0 x5254, 0 x18 }, { 0 x5256, 0 x1e },
/* fifo_line_length = 2*hts */
{ 0 x4606, (2 * OV10635_HTS) >> 8 }, { 0 x4607, (2 * OV10635_HTS) & 0 xff },
/* fifo_hsync_start = 2*(hts - xres) */
{ 0 x460a, (2 * (OV10635_HTS - OV10635_WIDTH)) >> 8 },
{ 0 x460b, (2 * (OV10635_HTS - OV10635_WIDTH)) & 0 xff },
{ 0 x460c, 0 x00 }, { 0 x4620, 0 x0e },
/* BT601: 0x08 is also acceptable as HS/VS mode */
{ 0 x4700, 0 x04 }, { 0 x4701, 0 x00 }, { 0 x4702, 0 x01 }, { 0 x4004, 0 x04 },
{ 0 x4005, 0 x18 }, { 0 x4001, 0 x06 }, { 0 x4050, 0 x22 }, { 0 x4051, 0 x24 },
{ 0 x4052, 0 x02 }, { 0 x4057, 0 x9c }, { 0 x405a, 0 x00 }, { 0 x4202, 0 x02 },
{ 0 x3023, 0 x10 }, { 0 x0100, 0 x01 }, { 0 x0100, 0 x01 }, { 0 x6f10, 0 x07 },
{ 0 x6f11, 0 x82 }, { 0 x6f12, 0 x04 }, { 0 x6f13, 0 x00 }, { 0 xd000, 0 x19 },
{ 0 xd001, 0 xa0 }, { 0 xd002, 0 x00 }, { 0 xd003, 0 x01 }, { 0 xd004, 0 xa9 },
{ 0 xd005, 0 xad }, { 0 xd006, 0 x10 }, { 0 xd007, 0 x40 }, { 0 xd008, 0 x44 },
{ 0 xd009, 0 x00 }, { 0 xd00a, 0 x68 }, { 0 xd00b, 0 x00 }, { 0 xd00c, 0 x15 },
{ 0 xd00d, 0 x00 }, { 0 xd00e, 0 x00 }, { 0 xd00f, 0 x00 }, { 0 xd040, 0 x9c },
{ 0 xd041, 0 x21 }, { 0 xd042, 0 xff }, { 0 xd043, 0 xf8 }, { 0 xd044, 0 xd4 },
{ 0 xd045, 0 x01 }, { 0 xd046, 0 x48 }, { 0 xd047, 0 x00 }, { 0 xd048, 0 xd4 },
{ 0 xd049, 0 x01 }, { 0 xd04a, 0 x50 }, { 0 xd04b, 0 x04 }, { 0 xd04c, 0 x18 },
{ 0 xd04d, 0 x60 }, { 0 xd04e, 0 x00 }, { 0 xd04f, 0 x01 }, { 0 xd050, 0 xa8 },
{ 0 xd051, 0 x63 }, { 0 xd052, 0 x02 }, { 0 xd053, 0 xa4 }, { 0 xd054, 0 x85 },
{ 0 xd055, 0 x43 }, { 0 xd056, 0 x00 }, { 0 xd057, 0 x00 }, { 0 xd058, 0 x18 },
{ 0 xd059, 0 x60 }, { 0 xd05a, 0 x00 }, { 0 xd05b, 0 x01 }, { 0 xd05c, 0 xa8 },
{ 0 xd05d, 0 x63 }, { 0 xd05e, 0 x03 }, { 0 xd05f, 0 xf0 }, { 0 xd060, 0 x98 },
{ 0 xd061, 0 xa3 }, { 0 xd062, 0 x00 }, { 0 xd063, 0 x00 }, { 0 xd064, 0 x8c },
{ 0 xd065, 0 x6a }, { 0 xd066, 0 x00 }, { 0 xd067, 0 x6e }, { 0 xd068, 0 xe5 },
{ 0 xd069, 0 x85 }, { 0 xd06a, 0 x18 }, { 0 xd06b, 0 x00 }, { 0 xd06c, 0 x10 },
{ 0 xd06d, 0 x00 }, { 0 xd06e, 0 x00 }, { 0 xd06f, 0 x10 }, { 0 xd070, 0 x9c },
{ 0 xd071, 0 x80 }, { 0 xd072, 0 x00 }, { 0 xd073, 0 x03 }, { 0 xd074, 0 x18 },
{ 0 xd075, 0 x60 }, { 0 xd076, 0 x00 }, { 0 xd077, 0 x01 }, { 0 xd078, 0 xa8 },
{ 0 xd079, 0 x63 }, { 0 xd07a, 0 x07 }, { 0 xd07b, 0 x80 }, { 0 xd07c, 0 x07 },
{ 0 xd07d, 0 xff }, { 0 xd07e, 0 xf9 }, { 0 xd07f, 0 x03 }, { 0 xd080, 0 x8c },
{ 0 xd081, 0 x63 }, { 0 xd082, 0 x00 }, { 0 xd083, 0 x00 }, { 0 xd084, 0 xa5 },
{ 0 xd085, 0 x6b }, { 0 xd086, 0 x00 }, { 0 xd087, 0 xff }, { 0 xd088, 0 x18 },
{ 0 xd089, 0 x80 }, { 0 xd08a, 0 x00 }, { 0 xd08b, 0 x01 }, { 0 xd08c, 0 xa8 },
{ 0 xd08d, 0 x84 }, { 0 xd08e, 0 x01 }, { 0 xd08f, 0 x04 }, { 0 xd090, 0 xe1 },
{ 0 xd091, 0 x6b }, { 0 xd092, 0 x58 }, { 0 xd093, 0 x00 }, { 0 xd094, 0 x94 },
{ 0 xd095, 0 x6a }, { 0 xd096, 0 x00 }, { 0 xd097, 0 x70 }, { 0 xd098, 0 xe1 },
{ 0 xd099, 0 x6b }, { 0 xd09a, 0 x20 }, { 0 xd09b, 0 x00 }, { 0 xd09c, 0 x95 },
{ 0 xd09d, 0 x6b }, { 0 xd09e, 0 x00 }, { 0 xd09f, 0 x00 }, { 0 xd0a0, 0 xe4 },
{ 0 xd0a1, 0 x8b }, { 0 xd0a2, 0 x18 }, { 0 xd0a3, 0 x00 }, { 0 xd0a4, 0 x0c },
{ 0 xd0a5, 0 x00 }, { 0 xd0a6, 0 x00 }, { 0 xd0a7, 0 x23 }, { 0 xd0a8, 0 x15 },
{ 0 xd0a9, 0 x00 }, { 0 xd0aa, 0 x00 }, { 0 xd0ab, 0 x00 }, { 0 xd0ac, 0 x18 },
{ 0 xd0ad, 0 x60 }, { 0 xd0ae, 0 x80 }, { 0 xd0af, 0 x06 }, { 0 xd0b0, 0 xa8 },
{ 0 xd0b1, 0 x83 }, { 0 xd0b2, 0 x40 }, { 0 xd0b3, 0 x08 }, { 0 xd0b4, 0 xa8 },
{ 0 xd0b5, 0 xe3 }, { 0 xd0b6, 0 x38 }, { 0 xd0b7, 0 x2a }, { 0 xd0b8, 0 xa8 },
{ 0 xd0b9, 0 xc3 }, { 0 xd0ba, 0 x40 }, { 0 xd0bb, 0 x09 }, { 0 xd0bc, 0 xa8 },
{ 0 xd0bd, 0 xa3 }, { 0 xd0be, 0 x38 }, { 0 xd0bf, 0 x29 }, { 0 xd0c0, 0 x8c },
{ 0 xd0c1, 0 x65 }, { 0 xd0c2, 0 x00 }, { 0 xd0c3, 0 x00 }, { 0 xd0c4, 0 xd8 },
{ 0 xd0c5, 0 x04 }, { 0 xd0c6, 0 x18 }, { 0 xd0c7, 0 x00 }, { 0 xd0c8, 0 x8c },
{ 0 xd0c9, 0 x67 }, { 0 xd0ca, 0 x00 }, { 0 xd0cb, 0 x00 }, { 0 xd0cc, 0 xd8 },
{ 0 xd0cd, 0 x06 }, { 0 xd0ce, 0 x18 }, { 0 xd0cf, 0 x00 }, { 0 xd0d0, 0 x18 },
{ 0 xd0d1, 0 x60 }, { 0 xd0d2, 0 x80 }, { 0 xd0d3, 0 x06 }, { 0 xd0d4, 0 xa8 },
{ 0 xd0d5, 0 xe3 }, { 0 xd0d6, 0 x67 }, { 0 xd0d7, 0 x02 }, { 0 xd0d8, 0 xa9 },
{ 0 xd0d9, 0 x03 }, { 0 xd0da, 0 x67 }, { 0 xd0db, 0 x03 }, { 0 xd0dc, 0 xa8 },
{ 0 xd0dd, 0 xc3 }, { 0 xd0de, 0 x3d }, { 0 xd0df, 0 x05 }, { 0 xd0e0, 0 x8c },
{ 0 xd0e1, 0 x66 }, { 0 xd0e2, 0 x00 }, { 0 xd0e3, 0 x00 }, { 0 xd0e4, 0 xb8 },
{ 0 xd0e5, 0 x63 }, { 0 xd0e6, 0 x00 }, { 0 xd0e7, 0 x18 }, { 0 xd0e8, 0 xb8 },
{ 0 xd0e9, 0 x63 }, { 0 xd0ea, 0 x00 }, { 0 xd0eb, 0 x98 }, { 0 xd0ec, 0 xbc },
{ 0 xd0ed, 0 x03 }, { 0 xd0ee, 0 x00 }, { 0 xd0ef, 0 x00 }, { 0 xd0f0, 0 x10 },
{ 0 xd0f1, 0 x00 }, { 0 xd0f2, 0 x00 }, { 0 xd0f3, 0 x16 }, { 0 xd0f4, 0 xb8 },
{ 0 xd0f5, 0 x83 }, { 0 xd0f6, 0 x00 }, { 0 xd0f7, 0 x19 }, { 0 xd0f8, 0 x8c },
{ 0 xd0f9, 0 x67 }, { 0 xd0fa, 0 x00 }, { 0 xd0fb, 0 x00 }, { 0 xd0fc, 0 xb8 },
{ 0 xd0fd, 0 xa4 }, { 0 xd0fe, 0 x00 }, { 0 xd0ff, 0 x98 }, { 0 xd100, 0 xb8 },
{ 0 xd101, 0 x83 }, { 0 xd102, 0 x00 }, { 0 xd103, 0 x08 }, { 0 xd104, 0 x8c },
{ 0 xd105, 0 x68 }, { 0 xd106, 0 x00 }, { 0 xd107, 0 x00 }, { 0 xd108, 0 xe0 },
{ 0 xd109, 0 x63 }, { 0 xd10a, 0 x20 }, { 0 xd10b, 0 x04 }, { 0 xd10c, 0 xe0 },
{ 0 xd10d, 0 x65 }, { 0 xd10e, 0 x18 }, { 0 xd10f, 0 x00 }, { 0 xd110, 0 xa4 },
{ 0 xd111, 0 x83 }, { 0 xd112, 0 xff }, { 0 xd113, 0 xff }, { 0 xd114, 0 xb8 },
{ 0 xd115, 0 x64 }, { 0 xd116, 0 x00 }, { 0 xd117, 0 x48 }, { 0 xd118, 0 xd8 },
{ 0 xd119, 0 x07 }, { 0 xd11a, 0 x18 }, { 0 xd11b, 0 x00 }, { 0 xd11c, 0 xd8 },
{ 0 xd11d, 0 x08 }, { 0 xd11e, 0 x20 }, { 0 xd11f, 0 x00 }, { 0 xd120, 0 x9c },
{ 0 xd121, 0 x60 }, { 0 xd122, 0 x00 }, { 0 xd123, 0 x00 }, { 0 xd124, 0 xd8 },
{ 0 xd125, 0 x06 }, { 0 xd126, 0 x18 }, { 0 xd127, 0 x00 }, { 0 xd128, 0 x00 },
{ 0 xd129, 0 x00 }, { 0 xd12a, 0 x00 }, { 0 xd12b, 0 x08 }, { 0 xd12c, 0 x15 },
{ 0 xd12d, 0 x00 }, { 0 xd12e, 0 x00 }, { 0 xd12f, 0 x00 }, { 0 xd130, 0 x8c },
{ 0 xd131, 0 x6a }, { 0 xd132, 0 x00 }, { 0 xd133, 0 x76 }, { 0 xd134, 0 xbc },
{ 0 xd135, 0 x23 }, { 0 xd136, 0 x00 }, { 0 xd137, 0 x00 }, { 0 xd138, 0 x13 },
{ 0 xd139, 0 xff }, { 0 xd13a, 0 xff }, { 0 xd13b, 0 xe6 }, { 0 xd13c, 0 x18 },
{ 0 xd13d, 0 x60 }, { 0 xd13e, 0 x80 }, { 0 xd13f, 0 x06 }, { 0 xd140, 0 x03 },
{ 0 xd141, 0 xff }, { 0 xd142, 0 xff }, { 0 xd143, 0 xdd }, { 0 xd144, 0 xa8 },
{ 0 xd145, 0 x83 }, { 0 xd146, 0 x40 }, { 0 xd147, 0 x08 }, { 0 xd148, 0 x85 },
{ 0 xd149, 0 x21 }, { 0 xd14a, 0 x00 }, { 0 xd14b, 0 x00 }, { 0 xd14c, 0 x85 },
{ 0 xd14d, 0 x41 }, { 0 xd14e, 0 x00 }, { 0 xd14f, 0 x04 }, { 0 xd150, 0 x44 },
{ 0 xd151, 0 x00 }, { 0 xd152, 0 x48 }, { 0 xd153, 0 x00 }, { 0 xd154, 0 x9c },
{ 0 xd155, 0 x21 }, { 0 xd156, 0 x00 }, { 0 xd157, 0 x08 }, { 0 x6f0e, 0 x03 },
{ 0 x6f0f, 0 x00 }, { 0 x460e, 0 x08 }, { 0 x460f, 0 x01 }, { 0 x4610, 0 x00 },
{ 0 x4611, 0 x01 }, { 0 x4612, 0 x00 }, { 0 x4613, 0 x01 },
/* 8 bits */
{ 0 x4605, 0 x08 },
/* Swap data bits order [9:0] -> [0:9] */
{ 0 x4709, 0 x10 }, { 0 x4608, 0 x00 }, { 0 x4609, 0 x08 }, { 0 x6804, 0 x00 },
{ 0 x6805, 0 x06 }, { 0 x6806, 0 x00 }, { 0 x5120, 0 x00 }, { 0 x3510, 0 x00 },
{ 0 x3504, 0 x00 }, { 0 x6800, 0 x00 }, { 0 x6f0d, 0 x01 },
/* PCLK falling edge */
{ 0 x4708, 0 x01 }, { 0 x5000, 0 xff }, { 0 x5001, 0 xbf }, { 0 x5002, 0 x7e },
{ 0 x503d, 0 x00 }, { 0 xc450, 0 x01 }, { 0 xc452, 0 x04 }, { 0 xc453, 0 x00 },
{ 0 xc454, 0 x00 }, { 0 xc455, 0 x01 }, { 0 xc456, 0 x01 }, { 0 xc457, 0 x00 },
{ 0 xc458, 0 x00 }, { 0 xc459, 0 x00 }, { 0 xc45b, 0 x00 }, { 0 xc45c, 0 x01 },
{ 0 xc45d, 0 x00 }, { 0 xc45e, 0 x00 }, { 0 xc45f, 0 x00 }, { 0 xc460, 0 x00 },
{ 0 xc461, 0 x01 }, { 0 xc462, 0 x01 }, { 0 xc464, 0 x03 }, { 0 xc465, 0 x00 },
{ 0 xc466, 0 x8a }, { 0 xc467, 0 x00 }, { 0 xc468, 0 x86 }, { 0 xc469, 0 x00 },
{ 0 xc46a, 0 x40 }, { 0 xc46b, 0 x50 }, { 0 xc46c, 0 x30 }, { 0 xc46d, 0 x28 },
{ 0 xc46e, 0 x60 }, { 0 xc46f, 0 x40 }, { 0 xc47c, 0 x01 }, { 0 xc47d, 0 x38 },
{ 0 xc47e, 0 x00 }, { 0 xc47f, 0 x00 }, { 0 xc480, 0 x00 }, { 0 xc481, 0 xff },
{ 0 xc482, 0 x00 }, { 0 xc483, 0 x40 }, { 0 xc484, 0 x00 }, { 0 xc485, 0 x18 },
{ 0 xc486, 0 x00 }, { 0 xc487, 0 x18 },
{ 0 xc488, (OV10635_VTS - 8 ) * 16 >> 8 },
{ 0 xc489, (OV10635_VTS - 8 ) * 16 & 0 xff},
{ 0 xc48a, (OV10635_VTS - 8 ) * 16 >> 8 },
{ 0 xc48b, (OV10635_VTS - 8 ) * 16 & 0 xff}, { 0 xc48c, 0 x00 },
{ 0 xc48d, 0 x04 }, { 0 xc48e, 0 x00 }, { 0 xc48f, 0 x04 }, { 0 xc490, 0 x03 },
{ 0 xc492, 0 x20 }, { 0 xc493, 0 x08 }, { 0 xc498, 0 x02 }, { 0 xc499, 0 x00 },
{ 0 xc49a, 0 x02 }, { 0 xc49b, 0 x00 }, { 0 xc49c, 0 x02 }, { 0 xc49d, 0 x00 },
{ 0 xc49e, 0 x02 }, { 0 xc49f, 0 x60 }, { 0 xc4a0, 0 x03 }, { 0 xc4a1, 0 x00 },
{ 0 xc4a2, 0 x04 }, { 0 xc4a3, 0 x00 }, { 0 xc4a4, 0 x00 }, { 0 xc4a5, 0 x10 },
{ 0 xc4a6, 0 x00 }, { 0 xc4a7, 0 x40 }, { 0 xc4a8, 0 x00 }, { 0 xc4a9, 0 x80 },
{ 0 xc4aa, 0 x0d }, { 0 xc4ab, 0 x00 }, { 0 xc4ac, 0 x0f }, { 0 xc4ad, 0 xc0 },
{ 0 xc4b4, 0 x01 }, { 0 xc4b5, 0 x01 }, { 0 xc4b6, 0 x00 }, { 0 xc4b7, 0 x01 },
{ 0 xc4b8, 0 x00 }, { 0 xc4b9, 0 x01 }, { 0 xc4ba, 0 x01 }, { 0 xc4bb, 0 x00 },
{ 0 xc4bc, 0 x01 }, { 0 xc4bd, 0 x60 }, { 0 xc4be, 0 x02 }, { 0 xc4bf, 0 x33 },
{ 0 xc4c8, 0 x03 }, { 0 xc4c9, 0 xd0 }, { 0 xc4ca, 0 x0e }, { 0 xc4cb, 0 x00 },
{ 0 xc4cc, 0 x0e }, { 0 xc4cd, 0 x51 }, { 0 xc4ce, 0 x0e }, { 0 xc4cf, 0 x51 },
{ 0 xc4d0, 0 x04 }, { 0 xc4d1, 0 x80 }, { 0 xc4e0, 0 x04 }, { 0 xc4e1, 0 x02 },
{ 0 xc4e2, 0 x01 }, { 0 xc4e4, 0 x10 }, { 0 xc4e5, 0 x20 }, { 0 xc4e6, 0 x30 },
{ 0 xc4e7, 0 x40 }, { 0 xc4e8, 0 x50 }, { 0 xc4e9, 0 x60 }, { 0 xc4ea, 0 x70 },
{ 0 xc4eb, 0 x80 }, { 0 xc4ec, 0 x90 }, { 0 xc4ed, 0 xa0 }, { 0 xc4ee, 0 xb0 },
{ 0 xc4ef, 0 xc0 }, { 0 xc4f0, 0 xd0 }, { 0 xc4f1, 0 xe0 }, { 0 xc4f2, 0 xf0 },
{ 0 xc4f3, 0 x80 }, { 0 xc4f4, 0 x00 }, { 0 xc4f5, 0 x20 }, { 0 xc4f6, 0 x02 },
{ 0 xc4f7, 0 x00 }, { 0 xc4f8, 0 x00 }, { 0 xc4f9, 0 x00 }, { 0 xc4fa, 0 x00 },
{ 0 xc4fb, 0 x01 }, { 0 xc4fc, 0 x01 }, { 0 xc4fd, 0 x00 }, { 0 xc4fe, 0 x04 },
{ 0 xc4ff, 0 x02 }, { 0 xc500, 0 x48 }, { 0 xc501, 0 x74 }, { 0 xc502, 0 x58 },
{ 0 xc503, 0 x80 }, { 0 xc504, 0 x05 }, { 0 xc505, 0 x80 }, { 0 xc506, 0 x03 },
{ 0 xc507, 0 x80 }, { 0 xc508, 0 x01 }, { 0 xc509, 0 xc0 }, { 0 xc50a, 0 x01 },
{ 0 xc50b, 0 xa0 }, { 0 xc50c, 0 x01 }, { 0 xc50d, 0 x2c }, { 0 xc50e, 0 x01 },
{ 0 xc50f, 0 x0a }, { 0 xc510, 0 x00 }, { 0 xc511, 0 x00 }, { 0 xc512, 0 xe5 },
{ 0 xc513, 0 x14 }, { 0 xc514, 0 x04 }, { 0 xc515, 0 x00 }, { 0 xc518, OV10635_VTS >> 8 },
{ 0 xc519, OV10635_VTS & 0 xff}, { 0 xc51a, OV10635_HTS >> 8 },
{ 0 xc51b, OV10635_HTS & 0 xff}, { 0 xc2e0, 0 x00 }, { 0 xc2e1, 0 x51 },
{ 0 xc2e2, 0 x00 }, { 0 xc2e3, 0 xd6 }, { 0 xc2e4, 0 x01 }, { 0 xc2e5, 0 x5e },
{ 0 xc2e9, 0 x01 }, { 0 xc2ea, 0 x7a }, { 0 xc2eb, 0 x90 }, { 0 xc2ed, 0 x00 },
{ 0 xc2ee, 0 x7a }, { 0 xc2ef, 0 x64 }, { 0 xc308, 0 x00 }, { 0 xc309, 0 x00 },
{ 0 xc30a, 0 x00 }, { 0 xc30c, 0 x00 }, { 0 xc30d, 0 x01 }, { 0 xc30e, 0 x00 },
{ 0 xc30f, 0 x00 }, { 0 xc310, 0 x01 }, { 0 xc311, 0 x60 }, { 0 xc312, 0 xff },
{ 0 xc313, 0 x08 }, { 0 xc314, 0 x01 }, { 0 xc315, 0 x00 }, { 0 xc316, 0 xff },
{ 0 xc317, 0 x0b }, { 0 xc318, 0 x00 }, { 0 xc319, 0 x0c }, { 0 xc31a, 0 x00 },
{ 0 xc31b, 0 xe0 }, { 0 xc31c, 0 x00 }, { 0 xc31d, 0 x14 }, { 0 xc31e, 0 x00 },
{ 0 xc31f, 0 xc5 }, { 0 xc320, 0 xff }, { 0 xc321, 0 x4b }, { 0 xc322, 0 xff },
{ 0 xc323, 0 xf0 }, { 0 xc324, 0 xff }, { 0 xc325, 0 xe8 }, { 0 xc326, 0 x00 },
{ 0 xc327, 0 x46 }, { 0 xc328, 0 xff }, { 0 xc329, 0 xd2 }, { 0 xc32a, 0 xff },
{ 0 xc32b, 0 xe4 }, { 0 xc32c, 0 xff }, { 0 xc32d, 0 xbb }, { 0 xc32e, 0 x00 },
{ 0 xc32f, 0 x61 }, { 0 xc330, 0 xff }, { 0 xc331, 0 xf9 }, { 0 xc332, 0 x00 },
{ 0 xc333, 0 xd9 }, { 0 xc334, 0 x00 }, { 0 xc335, 0 x2e }, { 0 xc336, 0 x00 },
{ 0 xc337, 0 xb1 }, { 0 xc338, 0 xff }, { 0 xc339, 0 x64 }, { 0 xc33a, 0 xff },
{ 0 xc33b, 0 xeb }, { 0 xc33c, 0 xff }, { 0 xc33d, 0 xe8 }, { 0 xc33e, 0 x00 },
{ 0 xc33f, 0 x48 }, { 0 xc340, 0 xff }, { 0 xc341, 0 xd0 }, { 0 xc342, 0 xff },
{ 0 xc343, 0 xed }, { 0 xc344, 0 xff }, { 0 xc345, 0 xad }, { 0 xc346, 0 x00 },
{ 0 xc347, 0 x66 }, { 0 xc348, 0 x01 }, { 0 xc349, 0 x00 }, { 0 x6700, 0 x04 },
{ 0 x6701, 0 x7b }, { 0 x6702, 0 xfd }, { 0 x6703, 0 xf9 }, { 0 x6704, 0 x3d },
{ 0 x6705, 0 x71 }, { 0 x6706, 0 x78 }, { 0 x6708, 0 x05 }, { 0 x6f06, 0 x6f },
{ 0 x6f07, 0 x00 }, { 0 x6f0a, 0 x6f }, { 0 x6f0b, 0 x00 }, { 0 x6f00, 0 x03 },
{ 0 xc34c, 0 x01 }, { 0 xc34d, 0 x00 }, { 0 xc34e, 0 x46 }, { 0 xc34f, 0 x55 },
{ 0 xc350, 0 x00 }, { 0 xc351, 0 x40 }, { 0 xc352, 0 x00 }, { 0 xc353, 0 xff },
{ 0 xc354, 0 x04 }, { 0 xc355, 0 x08 }, { 0 xc356, 0 x01 }, { 0 xc357, 0 xef },
{ 0 xc358, 0 x30 }, { 0 xc359, 0 x01 }, { 0 xc35a, 0 x64 }, { 0 xc35b, 0 x46 },
{ 0 xc35c, 0 x00 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 },
{ 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 x3042, 0 xf0 }, { 0 xc261, 0 x01 },
{ 0 x301b, 0 xf0 }, { 0 x301c, 0 xf0 }, { 0 x301a, 0 xf0 }, { 0 x6f00, 0 xc3 },
{ 0 xc46a, 0 x30 }, { 0 xc46d, 0 x20 }, { 0 xc464, 0 x84 }, { 0 xc465, 0 x00 },
{ 0 x6f00, 0 x03 }, { 0 x6f00, 0 x43 }, { 0 x381c, 0 x00 }, { 0 x381d, 0 x40 },
{ 0 xc454, 0 x01 }, { 0 x6f00, 0 xc3 }, { 0 xc454, 0 x00 }, { 0 xc4b1, 0 x02 },
{ 0 xc4b2, 0 x01 }, { 0 xc4b3, 0 x03 }, { 0 x6f00, 0 x03 }, { 0 x6f00, 0 x43 },
/* enable FSIN (FRAMESYNC input) functionality */
{ 0 x3832, (0 x0d + 2 * 0 x20 + 0 x15 + 38 ) >> 8 },
{ 0 x3833, (0 x0d + 2 * 0 x20 + 0 x15 + 38 ) & 0 xff },
{ 0 x3834, OV10635_VTS >> 8 }, { 0 x3835, OV10635_VTS & 0 xff },
{ 0 x302e, 0 x01 },
};
struct rdacm20_device {
struct device *dev;
struct max9271_device serializer;
struct i2c_client *sensor;
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler ctrls;
u32 addrs[2 ];
};
static inline struct rdacm20_device *sd_to_rdacm20(struct v4l2_subdev *sd)
{
return container_of(sd, struct rdacm20_device, sd);
}
static inline struct rdacm20_device *i2c_to_rdacm20(struct i2c_client *client)
{
return sd_to_rdacm20(i2c_get_clientdata(client));
}
static int ov10635_read16(struct rdacm20_device *dev, u16 reg)
{
u8 buf[2 ] = { reg >> 8 , reg & 0 xff };
int ret;
ret = i2c_master_send(dev->sensor, buf, 2 );
if (ret != 2 ) {
dev_dbg(dev->dev, "%s: register 0x%04x write failed (%d)\n" ,
__func__, reg, ret);
return ret;
}
ret = i2c_master_recv(dev->sensor, buf, 2 );
if (ret < 0 ) {
dev_dbg(dev->dev, "%s: register 0x%04x read failed (%d)\n" ,
__func__, reg, ret);
return ret;
}
return (buf[0 ] << 8 ) | buf[1 ];
}
static int __ov10635_write(struct rdacm20_device *dev, u16 reg, u8 val)
{
u8 buf[3 ] = { reg >> 8 , reg & 0 xff, val };
int ret;
dev_dbg(dev->dev, "%s(0x%04x, 0x%02x)\n" , __func__, reg, val);
ret = i2c_master_send(dev->sensor, buf, 3 );
return ret < 0 ? ret : 0 ;
}
static int ov10635_write(struct rdacm20_device *dev, u16 reg, u8 val)
{
int ret;
ret = __ov10635_write(dev, reg, val);
if (ret < 0 )
dev_err(dev->dev, "%s: register 0x%04x write failed (%d)\n" ,
__func__, reg, ret);
return ret;
}
static int ov10635_set_regs(struct rdacm20_device *dev,
const struct ov10635_reg *regs,
unsigned int nr_regs)
{
unsigned int i;
int ret;
for (i = 0 ; i < nr_regs; i++) {
ret = __ov10635_write(dev, regs[i].reg, regs[i].val);
if (ret) {
dev_err(dev->dev,
"%s: register %u (0x%04x) write failed (%d)\n" ,
__func__, i, regs[i].reg, ret);
return ret;
}
}
return 0 ;
}
static int rdacm20_s_stream(struct v4l2_subdev *sd, int enable)
{
struct rdacm20_device *dev = sd_to_rdacm20(sd);
return max9271_set_serial_link(&dev->serializer, enable);
}
static int rdacm20_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->pad || code->index > 0 )
return -EINVAL;
code->code = MEDIA_BUS_FMT_UYVY8_1X16;
return 0 ;
}
static int rdacm20_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *format)
{
struct v4l2_mbus_framefmt *mf = &format->format;
if (format->pad)
return -EINVAL;
mf->width = OV10635_WIDTH;
mf->height = OV10635_HEIGHT;
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
mf->colorspace = V4L2_COLORSPACE_RAW;
mf->field = V4L2_FIELD_NONE;
mf->ycbcr_enc = V4L2_YCBCR_ENC_601;
mf->quantization = V4L2_QUANTIZATION_FULL_RANGE;
mf->xfer_func = V4L2_XFER_FUNC_NONE;
return 0 ;
}
static const struct v4l2_subdev_video_ops rdacm20_video_ops = {
.s_stream = rdacm20_s_stream,
};
static const struct v4l2_subdev_pad_ops rdacm20_subdev_pad_ops = {
.enum_mbus_code = rdacm20_enum_mbus_code,
.get_fmt = rdacm20_get_fmt,
.set_fmt = rdacm20_get_fmt,
};
static const struct v4l2_subdev_ops rdacm20_subdev_ops = {
.video = &rdacm20_video_ops,
.pad = &rdacm20_subdev_pad_ops,
};
static int rdacm20_initialize(struct rdacm20_device *dev)
{
unsigned int retry = 3 ;
int ret;
max9271_wake_up(&dev->serializer);
/* Serial link disabled during config as it needs a valid pixel clock. */
ret = max9271_set_serial_link(&dev->serializer, false );
if (ret)
return ret;
/*
* Ensure that we have a good link configuration before attempting to
* identify the device.
*/
ret = max9271_configure_i2c(&dev->serializer,
MAX9271_I2CSLVSH_469NS_234NS |
MAX9271_I2CSLVTO_1024US |
MAX9271_I2CMSTBT_105KBPS);
if (ret)
return ret;
/*
* Hold OV10635 in reset during max9271 configuration. The reset signal
* has to be asserted for at least 200 microseconds.
*/
ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
usleep_range(200 , 500 );
ret = max9271_configure_gmsl_link(&dev->serializer);
if (ret)
return ret;
ret = max9271_verify_id(&dev->serializer);
if (ret < 0 )
return ret;
ret = max9271_set_address(&dev->serializer, dev->addrs[0 ]);
if (ret < 0 )
return ret;
dev->serializer.client->addr = dev->addrs[0 ];
/*
* Release ov10635 from reset and initialize it. The image sensor
* requires at least 2048 XVCLK cycles (85 micro-seconds at 24MHz)
* before being available. Stay safe and wait up to 500 micro-seconds.
*/
ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
if (ret)
return ret;
usleep_range(100 , 500 );
again:
ret = ov10635_read16(dev, OV10635_PID);
if (ret < 0 ) {
if (retry--)
goto again;
dev_err(dev->dev, "OV10635 ID read failed (%d)\n" ,
ret);
return -ENXIO;
}
if (ret != OV10635_VERSION) {
if (retry--)
goto again;
dev_err(dev->dev, "OV10635 ID mismatch (0x%04x)\n" ,
ret);
return -ENXIO;
}
/* Change the sensor I2C address. */
ret = ov10635_write(dev, OV10635_SC_CMMN_SCCB_ID,
(dev->addrs[1 ] << 1 ) |
OV10635_SC_CMMN_SCCB_ID_SELECT);
if (ret < 0 ) {
dev_err(dev->dev,
"OV10635 I2C address change failed (%d)\n" , ret);
return ret;
}
dev->sensor->addr = dev->addrs[1 ];
usleep_range(3500 , 5000 );
/* Program the 0V10635 initial configuration. */
ret = ov10635_set_regs(dev, ov10635_regs_wizard,
ARRAY_SIZE(ov10635_regs_wizard));
if (ret)
return ret;
dev_info(dev->dev, "Identified RDACM20 camera module\n" );
/*
* Set reverse channel high threshold to increase noise immunity.
*
* This should be compensated by increasing the reverse channel
* amplitude on the remote deserializer side.
*
* TODO Inspect the embedded MCU programming sequence to make sure
* there are no conflicts with the configuration applied here.
*
* TODO Clarify the embedded MCU startup delay to avoid write
* collisions on the I2C bus.
*/
return max9271_set_high_threshold(&dev->serializer, true );
}
static int rdacm20_probe(struct i2c_client *client)
{
struct rdacm20_device *dev;
int ret;
dev = devm_kzalloc(&client->dev, sizeof (*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->dev = &client->dev;
dev->serializer.client = client;
ret = device_property_read_u32_array(dev->dev, "reg" , dev->addrs, 2 );
if (ret < 0 ) {
dev_err(dev->dev, "Invalid FW reg property: %d\n" , ret);
return -EINVAL;
}
/* Create the dummy I2C client for the sensor. */
dev->sensor = i2c_new_dummy_device(client->adapter,
OV10635_I2C_ADDRESS);
if (IS_ERR(dev->sensor)) {
ret = PTR_ERR(dev->sensor);
goto error;
}
/* Initialize the hardware. */
ret = rdacm20_initialize(dev);
if (ret < 0 )
goto error;
/* Initialize and register the subdevice. */
v4l2_i2c_subdev_init(&dev->sd, client, &rdacm20_subdev_ops);
dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
v4l2_ctrl_handler_init(&dev->ctrls, 1 );
v4l2_ctrl_new_std(&dev->ctrls, NULL, V4L2_CID_PIXEL_RATE,
OV10635_PIXEL_RATE, OV10635_PIXEL_RATE, 1 ,
OV10635_PIXEL_RATE);
dev->sd.ctrl_handler = &dev->ctrls;
ret = dev->ctrls.error;
if (ret)
goto error_free_ctrls;
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&dev->sd.entity, 1 , &dev->pad);
if (ret < 0 )
goto error_free_ctrls;
ret = v4l2_async_register_subdev(&dev->sd);
if (ret)
goto error_free_ctrls;
return 0 ;
error_free_ctrls:
v4l2_ctrl_handler_free(&dev->ctrls);
error:
media_entity_cleanup(&dev->sd.entity);
i2c_unregister_device(dev->sensor);
dev_err(&client->dev, "probe failed\n" );
return ret;
}
static void rdacm20_remove(struct i2c_client *client)
{
struct rdacm20_device *dev = i2c_to_rdacm20(client);
v4l2_async_unregister_subdev(&dev->sd);
v4l2_ctrl_handler_free(&dev->ctrls);
media_entity_cleanup(&dev->sd.entity);
i2c_unregister_device(dev->sensor);
}
static void rdacm20_shutdown(struct i2c_client *client)
{
struct rdacm20_device *dev = i2c_to_rdacm20(client);
/* make sure stream off during shutdown (reset/reboot) */
rdacm20_s_stream(&dev->sd, 0 );
}
static const struct of_device_id rdacm20_of_ids[] = {
{ .compatible = "imi,rdacm20" , },
{ }
};
MODULE_DEVICE_TABLE(of, rdacm20_of_ids);
static struct i2c_driver rdacm20_i2c_driver = {
.driver = {
.name = "rdacm20" ,
.of_match_table = rdacm20_of_ids,
},
.probe = rdacm20_probe,
.remove = rdacm20_remove,
.shutdown = rdacm20_shutdown,
};
module_i2c_driver(rdacm20_i2c_driver);
MODULE_DESCRIPTION("GMSL Camera driver for RDACM20" );
MODULE_AUTHOR("Vladimir Barinov" );
MODULE_LICENSE("GPL" );
Messung V0.5 in Prozent C=95 H=91 G=92